Streaming

Agents and graphs emit a shared AiEvent stream. Pipe it to SSE, websockets, logs, or OpenTelemetry.

Agent SSE

sse.ts
reply.hijack();
reply.raw.writeHead(200, {
  "content-type": "text/event-stream",
  "cache-control": "no-cache",
  connection: "keep-alive",
});

for await (const ev of bot.stream(message)) {
  reply.raw.write(`data: ${JSON.stringify(ev)}\n\n`);
}
reply.raw.end();

Event union

events.ts
type AiEvent =
  | { type: "run_start"; runId: string; kind: "agent" | "graph"; name: string }
  | { type: "text"; runId: string; text: string }
  | { type: "tool_call"; runId: string; toolCall: AiToolCall }
  | { type: "tool_result"; runId: string; toolCallId: string; name: string; content: string }
  | { type: "node_start"; runId: string; nodeId: string; nodeType: string }
  | { type: "node_end"; runId: string; nodeId: string; output?: string }
  | { type: "interrupt"; runId: string; nodeId: string; prompt: string }
  | { type: "handoff"; runId: string; from: string; to: string }
  | { type: "error"; runId: string; error: string }
  | {
      type: "run_end";
      runId: string;
      status: "completed" | "failed" | "waitingInterrupt" | "handed_off" | "aborted";
      result?: JsonValue;
    };

Helpers

helpers.ts
import { collectEvents, tapEvents, createOtelListener } from "@monorch/ai";

const events = await collectEvents(bot.stream("hi"));

for await (const ev of tapEvents(bot.stream("hi"), createOtelListener())) {
  // same events, plus OTel side effects
}

FAQ