Pipeline File
A pipeline-file is the base YAML document that defines a pipeline. It
carries a header — name, description, and an optional roles block
that replaces the shipped default prompts of the authorable roles (see
Roles) — and a body that lists the ordered stages of the
pipeline.
Pipeline-files live at:
| Source | Path |
|---|---|
| project | <cwd>/.goga/pipelines/<name>.yml |
| user | ~/.goga/pipelines/<name>.yml |
Only top-level *.yml files are scanned. Subdirectories are ignored and
.yaml files are excluded. On name conflict, the project source wins.
Document shape
Every pipeline-file is a two-segment YAML document separated by a --- line:
<header>
---
<body>
- The header is a YAML mapping with
name,description, and an optionalrolesblock (see Roles). - The body is either a YAML list (phases format) or a YAML dict (stages format).
A file without the --- separator is rejected at parse time with a
structural error.
Header
name: GogaFeature
description: "Feature development"
roles: # optional block — see "Roles"
planner: |
Inline prompt that replaces the shipped default for the planner role.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Pipeline identifier, must be non-empty |
description |
string | yes | Short human-readable purpose |
roles |
map | no | Inline overrides for the three role prompts. See Roles. |
A header missing name or description is rejected with a structural
error.
Body formats
The body can be authored in one of two shapes — both are first-class.
Phases format (list)
A YAML list of step mappings. Each item is keyed by name; depends_on is
auto-generated by list position — the first step has no dependency, each
subsequent step depends on the previous one.
- name: propose
title: "Create the task from a user propose"
communication: true
prompt: |
Save the task file as `<git branch --show-current>.md`
skills:
- goga-propose
- name: task-review
title: "Review of the created task"
communication: true
prompt: |
Review the task `<git branch --show-current>.md`
skills:
- goga-review-task
When a workflow applies loop: N to a phases stage, the expanded copies
chain naturally via list position — the first copy inherits the original
position, subsequent copies depend on their predecessor, and the next
original step depends on the last expanded copy.
Stages format (dict)
A YAML mapping keyed by step id. Each value carries title and an optional
explicit depends_on plus any extra fields. depends_on is passed through
as-is, except that workflow loop expansion rewrites external references to
a base name to the last expanded id.
propose:
title: "Create the task from a user propose"
communication: true
prompt: |
Save the task file as `<git branch --show-current>.md`
skills:
- goga-propose
task-review:
title: "Review of the created task"
depends_on: [propose]
communication: true
prompt: |
Review the task `<git branch --show-current>.md`
skills:
- goga-review-task
Any other body shape (scalar, no separator, or an already-compiled pipeline
definition) raises unsupported body format; a body with zero steps
raises empty body.
Stage fields
Both body formats accept the same set of fields per stage. Every stage is one of two types, decided by what its body carries:
- Agent stage — the body describes work for an AI agent: a
promptwith optionalskillsthe agent must apply, an optionalroleslist that puts the stage into coordinated mode (see Roles), and an optionalcommunication: truepause for user input. - Script stage — the body is a literal shell script (
script). No agent runs: the stage executes the script and nothing else.
Only the body is exclusive: authoring script together with prompt
and/or skills is a structural error. before_script and after_script
are available on both types — they bracket an agent stage's agent
work exactly as they bracket a script stage's script — while timeout
scopes to the script action (it requires script).
The compiler preserves unknown fields verbatim — only the canonical fields below have assigned semantics:
The authoring field for user-input stages is
communication. Acommunication: truestage pauses for user input. Authoring the compiler-output keyinteractivedirectly is rejected with a structural error — usecommunication.Symmetrically, the authoring field for the launch mode is
trigger.trigger: manualpauses the stage when reached — it runs only when launched manually. Authoring the compiler-output keyauto_rundirectly is rejected with a structural error — usetrigger: manual.The per-stage note buttons have no pipeline-file authoring key at all: they are assembled by the compiler from a workflow
notesinstruction (see Workflows — Note buttons). Authoringbuttonsin a stage body is rejected with a structural error.Symmetrically, the memory instructions have no pipeline-file authoring key: they are assembled by the compiler from the workflow memory instructions (see Workflows — Project memory). Authoring
reflectormemory_usein a stage body is rejected with a structural error.The legacy
agentskey is forbidden in both the header and a stage body — authorrolesinstead.
Common fields
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | — (required, phases only) | Stage identifier. In phases format the item's name; in stages the map key. |
title |
string | — (optional, recommended) | Display label of the stage — what end users see in stage listings. |
trigger |
string (on_success | manual) |
on_success |
Launch mode of the stage. manual — the stage pauses when reached and runs only when launched manually; on_success (or an absent key) — the stage starts automatically once its dependencies succeed; any other value is a structural error. Authoring the compiler-output key auto_run directly is a structural error. Valid in both body formats and in workflow extend bodies; a workflow stages block can force or cancel it per-stage via manual (see Workflows). |
depends_on |
list of strings | auto (phases) / none (stages) | Stage dependencies. |
before_script |
string | — | Shell script run at the start of any stage — agent or script — before its body. See Script directives. |
after_script |
string | — | Shell script run at the end of any stage — agent or script — after its body. See Script directives. |
Agent-stage fields
| Field | Type | Default | Description |
|---|---|---|---|
prompt |
string | — | Stage-level prompt text for the stage's agent. |
skills |
list of strings | — | Skills the agent must apply at this stage. |
roles |
list of strings | autonomous mode when absent | Agent roles assigned to the stage. See Roles. |
communication |
bool | false | Whether the agent stage pauses and prompts for user input. Pointless on a script stage — a script has no dialogue to pause. Authoring the compiler-output key interactive directly is a structural error. |
Script-stage fields
| Field | Type | Default | Description |
|---|---|---|---|
script |
string | — | Shell script run as the stage body itself. Mutually exclusive with prompt and skills. See Script directives. |
timeout |
string | — | Timeout for the stage's script action (a duration string, e.g. 30m). Requires script in the same body; the value passes verbatim — a malformed duration fails the stage at run time. See Script directives. |
Body step title field
The body step carries a title field that becomes the compiled stage's
display name. Use a short human-readable phrase — it is what end users see
in stage listings.
Script directives
Any stage — agent or script — may carry shell scripts to run at fixed points relative to the stage's body:
| Field | When it runs |
|---|---|
before_script |
Before the stage's body. |
script |
As the stage body itself. |
after_script |
After the stage's body. |
timeout |
Bounds the stage's script action. |
A multi-line value serializes as a YAML block-literal (e.g. script: |);
a single-line value stays a plain scalar. The rule is uniform across all
four slots.
script is mutually exclusive with prompt and skills: a stage runs
either an agent-driven prompt (prompt/skills) or a literal shell script
(script), not both. Authoring script together with prompt and/or
skills is a structural error. before_script and after_script are
compatible with both script and prompt/skills — they bracket the stage
regardless of how its body is defined. An agent stage with bracketing
scripts:
release-notes:
title: Draft release notes
before_script: git fetch --tags
prompt: |
Draft release notes for the current version.
after_script: echo "release notes drafted"
A stage whose body carries script runs no agent at all — it is pure shell.
Consequently a roles list on a script stage has no effect: its values are
still validated as aliases (see Roles), but no roles are assigned.
Only script switches a stage to pure shell — before_script/after_script
alone still leave the stage agent-driven with the default role assignment.
The rule is uniform across both body formats and in workflow extend bodies.
timeout scopes to the script action: it requires script in the same body
(before_script/after_script do not open the directive — a timeout
without script is a structural error, as is a non-string value, including
YAML-null). The value passes verbatim — a malformed duration string fails
the stage at run time. Valid in both body formats and in workflow extend
bodies; loop-expanded copies inherit it.
deploy:
title: Deploy
before_script: |
set -e
echo "building..."
script: |
make build
make deploy
after_script: echo "done"
timeout: 30m
Shipped pipelines
Goga ships ready-to-use pipelines — bugfix, development, patch,
refinement, review, and sync — that cover the most common authoring
lifecycles. See
Shipped Pipelines for the per-pipeline walkthrough and how
project pipelines override the global ones.
Roles
The pipeline-file carries roles in two distinct places, and they
serve different purposes. A third agent concept exists in
workflow-files and
is intentionally different — see the comparison at the end of this
section.
| Where | Field | Type | Purpose |
|---|---|---|---|
| Header | roles |
map | Replace shipped default prompts for the three authorable roles. |
| Body stage | roles |
list of strings | Choose which roles run the stage (its mode). |
| Workflow-file stage | agent |
string | Choose which CLI agent runs the stage (e.g. codex, claude). |
The rest of this section covers the first two — both live in the pipeline-file. The third is documented in Workflows.
The agent roles
When a stage runs in coordinated mode (see below), the roles in its
roles list execute in sequence — each role's output becomes the next
role's input. Three roles are authorable:
| Alias | Responsibility |
|---|---|
planner |
Read the task, decompose it into a verifiable plan, hand off. Does not execute the work. |
executor |
Execute the plan task-by-task, including any required research, code, or analysis. Produces the deliverable. |
reviewer |
Verify the deliverable against the plan and acceptance criteria. Approves or requests changes. |
A fourth role, summary, produces the final report for the run,
covering every stage. It is not an authorable role: it never appears
as a key in the header roles block, and its prompt is always the shipped
default. (summary may still be listed in a stage's roles field — like
any non-alias value it passes through to the stage's role list verbatim —
but it is never an override target.)
What each role does
planner decomposes the incoming task into an actionable
plan with three sections: a numbered task list, the assumptions made along
the way, and explicit acceptance criteria the work must meet. It does not
perform the work itself — it hands the plan to the next role. It makes
decisions autonomously rather than asking questions, and documents every
non-obvious choice under assumptions.
executor executes the plan top to bottom. For
each task it decides the nature of the work — research, analysis, code,
discussion — and acts accordingly. It runs the acceptance criteria checks
before declaring the stage complete, and produces an honest report (not a
false "done") when a criterion cannot be met.
reviewer audits the deliverable against the plan: every
task actually done, every acceptance criterion met, the result matching
the intent of the prompt, edge cases handled. It returns a single verdict
— approved or needs_changes — with a list of critical blockers and a
list of non-blocking suggestions.
summary reads the logs of every stage in the run and produces a
final report: a one-paragraph overview, a per-stage breakdown of what
happened, and any open issues carried over from review. Because it is not
an authorable role, its prompt is always the shipped default.
Body stage roles — choosing the stage mode
The per-stage roles field is a list of role aliases. A stage runs in one
of two modes depending on whether the list is non-empty:
- Autonomous mode —
rolesis absent,null, or an empty list[]. The stage receives its task and decides for itself how to organize the work: which steps to take, in which order, and when the result is complete. Use this for stages that should not be decomposed ahead of time — research, free-form authoring, exploratory analysis. - Coordinated mode —
rolesis a non-empty list (e.g.[planner, executor]). The listed roles run in sequence and organize the work for the incoming task: theplannerdecomposes the task into a verifiable plan, theexecutorexecutes that plan, thereviewervalidates the result, and thesummaryrole produces the final report. Use this for stages where you want predictable, reviewable execution — feature builds, bug fixes, anything with acceptance criteria.
The two modes are mutually exclusive per stage — there is no hybrid.
Authoring even a single-element list (roles: [planner]) is enough to
switch the stage into coordinated mode; an authored non-empty value
always wins.
Choosing between modes
- Leave
rolesout for stages whose work cannot be planned ahead of time — exploratory research, free-form authoring, asking a question. - Author
rolesfor stages whose work is structurally predictable — building a feature, fixing a bug, anything where you want a plan, execution, review, and a final report.
Examples
Autonomous mode — no roles field. The stage receives the prompt and
organizes the work itself:
- name: research
title: "Explore the codebase for prior art"
prompt: |
Find any existing implementations of feature flagging
in this codebase and summarize what you find.
Coordinated mode — planner and executor roles assigned. The stage
decomposes the task into a plan, then executes it:
- name: ship
title: "Build and ship artifacts"
roles:
- planner
- executor
prompt: |
Build the artifacts for the current branch and ship them.
Full lifecycle — all three authorable roles. Useful for stages where
you want end-to-end verification (the automatic summary report covers
the stage on top):
- name: deliver
title: "Deliver the feature end-to-end"
roles:
- planner
- executor
- reviewer
prompt: |
Implement the feature described in the task file, verify
it meets the acceptance criteria, and produce a report.
Header roles — overriding the default prompts
The header-level roles block lets you replace the shipped default prompt
for any of the three authorable roles with an inline prompt of your own.
An override fully replaces the default — it does not merge with it.
When the block is absent or empty, the three shipped defaults are used
unchanged. (summary has no override slot — its prompt is always the
default.)
The block accepts exactly three keys — one per authorable role:
| Key | Replaces the shipped default prompt of |
|---|---|
planner |
the planner role |
executor |
the executor role |
reviewer |
the reviewer role |
Example:
name: GogaFeature
description: "Feature development"
roles:
planner: |
You are the planner for this feature pipeline.
Break the work into reviewable steps.
reviewer: |
Review each change against the feature's acceptance criteria.
---
Rules:
- Only those three keys are valid. An unknown key (including
summary) is rejected at compile time withunknown role in header.roles: <key>; valid keys: planner, executor, reviewer. - Each value must be a string. A non-string value raises
non-str value in header.roles.<key>. - The legacy
agentskey is rejected outright withagents key is forbidden in header; use roles. - An absent
rolesblock and an emptyroles:mapping are both treated identically — no overrides, the three shipped defaults are used unchanged. - Overrides are a pipeline-file-side artifact. They do not alter the compiled stage list — they are materialized into the pipeline's prompts directory at run time.
How header and stage roles relate
The two pipeline-file roles declarations compose without collision:
- The per-stage
roleslist decides which roles execute and in which order — i.e. the stage's mode. - The header-level
rolesmap decides what each role's prompt says when it runs.
A stage running in coordinated mode picks up the header-level overrides
for whatever roles appear in its list. If no override is supplied for a
role, that role uses its shipped default. The header overrides do not
add roles to a stage — they only change the prompt of roles already listed
in the stage's roles field. A stage in autonomous mode (no roles
field) is unaffected by header overrides.
Pipeline-file roles vs workflow-file agent
| Aspect | Pipeline-file header roles |
Pipeline-file stage roles |
Workflow-file stage agent |
|---|---|---|---|
| Scope | Pipeline-wide default | Single stage | Single stage (overrides at run time) |
| Value | Map of role → prompt | List of role aliases | Single CLI agent name |
| Controls | The prompt text of each role | Which roles run, in which order (mode) | Which CLI binary runs the stage |
| Examples | {planner: "...", reviewer: "..."} |
[planner, executor] |
codex, claude, opencode |
Use pipeline-file declarations for the stable structure of a pipeline
(its roles and their prompts). Use workflow-file agent for per-project
variation — running the same pipeline on different CLI agents without
forking the pipeline-file. See Workflows for the full
workflow-agent semantics.
See also
- Workflows — layer project-specific overrides on top of a compiled pipeline.
goga pipelineCLI reference — invocation flags, exit codes, and Docker mechanics.