Using taskflow on Codex
Install taskflow as a Codex plugin and orchestrate multi-phase workflows via MCP.
Codex is a natural home for taskflow: it already thinks in terms of subagents, and taskflow gives those subagents a declarative graph to run inside. On Codex, taskflow ships as a plugin that registers an MCP server plus a routing skill, so the model can call it the moment it sees a multi-step task.
This page walks through the whole arc: install the plugin, confirm the MCP server is live, run a flow through a tool call, and configure things for long-running work.
Install
taskflow is distributed through the shared plugin marketplace. Add the marketplace, then install the plugin:
Requires Node.js ≥ 22.19.0.
codex plugin marketplace add heggria/taskflow
codex plugin add taskflow@taskflowThat single plugin add does three things at once:
Registers the MCP server. The plugin's .mcp.json declares a taskflow server launched via npx codex-taskflow-mcp, so Codex can reach the runtime over stdio.
Installs the routing skill. A bundled skill teaches Codex when to reach for the taskflow tools, so you don't have to remember their names.
Sets a sane default timeout. The server ships with a 30-minute (1800 second) tool-call timeout, because DAGs can take a while.
Restart your Codex session if it was already running, so the new plugin is picked up.
Verify the install
Before running anything, confirm both the plugin and its MCP server registered cleanly:
codex plugin list # taskflow@taskflow should appear, enabled
codex mcp list # taskflow should appear, enabledIf either is missing, the plugin add step didn't complete — re-run it and check for errors.
Run your first flow
On Codex, you don't invoke taskflow through a slash command — you invoke it through an MCP tool. The model decides when to call it, guided by the bundled skill. So the most natural way to start is to just describe the work.
Just ask
Try one of these in a Codex session:
> List my saved taskflows.
> Verify this flow, then run it: {name:"review-changes", phases:[...]}
> Run the "review-changes" taskflow with dir set to src.The skill routes the request to the right tool. If a flow is saved in the current project, the model calls taskflow_run with the saved name; if you pasted an inline definition, it passes that instead.
Call the tool directly
If you want to be explicit — useful in scripts or when you know the exact shape — the tool is taskflow_run. It accepts either a saved flow name or an inline define:
{
"name": "review-changes",
"args": { "dir": "src" }
}{
"define": {
"name": "quick-review",
"phases": [
{
"id": "discover",
"type": "agent",
"agent": "scout",
"task": "List changed source files under src/. Output ONLY a JSON array of {path} objects.",
"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.",
"dependsOn": ["discover"],
"concurrency": 4
},
{
"id": "summarize",
"type": "reduce",
"from": ["review-each"],
"agent": "writer",
"task": "Combine these reviews into one prioritized summary:\n{steps.review-each.output}",
"dependsOn": ["review-each"],
"final": true
}
]
}
}Either form runs the same DAG. The tool returns only the final output — the intermediate transcripts from discover, review-each, and summarize stay inside the runtime and never enter your context.
Only the phase marked final: true is returned. Everything else is context-isolated by design.
Check a flow before spending tokens
Before running a DAG, you can ask Codex to verify it statically. This catches cycles, dangling dependsOn, unknown phase references, and malformed configs — all at zero token cost:
{
"name": "review-changes"
}Or render the DAG as a diagram to eyeball its shape:
{
"name": "review-changes"
}Long-running flows
taskflow_run is synchronous by default, which is ideal when you want the final result in the current turn. For a long DAG, set mode: "background"; Codex receives a durable runId immediately and the worker continues independently.
The plugin ships a 30-minute default tool-call timeout to accommodate this. If your flows run longer, override it in your Codex config:
[mcp_servers.taskflow]
tool_timeout_sec = 3600This timeout applies to foreground calls. For longer work, prefer background mode instead of relying on an oversized request timeout.
Start background work with taskflow_run { name: "...", mode: "background" }, then use taskflow_runs to list, inspect, wait for, or cancel it. A failed or paused run can be continued with taskflow_resume, which forks immutable history into a new child run.
Codex reports token usage but not cost. A Codex flow may use budget.maxTokens; any budget.maxUSD is rejected before execution. The budget is an observed-usage stop-loss, not a zero-overshoot maximum: ordinary calls are admitted serially, while active race branches may overshoot together.
Every child uses --ephemeral --ignore-user-config --ignore-rules and clears mcp_servers, so unrelated parent MCP OAuth failures, plugins, and rules cannot change a phase. The child environment keeps platform/proxy/CA and Codex/OpenAI provider variables only. Add an intentional task variable by name with the comma-separated PI_TASKFLOW_CHILD_ENV_ALLOW operator setting.
Inspect a run after the fact
Every taskflow_run returns a runId. If something went wrong — a gate blocked, a phase produced odd output — you can inspect a single phase's stored output without re-running the whole flow:
{
"runId": "run_2026-07-04_abc123",
"phaseId": "summarize"
}Omit phaseId to list every phase with its status and output size. Output is hard-truncated (default 4000 chars) so a peek never floods your context.
taskflow_peek is the one intentional exception to taskflow's context isolation. It pulls intermediate output into your conversation — use it for debugging, not as part of your normal flow.
Tool reference
Here's the full MCP surface the plugin exposes:
| Tool | Purpose |
|---|---|
taskflow_run | Run a saved flow (by name) or an inline definition (by define). Returns the final output. |
taskflow_runs | List background runs, or status / wait / cancel one by runId. |
taskflow_resume | Fork a failed or paused run into a new immutable child run, with optional one-phase overrides. |
taskflow_version | Report package version, build commit, schema version, build time, and host. |
taskflow_list | List saved flows in the current project. |
taskflow_show | Print a saved flow's JSON definition. |
taskflow_verify | Statically verify a flow (cycles, refs, configs) at zero cost. |
taskflow_compile | Render an inline SVG and text outline plus verification status. |
taskflow_peek | Inspect a stored phase's output for post-hoc debugging. |
taskflow_trace | Read a run's append-only event timeline. |
taskflow_replay | Replay recorded decisions offline with no model calls. |
taskflow_why_stale | Explain dependency staleness at zero tokens. |
taskflow_recompute | Report the stale frontier (MCP is dry-run only). |
taskflow_reconcile_workspace | Explicitly accept an inspected/repaired resolve-only workspace after a dirty-unknown write. |
taskflow_save | Save a reusable flow and optional library metadata. |
taskflow_search | Search and rank reusable flows. |
You rarely need to memorize these. The bundled skill tells Codex which tool fits the request — "verify this flow", "show me the diagram", "run it" all route correctly on their own.
Codex does not enforce tools as a strict name whitelist. Read-only sets map
to -s read-only; mutating or omitted sets map to -s workspace-write.
Thinking maps to model_reasoning_effort (off/none/minimal → none,
max/ultra → xhigh); unsupported values fail before spawn.
Remove
If you need to take taskflow off a machine:
codex plugin remove taskflow@taskflowThis unregisters the MCP server and removes the skill. Any saved flow definitions on disk are left untouched.
Next
Getting Started
The five-minute tour, if you haven't seen it yet.
Phase Types
The twelve building blocks you can compose into a DAG.
Using taskflow on Pi
The same runtime, wired into the Pi coding agent.
Last updated on
Was this helpful?
Help us improve the docs or ask a question in the community.