provider api: anthropic-beta header dropped on /v1/messages, breaking Claude 5.5 multi-turn

未關閉
#1,104 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

還沒有人認領這個 Issue。

評估

難度
3/5
預估耗時
1-2 天
新手友好度
72/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
活躍

研究方向

Start with the request-forwarding and header-allowlist code for the /provider/v1/messages Anthropic-format route; the issue does not name a file. Trace whether the client's anthropic-beta header is dropped or overwritten, and check existing proxy tests. Done means the two-step curl reproduction succeeds on turn 2 when the beta header is present, while still returning the existing 400 when it is absent.

由索引模型根據 Issue 內容生成。

描述

Summary

The Provider API proxy at https://api.commandcode.ai/provider/v1/messages drops the client's anthropic-beta request header before forwarding to the Anthropic upstream. The thinking-binding-controls-2026-08-01 beta therefore never reaches Anthropic, and any multi-turn Claude 5.5 conversation with thinking enabled whose system prompt changes between turns fails with invalid_request_error. Agent frameworks change the system prompt mid-session all the time (skill/instruction loading, compaction), so Claude 5.5 via the Provider API is unusable for multi-turn agents — in our case OpenCode's design agent dies on its second model call.

Expected Behavior

The proxy forwards the client's anthropic-beta header to the Anthropic upstream unchanged (or merged with any beta values the proxy itself adds), so thinking.block_binding.prefix_mismatch_behavior: "drop_block" is honored and the stale thinking block is dropped instead of rejected.

Actual Behavior

HTTP 400 on the second turn of an otherwise valid conversation. Exact response, captured from an on-demand reproduction on 2026-11-03:

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "messages.1.content.0: Invalid `signature` in `thinking` block. The block is bound to a different conversation. Remove the block, or set `thinking.block_binding.prefix_mismatch_behavior` to \"drop_block\". That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header. The `system` prompt differs from the one this block was created with."
  },
  "request_id": "req_011Cgg5ENiY5CvP1yD2Er5L8"
}

The error message itself states the beta value is missing from the anthropic-beta header — but the client did send exactly that header on this request (per-model header in the config below). It is stripped somewhere between api.commandcode.ai and the upstream. Client-side, OpenCode logs Failed to drain Session and the whole agent run aborts.

Steps to reproduce the issue

Client config (OpenCode v2.2.5, opencode.jsonc — the per-model anthropic-beta header is the key part):

"commandcode": {
  "models": {
    "claude-haiku-5-5": {
      "compatibility": { "supportsThinkingBlockBinding": true },
      "headers": { "anthropic-beta": "thinking-binding-controls-2026-08-01" },
      "body": { "thinking": { "block_binding": { "prefix_mismatch_behavior": "drop_block" } } }
    }
  }
}

In-client (reproduces on demand):

  1. Configure OpenCode to use the Provider API with claude-haiku-5-5, thinking enabled, and the header/body settings above.
  2. Invoke an agent whose system prompt changes mid-session (e.g. the design agent, which loads a large skill file after its first turn).
  3. The first model call succeeds; the second call — same conversation, new system prompt, prior assistant turn containing a signed thinking block — returns 400 and the session aborts.

Minimal curl reproduction:

CMD_API_KEY=...  # your API key

# ── Turn 1: create a signed thinking block under system prompt A ──
curl -sS https://api.commandcode.ai/provider/v1/messages \
  -H "Authorization: Bearer $CMD_API_KEY" \
  -H "content-type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
        "model": "claude-haiku-5-5",
        "max_tokens": 1024,
        "system": "You are agent A.",
        "thinking": { "type": "enabled", "budget_tokens": 512 },
        "messages": [{ "role": "user", "content": "Reply with the single word: ok" }]
      }' > turn1.json
# turn1.json content[0] is a `thinking` block whose signature is bound to system prompt A

# ── Turn 2: same conversation, DIFFERENT system prompt, beta header + drop_block ──
jq -n --slurpfile t1 turn1.json '{
    model: "claude-haiku-5-5",
    max_tokens: 1024,
    system: "You are agent B.",
    thinking: { type: "enabled", budget_tokens: 512,
                block_binding: { prefix_mismatch_behavior: "drop_block" } },
    messages: [
      { role: "user",      content: "Reply with the single word: ok" },
      { role: "assistant", content: $t1[0].content },
      { role: "user",      content: "Reply with the single word: ok" }
    ]
  }' > turn2.json

curl -sS https://api.commandcode.ai/provider/v1/messages \
  -H "Authorization: Bearer $CMD_API_KEY" \
  -H "content-type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
  -d @turn2.json
  • Via the Provider API: turn 2 returns 400 with the error above.
  • The same two calls against https://api.anthropic.com/v1/messages with an Anthropic key: turn 2 succeeds (the mismatched thinking block is dropped), confirming the request is valid and the header is what goes missing.
Command Code Version

Provider API user (api.commandcode.ai/provider/v1), not the CLI. Client: OpenCode v2.2.5

Operating System

Windows

Terminal/IDE

OpenCode coding agent calling the API directly

Shell

No response

Session file (optional)

No response

Fix prompt (optional)

Fix header forwarding on the Anthropic passthrough route (/provider/v1/messages). The proxy strips or overwrites the client's anthropic-beta header today; correct behavior is pass-through, merging the client's value (comma-separated) with any beta values the proxy itself adds, so client-opted betas reach Anthropic. Verify with the two-step curl in this issue: turn 2 must return 200 with anthropic-beta: thinking-binding-controls-2026-08-01 and thinking.block_binding.prefix_mismatch_behavior: "drop_block", and must still return the existing 400 when the header is genuinely absent. Likely location: the request-forwarding / header-allowlist code for the Anthropic-format route.

Additional context
  • Reproducible on demand; 10 failed requests observed across 2026-11-01 → 2026-11-03. Request IDs: req_011Cgg5ENiY5CvP1yD2Er5L8 (on-demand repro, 2026-11-03), req_011CgdGoFV9ds627HCFGHZEV, req_011CgdGMJPYjckxizLsaprkP, req_011CgdGLMERpWToXZ8T4BAoE, req_011CgdGLGaNj4ZuDqYo1Y63u, req_011CgdGGhA7md3tQXrQ81qrz, req_011CgdGDrHisNzb6QPAMjsFJ, req_011CgdG1E4nWTg57sKzdsYyS, req_011Cgc5NV3VvsQRkWCwp3AxT, req_011Cgc5HieQp56hca7QdWG3k (2026-11-01/02).
  • Client: OpenCode v2.2.5 on Windows 11 Pro (10.0.26300), model claude-haiku-5-5, thinking enabled, Bearer auth.
  • Client-side impact: any agent that changes its system prompt mid-session (skill loading, compaction, agent handoffs) hits this on its next turn.
  • Workaround: none that we could find via the API. We currently reroute Claude models through another provider for affected agents.
  • anthropic-beta also carries other opt-ins (e.g. context-1m, interleaved-thinking), so other beta-gated features are likely affected too.
主要語言
沒有語言資料
星號
4.2k
分支
377
平均合併
1 天 17 分鐘
30 天內合併 PR
7

環境準備

這個專案沒有提供開發容器、Dockerfile 或貢獻指南,環境需要你自己搭建:先看它的 README,通用步驟見我們的新手貢獻指南。

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

CommandCodeAI/command-code 的其他 Issue

查看 CommandCodeAI/command-code 的全部 Issue

相似的 Issue

更多 Backend & API Design Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。