ARES

RFC: WebUI Pending Intent Controls

RFC Positioning

This RFC is a child RFC under the Ares WebUI Live-to-Final product line.

The Live-to-Final parent RFC defines how a running agent turn moves from live process, tool activity, recovery state, and replay into a settled final answer or terminal outcome.

This RFC covers one specific part of that model: what user input means when the agent is already busy. In that state, a new user input must be interpreted clearly as Queue, Steer, or Stop-and-send.

This RFC does not redefine the whole Live-to-Final model. It defines the product semantics for user intervention during an active run.

Problem

Ares WebUI currently treats user input during a running agent turn as one of three busy modes: Queue, Interrupt, or Steer. These look like equivalent send modes, but they are not the same kind of action.

Queue means: wait, then send this as the next normal user turn.

Steer means: guide the currently running turn without starting a new turn.

Interrupt is currently a compound behavior: queue the message, cancel the current run, then drain the queued message as the next turn. It is not a simple send mode.

This mixed model has caused real failures:

This RFC defines a clearer pending-intent model for user input while the agent is busy.

Terms

Queue

Queue means the user submitted a message while the agent is running, but the message does not affect the current run. It waits until the current run ends, then sends as the next normal user turn.

Queue belongs to the current session.

Steer

Steer means the user submitted mid-run guidance. It is delivered to the current active run so the run can use it in later processing.

In the UI, Steer should render like a normal user message. In runtime semantics, it is not the next normal user turn. It is mid-run input for the active run.

Steer belongs to the current active run.

Stop

Stop means the user stops the current active run. Stop by itself does not send a new message.

If the current session has a waiting Queue message, Stop may be upgraded into Stop-and-send.

If the current run has already received a Steer, Stop only stops that run. The delivered Steer does not automatically become Queue and is not sent as the next turn.

Stop-and-send

Stop-and-send means there is already a waiting queued message, and the user chooses to stop the current run and send that queued message as the next normal user turn.

Stop-and-send is an upgrade action for Queue.

Interrupt

Interrupt is a legacy term from the current implementation and older UI copy. It was previously treated as a default busy send mode, but its behavior is closer to Queue + Cancel + Send.

This RFC no longer defines Interrupt as a user-facing default busy mode. If the term remains, it should be legacy/internal wording or an implementation detail of Stop-and-send.

Settings Model

Current Settings expose Default message mode with three choices:

This puts Queue, Interrupt, and Steer at the same level, as if they were equivalent default send modes.

This RFC proposes replacing that with:

The setting should only decide what happens when the agent is running and the user directly sends new input: either queue the input, or deliver it as Steer.

Interrupt current turn should no longer appear as a default busy mode. Its capability is represented by Stop-and-send when a waiting Queue message exists.

Legacy migration:

The reason is that old interrupt combined two behaviors: it preserved the new input as the next user turn and cancelled the active run. Migrating those users to Steer would preserve urgency, but it would drop the cancel-and-send part of their old intent. Queue by default is the safer migration because it never injects a message into the active run without an explicit Steer action.

If the user explicitly wants to stop the current run and send a waiting queued message, they can use Stop-and-send. Stop-and-send is the explicit replacement for the old cancel-and-send behavior that interrupt tried to provide.

Composer Interaction Model

When the agent is idle, Composer keeps the existing behavior:

When the agent is busy:

Queued messages should appear as a compact strip/card attached above Composer, reusing the existing Terminal collapsed-card pattern.

The queued strip should:

The right side should expose icon controls:

Edit moves the queued message back into Composer for editing.

Steer upgrades the queued message into Steer. After success, it disappears from the queued strip and appears in the transcript/live area as a user Steer message.

Open questions:

Steer Live-to-Final Rendering

Steer is not only a temporary live UI state. It must preserve meaning in both live and settled views.

Live phase

Steer renders like a normal user message.

It visually inserts into the middle of the current assistant live run. It splits the visible Assistant Worklog, but does not stop the active run. Assistant Worklog continues after the Steer.

The Worklog should show explicit feedback, such as “guidance received,” or equivalent natural assistant process text.

A Steer message is user-visible because it is user-authored input, not an internal recovery or runtime-control prompt. It renders like a user message, but it remains metadata-marked as Steer so replay and settled Worklog do not treat it as a normal next-turn user message.

Settled phase

Steer must not disappear after Final Answer appears.

The collapsed Activity / Worklog must retain Steer as a timeline boundary. Expanding Worklog should show what happened before Steer, what the user sent, what happened after Steer, and how the final answer followed.

A delivered Steer is not a running-only marker. It is part of the causal timeline of the active run, so it must remain visible or inspectable after settle.

Steer must not exist only as a toast or transient DOM state. It must survive refresh, session switch, replay, and settled render.

Relationship to system control events

Steer is similar to system-delivered control events such as tool-iteration-limit notices. The difference is source:

Both are causal timeline events. Neither is the final answer. This RFC only defines the user-delivered Steer side; tool-limit terminal semantics remain owned by the Live-to-Final / terminal-state track.

State Ownership

Queue belongs to the session.

A queued message must stay bound to the session where it was created. It must not drain into another session after session switch, refresh, or background completion.

Queue is waiting intent until drained. It should not render as an already-sent normal user message before dispatch.

Steer belongs to the active run.

Once delivered, Steer is no longer Queue. It cannot be edited, deleted as pending Queue, or used for Stop-and-send.

Steer renders like a user message, but metadata must preserve that it is Steer, not a next-turn user message.

Stop belongs to the active run.

Stop only stops the active run unless the interaction clearly becomes Stop-and-send.

Stop-and-send involves two objects:

It must preserve order:

  1. mark the queued message as the next user turn
  2. request cancellation of the active run
  3. wait until the session is safe
  4. send the queued message
  5. never show a user message in WebUI that the Agent durable conversation did not receive

Durability And Recovery

Pending intent must not be only current-page UI state.

Queue requirements:

Steer requirements:

Stop-and-send requirements:

Replay should rebuild the same causal timeline:

  1. run start
  2. Worklog
  3. user intervention
  4. runtime acknowledgement or handling
  5. terminal state
  6. final answer or error state

Recovery after replay does not need to reproduce every live animation, but it must preserve event order and meaning.

Leftover Steer

Leftover Steer is a Steer that could not be consumed by the active run before that run ended.

The RFC distinguishes three cases:

WebUI must not silently discard leftover Steer. It also must not claim the runtime applied the Steer without Agent/TUI Gateway evidence.

Runtime Boundary

This RFC defines product semantics, not a permanent WebUI-private runtime protocol.

This boundary is necessary because Ares WebUI also has the #1925 RuntimeAdapter direction. The RuntimeAdapter contract moves WebUI toward clearer runtime interfaces instead of permanently owning all Agent runtime behavior directly. Ares Desktop / TUI Gateway already exposes related surfaces such as session.steer, session.interrupt, active session status, and event streams.

WebUI may own:

WebUI should not invent:

Delivered vs Applied:

WebUI may claim delivered. WebUI must not claim applied without Agent/TUI Gateway evidence.

Implementation Slices

Each slice must satisfy this RFC and the Live-to-Final parent requirements around live rendering, settled Worklog, replay/recovery, and final answer boundary.

Slice 1: RFC and routing update

Slice 2: Queue durability

Slice 3: Steer delivered visibility and replay

Slice 4: Stop-and-send UI

Slice 5: Agent-side Steer applied / tool boundary

Testing Expectations

Implementation PRs should include focused tests for:

Manual verification should cover desktop, narrow, and mobile composer states when the visible queue/steer/stop surfaces change.

Issue / PR Routing

Open Questions