The catalog is the source of truth
The provider catalog inpackages/atoms/src/providers/catalog.ts
maps each ModelProviderType to a ProviderCatalogEntry:
A compile-time
Record<ModelProviderType, …> and unit tests (protocol control.test.ts,
atoms providers.test.ts) assert the catalog covers exactly KNOWN_PROVIDER_TYPES, so the
enum and the catalog can’t drift.
The two strategies
Thestrategy field is the mechanism that decides how a provider’s model is built. Both
strategies are bundled and registered at startup — there is no runtime download.
native— a dedicated AI SDK package, one provider module inpackages/atoms/src/providers/. Used only for providers that genuinely need their own SDK: Anthropic, OpenAI, OpenRouter (its own@openrouter/ai-sdk-provider), Vercel AI Gateway, Google Gemini, Mistral, Amazon Bedrock, Azure OpenAI.openai-compatible— the bundled@ai-sdk/openai-compatibleadapter pointed at the catalog’sdefaultBaseUrl. This covers the entire long tail (Groq, xAI, DeepSeek, Together, Fireworks, Cerebras, Perplexity, Moonshot, Z.AI, MiniMax, NVIDIA, Novita, Ollama, Hugging Face) with zero extra dependencies — they are presets, generated from the catalog inproviders/index.ts.
Adding a provider
- OpenAI-compatible endpoint → add one
ModelProviderTypeenum member + onePROVIDER_CATALOGentry (strategy: 'openai-compatible',defaultBaseUrl). That’s it — the registry, wizard, CLI, and settings pick it up automatically. Add a logo inapps/web/src/lib/ProviderMeta.tsx. - Needs a distinct SDK → also add the package to
apps/monad/package.jsonand a provider module, then register it inproviders/index.ts.
Auth model
22 of the 24 providers are exactly base URL + token and fit the credential model ({ accessToken, authType: 'api_key', baseUrl }). Two natives carry extra requirements:
Provider credentials are native Monad settings stored directly on their provider in
agents.json. They are redacted from settings responses and never use
auth.json, ${secret:...}, or the Agent Runtime Credentials registry.
- Azure OpenAI —
needsUrl: true; the user supplies a resource base URL (https://{resource}.openai.azure.com/openai/v1) + an api-key, and the model id is the Azure deployment name. - Amazon Bedrock — requires an AWS
region(anextraFieldstored inProvider.extra) and authenticates with a bearer API key (ABSK…). SigV4 (two-secret) is out of scope.
/models route, so the wizard and CLI fall back to a
manual model-id entry when a connection test returns no models.
Why there’s no runtime/dynamic download
A natural idea is to fetch a provider’s npm package (or its prebuiltdist) at runtime when a
user selects it. We deliberately don’t, because:
distis compiled, not bundled. It stillimports bare specifiers (@ai-sdk/provider,@ai-sdk/provider-utils,zod), so using it means recursively resolving the whole dependency tree at runtime — reimplementing a package manager.- Shared spec version. The AI SDK pins a
specificationVersion; a downloaded provider must share the same@ai-sdk/providercopy as the hostairuntime or the model object is rejected. CDN bundles (esm.sh?bundle) duplicate that peer and drift. - Supply chain. Executing network-fetched code inside the key-holding daemon has no lockfile, integrity check, or audit.
Third-party atom packs (the supported extension point)
Genuinely custom providers are still supported, unchanged, via drop-in atom pack files: place a.js module that default-exports a ModelProvider (or an array of them) into
~/.monad/atoms/providers/. The daemon discovers and watches that directory
(registry.discover(dir) + watchProviders() in
apps/monad/src/services/model.ts), so the atom pack
registers without a restart. The atom pack contract is documented in
provider.ts.