Skip to content

Workflows

A Workflow is a graph you draw. You place nodes — agent runs, loops, prototypes, decisions, human approvals — connect them, and save the result as a reusable definition. Firing it starts a workflow run, which walks the graph one node at a time.

Where a Run is one agent doing one thing, and a Loop is one agent iterating until a verifier agrees, a workflow is the thing that puts several of those in a row and decides what happens next based on how each one turned out.

You build a workflow on a blank canvas. Drag on the nodes you need — Agent Run, Loop and Prototype to do work; Decision and Human Approval to route — and connect them with edges. A work node takes exactly one outgoing connection; only a Decision or Approval fans out, one edge per labelled branch it can produce (see The five node kinds and How a Decision decides below). A connection can also point backwards — drawn dashed and capped ⟲ max N — so a “review failed → fix → review again” cycle is expressible without running forever (see Bounded loop-backs). Save the graph as a reusable definition; firing it starts a run.

Every node in a single workflow run shares one DevBox and one git branch, named wf/<slug>/run-<n>.

That is the whole point. The second node sees the files the first node wrote. A decision can test the repository the run has been building. A loop can pick up where an earlier run node left off. Without a shared workspace a graph of agents is just a list of unrelated tasks.

The DevBox is created by the first node that needs one and handed down the graph from there. You can also pin a workflow to an existing DevBox, in which case every run works in that same persistent environment instead of a fresh one.

Three kinds do work. Each one produces its own entity, with its own page you can open and read exactly as if you had started it by hand.

NodeWhat it doesProduces
Agent RunOne autonomous agent run against a prompta Run
LoopIterates until an independent verifier approvesa Loop
PrototypeRaces several engine+model variants on one briefa Prototype

Two kinds route. They do no work themselves; they decide where the run goes next.

NodeWhat it does
DecisionPicks a branch from the previous node’s result
Human ApprovalStops and waits for a person, then takes their answer’s branch

An Agent Run, a Loop and a Prototype each take exactly one outgoing connection. Only Decision and Approval nodes fan out, onto as many labelled branches as you draw.

This is enforced while you draw: once a work node has its one exit, its connection points dim and refuse a second. To split a path, put a Decision or an Approval in between. That constraint is what keeps a graph readable — every fork is an explicit, labelled, inspectable choice rather than an implicit one.

A Decision node picks its branch using one of three evaluators:

  • Status — routes on the previous node’s own result. No extra work, no agent, no cost.
  • Command — runs a command inside the run’s shared DevBox. Exit code 0 takes the pass branch; anything else takes fail. This is how you route on “do the tests actually pass”, not on what an agent claims. It runs from one specific repository’s checkout — see Where a Command decision runs.
  • Agent — asks an agent to judge, and offers your branch labels as the only answers it may give.

A Command decision is a bare command — npm test, pytest, make check — and what it means depends entirely on the directory it runs in. It runs from the checkout of the repository the run’s DevBox was launched for:

  1. the workflow’s own Repository setting, if you set one;
  2. otherwise the repoUrl the run was started with, if any;
  3. otherwise the first repository in the project’s list.

That repository always takes its own short name as its folder. Every other repository in the project is cloned beside it, and a name already taken is qualified with its owner:

/home/developer/
core/ # acme/core — launched for, so a Command decision runs here
connectors/ # acme/connectors
docs/ # acme/docs
other-org-core/ # other-org/core — "core" was taken

Which repository is “launched for” therefore decides the folder names as well. In a project holding acme/core and other-org/core, a workflow whose Repository is set to other-org/core gets the layout above reversed: other-org/core becomes core/, and acme/core becomes acme-core/.

To check a different repository, say so in the command. Change the directory as part of it:

Terminal window
sh -c "cd ../other-org-core && npm test"

Two things to get right:

  • Double quotes only. The command field understands "..." and nothing else. sh -c 'cd ../other-org-core && npm test' is split on the spaces, the shell receives an unterminated quote, and the decision routes fail — which reads exactly like failing tests.
  • Paths are relative to the launched-for repository’s checkout, so a sibling is ../<folder>.

A Status decision offers the branch labels that its predecessor can actually produce — and those differ by node kind, because the three kinds have genuinely different outcomes. The canvas offers you the right set as one-click chips; you never have to remember them.

