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:
pi install npm:pi-taskflowThat'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:
{
"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:
/tf run review-changes dir=srcEither 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:
/tf save review-changestaskflow writes the definition into your project's flow store. From then on, the flow has a shortcut:
/tf:review-changes dir=srcThat /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:
/tf resume <runId>To browse what you've run, including in-progress and paused runs:
/tf runsAnd 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:
/tf peek <runId> summarizepeek 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:
/tf initYou'll get a picker that walks you through each role and recommends sensible defaults. The roles are:
| Role | Purpose | Typical agents |
|---|---|---|
fast | Cheap & quick — high-volume, low-stakes work. | executor, scout, verifier, doc-writer |
strong | Balanced planning and review. | planner, reviewer, executor-code |
thinker | Deep analysis and ambiguity detection. | analyst, critic |
arbiter | Final judgment and tiebreaks. | plan-arbiter, final-arbiter |
vision | Multimodal — UI work, design reading. | executor-ui, visual-explorer |
reasoner | Cautious 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:
| Command | Description |
|---|---|
/tf list | List 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 runs | Browse 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 init | Configure 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
Getting Started
The five-minute tour, if you haven't seen it yet.
Phase Types
The ten building blocks you can compose into a DAG.
Using taskflow on Codex
The same runtime, wired into OpenAI Codex.
Last updated on
Was this helpful?
Help us improve the docs or ask a question in the community.