taskflow

Templates

Five ready-to-run taskflow templates you can save and adapt.

Templates are complete, runnable taskflow definitions for common agent workflows. Each one is a real JSON graph you can save verbatim and run, then tune for your own repo. They are not toy examples — every phase, dependency, and field here is one you would write in production.

These templates run identically on Pi (/tf run) and on Codex / Claude Code / OpenCode (taskflow_run). See the Pi guide or Codex guide for the host-specific invocation surface.

Save any template as a .json file in your project, then verify it for free before running:

Verify before you run
/tf verify <name>

1. PR Security Audit

Discover the files a pull request touches, fan out a per-file security review with bounded concurrency, run a parallel architecture review at the same time, gate the whole thing on risk, and finish with one merged report. Only the report returns to your context — the per-file transcripts stay inside the runtime.

pr-security-audit.json
{
  "name": "pr-security-audit",
  "description": "Audit a pull request: discover changed files, fan out per-file security review, run a parallel architecture review, gate on risk, and emit one merged report.",
  "args": {
    "base": { "default": "origin/main", "description": "The git ref to diff against." }
  },
  "concurrency": 6,
  "budget": { "maxUSD": 3.0 },
  "phases": [
    {
      "id": "discover",
      "type": "agent",
      "agent": "scout",
      "task": "List the source files changed between {args.base} and HEAD. Output ONLY a JSON array of {\"path\": \"<relative-path>\"} objects. No prose.",
      "output": "json",
      "expect": { "type": "array", "items": { "type": "object" } },
      "retry": { "max": 2, "backoffMs": 1000, "factor": 2 }
    },
    {
      "id": "security-each",
      "type": "map",
      "over": "{steps.discover.json}",
      "as": "file",
      "agent": "security-reviewer",
      "task": "Review {file.path} for security risks: missing auth checks, unsanitized input, hardcoded secrets, unsafe deserialization. Return one paragraph of findings, or 'No issues found.' if clean. Begin with the file path.",
      "dependsOn": ["discover"],
      "concurrency": 4,
      "context": ["{file.path}"],
      "retry": { "max": 2, "backoffMs": 1000, "factor": 2 }
    },
    {
      "id": "arch-review",
      "type": "parallel",
      "branches": [
        {
          "task": "Review the changed files for layering violations, leaked internals, and missing abstractions. Return a short prioritized list.",
          "agent": "reviewer"
        }
      ],
      "concurrency": 2
    },
    {
      "id": "risk-gate",
      "type": "gate",
      "agent": "reviewer",
      "dependsOn": ["security-each", "arch-review"],
      "join": "all",
      "task": "You are the final risk gate. If any finding is high-risk (missing auth, secret leak, broken layering, data-loss path), end with: VERDICT: BLOCK. Otherwise end with: VERDICT: PASS.\n\nSecurity:\n{steps.security-each.output}\n\nArchitecture:\n{steps.arch-review.output}",
      "onBlock": "halt"
    },
    {
      "id": "report",
      "type": "reduce",
      "from": ["security-each", "arch-review", "risk-gate"],
      "agent": "writer",
      "task": "Write the final PR review report: 1) Risk verdict, 2) Security findings (prioritized), 3) Architecture findings (prioritized), 4) Recommended actions before merge. Be concise.\n\nSecurity:\n{steps.security-each.output}\n\nArchitecture:\n{steps.arch-review.output}\n\nGate verdict:\n{steps.risk-gate.output}",
      "dependsOn": ["risk-gate"],
      "final": true
    }
  ]
}
Run on Pi
/tf run pr-security-audit base=origin/main
Save as a shortcut
/tf save pr-security-audit
/tf:pr-security-audit base=origin/main
Run on Codex
taskflow_run { "name": "pr-security-audit", "args": { "base": "origin/main" } }

Walk through how this flow is built incrementally — discover, fan out, gate, report — in the code audit case study.


2. Release Note Generation

Research the feature into a shared set of facts, run a four-variant tournament to pick the strongest headline, then assemble a full release note from the research and the winning headline. The losing headlines and the judge's reasoning are discarded; only the finished note reaches your context.

