[fix] Strip output-only citations from Claude server-tool blocks#8686
Open
vishalr15 wants to merge 1 commit into
Open
[fix] Strip output-only citations from Claude server-tool blocks#8686vishalr15 wants to merge 1 commit into
vishalr15 wants to merge 1 commit into
Conversation
Anthropic emits a `citations` field on `code_execution_tool_result` blocks
but rejects it on input. agno preserves server-tool blocks in
`provider_data["server_tool_blocks"]` for history reconstruction and replays
them verbatim on the next turn, causing a 400 on any multi-turn conversation
that used code execution:
messages.N.content.M.code_execution_tool_result.citations:
Extra inputs are not permitted
Add `dump_server_tool_block()` which serializes a block and drops the
output-only fields Anthropic's input schema forbids, and use it at both
capture sites in `Claude`. Also sanitize at the replay point in
`format_messages` so history persisted before this fix replays cleanly.
The citation data itself is unaffected — it is captured separately into
`ModelResponse.citations`; only the history-reconstruction copy is pruned.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
PR TriageMissing issue link: Please link the issue this PR addresses using |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fixes #8687
Summary
Multi-turn conversations that use Claude's code execution tool fail on the second turn with:
Root cause. Anthropic emits a
citationsfield oncode_execution_tool_resultblocks but rejects it on input (output and input schemas differ). agno preserves server-tool result blocks inprovider_data["server_tool_blocks"]viablock.model_dump()(which keepscitations), thenformat_messagesreplays those blocks verbatim on the next turn — so the illegal field is echoed straight back and the request is rejected before it reaches the model.Fix.
dump_server_tool_block()inutils/models/claude.py:model_dump()the block, then drop the output-only fields Anthropic's input schema forbids (currentlycitationsoncode_execution_tool_result/bash_code_execution_tool_result). Use it at both capture sites inClaude._parse_provider_responseand_parse_provider_response_delta. This is the root-cause fix — the field is never persisted.format_messages. The loop overserver_tool_blocksalready exists, so this adds no extra iteration, and it ensures history persisted before this fix still replays cleanly after upgrading.The citation data itself is unaffected: it is captured separately into
ModelResponse.citations. Only the redundant history-reconstruction copy — which should never be sent back as input — is pruned.Scope is kept to the block types Anthropic is confirmed to reject (
code_execution_tool_resultand its bash variant); the field map is trivially extensible if other output-only fields surface.Type of change
Checklist
ruff format --checkandruff checkpass on changed files).venv, editable install)New unit tests in
tests/unit/models/anthropic/test_server_tool_block_citations.pycover the capture helper (stripscitationsfrom code-execution results, preserves unrelated blocks, idempotent) and the replay path (format_messagesomitscitationsfor already-persisted blocks). The new tests plus the existingtest_citation_suppression.pyall pass (17 passed).Duplicate and AI-Generated PR Check
Additional Notes
The replay-side strip is a safety net for existing stored sessions; the capture-side fix means all newly stored history is clean and never needs the replay strip.