Repository navigation
Description
Description
Summary
packages/llm/src/protocols/anthropic-messages.ts refuses to lower any assistant history containing a provider-executed (providerExecuted: true) tool-result whose tool name is not one of Anthropic's three native server tools (web_search, code_execution, web_fetch). Instead of degrading the unrecognized result, it fails the whole request with:
"Anthropic Messages does not know how to round-trip server tool result for "
This happens before any network call, during message lowering. The practical effect: once a conversation's history contains a provider-executed tool result that isn't one of those three (for example a provider-executed read), that conversation can no longer be continued on an Anthropic-API provider (e.g. Anthropic direct, Bedrock, Vertex). Switching provider mid-conversation — or otherwise replaying that history to an Anthropic route — is permanently blocked for that session.
Root cause
packages/llm/src/protocols/anthropic-messages.ts
The name mapper only knows three server tools (lines ~293-298):
const serverToolResultType = (name: string): AnthropicServerToolResultType | undefined => {
if (name === "web_search") return "web_search_tool_result"
if (name === "code_execution") return "code_execution_tool_result"
if (name === "web_fetch") return "web_fetch_tool_result"
return undefined
}lowerServerToolResult throws on anything else (lines ~300-305):
const lowerServerToolResult = Effect.fn("AnthropicMessages.lowerServerToolResult")(function* (part: ToolResultPart) {
const wireType = serverToolResultType(part.name)
if (!wireType)
return yield* invalid(`Anthropic Messages does not know how to round-trip server tool result for ${part.name}`)
return { type: wireType, tool_use_id: part.id, content: part.result.value } satisfies AnthropicServerToolResultBlock
})And it is reached for every provider-executed tool-result during lowering (lines ~461-463):
if (part.type === "tool-result" && part.providerExecuted) {
content.push(yield* lowerServerToolResult(part))
continue
}So any providerExecuted: true tool-result with a name outside those three hard-fails the request.
Precedent
This is the Anthropic Messages analog of #29159 ("fix(llm): replay OpenAI Responses hosted tool history as native input items"), which was the same defect on the OpenAI Responses adapter — assistant history containing provider-executed hosted tool results was rejected during lowering with "only support text, reasoning, and tool-call content". That was fixed by teaching lowerMessages to lower the provider-executed pairs instead of rejecting them. The Anthropic Messages transform has the equivalent gap and never received the equivalent treatment.
Related: #45261 also concerns provider-executed tool calls breaking the rest of an Anthropic session (via repairToolCall), i.e. a nearby class of "provider-executed content is mishandled on the Anthropic path".
Suggested direction (not prescriptive)
Mirror #29159: in the Anthropic Messages transform, handle an unrecognized provider-executed tool-result by degrading it rather than throwing — e.g. lowering it to a normal content block (text, or a best-effort representation of the structured result) so the history remains replayable.
One caveat worth the maintainers' judgement: a native Anthropic tool_result block normally pairs with a client tool_use, which a provider-executed call does not have, so the exact safe representation (plain text vs. a synthesized block) needs deciding. The key ask is simply that an unrecognized provider-executed result should not hard-fail the entire request — a conversation should remain portable to an Anthropic provider.
Plugins
No response
OpenCode version
v2.0.18.
Steps to reproduce
- Have a conversation whose assistant history contains a tool-result with providerExecuted: true and a tool name that is not web_search / code_execution / web_fetch (any provider/runtime that surfaces a locally/externally executed tool as provider-executed will produce one — e.g. a provider-executed read).
- Continue that conversation on an Anthropic-API route (Anthropic, Bedrock, or Vertex Anthropic).
- The request fails during lowering with Anthropic Messages does not know how to round-trip server tool result for — no network call is made.
Screenshot and/or share link
No response
Operating System
No response
Terminal
No response
Activity
opencode-agent commentedon Oct 7, 2026
Thanks for the detailed report. I can confirm this on v2.0.18, and the current
v2branch behaves the same way.I tested it at the protocol level: I built a request for the Anthropic Messages route whose assistant history holds a
providerExecuted: truetool-call/tool-result pair, then compiled it.web_searchthe request compiles normally.read,file_search,tool_search_tool_regex) it fails during lowering, before any network call, withAnthropic Messages does not know how to round-trip server tool result for <name>.I couldn't test a real provider switch end to end here, so if you can share which provider/model produced the provider-executed result in your session, that would help pin down the realistic trigger.
nic-lan commentedon Oct 8, 2026
The realistic trigger is a mid-session provider switch — starting on
claude-code/claude-opus-5(which routes through the Claude Code CLI) and switching togoogle-vertex/claude-opus-4-6@default(Vertex AI, Anthropic Messages protocol) within the same conversation.The Claude Code CLI executes tools natively (e.g.
read,bash,edit), and those results end up in the conversation history asproviderExecuted: true. When the conversation then continues on the Vertex provider, the Anthropic Messages transform fails on those tool results during lowering.The switch can happen for any reason — manual model change, or automated (e.g. rate-limit-triggered). The effect is that any conversation that has used Claude Code's native tools becomes permanently non-portable to an Anthropic-API provider.
nic-lan commentedon Oct 19, 2026
Still reproducible on
dev—anthropic-messages.ts:608throwsdoes not know how to round-trip server tool resultfor any provider-executed tool outsideweb_search/code_execution/web_fetch.PR with a fix and regression tests: #55560