Bug
Message.ToParam() produces invalid request bodies for multi-turn conversations that include server-side tool results (web_search_tool_result and web_fetch_tool_result). The first turn succeeds (the API executes the tool and returns results), but the second turn fails with a 400 when the conversation history containing those results is sent back.
SDK version
v1.45.0 (also reproduced on v1.41.0)
Errors
web_search:
messages.1.content.1.web_search_tool_result.content.list[RequestWebSearchResultBlock]: Input should be a valid array
web_fetch:
messages.1.content.2.web_fetch_tool_result.content: Field required
Reproduction
Minimal Go program that triggers it (using the agent loop pattern from the SDK README):
// Any multi-turn agent loop that:
// 1. Sends a message with web_search or web_fetch tools enabled
// 2. Gets a response with server-side tool results
// 3. Calls msg.ToParam() to append the response to conversation history
// 4. Sends the next request with that history
// will fail on step 4.
I'm hitting this via cronicle's agent loop, which does:
conversation = append(conversation, msg.ToParam()) // line 323 of agent.go
// ... dispatch tool_use blocks ...
conversation = append(conversation, anthropic.NewUserMessage(results...))
// next iteration: Create request with conversation → 400
Root cause (from reading the SDK source)
WebSearchToolResultBlockContentUnion.ToParam() (messageutil.go:254):
The response union has OfWebSearchResultBlockArray which gets mapped to OfWebSearchToolResultBlockItem on the param side. The param struct serializes via param.MarshalUnion, but the API expects the content field to contain {"list": [...]} wrapping. The current serialization appears to produce a shape the API rejects.
WebFetchToolResultBlock.ToParam():
The content field is not being set at all in the param, so the API returns content: Field required.
Workaround
None currently — any agent loop that uses web_search or web_fetch and needs more than one turn will fail. The tools work fine on a single-turn request.
Environment
- Go 1.24
- macOS (also reproduced on Debian bookworm in k8s)
- Model:
claude-sonnet-4-6
- Both
web_search and web_fetch affected independently
Bug
Message.ToParam()produces invalid request bodies for multi-turn conversations that include server-side tool results (web_search_tool_resultandweb_fetch_tool_result). The first turn succeeds (the API executes the tool and returns results), but the second turn fails with a 400 when the conversation history containing those results is sent back.SDK version
v1.45.0(also reproduced onv1.41.0)Errors
web_search:
web_fetch:
Reproduction
Minimal Go program that triggers it (using the agent loop pattern from the SDK README):
I'm hitting this via cronicle's agent loop, which does:
Root cause (from reading the SDK source)
WebSearchToolResultBlockContentUnion.ToParam()(messageutil.go:254):The response union has
OfWebSearchResultBlockArraywhich gets mapped toOfWebSearchToolResultBlockItemon the param side. The param struct serializes viaparam.MarshalUnion, but the API expects thecontentfield to contain{"list": [...]}wrapping. The current serialization appears to produce a shape the API rejects.WebFetchToolResultBlock.ToParam():The
contentfield is not being set at all in the param, so the API returnscontent: Field required.Workaround
None currently — any agent loop that uses
web_searchorweb_fetchand needs more than one turn will fail. The tools work fine on a single-turn request.Environment
claude-sonnet-4-6web_searchandweb_fetchaffected independently