pi-taskflow

extensionmaintained

A declarative, verifiable graph of task nodes for the Pi coding agent — statically verified before it runs, with dynamic fan-out, gates, isolated subagent context, resumable runs, and saveable commands.

by · v0.2.7 · published 3d ago

$ pi install npm:pi-taskflow
downloads/mo
0
stars
53
last push
1d ago
open issues
3

Signals

license: MITtestspi manifest: missinginstall size: —deps: 0peer deps: 0

Download trend

10.2K downloads · last 12 weeks (weekly)

README


Build multi-agent systems you can inspect before they run.

taskflow turns agent plans into compiled task graphs: declared once, verified before model spend, executed in isolated subagents, resumed across sessions, replayed without tokens, and recomputed from the smallest stale frontier.

It runs on the coding agent you already use:

Pi · Codex · Claude Code · OpenCode · Grok Build

JSON or .tf.ts
      │
      ▼
 validate ──► Taskflow JSON ──► FlowIR + content hash
                                      │
                                      ▼
                           isolated DAG runtime
                                      │
                         ┌────────────┼────────────┐
                         ▼            ▼            ▼
                      resume        replay      recompute

Your host receives the final result. Intermediate transcripts stay inside the runtime unless you explicitly inspect them.

Why taskflow?

Built-in subagent tools are excellent for one turn. The moment the work branches, retries, crosses sessions, or needs a quality gate, the plan becomes infrastructure.

Ad-hoc agents / scriptstaskflow
PlanRe-derived from prose or hidden in a scriptAn explicit, versionable DAG
Before executionDiscover mistakes while spendingVerify structure at zero model calls
Intermediate outputFloods the host contextStays isolated in the runtime
FailureStart over or reconstruct stateResume from persisted phase state
Changed inputRe-run broadlyExplain staleness and re-run the affected frontier
PortabilityCoupled to one agentOne JSON contract across five hosts

The trade is deliberate: less arbitrary orchestration code, more verifiability, observability, recovery, and reuse.

60-second start

Install taskflow on Pi:

pi install npm:pi-taskflow

Then ask naturally:

Use taskflow to audit src/api in parallel and return one prioritized report.

The routing skill uses the same familiar task / tasks / chain shape:

{
  "chain": [
    { "agent": "scout", "task": "Map the public API under src/api." },
    {
      "agent": "security-reviewer",
      "task": "Audit this surface for missing auth and unsafe input boundaries:\n{previous.output}"
    },
    {
      "agent": "reviewer",
      "task": "Turn these findings into one prioritized report:\n{previous.output}"
    }
  ]
}

That already gives you an isolated, tracked run. When the job needs real topology, declare the graph:

{
  "name": "audit-api",
  "args": { "dir": { "default": "src/api" } },
  "concurrency": 4,
  "phases": [
    {
      "id": "discover",
      "type": "agent",
      "agent": "scout",
      "task": "List source files under {args.dir}. Output ONLY a JSON array of {\"path\":\"...\"} objects.",
      "output": "json"
    },
    {
      "id": "audit-each",
      "type": "map",
      "over": "{steps.discover.json}",
      "as": "file",
      "agent": "security-reviewer",
      "task": "Audit {file.path}. Cite evidence and assign severity.",
      "dependsOn": ["discover"]
    },
    {
      "id": "report",
      "type": "reduce",
      "from": ["audit-each"],
      "agent": "reviewer",
      "task": "Synthesize one prioritized report:\n{steps.audit-each.output}",
      "dependsOn": ["audit-each"],
      "final": true
    }
  ]
}

Save it as .pi/taskflows/audit-api.json, then run:

/tf:audit-api dir=src/api

On Codex, Claude Code, OpenCode, and Grok Build, run the same saved definition by name through taskflow_run. For long DAGs, use mode: "background", then manage the durable run with taskflow_runs (list / status / wait / cancel); list output reports active concurrency and can filter running or terminal runs.

Follow the full quickstart →

See the graph run

This is real output from a Pi run—not a mock dashboard:

⊗ taskflow self-improve  6/7 · blocked · $0.095
    ✓ discover            agent   deepseek-v4-flash  10t ↑38k ↓6.7k $0.011
  ┌ ✓ write-runner-tests  agent   claude-sonnet-4-6  10t ↑13 ↓6.6k $0.020
  ├ ✓ write-store-tests   agent   claude-sonnet-4-6  10t ↑11 ↓10k $0.018
  ├ ✓ write-agents-tests  agent   claude-sonnet-4-6  10t ↑28 ↓13k $0.030
  └ ✓ fix-stability       agent   claude-sonnet-4-6  10t ↑13 ↓3.9k $0.012
    ✓ verify              gate    BLOCK 3 type errors in test files
    ⊘ report              reduce  skipped · Gate blocked  ↳ fix-stability

