Skip to main content

Responses Proxy provider registration

Register providers through the Responses dashboard/BFF or through the authenticated /admin/* API. The browser should never send provider secrets directly to the backend service; the frontend BFF injects the admin bearer server-side.

For direct operator API calls:

export RESPONSES_PROXY_BASE_URL="https://agent-responses-proxy.svc.cloud.morph.so"
export ADMIN_HEADER="Authorization: Bearer $PROXY_ADMIN_TOKEN"

Validate before saving

Use presets to populate provider forms:

curl -sS -H "$ADMIN_HEADER" "$RESPONSES_PROXY_BASE_URL/admin/provider-presets"

Validate unsaved provider settings:

curl -sS -X POST "$RESPONSES_PROXY_BASE_URL/admin/providers/test" \
-H "$ADMIN_HEADER" \
-H "content-type: application/json" \
-d '{
"id": "kimi-main",
"name": "Kimi Main",
"provider_type": "custom",
"base_url": "https://api.moonshot.ai/v1",
"wire_api": "chat_completions",
"auth_type": "bearer",
"api_key": "replace-with-provider-key"
}'

After saving a provider, validate an upstream model id:

curl -sS -X POST "$RESPONSES_PROXY_BASE_URL/admin/models/test" \
-H "$ADMIN_HEADER" \
-H "content-type: application/json" \
-d '{"provider_id":"kimi-main","upstream_id":"kimi-k2.6"}'

OpenAI Responses

Register an OpenAI Responses provider:

curl -sS -X POST "$RESPONSES_PROXY_BASE_URL/admin/providers" \
-H "$ADMIN_HEADER" \
-H "content-type: application/json" \
-d '{
"id": "openai-main",
"name": "OpenAI Main",
"provider_type": "openai",
"base_url": "https://api.openai.com/v1",
"wire_api": "responses",
"auth_type": "bearer",
"api_key": "replace-with-provider-key"
}'

Register a client-facing alias:

curl -sS -X POST "$RESPONSES_PROXY_BASE_URL/admin/models" \
-H "$ADMIN_HEADER" \
-H "content-type: application/json" \
-d '{
"alias": "openai/gpt-mini",
"provider_id": "openai-main",
"upstream_id": "gpt-4.1-mini"
}'

Clients then send:

{"model": "openai/gpt-mini", "input": "hello"}

Kimi and OpenAI-compatible Chat

Kimi, OpenRouter, and many gateways use the OpenAI-compatible Chat Completions protocol.

curl -sS -X POST "$RESPONSES_PROXY_BASE_URL/admin/providers" \
-H "$ADMIN_HEADER" \
-H "content-type: application/json" \
-d '{
"id": "kimi-main",
"name": "Kimi Main",
"provider_type": "custom",
"base_url": "https://api.moonshot.ai/v1",
"wire_api": "chat_completions",
"auth_type": "bearer",
"api_key": "replace-with-provider-key",
"config": {"endpoint_path": "chat/completions"}
}'

Register an alias:

curl -sS -X POST "$RESPONSES_PROXY_BASE_URL/admin/models" \
-H "$ADMIN_HEADER" \
-H "content-type: application/json" \
-d '{"alias":"kimi/k2","provider_id":"kimi-main","upstream_id":"kimi-k2.6"}'

For OpenRouter, use its base URL and upstream model id:

{
"id": "openrouter-main",
"base_url": "https://openrouter.ai/api/v1",
"wire_api": "chat_completions",
"upstream_id_example": "replace-with-openrouter-model-id"
}

Anthropic Messages

Anthropic uses the Messages API with an API-key header:

curl -sS -X POST "$RESPONSES_PROXY_BASE_URL/admin/providers" \
-H "$ADMIN_HEADER" \
-H "content-type: application/json" \
-d '{
"id": "anthropic-main",
"name": "Anthropic Main",
"provider_type": "anthropic",
"base_url": "https://api.anthropic.com/v1",
"wire_api": "anthropic_messages",
"auth_type": "api_key",
"auth_header": "x-api-key",
"health_path": null,
"api_key": "replace-with-provider-key",
"config": {
"endpoint_path": "messages",
"anthropic_version": "2023-06-01",
"default_max_tokens": 4096
}
}'

Register an alias:

curl -sS -X POST "$RESPONSES_PROXY_BASE_URL/admin/models" \
-H "$ADMIN_HEADER" \
-H "content-type: application/json" \
-d '{
"alias": "anthropic/sonnet",
"provider_id": "anthropic-main",
"upstream_id": "replace-with-anthropic-model-id"
}'

Use aliases from Codex

Codex still points at Responses Proxy as a Responses provider. Choose a registered alias as the model:

codex \
-c model_provider='"proxy"' \
-c model='"kimi/k2"' \
-c model_providers.proxy.name='"Responses Proxy"' \
-c model_providers.proxy.base_url='"https://agent-responses-proxy.svc.cloud.morph.so/v1"' \
-c model_providers.proxy.wire_api='"responses"'

For aliases Codex does not know, add them to codex-model-catalog.json or provide your own catalog with MODEL_CATALOG_JSON=/path/to/models.json.

Current limits

  • responses, chat_completions, and anthropic_messages providers are routable.
  • wire_api="custom" providers are stored but not routable until a custom adapter exists.
  • Non-Responses adapters support text, streaming text, function tools, Codex custom tools, and namespace tool containers.
  • OpenAI-hosted Responses tools that cannot run on Chat Completions or Anthropic providers, such as web_search, are omitted for compatibility.
  • Image, audio, realtime, and unknown provider-specific tool types fail early with a clear error.
  • Chat Completions and Anthropic are stateless upstream protocols, so the proxy stores reconstructed response state in SQL for previous_response_id continuations.