- Transport Agnostic - Emit once, deliver via SSE, WebSocket, or HTTP.
- Durable - Events are persisted to storage (SQLite, Postgres, etc.).
- Resumable - Clients can reconnect and automatically replay missed events.
The emit() API
The implementation is simple. Any method in yourAgent subclass can call self.emit():
- event: A string identifying the event type (e.g., “status”, “log”, “chunk”)
- data: A JSON-serializable dictionary with the payload
- Returns: A unique, strictly increasing integer ID for the event
Basic Example
Event Persistence & Replay
One of the most powerful features is Automatic Event Replay. In distributed systems, connections drop. Mobile users lose signal. If an agent emits an event while the user is disconnected, that information is usually lost. ai-query solves this with theenable_event_log flag.
- Every emitted event is saved to the agent’s storage.
- Events are assigned a strictly increasing ID (1, 2, 3…).
- Clients can connect with a
last_event_idparameter. - The server automatically sends all events with
ID > last_event_idbefore sending new ones.
Consuming Events
The way you consume events depends on the transport.Server-Sent Events (SSE)
The recommended way to consume events is via an SSE stream.AgentServer: Exposes a long-running SSE stream atGET /agent/{id}/events.- Serverless/Adapters: Chat streaming is done via
POST /agent/{id}/chat?stream=true. Emitted events are injected into this response stream.
connect)
The connect() client handles SSE transparently for streaming.
WebSocket
If you connect via WebSocket (/agent/{agent_id}/ws), events are sent as JSON messages:
Custom Transports
If you useFastAPI or another framework without our adapters, you can inject a custom handler to deliver events however you like (e.g., to a message queue or a custom socket).