Runs that survive the things that go wrong
Chain paid calls and onchain actions. The SDK carries exponential backoff and idempotency keys, so a retried call resumes instead of paying twice. There is no trigger service yet — a workflow runs when you run it, not on a schedule.
What it does
Triggers that fit the job
A schedule, a webhook, an onchain event, or a manual run. Plain control flow inside — there is no DSL to learn.
Steps are checkpointed
A completed step is not re-executed on retry. That is what makes a retry free rather than a second charge.
Idempotency by default
Keys are carried into every paid call the workflow makes, so a network blip cannot bill the same unit of work twice.
Budgets that bind
Per-run and per-day caps are enforced server-side. A loop that goes wrong hits a ceiling, not your treasury.
A cron job that calls curl is not this
The difference is what happens on attempt two. Without checkpointing, a retry re-runs every paid call before the failure — and pays for all of them again. Ripar resumes at the step that failed.
In practice
export default defineWorkflow({
trigger: { type: "cron", every: "5m" },
budget: { perRun: "0.25", perDay: "5.00" },
async run({ step, ctx }) {
const health = await step("check", () =>
ctx.call("folks/health", { address: ctx.env.WALLET })
);
if (health.ratio >= 1.4) return { skipped: true };
// Wrapped in step(), so a retry resumes here and does not re-pay "check".
return step("top-up", () =>
ctx.call("folks/supply", { amount: health.deficit })
);
},
});Questions
- What happens if a step keeps failing?
- Attempts back off exponentially with jitter, so a downstream outage does not produce a thundering herd. The run is marked failed with every attempt in the record.
- Can a workflow call another workflow?
- Yes — a workflow is callable like any other endpoint, and its cost rolls into the calling run's budget.
- How long can a run take?
- Fifteen minutes per run, with up to 100 steps. Longer work belongs in a chained cron workflow or a posted job.