release-note.json
{
  "name": "release-note",
  "description": "Research a feature, run a 4-variant headline tournament, and assemble a full release note.",
  "args": {
    "feature": { "description": "The feature to write a release note for.", "required": true }
  },
  "concurrency": 6,
  "budget": { "maxUSD": 1.5 },
  "phases": [
    {
      "id": "research",
      "type": "agent",
      "agent": "scout",
      "task": "Read the diff and release notes for {args.feature}. Summarize in 5 bullets: what it does, who it helps, and the single most surprising benefit. Return bullets only.",
      "output": "json",
      "retry": { "max": 2, "backoffMs": 1000, "factor": 2 }
    },
    {
      "id": "headline",
      "type": "tournament",
      "agent": "writer",
      "dependsOn": ["research"],
      "task": "Write a punchy release-note headline based on the research below. It must be accurate and under 80 characters. Return ONLY the headline.\n\n{steps.research.output}",
      "variants": 4,
      "judge": "Pick the headline that is the most punchy while staying accurate and under 80 characters. Prefer specific over generic.",
      "judgeAgent": "final-arbiter",
      "mode": "best"
    },
    {
      "id": "note",
      "type": "reduce",
      "from": ["research", "headline"],
      "agent": "writer",
      "task": "Assemble a complete release note. Use the winning headline as the title, then write a 2-3 paragraph body from the research. End with a one-line 'How to try it' call to action.\n\nHeadline:\n{steps.headline.output}\n\nResearch:\n{steps.research.output}",
      "dependsOn": ["headline"],
      "final": true
    }
  ]
}
Run on Pi
/tf run release-note feature="subagent context isolation"
Save as a shortcut
/tf save release-note
Run on Codex
taskflow_run { "name": "release-note", "args": { "feature": "subagent context isolation" } }

The headline tournament is explained end to end — variants, judge rubric, and best vs aggregate modes — in the tournament case study.


3. Codebase Migration

Discover every call site of a legacy API, plan the migration per file, gate the plan for safety, then loop: re-plan based on what remains until no old calls are left. The runtime validates any model-authored sub-flow before it executes, so a bad plan never crashes the run.

codebase-migration.json
{
  "name": "codebase-migration",
  "description": "Iteratively re-plan a legacyAuth() -> authorize() migration until no calls remain, then execute the final plan.",
  "args": {
    "oldApi": { "default": "legacyAuth()", "description": "The old API call to migrate away from." },
    "newApi": { "default": "authorize()", "description": "The new API to migrate to." }
  },
  "concurrency": 4,
  "budget": { "maxUSD": 4.0 },
  "phases": [
    {
      "id": "refine",
      "type": "loop",
      "agent": "planner",
      "task": "Inspect the codebase for remaining calls to {args.oldApi}. If any remain, output {\"plan\": <taskflow-definition that fixes the remaining files>, \"done\": false}. If none remain, output {\"done\": true}. The plan, when present, must be a JSON taskflow with a 'name' and a 'phases' array.",
      "until": "{steps.refine.json.done} == true",
      "maxIterations": 6,
      "output": "json"
    },
    {
      "id": "execute-final",
      "type": "flow",
      "def": "{steps.refine.json.plan}",
      "when": "{steps.refine.json.done} == false",
      "dependsOn": ["refine"],
      "final": true
    }
  ]
}
Run on Pi
/tf run codebase-migration oldApi=legacyAuth\(\) newApi=authorize\(\)
Save as a shortcut
/tf save codebase-migration
Run on Codex
taskflow_run { "name": "codebase-migration", "args": { "oldApi": "legacyAuth()", "newApi": "authorize()" } }

The full plan → gate → execute → loop cycle, including dynamic hardening caps, is walked through in the migration planner case study.


4. API Doc Generation

Discover the public API surface of a directory, draft reference documentation for each file in parallel, then reduce the drafts into one coherent API reference document. The per-file drafts stay inside the runtime; only the compiled reference returns to your context.

api-docs.json
{
  "name": "api-docs",
  "description": "Discover public API surface, draft per-file reference docs, and merge into one document.",
  "args": {
    "dir": { "default": "src", "description": "The source directory to document." }
  },
  "concurrency": 4,
  "budget": { "maxUSD": 2.0 },
  "phases": [
    {
      "id": "discover",
      "type": "agent",
      "agent": "scout",
      "task": "List the source files under {args.dir} that export a public API (exported functions, classes, types). Output ONLY a JSON array of {\"path\": \"<relative-path>\", \"module\": \"<module-name>\"} objects. No prose.",
      "output": "json",
      "expect": { "type": "array", "items": { "type": "object" } },
      "retry": { "max": 2, "backoffMs": 1000, "factor": 2 }
    },
    {
      "id": "draft-each",
      "type": "map",
      "over": "{steps.discover.json}",
      "as": "file",
      "agent": "writer",
      "task": "Write reference documentation for the public API in {file.path} (module: {file.module}). For each export: a one-line summary, parameter descriptions, return type, and one usage example. Use Markdown. Begin with a '## {file.module}' heading.",
      "dependsOn": ["discover"],
      "concurrency": 4,
      "context": ["{file.path}"],
      "retry": { "max": 2, "backoffMs": 1000, "factor": 2 }
    },
    {
      "id": "compile",
      "type": "reduce",
      "from": ["draft-each"],
      "agent": "writer",
      "task": "Compile the per-module drafts into a single API reference document. Add a top-level title and a table of contents listing each module. Deduplicate cross-referenced types. Preserve the per-module sections in dependency order.\n\n{steps.draft-each.output}",
      "dependsOn": ["draft-each"],
      "final": true
    }
  ]
}
Run on Pi
/tf run api-docs dir=src
Save as a shortcut
/tf save api-docs
Run on Codex
taskflow_run { "name": "api-docs", "args": { "dir": "src" } }

