Skip to content

OpenCode

Codex Pooler OpenCode integration

OpenCode should use Codex Pooler through the narrow OpenAI-compatible /v1 surface. Keep the provider id as openai for this setup so OpenCode continues to use its OpenAI provider-family behavior. The Pool API key authenticates model requests. A separate operator MCP token authenticates the optional remote MCP endpoint. MCP is not required for OpenCode to use Codex Pooler; it only gives an operator MCP host read-only metadata tools.

OpenCode websocket support is the narrow Responses websocket route at GET /v1/responses, not OpenAI Realtime SDK compatibility.

For a deployed instance, use these URLs:

OpenCode provider base URL:
https://codex-pooler.example.com/v1
Remote MCP URL:
https://codex-pooler.example.com/mcp

For local setup, replace the host with http://localhost:4000.

Store the Pool API key outside the config and read it through environment expansion.

{
"$schema": "https://opencode.ai/config.json",
"small_model": "openai/gpt-5.6-luna",
"provider": {
"openai": {
"npm": "@ai-sdk/openai",
"name": "Codex Pooler",
"options": {
"baseURL": "https://codex-pooler.example.com/v1",
"apiKey": "{env:CODEX_POOLER_API_KEY}"
},
"models": {
"gpt-5.6-luna": {
"id": "gpt-5.6-luna",
"name": "GPT-5.6 Luna via Codex Pooler",
"family": "gpt",
"attachment": true,
"reasoning": true,
"tool_call": true,
"temperature": false,
"options": {
"reasoningEffort": "high",
"reasoningSummary": "auto",
"textVerbosity": "medium",
"include": ["reasoning.encrypted_content"],
// Optional: priority processing may cost more than the default tier.
// "serviceTier": "priority",
"store": false
},
"modalities": {
"input": ["text", "image"],
"output": ["text"]
},
"limit": {
"context": 353400,
"input": 289400,
"output": 64000
}
},
"gpt-5.6-terra": {
"id": "gpt-5.6-terra",
"name": "GPT-5.6 Terra via Codex Pooler",
"family": "gpt",
"attachment": true,
"reasoning": true,
"tool_call": true,
"temperature": false,
"options": {
"reasoningEffort": "high",
"reasoningSummary": "auto",
"textVerbosity": "medium",
"include": ["reasoning.encrypted_content"],
// Optional: priority processing may cost more than the default tier.
// "serviceTier": "priority",
"store": false
},
"modalities": {
"input": ["text", "image"],
"output": ["text"]
},
"limit": {
"context": 353400,
"input": 289400,
"output": 64000
}
},
"gpt-5.6-sol": {
"id": "gpt-5.6-sol",
"name": "GPT-5.6 Sol via Codex Pooler",
"family": "gpt",
"attachment": true,
"reasoning": true,
"tool_call": true,
"temperature": false,
"options": {
"reasoningEffort": "high",
"reasoningSummary": "auto",
"textVerbosity": "medium",
"include": ["reasoning.encrypted_content"],
// Optional: priority processing may cost more than the default tier.
// "serviceTier": "priority",
"store": false
},
"modalities": {
"input": ["text", "image"],
"output": ["text"]
},
"limit": {
"context": 353400,
"input": 289400,
"output": 64000
}
}
}
}
}
}

Define only model ids your assigned Pool can serve. If you run Codex Pooler locally, set baseURL to http://localhost:4000/v1.

OpenCode uses small_model for background helpers such as automatic session titles. Without an explicit override, it may infer a nano model that Codex Pools do not serve. Point small_model at a lightweight model assigned to your Pool. The setting remains effective when OMO is loaded.

Request-time OpenAI options belong under each model’s options block. Keep only connection settings such as baseURL and apiKey in provider-level options. The commented serviceTier line shows how to opt into priority processing. Enable it only when your Pool and upstream offer it and you intentionally accept the potentially higher cost; leave it commented to use the default tier.

OpenCode subtracts its compaction reserve from limit.input before declaring the session full. 289400 leaves 269.4k usable input tokens after the default 20k reserve, so 269.4k input plus a 64k output cap stays inside the 353.4k GPT-5.6 window used by these examples. OpenCode caps request output at 32k by default; set OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX=64000 only when you want OpenCode to request the full 64k cap.

If you use Oh My OpenAgent, keep the native openai provider configuration above and add model overrides in ~/.config/opencode/oh-my-openagent.jsonc. Keep the openai/ prefix on every OMO model so delegated agents continue to use the same Codex Pooler provider.

This example assigns Luna to lightweight and background work, Terra to daily agent work, and Sol to planning and deep-reasoning roles. Each explicit fallback stays inside the model ids assigned to the Pool and preserves the primary reasoning variant.

