Local
Install Workflows and run it locally while you build.
Durable workflows built on Rivet Actors. Steps record their results, wait for people or systems, and resume after crashes and deploys.
run_01JQ6R8T
Issue received
Recording event input
Agent edits repository
Not started
Run test suite
Not started
Wait for approval
Not started
Record result
Not started
Workflow is running.
import { actor, setup } from "rivetkit";
import { type WorkflowStepContextOf, workflow } from "rivetkit/workflow";
export const invoiceActor = actor({
state: {
invoiceId: null as string | null,
subtotal: 0,
tax: 0,
total: 0,
status: "idle" as "idle" | "complete",
},
run: workflow(async (ctx) => {
const subtotal = await ctx.step("load-subtotal", async (ctx) =>
loadSubtotal(),
);
const tax = await ctx.step("calculate-tax", async (ctx) =>
calculateTax(subtotal),
);
await ctx.step("save-invoice", async (step) =>
saveInvoice(step, subtotal, tax),
);
}),
actions: {
getState: (c) => c.state,
},
});
async function loadSubtotal(): Promise<number> {
const response = await fetch("https://api.example.com/carts/main");
if (!response.ok) {
throw new Error(`load subtotal failed: ${response.status}`);
}
const cart = (await response.json()) as { subtotal: number };
return cart.subtotal;
}
async function calculateTax(subtotal: number): Promise<number> {
const response = await fetch("https://api.example.com/tax/quote", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({ subtotal }),
});
if (!response.ok) {
throw new Error(`tax quote failed: ${response.status}`);
}
const quote = (await response.json()) as { tax: number };
return quote.tax;
}
async function saveInvoice(
ctx: WorkflowStepContextOf<typeof invoiceActor>,
subtotal: number,
tax: number,
): Promise<void> {
const total = subtotal + tax;
const response = await fetch("https://api.example.com/invoices", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({ subtotal, tax, total }),
});
if (!response.ok) {
throw new Error(`save invoice failed: ${response.status}`);
}
const invoice = (await response.json()) as { id: string };
ctx.state.invoiceId = invoice.id;
ctx.state.subtotal = subtotal;
ctx.state.tax = tax;
ctx.state.total = total;
ctx.state.status = "complete";
}
export const registry = setup({ use: { invoiceActor } });Address each workflow by key; every run keeps its own state, queue, and history.
Steps read and write the run's durable state in-process.
A run blocked on a queue wait or timer sleeps until the message or deadline arrives.
Broadcast step progress to connected clients as it happens.
Pause for approval, fan out, retry. Every step is recorded.
Read about queue waits, timers and concurrency, and failure and recovery.
The workflow gives an agent a computer and records every step.
Agent’s computer
Every step recorded
Read about agent patterns or view the source.
Deploy new code mid-run. Old runs keep their version; new runs take the latest.
Read about versioning.
Every step's status, from pending through complete or failed.
Durations, attempt counts, backoff delays, and terminal errors.
The recorded values each step received and returned.
Re-run eligible steps after the underlying problem is fixed.
Every workflow is an Actor run handler. Actors provide identity, state, queues, and scheduling.
Product overviewAdds files, processes, a shell, and networking when a workflow drives an agent using real tools.
Product overviewAdds a generated backend when the workflow should ship an application to users.
Product overviewInstall Workflows and run it locally while you build.
Deploy Workflows on Rivet Cloud with managed infrastructure and persisted Actor data.
Open the dashboardRun the open-source Rivet control plane as a Rust binary or container on your infrastructure.
Read self-hosting docsRead the documentation or explore the Apache 2.0 source.