Listen for events
Use wardrik.listen to process events and save your position. Each handler receives an event
and its cursor. Save the event and cursor in one database transaction, then pass the saved cursor
as after when your app restarts.
This example assumes a configured SDK client, database helpers, and an abort signal:
await wardrik.listen( { "wardrik.run.completed": async (event, cursor) => { await db.transaction(async (tx) => { await tx.insertRun(event.id, event.data); await tx.saveCursor("runs", cursor); }); }, }, { agents: [process.env.AGENT!], after: await db.cursor("runs"), signal },);listenruns handlers one at a time and reconnects automatically. It resolves whensignalaborts.- Delivery is at least once. Key rows by
event.idto skip duplicates.
Display live activity
Section titled “Display live activity”Reply deltas, progress, and activity updates are streamed live and are not stored for replay.
| Shows | Event | Stored |
|---|---|---|
| what it's doing now | wardrik.activity.changed |
no |
| its reply as it streams | wardrik.message.delta |
no |
| a tool's progress | wardrik.tool_call.progress |
no |
| each step, tool call and run | wardrik.step.*, wardrik.tool_call.*, wardrik.run.* |
yes |
for await (const event of agent.streamEvents({ types: ["wardrik.activity.changed"] })) { console.log(event.data.activity.doing.map((doing) => doing.type).join(", ") || "idle");}Activity can change many times per second. Throttle UI updates to keep them readable.
Details
Section titled “Details”wardrik.events.droppedmeans the log was trimmed past your cursor. It's sent regardless of:types.- A cursor grows by about 50 bytes per agent it has read.
- Events lists every event.