Conversation
…sults Implements a capability that hooks into before_model_request to repair structurally invalid message history caused by orphaned tool calls and results in multi-turn conversations. This prevents providers (especially Anthropic) from rejecting poisoned conversation history with 400 errors. Repairs: orphaned ToolCallPart (injects synthetic ToolReturnPart), orphaned BuiltinToolCallPart (injects BuiltinToolReturnPart in same response), and orphaned ToolReturnPart/RetryPromptPart (strips them). Also handles trailing responses and empty request edge cases. Refs: pydantic/pydantic-ai#4728 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each repair site now emits a `logging.debug()` message describing the specific action taken (synthetic return injected, orphaned return stripped, trailing response dropped, etc.), complementing the existing summary UserWarning. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…onses - Test the `before_model_request` capability hook directly - Test consecutive ModelResponse messages (no interleaved request) - Mark defensive Phase 6 code as `# pragma: no cover` (unreachable) - Mark unused `extra_parts` helper branch as `# pragma: no cover` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Audit vs prior art: ToolOrphanRepairWorth adding now:
Follow-up opportunities:
|
Notes from comparing with Hermes, Pi-mono, and MastraLooked at how other frameworks handle the same problem. A few things worth noting: Synthetic returns should be marked as errors Duplicate Tool ID sanitization is not this PR's job Errored/aborted turns — framework handles it (mostly) |
Summary
ToolOrphanRepair, a capability that sanitizes message history to fix orphaned tool calls and results before each model requestToolReturnPart/BuiltinToolReturnPartfor calls without matching results, stripsToolReturnPart/RetryPromptPartwhosetool_call_iddoesn't match any call, and handles trailing responses and empty request edge casesfrom pydantic_harness import ToolOrphanRepairRefs: pydantic/pydantic-ai#4728
Test plan
🤖 Generated with Claude Code