Skip to content

Task Flows

When an agent’s work spans multiple steps that need to be tracked, retried, and resumed across session boundaries, TaskFlow is the system that holds the state. It was imported from OpenClaw’s task-flow-registry and adapted for instar’s single-agent architecture. See docs/specs/OPENCLAW-IMPORT-TASKFLOW-SPEC.md for the original design.

  • TaskFlowRegistry — durable record store backed by SQLite. Each task flow is a row with a state, a step graph, and structured payload state JSON. Reads and writes use optimistic-concurrency tokens so concurrent updates can’t silently overwrite each other.
  • TaskFlowDueWaker — fires when a flow’s scheduled wake time arrives. Wakes are stored with millisecond precision; multiple flows due at the same time get batched into a single waker pass.
  • TaskFlowMaintenanceSweeper — runs periodically to retire completed flows, archive failed ones, and surface flows that have stalled past their expected duration.
  • ThreadlineFlowBridge — connects task flows to the Threadline relay surface, so flows can span multiple agents (one agent kicks off a flow, another agent picks up a step, the flow lifecycle stays coherent across both).
  • DivergenceChecker — watches for state mismatches between what a flow expects and what actually happened (e.g. a step claimed completion but the side effect isn’t visible). Surfaces divergences to the remediator.
  • LruCache — small in-memory cache for frequently-accessed flow records.
  • RateLimiter — bounds how aggressively flows can fire new steps, especially relevant when many flows wake simultaneously.

Each flow moves through a constrained state graph: pending → running → waiting → running → finished (or failed, or cancelled). Transitions are atomic and journaled. The optimistic-concurrency token ensures that two parallel attempts to advance the same flow get one success and one transition-conflict error rather than corrupting state.

Use casePick
One-shot work on a cron scheduleJob scheduler
Long-running work with multiple async stepsTask flow
Work that has to coordinate across agentsTask flow with ThreadlineFlowBridge
Stateless health checkJob
Multi-step user request that may pause for inputTask flow

The two systems interoperate. A scheduled job can launch a task flow as its body; a task flow can schedule a job for one of its steps. The split is about state durability — task flows persist their state across server restarts and session boundaries; jobs don’t unless they explicitly write state somewhere themselves.

EndpointDescription
POST /flowsCreate a new flow
GET /flows/:flowIdRead flow state
GET /flows/waitingList flows currently waiting on something
POST /flows/:flowId/start-stepBegin a step
POST /flows/:flowId/finishMark the flow as completed
POST /flows/:flowId/failMark the flow as failed (with reason)
POST /flows/:flowId/waitSuspend until a wake condition
POST /flows/:flowId/pingHeartbeat for long-running steps
POST /flows/:flowId/resumeResume from wait
POST /flows/:flowId/cancel-flowCancel the whole flow
POST /flows/:flowId/cancel-requestRequest cancellation (the flow can decline)
POST /flows/:flowId/mark-lostMark a flow as unrecoverable

Flow records live in task-flow-registry.store.sqlite.ts (with adjacent WAL and SHM files). State JSON can contain user-supplied content, so the store is treated as containing PII and is gitignored.