Skip to content

Run a conductor

You'll learn how to start the conductor for a checkout, read its status, stop it cleanly, and clean up after finished tickets.

A conductor is one claim-and-dispatch loop bound to one project checkout. You run one per checkout you want to work tickets in; the control plane coordinates them. It is hosted by herdr, the terminal workspace manager, so the agent sessions it starts get real terminal tabs you can look into.

Start

sh
cd /path/to/your/repo
gaia conductor start

start hands the loop to herdr and returns. The conductor registers itself on the control plane — its machine_id, project and workspace root — and begins to poll. Two flags:

FlagEffect
--foregroundrun the loop in this process instead of a herdr-hosted one; useful in a service unit or when debugging
--no-update-checkskip the once-a-day check for a newer @gaia-ai/gaia (the notice it prints is informational; gaia update installs it)

The conductor needs the repository's committed .gaia/conductor.config.js (Connect a repository) and the machine's ~/.gaia/ context. It does not need a WORKFLOW.md to start — but the runs it starts do.

Status

sh
gaia conductor status   # this checkout's conductor
gaia conductor ls       # every conductor the control plane holds for you, on any machine

Both print one line per conductor: machine id, liveness, project, label, workspace root.

pg-Mac.fritz.box-gaia	online	gaia	pg-Mac.fritz.box-gaia	/Users/pascal/Projects/gaia

Liveness is one of three words, derived the same way everywhere — the CLI, the cockpit and the control plane's own list: online (heartbeating within its lease), stale (registered as online but the heartbeat is old or the lease has lapsed), offline (stopped, or never reported). The control plane's conductor list adds the live load, as 3/10 — three active runs of a max_parallel of ten.

The cockpit has the same list on its root Conductors tab — label, machine_id, project, liveness, age, workspace, last known pid — filtered to the conductors you own, which is how it opens. Press m to see every conductor on the control plane and m again to go back; c returns to the default. While the filter is on, the list states how many rows it is holding back, so a filtered list never reads like a missing record. Rows are ordered by last heartbeat, newest first, and paged twenty at a time — and move between pages.

The filter is a presentation choice, not an access one: a session token may read every conductor in its workspace, and the cockpit simply does not show you everyone else's until you ask. There s starts the selected conductor, x stops it, R refreshes, and Enter opens its log.txt. Your own conductors on other machines stay listed, marked elsewhere, and take no action — the filter is by owner, never by machine.

What a tick does

On every poll the conductor:

  1. heartbeats its registration (last seen, current load) and reads its own status;
  2. stops here if it is draining or its slots are full;
  3. asks the control plane to atomically claim the next eligible ticket;
  4. ensures the worktree for that ticket under .gaia-worktrees/, running the project's worktree hooks;
  5. starts the agent session detached and marks the run running.

Separately, its finalise pass winds up runs the control plane has retired since the last tick — captures each run's transcript and footprint and closes its hosted tab. Nothing in the tick writes ticket state; that is the agent's job.

Which tickets it takes

A conductor claims the tickets of its project that carry it in their conductor_id — plus tickets that have no workflow yet, which any conductor of the project may qualify. The ticket must be in a claimable state, its blockers closed, and no live claim on it. The engine config's states list narrows further: an empty list means every claimable state, a list means only those. The generated config lists spec, diagnose, coding and review — add qualification if this conductor should qualify hand-written tickets. Eligible tickets are taken by priority first, then oldest first.

Capacity is per conductor — max_parallel in the engine config. Cluster capacity is simply the sum over the conductors you run.

Stop

sh
gaia conductor stop         # graceful: go offline, claim nothing more
gaia conductor stop --now   # hard-kill the hosted process; a server-side reaper marks it offline

Prefer the graceful form: it stops claiming and lets the control plane see the conductor go offline in an orderly way. Runs already started keep running — the agent sessions live in their own tabs.

Run a single cycle

sh
gaia conductor --log-level debug poll

poll runs one tick and exits. With debug it logs the tick: whether it claimed, whether it was at capacity, or that it found nothing to claim. It does not say why a particular ticket was passed over — a ticket that fails an eligibility rule is simply not a candidate — so for "why does nobody pick up my ticket?" check the ticket's conductor, state and blockers directly, as Troubleshooting walks through.

Clean up worktrees

sh
gaia conductor reap

reap tears down the herdr worktrees of tickets that are finished but were never cleaned up — the ones a live tick missed because the conductor was down when the ticket reached done, was restarted, or the ticket was reassigned. Safe to run any time.

Logs

The conductor logs to log.txt in the checkout's .gaia/ workspace root, and to the terminal when it has one. Two knobs, as flags or environment variables:

FlagEnvValues
--log-levelGAIA_LOG_LEVELdebug · info (default) · warn · error
--log-sinkGAIA_CONDUCTOR_LOGstdout · file · both (default on a terminal; file otherwise)

The flags go before the subcommand: gaia conductor --log-level debug start --foreground. Each run's own log and footprint live on the run, visible on the ticket's Runs tab in gaia ui.

Next