Skip to content

[cc/claude-*] Tool name rewritten to exec_ide + thinking blocks mutated on replay #2693

Description

@beprintvietnam

Two bugs in the tool-call / thinking translation layer for Claude models (cc/claude-*) served via /v1/messages. Both break standard Anthropic-API clients (found with OpenClaw); neither happens on openai/gpt-5.5.

Bug 1 — tool name exec is rewritten to exec_ide in tool_use responses

A client declares a tool named exec. 9Router returns the tool_use block with name: "exec_ide" (the request never mentions exec_ide). The input is preserved. Clients that only registered exec reject the unknown exec_ide and retry-loop / fail (breaks shell/python execution, file & Excel processing, etc.).

Minimal reproduction (direct API, no middleware):

POST https://9router.printwayglobal.com/v1/messages
x-api-key: <key>
anthropic-version: 2023-06-01

{
  "model": "cc/claude-opus-4-8",
  "max_tokens": 256,
  "tools": [{
    "name": "exec",
    "description": "Run a shell command",
    "input_schema": {"type":"object","properties":{"command":{"type":"string"}},"required":["command"]}
  }],
  "messages": [{"role":"user","content":"Use the exec tool to run: echo HELLO"}]
}
  • Expected: {"type":"tool_use","name":"exec","input":{"command":"echo HELLO"}}
  • Actual: {"type":"tool_use","name":"exec_ide","input":{"command":"echo HELLO"},"caller":{"type":"direct"}}

Two anomalies: (1) name rewritten execexec_ide; (2) non-standard "caller":{"type":"direct"} field injected (not part of the Anthropic Messages schema) — indicates a tool-call transform layer remapping names.

Bug 2 — thinking blocks are modified on multi-turn replay → HTTP 400

With thinking enabled, each assistant turn emits a thinking block. On the next multi-turn request, the returned/forwarded history blocks are altered, and upstream rejects with:

400 invalid_request_error
messages.N.content.M: `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.

Single turns succeed; multi-turn poisons the transcript so every subsequent turn fails. Workaround today is to disable thinking entirely on cc/claude-*.

Requested fixes

  1. Echo the exact tool name the client declared in tools[]; do not remap to exec_ide. Drop (or make opt-in) the non-standard caller field.
  2. Do not mutate thinking / redacted_thinking blocks when forwarding assistant history — preserve them byte-for-byte from the original response.

Both likely live in the same translation layer as the recently fixed output_config.effort adaptive-thinking issue (open-sse/translator/concerns/).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions