Model gateway
Model API keys never enter the workspace.
model-gateway accepts its own client token from the workspace, strips it, injects the real provider key, and forwards only allowlisted paths. Compose sets ANTHROPIC_BASE_URL=http://model-gateway:7434/anthropic and exports ANTHROPIC_AUTH_TOKEN from the gateway token file — Claude Code and the Anthropic SDKs work unchanged.
Note
Use ANTHROPIC_AUTH_TOKEN (sent as Authorization: Bearer). Don't set ANTHROPIC_API_KEY in the workspace — it's sent as x-api-key, which the gateway doesn't accept as a client token.
Configure routes
{
"routes": [
{
"prefix": "/anthropic",
"upstream": "https://api.anthropic.com",
"allowPaths": ["^/v1/messages$", "^/v1/messages/count_tokens$", "^/v1/models$"],
"inject": { "header": "x-api-key", "valueFile": "/run/secrets/anthropic_api_key" }
}
],
"budget": { "maxRequestsPerHour": 600, "maxGlobalRequestsPerHour": 3000, "maxRequestBytes": 8388608 },
"maxConcurrent": 8
}Other SDKs work the same way: point their base URL at http://model-gateway:7434/<prefix> and use the gateway token.
Setup
umask 077; openssl rand -hex 32 > ~/.agentgate-model-gateway-tokenSet ANTHROPIC_API_KEY_PATH and AGENTGATE_MODEL_GATEWAY_CLIENT_TOKEN_PATH in .env. The key file must be mode 600 and owned by the container's node user, or the gateway returns 503. It's re-read on every request, so rotation needs no restart.
Guarantees
- Only
GETandPOSTto paths matching an anchoredallowPathsregex; everything else is 404. Dot segments,//, and encoded separators are refused. - Client auth headers, cookies,
x-agentgate-*, and forwarding headers are stripped. Redirects are refused. - Responses stream back unchanged (SSE works), minus
set-cookieand any header containing the injected key. - A separate token from agentd's, so a compromised gateway can't call the broker.
Budgets
maxRequestsPerHour is a token bucket per client IP; maxGlobalRequestsPerHour spans all clients. Both return 429 RATE_LIMITED with Retry-After. maxRequestBytes (default 8 MiB) caps bodies; maxConcurrent and maxBufferedBytes return 503 GATEWAY_BUSY.