fix: recover XML tool calls as proper tool execution in agent loop

Move XML tool call extraction from HTTPProvider-only to the central
agent loop so all providers benefit. Plain-text XML tool calls are
now parsed and re-executed as real tool calls, with the XML stripped
from the response content before sending to users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
dj-oyu 2026-02-22 09:11:26 +09:00
parent 110c8b028b
commit d1d09d84c3
2 changed files with 18 additions and 0 deletions

View file

@ -1525,6 +1525,14 @@ func (al *AgentLoop) runLLMIteration(
)
}
// Recover XML tool calls emitted as plain text by some providers.
if len(response.ToolCalls) == 0 {
if xmlCalls := providers.ExtractXMLToolCalls(response.Content); len(xmlCalls) > 0 {
response.ToolCalls = xmlCalls
}
}
response.Content = providers.StripXMLToolCalls(response.Content)
// Check if no tool calls - we're done
if len(response.ToolCalls) == 0 {
// Plan continuation: if unchecked steps remain, nudge the LLM to

View file

@ -171,6 +171,11 @@ func findToolCallBlock(text string) (blockStart, blockEnd int, content string, f
// <parameter name="param">value</parameter>
// </invoke>
// </ns:toolcall>
// ExtractXMLToolCalls is the exported version for use by the agent loop.
func ExtractXMLToolCalls(text string) []ToolCall {
return extractXMLToolCalls(text)
}
func extractXMLToolCalls(text string) []ToolCall {
var result []ToolCall
remaining := text
@ -260,6 +265,11 @@ func extractXMLToolCalls(text string) []ToolCall {
return result
}
// StripXMLToolCalls is the exported version for use by the agent loop.
func StripXMLToolCalls(text string) string {
return stripXMLToolCalls(text)
}
// stripXMLToolCalls removes XML tool call blocks from response text.
// Prevents raw XML tool calls from leaking to users.
func stripXMLToolCalls(text string) string {