Skip to content

fix(ai): demote unavailable Anthropic tool references in request payloads - #437

Merged
code-yeongyu merged 1 commit into
mainfrom
fix/anthropic-orphan-tool-refs
Jul 28, 2026
Merged

code-yeongyu merged 1 commit into
mainfrom
fix/anthropic-orphan-tool-refs

Conversation

@code-yeongyu

@code-yeongyu code-yeongyu commented Jul 28, 2026 •

Copy link
Copy Markdown
Owner

Problem

Resuming a session whose history contains calls to tools that no longer exist in the request — e.g. an MCP server absent after senpi --session <id> resume, a deactivated extension tool, or an onPayload hook stripping a definition — fails the entire turn:

400 invalid_request_error: Tool reference 'mcp_computer_use_drag' not found in available tools

Anthropic validates that every tool referenced by the message history is available in the same request: defined in tools, or discovered through a tool_reference block. The codebase already repaired pairing (orphan tool_results, dangling calls) but never referential integrity between history and the tool definitions, so one missing MCP server bricked the whole resumed session.

Fix

demoteUnavailableToolReferences() in packages/ai/src/api/anthropic-messages.ts — a final payload pass applied after sanitizeUnsupportedNativeTools() on every request, right before send:

  1. Collects defined tool names (params.tools) and discovered names (any nested tool_reference, including replayed server-side tool-search results).
  2. Demotes tool_use blocks referencing unavailable tools to plain text (name + input preserved).
  3. Demotes their tool_results in lockstep (original result text preserved) so no orphan-pairing 400 replaces the original one.
  4. Strips tool_reference entries whose definition vanished (e.g. removed by a payload hook), never leaving empty tool_result content.

Deferred-tool discovery (splitDeferredTools + tool_reference) is untouched and covered by a guard test.

Evidence

  • New packages/ai/test/anthropic-tool-reference-integrity.test.ts: 5 tests driving the full request path offline through a fake Anthropic client — single/mixed-turn demotion, still-available tools intact, deferred tool_reference discovery intact, dangling-reference stripping. Red before, green after.
  • packages/ai full suite: 1458 passed (the one initial suite failure was an unbuilt packages/tui/dist in the fresh worktree; green after npm run build there — unrelated to this change).
  • Root npm run check: exit 0.
  • senpi-qa (local-ignore/qa-evidence/20260728-anthropic-tool-ref-integrity/):
    • mock-loop.mjs --self-test --api anthropic-messages: 20/20 passed, zero real provider calls, real auth unchanged.
    • cli-smoke.mjs --self-test: 8/8 passed.

Summary by cubic

Prevents Anthropic 400s when history references tools that aren’t in the current request by demoting those tool calls/results to text and removing dangling tool_reference entries so the turn can continue.

  • Bug Fixes
    • Added demoteUnavailableToolReferences() in packages/ai/src/api/anthropic-messages.ts, run after sanitizeUnsupportedNativeTools() on every request.
    • Collects available tool names from tools and nested tool_reference blocks; converts missing tool_use to text (keeps name + input) and demotes paired tool_result (keeps result text) to avoid orphan errors.
    • Strips tool_reference items whose definitions were removed (e.g., by an onPayload hook) without leaving empty tool_result content; deferred discovery remains intact.
    • Added packages/ai/test/anthropic-tool-reference-integrity.test.ts to cover mixed turns, still-available tools, deferred tool_reference flows, and dangling-reference stripping.

Written for commit 5ecb304. Summary will update on new commits.

Review in cubic

@code-yeongyu
code-yeongyu merged commit fe8a135 into main Jul 28, 2026
11 checks passed
@code-yeongyu
code-yeongyu deleted the fix/anthropic-orphan-tool-refs branch July 28, 2026 14:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant