Domain Events & SSE
All agent output flows through a unified event pipeline: backend JSONL lines are parsed into ParsedEntry objects, converted to DomainEvent dataclasses, serialized to SSE-compatible dicts, and streamed to the browser via EventSourceResponse. The same event model is used for single-agent chats, group chats, and scheduled tasks. Defined in web/domain_events.py.
CLI Subprocess stdout JSONL line {"type":"assistant",...} Backend Parser parse_entries(raw, pending) backends/*/backend.py ParsedEntry role, text, content_type backends/base.py DomainEvent dataclass hierarchy web/domain_events.py SSE Dict {event, data} domain_event_to_sse() Browser EventSource SSE stream For group chats: store.broadcast_raw(event) pushes to SSE subscriber queues. For web chats: yield from async generator inside EventSourceResponse.
Event Catalog
DataclassSSE EventData FieldsUsed In
AgentStarted started session_id, agent_type Web chat
TextDelta text_delta text, agent_type All flows
ThinkingDelta thinking thinking, agent_type All flows
ToolInvocationStarted tool_use_start tool_name, tool_use_id, input, agent_type All flows
ToolInvocationCompleted tool_result tool_use_id, result, is_error, agent_type All flows
AgentCompleted completed usage (dict), success, session_id, agent_type Web chat, scheduled
AgentError error message, error_type, agent_type All flows
AgentStatus agent_status agent_type, status (idle|listening|responding|dead) Group chat only
GroupMessagePosted group_message sender, content, sequence, thread_id, mentioned_agent Group chat only
MessageReaction reaction reactor, sequence, emoji, action (add|remove) Group chat only
MessageReadReceipt read_receipt reader (agent_type), sequences (int[]) Group chat only

Serialization

domain_event_to_sse(event) returns {"event": "...", "data": "..."} where data is a JSON string. The SSE event name maps directly to the frontend's EventSource listener names. Agent type is included in the data payload when present (for group chat multi-agent disambiguation).

Group Chat Events

Group chats emit additional events beyond the agent execution events: group_message when any participant posts, agent_status on state transitions, reaction for emoji reactions, read_receipt when agents consume messages. These are broadcast via GroupChatStore._broadcast_sse() to all SSE subscriber queues.

Usage Dict Fields

The AgentCompleted.usage dict varies by backend:

  • All: input_tokens, output_tokens, tokens_remaining_pct, context_window
  • Claude: + cost_usd, duration_ms, duration_api_ms, num_turns, stop_reason, cache_read/write_tokens
  • Codex: + cached_input_tokens, tool_calls count, num_turns
  • Gemini: + cached_tokens, duration_ms, tool_calls count