Skip to content

Pipeline File

A pipeline-file is the base YAML document that defines a pipeline. It carries a header (name, description, optional overrides) 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 optional roles block (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.

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 flow-file shape) raises unsupported body format.

Stage fields

Both body formats accept the same set of fields per stage. The compiler preserves unknown fields verbatim — only the canonical fields below have assigned semantics:

The authoring field for user-input stages is communication. The compiler translates it to the afm output key interactive (which stays stable in the compiled flow-file). Authoring interactive directly is rejected with a structural error — use communication.

Symmetrically, the authoring field for the launch mode is trigger. The compiler translates trigger: manual to the afm output key auto_run: false (the stage pauses when reached and runs only when launched manually). Authoring auto_run directly is rejected with a structural error — use trigger: manual.

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 emitted as the compiled stage's name.
communication bool false Whether the stage prompts for user input. Authors as communication; compiles to the afm interactive key. Authoring interactive directly is a structural error.
prompt string Stage-level prompt text; emitted as the compiled prompt field.
skills list of strings Skills the agent must apply at this stage.
before_script string Shell script run before the stage; compiles to the afm script_before field. See Script directives.
script string Shell script run as the stage body; compiles to the afm script field. Mutually exclusive with prompt and skills. See Script directives.
after_script string Shell script run after the stage; compiles to the afm script_after field. See Script directives.
timeout string — (no key emitted) Timeout for the stage's script action (Go duration, e.g. 30m); compiles to the afm script_timeout field. Requires script in the same body; the value passes verbatim (the duration grammar is validated by afm at runtime). See Script directives.
roles list of strings autonomous mode when absent Agent roles assigned to the stage. See Roles.
trigger string (on_success | manual) on_success (no key emitted) Launch mode of the stage. trigger: manual compiles to the afm auto_run: false key (canonical slot right after auto_approve) — the stage pauses when reached and runs only when launched manually; trigger: on_success (or an absent key) emits no auto_run key. Authoring 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.

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

A stage may carry shell scripts to run at fixed points relative to the agent's work. The three authoring fields are translated into the matching afm output keys at compile time:

Author as Compiles to When it runs
before_script script_before Before the stage's agent work.
script script As the stage body itself.
after_script script_after After the stage's agent work.
timeout script_timeout Bounds the stage's script action.

The authoring keys are consumed and never appear in the compiled flow-file — only the translated script_* keys do. A multi-line script_before, script, script_after, or script_timeout 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.

A stage whose body carries script compiles with no agents key at all: afm rejects agents combined with script, so the default auto agent is not injected and an authored body roles value (see Roles) is element-validated but not emitted — body roles has no effect on a script stage's compiled output. Only script opens this suppression: before_script/after_script alone keep the default agents: [auto] injection. 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 with no duration-grammar validation on the goga side — a malformed string fails in afm at runtime. The key is emitted only when authored; authoring script_timeout directly is not forbidden, but when both are authored the translated timeout value wins. 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 six 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. You author the three overridable roles by alias; the compiler maps each alias to the afm agent name (and the matching shipped prompt file):

Author as (alias) afm agent / prompt stem Responsibility
planner planning Read the task, decompose it into a verifiable plan, hand off. Does not execute the work.
executor implementation Execute the plan task-by-task, including any required research, code, or analysis. Produces the deliverable.
reviewer review Verify the deliverable against the plan and acceptance criteria. Approves or requests changes.

A fourth afm 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 file (summary.md) is always materialized from the shipped default. (summary may still be listed in a stage's roles field — like any non-alias value it passes through to the afm agents list verbatim — but it is never an override target.)

What each role does

planner (planning) 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 (implementation) 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 (review) 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 moderoles is 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 moderoles is a non-empty list (e.g. [planner, executor]). The listed roles run in sequence and organize the work for the incoming task: the planner decomposes the task into a verifiable plan, the executor executes that plan, the reviewer validates the result, and the summary role 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 roles out for stages whose work cannot be planned ahead of time — exploratory research, free-form authoring, asking a question.
  • Author roles for 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 modeplanner 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 shipped default prompt for afm agent
planner planning
executor implementation
reviewer review

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 with unknown 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 agents key is rejected outright with agents key is forbidden in header; use roles.
  • An absent roles block and an empty roles: mapping are both treated identically — no overrides, the three shipped defaults are used unchanged.
  • Overrides are a pipeline-file-side artifact. They are not carried into the compiled flow-file — they are materialized into a separate prompts directory at run time.

How header and stage roles relate

The two pipeline-file roles declarations compose without collision:

  • The per-stage roles list decides which roles execute and in which order — i.e. the stage's mode.
  • The header-level roles map 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.

Errors

Condition Exception
--- separator missing missing body separator
Header missing name or description header missing name/description
Legacy agents key in header agents key is forbidden in header; use roles
Unknown key in header roles block (incl. summary) unknown role in header.roles: <key>; valid keys: planner, executor, reviewer
Non-mapping roles block in header non-mapping roles block in header
Non-string value in header roles.<key> non-str value in header.roles.<key>
Legacy agents key in a stage body agents key is forbidden in stage body; use roles
Authoring interactive in a stage body interactive key is forbidden in stage body; use communication
Authoring auto_run in a stage body auto_run key is forbidden in stage body; use trigger: manual
trigger value outside on_success/manual trigger must be one of: on_success, manual
timeout value is not a string (including YAML-null) timeout must be a string in stage <NAME>
timeout without script in the same body timeout requires script in stage <NAME>
script authored together with prompt and/or skills script is mutually exclusive with prompt/skills in stage <NAME>
Body shape is neither list nor dict unsupported body format
Body has zero steps empty body

See also