{
"agents": {
"sisyphus": {
"model": "openai/gpt-5.6-terra",
"variant": "high",
"fallback_models": [{ "model": "openai/gpt-5.6-sol", "variant": "high" }]
},
"hephaestus": {
"model": "openai/gpt-5.6-sol",
"variant": "xhigh",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "xhigh" }]
},
"oracle": {
"model": "openai/gpt-5.6-sol",
"variant": "high",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "high" }]
},
"librarian": {
"model": "openai/gpt-5.6-luna",
"variant": "low",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "low" }]
},
"explore": {
"model": "openai/gpt-5.6-luna",
"variant": "low",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "low" }]
},
"multimodal-looker": {
"model": "openai/gpt-5.6-terra",
"variant": "medium",
"fallback_models": [{ "model": "openai/gpt-5.6-sol", "variant": "medium" }]
},
"prometheus": {
"model": "openai/gpt-5.6-sol",
"variant": "high",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "high" }]
},
"metis": {
"model": "openai/gpt-5.6-sol",
"variant": "high",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "high" }]
},
"momus": {
"model": "openai/gpt-5.6-sol",
"variant": "xhigh",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "xhigh" }]
},
"atlas": {
"model": "openai/gpt-5.6-terra",
"variant": "medium",
"fallback_models": [{ "model": "openai/gpt-5.6-sol", "variant": "medium" }]
},
"sisyphus-junior": {
"model": "openai/gpt-5.6-terra",
"variant": "medium",
"fallback_models": [{ "model": "openai/gpt-5.6-sol", "variant": "medium" }]
}
},
"categories": {
"visual-engineering": {
"model": "openai/gpt-5.6-terra",
"variant": "high",
"fallback_models": [{ "model": "openai/gpt-5.6-sol", "variant": "high" }]
},
"ultrabrain": {
"model": "openai/gpt-5.6-sol",
"variant": "xhigh",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "xhigh" }]
},
"deep": {
"model": "openai/gpt-5.6-sol",
"variant": "medium",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "medium" }]
},
"artistry": {
"model": "openai/gpt-5.6-sol",
"variant": "xhigh",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "xhigh" }]
},
"quick": {
"model": "openai/gpt-5.6-luna",
"variant": "low",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "low" }]
},
"unspecified-low": {
"model": "openai/gpt-5.6-luna",
"variant": "low",
"fallback_models": [{ "model": "openai/gpt-5.6-terra", "variant": "low" }]
},
"unspecified-high": {
"model": "openai/gpt-5.6-terra",
"variant": "high",
"fallback_models": [{ "model": "openai/gpt-5.6-sol", "variant": "high" }]
},
"writing": {
"model": "openai/gpt-5.6-terra",
"variant": "medium",
"fallback_models": [{ "model": "openai/gpt-5.6-sol", "variant": "medium" }]
}
}
}

OMO tries configured fallback_models before its built-in model chains. Define only model ids your assigned Pool can serve; if one tier is unavailable, replace it in both primary and fallback entries instead of leaving an unreachable model in the routing map.

Validate the OMO configuration after editing the routing map:

Terminal window
bunx oh-my-openagent doctor --platform=opencode --json

The doctor validates plugin loading, schema, and model resolution, but it does not prove that an upstream can serve the selected model. Send one bounded request through the installed OpenCode headless workflow for every model tier assigned to OMO before relying on the routing map.

Add Codex Pooler as a remote MCP server only when the OpenCode host should inspect metadata that the operator can already see in the admin UI.

{
"mcp": {
"codex_pooler": {
"type": "remote",
"url": "https://codex-pooler.example.com/mcp",
"oauth": false,
"headers": {
"Authorization": "Bearer <operator-mcp-token>"
},
"enabled": true,
"timeout": 30000
}
}
}

Use a dedicated operator MCP token for hosts that persist remote MCP headers. Don’t use a Pool API key for /mcp.

If you automate OpenCode from scripts, use OpenCode’s own documented headless command shape for your installed version and verify both the final response and the expected file changes. The examples on this page focus on configuration, not a full automation workflow.

Codex Pooler provides narrow OpenAI-compatible /v1 support for selected SDK routes. Supported OpenCode traffic should stay on /v1/responses or /v1/chat/completions, depending on the OpenAI provider path OpenCode uses.

GET /v1/responses is narrow Responses websocket compatibility, not /v1/realtime support. /v1/realtime and OpenAI Realtime SDK websocket or session routes are unsupported.

Continuity headers such as session-id, x-session-id, and x-session-affinity are local routing inputs only and are not forwarded upstream.

Unsupported /v1 routes return deterministic OpenAI-shaped unsupported endpoint errors when explicitly routed. Don’t treat Codex Pooler as full OpenAI API parity.