Skip to content

Workflows & Phases

A workflow is the workflow section of team.yml. It declares which phases exist, how they connect, and what configuration each phase carries. The orchestrator reads this definition, resolves the dependency graph, and executes phases in the right order.

A phase is one step in a pipeline. Every phase has a name and a type. The type determines what the orchestrator does — whether it launches an agent, runs automated commands, fetches external files, or all three.

For the complete field-by-field schema, see team.yml Reference.

workflow:
phases:
- name: architect
type: standard
- name: developer
type: standard
depends_on: [architect]
- name: reviewer
type: gate
depends_on: [developer]
commands:
- name: tests
run: npm test
max_iterations: 3

TypeAgent?Commands?What it does
standardYesOptionalRuns an agent that does work and signals done. With agent: exec, runs commands with no LLM.
gateYesOptionalRuns commands, then an agent renders a verdict (automated). With agent: hug, a human reviewer renders the verdict via the HUG review page.
teamBuilt-inNoRuns an entire sub-team pipeline; role becomes the requirements spec

Data collection and delivery (fetching from Google Drive, Jira, S3, or pushing results to external systems) is handled by connector agents — standard phases that use a built-in connector agent like jira, gdrive, s3, curl, confluence, zendesk, datadog, or hubspot. See team.yml Reference — Sources and Target Entries for configuration.


The workhorse. A standard phase launches an agent, gives it a role and the task requirements, and waits for it to signal completion. This is where the real work happens — writing code, designing architecture, authoring tests, producing documents.

- name: developer
type: standard
depends_on: [architect]

The agent SDK reads the role file and incoming channel handoffs from predecessors, passes them to the implementation, captures the result, writes handoff notes for successors, and signals done.

Every standard phase produces a handoff envelope — a JSON file with two parts that downstream phases can consume:

  • text — a natural language summary, automatically injected into downstream LLM agent prompts
  • data — a structured payload accessible via $(handoff.<phase>.<path>) template variables and in custom SDK agents

For LLM agents, text is the agent’s response and data carries any structured information. For connector agents (S3, Jira, Google Drive, curl, etc.), data contains enriched results with URLs, metadata, and local file paths in name-keyed maps. See the Agent Reference for the exact handoff structure each agent produces.

This dual structure means downstream phases get both human-readable context for LLMs and machine-readable data for template variables and programmatic access — from every phase, regardless of agent type.


A gate is a quality checkpoint that combines automated commands with agent intelligence. Gates create feedback loops that let work improve iteratively.

- name: reviewer
type: gate
depends_on: [developer]
commands:
- name: build
run: npm run build
- name: tests
run: npm test
max_iterations: 3

When a gate’s dependencies complete:

  1. Run commands — the orchestrator executes each command as a shell command (exit 0 = pass, non-zero = fail). Command outcomes are evaluated by the agent, not the orchestrator.
  2. Build gate context — command results and verdict history are written to .cliq/gate_context.md
  3. Launch the gate agent — the agent reviews the work and produces a structured verdict
VerdictWhat happens
PASSQuality bar is met. Pipeline continues to the next phase.
ROUTE:<phase>Work needs revision. The named phase is re-activated with feedback. When it finishes, the gate re-evaluates from step 1.
ESCALATEHuman intervention required. The pipeline halts.

On a ROUTE verdict, the orchestrator:

  1. The gate writes its verdict envelope to the channel (e.g. .cliq/channels/reviewer--developer/handoff.json)
  2. Re-activates the target phase (which reads the feedback and fixes the issues)
  3. Waits for the target to signal done
  4. Re-runs the gate’s commands
  5. Launches the gate agent again with updated results and the growing verdict history

This loop continues until the gate passes, escalates, or exhausts its max_iterations budget. The default is 3 iterations; the maximum is 5. After the budget is spent, the orchestrator auto-escalates.

The gate agent sees the full history of previous verdicts, so it can make increasingly informed decisions — for example, escalating after a second failed route to the same phase.


