Orchestrate
Workflows
Run agents as steps in durable, multi-step workflows.
Run an agent as a workflow step to get retries, and durable waits between steps.
import { pi } from "@rivet-dev/pi";
import { agentOSProvider } from "@rivet-dev/sandbox-adapter/agentos";
import { type Registry, setup, workflow } from "@rivet-dev/workflows";
const agent = pi({
model: "anthropic/claude-opus-5-5",
sandbox: agentOSProvider(),
});
type Agents = Registry<{ agent: typeof agent }>;
const flakyTest = workflow({
state: { report: null as string | null },
run: async (ctx) => {
await ctx.step({
name: "first-run",
timeout: 10 * 60_000,
run: async (step) => {
const fixer = step.client<Agents>().agent.getOrCreate([step.actorId]);
await fixer.abort();
await fixer.prompt("Run the test suite and note any failing tests.");
},
});
await ctx.sleep("wait-before-rerun", 10 * 60_000);
await ctx.step({
name: "second-run",
timeout: 10 * 60_000,
run: async (step) => {
const fixer = step.client<Agents>().agent.getOrCreate([step.actorId]);
await fixer.abort();
await fixer.prompt("Run the suite again. Which failures happened both times?");
step.state.report = (await fixer.getLastAssistantText()) ?? null;
},
});
},
actions: {
getReport: (c) => c.state.report,
},
});
export const registry = setup({ use: { agent, flakyTest } });
- Steps time out after 30 seconds by default, so
timeoutgives each prompt up to ten minutes. - A step that throws is retried up to three times, while a timeout fails the step right away. Each attempt calls
abortfirst, so a retry stops any run the previous attempt left going before prompting again. ctx.sleepwaits ten minutes with nothing running. The workflow resumes on time, even after a crash or deploy.- Both steps use the same agent key, so the second prompt continues the first conversation.
- Use a workflow when the work has fixed steps, waits, or retries. Use a single agent session when the agent should decide the steps itself.
See Workflows for steps, sleeps, and retries.