Theo Docs
TheoKitTheoKit-SDKTheoUITheo PaaS
Concepts

Workflows

Declarative multi-step pipelines — Workflow.create with 7 control-flow primitives.

Canonical contract: packages/sdk/docs.md — "Workflows (v1.17+)".

Workflow is a declarative DSL for multi-step pipelines. Inspired by Mastra + Temporal. Use when imperative agent.send loops get awkward.

Build + run

import { Workflow, Agent } from "@theokit/sdk";

const triage = Workflow
  .create({ name: "support-triage" })
  .then("fetch", async (input: { ticketId: string }) => {
    return { text: await db.getTicket(input.ticketId) };
  })
  .branch("route", [
    [(s) => s.text.includes("refund"), {
      step: { kind: "fn", id: "refund-flow", fn: async (s) => ({ result: "refund handled" }) },
    }],
    [(s) => s.text.includes("bug"), {
      step: { kind: "fn", id: "bug-flow", fn: async (s) => ({ result: "bug logged" }) },
    }],
  ])
  .commit();

const result = await Workflow.run(triage, { ticketId: "T-1234" });
console.log(result.output);

7 primitives

PrimitivePurpose
.then(id, fn)Sequential step
.parallel([...], { errorPolicy })Run N steps concurrently
.branch(id, [[pred, branch], ...])First-match-wins routing
.foreach(id, items, fn, { concurrency })Map over a collection
.dowhile(id, predicate, body)Loop until predicate false
.sleep(id, ms)Wait
.suspend(payload?)Pause; resume via Workflow.resume(...)

Suspend / resume

For long-running flows (human in the loop, external webhook):

const wf = Workflow.create({ name: "pr-review" })
  .then("draft", draftReview)
  .suspend()                              // ← pause here
  .then("publish", publishReview)
  .commit();

const run = await Workflow.run(wf, input);
// run.status === "suspended", run.suspendPayload visible

// Later, after the human reviews:
const finished = await Workflow.resume({
  workflowId: run.workflowId,
  runId: run.runId,
  resumeInput: { approved: true },
});

Retry policies

Per-step Temporal-style retry (ADR D237):

.then("flaky", flakyApiCall, {
  retry: { maxAttempts: 3, backoffMs: 500, coef: 2 },
})

Cancellation

AbortSignal is honored at step boundaries (ADR D245). Pass via options:

const ctrl = new AbortController();
const run = Workflow.run(wf, input, { signal: ctrl.signal });
// elsewhere: ctrl.abort();

Persistence

Default: in-memory. Opt-in JSON snapshots:

Workflow.run(wf, input, {
  persistence: { backend: "json", dir: ".theokit/workflows" },
});

Telemetry

OTel spans workflow.run + workflow.step.<id> via the existing telemetry seam (ADR D241).

CloudAgent

Workflow steps throw UnsupportedRunOperationError on CloudAgent — local-only in v1 (ADR D244).

API reference

On this page