The layout is the DAG. Parallel rails expose concurrency; long edges expose dependencies; the gate explains why downstream work stopped. No separate control plane is required to understand the run.

0.2.7: plan before spend · close the loop

The 0.2 line made graphs compiled and inspectable. 0.2.7 makes the day-to-day loop feel finished: you can see the plan before any model call, and you can hear about the run after it finishes — without stuffing transcripts into the host.

Before spendAfter spend
taskflow_plan / /tf plan — bind typed args, project phase order, mark dynamic refs, worst-case agent-call boundhooks.onComplete / onFail / onBlocked — webhook, file, or argv-only command; summary payload only (taskflow.hook.v1)
verify / lint still freeapproval.timeoutMs + onExpire — HITL no longer waits forever
recompute savings linereused N · rerun M · cutoff K · saved ~P%taskflow_analytics — last-N status, duration, fail/cache rates (read-only)
# Zero tokens: see what would run and how expensive the worst case looks
# MCP: taskflow_plan  ·  Pi: /tf plan my-flow '{"dir":"src"}'
// Optional: fire-and-forget when a background run finishes
{
  "hooks": {
    "onComplete": [{ "type": "file", "path": ".taskflow/hooks/last-complete.json" }]
  }
}

MCP hosts now expose 19 tools (added taskflow_plan and taskflow_analytics). Starter templates: examples/templates/. Full notes: CHANGELOG 0.2.7.

0.2 is the compiler turn

Before 0.2, taskflow executed declarative graphs. Now the graph also has a compile-time frontend, a canonical intermediate representation, an append-only decision trace, offline replay, and incremental recompute.

Author in JSON or TypeScript

JSON remains the portable runtime contract. For larger flows, taskflow-dsl adds a compile-time TypeScript authoring layer:

import { agent, flow, json, map, reduce } from "taskflow-dsl";

export default flow("audit", (ctx) => {
  ctx.budget({ maxUSD: 2 });

  const files = agent("List files under {args.dir}", {
    agent: "scout",
    output: json<{ path: string }[]>(),
  });

  const audits = map(files, (file) =>
    agent(`Audit ${file.path}`, { agent: "security-reviewer" }),
  );

  return reduce(
    [audits],
    (parts) => agent(`Write one report:\n${parts.audits.output}`),
    { final: true },
  );
});
pnpm add -D taskflow-dsl
taskflow-dsl check audit.tf.ts
taskflow-dsl build audit.tf.ts --emit both
# → audit.taskflow.json + audit.flowir.json

.tf.ts is compile-time only. Hosts execute the emitted Taskflow JSON; they never interpret TypeScript.

Compile to a contract you can reason about

FlowIR canonicalizes the graph and gives it a content hash. That compiled identity makes provenance and stale analysis inspectable, while the runtime adds content-addressed caching and deterministic tools:

OperationWhat it answersModel calls
planWhat will run, which args bind, worst-case agent calls?0
verify / compile / lintIs the graph structurally safe / lint-clean?0
irWhat is the canonical graph and content hash?0
resumeWhat unfinished work remains? (forks a new run; original untouched)Only unfinished phases
traceWhat calls and runtime decisions actually happened?0 to inspect
replayWhat if thresholds or budgets had been different?0
why-staleWhat changed, and what depends on it?0
recomputeWhat is the smallest observable affected frontier? (+ savings line)Only affected phases
analyticsHow have recent runs of this flow behaved?0

Explore the compiler and runtime →

One runtime, 12 phase types

FamilyPhasesUse them for
Workagent · parallel · map · reduce · scriptSingle tasks, static fan-out, dynamic fan-out, aggregation, zero-token shell steps
Controlgate · approval · flow · loopQuality decisions, human checkpoints, composition, iterative refinement
Selectiontournament · raceBest-of-N quality or first-success latency
Dynamic graphexpandValidate and execute a runtime-produced fragment, nested or grafted

Across those phase types, the DSL provides dependencies, conditions, retries, timeouts, output contracts, budgets, workspace isolation, and explicit final-output selection. Each kind accepts only the fields that are safe and meaningful for it; freshness-sensitive phases are excluded from cross-run caching.

Read the phase reference →

Runtime guarantees, not prompt conventions

Verify before spend

Cycles, dangling dependencies, invalid references, impossible joins, unsafe dynamic fragments, and configuration hazards are rejected or surfaced before the expensive work starts.

Keep intermediate work out of the host context

Agent-running phases execute in isolated subagent processes; control and script phases stay inside the runtime. Upstream outputs are wired into downstream inputs internally. Only finalOutput returns to the host unless you explicitly use peek or trace.

Survive sessions and failures

