A workflow template is what a Factory task runs. Warpforge ships three. They are a starting point, not the menu: drop a YAML file in .warpforge/workflows/ and it appears in the Workflow template picker of Factory mode alongside them, for everyone who checks out the repository.
| Built-in | Stages |
|---|---|
Implement + review loop (review-loop) |
implement → review ⇄ fix |
Plan + implement + review loop (plan-review-loop) |
plan → implement → review ⇄ fix |
Implement + verify + review loop (verify-review-loop) |
implement → verify → review ⇄ fix |
The Test in the running app toggle in New Task switches between templates with and without a verify stage: on picks one that has it (verify-review-loop), off goes back to one without. It is shown when the project has a template with a verify stage.
Start from a built-in
Don’t write one from scratch. In the New Task dialog, choose Factory, pick a built-in and choose Copy to project — it writes the template into .warpforge/workflows/<id>.yaml, fully commented, with every stage spelled out. Edit from there.
Copying refuses to overwrite an existing file, so it is safe to press twice.
Where files live, and who wins
-
Workflows are read from
.warpforge/workflows/*.yaml(and.yml) in the project directory. -
The file stem is the id —
strict-review.yamlis the workflowstrict-review. -
A project file with the same id as a built-in replaces it in the picker. Copy
review-loop.yamlin, edit it, and the built-in stops being offered — your version is what the team gets.
Because the files sit in the repository, the process travels with the code instead of living in one person’s settings.
A minimal file
Only name is required. Everything else falls back to Warpforge’s defaults, and any stage you omit still runs.
version: 1
name: Quick review
description: One reviewer, one repair attempt.
review:
max_rounds: 2
reviewers:
- focus: correctness and error handlingThat is a complete workflow. It implements with the agent you picked as Lead, reviews once with a focus line appended to the built-in reviewer prompt, allows one fix, and asks you what to do if findings are still open.
Top level
| Key | Type | Default | Meaning |
|---|---|---|---|
version |
number | 1 |
File format version. Only 1 is understood; anything else makes the file invalid. |
name |
string | — | Required. What the picker shows. |
description |
string | — | One line under the name in the picker. |
plan |
mapping | absent | Enables the planning stage. Omit the key to run without one. |
implement |
mapping | defaults | Implementation stage. |
verify |
mapping | absent | Enables the verification stage: an agent tests the change in the running app. See verify. |
review |
mapping | defaults | Review rounds — see below. |
fix |
mapping | inherits implement |
Repair stage between review rounds. |
An unknown key is a warning, not an error — the workflow still loads, and the picker shows the warning in its tooltip. That keeps a file written for a newer build usable on an older one.
Planning and verification are the real switches
plan and verify are the only stages you can add or remove; the other three always run.
plan: # present with defaults — planning runs
plan: false # planning is off (deleting the key does the same)
verify: # present with defaults — verification runsOmitting implement, review or fix does not remove them — it selects Warpforge’s built-in settings for that stage.
Stage keys
plan, implement and fix all take the same three keys:
| Key | Default |
|---|---|
agent |
The Lead agent picked in the New Task dialog |
model |
The Lead model picked in the New Task dialog, when the stage runs on the Lead agent; otherwise that agent’s own default |
prompt |
Warpforge’s built-in prompt for that stage |
fix is the exception to the fallback: an omitted agent or model there inherits the implement stage rather than the Lead, so the same agent that wrote the code repairs it unless you say otherwise. A model is only ever inherited by a stage on the same agent — a stage that names a different agent and no model runs on that agent’s own default, never on another agent’s model.
Mixing agents per stage is the point — plan with one, implement with another, review with a third:
plan:
agent: claude
implement:
agent: codex
review:
reviewers:
- agent: claudereview
| Key | Type | Default | Meaning |
|---|---|---|---|
max_rounds |
number | 3 |
Review rounds. A fix runs between rounds, so N rounds buy N−1 repair attempts. Must be ≥ 1; values above 5 are clamped with a warning. |
on_limit |
ask | finish |
ask |
What happens when the rounds run out with findings still open. ask suspends and asks you (extend / finish / stop); finish lands the task as Waiting with the open findings in its summary. |
reask |
same_session | fresh |
same_session |
How repeat rounds are staffed. same_session follows up with the reviewer that raised the findings, so it verifies its own — at the cost of some anchoring bias. fresh spawns new reviewers each round, still handed the previous findings to check. |
context |
list | all four | Which sections the built-in reviewer prompt includes: prompt, plan, implementer_summary, diff. |
reviewers |
list | one default reviewer | 1–4 reviewers, run in the same round. |
Reviewers
Each entry takes agent, model, and then one of two ways to steer it:
focus— a sentence appended to the built-in reviewer prompt. The light touch.prompt— a full replacement. You decide everything the reviewer sees.
review:
max_rounds: 4
on_limit: finish
reask: fresh
reviewers:
- agent: claude
focus: correctness, error handling, and edge cases
- agent: codex
focus: performance and unnecessary allocationverify
The verification stage tests the change the way a QA engineer would. After the implementation, and again after a fix, an agent starts the project’s dev services, works out a test plan from the task, walks through it in the in-app browser, checks the browser console for errors, and takes screenshots of the key states. It ends with pass, fail, or blocked (it could not test at all), plus a checklist of what it tried.
| Key | Type | Default | Meaning |
|---|---|---|---|
agent |
string | the Lead agent | Who tests. |
model |
string | the Lead model on the Lead agent, else the agent’s default | |
instructions |
string | — | Added to the built-in testing prompt: logins, seed data, the page to start from. |
required |
boolean | true |
true: review never starts without a pass. false: a failed or impossible check is noted and review goes on. |
max_attempts |
number | 2 |
How many times in a row verification may fail before the pipeline asks you. Must be ≥ 1; values above 5 are clamped with a warning. |
version: 1
name: QA + review
description: Test every change in the running app before review.
verify:
agent: claude
instructions: |
Sign in as demo@example.com / demo. Billing lives under Settings → Billing.
max_attempts: 2
review:
max_rounds: 3How it fits the pipeline:
- Placement.
implement → verify → review ⇄ fix. A fix that follows a failed verification is always verified again. A fix that follows a review is verified again when it changed the code. - A failure goes to the fixer, not the reviewers. The failed steps become the fix stage’s findings (
{{findings}}), so reviewers only see work that passed. - Out of attempts. When verification has failed
max_attemptstimes in a row, or could not run, the task moves to Needs you with three choices: try again (another fix, then another check), continue to review without a pass, or stop. Anything you type goes to the next attempt as guidance. - Evidence. Every screenshot the tester takes is kept with the pipeline and shown on its verify stage in the Pipeline view. The verdict, the checklist and the screenshots are part of the pipeline’s final summary.
Placeholders
A custom prompt may interpolate {{name}}. An unknown placeholder is a validation error, not a blank — a typo like {{taks_prompt}} fails the file with the offending name rather than quietly sending an agent a prompt with a hole in it.
| Placeholder | plan |
implement |
review |
fix |
|---|---|---|---|---|
{{task_prompt}} — what you typed |
✓ | ✓ | ✓ | ✓ |
{{plan}} — the approved plan |
✓ | ✓ | ✓ | |
{{implementer_summary}} — the last implement/fix session’s closing message |
✓ | ✓ | ||
{{diff}} — the working-copy diff |
✓ | ✓ | ||
{{findings}} — what the reviewers raised, or what verification found |
✓ | |||
{{round}}, {{max_rounds}} — where the loop is |
✓ | ✓ | ||
{{focus}} — that reviewer’s focus line |
✓ |
{{plan}} is only allowed when the file has a planning stage, and {{focus}} only in a reviewer that defines one — a placeholder nothing can fill would render as an empty section, so it is rejected up front instead.
A worked example
Two reviewers with different jobs, on different agents, and a hard stop rather than a question:
version: 1
name: Ship it
description: Plan, implement on Codex, review on two agents, land without asking.
plan:
agent: claude
prompt: |
Produce a short implementation plan: files to touch, approach, edge cases,
and how to verify. Do not edit files. End with the complete plan, because
it is handed to the implementer verbatim.
## Task
{{task_prompt}}
implement:
agent: codex
review:
max_rounds: 4
on_limit: finish
reask: fresh
reviewers:
- agent: claude
focus: correctness, edge cases, and error handling
- agent: codex
focus: tests — is the new behaviour actually covered?
fix:
agent: codexWhen a file is wrong
Invalid workflows are not hidden. They stay in the picker, greyed out, with the reason in the tooltip — including the line and column for a YAML error — so a broken file is something you notice and fix rather than something that silently disappears.
Errors that reject a file: a missing name, an unsupported version, max_rounds: 0, max_attempts: 0, an unknown value for on_limit, reask or context, more than four reviewers, and any unknown placeholder. Warnings that still load: unknown keys, max_rounds or max_attempts above the cap, an empty context, and context or focus set where a custom prompt makes them inert.