Using taskflow on OpenCode
Register taskflow as an MCP server on OpenCode and orchestrate multi-phase workflows.
OpenCode 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 OpenCode, taskflow is exposed as a dependency-free MCP server, so the taskflow_* tools appear inside the session and each phase's subagent runs as an isolated opencode run process.
This page walks through the whole arc: register the MCP server, confirm it's live, run a flow through a tool call, and understand the permission and model-resolution model.
Install
OpenCode has no git-based plugin marketplace, so you register the MCP server directly — either with the CLI or by editing your opencode.json.
Option A: the CLI
opencode mcp add taskflow -- npx -y -p opencode-taskflow opencode-taskflow-mcpOption B: edit opencode.json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"taskflow": {
"type": "local",
"command": ["npx", "-y", "-p", "opencode-taskflow", "opencode-taskflow-mcp"],
"enabled": true
}
},
"skills": {
"paths": ["./node_modules/opencode-taskflow/plugin/skills"]
}
}The command runs via npx (a version-pinned opencode-taskflow), so the server is fetched and launched on demand — nothing else to install globally, and the pin binds the exact code that runs.
The skills.paths entry is optional. OpenCode auto-discovers **/SKILL.md skills (including Claude Code .claude/skills), and the taskflow tools are self-describing, so the routing skill just helps OpenCode reach for them at the right time. A ready-to-copy opencode.json ships in the package's plugin/ directory.
Verify the install
Before running anything, confirm the MCP server registered cleanly:
opencode mcp list # taskflow should appear, enabledIf it's missing, the mcp add step didn't complete — re-run it and check for errors.
Run your first flow
On OpenCode, 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 routing skill. So the most natural way to start is to just describe the work.
Just ask
Try one of these in an OpenCode 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 OpenCode 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"
}taskflow_compile returns the DAG grouped into topological layers as a text outline, plus an inline SVG image for clients that render images.
How subagents run
Each phase's subagent runs as an isolated opencode run process — a real OpenCode session, not a pi process. The server discovers saved flows and agents from its launch cwd, so the project you start it in determines which flows are visible.
Permission mapping
OpenCode has no per-run tool-whitelist flag, but it honours a per-process config injected via the OPENCODE_CONFIG_CONTENT env var. The runner maps each phase's tool whitelist to a permission policy:
| Phase tools | Permission policy | What it means |
|---|---|---|
Read-only (no write/edit/bash) | Injected policy that denies bash/write/edit | A denied tool call is genuinely rejected (not merely un-approved). This is real enforcement, closer to a read-only OS sandbox than an advisory whitelist. |
| Mutating (or no whitelist) | opencode run --auto | Auto-approves every permission — the workspace-write analogue. Run flows you trust, ideally in a throwaway worktree (cwd: "worktree"). |
Mutating phases run with --auto and auto-approve every permission. Prefer a throwaway worktree (cwd: "worktree") for flows that touch the filesystem, and only run flows you trust.
Model resolution
OpenCode model ids are provider/model (e.g. anthropic/claude-sonnet-4-5). Because a valid OpenCode id contains a slash, the runner does not reuse the codex/claude "contains / ⇒ drop" rule. It drops only ids that clearly aren't OpenCode models:
- An unresolved role placeholder (
{{fast}}) - A pi thinking suffix (
…:xhigh) - A multi-segment openrouter path (
openrouter/vendor/model, ≥ 2 slashes)
A dropped id falls back to OpenCode's configured default model.
Long-running flows
Here's the one thing to know about running taskflow on OpenCode: taskflow_run is synchronous. The tool call doesn't return until the entire DAG finishes — every phase, every subagent. For a three-phase review that's fine; for a fan-out over fifty files with a tournament at the end, it can take a while.
If a flow is genuinely huge, consider splitting it into a few smaller taskflow_run calls so each returns promptly, or run it in the background from a plain shell:
opencode run "run the nightly-audit taskflow" &Then inspect the run afterward with taskflow_peek:
{
"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.
Approvals in MCP mode
MCP-driven runs are non-interactive, so an approval phase auto-rejects (fail-open). Prefer a gate (agent review) in flows you run through the taskflow_* tools; use approval only in flows a human runs interactively.
Tool reference
Here's the full MCP surface the server exposes:
| Tool | Purpose |
|---|---|
taskflow_run | Run a saved flow (by name) or an inline definition (by define). Returns the final output + a runId. |
taskflow_list | List saved flows discoverable from the cwd, with library metadata when available. |
taskflow_show | Show a saved flow's definition plus its library sidecar metadata. |
taskflow_save | Save a flow to the library with optional purpose, tags, and notes. |
taskflow_search | Search the library before authoring. Returns ranked reusable flows. |
taskflow_verify | Statically verify a flow (cycles, refs, configs) at zero cost. |
taskflow_compile | Render the DAG as a text outline + inline SVG. |
taskflow_peek | Inspect a stored phase's output for post-hoc debugging. |
You rarely need to memorize these. The bundled skill tells OpenCode which tool fits the request — "verify this flow", "show me the diagram", "run it" all route correctly on their own.
Alternative: run from a repo checkout
If you'd rather not install the package, build from a checkout of this repo and point OpenCode at the built bin:
pnpm run build
opencode mcp add taskflow -- node /abs/path/to/taskflow/packages/opencode-taskflow/dist/mcp/bin.jsThe server behaves identically to the npx version.
Remove
If you need to take taskflow off a machine:
opencode mcp remove taskflow # or delete the mcp.taskflow entry from opencode.jsonAny 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 ten building blocks you can compose into a DAG.
Using taskflow on Claude Code
The same runtime, wired into Claude Code.
Last updated on
Was this helpful?
Help us improve the docs or ask a question in the community.