An exec configuration runs shell commands with no LLM agent and no prompt. Use type: standard with agent: exec. Each exec phase gets its own tmux pane where commands execute with real-time output. Each command has an optional escalate_on_fail boolean (default true). Commands with escalate_on_fail: false log failures as warnings and continue.

- name: git-verify
type: standard
agent: exec
depends_on: [git-finalize]
commands:
- name: pushed
run: "git ls-remote --heads origin $(git branch --show-current) | grep -q ."
- name: changelog-updated
run: "test -f CHANGELOG.md"
escalate_on_fail: false

Use exec phases to verify that critical external actions actually happened — things like “was the code pushed?” or “was the changelog updated?” — where an agent’s self-report isn’t reliable enough. Exec phases must have at least one command and cannot have max_iterations.


A HUG configuration pauses the pipeline for human review. Use type: gate with agent: hug and a nested review: block. Instead of an AI agent rendering the verdict, a real person reviews the work on a web-based review page and decides the outcome.

- name: human-review
type: gate
agent: hug
depends_on: [developer]
commands:
- name: tests
run: npm test
review:
reviewer: architects
timeout: 48h

HUG gates use the same PASS / ROUTE / ESCALATE verdict model as automated gates. The review.reviewer field is required — it tells the orchestrator who reviews. Optional artifacts, timeout, and remind_every fields within the review: block control which files to present and how long to wait.

See Human Gate (HUG) for the full setup and configuration.


A team phase delegates an entire step of your pipeline to another cliq team. Instead of launching a single agent, the orchestrator runs a full nested pipeline with its own workflow, roles, channels, and signals — all inside an isolated call frame under .cliq/team-phases/<phase_name>/.

- name: security-audit
type: team
depends_on: [developer]
team: "@acme/security-scan"
inputs:
scan_target: src/
- name: fixer
type: standard
depends_on: [security-audit]

Like every other phase type, team phases require a role file in roles/. The role is the author’s instructions for what the sub-team should accomplish — it becomes the requirements spec passed to cliq req inside the call frame.

roles/security-audit.md
Analyze the project at $(dirs.project) for security vulnerabilities.
Focus on authentication, input validation, and dependency risks.
Write your findings report to $(dirs.project)/reports/security-report.md.

Team phase roles support special template variables for directory paths. See Roles — Team Phase Roles for the full list.

At assembly time (cliq assemble):

  1. Recursive assemblycliq assemble recursively resolves all sub-team references, assembling each into its call frame at .cliq/team-phases/<phase_name>/
  2. Hub downloadhub:// references are downloaded from the remote registry and assembled locally
  3. Input validation — declared inputs at every nesting level are validated against provided inputs
  4. Lockfile.cliq/team-lock.yml is written at the project root, recording all hub-resolved teams with versions and integrity hashes

At runtime (when the team phase’s dependencies complete):

  1. Build spec — the built-in team agent combines the expanded role file (with $(dirs.*) and $(inputs.*) resolved) and upstream channel content into a spec file
  2. Run cliq req — passes the spec and input values to the sub-team’s cliq req in the call frame
  3. Run the sub-pipelinecliq run --headless launches the sub-team’s full workflow
  4. Write handoff — the team agent collects the sub-team’s task board and channel outputs into a structured handoff, sent to downstream phases via normal channels

The team agent is entirely deterministic — no LLM is involved. The human-authored role file is the spec; the handoff is a faithful pass-through of the sub-team’s own outputs.

Every agent’s working directory (cwd) defaults to $(dirs.self) — the orchestration state directory for the current pipeline level. At top level, dirs.self equals the project root so nothing changes for single-team projects. In sub-teams, dirs.self is the call frame (.cliq/team-phases/<phase_name>/), which means bare relative paths resolve inside the call frame, not the project root.

ConceptTop-level runSub-team run
cwd (dirs.self)Project rootCall frame path
dirs.projectProject rootProject root (same)

To read or write project files from a sub-team, use $(dirs.project) explicitly:

Write your report to $(dirs.project)/reports/security-report.md.

