Provider Registry
How provider packages register with ProviderRegistry, how to create providers safely, and how to hand them into agents.
ProviderRegistry is the stable provider boundary inside @namzu/sdk. Every published provider package registers itself into this registry, and every agent run receives an LLMProvider instance created through the same API.
1. Why the Registry Exists
The registry solves three problems:
- provider packages can live outside the SDK without changing agent code
- application code can stay vendor-neutral after initial registration
- the runtime can depend on one
LLMProvidercontract instead of branching on vendors
The result is a consistent pattern:
- install
@namzu/sdkand one provider package - call the provider package's
register...()function once - create a provider through
ProviderRegistry.create(...) - pass the returned
providerinto aReactiveAgentor callprovider.chat()directly
2. The Registration Flow
Each provider package exports a registration helper:
| Package | Registration helper | Registry type |
|---|---|---|
@namzu/openai | registerOpenAI() | openai |
@namzu/anthropic | registerAnthropic() | anthropic |
@namzu/bedrock | registerBedrock() | bedrock |
@namzu/openrouter | registerOpenRouter() | openrouter |
@namzu/http | registerHttp() | http |
@namzu/ollama | registerOllama() | ollama |
@namzu/lmstudio | registerLMStudio() | lmstudio |
The helper wires three things into the SDK:
- a provider type string
- a provider constructor
- a capability declaration such as tool support and streaming support
3. Minimal Example
4. What ProviderRegistry.create() Returns
ProviderRegistry.create(config) returns:
provider: the normalizedLLMProviderinstance used by the runtimecapabilities: the package's declared capability flags
That capability object is useful when your application wants to make decisions such as:
- whether to expose tool-using agents on this backend
- whether to prefer streaming UI behavior
- whether a provider should be used for structured-output or function-calling tasks
5. ProviderRegistry API Surface
| Method | Purpose |
|---|---|
register(type, ctor, capabilities, options?) | Register a provider package manually |
create(config) | Create { provider, capabilities } in one step |
createProvider(config) | Create only the provider instance |
getCapabilities(type) | Read declared capabilities for a provider type |
isSupported(type) | Check if a provider type has been registered |
listTypes() | List currently registered provider types |
unregister(type) | Remove a provider registration |
Most applications only need register...() plus ProviderRegistry.create(...).
6. Direct Provider Calls vs Agent Runtime
Direct provider calls are useful for:
- credential validation
- model smoke tests
- debugging provider-specific behavior
- building provider-aware tooling before adding agents
Once that succeeds, the usual next step is to hand the provider to an agent:
7. Registration Lifetime
The recommended application pattern is:
- register each provider package once during app startup
- create provider instances as needed for runtime config, tenants, or per-request selection
Do not call register...() before every request. Registration is process-level catalog setup, not per-run work.
8. Common Errors
| Error | Meaning | Fix |
|---|---|---|
Unsupported provider type | The provider package was never registered | Call registerOpenAI() or the matching helper before create() |
Provider type "x" is already registered | The same provider was registered twice | Register once, or pass { replace: true } intentionally |
| provider-specific missing credential error | Required config such as apiKey was not supplied | Fix the package config before creating the provider |
missing model error on chat() | Neither provider config nor chat() params supplied a model | Set a default model in config or pass model per call |
9. Optional Provider Methods
The LLMProvider contract always requires:
chat(params)chatStream(params)
Most published providers also implement:
listModels()healthCheck()
That makes the registry useful beyond agent runtime. You can use the same provider instance for:
- preflight health checks
- model catalog UI
- runtime readiness probes
Read Provider Operations if you want concrete direct-call patterns for those optional methods.
10. Related Decisions
Use the registry layer when:
- the provider should remain swappable
- your code should not import vendor SDKs directly
- you want one runtime flow across OpenAI, Anthropic, Bedrock, local models, and compatible HTTP endpoints
Skip the registry only if you are intentionally using a vendor SDK directly and not using Namzu's provider abstraction.