Skip to content

bug(pi-ai): Kimi /coding provider 429s with 'engine overloaded' — Anthropic SDK User-Agent is filtered by Kimi API #4640

Description

@AriaShishegaran

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: aiAI/LLM layer (packages/pi-ai)blockedWaiting on something externalbugSomething isn't workingcloses-on-mergeWill close automatically when linked PR mergesneeds-maintainer-reviewpriority: highUrgent — needs attention now

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions