Workflows
Workflows
Section titled “Workflows”Colony pipelines are defined as workflows — YAML state machines that control how issues move through the pipeline. Colony ships with one built-in workflow (colony-default) that covers the standard analyze → develop → review → merge lifecycle. You can replace it with a custom workflow per-tenant.
YAML schema
Section titled “YAML schema”Every workflow file must satisfy schema_version: 1. The top-level keys are:
schema_version: 1
workflow: id: my-workflow # kebab-case slug, unique identifier name: "My pipeline" # human-readable label version: 1 # positive integer, incremented on each change description: "..." # optional
intake: initial_state: new # slug of the first state issues enter trigger_label: colony:enqueue # optional GitHub label that seeds an issue
states: <slug>: # ... per-state fields
operator_actions: <slug>: # ... per-action fieldsState slugs
Section titled “State slugs”State and action keys must be kebab-case slugs: lowercase letters, digits, and hyphens; 1–64 characters; must start with a letter or digit.
States
Section titled “States”The states key is a record of slug → state definition. Each state has the following fields:
| Field | Required | Description |
|---|---|---|
type | yes | State trait — see State traits |
executor | no | Which executor to run — see ExecutorRef |
recovery | yes (if type: blocked) | How the state recovers: manual or auto |
label | no | GitHub label string for this state (cosmetic) |
on | no | Outcome → route map — see Outcome routing |
transitions | no | Array of state slugs that operators can manually target from this state |
hooks | no | Terminal-only post-completion hooks — see Hooks |
State traits
Section titled “State traits”The type field controls the lifecycle semantics of a state:
| Trait | Meaning |
|---|---|
active | Worker picks up a task and runs the state’s executor |
blocked | Issue is blocked; must declare recovery: manual or recovery: auto |
awaiting-human | Issue is waiting for human input; no executor runs |
terminal | Issue is complete; must not declare executor or transitions |
ExecutorRef
Section titled “ExecutorRef”The executor field takes a reference string in one of two forms:
builtin:<name> # e.g. builtin:analyze, builtin:developplugin:<package>/<name> # e.g. plugin:colony-content/analyzeBuilt-in executors are provided by Colony itself. Plugin executors are declared by a registered plugin — see Plugins.
Outcome routing
Section titled “Outcome routing”The on key maps executor outcome names to state transitions. Each value is either a plain slug (shorthand) or an explicit route object:
on: success: ready-for-dev # shorthand: target state slug escalate_to_planning: target: planning # explicit object form outputs: # optional metadata forwarded to the next state upstream_outcome: scope_overflowThe key noop is reserved and must not appear in on:. The framework handles noop returns without transitioning the issue.
All target slugs in on: must reference states defined in the same workflow definition.
hooks may only be declared on terminal states. They trigger out-of-band tasks after the issue reaches the terminal state:
done: type: terminal hooks: - task_type: retrospect executor: builtin:retrospect optional: true # if true, failure does not block the terminal transition once_per_issue: true # if true, the hook only fires once regardless of rerunsOperator actions
Section titled “Operator actions”The operator_actions key registers named actions that pipeline operators (humans or MCP tools) can trigger via slash commands. Each action has:
| Field | Required | Description |
|---|---|---|
description | yes | Human-readable label for the action |
framework | no | true marks this as a framework-reserved action (no from/to required) |
from | yes (non-framework) | Array of source state slugs from which this action is valid |
to | yes (non-framework) | Target state slug |
side_effects | no | Side effects to execute: close-pr, add-label, remove-label |
Non-framework operator actions must declare both from and to. Framework actions (e.g. retry) are handled by the engine and do not require routing fields.
operator_actions: retry: description: "Re-enqueue current state's executor after failure." framework: true reimplement: description: "Discard PR; return to development." from: [in-review, merge-pending] to: ready-for-dev side_effects: [close-pr]All from and to slugs in operator actions must reference defined states.
Schema constraints
Section titled “Schema constraints”The schema enforces the following rules at parse time:
intake.initial_statemust reference a defined state.- States of type
blockedmust declarerecovery. - States of type
terminalmust not declareexecutorortransitions. noopmust not appear as a key in any state’son:map.hooksmay only be declared onterminalstates.- Every target in
on:,transitions, and operator actionfrom/tofields must reference a defined state.
Built-in workflow: colony-default
Section titled “Built-in workflow: colony-default”Colony ships with colony-default, the standard analyze → develop → review → merge pipeline. It is the default workflow for all tenants unless overridden.
Key properties:
intake.trigger_label: colony:enqueue— adding this label to a GitHub issue seeds it into the pipeline. See First Issue for details.intake.initial_state: new— issues enter thenewstate, wherebuiltin:analyzeruns.- States:
new,planning,analyzing,needs-clarification,ready-for-dev,dependency-blocked,failure-blocked,changes-requested,in-review,merge-pending,human-review-ready,waiting-for-subtasks,done,paused,unlabeled. - Terminal state:
done— triggers aretrospecthook (optional, once-per-issue). - Operator actions:
retry(framework),reimplement,reanalyze,reopen.
To view the full YAML:
colony workflow show --builtin colony-defaultCustom workflow example
Section titled “Custom workflow example”The following is the colony-content workflow from packages/sdk/examples/plugin-content-stub/workflow/colony-content.yaml. It illustrates a lean pipeline for content/documentation issues that uses two plugin executors and omits the planning stage.
schema_version: 1
workflow: id: colony-content version: 1 name: "Content pipeline" description: "Lean workflow for content/docs. No planning, no CI gating."
intake: initial_state: new trigger_label: colony:enqueue
states: new: type: active executor: plugin:colony-content/analyze on: success: drafting needs_clarification: needs-clarification no_work_pr_open: human-review-ready no_work_done: done failure: failure-blocked transitions: [drafting, needs-clarification, human-review-ready, done, failure-blocked]
drafting: type: active executor: plugin:colony-content/draft on: draft_created: review-ready needs_clarification: needs-clarification failure: failure-blocked transitions: [review-ready, needs-clarification, failure-blocked]
review-ready: type: active executor: builtin:review on: approved: merge-pending changes_requested: changes-requested needs_rebase: review-ready escalate_human: human-review-ready no_pr: drafting already_merged: done failure: failure-blocked transitions: [merge-pending, changes-requested, review-ready, human-review-ready, drafting, done, failure-blocked]
changes-requested: type: active executor: plugin:colony-content/draft on: draft_created: review-ready needs_clarification: needs-clarification failure: failure-blocked transitions: [review-ready, needs-clarification, failure-blocked]
merge-pending: type: active executor: builtin:merge on: merged: done reimplement_requested: drafting escalate_human: human-review-ready needs_rebase: review-ready not_approved: review-ready auto_merge_disabled: human-review-ready failure: failure-blocked transitions: [done, drafting, human-review-ready, review-ready, failure-blocked]
needs-clarification: type: awaiting-human transitions: [new, drafting]
human-review-ready: type: awaiting-human transitions: [drafting, done, failure-blocked]
failure-blocked: type: blocked recovery: manual transitions: [new, drafting, done]
done: type: terminal
operator_actions: redraft: description: "Discard draft and start over." from: [review-ready, merge-pending, changes-requested] to: drafting side_effects: [close-pr] retry: description: "Retry the last failed step." framework: trueThis workflow uses plugin:colony-content/analyze and plugin:colony-content/draft — executors provided by the colony-content plugin. See Plugins for how to author and register a plugin.
CLI reference
Section titled “CLI reference”colony workflow validate <file>
Section titled “colony workflow validate <file>”Parse and validate a workflow YAML file against the schema. Exits 0 on success, 2 on parse or validation error.
$ colony workflow validate ./my-workflow.yamlOK: my-workflow v1 states: 9 operator_actions: 2 content_hash: a3f1...validate checks the Zod schema and all cross-reference constraints (target states exist, blocked states declare recovery, etc.). It does not verify that every executor outcome declared by a plugin is handled in the workflow’s on: block — that check runs at workflow-load time when the worker starts.
colony workflow show
Section titled “colony workflow show”Print a workflow definition as YAML. Two modes:
Built-in workflow (no database required):
colony workflow show --builtin colony-defaultValid --builtin values: colony-default.
Stored workflow (reads from the registry database):
colony workflow show \ --workflow-id my-workflow \ --version 2 \ --tenant-id 42 \ [--database-url postgres://...]All three of --workflow-id, --version, and --tenant-id are required for registry reads. The database URL is read from --database-url or the $DATABASE_URL environment variable. The command exits 2 if neither mode is fully specified.