Event Protocol
The typed StreamEvent protocol that runAgent, streamAgent, and arcie dev emit.
Every run produces a stream of typed events. Both streamAgent (which yields
them) and runAgent (which collects them into result.events) speak the same
StreamEvent union, defined in arcie/protocol.
Each event is { type, data } (a couple are payload-less). Every event carries
ordering fields — sequence, turnId, and usually stepIndex — so a consumer can
reconstruct the timarcie.
Event types
Enumerations
type AssistantStepFinishReason =
| "stop" | "tool-calls" | "length" | "content-filter" | "error" | "other";
type ActionResultStatus = "completed" | "failed" | "rejected";Consuming events
Switch on type — the union narrows data automatically:
import { streamAgent } from "arcie/runner";
for await (const event of streamAgent("./agent", "Summarize the news")) {
switch (event.type) {
case "message.appended":
process.stdout.write(event.data.delta);
break;
case "tool.started":
console.log(`→ ${event.data.name}`, event.data.input);
break;
case "step.completed":
if (event.data.usage) console.log("tokens:", event.data.usage);
break;
}
}Constructing and encoding events
arcie/protocol exports constructor helpers and encoders — useful when you build a
host that re-emits the stream. Exported creators include createSessionStarted,
createTurnStarted, createMessageReceived, createMessageAppended,
createMessageCompleted, createStepStarted, createStepCompleted,
createTurnCompleted, createSessionWaiting, and createSessionCompleted.
import { encodeEvent, encodeEvents } from "arcie/protocol";
res.write(encodeEvent(event)); // JSON + "\n" (newline-delimited JSON)
const blob = encodeEvents(events); // many events, one per lineThe dev server streams events as newline-delimited JSON (application/x-ndjson)
— each line is one StreamEvent. That's exactly what encodeEvent produces.