Skip to content

Agent events

Agent events answer more than “what happened”: before a side effect occurs, they can also decide whether it should happen at all. Every Agent’s EventBus supports both observation and synchronous intervention.

Kind Purpose How to get it Can it intervene?
AgentEvent Coordinate and intercept the current execution agent.events.on(...) Yes: modify fields or set decision
StreamEvent Deliver output to the caller Iterate the stream from agent.run() Yes: closing the stream ends the Run
TapeEntry Keep the history Query the Tape No: normal recording only appends

The three never convert into each other automatically: stream output is not written to disk on its own, and Tape entries do not flow back into the Step that is running. Only the entries TapeContext selects become input to later model calls.

emit() calls each matching handler in registration order, and waits for an async handler to finish before it continues. Four rules are worth remembering:

  1. A handler registered for a base class also receives its subclasses.
  2. Return values are ignored; to steer execution, change event fields or set decision.
  3. Exceptions propagate to the publisher and may fail the whole Run.
  4. event.stopped is checked before every handler, and True ends delivery for that emit.

Before-call events expose a replaceable request and a decision. One tool call has four possible outcomes:

Action Does the original tool run? What the model receives
No decision Yes The real result
Replace event.call Yes, with the new call The real result
deny(message) No A tool error
replace(result) No The given result

A denied or replaced call still emits ToolCallFinished, so logic that observes completed calls never misses it. Model calls follow the same before-call intervention model: for example, LLMCallDecision.finish(text) can produce text without calling the provider.

Agent events intervene in the model calls, tool calls, Steps, and Runs of the core loop; application hooks cover the application lifecycle — Turn stages, tool supply, storage, and channels — and carry plugin distribution. Application interception hooks can join the same set of Agent events through an adapter, but the two differ in how they return arguments and in their exception policy, as the Hooks reference details. For how to write each, see SDK: events and Plugins and Hooks: intercept a model or tool call.