TanStack AI version
@tanstack/ai@0.48.0, @tanstack/ai-openai@0.21.1
Framework/Library version
node@24.19.0, zod@4.4.3 — server-side only, no UI framework involved
Describe the bug and the steps to reproduce it
On the Responses API, a tool loop intermittently dies on the second turn with:
400 Item 'fc_04c5d379bb13126a006a8b1700e3ac87d19dae6257035321cf' of type 'function_call'
was provided without its required 'reasoning' item:
'rs_0bf74942a9c5d320006a8b0d57d26487d1981665bb013fd0f3'.
When a reasoning model emits a reasoning item alongside a function_call, the Responses API requires that reasoning item to be sent back with the function_call on the following turn. OpenAITextAdapter re-sends the function_call but not its paired reasoning item, so the request is rejected and the run ends with RUN_ERROR after the tools have already executed.
It is intermittent, which is what makes it easy to miss — it fails only on runs where the model actually produced a reasoning item. On gpt-5.6-luna with default effort I measured 4 failures in 6 consecutive runs of the script below, unchanged between runs. My first attempt at a minimal reproduction passed twice and I nearly concluded the trigger was something else.
Not specific to parallel tool calls, large tool outputs, system prompts, or the number of registered tools — I bisected all four away. One tool and a one-line result reproduces it.
Workaround: modelOptions: { reasoning: { effort: 'none' } }. That suppresses the reasoning item entirely, so there is nothing to round-trip and the loop runs. Chat Completions is not an alternative — it rejects function tools alongside reasoning outright, with "Function tools with reasoning_effort are not supported ... set reasoning_effort to 'none'".
This looks like the OpenAI counterpart of #340 ("Anthropic tool loops: thinking blocks missing on turn 2+"), which was fixed for Anthropic.
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
Run this a few times — expect roughly two failures in three. npm i @tanstack/ai @tanstack/ai-openai zod, set OPENAI_API_KEY, npx tsx repro.mts:
import { chat, maxIterations, toolDefinition } from '@tanstack/ai';
import { OpenAITextAdapter } from '@tanstack/ai-openai';
import { z } from 'zod';
const search = toolDefinition({
name: 'search',
description: 'Search passages of the archive.',
inputSchema: z.object({ query: z.string() }),
outputSchema: z.object({ passages: z.array(z.object({ id: z.string(), text: z.string() })) }),
}).server(({ query }) => ({ passages: [{ id: 'p1', text: `${query}: lorem ipsum dolor sit amet` }] }));
const stream = chat({
adapter: new OpenAITextAdapter({ apiKey: process.env.OPENAI_API_KEY! }, 'gpt-5.6-luna'),
messages: [{ role: 'user', content: 'Search the archive for anything about being tired, then summarise in one sentence.' }],
tools: [search],
agentLoopStrategy: maxIterations(6),
});
for await (const chunk of stream) {
if (chunk.type === 'RUN_ERROR') console.log('RUN_ERROR:', chunk.message);
if (chunk.type === 'TEXT_MESSAGE_CONTENT') process.stdout.write(chunk.delta);
}
Expected: the loop completes and the model answers using the tool result.
Actual: about two runs in three end in RUN_ERROR with the 400 above, after the tool has run.
Do you intend to try to help solve this bug with your own PR?
No
TanStack AI version
@tanstack/ai@0.48.0, @tanstack/ai-openai@0.21.1
Framework/Library version
node@24.19.0, zod@4.4.3 — server-side only, no UI framework involved
Describe the bug and the steps to reproduce it
On the Responses API, a tool loop intermittently dies on the second turn with:
When a reasoning model emits a
reasoningitem alongside afunction_call, the Responses API requires that reasoning item to be sent back with thefunction_callon the following turn.OpenAITextAdapterre-sends thefunction_callbut not its pairedreasoningitem, so the request is rejected and the run ends withRUN_ERRORafter the tools have already executed.It is intermittent, which is what makes it easy to miss — it fails only on runs where the model actually produced a reasoning item. On
gpt-5.6-lunawith default effort I measured 4 failures in 6 consecutive runs of the script below, unchanged between runs. My first attempt at a minimal reproduction passed twice and I nearly concluded the trigger was something else.Not specific to parallel tool calls, large tool outputs, system prompts, or the number of registered tools — I bisected all four away. One tool and a one-line result reproduces it.
Workaround:
modelOptions: { reasoning: { effort: 'none' } }. That suppresses the reasoning item entirely, so there is nothing to round-trip and the loop runs. Chat Completions is not an alternative — it rejects function tools alongside reasoning outright, with"Function tools with reasoning_effort are not supported ... set reasoning_effort to 'none'".This looks like the OpenAI counterpart of #340 ("Anthropic tool loops: thinking blocks missing on turn 2+"), which was fixed for Anthropic.
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
Run this a few times — expect roughly two failures in three.
npm i @tanstack/ai @tanstack/ai-openai zod, setOPENAI_API_KEY,npx tsx repro.mts:Expected: the loop completes and the model answers using the tool result.
Actual: about two runs in three end in
RUN_ERRORwith the 400 above, after the tool has run.Do you intend to try to help solve this bug with your own PR?
No