-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Backport: fix(xai): support Responses API streaming events and custom_tool_call type #10610
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
… type (#10523) Add missing schema validation for xAI Responses API server-side tools: - Add custom_tool_call type to outputItemSchema - Make toolCallSchema fields optional for in_progress states - Add input field for custom_tool_call (vs arguments) - Add action field for in_progress tool execution states - Add 12 streaming event types for tool lifecycle: - web_search_call: in_progress, searching, completed - x_search_call: in_progress, searching, completed - code_execution_call: in_progress, executing, completed - code_interpreter_call: in_progress, executing, completed Fixes validation errors ('Invalid JSON response', 'No matching discriminator') when using xai.responses() with xai.tools.webSearch(), xai.tools.xSearch(), or xai.tools.codeExecution(). ## Background The xAI Responses API with server-side tools (`web_search`, `x_search`, `code_execution`) was failing with validation errors when using the Vercel AI SDK: ``` AI_TypeValidationError: Invalid JSON response Error: No matching discriminator for output[].type ``` **Root cause**: The xAI API returns response formats that were not included in the SDK's Zod validation schemas: 1. **`custom_tool_call` type** - Server-side tool calls use this type instead of the standard tool call types 2. **Streaming progress events** - Events like `response.web_search_call.in_progress`, `response.web_search_call.searching`, `response.web_search_call.completed` were not recognized 3. **Optional fields during execution** - During `in_progress` state, fields like `name`, `arguments`, `call_id` are undefined 4. **Different field names** - `custom_tool_call` uses `input` field instead of `arguments` ## Summary Updated `packages/xai/src/responses/xai-responses-api.ts` to support the complete xAI Responses API format: ### 1. Added `custom_tool_call` Type Support **Type definition** (`XaiResponsesToolCall`): ```typescript export type XaiResponsesToolCall = { type: | 'function_call' | 'web_search_call' | 'x_search_call' | 'code_interpreter_call' | 'custom_tool_call'; // ✅ Added id: string; call_id?: string; // ✅ Made optional name?: string; // ✅ Made optional arguments?: string; // ✅ Made optional input?: string; // ✅ Added for custom_tool_call status: string; action?: any; // ✅ Added for in_progress state }; ``` **Schema** (`outputItemSchema`): ```typescript z.object({ type: z.literal('custom_tool_call'), ...toolCallSchema.shape, }), ``` ### 2. Made Tool Call Fields Optional Updated `toolCallSchema` to handle in-progress states where fields are undefined: ```typescript const toolCallSchema = z.object({ name: z.string().optional(), // Was required arguments: z.string().optional(), // Was required input: z.string().optional(), // ✅ New (for custom_tool_call) call_id: z.string().optional(), // Was required id: z.string(), status: z.string(), action: z.any().optional(), // ✅ New (for in_progress state) }); ``` ### 3. Added 12 Streaming Event Types Added to `xaiResponsesChunkSchema` for complete tool execution lifecycle: **Web Search:** - `response.web_search_call.in_progress` - `response.web_search_call.searching` - `response.web_search_call.completed` **X Search:** - `response.x_search_call.in_progress` - `response.x_search_call.searching` - `response.x_search_call.completed` **Code Execution:** - `response.code_execution_call.in_progress` - `response.code_execution_call.executing` - `response.code_execution_call.completed` **Code Interpreter:** - `response.code_interpreter_call.in_progress` - `response.code_interpreter_call.executing` - `response.code_interpreter_call.completed` ## Manual Verification Tested all server-side tools with both `generateText()` and `streamText()` to ensure end-to-end functionality: ### ✅ Web Search Tool ```typescript import { xai } from '@ai-sdk/xai'; import { generateText } from 'ai'; const { text, sources } = await generateText({ model: xai.responses('grok-4-fast'), prompt: 'What are the latest developments in AI?', tools: { web_search: xai.tools.webSearch(), }, }); console.log(text); // Comprehensive response console.log(sources); // Array of URL citations ``` **Result**: ✅ Returned comprehensive response with 14 URL citations, no validation errors ### ✅ X Search Tool ```typescript import { xai } from '@ai-sdk/xai'; import { generateText } from 'ai'; const { text, sources } = await generateText({ model: xai.responses('grok-4-fast'), prompt: 'What are people saying about AI on X this week?', tools: { x_search: xai.tools.xSearch({ allowedXHandles: ['elonmusk', 'xai'], fromDate: '2025-11-18', toDate: '2025-11-24', enableImageUnderstanding: true, enableVideoUnderstanding: true, }), }, }); console.log(text); // Analysis of X discussions console.log(sources); // Array of X post citations ``` **Result**: ✅ Returned analysis with 16 X post citations, all streaming events properly handled ### ✅ Code Execution Tool ```typescript import { xai } from '@ai-sdk/xai'; import { generateText } from 'ai'; const { text } = await generateText({ model: xai.responses('grok-4-fast'), prompt: 'Calculate the factorial of 20 using Python', tools: { code_execution: xai.tools.codeExecution(), }, }); console.log(text); // Result with code execution details ``` **Result**: ✅ Computed result with execution details, no validation errors ### ✅ Multiple Tools with Streaming ```typescript import { xai } from '@ai-sdk/xai'; import { streamText } from 'ai'; const { fullStream, usage: usagePromise } = streamText({ model: xai.responses('grok-4-fast'), system: 'You are an AI research assistant.', tools: { web_search: xai.tools.webSearch(), x_search: xai.tools.xSearch(), code_execution: xai.tools.codeExecution(), }, prompt: 'Research prompt caching in LLMs and explain how it reduces costs', }); const sources = new Set<string>(); let lastToolName = ''; for await (const event of fullStream) { switch (event.type) { case 'tool-call': lastToolName = event.toolName; if (event.providerExecuted) { console.log(`[Calling ${event.toolName} on server...]`); } break; case 'tool-result': console.log(`[${lastToolName} completed]`); break; case 'text-delta': process.stdout.write(event.text); break; case 'source': if (event.sourceType === 'url') { sources.add(event.url); } break; } } const usage = await usagePromise; console.log(`\nSources used: ${sources.size}`); console.log(`Token usage: ${usage.inputTokens} input, ${usage.outputTokens} output`); ``` **Result**: ✅ Full streaming response with web searches, real-time progress updates, and source citations. All streaming events (`tool-call`, `tool-result`, `text-delta`, `source`) work correctly. **Summary of manual testing:** - ✅ All three tool types (web_search, x_search, code_execution) work without validation errors - ✅ Both `generateText()` and `streamText()` work correctly - ✅ Source citations are properly parsed and returned - ✅ Streaming progress events are handled correctly - ✅ No "Invalid JSON response" or "No matching discriminator" errors ## Related issues closes #10607
4 tasks
gr2m
approved these changes
Nov 25, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is an automated backport of #10523 to the release-v5.0 branch. FYI @baturyilmaz