I have this bit of code (not runnable as is, but you don't need it, I just want you to get the structure)
async function loop({
startingMessages,
env,
}: {
startingMessages: ModelMessage[];
env: AgentEnv;
}) {
const messages: ModelMessage[] = [...startingMessages];
const model = createGoogleGenerativeAI({
apiKey: env.GEMINI_API_KEY,
})("gemini-2.5-flash-preview-09-2025")
const tools = getTools({ env });
// each of these tools has an .execute() function defined,
// so the AI framework will call it for us.
let result;
while (true) {
result = streamText({
model,
messages,
tools,
});
for await (const chunk of result.fullStream) {
// ..do stuff
}
const responseMessages = (await result.response).messages;
messages.push(...responseMessages);
const finishReason = await result.finishReason;
if (finishReason === 'tool-calls') {
// The agent asked to use tools, then the ai framework invoked them already,
// but now we actually need to give the tool results back to the model.
console.log(`giving tool results back to model`);
} else {
// Exit the loop when the model didn't request to use any more tools
return result;
}
}
}
What happens is one of the tools I wrote had a bug, and returned an object that doesn't pass the ModelMessage schema, because it contained an undefined value, eg {temperature: undefined}, and therefore wasn't JSON serializable.
But, this was a total pain for me to debug. There is no error raised when the tool is actually called and the result is handed back to the AI sdk. Instead, that poison pill of a response is in responseMessages and then is added to the message chain in messages.push(...responseMessages);, and only in then the next iteration of the loop, when I call streamText(), do I get a very obtuse schema validation error from zod.
I realize I need to make my tools return valid JSON-serializable things, that's fine, but can you make it easier to help me pinpoint this when I make a mistake? Several options I see:
tool.execute()