Skip to main content

Streaming

Normative: MODEL.md §10.

A run is one canonical stream of typed events. Every event carries a common envelope plus its type-specific fields:

{ "run_id": "…", "thread_id": "…", "seq": 7, "ns": [], "type": "node_end", … }
  • seq — monotonic within a run, 1-based, no gaps. A consumer that drops its connection reconnects and skips everything up to its last-seen seq, so a streamed run survives a broken pipe without replaying from the top.
  • ns — the namespace path to the (sub)graph that emitted the event; [] at the root. Always [] today, reserved so subgraphs can tag their events without a breaking envelope change. Filter by graph off ns, not the run id.

Event types​

Every implementation emits these, in this order:

EventWhen
run_startrun begins
step_start { step, tasks }superstep begins
node_start { node, task_id }task begins
custom { payload }ctx.emit(...) — delivered live, mid-superstep
node_end { node, update }task returns
node_error { node, error }task raises
state { channels }after REDUCE
checkpoint { id }after CHECKPOINT
interrupt { pending }run halts on a pause
run_end { status }done · interrupted · error · aborted

interrupt is a distinct event type. Consumers never parse error text or poll graph state to discover a pause — the defect this design exists to remove.

Two consumption styles​

import { graph, channel, START, END, stream, streamModes } from "@ilmek/core";
import type { ChannelMap, StateOf } from "@ilmek/core";

/** Support state — one append-only channel of messages. */
const SupportState = {
messages: channel.append<string>(),
} satisfies ChannelMap;

type SupportState = StateOf<typeof SupportState>;

const g = graph("support", SupportState)
.node("agent", async (state, ctx) => ({ messages: ["hi"] }))
.edge(START, "agent")
.edge("agent", END)
.compile();

const input = { messages: ["hello"] };

// full event stream
for await (const ev of stream(g, input)) console.log(ev);

// projected into LangGraph-style mode views — see the next page
for await (const part of streamModes(g, input, ["messages", "updates"])) { /* … */ }

→ Projection modes · Tokens & cancellation