Interfaces

Agent action patterns: who has the turn?

An agent that only answers needs one screen. An agent that sends emails, edits records and drives a browser needs a clear answer, at every moment, to one question: who is acting right now?

Author
Interfaces teamDesign engineering
Published
Reading time
12 min
TL;DR
  • Every moment in a session has exactly one owner: the agent, the person, or nobody.
  • We design every hand-off as one of five patterns: Ask, Approve, Watch, Take over, Background. Each has its own states, and each state looks the same everywhere the session appears.
  • A waiting agent must never look busy, and a busy agent must never look done.

The question

Chat interfaces were built for a simple rhythm: you write, the model writes back, repeat. The person always knows whose move it is, because the only move is typing.

Agents broke that rhythm. A single request like “clean up the Q3 pipeline” can turn into fifty tool calls, a clarifying question, an email that needs sign-off, a browser session on a CRM, and a long-running job that finishes after you have closed the tab. In between, people kept asking us the same thing in different words: is it doing something, or is it waiting for me?

We stopped treating this as a loading-state problem and started treating it as an ownership problem. At any moment, exactly one party holds the turn: the agent is acting, a person is expected to act, or nobody is, because the work moved to the background. Figure 1 shows one ordinary session through that lens.

Fig. 1
100%
Timeline of one session showing the turn moving between person, agent and nobodyThree lanes: Person, Agent and Nobody. In order: the person sends a prompt; the agent plans and reads; the person answers an Ask; the agent drafts; the person approves; the agent acts while the person watches; the person takes over; the agent resumes; the work moves to the background, owned by nobody, while the chat stays usable; finally the person is notified. Exactly one lane owns the turn at every moment.PersonAgentNobodypromptplans, readsAskdraftsApproveWatchTake overresumesBackgroundnotifiedperson watchesturn free, chat usabletime →one owner at every moment
One session, three lanes. The turn moves between the person and the agent, and sometimes to nobody. Every lane change is a hand-off the interface has to make obvious.
Fig. 1One session, three lanes. The turn moves between the person and the agent, and sometimes to nobody. Every lane change is a hand-off the interface has to make obvious.

Five patterns

We went through every hand-off in the product and grouped them by two properties: who holds the turn, and what returns it. Five patterns covered everything. Step through them below. The left side is a simplified version of the real component; the right side is the state machine behind it.

Fig. 2 · interactive
100%
Send the Q3 churn summary to the leadership list.
I drafted the summary from the three dashboards. It is ready to send.
● Waiting for yousend_email
To leadership@acme.com (14 recipients)
Subject Q3 churn: summary and next steps
Approve & sendEdit draftDecline
The agent is paused. Only this card moves the session forward.
Turn owner: Person
The five patterns. Click a tab, then step through the states or press autoplay. The interface on the left only ever shows the state on the right.
Fig. 2The five patterns. Click a tab, then step through the states or press autoplay. The interface on the left only ever shows the state on the right.
PatternTurn ownerWhat returns the turnTypical wait
AskPersonAn answerseconds to hours
ApprovePersonApprove, edit or declineminutes to days
WatchAgentThe agent finishes, or the person interruptsseconds to minutes
Take overPersonHand backminutes
BackgroundNobodyA result, delivered as a new messageminutes to hours

Ask and approve

Ask and Approve look alike: the agent stops and a card appears. The difference is what the person is deciding. With Ask, the agent lacks information (“which field means at risk?”). With Approve, it has everything and needs permission for an effect it cannot take back: sending an email, writing to a system of record, spending money.

Our first approval card looked like any other assistant message, so people scrolled past it and assumed the agent had stalled. The fix was not a louder colour. We made the card the only place where the session can move forward, and made every other surface say so: the composer, the sidebar entry and the tab title all switch to the same “Waiting for you” state.

Design principleA waiting agent must never look busy, and a busy agent must never look done.
Fig. 3
100%
Annotated approval card for sending an email to 14 recipients
Anatomy of an approval card. Every element answers one question the person has before they press the button.
Fig. 3Anatomy of an approval card. Every element answers one question the person has before they press the button.

Two details mattered more than we expected. First, the answer to a question is the tool result, not a new chat message. The agent continues the same turn with the answer in hand, instead of starting over and re-deriving its plan. Second, an approval can wait a long time. People approve on their phone the next morning, or after the weekend. The card has to look exactly the same on day three as it did in the first minute, which turned out to be a backend problem as much as a design one.

Watch and take over

Computer use adds a new kind of hand-off. The agent operates a real desktop with a shared browser, and anyone with access to the thread can open a live view of it. Watching is the default; taking over is one click away.

In Watch, the agent holds the turn and the person is an observer. The hard part is motion. An agent acts in bursts: three clicks in 200 ms, then nothing for two seconds while it reads the page. Rendering each action literally looks like flicker. We animate an agent cursor instead: each action glides for 80 to 150 ms depending on distance, clicks get a ripple, and actions without a position get a short label. The cursor is never allowed to trail the real action by more than 150 ms. If a burst arrives faster than we can glide, the in-between clicks ripple in place and the cursor jumps to the newest position.

Constraint The agent never depends on a viewer. Everything it needs to observe and act works with nobody watching. The live view is for people.

Take over is the reverse. Sometimes the agent asks for it (“enter the SSO code”), sometimes the person simply grabs the mouse. In both cases one arbiter in the sandbox decides who may send input, and the person always wins. While a person holds the control lease, the agent’s input is refused and its script waits. When they hand back, the script continues in the same turn.

Fig. 4
100%
Agent scriptControl leasePerson (viewer)click · type · clickagent input refused · script waitsagent permitperson holds the leaseagent permitkeyboard + mouseTake overHand backon a person’s own Mac: lease returns after 5 s idle
One arbiter, one control lease. The agent acts under a permit; a take-over moves the lease to the person and the agent’s input is refused until they hand back.
Fig. 4One arbiter, one control lease. The agent acts under a permit; a take-over moves the lease to the person and the agent’s input is refused until they hand back.

Background

Some work is simply long: re-running a model over every campaign, a workflow that polls an external system, a sub-agent researching a market. Holding the turn for forty minutes would block the chat for no reason.

In the Background pattern, nobody holds the turn. The agent commits a placeholder (“Running in the background”), finishes its turn, and the chat is free. When the result arrives, it shows up as a new message in its own turn. Two rules keep this predictable:

  • A background call belongs to the session, not the turn. Stopping or steering the current turn does not cancel it. Each background call has its own stop control.
  • Sending to background works at any time. A call that started synchronously can be moved to the background while it is still running, or while it is waiting at an approval.

The agent does not decide which mode a call runs in, and neither does the tool. The runtime does. That keeps the interface simple: the same tool can appear as a waiting card or as a background card, and the person can move it from one to the other.

What we learned

  • Name the owner, not the activity. “Waiting for you” is more useful than any spinner, because it tells people what to do.
  • One state, every surface. If the card says waiting and the sidebar says running, people believe the sidebar.
  • Design the long wait first. The card that has been open for three days is the one that breaks. Treat time as a design input.
  • Share vocabulary with the engine. Turns, hand-offs and background calls exist in our backend with the same names. Design reviews and design docs now read the same way.

The five patterns are not finished. Approvals reviewed by another model, and agents that ask other agents, will add new hand-offs. But the question stays the same, and so does the answer we design for: at every moment, someone has the turn, and the interface says who.

Want to work on problems like this? We’re hiring