Skip to content

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

Open

Description

@JunhyeongSong

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.

Activity

  1. added theissue type on Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions