Skip to content

tool_use/tool_result pairing breaks causing 400 error with Claude Code / OpenClaw #143

@yinshanlake

Description

@yinshanlake

Bug Description

When using Agent Maestro as a proxy for Claude Code (or OpenClaw), the Anthropic API returns a 400 error about mismatched tool_use_id in tool_result blocks after extended tool-using conversations. This makes Agent Maestro unusable for any non-trivial agent workflow.

Error message:

messages.0.content.0: unexpected `tool_use_id` found in `tool_result` blocks: <id>. 
Each tool_result block must have a corresponding tool_use block in the previous message.

Root Cause Analysis

The Problem

The Anthropic Messages API enforces a strict invariant: every tool_result content block in a user message must reference a tool_use_id from a tool_use block in the immediately preceding assistant message. This is a hard constraint — violating it produces a 400 error.

When Agent Maestro converts Anthropic messages → VS Code Language Model API format → sends to the model, the VS Code LM API (Copilot backend) internally processes and may truncate/compact the conversation history. However, Agent Maestro does NOT actually re-validate the original Anthropic message array before forwarding it. The error actually comes from the VS Code LM API's internal handling — it passes the messages to its own backend which apparently enforces similar constraints.

Why the Current Workaround Is Insufficient

In anthropicRoutes.ts (lines 481-486), there's an existing workaround:

const isContextWindowExceeded =
  errorMessage.includes("unexpected `tool_use_id` found in `tool_result` blocks") &&
  maxInputTokens > 0 &&
  inputTokens > maxInputTokens;

This workaround only triggers when inputTokens > maxInputTokens, meaning it only handles the case where the context window is exceeded. However, the pairing error frequently occurs within the context window limit — the VS Code LM API backend can reject tool_use/tool_result pairings for various reasons unrelated to context length.

When the workaround DOES trigger, it returns a fake model_context_window_exceeded stop reason with inflated token counts to force the client (Claude Code/OpenClaw) to auto-compact. This is a reasonable strategy, but since it rarely triggers, most errors just bubble up as 500 internal server errors.

Message Flow

OpenClaw/Claude Code → Agent Maestro (localhost:23333/api/anthropic/v1/messages)
    → convertAnthropicMessagesToVSCode() [src/server/utils/anthropic.ts]
    → client.sendRequest() [VS Code Language Model API]
    → VS Code LM API backend (Copilot)
    → Error: "unexpected tool_use_id found in tool_result blocks"
    → Caught in catch block of anthropicRoutes.ts
    → Workaround condition NOT met (inputTokens <= maxInputTokens)
    → Returns 500 error to OpenClaw/Claude Code
    → OpenClaw completely broken

Proposed Fix

Add a message sanitization step before sending to the VS Code LM API that validates and repairs tool_use/tool_result pairing:

  1. Before calling client.sendRequest(), scan the Anthropic messages array
  2. For each user message containing tool_result blocks, verify that the immediately preceding assistant message contains matching tool_use blocks with the same IDs
  3. For orphaned tool_result blocks (no matching tool_use in the previous assistant message):
    • Either inject a synthetic tool_use block into the preceding assistant message
    • Or remove the orphaned tool_result block and convert its content to a plain text block
  4. For orphaned tool_use blocks in assistant messages (no matching tool_result in the next user message):
    • Either inject a synthetic tool_result block
    • Or remove the orphaned tool_use block

Additionally, the catch block workaround should be broadened: when the "unexpected tool_use_id" error occurs, it should ALWAYS return the model_context_window_exceeded fake response (not just when inputTokens > maxInputTokens), so the client always gets a chance to compact and retry.

Reproduction Steps

  1. Install Agent Maestro v2.8.1 in VS Code
  2. Configure OpenClaw or Claude Code to use http://localhost:23333/api/anthropic as the API base URL
  3. Start a conversation that uses tools (e.g., file reading, bash commands)
  4. After several rounds of tool use (typically 5-10+ tool calls), the error appears
  5. Once the error occurs, the session becomes completely unusable — every subsequent request also fails

Environment

  • Agent Maestro: v2.8.1
  • VS Code: 1.100+
  • Client: OpenClaw 2026.2.24 / Claude Code
  • Model: claude-opus-4-20250514 (via VS Code Copilot)

Impact

This bug makes Agent Maestro completely unusable for any agent workflow that involves tool use (which is the primary use case for Claude Code / OpenClaw). After a few tool calls, the session breaks and cannot recover without restarting the entire conversation.

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