creating-providers-and-modules
Skill1 starsChanged 3 months agoMITView on GitHub
Use when creating new extension packages, adding providers, or defining modules in the Lexigram framework
In this repository17 other files it gives its agents.
- ai-subsystem-quickstartSkill
- auth-and-securitySkill
- caching-patternsSkill
- cli-code-generationSkill
- cli-config-and-inspectSkill
- cli-database-operationsSkill
- cli-project-scaffoldingSkill
- configuration-managementSkill
- database-repository-patternSkill
- events-and-messagingSkill
- lexigram-uiSkill
- multimedia-generationSkill
- real-time-webSkill
- resilience-patternsSkill
- testing-with-lexigramSkill
- using-result-and-error-codesSkill
- web-controllers-and-routingSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 2 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 47
No business logic on Provider classes
- Distinctive: line 48
All I/O in boot/shutdown is async
- Very specific: line 126
Never share a Subscription across providers — always unsubscribe in shutdown().
- Very specific: line 134
Not defining stub() — forces test modules to use real implementations
- Very specific: line 136
Not unsubscribing in shutdown() — subscription handles leak, consumers pile up
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Creating Providers and Modules
Overview
Providers wire services into the DI container. Modules group providers and enforce visibility.
Core Pattern
Provider = registers/boots/shuts down one bounded concern. Module = groups providers, defines imports/exports.
Provider Lifecycle
from lexigram.di import Provider
from lexigram.contracts.core.di import ContainerRegistrarProtocol, BootContainerProtocol
from lexigram.contracts.core.health import HealthCheckResult, HealthStatus
class MyProvider(Provider):
name = "my_provider"
priority = ProviderPriority.NORMAL
async def register(self, container: ContainerRegistrarProtocol) -> None:
container.singleton(MyProtocol, MyImpl)
container.transient(OtherProtocol, lambda: OtherImpl(...))
async def boot(self, container: BootContainerProtocol) -> None:
svc = await container.resolve(MyProtocol)
await svc.connect()
async def shutdown(self) -> None:
await self._cleanup()
async def health_check(self, timeout: float = 5.0) -> HealthCheckResult:
return HealthCheckResult(component=self.name, status=HealthStatus.HEALTHY)Rules
register()getsContainerRegistrarProtocol— binds only, no resolutionboot()getsBootContainerProtocol— may resolve AND register- Optional hooks:
on_error(error, phase),shutdown(),health_check(timeout) - No business logic on Provider classes
- All I/O in boot/shutdown is async
Provider Priorities
| Priority | Value | Use |
CRITICAL | 0 | Logging, errors |
INFRASTRUCTURE | 10 | DB, cache, queues |
SECURITY | 20 | Auth, encryption |
NORMAL | 30 | Default |
APPLICATION | 40 | CLI, admin utilities |
DOMAIN | 50 | Business services |
PRESENTATION | 80 | Web/API entry points |
COMMS | 90 | Outbound email/SMS/webhooks |
LOW | 100 | Optional, boot last |
Shutdown runs in reverse order.
Module Patterns
Static Module (no config)
from lexigram.di import module, Module
@module(providers=[MyProvider], imports=[ConfigModule], exports=[MyProtocol])
class MyModule(Module):
passDynamic Module (with config)
from lexigram.di import module, Module, DynamicModule
@module()
class MyModule(Module):
@classmethod
def configure(cls, config: MyConfig | None = None) -> DynamicModule:
return DynamicModule(
module=cls,
providers=[MyProvider(config=config)],
exports=[MyProtocol],
)
@classmethod
def stub(cls, config: MyConfig | None = None) -> DynamicModule:
return DynamicModule(
module=cls,
providers=[MyStubProvider(config=config)],
exports=[MyProtocol],
)Three factory conventions: configure(), scope(), stub().
Package File Layout
src/lexigram/mypackage/ __init__.py (lazy exports), config.py,
module.py, exceptions.py, di/provider.py
tests/ pyproject.tomlShared Queue Lifecycle
Coordinate subscribe/unsubscribe when multiple providers share a queue:
class WorkerProvider(Provider):
async def boot(self, container):
queue = await container.resolve(QueueProtocol)
self.sub = await queue.subscribe("orders.new", self.handle)
async def shutdown(self):
await self.sub.unsubscribe() # each provider owns its handlesNever share a Subscription across providers — always unsubscribe in shutdown().
Common Mistakes
- Registering after container freeze — raises
ContainerError - Resolving in
register()— useboot()instead - Business logic on Provider — belongs in services, not providers
- Forgetting
exportsin DynamicModule — consumers can't resolve the type - Not defining
stub()— forces test modules to use real implementations - Declaring
config_keywithoutconfig_model— raisesConfigurationErrorat boot unless aLexigramConfigis registered orprovider.configis set directly - Not unsubscribing in
shutdown()— subscription handles leak, consumers pile up - Sharing a
Subscriptionacross providers — race on unsubscribe tears down other consumers
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

