arcie.
++

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

typeKey data fields
session.startedsessionId, runtime? (agentId, modelId, arcieVersion)
turn.startedsequence, turnId
message.receivedmessage, sequence, turnId
message.appendeddelta, textSoFar, sequence, stepIndex, turnId
message.completedtext (or null), finishReason, …
reasoning.appendeddelta, soFar, …
reasoning.completedtext, …
step.startedsequence, stepIndex, turnId
step.completedfinishReason, usage? (inputTokens, outputTokens), …
step.failedcode, message, …
tool.startedname, input, callId, …
tool.completedname, output, callId, status, error?, …
turn.completedsequence, turnId
turn.failedcode, message, sequence, turnId
session.waitingwait: "next-user-message"
session.completed
session.failedcode, message, sessionId
subagent.calledname, callId, childSessionId, turnId
subagent.completedname, callId, output

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 line

The dev server streams events as newline-delimited JSON (application/x-ndjson) — each line is one StreamEvent. That's exactly what encodeEvent produces.