Summary
The built-in kimi-coding provider cannot reach api.kimi.com/coding/v1/messages from gsd-pi. Every request returns HTTP 429 with body
{"error":{"type":"rate_limit_error","message":"The engine is currently overloaded, please try again later"},"type":"error"}
The Anthropic SDK retries 3× (~21s each), then gsd's auto-retry starts another round — so the turn eventually aborts with stopReason: error. Thinking mode, tools, and stream: true are all irrelevant; the 429 fires before any model work happens.
Root cause
Kimi's /coding gateway filters incoming requests by User-Agent. Any value that starts with Anthropic (including the stock Anthropic/JS <ver> that @anthropic-ai/sdk sets in buildHeaders) is rejected with 429 rate_limit_error / "engine is currently overloaded", regardless of the actual key's quota.
packages/pi-ai/src/providers/anthropic.ts::createClient instantiates new AnthropicClass(...) without overriding User-Agent, so every kimi-coding request goes out as User-Agent: Anthropic/JS 0.90.0 and is blocked. opencode and kimi-cli don't use the Anthropic JS SDK, so they hit the endpoint with opencode/* or kimi-cli/* respectively and work fine.
Repro
# With a valid Kimi coding-plan key
K=<your-kimi-key>
for ua in 'Anthropic/JS 0.90.0' 'Anthropic' 'gsd/2.77.0' 'curl/8.7.1'; do
printf 'UA=%-25s -> ' "\$ua"
curl -s -o /dev/null -w 'HTTP %{http_code}\n' https://api.kimi.com/coding/v1/messages \
-H "x-api-key: \$K" \
-H 'anthropic-version: 2023-06-01' \
-H 'content-type: application/json' \
-H "user-agent: \$ua" \
-d '{"model":"kimi-k2.6","max_tokens":16,"messages":[{"role":"user","content":"hi"}]}'
done
Result:
UA=Anthropic/JS 0.90.0 -> HTTP 429
UA=Anthropic -> HTTP 429
UA=gsd/2.77.0 -> HTTP 200
UA=curl/8.7.1 -> HTTP 200
gsd-pi log excerpt (ANTHROPIC_LOG=debug gsd --print --model kimi-coding/kimi-k2.6 ...):
[log_3edb65] post https://api.kimi.com/coding/v1/messages failed with status 429 in 21482ms - retrying, 2 attempts remaining
...
errorMessage: '429 {"error":{"type":"rate_limit_error","message":"The engine is currently overloaded, please try again later"},"type":"error"}'
Workaround (config-only, no code change)
Add a headers.user-agent override to the provider in ~/.gsd/agent/models.json:
{
"providers": {
"kimi-coding": {
"baseUrl": "https://api.kimi.com/coding",
"apiKey": "!security find-generic-password -ws gsd-kimi-api",
"headers": { "user-agent": "gsd/2.77.0" }
}
}
}
This merges into defaultHeaders (see client.mjs::buildHeaders, where _options.defaultHeaders comes after the SDK's built-in User-Agent) and clears the 429.
Suggested fix
In packages/pi-ai/src/providers/anthropic.ts::createClient, when model.provider === "kimi-coding" (and arguably for every non-Anthropic Anthropic-compatible provider), set a default "User-Agent": "gsd/<version>" in the defaultHeaders merge. The existing model.headers merge still allows users to override further if needed.
Kimi K2.6 also shipped yesterday (2026-04-20); once the UA is non-Anthropic, thinking (off/low/medium/high) and tool use all work end-to-end against kimi-k2.6 and kimi-for-coding on /coding/v1/messages.
Environment
gsd-pi@2.77.0
@anthropic-ai/sdk@0.90.0
- Node v25.8.2, macOS 25.5.0 (arm64)
- Endpoint:
https://api.kimi.com/coding/v1/messages
Summary
The built-in
kimi-codingprovider cannot reachapi.kimi.com/coding/v1/messagesfrom gsd-pi. Every request returnsHTTP 429with body{"error":{"type":"rate_limit_error","message":"The engine is currently overloaded, please try again later"},"type":"error"}The Anthropic SDK retries 3× (~21s each), then gsd's auto-retry starts another round — so the turn eventually aborts with
stopReason: error. Thinking mode, tools, andstream: trueare all irrelevant; the 429 fires before any model work happens.Root cause
Kimi's
/codinggateway filters incoming requests byUser-Agent. Any value that starts withAnthropic(including the stockAnthropic/JS <ver>that@anthropic-ai/sdksets inbuildHeaders) is rejected with429 rate_limit_error / "engine is currently overloaded", regardless of the actual key's quota.packages/pi-ai/src/providers/anthropic.ts::createClientinstantiatesnew AnthropicClass(...)without overridingUser-Agent, so everykimi-codingrequest goes out asUser-Agent: Anthropic/JS 0.90.0and is blocked. opencode and kimi-cli don't use the Anthropic JS SDK, so they hit the endpoint withopencode/*orkimi-cli/*respectively and work fine.Repro
Result:
gsd-pi log excerpt (
ANTHROPIC_LOG=debug gsd --print --model kimi-coding/kimi-k2.6 ...):Workaround (config-only, no code change)
Add a
headers.user-agentoverride to the provider in~/.gsd/agent/models.json:{ "providers": { "kimi-coding": { "baseUrl": "https://api.kimi.com/coding", "apiKey": "!security find-generic-password -ws gsd-kimi-api", "headers": { "user-agent": "gsd/2.77.0" } } } }This merges into
defaultHeaders(seeclient.mjs::buildHeaders, where_options.defaultHeaderscomes after the SDK's built-inUser-Agent) and clears the 429.Suggested fix
In
packages/pi-ai/src/providers/anthropic.ts::createClient, whenmodel.provider === "kimi-coding"(and arguably for every non-Anthropic Anthropic-compatible provider), set a default"User-Agent": "gsd/<version>"in thedefaultHeadersmerge. The existingmodel.headersmerge still allows users to override further if needed.Kimi K2.6 also shipped yesterday (2026-04-20); once the UA is non-Anthropic, thinking (off/low/medium/high) and tool use all work end-to-end against
kimi-k2.6andkimi-for-codingon/coding/v1/messages.Environment
gsd-pi@2.77.0@anthropic-ai/sdk@0.90.0https://api.kimi.com/coding/v1/messages