Ripardocs
Dashboard

Build a workflow

An endpoint answers a question. A workflow watches for something and acts — which is where execution guarantees start to matter.

Anatomy

workflows/liquidation-guard.ts
import { defineWorkflow } from "@ripar/sdk";
 
export default defineWorkflow({
  name: "liquidation-guard",
  trigger: { type: "cron", every: "5m" },
  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 };
 
    // Each `step` is checkpointed: a retry resumes here rather than
    // re-running `check` and paying for it twice.
    const tx = await step("top-up", () =>
      ctx.call("folks/supply", { amount: health.deficit })
    );
 
    return { toppedUp: true, tx };
  },
});

Triggers

TriggerFires whenExample
cronOn a schedule{ type: "cron", every: "5m" }
webhookAn HTTP call arrives{ type: "webhook" }
onchainAn Algorand event matches{ type: "onchain", app: 1234, event: "Swap" }
manualYou invoke itripar run liquidation-guard

Execution guarantees

This is the part that separates a workflow from a cron job that calls curl.

  • Retries with exponential backoff — transient failures are retried; the schedule is jittered so a downstream outage does not get a thundering herd.
  • Step checkpointing — completed steps are not re-executed on retry. You do not pay twice for the same paid call.
  • Idempotency keys — carried automatically into every ctx.call.
  • Nonce-safe submission — concurrent onchain actions from one workflow are serialised so they cannot collide.
Wrap every paid call in a step

A ctx.call outside a step() is re-executed on retry — and re-paid. Steps are how you make retries free.

Conditions and branching

const price = await step("price", () => ctx.call("algo-usd/spot"));
 
if (price.value < ctx.env.FLOOR) {
  await step("alert", () => ctx.call("notify/slack", { text: "below floor" }));
  return { acted: "alerted" };
}

Plain control flow. There is no DSL to learn.

Budgets

Cap what a workflow can spend before it can spend it:

budget: { perRun: "0.25", perDay: "5.00" },

Exceeding the cap fails the run rather than the wallet. See Security.

Watching runs

ripar runs liquidation-guard --last 20
ripar runs show run_8c21

Every attempt, its steps, its payments and its result are in the record — including the attempts that failed.