This isolation prevents parallel team phases from stepping on each other via bare relative paths. cliq team validate and cliq assemble warn about bare relative paths that should be qualified with a $(dirs.*) prefix ($(dirs.project), $(dirs.self), or $(dirs.<phase>)) for portability. cliq team publish blocks them; pass --force only when the flag is a confirmed false positive.

Downstream phases that depend on a team phase receive handoff content through normal channels — exactly like any other phase. The handoff includes the sub-team’s final task board and channel outputs. No special call-frame knowledge is needed.

Each orchestrator — top-level and nested — runs a WebSocket event server. The team agent connects to the sub-orchestrator’s WebSocket and relays events up the call stack with prefixed phase names (e.g., security-audit.analyzer), giving full hierarchical visibility into nested pipelines.

The team field accepts two reference styles:

StyleExampleResolved at
Local (installed)"@acme/scanner"Assembly time — from global install dir
Hub"hub://@acme/scanner" or "hub://@acme/[email protected]"Assembly time — downloaded from CliqHub

References are explicit: there is no fallback search path. A local ref always resolves from the installed team registry. A hub ref always downloads from the remote registry.

Team phases can nest recursively. A sub-team’s workflow can itself contain team phases, creating a call stack. Each level gets its own isolated call frame, but all levels share the same project workspace. cliq assemble detects cycles at assembly time and enforces a maximum of 50 teams per project to prevent runaway transitive dependencies.

After recursive assembly, cliq writes a lockfile at the project root recording every hub-resolved team:

locked_at: "2026-04-30T18:00:00Z"
teams:
"@acme/scanner":
version: "1.2.0"
source: hub
integrity: "sha256:abc123..."

This provides a reproducibility audit trail. Future use: --offline mode could skip network calls using the lockfile.

  • Team phases require a role file — the role becomes the sub-team’s requirements spec
  • Phase names cannot contain . characters (dots are reserved for event name mangling in nested monitoring)
  • The team field is required on team phases and not allowed on other types
  • inputs on a team phase are static key-value pairs passed to the sub-team at cliq req time
  • cliq assemble must be re-run whenever team references change

Phases connect through depends_on. A phase won’t start until all of its dependencies have completed. Phases with no shared dependencies run in parallel automatically.

- name: architect
type: standard
- name: tester
type: standard
depends_on: [architect]
- name: security-auditor
type: standard
depends_on: [architect]
- name: developer
type: standard
depends_on: [tester, security-auditor]

Here, tester and security-auditor both depend on architect and nothing else — so they run simultaneously once the architect finishes. developer waits for both (fan-in). The orchestrator handles all of this from the depends_on declarations.

A phase with no depends_on is a root phase — it starts immediately when the pipeline runs. Every workflow must have at least one root phase.


Commands are shell commands attached to gate and standard phases. Each command runs as a subprocess — exit code 0 means pass, non-zero means fail.

commands:
- name: build
run: npm run build
scope: repo
if: "test -f package.json"
- name: tests
run: npm test
- name: output-exists
run: "test -f output.md"

See team.yml Reference — Commands for the full field reference.

The if field lets you skip commands when they don’t apply:

- name: build
run: npm run build
if: "test -f package.json"

If package.json doesn’t exist, the command is skipped — not failed. This is common in teams that work across different project types.

By default, commands run from the current working directory ($(dirs.self)). In multi-repo setups, scope: repo runs the command in each repository:

- name: tests
run: npm test
scope: repo
if: "test -f package.json"

In a single-repo workspace, scope: repo behaves identically to scope: workspace.


A support phase sits idle until a gate routes work to it. Support phases are declared in a separate support section under workflow, not in the main phases list.

workflow:
phases:
- name: developer
type: standard
- name: reviewer
type: gate
depends_on: [developer]
commands:
- name: tests
run: npm test
max_iterations: 3
support:
- name: fixer
type: standard
- name: git-resolver
type: standard

Support phases have their real functional type (standard, gate, etc.) — they’re just topologically separated from the main flow. They must not have depends_on and are only reachable through gate routing.

