fix: normalize toolCall arguments to prevent Anthropic API rejection#2213
fix: normalize toolCall arguments to prevent Anthropic API rejection#2213manzienkog wants to merge 1 commit intoopenclaw:mainfrom
Conversation
Some models (e.g., via google-antigravity) omit the 'arguments' field
for tools with no required parameters. When this happens, pi-ai passes
undefined to Anthropic's 'input' field, causing API rejection with:
'messages.N.content.M.tool_use.input: Field required'
This fix adds normalizeToolCallArguments() which ensures arguments is
always an object (defaulting to {}) before messages reach the API.
Fixes tool calls for:
- memory_status
- load_memory (without trigger)
- Any tool with optional-only or no parameters
|
We hit this exact bug running clawdbot v2026.1.24-3 with Google Antigravity on a Hetzner VPS and spent time tracing the root cause on our end. Confirming the fix is correct. Root cause trace
AssessmentPR #2213's Suggestion: Consider also adding Grade: A. Ship it. Investigated hands-on from a VM running clawdbot with Antigravity — session JSONL confirmed missing |
|
|
||
| // Normalize toolCall arguments to ensure they're always an object. | ||
| // Some models omit `arguments` for tools with no required params, | ||
| // but Anthropic API requires `input` to be present. | ||
| const normalizedArgs = normalizeToolCallArguments(repairedTools); |
There was a problem hiding this comment.
[P3] Comment mentions Anthropic, but this normalization runs unconditionally
sanitizeSessionHistory always applies normalizeToolCallArguments regardless of provider/model (google, openai-responses, etc.). The comment at google.ts:340-343 says “Anthropic API requires input”, which is true for the reported failure, but it’s misleading in this location since the logic isn’t Anthropic-specific; consider rewording to reflect that we’re normalizing transcript/tool-call shape for downstream consumers/providers in general.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/google.ts
Line: 339:343
Comment:
[P3] Comment mentions Anthropic, but this normalization runs unconditionally
`sanitizeSessionHistory` always applies `normalizeToolCallArguments` regardless of provider/model (`google`, `openai-responses`, etc.). The comment at `google.ts:340-343` says “Anthropic API requires `input`”, which is true for the reported failure, but it’s misleading in this location since the logic isn’t Anthropic-specific; consider rewording to reflect that we’re normalizing transcript/tool-call shape for downstream consumers/providers in general.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.|
Thanks for the careful fix and clear context. We’re closing this PR because malformed tool-call handling has since been addressed in later updates on Really appreciate the contribution. |
Problem
Some models (e.g., via google-antigravity) omit the
argumentsfield for tools with no required parameters. When this happens, pi-ai passesundefinedto Anthropic'sinputfield, causing API rejection:Solution
Added
normalizeToolCallArguments()which ensuresargumentsis always an object (defaulting to{}) before messages reach the API.Affected tools
memory_statusload_memory(without trigger)Testing
Added tests in
tool-call-id.test.tscovering:{}{}Greptile Overview
Greptile Summary
This PR adds
normalizeToolCallArguments()to ensure assistant tool-call blocks always have an object-valuedargumentsfield (defaulting missing/nullto{}), preventing downstream providers (notably Anthropic) from rejecting messages where tool input is required but omitted by upstream models. The normalization is exported viapi-embedded-helpersand applied in the Google transcript sanitization pipeline (sanitizeSessionHistory), and a dedicated vitest suite is added to validate behavior across tool block types and message roles.Confidence Score: 4/5
(2/5) Greptile learns from your feedback when you react with thumbs up/down!