GPT-6 Astra Changed the Shape of a Turn

For three years, tool calling has had one rhythm. The model asks for a tool, your code runs it, the model waits, and then it resumes. Nothing happens in the gap. On September 3, OpenAI shipped GPT-6 Astra and, in the same API changelog entry, three controls that break that rhythm: tools the model does not wait for, user messages that land in the middle of a running response, and a reasoning setting you can change without paying for your prompt again. The launch post leads with benchmarks. The changelog is where the engineering changed, and it changes what your harness has to track.


The contract Astra loosens

A classic function call is a blocking contract. The model emits a function_call item with a call_id, the response ends, and the model's turn cannot continue until your application sends back a function_call_output with the same call_id. Parallel tool calls softened this a little: the model can ask for three lookups at once. It still waits for all of them before it does anything else. If one lookup takes 14 seconds, the model sits idle for 14 seconds, even when half of the remaining work never needed that result.

That idle time shows up in every harness I have taken apart on this site. Codex and Claude Code both treat the tool call as a hard synchronization point, and most of the engineering around them (timeouts, background shells, subagents) exists to work around it from the outside. Astra's API moves one of those workarounds inside the protocol.

Async tools: the model keeps working

The mechanism is one field. Set async: true on a function or custom tool definition, and when the model calls it, the call item carries async: true as well. The async tool calling guide describes the rest: the model can "continue working after issuing that call, before your application returns the output." One response can contain both the async call and an answer to an independent part of the request. When your job finishes, you send its output in a later request, matched by the original call_id, chained with previous_response_id to whatever the latest response is by then.

Two details decide whether this is useful or dangerous. First, execution does not move: "Your application still executes the tool. Async tools don't move execution to OpenAI or manage your background jobs." You now own a registry of pending work that outlives a single request. Second, the model needs a way to say "I need that result now." OpenAI's answer is a pattern, not a built-in: you define a synchronous wait_for_tasks tool, give every async tool a task_handle argument, and bind each handle to its call_id and running job. When the model calls wait, you return the finished results on their original call IDs first, then the wait status on the wait call's own ID, so the results are in context when the model resumes. The same shape gives you a tool that asks the user a question while the model keeps gathering facts.

The figure below runs one incident-triage turn both ways. Drag the latencies and the amount of independent work, and watch where the savings come from.

Fig. 1 · one turn, two contracts

Prompt: "Find why checkout p99 regressed and draft the incident note." The model launches query_traces and fetch_deploy_log, has some work that does not depend on them (outlining the note, reviewing the PR already in context), then must wait before it analyzes. Durations are illustrative seconds.

