agent.stream() returns; see Streaming.
Queued input
run.enqueue(input) adds user input (a string, content parts or a
Message[]) to a run that is still going, for example a follow-up the user
types while the agent works. The run does not stop: the input joins the
transcript at the next safe point - after the current step’s tool results,
never between a tool-call turn and its results - and the next model call sees
it, as if the user had typed it. Input queued while the model writes its final
reply gets one more step, so the model answers it in the same run.
enqueue() returns { id, applied }. id is on the input.queued and
input.applied events. applied is false when the run had already
finished: the input was not taken, so send it yourself, as a new turn
(session.send()). Otherwise it is a promise that resolves to true once the
input is in the transcript, or to false when the run stopped before its next
model call (aborted, paused for approval, out of maxSteps or budget, or
failed); the input is then left to you too.
- Several inputs queued before the same model call are applied together, in the order they were queued.
- With checkpointing (
sessionIdor a durable session), an input that is still waiting is saved at the end of the run’s checkpoint right away, the same slot as input queued behind unanswered tool calls (see Durable execution). A crash, or a run that fails, does not lose it:agent.resume()applies it (appliedof a run that failed in-process still resolvesfalse). A run that finishes, pauses or is aborted does not keep it. - Without a stream, pass an
InputQueueasExecuteOptions.inputQueueand call itspush(): the same queue that is behindrun.enqueue(). One queue serves one run. - In a session,
agent.session({ turnPolicy: 'queue' })makes asend()orstream()made while a turn runs (or waits to start) join that turn this way. See Sessions.
Advanced: the executor API
Without a stream, pass anInputQueue to AgentExecutor.execute() (see
the executor API):
Steering
run.steer(input) redirects a running run to new user input, for example when
the user changes their mind while the agent is still thinking:
- If a model call is in flight and has not emitted text or tool calls yet, it
is aborted (with a signal of its own, not the run’s: the run goes on), its
partial output is discarded,
inputis appended as a user message and the model is called again.appliedis'immediate', and the aborted call’s step ends withstep.done'steered'. A provider that ignores the abort signal is not waited for; its late reply is dropped. - If the model has already emitted text (or tool calls),
inputwaits for the next safe point likeenqueue():appliedis'queued'. - Tool calls already running finish and their results are kept; calls of that turn that have not started yet are not run and get the usual “cancelled before it ran” result. Then the input is applied.
appliedisfalseonce the run has finished: send the input as a new turn.
steer() returns { id, applied, joined }: id is on the input.steered and
input.applied events, and joined is a promise of whether the input made it
into the transcript (as enqueue()’s applied). The aborted call counts as a
step of maxSteps. With checkpointing, the input is saved at the end of the
checkpoint as soon as it is taken and before the model is called again, so a
crash during the redirect does not lose it; the discarded partial turn is never
checkpointed. Without a stream, call steer() on the run’s
ExecuteOptions.inputQueue. In a session, agent.session({ turnPolicy: 'steer' })
makes a send() or stream() made while a turn runs steer that turn (see
Sessions).