taskflow

Using taskflow on Pi

Install, run, save, and resume taskflows on the Pi coding agent.

If you already use Pi to delegate work to subagents, taskflow turns those one-off delegations into named, resumable, multi-step workflows. You describe the work as a graph — fan-out, gates, loops, whatever you need — and only the final result comes back into your context.

This page walks through the whole arc: install, run your first flow, save it, run it by name, and wire up model roles. By the end you'll have a reusable command that does a real job in one line.

Install

taskflow is a Pi extension. Install it once:

Install pi-taskflow
pi install npm:pi-taskflow

That's it. The extension registers a taskflow tool that the model can call automatically, plus a /tf command for you. No model-side configuration is required to start.

The extension lives in your Pi agent directory. Restart your Pi session if it was already running when you installed.

Run your first flow

Let's start with something real: review the changed files in a project and return a single risk summary. Save this as review-changes.json next to wherever you run Pi:

review-changes.json
{
  "name": "review-changes",
  "description": "Review changed files and return a single risk summary.",
  "args": {
    "dir": { "default": "." }
  },
  "concurrency": 4,
  "phases": [
    {
      "id": "discover",
      "type": "agent",
      "agent": "scout",
      "task": "List the source files under {args.dir} that have been changed recently. Output ONLY a JSON array of objects with a 'path' field. No prose.",
      "output": "json"
    },
    {
      "id": "review-each",
      "type": "map",
      "over": "{steps.discover.json}",
      "as": "file",
      "agent": "security-reviewer",
      "task": "Review {file.path} for security risks. Return one paragraph of findings or 'No issues found.'.",
      "dependsOn": ["discover"],
      "concurrency": 4
    },
    {
      "id": "summarize",
      "type": "reduce",
      "from": ["review-each"],
      "agent": "writer",
      "task": "Combine the following per-file reviews into a single prioritized risk summary:\n{steps.review-each.output}",
      "dependsOn": ["review-each"],
      "final": true
    }
  ]
}

There are three phases, wired into a small DAG. discover lists the files. review-each fans out — one security reviewer per file, up to four at once. summarize folds the individual reviews into one report, and because it's marked final: true, that report is the only thing that returns to your conversation.

Now run it. You have two ways to ask.

Just describe the work

You don't need to remember a command. In a Pi session, describe what you want in plain language:

Try: "Run the review-changes flow in this repo with dir set to src."

The model recognizes the intent, loads the taskflow tool, and executes the DAG. The intermediate transcripts from discover, review-each, and summarize stay inside the runtime — your context window only receives the final summary.

Use the command directly

If you prefer to be explicit, the /tf command is always available:

Run a saved flow by name
/tf run review-changes dir=src

Either path runs the same flow. The command form is handy when you know exactly what you want and don't want to spend a model turn negotiating it.

Not sure your flow is sound before spending tokens? Run /tf verify review-changes — it statically checks for cycles, dangling dependsOn, unknown phase refs, and malformed configs at zero cost.

Save a flow for later

Running from a JSON file is fine for experimentation, but the real payoff is turning a flow you like into a one-word command.

After a run, just tell Pi to save it:

Try: "Save that flow as review-changes."

Or save it directly from a file with the command:

Save a flow definition
/tf save review-changes

taskflow writes the definition into your project's flow store. From then on, the flow has a shortcut:

Run a saved flow via its shortcut
/tf:review-changes dir=src

That /tf:<name> form is the fastest way to invoke a flow you've already shaped. It's the same as /tf run <name> — just shorter.

Saved flows are scoped per project. Run /tf list to see everything available in the current directory.

When a run pauses or fails

Real workflows don't always finish on the first try. An approval phase might pause for a human, a subagent might hit a transient error, or you might abort a long run and come back to it.

Every run gets a runId, and the runtime persists its state. To continue a paused or failed run:

Resume a paused or failed run
/tf resume <runId>

To browse what you've run, including in-progress and paused runs:

Browse run history
/tf runs

And if you ever need to inspect a single phase's intermediate output after the fact — say, to debug why a gate blocked — peek shows it without re-running anything:

Peek at a phase's stored output
/tf peek <runId> summarize

peek is for debugging only. By design it pulls intermediate output into your context — that's the one exception to taskflow's isolation guarantee, and it's opt-in.

Model roles

taskflow ships with eighteen built-in agents (scout, security-reviewer, writer, and friends), and each one is tagged with a role that maps to a model. Out of the box, those roles may resolve to a default model — but you'll want to point them at your own.

Run the interactive setup:

Configure model roles
/tf init

You'll get a picker that walks you through each role and recommends sensible defaults. The roles are:

RolePurposeTypical agents
fastCheap & quick — high-volume, low-stakes work.executor, scout, verifier, doc-writer
strongBalanced planning and review.planner, reviewer, executor-code
thinkerDeep analysis and ambiguity detection.analyst, critic
arbiterFinal judgment and tiebreaks.plan-arbiter, final-arbiter
visionMultimodal — UI work, design reading.executor-ui, visual-explorer
reasonerCautious reasoning — security and risk.risk-reviewer, security-reviewer

If you skip this step, taskflow will hint that roles are unconfigured and agents will fall back to the default model. It works, but you're leaving cost and quality on the table — fast roles on a cheap model save a lot of tokens over time.

The configuration is written to your Pi settings.json under modelRoles. You can re-run /tf init any time to change a single role or accept the recommended defaults.

Command reference

Here's the full /tf surface, for when you know what you need:

CommandDescription
/tf listList saved flows in the current project.
/tf run <name> [args]Run a saved flow, optionally with args.
/tf:<name> [args]Shortcut for /tf run <name>.
/tf show <name>Print a saved flow's JSON definition.
/tf verify <name>Statically verify a flow (cycles, refs, configs).
/tf compile <name>Render the DAG as a Mermaid diagram.
/tf save <name>Save a flow definition to the project store.
/tf runsBrowse run history (in-progress, paused, done).
/tf resume <runId>Continue a paused or failed run.
/tf peek <runId> [phaseId]Inspect a stored phase's output for debugging.
/tf initConfigure model roles interactively.

Several advanced subcommands exist for cache and provenance work (ir, provenance, why-stale, recompute, cache-clear). You'll meet them when you need them — see the reference docs for details.

Next

Last updated on

Was this helpful?

Help us improve the docs or ask a question in the community.

On this page