Appearance
Labels & work types
You'll learn what the two kinds of labels do — work:* labels select skills, agent labels select the coding agent — and how to set them.
Labels are terms on the control plane. Most are plain tags, but two families carry meaning for the machinery, and both are read by the agent at dispatch time rather than by the control plane.
work:* — the sub-works a ticket contains
A work:* label declares one kind of work in the ticket, its sub-work. The value after the prefix is the work type, and it is the first component of the triple a skill declares it owns — (work_type, workflow, step). That is how a ticket carrying work:docs gets a documentation skill for coding, while one carrying work:code gets the code skill.
| Label | Work type | Owned by | Validated by |
|---|---|---|---|
work:code | code | the project's code skills (for a Drupal project: @gaia/ddev-drupal-feature, @gaia/ddev-drupal-bug) | the project's test suite, a browser scenario where one applies |
work:docs | docs | @gaia/docs-authoring | proportional doc, frontmatter and contract checks — no runtime |
| project-defined | — | a skill the project loads | whatever that skill declares |
Only work:code is universal. work:docs is shipped but opt-in — a project loads the skill in its WORKFLOW.md or does not. Projects add their own: the GAIA repository itself carries work:design-to-designbook and work:designbook-to-config for design work that runs through Designbook.
A ticket may carry several work:* labels. Then each sub-work has its own step owner, all of them run at each step in WORKFLOW.md load order, and the last one performs the single confirmation and transition — see Skills and the workflow contract.
qualification is the one step before the sub-works are known — it is owned by a skill that declares no work type, and it is what sets the work:* labels in the first place. From spec on, the work type selects the owner: @gaia/create-spec owns spec for code, @gaia/docs-authoring for docs.
Agent labels — which coding agent runs the ticket
The engine config lists the agent addons a conductor may launch. Each candidate may carry a priority function the conductor calls per ticket at dispatch; the ticket arrives with its labels as a list of names, so a label on the ticket picks the agent:
js
agent: [
{ agent: { plugin: '@gaia-ai/addon-claude' }, priority: () => 0 },
{ agent: { plugin: '@gaia-ai/addon-codex' },
priority: (t) => t.labels.includes('codex') ? 10 : -Infinity },
]With that config, a ticket labelled codex runs on Codex and every other ticket on Claude Code. The { agent, priority } wrapper is what carries the function — a bare { plugin } entry has no priority and scores lowest. The GAIA control plane ships codex, kimi, kimi-opencode, pi and grok as labels for exactly this use; which of them your conductor honours is its engine config's business — Choose the coding agent.
Other labels
Anything else is a plain tag for people and filters. Projects add what they need; nothing in GAIA reacts to a label outside the two families above.
Setting labels
- In the cockpit: open the ticket and use the edit form — labels, parent and cancel live there.
- In the new-ticket popup: labels are a field; add
work:codeunless you want the qualification step to decide. - With
gaia dropsh: write thelabelsrelationship on the ticket. The terms' uuids come fromgaia dropsh search gaia_term --bundle gaia_labels:
sh
gaia dropsh --auth-profile pm update gaia_ticket/gaia_ticket/<uuid> --data @labels.json --dry-runjson
{ "data": { "type": "gaia_ticket--gaia_ticket", "id": "<uuid>",
"relationships": { "labels": { "data": [
{ "type": "gaia_term--gaia_labels", "id": "<work:code uuid>" },
{ "type": "gaia_term--gaia_labels", "id": "<codex uuid>" } ] } } } }A labels write replaces the list; include every label the ticket should keep.
Next
- Skills and the workflow contract — how the work type selects exactly one skill per step.
- Choose the coding agent — the agent addons and the priority rule.
- Handoffs & comments — where the qualification step records the labels it set.