Model providers
packs:ai-agents
A model provider is a first-class catalog record — beside identity
providers and secrets providers — holding the brokered model credentials
AI agents reason with. The custody posture: rather than share API keys
with each agent, an agent references a provider by code and the
platform's model gateway does the heavy lifting — the gateway resolves
the record, injects the stored key server-side and streams the model's
answer through, so no model key ever lands on an agent host. A
compromised host yields a revocable agent session, not your Anthropic or
OpenAI key, and rotation happens here, in one place. The hands-on
walkthrough is opschain docs getting-started/12-6-model-providers-and-budgets;
the custody modes and the wider AI-agent lane are
ai-agents. This page is the component reference.
The kind set
| Kind | Serves | Default endpoint | Credential injection |
|---|---|---|---|
anthropic | Anthropic-hosted Claude models | https://api.anthropic.com | x-api-key |
openai | OpenAI-hosted models | https://api.openai.com/v1 | Authorization bearer |
azure-foundry-anthropic | Claude deployed in Azure AI Foundry (the Anthropic wire — agents keep the Claude adapter unchanged) | none — the record requires your resource endpoint | x-api-key |
azure-openai | GPT-family models on Azure OpenAI (the chat-completions wire) | none — the record requires your deployment URL (an api-version may ride in the endpoint string) | api-key |
openai-compatible | A model you host yourself speaking the OpenAI wire format (vLLM, Ollama, TGI, llama.cpp server, LiteLLM and similar) | none — the record requires your endpoint's base URL | Authorization bearer when a credential is stored; no auth header otherwise |
The kind picks the default endpoint, where one exists, and how the
gateway injects the stored credential upstream. The Azure kinds address
a per-resource (and per-deployment) URL in the customer's own tenancy,
so their records cannot resolve anywhere until they carry an endpoint;
authentication to them is by API key in this release, with Microsoft
Entra ID a planned follow-up. The openai default carries the /v1
segment because an OpenAI-SDK caller's base URL includes it, and the
gateway forwards the caller's path remainder verbatim.
Self-hosted models: the openai-compatible kind
The openai-compatible kind brings a model you host yourself under the
same governance as the vendor kinds — the brokered gateway, transcripts,
token budgets and the emergency stop all apply unchanged. Three things
differ from the hosted kinds:
- The endpoint is required — there is no platform default for an
endpoint only you can reach. Register your serving stack's base URL
(include the
/v1segment where your stack serves it there). - The credential is optional. Internal endpoints are often
unauthenticated or fronted by their own transport auth; with a
credential stored the gateway injects it as
Authorization: Bearer, without one it injects no auth header at all. - TLS trust is configurable per record (
ssl_verify,ssl_ca_cert, below) for endpoints behind a private certificate authority.
The gateway stays a faithful byte proxy: requests and responses are
forwarded untouched and the wire format is never parsed or translated,
so protocol fidelity is the hosting stack's responsibility — a stack
that deviates from the OpenAI dialect surfaces its own answers and
errors verbatim to the calling SDK. The endpoint is operator
configuration, set by an administrator on an admin-gated record, and the
data_handling_approved review marker works unchanged — for a
self-hosted model the review is your own sign-off on where the content
flows.
TLS trust (ssl_verify, ssl_ca_cert)
Every record carries two TLS trust attributes for its endpoint connection, defaulting to ordinary verification against the system roots:
ssl_verify(defaulttrue) — setfalseas an explicit opt-out for a self-signed endpoint; the opt-out is recorded on the entry and audited like any other change.ssl_ca_cert(default empty) — a CA trust anchor: a PEM block inline, or a certificate file path on the server host. A trust anchor that cannot be loaded refuses the call loudly rather than silently falling back to the system roots.
The record, attribute by attribute
| Attribute | Meaning |
|---|---|
code | The estate code the provider is addressed by: agent manifests reference it, and the gateway path carries it. Immutable after create. |
display_name | The human name admin surfaces render. |
kind | The provider kind (table above). Immutable after create. |
endpoint | Endpoint override; empty means the kind's default where one exists — the Azure kinds and openai-compatible require one. |
credential_set | Whether a credential is stored — the value itself is write-only: no response, audit row or error ever echoes it. For openai-compatible the credential is optional. |
credential_ref | The canonical secret-vault:// reference the credential lives at — an address, never a value. Empty on a grandfathered record whose inline encrypted credential predates reference-first custody. |
data_handling_approved | The estate's one-time data-handling review marker (below). |
ssl_verify | Whether the endpoint's TLS certificate is verified (default true; the TLS trust section above). |
ssl_ca_cert | A CA trust anchor for the endpoint connection — a PEM block inline or a certificate file path on the server host; empty uses the system roots. |
enabled | Whether the gateway serves calls for this provider. |
Custody is reference-first: --credential-ref pins an existing
secret-vault:// reference, resolved at write time (an unresolvable
reference refuses by name), while an inline credential is vault-write
sugar — the value lands in the platform vault under the reserved
model-providers/<code>/credential path and only the resulting
reference is stored. Records created before the retrofit keep their
inline encrypted key until the next credential write, which moves
custody to the vault.
Lifecycle
- Create registers a provider (requires
packs:ai-agents): code and kind immutable, the API key via environment variable or no-echo prompt (never argv), exactly one of the inline credential or acredential_refcarrying it (openai-compatiblealone may carry neither). - Update partially updates — a supplied credential rotates the
stored key for every agent at once; a supplied
credential_refre-pins the reference. Enabling a disabled provider requirespacks:ai-agents, exactly as create does; disabling is never gated. - Delete removes a provider, ungated. Agents whose manifest references the deleted code keep their sessions, but every gateway call refuses until the provider is re-created or the agent re-registers without it.
Compositions without the model-provider plane answer not-found, the nil-domain convention, and listings order by code ascending.
Which agents use this provider
An agent is bound to exactly one provider — the catalog code its
manifest names (OPSCHAIN_MODEL_PROVIDER on the agent host) — and the
binding is by code, never by kind: two anthropic entries are two
different providers, and an agent bound to one never falls back to the
other. To see who references an entry, read the fleet:
opschain admin agents list carries a PROVIDER column (the code —
--filter provider=<code> narrows to its agents), opschain admin agent show renders the MODEL PROVIDER row with the entry's kind and
standing (demo-anthropic (anthropic, enabled),
… (anthropic, disabled), … (missing from the catalog)), the agent
resource carries model_provider_code / model_provider_kind /
model_provider_state, and the GUI model-providers page counts the
agents referencing each entry. The disclosure an ai-type agent attests
(disclosures.model_provider, the MODEL row) is the model vendor,
not this code — see resources/agent.
The data-handling-approved marker
Each catalog entry carries a data-handling-approved marker
(data_handling_approved; --data-handling-approved on the create and
update verbs, the DATA-HANDLING column in the listing): the record of
the estate's one-time review of that provider's data-processing
terms — training use, retention, residency, DPA. An administrator sets
it after the review; a new entry defaults to unreviewed.
Lanes that send customer-submitted content to a model — such as a support-desk agent's AI lane — refuse to be configured against an unapproved provider. Because the approval is a property of the catalog entry itself, never a hardcoded provider list, a new or custom provider added later inherits the same check: review its terms, mark the entry, and only then can such a lane use it. The marker does not gate ordinary brokered calls over the estate's own content. The marker's place in the wider AI-agent custody story is ai-agents.
How a brokered model call flows
The gateway's route is /api/model/{provider}/… — the rest of the path
and query are forwarded to the provider's endpoint, so an Anthropic-SDK
caller sets its base URL to <server>/api/model/<code> and its usual
/v1/messages lands on the provider. Per call:
- The agent authenticates with its existing session token — the
same credential every other agent-plane surface takes, carried as the
Authorization bearer or as the
x-api-keyheader value. No new auth mechanism exists for the gateway. - The agent's manifest must reference the addressed provider — an agent calls only the provider it declared at registration; anything else refuses by name.
- The provider must be registered, enabled and — except for
openai-compatible, whose credential is optional — hold a credential; each miss is its own named refusal. - The grant's token budget, where one is set, is checked before the call forwards — spend over the budget refuses pre-flight until the UTC-day window resets (the caps live on trust grants; see ai-agents).
- The gateway injects the stored credential per the kind, strips every inbound credential carriage and hop-by-hop header (the agent's bearer never reaches the provider; no inbound API key is ever forwarded), and streams the provider's answer through untouched — payloads are never parsed or transformed, and the upstream connection carries no overall timeout, as a streamed response holds it for its whole generation.
- Token usage is read off the response as it streams — Anthropic streaming usage blocks and chat-completions usage alike — and stamped onto the call's audit event.
Every refusal is loud JSON in the provider error shape, so the calling model SDK surfaces it verbatim. Registration is guarded at the other end too: an agent manifest naming a provider the catalog does not hold refuses at enrolment, so a typo fails loudly before the first model call.
Settings and configuration
No config.yaml key tunes this component: the catalog is
database-backed and administered entirely through the service. On the
agent host, the manifest's provider reference is set from
OPSCHAIN_MODEL_PROVIDER; the adapter environment and custody modes are
ai-agents territory.
Governance and audit
Every catalog verb sits behind the /admin updatable determination
(permission denied on deny), over the v2 user-token lane — the caller's
own opschain login session, with the admin-token fallbacks the CLI
manual records.
Entitlement: create and enable gate on packs:ai-agents — the
same pack an ai-type agent enrols under, with the typed refusal naming
it. The lapse posture is polite: stored providers keep resolving and
serving existing agents, only new registrations (the create/enable
writes) refuse, and delete stays open — a lapse never bricks a running
fleet. See entitlements.
Events:
api:model_providers:create/update/destroy— catalog lifecycle; record facts only (code, kind, endpoint, the reference, the marker, the TLS trust facts —ssl_verifyand whether a trust anchor is set — and enabled), never a credential, a rotation carryingcredential_rotated.info:agent:model_call— every served gateway call: the provider, the sniffed model name, method, path, upstream status and the observedinput_tokens/output_tokens.warn:agent:model_call_refused— a gateway refusal, with the provider and the named reason.warn:agent:model_provider_refused— a registration named a provider the catalog does not hold.
The token-budget refusal and the trust-review spend aggregation
(tokens_by_provider, cost attribution) are the trust-grant story —
ai-agents carries them in full.
Related pages
opschain docs cli/admin-model-providers— the command family (list,show,create,update,delete), verb by verb.opschain docs getting-started/12-6-model-providers-and-budgets— the hands-on guide: custody, the catalog, token budgets.opschain docs ai-agents— the custody modes, the adapters, the transcripts and the caps.opschain docs entitlements—packs:ai-agentsand the lapse posture.- The API service is the v2
ModelProviderService(opschain docs api-v2); the gateway route is/api/model/{provider}/…, agent- authenticated and deliberately not part of the admin service.