Description
A conversation that uses Claude's code execution tool fails on the second (and later) turn with an Anthropic 400:
400 - messages.N.content.M.code_execution_tool_result.citations:
Extra inputs are not permitted
The first turn succeeds; the error only appears once the prior assistant response is replayed as input.
Root cause
Anthropic emits a citations field on code_execution_tool_result blocks but rejects it on input (the output and input schemas differ). agno preserves server-tool result blocks for history reconstruction:
# agno/models/anthropic/claude.py
server_tool_blocks.append(block.model_dump()) # model_dump() keeps `citations`
...
model_response.provider_data.setdefault("server_tool_blocks", []).extend(server_tool_blocks)
On the next turn format_messages replays those stored blocks verbatim:
# agno/utils/models/claude.py
for block_dict in message.provider_data["server_tool_blocks"]:
...
content.append(block_dict) # `citations` echoed back as input -> 400
Because the Messages API is stateless, the whole prior response is re-sent every turn, so the illegal field is rejected before the request reaches the model.
Steps to reproduce
- Create a
Claude agent with skills / code execution enabled.
- Send a message that triggers code execution (turn 1) — succeeds.
- Send any follow-up in the same conversation (turn 2) — 400 with the error above.
Expected
Server-tool result blocks should be replayable across turns; output-only fields Anthropic rejects on input should not be echoed back.
Environment
- agno: 2.6.x (reproduced against
main)
- Provider: Anthropic (Claude), code execution / skills
Proposed fix
Strip the output-only citations field from code_execution_tool_result / bash_code_execution_tool_result blocks at capture time (so it's never persisted), with a matching strip at the replay point for already-persisted history. The citation data is preserved separately in ModelResponse.citations. PR to follow.
Description
A conversation that uses Claude's code execution tool fails on the second (and later) turn with an Anthropic 400:
The first turn succeeds; the error only appears once the prior assistant response is replayed as input.
Root cause
Anthropic emits a
citationsfield oncode_execution_tool_resultblocks but rejects it on input (the output and input schemas differ). agno preserves server-tool result blocks for history reconstruction:On the next turn
format_messagesreplays those stored blocks verbatim:Because the Messages API is stateless, the whole prior response is re-sent every turn, so the illegal field is rejected before the request reaches the model.
Steps to reproduce
Claudeagent with skills / code execution enabled.Expected
Server-tool result blocks should be replayable across turns; output-only fields Anthropic rejects on input should not be echoed back.
Environment
main)Proposed fix
Strip the output-only
citationsfield fromcode_execution_tool_result/bash_code_execution_tool_resultblocks at capture time (so it's never persisted), with a matching strip at the replay point for already-persisted history. The citation data is preserved separately inModelResponse.citations. PR to follow.