Event types¶
An event is one entry in a task session's event stream: a message, a typed category, a severity, and optional structured fields. The event stream concept page explains the stream mechanics (one stream per session, the verbatim tail plus rolling summary, how snapshots reach the model). This page is the per-type catalogue: what each EventType value means, what fields an event record carries, and how consumers route on them.
The type is a closed set. It is defined as the EventType enum in agent_core/core/event_stream/event.py and has exactly 13 values. Consumers route on this field and never on message text.
Event types¶
The "UI render" column describes what the browser event transformer (app/ui_layer/events/transformer.py) produces for each type. The "Conversational" column marks the two types recorded into the cross-task conversation buffer (record_conversation_message) that injects recent dialogue into new tasks. Everything else is stream-only or transient.
EventType |
Emitted when | UI render | Conversational |
|---|---|---|---|
user_message |
A message arrives from you, entered locally or routed from a connected platform. | Shown as a chat bubble, emitted directly by the controller. The transformer suppresses the stream echo to avoid a double render. | Yes |
agent_message |
The agent sends a chat reply (the send_message action). |
Chat bubble. | Yes |
system |
The harness posts a notice: a status change, a warning, or a loop-detection notice upgraded to system. |
System notice line. | No |
error |
The agent surfaces a failure worth showing. | Error notice line. | No |
reasoning |
The LLM emits its rationale for the next action(s). | Reasoning block, keyed so repeated updates group together. | No |
action_start |
Immediately before an action runs. | Action row opens. Suppressed when action_name is an internal control action (task_start, ignore). |
No |
action_end |
After an action finishes. | Action row closes; status is read from action_output["status"], not from message text. Suppressed for the same internal action names. |
No |
task_start |
A task is created. | Task-start marker. | No |
task_end |
A task finishes. | Task-end marker carrying task_status (completed, error, or cancelled). |
No |
waiting_for_user |
A task pauses for your reply or approval. | Waiting indicator on the task. | No |
relevant_memories |
Memory retrieval injects recall pointers into the stream. | Hidden. It is context for the model, not for you. | No |
todos |
The task's todo list changes. | Hidden by the transformer; the checklist renders from task state on a separate path. | No |
internal |
Bookkeeping the agent records for itself. | Hidden. | No |
Every type above is documented; the enum contains no others. Producers must pass event_type explicitly at log() time. An event that reaches the transformer with no event_type renders as nothing, which flags an unmigrated producer.
Event record fields¶
Each event is an Event dataclass. The stream wraps it in an EventRecord that adds timing and a repeat counter. Fields, from the source:
| Field | Meaning |
|---|---|
message |
The full event payload used for prompts and debugging. Oversized messages are externalized to a temp file and replaced by a pointer, so a single huge payload cannot bloat every later turn. |
kind |
A human-readable label for the prompt-facing snapshot (for example agent message to platform: Telegram). Free text. Not used for routing. |
severity |
One of DEBUG, INFO, WARN, ERROR. Unknown values fall back to INFO. |
display_message |
An optional shorter or friendlier string for the UI. The full message stays intact for the model and for logs. |
ts |
Creation timestamp, stored in UTC and rendered in local time in compact lines. |
event_type |
The closed-set category from the table above. The one field consumers route on. |
action_name |
Canonical action identifier, set on action_start and action_end. None otherwise. |
action_display_name |
User-facing action name. Consumers fall back to a title-cased action_name when it is absent. |
action_id |
Stable identifier shared by an action's start and end events so they correlate without parsing. |
action_input |
Structured input payload on action_start. |
action_output |
Structured output payload on action_end, including the status key the UI reads. |
task_status |
completed, error, or cancelled on task_end. |
platform |
Originating or destination platform for chat messages (for example Telegram, CraftBot Interface). |
repeat_count |
On the wrapping EventRecord: how many identical consecutive occurrences collapsed into this record. Defaults to 1. |
Action event pairing¶
An action_start and its action_end share the same action_id. That id is generated by the action manager (as run_id) and set on both events, so a consumer can match a start to its end even when several copies of the same action run at once and finish within the same second. Without the shared id, two parallel web_search calls would be indistinguishable by name and timestamp alone.
Two details follow from routing on structured fields rather than text:
- Status comes from the payload.
action_endclassification readsaction_output["status"] == "error". The message string is never inspected, so an action whose output text happens to contain the word "error" is not miscoloured. - Internal actions stay hidden.
action_startandaction_endwhoseaction_nameistask_startorignoreproduce no UI row. They are control flow, not user-visible work.
Repeated identical events do not each get their own record. When the same event recurs, the stream increments repeat_count on the existing EventRecord instead of appending a new one. The compact line renders the count as an xN suffix, so a stall that logs the same notice fifty times reads as one line with x50 rather than fifty lines.
Event routing and legacy upgrade¶
The routing contract is a single dispatch on event_type. The transformer holds a table mapping each EventType to one builder and consults nothing else. It must not read kind or message substrings to decide which UI event to make, whether to hide an event, or how to classify a status. This rule exists because the older substring approach hid a legitimate chat message that contained the word "Ignored" (it matched "ignore" in message_lower). Adding a new UI variant means adding an EventType value and a dispatch entry, never a new string check at a call site.
Persisted events written before event_type existed have no value for that field. They are upgraded once at load time in Event.from_dict(), which maps the old free-text kind to a type through _legacy_event_type_from_kind. A sample of that map:
Legacy kind |
Upgraded event_type |
|---|---|
action_error |
action_end |
task_started / task_ended |
task_start / task_end |
agent reasoning |
reasoning |
warning, loop_detection_warning |
system |
agent message ... (prefix) |
agent_message |
user message ... (prefix) |
user_message |
This path is for restored data only. New code sets event_type at log() time and never calls the legacy mapper. Once all persisted data has rolled over, the map and its helper can be removed.
Events and the memory buffer¶
Every event is also appended to EVENT.md, the complete on-disk history. A subset is additionally staged in EVENT_UNPROCESSED.md, the buffer the memory pipeline distills. Routine event kinds the memory processor would always discard are filtered out at write time by SKIP_UNPROCESSED_EVENT_TYPES (in agent_core/core/impl/event_stream/manager.py), so the buffer holds only dialogue and meaningful state changes.
The filtered kinds are action_start, action_end, reasoning, todos, error, waiting_for_user, and relevant_memories. Task boundaries (task_start, task_end) are intentionally left in the buffer. Separately, the memory-processing task itself is named in SKIP_UNPROCESSED_TASK_NAMES, so its own events never write to the buffer and cannot loop back into the next distillation run.
Next¶
- Event stream: the concept, the tail-plus-summary mechanics, and on-disk files.
- Default actions: the actions that produce
action_startandaction_end. - Memory: how buffered events become long-term recall.
- Agent MD files: the schema of
EVENT.mdand the other files underagent_file_system/.