|
1 | 1 | <h1 align="center">Codex Pooler</h1> |
2 | 2 |
|
3 | 3 | <p align="center"> |
4 | | - <strong>One gateway for many Codex accounts.</strong><br> |
5 | | - Pool capacity, preserve sessions, route requests, and expose stable API keys |
6 | | - for agents and tools. |
| 4 | + <strong>The full featured self-hosted Codex gateway, for teams, agents and you. Works with:</strong><br> |
| 5 | + <br> |
| 6 | + <a href="https://docs.codex-pooler.com/clients/opencode/" title="OpenCode"><img src=".github/assets/opencode-favicon.png" alt="OpenCode" width="24" height="24"></a> |
| 7 | + <a href="https://docs.codex-pooler.com/clients/codex-cli/" title="Codex CLI and Codex Desktop"><img src=".github/assets/codex-cli-favicon.png" alt="Codex CLI and Codex Desktop" width="24" height="24"></a> |
| 8 | + <a href="https://docs.codex-pooler.com/clients/openclaw/" title="OpenClaw"><img src=".github/assets/openclaw-favicon.png" alt="OpenClaw" width="24" height="24"></a> |
| 9 | + <a href="https://docs.codex-pooler.com/clients/hermes/" title="Hermes Agent"><img src=".github/assets/hermes-favicon.png" alt="Hermes Agent" width="24" height="24"></a> |
| 10 | + <a href="https://docs.codex-pooler.com/clients/pi/" title="Pi"><img src=".github/assets/pi-favicon.png" alt="Pi" width="24" height="24"></a> |
| 11 | + <a href="https://docs.codex-pooler.com/clients/omp/" title="OMP"><img src=".github/assets/omp-favicon.png" alt="OMP" width="24" height="24"></a> |
| 12 | + <a href="https://docs.codex-pooler.com/clients/kilo/" title="Kilo"><img src=".github/assets/kilo-favicon.png" alt="Kilo" width="24" height="24"></a> |
| 13 | + <a href="https://docs.codex-pooler.com/clients/aider/" title="Aider"><img src=".github/assets/aider-favicon.png" alt="Aider" width="24" height="24"></a> |
| 14 | + <a href="https://docs.codex-pooler.com/clients/continue/" title="Continue"><img src=".github/assets/continue-favicon.png" alt="Continue" width="24" height="24"></a> |
| 15 | + <a href="https://docs.codex-pooler.com/clients/cline/" title="Cline"><img src=".github/assets/cline-favicon.png" alt="Cline" width="24" height="24"></a> |
| 16 | + <a href="https://docs.codex-pooler.com/clients/goose/" title="Goose"><img src=".github/assets/goose-favicon.png" alt="Goose" width="24" height="24"></a> |
| 17 | + <a href="https://docs.codex-pooler.com/clients/windmill/" title="Windmill AI"><img src=".github/assets/windmill-favicon.png" alt="Windmill AI" width="24" height="24"></a> |
| 18 | + <a href="https://docs.codex-pooler.com/clients/openhands/" title="OpenHands"><img src=".github/assets/openhands-favicon.png" alt="OpenHands" width="24" height="24"></a> |
| 19 | + <a href="https://docs.codex-pooler.com/clients/openai-compatible/" title="OpenAI-compatible SDKs"><img src=".github/assets/python-favicon.png" alt="OpenAI-compatible SDKs" width="24" height="24"></a> |
| 20 | + <a href="https://docs.codex-pooler.com/clients/openai-compatible/" title="OpenAI-compatible SDKs"><img src=".github/assets/nodejs-favicon.png" alt="OpenAI-compatible SDKs" width="24" height="24"></a> |
| 21 | + <a href="https://docs.codex-pooler.com/clients/openai-compatible/" title="Vercel AI SDK"><img src=".github/assets/vercel-favicon.png" alt="Vercel AI SDK" width="24" height="24"></a> |
7 | 22 | </p> |
8 | 23 |
|
9 | 24 | <p align="center"> |
|
43 | 58 | </tr> |
44 | 59 | </table> |
45 | 60 |
|
46 | | -Codex Pooler is a self-hosted gateway for sharing Codex account capacity across |
47 | | -agents, tools, and teams. |
| 61 | +Codex Pooler is a self-hosted gateway for running Codex-compatible agents, |
| 62 | +tools, and automation through stable Pool API keys. It works with one upstream |
| 63 | +Codex account for credential isolation, client normalization, metadata-only |
| 64 | +operations, and saved reset visibility; add more accounts when you want shared |
| 65 | +capacity and routing across eligible accounts. |
48 | 66 |
|
49 | | -Instead of binding each client to one Codex account, you add accounts to Pools |
50 | | -and issue stable Pool API keys. Clients send familiar Codex backend or |
51 | | -OpenAI-compatible requests; Codex Pooler selects the right account based on |
52 | | -model support, limits, session continuity, routing policy, and health. |
| 67 | +Clients send familiar Codex backend or OpenAI-compatible requests; Codex Pooler |
| 68 | +selects an eligible account based on model support, quota evidence, limits, |
| 69 | +session continuity, routing policy, and health. The Pool key stays stable while |
| 70 | +upstream assignments, lifecycle state, reset policy, and capacity change behind |
| 71 | +it. |
53 | 72 |
|
54 | | -Operators get one place to manage accounts, keys, routing, request accounting, |
55 | | -audit logs, and health without storing prompts, files, audio, images, bearer |
56 | | -tokens, or raw Codex secrets. Instance owners keep the global administration |
57 | | -surface, while instance admins work only with their assigned Pools. |
| 73 | +Operators get one place to manage Pools, accounts, API keys, saved resets, |
| 74 | +routing, request accounting, audit logs, and health without storing prompts, |
| 75 | +files, audio, images, bearer tokens, or raw Codex secrets. Instance owners keep |
| 76 | +the global administration surface, while instance admins work only with their |
| 77 | +assigned Pools. |
58 | 78 |
|
59 | 79 | ## Highlights |
60 | 80 |
|
61 | | -- **One key for many accounts:** group Codex accounts into Pools and give |
62 | | - clients stable Pool API keys instead of binding each tool to one account |
63 | | -- **Smarter capacity sharing:** route each request to an eligible account with |
64 | | - available limits, matching model support, health, session state, and Pool |
| 81 | +- 🔑 **Stable Pool API keys:** give clients one Pool credential whether the Pool |
| 82 | + currently has one upstream account or several, without distributing raw Codex |
| 83 | + account material |
| 84 | +- 🎯 **Eligibility-aware routing:** route each request to an account with compatible |
| 85 | + model support, usable quota evidence, matching health, session state, and Pool |
65 | 86 | policy |
66 | | -- **Codex backend compatibility:** point Codex-compatible clients at Codex |
| 87 | +- 🧩 **Codex backend compatibility:** point Codex-compatible clients at Codex |
67 | 88 | Pooler and keep responses, compacting, usage, files, audio, images, and |
68 | | - backend websocket flows working through pooled accounts |
69 | | -- **OpenAI-compatible SDK surface:** let `/v1`-only apps and agent tools use |
70 | | - multiple Codex subscriptions behind one gateway, with supported requests |
71 | | - translated and routed through Codex capacity to help contain API spend |
72 | | -- **Session-aware websockets:** keep resumable Codex sessions and websocket |
| 89 | + backend websocket flows working through assigned accounts |
| 90 | +- 🔌 **OpenAI-compatible SDK surface:** let `/v1`-only apps and agent tools use |
| 91 | + Codex capacity through the same Pool boundary, with supported requests |
| 92 | + translated and routed to help contain API spend |
| 93 | +- 🔁 **Session-aware websockets:** keep resumable Codex sessions and websocket |
73 | 94 | reconnects attached to the right upstream account without translating backend |
74 | 95 | websocket traffic through an HTTP compatibility layer |
75 | | -- **Prompt-cache locality:** use a transient `prompt_cache_key` to prefer the |
| 96 | +- ⚡ **Prompt-cache locality:** use a transient `prompt_cache_key` to prefer the |
76 | 97 | same eligible upstream account for repeat stateless requests, improving |
77 | 98 | provider-side cache locality without storing prompts or responses locally |
78 | | -- **Per-Pool request compression:** optionally compress upstream-bound |
| 99 | +- 🗜️ **Per-Pool request compression:** optionally compress upstream-bound |
79 | 100 | Responses tool outputs before dispatch on supported request routes. The |
80 | 101 | option is disabled by default, request-side only, and records safe aggregate |
81 | 102 | savings without storing raw outputs. |
82 | | -- **Operator dashboard:** manage Pool-scoped accounts, API keys, invites, |
83 | | - usage, request logs, audit logs, MCP access, and the owner-only jobs, |
| 103 | +- 🏦 **Saved reset management:** surface reported saved or banked reset credits on |
| 104 | + upstream accounts, show known expirations when available, and let operators |
| 105 | + redeem manually or opt into guarded auto-redemption policy |
| 106 | +- 🖥️ **Operator dashboard:** manage Pool-scoped accounts, API keys, invites, saved |
| 107 | + resets, usage, request logs, audit logs, MCP access, and the owner-only jobs, |
84 | 108 | operators, and system settings surfaces |
85 | | -- **Privacy-minded observability:** store request, routing, and audit metadata |
| 109 | +- 🛡️ **Privacy-minded observability:** store request, routing, and audit metadata |
86 | 110 | without storing prompts, file bodies, audio, images, bearer tokens, cookies, |
87 | 111 | raw Codex account tokens, or raw API keys |
88 | | -- **Configurable without code changes:** tune Pool policy, gateway defaults, |
| 112 | +- ⚙️ **Configurable without code changes:** tune Pool policy, gateway defaults, |
89 | 113 | diagnostics, model support, limits, and operational settings from the admin UI |
90 | | -- **Built for self-hosting:** run on Elixir/Erlang's fault-tolerant runtime, |
| 114 | +- 🐳 **Built for self-hosting:** run on Elixir/Erlang's fault-tolerant runtime, |
91 | 115 | start locally with Docker Compose, or deploy the Helm chart with separate web, |
92 | 116 | worker, scheduler, and migration roles for Kubernetes-friendly, multinode |
93 | 117 | growth |
@@ -1340,10 +1364,13 @@ docker compose down -v |
1340 | 1364 | After bootstrap: |
1341 | 1365 |
|
1342 | 1366 | 1. Create a Pool in `/admin/pools` |
1343 | | -2. Link, import, or invite Codex accounts in `/admin/upstreams` |
| 1367 | +2. Link, import, or invite one or more Codex accounts in `/admin/upstreams` |
1344 | 1368 | 3. Create a Pool API key in `/admin/api-keys` |
1345 | 1369 | 4. Point Codex or SDK clients at one of the runtime base URLs: |
1346 | 1370 |
|
| 1371 | +One upstream account is enough for a working setup. Additional upstreams expand |
| 1372 | +the same Pool into shared capacity without changing client credentials. |
| 1373 | + |
1347 | 1374 | Prefer `OAuth` in `/admin/upstreams` for new operator-managed upstream |
1348 | 1375 | accounts when browser authorization is practical. The admin dialog links the |
1349 | 1376 | account, stores resulting credential material through encrypted upstream secret |
@@ -1390,77 +1417,21 @@ audit rows for archived or deleted Pools remain owner-only. |
1390 | 1417 |
|
1391 | 1418 | ## Runtime Compatibility |
1392 | 1419 |
|
1393 | | -Codex Pooler supports two client-facing shapes: |
1394 | | - |
1395 | | -- **Codex backend clients:** `/backend-api/codex/*`, `/backend-api/files`, |
1396 | | - `/backend-api/transcribe`, usage routes, and backend websocket response |
1397 | | - streams |
1398 | | -- **OpenAI-style SDK clients:** `/v1/models`, `/v1/responses`, |
1399 | | - `/v1/chat/completions`, `/v1/files`, `/v1/audio/transcriptions`, selected |
1400 | | - image endpoints, and narrow Responses websocket compatibility on |
1401 | | - `GET /v1/responses` |
1402 | | - |
1403 | | -The `/v1` surface is compatibility, not a second engine. Supported requests are |
1404 | | -translated into Codex-compatible calls, then routed through the same Pool rules, |
1405 | | -limit checks, accounting, and account selection path. `/v1/realtime` and OpenAI |
1406 | | -Realtime SDK websocket or session routes are not supported. |
1407 | | - |
1408 | | -OpenAI Responses remote MCP tool definitions such as top-level tools[type=mcp] and nested additional_tools tools[type=mcp] are rejected before upstream dispatch; use client-side MCP configuration or Codex Pooler's separate /mcp operator endpoint for metadata tooling. |
1409 | | - |
1410 | | -Public `/v1` responses preserve client-facing OpenAI shapes where possible: |
1411 | | - |
1412 | | -- `/v1/chat/completions` returns content-filter stops as |
1413 | | - `finish_reason: "content_filter"`; max-output fallbacks still use the |
1414 | | - `finish_reason: "length"` shape. |
1415 | | -- Server-class upstream, gateway, or provider failures redact provider and |
1416 | | - internal text. Clients receive safe generic server errors such as |
1417 | | - `upstream request failed`, while explicit local validation failures remain |
1418 | | - `invalid_request_error` responses with safe details. |
1419 | | -- `/v1/files` direct uploads accept only public HTTPS upstream `upload_url` |
1420 | | - values. Loopback, private, reserved, NAT64, userinfo, non-HTTPS, and raw |
1421 | | - control or whitespace URLs are rejected before the direct PUT. |
1422 | | - |
1423 | | -Continuity headers are local routing inputs. Codex Pooler chooses them in this |
1424 | | -order: `x-codex-window-id` > `x-codex-session-id` > `session-id` > |
1425 | | -`x-session-id` > `x-session-affinity` > `session_id` > |
1426 | | -`x-codex-conversation-id`. `session-id`, `x-session-id`, and |
1427 | | -`x-session-affinity` are not forwarded upstream. The raw `x-codex-window-id` |
1428 | | -value is hashed before it becomes a local persisted session key. Local timing |
1429 | | -regressions showed `/v1/responses` HTTP streaming and Responses websocket paths |
1430 | | -stay inside the observed client budgets with the existing stream timeout |
1431 | | -settings, so no new route-specific timeout defaults are required. |
1432 | | - |
1433 | | -Backend regular HTTP Responses and compact routes forward request-scoped |
1434 | | -`x-codex-turn-state` plus the approved lineage metadata headers upstream: |
1435 | | -`x-codex-turn-metadata`, `x-codex-window-id`, |
1436 | | -`x-codex-parent-thread-id`, `x-codex-installation-id`, and |
1437 | | -`x-openai-subagent`. They also relay upstream `x-codex-turn-state` response |
1438 | | -headers downstream. Public `/v1/responses` and websocket request headers do not |
1439 | | -use that backend-only forwarding lane; backend websocket request-scoped turn |
1440 | | -state travels in `response.create.client_metadata["x-codex-turn-state"]`, and |
1441 | | -raw metadata values are not persisted. |
1442 | | - |
1443 | | -Request compression is a per-Pool admin option stored as |
1444 | | -`request_compression_enabled`. It is disabled by default. When enabled, Codex |
1445 | | -Pooler can rewrite request-side Responses tool-output payloads before upstream |
1446 | | -dispatch for these routes only: `POST /backend-api/codex/responses`, |
1447 | | -`POST /backend-api/codex/v1/responses`, |
1448 | | -`POST /backend-api/codex/v1/chat/completions`, `POST /v1/responses`, |
1449 | | -`POST /v1/chat/completions`, `POST /backend-api/codex/responses/compact`, |
1450 | | -`POST /backend-api/codex/v1/responses/compact`, and backend or narrow public |
1451 | | -Responses websocket `response.create` work. Multipart, file, audio, image, |
1452 | | -admin, MCP, usage, and other non-Responses requests are not eligible; public |
1453 | | -`/v1/responses/compact` remains unsupported because it has no upstream compact |
1454 | | -dispatch. |
1455 | | - |
1456 | | -Compression preserves protected exact-output tool results before rewriting: |
1457 | | -default exact-output function tools `Read`, `Glob`, `Grep`, `Write`, and `Edit`, |
1458 | | -plus external retrieval outputs, stay byte-for-byte upstream-bound. Output-only |
1459 | | -function tool results also fail closed as protected when the tool name is not |
1460 | | -available. Only aggregate skip counts are recorded in safe `payload_compression` |
1461 | | -metadata. |
1462 | | -Request compression is request-side only. Codex Pooler does not store raw tool |
1463 | | -outputs or raw response bodies. |
| 1420 | +Use the client guides when wiring a specific tool. At a glance, clients pick one |
| 1421 | +of two public shapes: |
| 1422 | + |
| 1423 | +- **Codex backend clients** use `/backend-api/codex` for Codex-native behavior |
| 1424 | + such as sessions, compacting, files, audio, images, and backend websockets. |
| 1425 | +- **OpenAI-compatible clients** use `/v1` for supported SDK-style Responses, |
| 1426 | + chat, files, audio, image, and model-list calls. |
| 1427 | + |
| 1428 | +Both paths authenticate with Pool API keys and route through the same Pool |
| 1429 | +policy, account health, model support, quota evidence, session continuity, and |
| 1430 | +metadata-only accounting. Codex Pooler is intentionally not a wildcard OpenAI |
| 1431 | +proxy; unsupported API areas fail predictably. For exact route details, use the |
| 1432 | +[Runtime Routes](https://docs.codex-pooler.com/reference/runtime-routes/) |
| 1433 | +reference and the |
| 1434 | +[OpenAI-compatible client guide](https://docs.codex-pooler.com/clients/openai-compatible/). |
1464 | 1435 |
|
1465 | 1436 | ## Operator MCP Service |
1466 | 1437 |
|
|
0 commit comments