The discover phase is a pure function of the codebase. Mark it cross-run with a glob!: fingerprint so a re-run after an unrelated change reuses the cached discovery — only files that actually changed get re-documented.


5. Dependency Upgrade Review

Enumerate the project's outdated dependencies, evaluate each for breaking-change risk in parallel, gate on any critical finding, and finish with a prioritized upgrade plan. The gate can halt the run before the plan is written if a dependency is too dangerous to upgrade blindly.

dep-upgrade-review.json
{
  "name": "dep-upgrade-review",
  "description": "Enumerate outdated dependencies, evaluate breaking-change risk, gate on criticals, and emit a prioritized upgrade plan.",
  "args": {
    "manager": { "default": "npm", "description": "The package manager to query (npm, pnpm, yarn)." }
  },
  "concurrency": 4,
  "budget": { "maxUSD": 2.0 },
  "phases": [
    {
      "id": "discover",
      "type": "agent",
      "agent": "scout",
      "task": "Run `{args.manager} outdated --json` (or the equivalent) and list every outdated dependency. Output ONLY a JSON array of {\"name\": \"<package>\", \"current\": \"<version>\", \"wanted\": \"<version>\", \"latest\": \"<version>\"} objects. No prose.",
      "output": "json",
      "expect": { "type": "array", "items": { "type": "object" } },
      "retry": { "max": 2, "backoffMs": 1000, "factor": 2 }
    },
    {
      "id": "evaluate-each",
      "type": "map",
      "over": "{steps.discover.json}",
      "as": "dep",
      "agent": "risk-reviewer",
      "task": "Evaluate the risk of upgrading {dep.name} from {dep.current} to {dep.latest}. Check the changelog for breaking changes, deprecations, and peer-dependency shifts. Return: package name, risk level (LOW|MEDIUM|HIGH|CRITICAL), a one-sentence reason, and a recommended action (safe-to-upgrade|test-first|pin-major|hold). Begin with the package name.",
      "dependsOn": ["discover"],
      "concurrency": 4,
      "retry": { "max": 2, "backoffMs": 1000, "factor": 2 }
    },
    {
      "id": "risk-gate",
      "type": "gate",
      "agent": "reviewer",
      "dependsOn": ["evaluate-each"],
      "join": "all",
      "task": "You are the upgrade risk gate. If any dependency is rated CRITICAL (a known breaking change with no migration path, or a security-sensitive package), end with: VERDICT: BLOCK. Otherwise end with: VERDICT: PASS.\n\n{steps.evaluate-each.output}",
      "onBlock": "halt"
    },
    {
      "id": "plan",
      "type": "reduce",
      "from": ["evaluate-each", "risk-gate"],
      "agent": "writer",
      "task": "Write a prioritized dependency upgrade plan. Group by risk level (CRITICAL first, then HIGH, MEDIUM, LOW). For each dependency: the recommended action and a one-line reason. End with a suggested upgrade order that respects peer-dependency constraints.\n\n{steps.evaluate-each.output}\n\nGate verdict:\n{steps.risk-gate.output}",
      "dependsOn": ["risk-gate"],
      "final": true
    }
  ]
}
Run on Pi
/tf run dep-upgrade-review manager=npm
Save as a shortcut
/tf save dep-upgrade-review
Run on Codex
taskflow_run { "name": "dep-upgrade-review", "args": { "manager": "npm" } }

The risk-gate uses onBlock: "halt". If a CRITICAL dependency is found, the run stops before the plan phase runs — you get the gate's verdict instead of a plan that would greenlight a dangerous upgrade. Drop the gate (or set onBlock: "continue") if you always want the plan, regardless of risk.


Adapting a template

Every template above is a starting point, not a prescription. The knobs worth turning are the same across all of them:

  • concurrency — raise it on a generous rate limit to finish faster; lower it to avoid 429s. The retry policy absorbs the rest.
  • budget — the run-wide cost ceiling. A BLOCK verdict or budget breach halts the run before downstream phases spend more tokens.
  • cache — mark pure, expensive phases (discover, per-file reviews) cross-run with a git:HEAD or glob!: fingerprint so re-runs reuse work whose inputs did not change.
  • retry — two attempts with exponential backoff covers most transient provider errors. Raise max for phases that hit larger models.

Always run /tf verify <name> on a template after you edit it. Verification is zero-token and catches the vast majority of authoring mistakes — cycles, dead-ends, dangling references — before you spend anything.

Where to go next

Last updated on

Was this helpful?

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

On this page