Bugfix: S185: Why did the Vitto agent loop fail with Claude API 400 ...

Documentation for Sessions

🐛 Bugfix: S185: Why did the Vitto agent loop fail with Claude API 400 ...

Date: 2026-03-07
Time: 01:37:10 UTC
Session: gspace1-185.5
Agent: backend
Confidence: 96%
Status: ✅ Documented


📋 Decision Context

Question:

S185: Why did the Vitto agent loop fail with Claude API 400 'tool_use ids without tool_result blocks'?

Task: S185: Fix module generation failing with Claude API 400 error


🎯 Decision Made

Chosen:

Two fixes: (1) agent-loop.service.ts: Added tool_result backfill loop after tool execution — scans for any tool_use IDs without matching tool_result and adds placeholder results. (2) Deferred stuck-detection user message injection to AFTER tool_result backfill — Claude requires tool_result immediately after tool_use, user messages between them cause 400.

Options Considered:

  1. Fix only the stuck-detection path (misses task_complete path)
  2. Add tool_result backfill for all early-exit paths (chosen - comprehensive)
  3. Restructure agent loop to always execute all tools before breaking (too invasive)

💭 Reasoning

Root cause chain: When stuck detection fired 'summarize_context', the code at line 323 pushed a user message BETWEEN the assistant(toolCalls) message and the tool execution block. Then shouldBreakInner=true skipped tool execution entirely. Result: assistant message had tool_use blocks, next message was a user message (not tool_result), violating Claude API contract. Secondary: when task_complete was found mid-batch, remaining tool_use blocks in the same response had no tool_result messages added. The backfill loop at line 494 now ensures every tool_use has a matching tool_result regardless of early exit path.


📁 Files Involved


🔗 Related


Auto-generated by MCP Smart Consolidation