Claude Pool
Serve an organization's Claude traffic on registered Claude subscription setup-tokens, metered and billed exactly like API-key usage.
The Claude Pool lets a platform admin register Claude subscription setup-tokens (or Anthropic API keys) for an organization. Tokamak then uses those tokens as the upstream credential for that organization's Anthropic requests through the ordinary /v1/messages router.
Three properties define it:
- It is a credential source, not a product path. The pool changes only which secret Tokamak puts on the upstream call. Provider resolution, billing admission, the execution id, the usage row, pricing, settlement,
usage.cost,/v1/generationand usage limits are the same code the provider-key path runs. A pooled generation is admitted, metered, priced and charged exactly like an API-key one. - Tokens never leave the server. They are validated once, encrypted at rest, decrypted per request in memory, and never shown again. Only the last four characters are visible.
- Members see nothing. There is no member-facing pool surface.
tokamak launch claudebehaves as today; when the organization's pool is on, the router serves it on pooled tokens.
How Anthropic accepts a setup-token
Anthropic serves a subscription token as Authorization: Bearer sk-ant-oat…. Haiku-class models are served on any request. Sonnet, Opus and Fable-class models are served only when the first system block is Claude Code's own identity line. Claude Code always sends that line, so Claude Code traffic through the router needs no rewriting. Other clients (SDKs, curl) sending their own system prompt get an instant 429 rate_limit_error on those models, and Tokamak forwards bodies as received — it never prepends the identity line to make a request eligible. Such a request simply uses the organization's provider API key, untouched.
Turning it on
1. Platform switch (operator)
On tokamak-core:
TOKAMAK_CLAUDE_POOL_ENABLED=true
TOKAMAK_CLAUDE_POOL_TOKEN_ENCRYPTION_KEY=<a long random secret>
TOKAMAK_CLAUDE_POOL_TOKEN_ENCRYPTION_KEY_ID=v1Core refuses to boot with the switch on and no key. With the switch off (the default) the pool does not exist: nothing is consulted on the request path and the admin API answers 404. See Environment variables for the optional knobs.
2. Organization switch (platform admin)
In the admin console, open Organizations, choose the organization and click Claude Pool. Turn it On and set the priority. Nothing here is visible to the organization's members.
| Setting | Options | Meaning |
|---|---|---|
| Priority | Pool first (default) | Pooled credentials are tried first; the provider API key is the fallback when the pool is exhausted or rejected. |
| Provider key first | The provider API key is tried first; the pool is the fallback. |
Eligibility is not configurable: a request whose first system block is Claude Code's identity line, or any Haiku request, may ride the pool; everything else uses the organization's provider API key, untouched, whichever priority is set.
3. Register tokens (platform admin)
The token owner runs:
claude setup-tokenand hands the sk-ant-oat01-… value to the admin, who pastes it into Register token on the same panel, optionally with an alias. Tokamak proves the token live with one count_tokens call, encrypts it, and stores the last four characters as the visible hint. Anthropic API keys (sk-ant-api…) are accepted too. Claude Code session files (auth.json) are not accepted: Tokamak does not hold refresh chains.
Operating it
The credentials table shows, per token: alias, hint, status, Anthropic's own five-hour and seven-day utilization (read from the response headers on every pooled call), when it was last used, and today's pooled requests and cost attributed to it.
| Status | Meaning | Action |
|---|---|---|
active | Selectable | — |
paused | Admin took it out of rotation | Resume |
invalid | Anthropic answered 401/403 | Resume to re-test, or revoke and register a fresh token |
revoked | Terminal | — |
How the router picks a credential for a request:
- The requesting member's own credential first (when an admin registered one on their behalf), then the least recently used shared credential.
- Credentials that are rate-limited, or whose five-hour utilization is at or above
TOKAMAK_CLAUDE_POOL_UTILIZATION_CEILING(default 90 %) inside its window, are skipped. - A session stays on the same credential for
TOKAMAK_CLAUDE_POOL_AFFINITY_TTL(default 60 s) so Anthropic's prompt cache keeps hitting. The key is the organization, user, model and the client's session id (a request without a session id shares one slot per user and model). WithREDIS_URLset, every core replica shares it; affinity only reorders credentials that pass the checks above. - If the upstream rejects the credential (401/403, or a real 429 with
retry-after), it is marked — a real 429 quarantines every token of the same Anthropic account — and the request falls through to the next credential in the order, ending with the provider API key, inside the same byte-for-byte forward: the request bytes are re-sent unchanged, only the credential differs. At mostTOKAMAK_CLAUDE_POOL_MAX_RETRIES(default 2) such retries happen per request, and only rejections that produced no generation are retried, so nothing is ever billed twice. - Pooled secrets are released only to HTTPS endpoints on
TOKAMAK_CLAUDE_POOL_ALLOWED_HOSTS(defaultapi.anthropic.com). An Anthropic-kind provider pointed anywhere else is served on the provider key. - A token registered with an owner and not shared serves only that member. Shared tokens (the default) serve every member. Rows copied from the previous pool keep their
sharedflag.
When the pool took part in a request, the response carries X-Tokamak-Credential-Source: pool or provider_key naming the credential that answered. Deployments with the pool off never see those two values. An organization's own provider key (bring your own key) is tried before the pool: a request it served, or a 503 byok_key_unavailable about it, carries org_key, and one that fell back from it carries org_key_fallback unless the pool then served it. Responses served on a pooled token do not expose the shared account's anthropic-ratelimit-*, organization or workspace headers.
Metering and billing
Pooled rows in token_usage differ from provider-key rows in exactly two columns: credential_source (pool) and pool_credential_id. Everything else — model, provider, tokens, estimated_cost_usd, execution_id, the settled charge — is produced by the same funnel, at the same catalog prices. Usage dashboards, usage limits and invoices therefore include pooled traffic with no special handling.
Migrating from the previous agent pool
Deployments that still run the pre-prune agent pool keep their tokens: migration 000081 copies active setup_token and api_key rows into the new store, switches those organizations on with the default policy so nobody loses the pool on deploy, scrubs every secret column from the old rows and renames the old table rather than dropping it (an audit skeleton remains: who contributed what type, when). session and auth_json rows are not copied; their owners should hand an admin a fresh claude setup-token. Copied rows are re-encrypted under the new key by the claude-pool-rekey job at boot.
The old CLI's GET /v1/agent-pool/launch-auth answers 404 with an upgrade hint and never returns a token; the CLI then offers the router path. Run tokamak update.
Access control
Fixed roles, scoped permissions and the separation between platform and tenant administration.
Bring your own key
Let an organization route its Anthropic and OpenAI traffic through its own provider accounts. Configure the encryption key, switch BYOK on per organization, and watch key health and fallback across the platform.