Events¶
AgentEvent¶
tau_agent_core.events.AgentEvent
A single event from the agent loop.
Reference: SUBPHASE-0.0.md, "5. Agent Events" section. Reference: docs/SUBMISSION-LIFECYCLE.md, "Provenance on events" (phase 2).
args¶
tau_agent_core.events.AgentEvent.args: dict[str, Any] | None
Tool execution arguments (tool_execution_start)
blocked¶
tau_agent_core.events.AgentEvent.blocked: bool
Whether a tool_execution_end is an extension VETO (S50) —
distinct from a generic errored result, so a front-end can render
"⛔ blocked by
blocked_by¶
tau_agent_core.events.AgentEvent.blocked_by: str | None
The extension that vetoed the call (its runner path label),
paired with blocked on a tool_execution_end; None otherwise.
correlation¶
tau_agent_core.events.AgentEvent.correlation: dict[str, Any] | None
The submission's free-form origin detail (bus subject, cron
id, HTTP request id), carried through unchanged so an embedded server
can fan out to the right stream. None alongside submission_id
(an EMPTY dict would claim "a submission with no correlation data";
None says "no submission stamped this event" instead).
details¶
tau_agent_core.events.AgentEvent.details: dict[str, Any] | None
A tool's structured facts about its own execution on
tool_execution_end — the path it read, the line range, the match
count, the diff. What result holds is what the MODEL reads; this
is what a head can render beside it. None when the tool declared
none, and on every other event type.
end_reason¶
tau_agent_core.events.AgentEvent.end_reason: AgentEndReason | None
How an agent_end closed, as one of "done",
"terminate", "aborted", "max_turns",
"repeat_tool_calls" or "error". None on every other event
type. This distinguishes a loop that finished from one that was cut
short: before it, a run stopped by max_turns emitted the same
agent_end as one where the model simply had nothing more to say,
so a caller could not tell a truncated answer from a complete one.
error¶
tau_agent_core.events.AgentEvent.error: str | None
Why an agent_end closed, when the loop raised rather than
finishing ("RuntimeError: Connection refused"). None on a
normal close; always paired with is_error=True.
is_error¶
tau_agent_core.events.AgentEvent.is_error: bool
Whether this event represents an error
message¶
tau_agent_core.events.AgentEvent.message: dict[str, Any] | None
Message data (agent_start/end, message_*)
messages¶
tau_agent_core.events.AgentEvent.messages: list[dict[str, Any]] | None
List of messages produced (agent_end)
result¶
tau_agent_core.events.AgentEvent.result: Any | None
Tool execution result (tool_execution_*)
source¶
tau_agent_core.events.AgentEvent.source: SubmissionSource | None
The submission's origin ("interactive", "bus", "agent",
…) — pi's InputSource equivalent, so a renderer can decide how to
show a turn (Jupyter's rule: render every source, differently) without
the core knowing any renderer exists. None alongside
submission_id.
submission_id¶
tau_agent_core.events.AgentEvent.submission_id: str | None
The Submission that drove this turn, if any — Jupyter's
parent_header. None for a turn not driven through submit()
(e.g. continue_conversation(), which predates the Submission
contract) — an honest "no submission", never a fabricated id.
submitter¶
tau_agent_core.events.AgentEvent.submitter: str | None
WHO submitted — an extension name, "human", a channel id.
None alongside submission_id.
timestamp¶
tau_agent_core.events.AgentEvent.timestamp: int
Milliseconds since epoch
tool_call_id¶
tau_agent_core.events.AgentEvent.tool_call_id: str | None
Tool call ID (tool_*)
tool_name¶
tau_agent_core.events.AgentEvent.tool_name: str | None
Tool name (tool_*)
tool_results¶
tau_agent_core.events.AgentEvent.tool_results: list[dict[str, Any]] | None
List of tool result messages (turn_end)
turn_index¶
tau_agent_core.events.AgentEvent.turn_index: int | None
Turn number (turn_*)
type¶
tau_agent_core.events.AgentEvent.type: Literal['agent_start', 'agent_end', 'turn_start', 'turn_end', 'message_start', 'message_update', 'message_end', 'tool_execution_start', 'tool_execution_update', 'tool_execution_end']
Event type discriminator
EventBus¶
tau_agent_core.events.EventBus
Central event bus for τ-agent-core.
Provides publish/subscribe for AgentEvents. Used by: - AgentSession (for TUI consumers) - AgentLoop (for emitting events) - Extensions (for event-driven behavior)
Reference: SUBPHASE-0.0.md, "5. Agent Events" section. Reference: PHASE-3-SUBPHASE-0.md EventBus contract.
Constraint: "fire-and-forget" is a failure-isolation contract, not a
scheduling one — see the module docstring. emit awaits each handler
that returns a coroutine before moving to the next, so handlers are
ordered with respect to each other AND to the emitter, and a handler that
suspends suspends the emitter. Subscribers rely on this to pace the agent
loop; do not "optimize" it into create_task.
Contract
class EventBus: def on(self, channel: str, handler: Callable) -> Callable[[], None]: ... def off(self, channel: str, handler: Callable) -> None: ... async def emit(self, event: AgentEvent) -> None: ... async def emit_channel(self, channel: str, args: Any, *kwargs: Any) -> None: ...
emit¶
emit(event: AgentEvent) -> None
tau_agent_core.events.EventBus.emit
Emit an event to all matching handlers.
Handlers subscribed to the specific event type AND to 'all' will receive the event. Handlers are called synchronously. This is an async method to be compatible with async consumers.
Parameters
event: AgentEvent— The AgentEvent to emit.
emit_channel¶
emit_channel(channel: str, *args: Any, **kwargs: Any) -> None
tau_agent_core.events.EventBus.emit_channel
Emit to all handlers on a specific channel.
Parameters
channel: str— Channel name.*args: Any— (no description)**kwargs: Any— (no description)
off¶
off(channel: str, handler: Callable) -> None
tau_agent_core.events.EventBus.off
Remove a specific handler from a channel.
Parameters
channel: str— Channel name.handler: Callable— The handler to remove.
on¶
on(channel: str, handler: Callable) -> Callable[[], None]
tau_agent_core.events.EventBus.on
Subscribe to a channel.
Parameters
channel: str— Channel name (e.g., 'all', 'agent_start').handler: Callable— Callable that receives an AgentEvent.
Returns
An unsubscribe function.
Example
bus = EventBus() def my_handler(event): ... print(event.type) unsub = bus.on('all', my_handler) await bus.emit(AgentEvent(type='agent_start', timestamp=0)) unsub() # Remove subscription
on_error¶
on_error(listener: ErrorListener) -> Callable[[], None]
tau_agent_core.events.EventBus.on_error
Register a listener for handler exceptions. Returns an unsubscribe.
S44 (anchor G3). A notify handler that raises is routed here instead of
being swallowed — the session binds this to the same on_error surface the
:class:~tau_agent_core.extensions.runner.ExtensionRunner uses, so a
failing observer is as visible as a failing mutating hook.
Parameters
listener: ErrorListener— (no description)