\n\n\n\n Nine Ways of Waiting and Why Your AI Agent Cares - Agent 101 \n

Nine Ways of Waiting and Why Your AI Agent Cares

📖 5 min read•845 words•Updated Sep 12, 2026

Async/await is not a solved problem, and the fact that most of us treat it like one is exactly why AI agents behave strangely when you ask them to stop.

That is a strong claim for a topic that usually gets filed under “boring plumbing.” But a paper making the rounds right now suggests the plumbing is a lot less settled than the tutorials imply. Gavin Gray, Shriram Krishnamurthi, and Will Crichton, working out of Brown’s Cognitive Engineering Lab, published A Design Space Exploration of Async/Await for OOPSLA 2026, with the preprint hitting arXiv on August 21, 2026. Their finding, boiled down: the same two keywords mean meaningfully different things depending on which language you are writing in, and those differences fall along nine distinct design dimensions.

If you build or use AI agents and you are not a programmer, that sentence deserves unpacking, because it explains a category of agent weirdness you have probably already run into.

What async/await actually does

Imagine you ask an assistant to do three things: look up a flight price, check your calendar, and draft an email. A naive program does them one at a time. It sits and stares at the flight website until it answers, then moves on. Most of that time is spent waiting, not working.

Async/await is the trick that lets a program hand off the waiting. The async keyword marks a chunk of work that might need to pause. The await keyword marks the exact spot where the pause happens, and says: go do something else, come back when this finishes. The appeal is that the code still reads top to bottom, like a recipe, even though the execution is jumping around. The researchers call this straight-line asynchrony, and it is the whole reason the paradigm caught on. Concurrency is genuinely hard to reason about. Async/await makes it look almost normal.

Where the nine dimensions come in

The paper’s contribution is refusing to stop at “it makes concurrency readable.” Instead it maps out the choices language designers make underneath, and there are more of them than you would expect. Two of the dimensions the authors highlight matter directly to anyone running agents.

The first is task lifecycle. When you kick off an async task, when does it actually start? Some languages begin the work immediately. Others create a task object that does nothing at all until something awaits it. Both are defensible. Both produce completely different behavior when a program has three tasks in flight and one of them fails.

The second is cancellation. What happens when you want to stop something already in progress? Does the task get told to wind down and given a chance to clean up? Does it get killed outright? Does anyone notice if it just keeps running in the background, unwatched? Again, different languages answer differently, and the answers are not interchangeable.

Why this shows up in your agent

Agents are essentially long chains of waiting. A single agent run might call a model, wait, call a search tool, wait, call three tools at once, wait, then decide what to do with whatever came back. Under the hood, that orchestration is async/await work almost every time.

So when you hit the stop button on an agent and it keeps posting tool calls for another few seconds, that is a cancellation design decision surfacing. When you cancel a research agent and later discover it charged you for API calls that happened after you cancelled, same story. When an agent framework works fine in Python and behaves subtly differently after someone ports it to TypeScript or Rust, the port may be correct line for line and still wrong, because the two keywords do not carry identical promises across the border.

None of that is sloppiness by framework authors. It is the consequence of a shared vocabulary hiding unshared semantics. The nine dimensions are a way of naming what varies, so that a disagreement can be pointed at instead of merely suffered.

The useful takeaway for non-programmers

You do not need to memorize the dimensions. What is worth carrying around is a mental model: an agent that is “waiting” is not a single thing, and “stop” is not a single thing either. Both are design choices someone made, and they vary.

Practical version, when you are evaluating agent tooling:

  • Ask what happens to in-flight tool calls when a run is cancelled. Vague answers are a signal.
  • Treat cancellation as a feature to test, not a guarantee to assume.
  • Be skeptical of claims that a framework was ported across languages with identical behavior.
  • When timing bugs appear only under load, suspect the concurrency model before suspecting the model itself.

The paper is aimed at language designers, and its reception so far has been modest, a handful of points on Hacker News. Yet the underlying point travels well beyond compiler circles. We built a shorthand for waiting, agreed it was simple, and moved on. The people who study it closely keep finding that the simplicity was mostly in the spelling.

🕒 Published:

🎓
Written by Jake Chen

AI educator passionate about making complex agent technology accessible. Created online courses reaching 10,000+ students.

Learn more →
Browse Topics: Beginner Guides | Explainers | Guides | Opinion | Safety & Ethics
Scroll to Top