Use support phases for specialized remediation: a git-resolver that fixes merge conflicts, a security-fixer that patches vulnerabilities, a fixer that addresses gate feedback.


By default, every phase uses the runtime’s default agent. The agent field overrides this for a specific phase:

- name: security-audit
type: standard
depends_on: [developer]
agent: security-scanner

The value must be a built-in agent name or an agent declared in the team’s agents section. See Cliq SDK for details on choosing and configuring agents.


When cliq run ends in an escalation or failure, you don’t need to re-run cliq req — the requirement hasn’t changed. Fix the issue and run again.

ScenarioWhat happens
Early escalation — first gate fails before any agent did workcliq run silently cleans prior artifacts and proceeds
Mid-pipeline failure — some agents completed phasescliq run warns which phases completed and asks for confirmation
Successful completion — pipeline finished cleanlycliq run refuses. Start a new task with cliq req
Terminal window
cliq run # auto-cleans if no agents did real work
cliq run -f # force re-run, skip confirmation

cliq team validate checks your workflow for structural correctness. See team.yml Reference — Validation Rules for the full list of checks and error messages.

Key rules:

  • Every phase must have name and type
  • No duplicate phase names, no cycles in depends_on, at least one root phase
  • Phase names cannot contain . characters
  • Phases with agent: exec must have commands and no max_iterations
  • Gate phases with agent: hug must have a review: block with reviewer; the review: block is not allowed on other configurations
  • Team phases must have a team field; the team field is not allowed on other types
  • Every phase (except agent: exec) must have a matching roles/<name>.md (including team phases)

workflow:
phases:
- name: architect
type: standard
- name: developer
type: standard
depends_on: [architect]
- name: reviewer
type: gate
depends_on: [developer]
commands:
- name: tests
run: npm test
max_iterations: 3
workflow:
phases:
- name: architect
type: standard
- name: tester
type: standard
depends_on: [architect]
- name: security-auditor
type: standard
depends_on: [architect]
- name: developer
type: standard
depends_on: [tester, security-auditor]
- name: reviewer
type: gate
depends_on: [developer]
commands:
- name: build
run: npm run build
- name: tests
run: npm test
max_iterations: 3
workflow:
phases:
- name: architect
type: standard
- name: developer
type: standard
depends_on: [architect]
- name: security-audit
type: team
depends_on: [developer]
team: "@acme/security-scan"
inputs:
scan_target: src/
- name: reviewer
type: gate
depends_on: [security-audit]
commands:
- name: tests
run: npm test
max_iterations: 3

Here, the security audit is handled by a separate team (@acme/security-scan) that runs its own multi-agent pipeline. The reviewer gate downstream receives the security audit’s results through a normal channel handoff — the team agent collects the sub-team’s task board and channel outputs and writes them as a standard handoff.

workflow:
phases:
- name: fetch-data
type: standard
agent: gdrive
action: get
sources:
- name: source-docs
ref: "$(inputs.folder_id)"
- name: architect
type: standard
depends_on: [fetch-data]
- name: developer
type: standard
depends_on: [architect]
- name: tester
type: standard
depends_on: [architect]
agent: test-specialist
- name: reviewer
type: gate
depends_on: [developer, tester]
commands:
- name: build
run: npm run build
scope: repo
if: "test -f package.json"
- name: tests
run: npm test
scope: repo
if: "test -f package.json"
max_iterations: 3
- name: git-finalize
type: standard
depends_on: [reviewer]
agent: git
action: create_pr
- name: git-verify
type: standard
agent: exec
depends_on: [git-finalize]
commands:
- name: pushed
run: "git ls-remote --heads origin $(git branch --show-current) | grep -q ."
- name: publish
type: standard
depends_on: [git-verify]
agent: gdrive
action: create
target_entries:
- name: summary
file: reports/summary.md
ref: "$(inputs.output_folder)"
support:
- name: git-resolver
type: standard
- name: hotfix-dev
type: standard