Phase state is persisted atomically. Resume skips unchanged completed work; detached Pi runs can outlive the initiating session; an idle watchdog terminates stalled subagents.

Reuse work honestly

Within-run resume is content-addressed. Cross-run caching is opt-in and can fingerprint Git commits, files, globs, environment variables, and TTLs. Change one declared input and only its dependents become stale.

Bound the blast radius

Budgets, concurrency caps, retries, timeouts, nesting limits, dynamic-graph breadth caps, path containment, non-idempotent phase classification, and fail-closed approval behavior are runtime semantics—not suggestions in a prompt.

0.2.1: safe dynamic cwd and Pi terminal reaping

An invocation argument declared as type: "relative-path" may select a phase working directory with the exact form cwd: "{args.package}". The bridge is default-off, requires host resolve-only authorization, and confines the canonical directory to the invocation root. Absolute paths, concatenation, and {steps.*} remain rejected; this compatibility bridge is not an OS sandbox. Resolve-only writer phases within one invocation are serialized before durable lease acquisition, so fan-out cannot self-timeout while separate processes remain protected by cross-process leases.

Pi child agents no longer inherit ambient extensions by default. Trusted host settings can use an explicit extension allowlist or opt back into legacy inheritance. If a Pi child produces a validated final answer and terminal event but an extension keeps the process alive, Taskflow waits a bounded grace window, reaps the process group, and records completionSource: "terminal-reap" instead of reporting a false timeout.

{
  "taskflow": {
    "piChild": {
      "resourceProfile": "isolated",
      "extensions": [],
      "terminalGraceMs": 1500
    }
  }
}

allowlist accepts explicit trusted extension files; inherit restores ambient Pi extension discovery as a compatibility mode. Flows cannot widen this host authority.

Read the core concepts →

Install on your host

All packages require Node.js ≥ 22.19.0.

Pi

pi install npm:pi-taskflow

Pi provides the richest local experience: the taskflow tool, /tf commands, live DAG rendering, interactive approvals, background runs, and model-role setup.

Pi guide →

OpenAI Codex

codex plugin marketplace add heggria/taskflow
codex plugin add taskflow@taskflow

Codex guide →

Claude Code

claude plugin marketplace add heggria/taskflow
claude plugin install claude-taskflow@taskflow

Claude Code guide →

OpenCode

opencode mcp add taskflow -- \
  npx -y -p opencode-taskflow@0.2.7 opencode-taskflow-mcp

OpenCode guide →

Grok Build

grok mcp add taskflow -- \
  npx -y -p grok-taskflow@0.2.7 grok-taskflow-mcp

Grok Build support is new in 0.2. Its CLI stream does not report token/cost usage, so budget-declaring flows are rejected rather than silently running without enforcement.

Grok Build guide →

Built to survive real work

9 packages · 5 hosts · 12 phase types · 18 built-in agents · 1,500+ tests · MIT

                              taskflow-core
                 ┌──────────────┼───────────────┐
                 │              │               │
           taskflow-dsl   pi-taskflow   taskflow-mcp-core ─┐
                                       taskflow-hosts ─────┼─ codex-taskflow
                                                          ├─ claude-taskflow
                                                          ├─ opencode-taskflow
                                                          └─ grok-taskflow

taskflow-core is host-neutral and imports no host SDK. taskflow-mcp-core implements stdio JSON-RPC without an MCP SDK dependency; taskflow-hosts owns the shared host process runners. The four MCP delivery packages bind both layers (and core), while Pi keeps its native adapter.

The test suite covers orchestration semantics, persistence and file-lock races, cache freshness, path traversal, dynamic graph hardening, cancellation, budgets, all 12 phase kinds, FlowIR/replay/recompute, TypeScript DSL erasure, host argv contracts, MCP servers, and packed consumer imports.

Documentation

Start hereWhen you need
Getting StartedYour first successful run
ConceptsDAGs, isolation, verification, resume, shared context
SyntaxPhase fields, control flow, budgets, caching, scorers
Compiler & RuntimeTypeScript DSL, FlowIR, replay, recompute, background runs
Host GuidesPi, Codex, Claude Code, OpenCode, and Grok setup
ReferenceCommands, shorthand, and exact tool surfaces
ShowcaseReal flows and case studies
0.2.0 Frontier AssessmentIndependent, evidence-based technical assessment (Chinese)

Also see examples/, the changelog, and the release guide.

Contributing

pnpm install
pnpm run typecheck
pnpm test
pnpm run build
pnpm run test:pack

Contributions are welcome. Start with CONTRIBUTING.md for the workflow and AGENTS.md for architecture and coding conventions.

License

MIT © heggria

Declare once. Verify first. Recompute only what changed.

Read the docs · Try an example · View releases