Provider Leaf Anatomy
File responsibilities and protocol decisions for certified provider leaves
Provider Leaf Anatomy
A certified provider leaf is a small package-local driver. The generator discovers leaf folders under self/subcortex/providers/src/providers/ and builds the public catalogs from their standard exports.
self/subcortex/providers/src/providers/<vendor>/
├── definition.ts # exports providerDefinition
├── adapter.ts # exports providerAdapter
├── provider.ts # exports providerFactory
├── implementation.ts # provider class and constants, when leaf-owned
└── index.ts # leaf public exports; required by leaf validationRequired Files
The generator requires definition.ts, adapter.ts, provider.ts, and index.ts. It validates provider leaf directory names with lowercase ASCII kebab-case starting with a letter, then creates unique generated aliases from those names.
implementation.ts is a convention, not a generator requirement. Use it when the leaf owns request execution. The OpenAI leaf intentionally has no implementation.ts; it reuses self/subcortex/providers/src/protocols/openai-api/provider.ts.
Keys And Protocols
| Name | Meaning |
|---|---|
vendorKey | Certified provider identity, such as anthropic, openai, or ollama |
adapterKey | Adapter implementation key used by resolver/runtime, such as anthropic, chat-completions, or ollama |
protocol | Wire/API family, such as anthropic-messages, chat-completions, or ollama |
auth.header | API-key header metadata for Settings key tests and model discovery, using { name, scheme: 'raw' | 'bearer' } |
modelListEndpoint | Relative endpoint that opts the provider into dynamic model discovery, such as /v1/models |
modelListFormat | Model-list response-envelope format parser. Current values are anthropic-models and openai-models; the names describe response shapes, not exclusive provider identities. |
executionCapabilityProfile | Optional provider-definition declared execution profile for CLI-style providers: one_shot_command, session_bound_command, or persistent_process. Declared on the provider definition so selection-time role compatibility filtering can use it before constructing a runtime instance. |
A vendor can reuse a shared adapter key when it speaks an existing protocol. OpenAI's vendorKey is openai, while its adapter key is chat-completions.
For API-key providers, auth.purpose, auth.required, auth.envVar, and auth.vaultKeyNamespace make the provider eligible for a vault-backed Settings key field. Add auth.header plus modelListEndpoint/modelListFormat when the provider should also support dynamic model discovery. There is no Settings component or runtime vendor branch to edit for a normal provider leaf.
Do not hand-author built-in provider UUIDs in leaves. Built-in provider ids are derived centrally from vendorKey by self/subcortex/providers/src/provider-identity.ts and hydrated into the generated PROVIDER_DEFINITIONS catalog. User/custom provider instances still receive generated persisted ids at runtime; certified built-in leaves should focus on semantic identity and metadata.
For agent-CLI providers, lifecycle behavior is contextual. Declare the adapter's execution capability on the provider definition so model-selection and assignment surfaces can filter incompatible roles before runtime. The runtime CLI session manager still enforces the same capability contract defensively when a caller bypasses Settings/config validation.
Example:
export const CODEX_CLI_PROVIDER_DEFINITION = {
vendorKey: 'codex-cli',
displayName: 'Codex CLI',
protocol: AGENT_CLI_PROTOCOL_ID,
adapterKey: 'codex-cli',
executionCapabilityProfile: 'session_bound_command',
// No wellKnownProviderId here — generated centrally from vendorKey.
} as const satisfies ProviderDefinitionLeaf;session_bound_command means the CLI can maintain command/session context but does not expose a strict persistent process suitable for Cortex persistent chat. Cortex Chat/System require persistent_process; Settings disables/rejects command-bound CLI providers for those roles while leaving them available for compatible agent roles. See the CLI Provider Guide for the full CLI contributor contract including selection-time guardrails and the contributor checklist.
Protocol Decision Table
| If your provider... | Do this |
|---|---|
| Speaks OpenAI Chat Completions | Reuse src/protocols/openai-api/** and wrap it with a provider leaf |
| Has the same vendor API but different defaults or credentials | Keep vendor-specific metadata in the leaf and reuse shared protocol logic |
| Has a new wire protocol | Write provider-specific adapter.ts and implementation.ts |
| Shares behavior across multiple vendors | Put reusable behavior in src/protocols/<protocol>/ |
| Needs generic output fallback behavior | Use src/shared/ only for truly generic helpers |
Normal provider additions should not edit src/adapter-resolver.ts or add runtime vendor branches. Adapter resolution should flow from definitions and generated catalogs unless the resolution policy itself changes.