Classic function calling has a shape every agent builder knows by heart. The model requests one tool call, your application executes it, you append the result, and the model requests the next. Four tools, four round trips. Forty tools, forty. Each pass adds network latency and re-billed context. When OpenAI pushed GPT-5.6 to general availability on July 9, 2026, it shipped a way off that treadmill: programmatic tool calling in the Responses API.
The idea is direct. Instead of returning tool calls one at a time for your code to run in a loop, the model writes JavaScript that orchestrates multiple tool calls itself. That code executes in an isolated V8 runtime with no network access. Your tools remain the only way the code can touch the outside world, so the security boundary you already reason about with OpenAI function calling stays exactly where it was. What moves is the orchestration: the loops, conditionals, and aggregation that used to live in your application.
The shift lands on your side of the API too. Every tool you expose is now a contract the model may call in bursts of dozens rather than one careful call per turn. Schema precision, error shapes, and rate behavior matter more than they did last week. This article covers what shipped, why the old loop hurts, what stays the same, and how to get your tool endpoints ready with Apidog before handing them to the model.
TL;DR
- GPT-5.6 went GA on July 9, 2026. At GA, the Responses API gained programmatic tool calling, confirmed in OpenAI’s developer docs.
- Instead of one tool call per round trip, the model writes JavaScript that composes loops, conditionals, and aggregation over your tools.
- The generated code runs in an isolated V8 sandbox with no network access. Your tool definitions stay the only path to external systems, so the security boundary does not move.
- Latency and token cost stop compounding with the number of tool calls, which is where classic agent loops bleed.
- The feature is days old; exact request parameters and limits live in OpenAI’s API reference, so read it before you build.
- Test and mock each tool endpoint before the model orchestrates it; a schema ambiguity becomes a bug repeated in a loop.
What shipped on July 9
GPT-5.6 arrived as a three-tier family: gpt-5.6-sol for deepest reasoning, gpt-5.6-terra for balanced work, and gpt-5.6-luna for fast, cost-efficient volume. The bare alias gpt-5.6 routes to Sol. All three are self-serve through the API with no plan gating, after a two-week limited preview that ended when the access restriction lifted on July 8.
The model family got most of the launch-day attention, but the new API surface is the bigger story for agent builders. Per MarkTechPost’s launch coverage and OpenAI’s own documentation, the Responses API picked up four things at GA: programmatic tool calling, a multi-agent beta, persisted reasoning across turns, and vision detail settings that preserve original image dimensions.
Programmatic tool calling is the headline. OpenAI describes it as the model writing JavaScript to orchestrate tool calls, executed in an isolated V8 runtime with no network access. The model stops being a turn-by-turn requester and becomes the author of the orchestration layer.
The loop that programmatic tool calling replaces
Here is classic function calling against the Responses API, the shape almost every production agent uses today:
import OpenAI from "openai";
const client = new OpenAI();
const tools = [
{
type: "function",
name: "get_flight_status",
description: "Return live status for a flight by IATA flight number.",
parameters: {
type: "object",
properties: {
flight_number: {
type: "string",
description: "IATA flight number, for example SQ317"
}
},
required: ["flight_number"]
}
}
];
let response = await client.responses.create({
model: "gpt-5.6",
input: "Which of these 12 flights are delayed: SQ317, BA15, UA857...",
tools
});
The model cannot answer without data, so it emits a function call. Your code runs the lookup, appends a function_call_output item, and calls the API again:
// One round trip per tool call. This loop is the tax.
while (hasFunctionCalls(response)) {
const outputs = await executeToolCalls(response); // your code, your infra
response = await client.responses.create({
model: "gpt-5.6",
previous_response_id: response.id,
input: outputs,
tools
});
}
For 12 flights, that loop can run 12 times, and every iteration pays twice. First in latency: a full network round trip to OpenAI plus model time, serialized, because call N+1 depends on the model seeing result N. Second in tokens: tool results accumulate in context, so late iterations re-process everything the early ones produced. Chain agents together and the compounding gets ugly: a five-step agent where each step wraps a ten-call loop is fifty billed model invocations.
None of that loop is intelligence. It is plumbing, and until this week the model had no way to write the plumbing itself.
How programmatic mode changes the shape
With programmatic tool calling, the model answers the flight question differently: it writes a short JavaScript program that loops over the twelve flight numbers, calls get_flight_status for each, filters for delayed status, sorts by delay length, and returns the aggregate. The sandbox executes that program. Your tools still do the real work; the control flow around them now belongs to the model.
Three properties make this workable rather than alarming:
- The runtime is isolated. OpenAI runs the generated JavaScript in a V8 sandbox with no network access. The code cannot fetch a URL, open a socket, or exfiltrate anything on its own.
- Tools are the only exit. Every external effect routes through the tool surface you defined. If you did not expose a
delete_recordtool, no generated code can delete a record. - Control flow becomes expressive. Loops, conditionals, early exits, aggregation across results: patterns that took N round trips now happen inside a single response cycle.
| Classic function calling | Programmatic tool calling | |
|---|---|---|
| Who writes the control flow | Your application | The model, as JavaScript |
| Round trips for N tool calls | N, serialized | One response cycle |
| Where orchestration runs | Your infrastructure | Isolated V8 sandbox, no network |
| How tools execute | Your code invokes them | Still through your declared tool surface |
| Security boundary | Tool definitions | Tool definitions, unchanged |
What stays the same
You still define tools with names, descriptions, and JSON Schema parameters, exactly as in the code above. The model can only compose calls to tools you declared, which means the question “what can this agent do to my systems” has the same answer it had before: whatever your tool surface permits, and nothing else.
Schema quality matters more now, not less. In the classic loop, a vague parameter description produced one bad call you could catch and correct before the next round trip. In programmatic mode, the same vagueness can be baked into a loop and repeated across every iteration before you see a single result. The habits you built for structured outputs transfer directly: strict types, enums for closed sets, descriptions that state units and formats, required fields that are honestly required.
Limits and open questions
This capability is days old. A few cautions before you rebuild your agent stack around it:
- The exact request parameters, execution limits, and timeout behavior belong to OpenAI’s API reference and model guide. Parameter names can drift during the polish that follows any GA launch, so read the reference before you write code against the feature.
- Debugging is a new surface. When orchestration lived in your repository, you could set a breakpoint; now part of the control flow is generated fresh per request. Logging the tool-call sequence the sandbox makes becomes a core observability task.
- There is no production track record yet. Simon Willison’s day-one notes on GPT-5.6 are a good running record of what independent testing surfaces; expect sharp edges to appear there before official docs mention them.
- A sane rollout order: start with read-only tools, watch the generated orchestration, verify token accounting against your old loop, and only then expose tools with side effects.
Your tools are now an API that someone else’s code calls
Under classic function calling, a tool was called once per round trip, with a human-authored loop deciding pace and order. Under programmatic tool calling, generated code calls your tools in bursts, branches on their responses, and aggregates their output. Each tool is an API contract consumed by a machine-written client you never review before it runs.
That raises the bar on four things:
- Schema precision. State units, formats, and ranges in every parameter description. An ambiguous date format is no longer one bad call; it is a loop of them.
- Error shapes. Generated code will branch on failures. A tool that returns 200 with an error message buried in a string will mislead any orchestration written against your schema. Return honest status codes and structured error bodies.
- Idempotency and rate behavior. Twelve calls that used to arrive over a minute may now arrive in one burst. Know what your endpoint does under that pattern before the model finds out for you.
- Latency. A tool that takes eight seconds was tolerable once per turn. Inside a twelve-iteration loop, it defines your response time.
This is where a real API workbench earns its place. Define or import each tool endpoint’s spec, send test requests against it, and confirm the response schema matches what your tool definition promises. Then go one step further: mock the tool API so you can exercise orchestration against predictable fake data without touching production. Download Apidog and its built-in mock server will serve schema-shaped responses for every endpoint you have defined, so you can hand the model a full tool surface and watch how it orchestrates before touching a single real record.
The other GA features in brief
Programmatic tool calling did not ship alone. Two adjacent Responses API additions matter here:
- Multi-agent, in beta: parallel subagent execution managed by the API. Early stage, worth watching rather than betting on.
- Persisted reasoning: reasoning context reused across turns via
reasoning.context, so long agent sessions stop re-deriving the same conclusions every turn.
Both compound with programmatic tool calling: an agent that keeps its reasoning across turns and writes its own orchestration does far less redundant work per task.
Programmatic tool calling vs ultra mode
The launch also brought ultra, and the two get confused because both do more per request. They solve different bottlenecks.
Ultra is a multi-agent setting that runs four agents in parallel by default, spending more tokens deliberately to cut wall-clock time; per OpenAI, it lifts Terminal-Bench 2.1 from 88.8% to 91.9%. It lives in ChatGPT Work on Pro and Enterprise plans, and in Codex from Plus upward. Programmatic tool calling is an API capability where one agent orchestrates its tools in code. Ultra parallelizes the thinking; programmatic tool calling collapses the execution round trips. The full breakdown is in our GPT-5.6 ultra mode piece, but the short version: if your bottleneck is tool-call latency, you want programmatic tool calling; if it is deliberation time on hard problems, you want ultra.
FAQ
Do I need to rewrite my existing tool definitions?
No. Tools keep the same JSON Schema shape shown in the code above, and definitions written for classic function calling carry over. The worthwhile work is tightening them: add enums, state formats, and make descriptions specific enough that generated code cannot misread them.
Can the generated JavaScript reach the internet?
No. The code runs in an isolated V8 runtime with no network access, and your declared tools are its only way to affect anything outside the sandbox. That makes your tool surface the entire risk model, so audit which tools you expose with the same care you would give a public API.
Which GPT-5.6 models support programmatic tool calling?
OpenAI documents it as Responses API surface for the GPT-5.6 family, and all three tiers (gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna) are self-serve for any API account. Check the API reference for tier-level details before committing to one. For key setup and a first request walkthrough, see how to use the GPT-5.6 API.
How is this different from code interpreter?
Code interpreter runs code as the deliverable: analysis, charts, file transforms. Programmatic tool calling generates code whose only job is coordinating your declared tools; the deliverable is the aggregated tool results, not the code itself.
Where this leaves you
The round-trip loop was the least interesting part of every agent you have shipped, and GPT-5.6 made it optional. The orchestration moved to the model; the responsibility for clean, precise, well-behaved tool APIs moved to you, with more weight than before.
The next step is concrete. Pick one read-heavy workflow, write or tighten the tool schemas it needs, and put each endpoint through Apidog’s API client and mock server until the contract holds under burst calls and bad inputs. When the model starts writing code against your tools, you want that code reading from a surface you have already tested.



