Your agents stop for a human before the risky move, pick up where they left off after a crash, and record what every run cost.
Every model call is a durable step. On top of that, Duraton makes the things agents actually need in production - spend limits, human approval, and evaluation - primitives you declare, not infrastructure you assemble.
A model call runs once. Its answer is saved the moment it lands, so a crash or a retry replays that answer instead of paying the model a second time. Wrap the call in ctx.step.ai and you are done.
const { output } = await ctx.step.ai.generate("classify", { model: "claude-opus-4-8", prompt: `Classify: ${subject}`, output: triageSchema,});
The run stops before it overspends, not after the bill arrives. A cap halts it just before the call that would cross the ceiling, and fails it there. A budget pauses over a rolling window and starts itself again. A throttle simply slows it down. All three are declared next to retry.
An agent that runs for hours survives a restart and picks up at its last finished turn, because every turn and every tool call is saved as its own step. A tool can be another workflow. That is ctx.step.ai.loop.
Show a model’s answer arriving word by word. Someone who opens the page late still sees it from the first word. The finished text is saved as the step’s result, so a replay never pays for the call again.
The run stops and waits for a person - for minutes or for days - without holding a worker while it waits. Approve it, deny it, or edit the arguments first; it carries on from exactly where it stopped. That is ctx.step.approval.

Find out whether the new prompt is actually better. Score a run as it goes with ctx.score, grade it afterwards with an LLM judge, fork one real run with a single change and compare the two, or send a whole dataset through it. The evidence stays on the run.

One provider having a bad afternoon does not take your feature down: a fallback chain moves past a rate-limited or unavailable model to the next one, across providers if it has to. And the exact same call, asked again, comes back from cache at no cost - deterministic calls only, since anything with a temperature is not one.
The model call happens in your runner, with your provider SDK and your key. Duraton records metadata - model, tokens, latency, cost - and never sees your prompt, the response, or your key.
Agents are first-class operators: list and control runs, trigger events, score runs, and run fork-compares through the MCP server.
Each row pairs what you write with the live console view it produces.
Wrap each piece of work in a step. It runs once, its result is saved, and a crash picks the run back up at the next one - never re-running what already finished.
const triage = await ctx.step.ai.generate("triage", { model, prompt });await ctx.step.sleep("cool-off", "10s");return ctx.step.run("refund", () => issueRefund(ticket.id));

A run starts from whatever your business already emits: an event over REST, a webhook from a third party, a record on your own Kafka topics, or a schedule with no event at all. Fire only on the ones that matter by writing the condition inline. Every event is kept in a log you can replay.
defineWorkflow({ name: "welcome.pro", triggers: [{ event: "user.signup", if: 'event.data.plan == "pro"' }], handler,});

Eight controls live right next to retry on the workflow, enforced before a run starts. Pick one to see how it is declared.

Every run, step, input, output, token, and score is live in the console. Cancel, pause, resume, fork, or replay a finished run - and every webhook delivery, in and out, has its own attempt log you can redeliver or replay too.
import { createClient } from "@duraton/sdk/client"; const duraton = createClient({ engineUrl, apiKey });await duraton.runs.replay(runId); // also: cancel, pause, resume, fork

A single wire protocol drives every SDK. Author in TypeScript, Python, or Go; trigger and control from anything over REST. The step semantics are identical across all of them.
const triage = await ctx.step.ai.generate("classify", { model: "claude-opus-4-8", prompt: `Classify this ticket: ${subject}`, output: triageSchema,});
Model calls run on your side; Duraton stores only metadata.
Runs, events, keys, and runners are scoped to a project boundary.
Every runner call is signature-verified per key.
Every control action is recorded with the actor behind it.
Durability isn't a library you write. Sign up, connect a runner, trigger a run - available today.