DromioWorkflow SDK
Workflow SDKAuthoringAPIWorkflow Apps & Harnesses

Expose and operate

Workflow AppsGUI, CLI, TUI, and SVGExecution and durabilityEvents and traces

External harnesses

Architecture and setup
Expose and operate
Workflow Apps
GUI, CLI, TUI, and SVG
Execution and durability
Events and traces
External harnesses
Architecture and setup

Events, traces, and artifacts

Every run retains structured EventRecord objects and can stream them through an onEvent sink. CLI, TUI, GUI, and SVG surfaces project the same facts.

Consume events​

const session = await reviewWorkflow.start({prompt}, {
onEvent(event) {
console.log(JSON.stringify(event));
},
});

const failures = session.events.filter((event) =>
event.type === "step.failed" || event.type === "run.failed"
);

The callback may be asynchronous. If you provide a LoopStore, the runtime also calls appendEvent() and saves session status as events are emitted. Application telemetry should index at least runId, type, stepId, attempt, timestamp, and trace identifiers.

Event record shape​

type EventRecord = {
type: string;
message: string;
runId: string;
correlationId: string;
index: number;
timestamp: string;
stepId?: string;
attempt?: number;
detail?: unknown;
trace?: TraceContext;
};

index is monotonic within a run and survives snapshot hydration. Treat event records as execution facts; do not mutate them into a second runtime state. Run-level events use a run/event correlation identifier; step events use the stable run:<runId>:step:<stepId>:attempt:<n> attempt correlation, which groups facts emitted by that attempt. traceId joins the wider run trace, while spanId identifies one traced operation.

Common event families​

FamilyExamples
Runrun.started, run.completed, run.failed, run.paused, run.cancelled
Stepstep.created, step.started, step.retrying, step.waiting, step.completed, step.failed
Hookhook.created, hook.waiting, hook.resumed, hook.cancelled; delegation uses handoff_requested metadata
Questionquestion.requested, question.answered
Modelmodel.request.started, model.response.delta, model.response.completed, model.request.failed
Evaluationindividual judgment evidence, canonical scores, score bars, policy facts, and gate decisions
Compositionrouter selection, child lifecycle, fork branches, join, and iteration
Artifactartifact.created with a registered output reference
Checkpointcheckpoint.created before a step attempt

Consumers must tolerate new event types during beta and should switch on the types they understand instead of treating unknown events as errors.

Trace ancestry​

type TraceContext = {
name: string;
traceId: string;
spanId: string;
parentSpanId?: string;
status?: "unset" | "ok" | "error";
kind?: "internal" | "producer" | "consumer" | "client";
attributes?: Record<string, boolean | number | string | Array<boolean | number | string>>;
};

The run ID anchors the trace. Every step attempt receives distinct identity, so a retry does not overwrite the prior attempt. Model calls, child workflows, router routes, fork branches, and iterations retain parent ancestry.

A delegated child workflow retains child run, workflow, step, attempt, trace, and parent identity in its handoff. Resumption attribution belongs on the hook.resumed event source; it is not copied into workflow business state. Workflow App thread integrations may additionally emit one deduplicated run.suspended notification when a run first becomes waiting.

Register artifacts​

const writeNote = step({
id: "notes.write",
input: {note: noteSchema},
output: {path: z.string()},
async run({artifacts, input}) {
const path = "note.json";
await Bun.write(path, `${JSON.stringify(input.note, null, 2)}\n`);
artifacts.file({mediaType: "application/json", path});
return {path};
},
});

Registration makes the file visible to Workflow App renderers. It does not write the file, upload it, or grant access; the owning step and host remain responsible for storage, redaction, retention, and authorization.

Operate from facts​

Alert on terminal failures and persistence errors, not renderer labels. Use the compact renderer for routine operation and raw event records for diagnosis. Model deltas are public response progress; the SDK does not expose private reasoning. Redact sensitive input and provider output before exporting events outside the trust boundary.

On this page

  • Event families
  • Trace ancestry
  • Observable model steps
  • Register artifacts
  • Renderer projection