PredecessorBranch labels it can produce
Agent Runcompleted · failed · skipped · stopped
Loopverified · needs_owner · budget_exhausted · no_progress · circuit_broken · error · user_cancelled
Prototypecompleted · failed · cancelled · archived

A loop’s labels are its stop reasons, because a loop has no other verdict to report — “why did you stop” is its outcome. That is what makes verified → ship, no_progress → ask a human expressible as a graph.

Every routing node also accepts a default branch, which catches anything the other labels did not match. If a result matches no branch and there is no default, the run fails rather than quietly stopping — a graph that silently does nothing is worse than one that tells you it has a hole.

A connection may point backwards, which is how “review failed → fix → review again” is expressible without a separate construct. A backwards connection is drawn dashed and carries a cap: ⟲ max N.

The cap is what makes it finite. When a back-edge has been traversed N times the run stops with back_edge_exhausted rather than cycling forever. If you want something better than a failure at the end of the rope, wire an explicit give-up branch off the decision — for example a Human Approval that asks you whether to keep going.

A node re-entered by a back-edge shows a ×N badge in the run trace, so you can see at a glance which parts of the graph the run went around more than once.

Firing a workflow snapshots its definition. Editing the workflow afterwards never changes a run that is already in flight, and never rewrites the history of one that has finished — a run is a record of what was actually executed. To change a single run instead, edit its steps from the run page (see Changing a run after it starts).

The run page shows the graph with each node coloured by status alongside an execution order timeline: one row per node attempt, with its kind, duration and cost, and a link straight into the entity that node produced. Costs roll up from those entities to the run total, so a workflow’s price is the real sum of the work it did.

The definition page keeps the full run history for that workflow, and while one is in flight it carries a live banner through to it.

A firing walks the graph one node at a time, all of it in the run’s one shared DevBox on its one branch — the same workspace every node before it has been writing to. Open the run and you watch that walk happen: each node lights up as it starts, and finishes into whichever status its kind can produce before the run moves to whatever the graph says comes next.

If the graph carries a Human Approval node, the run stops there and waits — its status parks until someone answers, however long that takes — then resumes down whichever branch the answer selects.

A run works from the snapshot taken when it was fired, but that snapshot is not frozen for good. From the run page you can change a step the run has not reached yet, or send the run back to a step and start again from there. Both change this run only: the saved workflow definition is never touched, so the next firing still uses the graph you saved.

Click a node on the run page to open its panel. The buttons at the bottom of that panel depend on where the node sits relative to the run. You only see them if you can manage workflows.

On an active run, a step that is still ahead of the run shows Edit step. “Ahead” means reachable from the step the run is on now by following the graph, which includes a step that a review loop-back can send the run back to.

Edit step opens a dialog titled Edit "<step>" holding only that step’s own settings: its prompt, engine and model, timeout, a decision’s command, an approval’s question, and so on. Click Save edit. Nothing is stopped; the run carries on with its current step, and the edited step runs with the new settings when the run gets to it. A toast confirms this, and the run’s timeline records a marker:

✎ Edited "<step>" by <you> · applies when the run reaches it

If the run reaches that step before you save, the edit is refused and the dialog tells you to restart from the step instead. Edits apply one step at a time. A step the run has already passed can’t be edited this way, because the run will not reach it again unless you restart from it.

Every node also shows a restart button, worded for where it sits:

ButtonShown on
Stop, edit & restartthe step the run is on now
Stop, edit & restart from hereany other step of an active run, including a run waiting at a Human Approval
Edit & restart from hereany step of a finished run: completed, failed or cancelled

The dialog lets you change the step’s settings before it runs again, and the run’s inputs as well. The one exception is a run started by a schedule’s fan-out: its input values are what identify it, so the dialog shows them but won’t let you change them. Leave the fields as they are to restart with the same settings.

When you confirm, the run goes back to that step and continues through the graph from there. Before you do, the dialog spells out what that means:

  • On an active run, the step running now is stopped.
  • Git is not rewound. The run has one branch that every step shares, so commits made by later steps stay on it. The restarted step continues on top of them, not from the state it originally saw.
  • Loop limits downstream are reset. Any capped loop-back reachable from the step gets its full ⟲ max N budget again, and the dialog says how many edges that affects.
  • Re-opening a finished run uses one of your concurrent workflow-run slots, the same as firing a new one. If the run’s DevBox has been stopped it is started again. If that isn’t possible, the step starts on a fresh DevBox from the branch as it was last pushed, and any uncommitted work is lost.

