Asynchronous Execution: Running Long AI Tasks Without Blocking Developers
A developer who kicks off an agent to “migrate this module to the new API” and then sits staring at a terminal for eight minutes has gained very little compared to doing it themselves faster. The real productivity unlock of agentic coding tools isn’t that they write code — it’s that they let a developer hand off a task and keep working on something else while it runs, the same way you’d delegate a task to a teammate instead of watching over their shoulder.
That only works if execution is genuinely asynchronous: the task runs remotely, independent of the developer’s machine or session, and reports back when it’s done or when it needs input.
Why Synchronous Execution Doesn’t Scale to Real Tasks
A synchronous model — start a task, block until it finishes — has a hard ceiling: it caps how many tasks you can have in flight at exactly one per available human attention span. It also means a dropped connection, a closed laptop lid, or a flaky local environment kills the task entirely, with no way to resume.
The Async Job Pattern
1. Submit → POST /tasks {goal, repo, constraints} → returns task_id immediately2. Execute → task runs in a cloud sandbox, independent of the requester's session3. Signal → progress events pushed to a queue/webhook (not polled by a blocked client)4. Checkpoint→ if human input is needed mid-task, task pauses and notifies, doesn't block a thread5. Complete → final result (PR, diff, report) delivered; requester is notified, not waitingThe key design shift from a traditional job queue is step 4 — an agent task isn’t guaranteed to run start-to-finish without needing anything. It might need a decision (which of two approaches to take), a credential it doesn’t have, or approval for a risky action. The async model has to support “pause and ask,” not just “run and report.”
What Changes in the Developer Experience
| Synchronous execution | Asynchronous execution |
|---|---|
| Developer waits, task blocks their session | Developer kicks off task, moves to other work |
| One task in flight per developer | Many tasks in flight, tracked in a queue/dashboard |
| Failure often means starting over | Task state persists; can resume or retry from checkpoint |
| Local machine is a single point of failure | Task survives disconnects, laptop sleep, session end |
| Review happens live, in the same session | Review happens later, async, often by a different reviewer |
Infrastructure Requirements
Async execution isn’t just “run it on a server instead of locally” — it requires the pieces that make async safe and observable:
- A durable task queue so tasks survive worker restarts and can be retried without duplicate side effects.
- Idempotent operations so a retried step (e.g., a git commit) doesn’t double-apply if the first attempt partially succeeded.
- Notification channels (webhook, email, Slack, in-app) so “done” reaches the developer without them polling.
- A review queue, since async work naturally decouples “task finished” from “task reviewed” — see Human-in-the-Loop Control for how that queue should behave.
The Practical Tradeoff
Async execution trades immediacy for throughput. A developer gets an answer slower for any single task, but can have five or ten running simultaneously across the day instead of one at a time. The platforms getting this right treat the task queue itself as a first-class product surface — a dashboard of in-flight and completed agent work — rather than treating async as just a backend implementation detail invisible to the user.