fix(ag-ui): use input instead of args for tool-call parts#1149
fix(ag-ui): use input instead of args for tool-call parts#1149corners99 wants to merge 1 commit intoVoltAgent:mainfrom
input instead of args for tool-call parts#1149Conversation
…age conversion When converting CopilotKit assistant messages with tool calls to VoltAgent format, the adapter sets `args` on tool-call parts. The AI SDK's `ToolCallPart` interface expects `input`, so the Anthropic provider sends `undefined` as the tool_use input — rejected by the API with: "messages.N.content.N.tool_use.input: Input should be a valid dictionary" This rename aligns with the AI SDK's ToolCallPart interface from @ai-sdk/provider-utils. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 27387c6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughThe change renames the tool-call payload field from Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 5368cdb7-c75b-40a5-91cd-fa06e7044432
📒 Files selected for processing (2)
.changeset/fix-ag-ui-tool-call-input.mdpackages/ag-ui/src/voltagent-agent.ts
| | { type: "tool-call"; toolCallId: string; toolName: string; input?: unknown } | ||
| | { type: "tool-result"; toolCallId?: string; toolName?: string; output?: unknown }; |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In the current AI SDK / Anthropic tool-use contract, is tool_use.inputrequired to be a JSON object/dictionary, and what is the TypeScript shape ofToolCallPart.input?
💡 Result:
Anthropic tool-use contract (tool_use.input)
Yes—tool_use.input is required, and it is a parsed JSON object (i.e., a dictionary) containing the arguments for the tool, conforming to the tool’s input_schema. (docs.anthropic.com)
AI SDK TypeScript shape (ToolCallPart.input)
In the AI SDK, ToolCallPart.input is typed as unknown (i.e., not restricted to an object at the type level). The shape is: (app.unpkg.com)
export interface ToolCallPart {
type: 'tool-call';
toolCallId: string;
toolName: string;
input: unknown;
providerOptions?: ProviderOptions;
providerExecuted?: boolean;
}Citations:
- 1: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/implement-tool-use
- 2: https://app.unpkg.com/ai%406.0.116/files/dist/internal/index.js.map
Normalize tool-call input to an object, not unknown.
The Anthropic API requires tool_use.input to be a JSON object, but the current code at line 314 can produce a string, array, primitive, or null via safelyParseJson(), and line 279 allows that invalid value through unchecked with the input?: unknown type. This will cause requests to fail at runtime.
Proposed fix
+type VoltToolInput = Record<string, unknown>;
+
type VoltUIPart =
| { type: "text"; text: string }
- | { type: "tool-call"; toolCallId: string; toolName: string; input?: unknown }
+ | { type: "tool-call"; toolCallId: string; toolName: string; input: VoltToolInput }
| { type: "tool-result"; toolCallId?: string; toolName?: string; output?: unknown };
@@
- const input = safelyParseJson(call.function.arguments);
+ const parsedInput = safelyParseJson(call.function.arguments);
+ if (
+ parsedInput === null ||
+ typeof parsedInput !== "object" ||
+ Array.isArray(parsedInput)
+ ) {
+ throw new Error(
+ `Invalid tool-call arguments for "${call.function.name}": expected a JSON object`,
+ );
+ }
toolNameById.set(call.id, call.function.name);
parts.push({
type: "tool-call",
toolCallId: call.id,
toolName: call.function.name,
- input,
+ input: parsedInput,
});Lines 279–280, 314–320.
Summary
convertAGUIMessagesToVoltMessages()— renamesargstoinputon tool-call parts to match the AI SDK'sToolCallPartinterfaceProblem
When CopilotKit replays assistant messages containing tool calls, the ag-ui adapter creates tool-call parts with an
argsfield. The AI SDK'sToolCallPartinterface (from@ai-sdk/provider-utils) expectsinput. When the Anthropic provider builds the API request, it readspart.inputwhich isundefined, causing:This breaks any multi-turn conversation where the assistant previously called a tool (the replayed message has the wrong field name).
Root Cause
In
packages/ag-ui/src/voltagent-agent.ts,convertAGUIMessagesToVoltMessages()line 314-321:The AI SDK
ToolCallParttype:Test plan
ToolCallPartinterface in@ai-sdk/provider-utilsexpectsinputfieldpart.inputto constructtool_useblocksAI_APICallError🤖 Generated with Claude Code
Summary by cubic
Use
inputinstead ofargsfor tool-call parts in@voltagent/ag-uimessage conversion. This matches@ai-sdk/provider-utilsToolCallPartand prevents Anthropic requests from failing when replaying tool calls.Written for commit 27387c6. Summary will update on new commits.
Summary by CodeRabbit
Release Notes