tool

Neutron Workflow

A durable execution engine. Every step is an event on Nucleus; on restart the engine replays the log to reconstruct state and continue. Workflows suspend for an event, an approval, or a timer — and resume days later, exactly where they stopped.

Durable, event-sourced workflows — suspend for days, survive restarts, resume exactly where you left off.

Available
Event-SourcedReplay on Nucleus
SuspendSleep, Wait, Approve
DeterministicReplay Reconstructs State
SchedulerPicks Up Parked Runs

The primitive Next.js and Astro don't have.

Web frameworks give you a request and a response. They have no answer for "run this, then wait three days for the customer to reply, then continue" — that's where you reach for a queue, a cron job, a state table, and a lot of glue. Neutron Workflow is a durable execution primitive built in. You write a plain async function; the engine makes it survivable.

Every step is recorded as an event. When a process restarts — a crash, a deploy, a scale-down — the engine replays the event log from the top, feeds completed steps their recorded results instead of re-running them, and continues from the first step that never finished. State is reconstructed, not persisted by hand.

onboarding.ts
import { workflow } from "@neutron-build/workflow";

export const onboarding = workflow("onboarding", async (ctx, userId: string) => {
  // step() runs once, records the result, and replays it forever after.
  const user = await ctx.step("load-user", () => db.users.get(userId));
  await ctx.step("welcome-email", () => sendEmail(user.email, "welcome"));

  // Suspend for three days. No process stays alive; the scheduler wakes it.
  await ctx.sleep("3d");

  if (!(await ctx.step("did-activate", () => hasActivated(userId)))) {
    await ctx.step("nudge-email", () => sendEmail(user.email, "nudge"));
  }
  return { onboarded: true };
});
A function that runs for a week without a process staying alive.
Event-sourced steps
Every ctx.step() runs once, records its result as an event, and replays that result on every later pass. The event log is the source of truth.
Replay on restart
The run function re-executes from the top on every resume. Completed steps replay from the log instead of re-running, so a crash costs nothing already done.
Suspend and resume
sleep parks on a timer, waitForEvent parks until a payload arrives. No thread, no process — the run is durable state, woken later.
Deterministic by design
ctx.now() and ctx.random() are recorded like steps, and a NondeterminismError catches replay drift. All I/O goes inside step().
Nucleus event store
NucleusEventStore persists the log to Nucleus streams; MemoryEventStore runs the same semantics in tests. Same engine, swappable backing.
Scheduler
A Scheduler over a RunIndex picks up runs that are due or parked — a slept timer fired, a retry delay elapsed — and drives them forward.

Wait for the outside world, then continue.

A workflow can suspend until an external event arrives — a webhook, a human approval, a payment confirmation. The run parks as durable state; when you deliver the event, it wakes and continues with the payload in hand. The waiting costs nothing, and it can last days.

expense.ts
import { workflow } from "@neutron-build/workflow";

export const expense = workflow("expense", async (ctx, claim: Claim) => {
  await ctx.step("record", () => db.claims.insert(claim));

  // Suspend until deliverEvent(runId, "decision") supplies a payload.
  const decision = await ctx.waitForEvent<{ approved: boolean }>("decision");

  if (decision.approved) {
    await ctx.step("reimburse", () => pay(claim.userId, claim.amount));
  }
  return { status: decision.approved ? "paid" : "denied" };
});
Parks on a human decision. Resumes when the event is delivered.

Run it, park it, wake it.

executeRun drives a run against an event store until it completes or suspends. A suspended run returns to the store as durable state. Later — when a timer fires or an event lands — the scheduler or an explicit deliverEvent resumes it. Same engine, whether it runs for ten milliseconds or ten days.

driver.ts
import { executeRun, deliverEvent, NucleusEventStore } from "@neutron-build/workflow";

const store = new NucleusEventStore(nucleus.streams);

// First pass: runs until the workflow suspends on waitForEvent.
await executeRun({ workflow: expense, runId: "claim-91", store, input: claim });

// ...minutes or days later, from a webhook handler:
await deliverEvent(store, "claim-91", "decision", { approved: true });
// The scheduler picks the run back up and continues from the wait.
Start a run; deliver an event days later to resume it.

What's in the box

Engine
workflow() + ctx.step, event-sourced
Suspend
sleep, waitForEvent, retry backoff
Store
NucleusEventStore + MemoryEventStore
Scheduler
RunIndex + due/parked run pickup
Leasing
LeaseManager for exclusive execution

What it's for

Multi-day business processes — onboarding drips, approval chains, subscription lifecycles. Sagas that coordinate several services and need to unwind cleanly on failure. Retry-heavy jobs where a delayed retry should park for free rather than hold a worker. Anything that has to wait on a human or an external system and then reliably pick up where it stopped. And it's the substrate under Neutron Agents and Teploy Ship — an agent turn is a durable workflow.

Why durable execution?

Because the alternative is a queue plus a state table plus a cron job plus reconciliation logic, reinvented per feature and wrong in a different way each time. Event sourcing gives you the audit log for free: every run's history is the exact sequence of steps that happened. Deterministic replay means the same inputs always reconstruct the same state, so a resumed run is indistinguishable from one that never stopped.

Part of a bigger system

Neutron Workflow is the durability layer the rest of the stack stands on. Neutron Agents turns an agent turn into a workflow so it survives restarts and pauses for approval. The AI SDK's tool loop becomes durable through agentStep. The event log lives in Nucleus, alongside everything else — one database, one contract, one system.

Start building with Neutron