Context

Share state between workflow steps in Node.js

What is Context?

Context is a key-value store shared across all steps in a workflow run. Every step handler receives a ctx object as its second argument, giving each step access to the same shared state.

StateValue Type

All context values are represented by the StateValue type:

type StateValue = string | number | boolean | null | Buffer | StateValue[] | { [key: string]: StateValue };

ctx.set() accepts any JSON-serializable subset of StateValue (everything except Buffer). For binary data, use the dedicated setBytes/getBytes methods described below.

ctx.get() returns Promise<StateValue | null> and now returns data for all StateValue variants, including arrays and nested objects. It no longer silently drops bytes or native data — if a key was stored via setBytes, get() will return the data as a Buffer.

Setting and Getting Values

wf.addStep("store_data", ["blazen::StartEvent"], async (event, ctx) => {
  await ctx.set("user_id", "user_123");
  await ctx.set("doc_count", 5);
  await ctx.set("tags", ["rust", "workflow"]);
  await ctx.set("config", { retries: 3, verbose: true });
  return { type: "NextEvent" };
});

wf.addStep("use_data", ["NextEvent"], async (event, ctx) => {
  const userId = await ctx.get("user_id");     // "user_123"
  const docCount = await ctx.get("doc_count"); // 5
  const tags = await ctx.get("tags");          // ["rust", "workflow"]
  const config = await ctx.get("config");      // { retries: 3, verbose: true }
  return { type: "blazen::StopEvent", result: { user: userId, docs: docCount } };
});

Important: ctx.set() and ctx.get() are async — always use await.

Run ID

Each workflow execution is assigned a unique run ID. Access it from the context:

const runId = await ctx.runId(); // Returns a UUID string

Binary Storage

While ctx.get() now returns data for all value types (including binary), you can still use ctx.setBytes() and ctx.getBytes() for explicit binary storage. These methods are useful when you want to make it clear that a value is raw binary data, or when you need to store data that should not be JSON-serialized. Binary data persists through pause/resume/checkpoint.

// Store raw binary data
const pixels = Buffer.from([0xff, 0x00, 0x00, 0xff]);
await ctx.setBytes("image-pixels", pixels);

// Retrieve it in another step
const data = await ctx.getBytes("image-pixels"); // Buffer | null

Manual Event Routing

Use ctx.sendEvent() to emit an event manually instead of returning one from the step handler:

await ctx.sendEvent({ type: "Continue" }); // Async
return null; // Don't return an event when using sendEvent