# The Responses API tool loop in Node
Verified against the function calling guide on 2026-09-26.
## The loop
1. `const response = await openai.responses.create({ model, input, tools })`
with tools declared as `{ type: "function", name, description, parameters }`.
2. `const calls = response.output.filter((i) => i.type === "function_call")`.
3. For each call: `const args = JSON.parse(call.arguments)` in try/catch;
`await` your implementation (never fire-and-forget inside the loop, or the
output ordering breaks).
4. Build the follow-up input: the previous `response.output` items plus, per call,
`{ type: "function_call_output", call_id: call.call_id, output: JSON.stringify(result) }`.
Omitting the original function_call items from the follow-up input is the most
common 400 in this loop; the API needs the full item history.
5. `await openai.responses.create({ model, input: nextInput, tools })` and repeat
until no function_call items remain.
## Guards
- Cap the loop (for example 8 iterations) and surface a partial answer at the cap.
- `parallel_tool_calls: false` when functions depend on each other's results.
- Whitelist `call.name` against your tool registry before dispatch; never index
into an object with a model-supplied name without a hasOwnProperty-style check.
## Check before you ship
- In Express, this whole loop runs inside one request handler; set a route
timeout longer than your worst-case loop, or move the loop to a background job
and poll.
- Assert in a test that every function_call_output's call_id matches its call.