Async Coding Agents: Let AI Keep Working While You Decide
💡 Tool Tip:While tuning coding agents, pair them with Evergreen Tools' JSON Formatter to inspect tool output, Base64 Encode/Decode for credentials, and UUID Generator for task IDs — everyday companions in agent workflows!
In August 2026, OpenAI merged send_user_message_async into the public Codex repository (as reported by The New Stack). The change looks small, but it reshapes the relationship between coding agents and the developers supervising them: instead of grinding to a halt every time the agent has a question, it can fire off a message, get an "accepted" acknowledgment, and keep working. This article explains async coding agents and why they are becoming a production necessity.
AI agents in the modern dev workflow
1. What Is an Async Coding Agent?
The core idea of an async coding agent is non-blocking. The New Stack's report contrasts two tools: Codex's existing request_user_input pauses the entire turn until the developer answers, while the newly merged send_user_message_async sends the question or update, receives an "accepted" response, and continues the current turn — the developer's reply comes back later as a new user message. In the integration test, Codex sent "Still investigating," immediately got another opportunity to respond, and never sat idle.
2. Why Production Teams Need Async
A real refactor asks 3-5 decision questions. With blocking tools, a 20-minute session burns half its time waiting. Async lets the agent finish work that does not depend on the answer: analyze the call graph, write tests, prepare the patch — and only interrupt you when a decision is actually required. The New Stack notes this proves OpenAI is building a different relationship between coding agents and the developers supervising them.
# The old blocking pattern: request_user_input
# Codex pauses the whole turn and waits for the developer
def verify_breaking_change(plan):
# This tool BLOCKS: the agent stops generating
answer = request_user_input(
"This refactor touches auth/validator.ts. Proceed?"
)
if answer == "yes":
return execute(plan)
return plan.revised3. Async Messages Are a Side Channel, Not Context Pollution
One detail is easy to miss: OpenAI avoids inserting a second, synthetic copy of the developer-facing update into the model's input. The original tool call and its accepted result stay in the exchange, but the message is not re-added as a normal assistant response — effectively a side channel. That saves tokens and prevents the agent from being derailed by its own progress reports. For teams that watch context budgets, this design matters.
# The new async pattern: send_user_message_async
# Codex sends the message, gets "accepted", and keeps working
def long_running_refactor():
send_user_message_async(
"Still investigating the cache invalidation path."
)
# No blocking: the agent continues the current turn
graph = inspect_call_graph("src/cache")
risky = find_write_cycles(graph)
if risky:
send_user_message_async(
"Found 3 write cycles. Preparing a minimal patch."
)
return patch4. The Boundary: Subagents and Async
Per the registration logic in the merged code, subagents do not receive this tool. A Codex task using several subagents still has exactly one agent responsible for communicating with the developer. This is deliberate — it prevents multiple agents from firing questions at you at once. Teams orchestrating multi-agent workflows should adopt the same rule: a single outward communication channel.
# Worker agent pattern: background jobs with a heartbeat
# A task queue keeps the human informed without stalling the agent
from codex import CodexSession
session = CodexSession(repo="evergreen-tools")
job = session.submit_async(
prompt="Upgrade all lodash imports to native ES2024",
notify_on=["progress", "question", "done"],
)
# The human sees updates as they arrive and answers only
# when a decision is actually needed
for update in job.stream():
if update.kind == "question":
update.answer(input("Decision needed: "))
elif update.kind == "progress":
print(f"[agent] {update.text}")5. How to Roll It Out: Queues, Heartbeats, and Decision Points
To put async agents into real workflows, use three patterns: a task queue (submit background jobs and subscribe to notifications), heartbeats (long tasks report progress periodically), and decision-point splitting (only ask when you must make a call). The developer shifts from "chatting along" to "approving," and the agent shifts from "one step per question" to "continuous progress" — throughput improves by an order of magnitude.
# Review-loop pattern: async handoff between agent and reviewer
# The agent keeps the repo green while the reviewer thinks
pipeline = [
("agent", "implement feature X with tests"),
("async", "notify reviewer: PR ready for early look"),
("agent", "continue on independent task Y"), # no waiting
("human", "approve or request changes"),
("agent", "address review comments and rebase"),
]
for step in pipeline:
run(step) # async steps never block the queue6. When NOT to Use Async
Async is not a silver bullet. High-risk operations (database schema changes, production config) should still use blocking confirmation; and without solid test coverage, letting an agent run free can manufacture junk changes. Best practice: default to async progress, force sync confirmation on critical paths — "ask when you must, don't bother me otherwise."
From research to production
📌 Frequently Asked Questions
What is the difference between async and normal coding agents?
A normal agent (like request_user_input) pauses the entire turn while asking the developer a question. An async agent (send_user_message_async) sends the message, immediately receives an 'accepted' acknowledgment, and continues the current turn; the reply arrives later as a new user message. The difference is whether the agent stays productive while waiting.
Do async messages waste tokens?
No. Per The New Stack's report, OpenAI deliberately avoids injecting a second copy of the developer-facing message into the model input as a normal assistant response. The original tool call and its accepted result remain, but the message travels through a side channel and does not consume extra context budget.
Can subagents send async messages to developers?
Not currently. The code merged into Codex shows subagents do not receive send_user_message_async; regardless of how many subagents a task uses, a single agent stays responsible for communicating with the developer to avoid a flood of questions from multiple agents.
Which tasks suit async mode?
Long-running and parallelizable work: large refactors, dependency upgrades, test completion, cross-file analysis. High-risk operations — database schema changes, production config edits — should still use blocking confirmation so the agent cannot barrel ahead into an incident.
How do I start using async coding agents?
Watch the changelog of your coding agent (Codex, Claude Code, Cursor, etc.) for async messaging or background-task capabilities. Start with progress reporting: have the agent send one progress message and verify it doesn't block, then convert decision points to async. Pair it with a task queue and heartbeat messages for the best results.