Earlier attempts are not deleted. They stay in the run’s timeline, marked as superseded, and what they cost still counts toward the run total. The timeline also records the restart:

⟲ Restarted from "<step>" (was on "<other step>") by <you> · loop limits reset

Because a finished run can be re-opened this way, cancelling a run is not final: a cancelled run can be picked up again from any of its steps.

A Schedule can fire a workflow the same way it fires a run — on a cron expression, or on an interval. The schedule references the workflow by id, so it always fires the current saved definition.

Drawing a graph from an empty canvas is the slow way to start. The Workflow Library is a docked panel on the Workflows page — titled “Workflow Library”, collapsed by default — with 11 curated graphs for common shapes: an issue taken all the way to a merge-ready PR, a tournament between two competing approaches, a progressive rollout with auto-rollback. Picking one is different from the Loop Library: Use navigates you away, to /workflows/new?template=<id>, and opens the graph editor there already populated — every node, every labelled edge, every capped back-edge, laid out and ready to read. As with the Loop Library, the host axis is left blank — worker, DevBox, image, repository travel with your account, not the template — so you always fill those in before you can save and fire it.

TemplateWhat it does
Hello, workflowA read-only tour of your repository, then a branch on how it went — the smallest graph that is still a workflow.
Fix until greenDo the work, re-check, loop back on failure up to three times, then ask a human before shipping.
Issue → agent review → your approvalOne agent implements a fix, a fresh agent reviews the diff against the issue, and you approve the resulting PR.
Tight loopBuild and test in one node, gate on the real test command, loop back until it exits 0.
Triage routerReads an issue once, classifies what it really is, then hands it to the right downstream handler.
Adversarial verificationOne agent builds it, a fresh agent tries to refute it, and the verdict decides whether to redo the work.
Tournament of approachesTwo candidate implementations on two branches, judged head-to-head by an agent decision, winner shipped.
Progressive rollout with auto-rollbackBuilds, gates on tests, deploys behind a flag, raises traffic in steps, and rolls back automatically when health drops.
Closed observability loopShips the change, watches production for anomalies over a real observation window, and feeds what the telemetry says back into the fix.
The SDLC, drawn as a graphThe whole lifecycle as ten explicit nodes, using every node kind, with both its review and monitoring cycles drawn and capped.
Issue in, merge-ready PR outSixteen nodes, two capped loops, exactly one human gate — the graph translation of ClusterCode’s own autonomous delivery skill.

Every workflow page has a More actions menu (…) in its header, and it’s how you back a workflow up or copy it somewhere else.

  • Export, on a workflow’s own page, downloads it as a .ccbackup file named after the workflow: Nightly triage becomes nightly-triage.ccbackup.
  • Import, on the Workflows page or any workflow’s page, opens a file picker that only accepts .ccbackup files. A valid backup opens the graph editor already filled in, just like picking a template from the library. Nothing is saved until you save it, and it’s saved as a new workflow.

A backup carries what a library template carries: the name, description, timeout, repository and the whole graph. The host stays blank, the same as with a template, because worker, DevBox and image belong to your account and not to the file. You pick those before saving, which also makes a backup the way to copy a workflow into another account. Import is offered to anyone who can create workflows.

If the file isn’t a valid backup (a different kind of file, a damaged file, or one edited into the wrong shape), a dialog tells you so and nothing is opened. A loop backup imported here opens the Loops create panel instead, so you don’t need to find the right page first.

On a phone, the header’s other actions fold into the same … menu.

Workflows is available on every plan, including Free.

The plan limit is on concurrently active workflow runs, not on how many workflows you have drawn. Saving definitions is unlimited on every plan; what a higher plan buys you is more of them running at the same time.

  • Create a Workflow — draw and fire your first one
  • Loops — the iterate-until-verified node, on its own
  • Prototyping — the race-N-engines node, on its own
  • Runs — what a single agent run is
  • Schedules — firing a workflow on a timer