Responses Proxy concepts
Responses Proxy has a simple boundary: clients send OpenAI Responses-shaped traffic to one Morph endpoint, and the proxy routes each request through a registered provider and model alias.
For most users, the mental model is:
- Register a provider such as OpenAI, Kimi/OpenRouter, Anthropic, or an internal gateway.
- Register a model alias such as
openai/gpt-minioranthropic/sonnet. - Mint an org-scoped proxy key.
- Send
POST /v1/responseswith that key andmodelset to the alias. - Let the proxy inject credentials, translate protocols when needed, preserve affinity, and record telemetry.
Claude Code can also connect through the Anthropic Messages-compatible gateway at /v1/messages. That gateway uses the same org-scoped proxy keys, providers, aliases, credential rows, and telemetry as the Responses facade.
Core concepts
| Concept | What it means |
|---|---|
| ServiceProvider | Durable SQL record for a backend that can serve model, agent, or compound-agent traffic. |
| Model alias | Client-facing model value stored in registered_models and linked to a provider. |
| Proxy key | Org-scoped data-plane credential used as Authorization: Bearer <key> on /v1/responses. |
| Adapter | Runtime translator for an upstream wire protocol. Supported adapters are responses, chat_completions, and anthropic_messages. |
| Resource | Active load-balancer target derived from an enabled, credential-resolved provider. |
| Session affinity | Redis mapping that keeps a logical conversation on the same resource. |
| Response affinity | Mapping from a resp_* id to the resource that produced it. |
| Proxy-owned response state | SQL state used to support previous_response_id continuations for stateless upstream protocols. |
| Durable telemetry | SQL history for sessions, requests, token usage, decisions, providers, aliases, and raw events. Request and decision rows are written on the request path; raw telemetry events are written by the worker. |
| Claude Code BYOS | Stored-subscription flow that lets a user teleport local Claude Code OAuth credentials into an encrypted org-owned provider credential row. |
Service providers
A ServiceProvider answers these questions:
- Where is the backend?
- Which protocol does it speak?
- How should the proxy authenticate?
- Which credential or secret reference should be used?
- What metadata should dashboards and operators see?
Enabled providers with a supported wire_api and a resolvable credential become active runtime resources after startup, registry mutation, manual reload, or periodic SQL refresh.
Providers, aliases, and proxy keys are scoped to the Morph organization. Two orgs can use the same alias string independently. A proxy key binds data-plane routing to its owning org, so requests only see that org's providers and aliases.
Supported routable wire_api values:
responseschat_completionsanthropic_messages
custom providers can be stored for future use but are not routable until a custom adapter exists.
Model aliases
POST /v1/responses create requests must include a valid proxy key and a registered alias in model.
An alias links the client-facing model name to:
provider_idupstream_id- optional route hints
- capabilities and metadata
When a request uses an alias, the proxy pins routing to that provider pool, rewrites the upstream model to route.model or upstream_id, and records both provider_id and model_alias in telemetry.
Resources and pools
Resources are derived from org-scoped registry rows. A resource includes provider credentials, base URL, auth settings, health path, provider id, pool id, weight, and wire API.
Preferred BYOS credentials live in provider credential rows owned by the same org and provider. A row can be an encrypted inline credential, an environment reference, or a feature-gated Claude Code OAuth credential. If at least one enabled credential row resolves, routing uses those rows only.
If no enabled credential rows exist, the provider falls back to provider-level sources: env-sourced key slots, encrypted inline api_key, then credential_ref=env:NAME. The provider id becomes an uppercase env prefix with non-alphanumeric characters replaced by _: openai uses OPENAI_API_KEY, OPENAI_API_KEY_1, and later numbered slots; kimi.k2 uses KIMI_K2_API_KEY. The base variable is slot env0, numbered slots may have gaps, and duplicate values collapse to one resource.
Admin responses expose credential_count, credential_resolved, resolved_key_count, and pool_size, never raw keys.
Env-sourced provider keys are deployment-global and resolve only for PROXY_BOOTSTRAP_ORG_ID by default, or for org ids listed in PROXY_ENV_CREDENTIAL_OWNER_ORG_IDS. Provider rows, aliases, telemetry, and proxy keys remain org-scoped, but two allowed orgs using the same provider id share the same env prefix and physical key pool. Use org-distinct provider ids, such as openai-seele -> OPENAI_SEELE_API_KEY, when physical key isolation matters.
Alias routing pins the pool to route.pool_id when present, otherwise to the provider id. This prevents an incoming pool header from selecting credentials that do not match the alias.
Affinity and continuations
Session ids can come from:
X-Proxy-Session-IDX-Session-IDmetadata.session_idmetadata.session_uuidmetadata.conversation_idmetadata.thread_idconversationconversation.id
Response affinity maps resp_* ids to the resource that produced them. Continuations using previous_response_id or /v1/responses/resp_... can route by affinity even when the create-time alias gate is not involved.
For Chat Completions and Anthropic providers, the proxy creates its own resp_* ids and stores reconstructed response state in SQL. This lets Codex continuations work against stateless upstream APIs when the same SQL database is reused.
Retry failover only applies to initial upstream failures before a continuation is pinned by response affinity. Retryable failures include 429, 502, 503, 504, connection errors, and timeouts. Terminal client and quota failures are returned unchanged.
Claude Code gateway
Claude Code connects to /v1/messages, /v1/messages/count_tokens, and /v1/models. Because Claude Code may already use Authorization or x-api-key for Anthropic credentials, the proxy key is read from X-Responses-Proxy-Key by default.
Registered-alias mode is the managed path. The proxy key selects an org, the Claude model name must be an org-owned alias, and the proxy injects the selected provider credential. Aliases may point at anthropic_messages, responses, or deployment-enabled chat_completions providers. Responses aliases translate Claude Messages into Responses and back into Anthropic Messages-shaped JSON or SSE. Chat Completions aliases use the same canonical conversion, then pass through the OpenAI-compatible Chat adapter in both directions.
Each alias can declare capabilities.claude_code: enabled, profile, images, documents, client_tools, parallel_tools, and hosted_tools. The default profile is inferred from wire_api; Boolean fields default to true, while hosted tools default to none. Alias create and update validate the schema and reject profiles that do not match the provider protocol.
Portable translated content includes text, base64/URL images, base64/text documents, client function tools, tool calls, and tool results. Chat Completions does not portably accept document URLs. Only hosted web_search has a Responses mapping; Chat Completions has no hosted-tool mapping. Unsupported translated content fails explicitly instead of being discarded.
Direct passthrough mode is available only for model ids listed in PROXY_CLAUDE_GATEWAY_DIRECT_MODELS. It forwards the caller's local Anthropic credential while still recording org-scoped telemetry.
For stored-subscription BYOS, the dashboard creates a claude_code_oauth_sessions setup row and returns a one-time setup token. responses-proxy-claude-code teleport runs where Claude Code is already authenticated, discovers the local OAuth login state, and completes the session. The proxy stores an encrypted provider_credentials.kind="claude_code_oauth" row. Stored Claude Code OAuth credentials are pinned to first-party Anthropic routing and can refresh server-side when PROXY_CLAUDE_CODE_OAUTH_REFRESH_URL is configured.
Telemetry
The proxy records lb_decision and request_completed domain rows inline so request history, token totals, and dashboard metrics update as soon as requests finish. It also emits the same events to Redis. The worker consumes the Redis stream to persist raw telemetry events and replay domain rows idempotently if a request-path write or worker delivery was interrupted.
Durable telemetry includes:
- sessions
- requests
- load-balancer decisions
- token usage
- raw telemetry events
Dashboard-facing rows include provider_id and model_alias so operators can filter by provider or alias.
Request and response body persistence is disabled by default with PROXY_CAPTURE_REQUEST_BODY=false and PROXY_CAPTURE_RESPONSE_BODY=false. Token usage still persists separately when providers return usage metadata.
Live state versus durable state
Redis stores live counters, recent decisions, resource health, active resource ids, affinity, and queue depth. SQL stores providers, aliases, sessions, requests, decisions, token usage, proxy-owned response state, and raw telemetry events.
Redis can reset on deploy or container lifecycle. SQL persists when the same PROXY_DATABASE_URL is reused.
Deleting a provider or alias removes the registry row. The enabled field is a runtime pause while the row exists; disabled provider and model rows are purged on proxy boot.