14 s
6 s
9 s
Blocking call 0 s
model
query_traces
fetch_deploy_log
    async: true 0 s
    model
    query_traces
    fetch_deploy_log
      model working (numbered steps)your tool runningmodel blocked

       

      The arithmetic in that verdict is the whole case for and against the feature. With a blocking call, wall-clock time is the model's work plus the slowest tool. With an async call, the slow tool overlaps with whatever work does not depend on it, so the saving is the smaller of two numbers: the slowest tool's latency, or the independent work available. A request with no independent work saves nothing. A request with lots of it saves up to the full tool latency. Async tools are a scheduling feature, and they pay off in proportion to how parallel your task already was.

      The guide also lists where async does not apply. It works for function and custom tools your application runs, not for hosted tools like web search. You should not mark tools async when you use programmatic tool calling, and in multi-agent mode you should not combine async tools with parallel tool calls. And it is model-gated: "supported by GPT-6 Astra and later models."

      Steering: a message that lands mid-response

      The second control addresses the user who types while the agent works. Before Astra, a correction had two outcomes: cancel the response and lose its progress, or wait for it to finish and then pay for a second turn that undoes part of the first. Mid-turn steering adds a third, and it only exists over a WebSocket connection to the Responses API. GPT-5.6 and earlier models do not support it.

      The event flow is precise, and worth reading slowly. After the response's response.created event, you send response.steer with the response ID as previous_response_id. The server replies response.steer.accepted, which means the input is queued, not acted on. Then the server "finishes the current output item and any hosted tool work already running," ends the original response with response.incomplete and incomplete_details.reason: "steered", and creates a continuation response that includes your update. The continuation inherits the original request settings, and token and tool-call limits apply to each response separately.

      There is one exception, and it is the one that bites. If the response ends needing a client tool result or an approval, the steer stays queued. The server sends response.steer.pending with a required_input list naming the calls it needs, and waits for you to return them with a normal response.create. The server prepends the queued steer for you; resending it duplicates it. Slide the arrival point below to see both paths.

      Fig. 2 · the steer injector

      A running response, resp_1, drafting an incident report. The user sends "keep it to the customer-facing impact" while it streams. Pick the output item that is in flight when the steer arrives.

      item 3
      output items
        WebSocket events

           

          Three rules fall out of that event log. Steering never rewrites output that already reached your application, never undoes earlier actions, and never cancels a tool that already started. Queued steering lives on the connection, not on the stored response, so a dropped socket can lose it: the guide says to record every steer you send and compare it against response history before replaying. And a failure is final. response.steer.failed means the input "will not apply it automatically later," with error codes such as steering_not_supported and too_many_pending_steers. A harness that treats steering as fire-and-forget will occasionally drop the user's most important sentence.

          The launch post describes the same behavior at the product level. In Codex, Astra "can ask asynchronously while continuing work that doesn't depend on your reply," and it proceeds on sensible assumptions for small gaps but waits on consequential decisions. Async tools and steering are the two halves of that: the model can ask without stopping, and you can answer without restarting.

          Effort became a message

          The third control looks small and is about money. Reasoning effort used to be a request-level setting, reasoning.effort. Astra accepts low, medium, high, xhigh, and max per its model page, and a conversation that needs high effort for one hard step and low effort for routine follow-ups used to change that field between requests. OpenAI's migration guidance now says to keep the request-level value fixed "to preserve the prompt prefix for caching," and to change effort with a configuration_update input item placed before the next user message instead.

          { "type": "configuration_update", "reasoning": { "effort": "high" } }

          The reasoning guide sets the rules. The update applies to the next response and every one after it until another update overrides it. The response's own reasoning.effort field keeps reporting the request-level value, so your logs will lie unless you record the updates yourself. Two updates cannot sit next to each other in history. And updates do not mix with automatic compaction or truncation, and the standalone compact endpoint rejects histories that contain them. It is supported in standard, single-agent mode only.

          Why it matters is on the price sheet. Astra lists $10 per million input tokens, $1 per million cached input tokens, $12.50 per million for cache writes, and $50 per million output tokens, with prompts over 272K input tokens billed at twice the input and cache rates. A cached read costs a tenth of a fresh one. An agent conversation is mostly prefix: system prompt, tool schemas, and every earlier turn. The figure prices eight turns both ways.

          Fig. 3 · the effort strip

          Eight turns of one agent session: 24,000 tokens of system prompt and tools, plus 6,000 new tokens per turn (illustrative). Tap a turn to switch its effort. Input is priced at Astra's list rates; output is the same in both rows and left out.

           

          Assumption, stated: a changed request-level reasoning.effort invalidates the cached prefix, so that turn re-writes the whole prefix at the cache-write rate. That is the worst case OpenAI's guidance warns about. A configuration_update keeps the prefix, so only the new tokens are written.

          The pattern generalizes past Astra. Anything that sits in the prefix and changes between turns (a tool list you rebuild, a timestamp in the system prompt, a setting encoded early) turns a cheap cached read into an expensive write. I made the same argument about Anthropic's cache pricing in Fable 5.1's two doors. OpenAI has now moved one of the most common per-turn changes out of the prefix and into the message stream, where it belongs.

          The monitor in the loop

          The fourth change is the one you cannot turn off. OpenAI says Astra "meets the Critical threshold in cybersecurity under our Preparedness Framework," and it shipped with misalignment monitoring. The monitor "reviews model reasoning and actions asynchronously and can stop a conversation when it identifies a potential issue," focused on consequential contexts such as transferring or accessing sensitive data or making destructive changes.

          Coverage depends on how you keep conversation state:

          Request typeMonitoredCan auto-stop
          Responses API with persisted reasoning, WebSockets, or OpenAI compactionyesyes
          Responses API using none of thoseyesno, webhook alerts only
          Chat Completionsnono, other checks apply

          A stop arrives as HTTP 403 with code misalignment_policy_violation, and the guide is blunt about what it means: "The API does not provide a general way to resume a conversation stopped by misalignment monitoring." Because the check is asynchronous, "an action may already have completed before monitoring identifies a concern. A stopped request does not undo earlier actions." Alerts can also reach you through a safety.alert.created webhook that carries only an alert ID, which you fetch with a key holding the api.safety.alerts.read permission.

          Put that next to async tools and the design constraint is clear. Your application may have three jobs in flight, a steer queued, and a user question pending when a 403 arrives, and nothing on OpenAI's side will unwind them. The launch post adds that in ChatGPT and Codex a paused task may ask you to review the action, but "in the API, the task will stop." The same post says Astra will refuse more advanced security work, such as proof-of-concept exploits, with less restrictive access planned through OpenAI's Daybreak program. If you build defensive tooling, plan for refusals on the public model and for stops you did not trigger.

          The migration list, read as a harness spec

          The model guide has the usual migration checklist, and every line of it changes code somewhere. Astra has no none effort; use low. It does not accept custom temperature, top_p, or log probabilities. It supports Chat Completions, but its tool calling requires the Responses API. It is priced at 2x for Fast mode, and at half for Batch and Flex. The window is 1,050,000 tokens with up to 128,000 output tokens.

          One line in the prompting section deserves more attention than it will get. The guide says Astra "can be more sensitive to instructions contained in skills and other files, such as AGENTS.md," and recommends auditing them. That is the flip side of better instruction following, and it is the same supply-chain surface I wrote about in the AGENTS.md practices nobody uses: a model that obeys your files more closely also obeys a poisoned file more closely.

          Collected, this is the state a harness now carries per conversation:

          The vendor numbers in the launch post are strong. OpenAI reports 57.9% on Terminal-Bench 4.0 against 55.8% for Claude Fable 5.1 and 37.3% for GPT-5.6, and says Astra often finishes tasks with fewer output tokens than the models it compares against. Treat those as OpenAI's measurements until independent ones arrive. The API changes need no benchmark. A turn used to be a straight line with pauses in it. With Astra it is a set of overlapping timelines: model work, your jobs, the user's corrections, and a monitor watching all three. The harness that keeps those timelines straight is the part you still have to write.

          rg
          Rohit Ghumare

          CNCF Ambassador and Google Developer Expert. I build agent infrastructure and write about the fundamentals underneath the AI stack. API behavior here comes from OpenAI's GPT-6 Astra launch post, the API changelog entry of September 3, and the async tool calling, mid-turn steering, reasoning, model, and misalignment monitoring guides, read in September 2026. Benchmark figures are OpenAI's own. Figure durations and token counts are illustrative; prices are OpenAI's list rates for gpt-6-astra.

          Related: Inside the Codex Harness · Harness Engineering · More posts · X