Skip to content

Streaming

Discriminated union of 9 event types:

type AgentStreamEvent =
| { type: 'turn_start'; userMessage: string }
| { type: 'llm_start'; iteration: number }
| { type: 'thinking'; content: string }
| { type: 'token'; content: string }
| { type: 'llm_end'; iteration: number; toolCallCount: number; content: string; model?: string; latencyMs: number }
| { type: 'tool_start'; toolName: string; toolCallId: string; args: Record<string, unknown> }
| { type: 'tool_end'; toolName: string; toolCallId: string; result: string; error?: boolean; latencyMs: number }
| { type: 'turn_end'; content: string; iterations: number; paused?: boolean }
| { type: 'error'; phase: 'prompt' | 'llm' | 'tool' | 'message'; message: string };
await agent.run('Hello', {
onEvent: (event: AgentStreamEvent) => {
// handle events
},
});

Format events for Server-Sent Events:

import { SSEFormatter } from 'agentfootprint/stream';
// Single event
const sse = SSEFormatter.format(event);
// "event: token\ndata: {"type":"token","content":"Hello"}\n\n"
// Batch of events
const batch = SSEFormatter.formatAll(events);

Multi-subscriber event dispatcher with error isolation:

import { StreamEmitter } from 'agentfootprint/stream';
const emitter = new StreamEmitter();
// Subscribe — receives all AgentStreamEvents
const unsubscribe = emitter.on((event) => {
if (event.type === 'token') console.log(event.content);
if (event.type === 'tool_start') console.log(`Running ${event.toolName}...`);
});
// Dispatch events from agent run
await agent.run('Hello', {
onEvent: (event) => emitter.emit(event),
});
// Unsubscribe when done
unsubscribe();