Description
The Vercel AI SDK generates assistant messages with empty text content blocks (e.g., {"type": "text", "text": ""}) when using tool calling with the Anthropic API (e.g., claude-3-5-sonnet-latest). This triggers the error [AI_APICallError: messages: text content blocks must be non-empty], breaking chat functionality. The Anthropic API requires non-empty text blocks, unlike other models.
Steps to Reproduce
- Set up a chat stream using the Vercel AI SDK and configure it to use an Anthropic Claude model (e.g.,
claude-3-5-sonnet-latest).
- Implement a function call within the chat flow that the Anthropic model can trigger mid-response.
- Initiate a conversation that leads the Anthropic model to invoke the defined tool.
- Observe the streamed response from the assistant. You will notice an assistant message containing a
tool_call and a preceding or subsequent content block with {"type": "text", "text": ""}.
- Attempt to send the tool call result back to the Anthropic API. This action will fail with the
[AI_APICallError: messages: text content blocks must be non-empty] error.
Expected Behavior
The Vercel AI SDK should automatically filter out any text content blocks with empty text values in messages being sent to the Anthropic API. This would ensure that only valid, non-empty text blocks and tool calls are included in the API request, allowing for seamless tool calling and continued chat functionality without errors.
Actual Behavior
The Vercel AI SDK includes empty text content blocks in the messages sent to the Anthropic API when a tool call is triggered mid-response. This violates the Anthropic API's requirement for non-empty text blocks, leading to the API rejecting the request and throwing the [AI_APICallError: messages: text content blocks must be non-empty] error, thus breaking the chat flow.
Additional context
import { streamText } from 'ai';
import { createAnthropic } from '@ai-sdk/anthropic';
// Configure Anthropic provider (replace with your API key)
const anthropic = createAnthropic({
apiKey: process.env.ANTHROPIC_API_KEY || 'your-api-key-here',
});
// Define a simple tool
const tools = {
getData: {
description: 'Fetches data based on a query',
parameters: {
type: 'object',
properties: {
query: { type: 'string' },
},
required: ['query'],
},
execute: async ({ query }) => {
return `Data for: ${query}`;
},
},
};
// Sample system prompt
const systemPrompt = 'You are a helpful assistant that can fetch data using tools.';
// Function to simulate the chat stream
async function reproduceBug() {
try {
// Initial messages array with a user query
const messages = [
{
role: 'user',
content: 'Tell me something and fetch data about "example"',
},
];
// Start streaming with tool calling enabled
const result = await streamText({
model: anthropic('claude-3-5-sonnet-latest'),
system: systemPrompt,
messages,
tools,
maxSteps: 5,
});
// Process the stream (simulating tool call response)
let toolCallDetected = false;
const updatedMessages = [...messages];
for await (const chunk of result.fullStream) {
if (chunk.type === 'tool-call') {
toolCallDetected = true;
const toolCall = chunk.args;
const toolResult = await tools.getData.execute({ query: toolCall.query });
// Simulate Claude's behavior: Assistant message with empty text + tool call
updatedMessages.push({
role: 'assistant',
content: [
{ type: 'text', text: '' }, // Empty text block causing the bug
{
type: 'tool_use',
id: chunk.toolCallId,
name: 'getData',
input: { query: toolCall.query },
},
],
});
// Add tool result message
updatedMessages.push({
role: 'user',
content: [
{
type: 'tool_result',
tool_call_id: chunk.toolCallId,
content: toolResult,
},
],
});
// Attempt to continue the stream with the tool result
const continuedResult = await streamText({
model: anthropic('claude-3-5-sonnet-latest'),
system: systemPrompt,
messages: updatedMessages,
tools,
maxSteps: 5,
});
for await (const nextChunk of continuedResult.fullStream) {
console.log(nextChunk);
}
}
}
if (!toolCallDetected) {
console.log('No tool call occurred.');
}
} catch (error) {
console.error('Error in chat stream:', error);
// Expected output: [AI_APICallError: messages: text content blocks must be non-empty]
}
}
// Run the reproduction
reproduceBug();
Description
The Vercel AI SDK generates assistant messages with empty text content blocks (e.g.,
{"type": "text", "text": ""}) when using tool calling with the Anthropic API (e.g.,claude-3-5-sonnet-latest). This triggers the error[AI_APICallError: messages: text content blocks must be non-empty], breaking chat functionality. The Anthropic API requires non-empty text blocks, unlike other models.Steps to Reproduce
claude-3-5-sonnet-latest).tool_calland a preceding or subsequent content block with{"type": "text", "text": ""}.[AI_APICallError: messages: text content blocks must be non-empty]error.Expected Behavior
The Vercel AI SDK should automatically filter out any text content blocks with empty
textvalues in messages being sent to the Anthropic API. This would ensure that only valid, non-empty text blocks and tool calls are included in the API request, allowing for seamless tool calling and continued chat functionality without errors.Actual Behavior
The Vercel AI SDK includes empty text content blocks in the messages sent to the Anthropic API when a tool call is triggered mid-response. This violates the Anthropic API's requirement for non-empty text blocks, leading to the API rejecting the request and throwing the
[AI_APICallError: messages: text content blocks must be non-empty]error, thus breaking the chat flow.Additional context