Roster
Browse the docs

org.yaml reference

Every field in the org manifest, and what reads it.

The org manifest. Lives at the root of the ops repo, and is read at the top of every composed prompt, by runner-plan.mjs, by agents.mjs, and by every CLI command.

Parsed by parseYaml in compose.mjs, which reads a deliberately small, strict subset of YAML: scalars, nested maps, block lists, and inline maps in a list. It does not do anchors, multi-line scalars, or flow maps at the top level. A manifest that needs more than that has outgrown being a manifest, and the parser refuses to guess rather than misparsing.

A complete example

org: acme
name: Acme Robotics
ops_dir: roster-ops
 
human:
  name: Will
  github: you
  marker: will
  role: founder
 
experiment_private: true
 
agent:
  id: claude-code-action
  permissions: full
 
defaults:
  model: claude-opus-5
  timeout_minutes: 90
  mention_timeout_minutes: 90
 
staff:
  - { handle: cto, dir: technology, name: Chief Technology Officer, schedule: "0 7 * * 1-5" }
  - { handle: cmo, dir: marketing, name: Chief Marketing Officer, schedule: "40 7 * * 1-5" }
 
repos:
  - { name: acme-web, visibility: public, role: product }
  - { name: technology, visibility: private, role: brain }
  - { name: roster-ops, visibility: private, role: ops }

Fields

Top level

Field Required Means
org yes The GitHub organisation. Every repo name is resolved against it.
name yes What the business is called, in prose. Appears in prompts.
ops_dir no Directory name of the ops repo in the runner checkout. Defaults to roster-ops.
experiment_private no Whether the fact that this org is agent-run is itself private. Read by the guardrails fragment.

human and humans

Who the staff answer to. One person is a human map; more than one is a humans list:

humans:
  - { name: Will, github: will-lamerton, marker: will, role: founder }
  - { name: Sam, github: sam-x, marker: sam, role: operations }
Field Required Means
github yes Login. The mention callers gate on these, so without one nothing can wake an agent.
name no What to call them in prose. Defaults to the login.
marker no Provenance tag on a fact they ruled on, as in [will]. Also used as a label. Defaults to the first part of the name, lowercased.
role no Prose only.

Both keys are read, and the singular is not deprecated: an org with one human should keep writing human. When both are present, anyone in human who is not already in the list is appended rather than dropped.

The first entry is the primary. Prompts are prose addressed to somebody ("Will is not here"), and a list of two cannot go in that sentence, so the first one goes there, their marker is what %%HUMAN_MARKER%% renders, and the rest are named by {{humans_extra}} in the identity fragment. Everything that gates on identity reads all of them: the mention caller's if: is contains(fromJSON('["will-lamerton","sam-x"]'), …).

Adding a human changes every generated caller workflow, so it takes a roster upgrade to reach the brain repos. Until that lands, the new person can open issues and read everything, and mentioning a staff member does nothing.

agent

Which coding agent runs a session. Either a string, or a map. See choosing a coding agent.

Field Required Means
id no A preset name, or your own label. Defaults to claude-code-action.
install if id is unknown Shell command that installs the agent on the runner.
run if id is unknown Shell command that runs it, reading $AGENT_PROMPT_FILE.
token_env if id is unknown Environment variable its credential goes in.
model no Default model for this agent. A staff member's own model wins.
permissions no full, workspace or read-only. Defaults to full. One word, translated into each agent's own vocabulary: a tool list for Claude, a sandbox and an approval policy for Codex, a development mode for nanocoder. A staff member can set their own, and be trusted less than the org.
options no A map, in that agent's own vocabulary, spelled onto its command line untranslated. The escape hatch for anything roster does not model.

Any field given overrides the preset's, so a preset that is right except for one flag needs one line.

An agent that needs a config file of its own gets one written when roster init chooses it, with the parts only a person can supply left as FILL IN blanks. roster doctor fails while any of them are still there.

defaults

Fallbacks for staff members who do not set their own.

Field Means
model Model id passed to the agent.
timeout_minutes Ceiling on a daily session. 90 if unset.
mention_timeout_minutes Ceiling on a mention run. Falls back to timeout_minutes, then 90.
allowed_tools Claude's own spelling of a permission level, kept because it predates agent.permissions and still wins for the agents that take a tool list. Nothing translates it for the others: a list written for one agent is not a permission level for another. Prefer agent.permissions, which every agent understands.

staff

The registry. One inline map per staff member. This is the org's view of them; the rest lives in their own staff.yaml.

Field Required Means
handle yes Short identifier. Must match the handle in their manifest.
dir no Directory and repo name. Defaults to the handle.
name no Role name in prose.
schedule no Cron. Informational here; the caller workflow is what actually schedules.

roster hire appends to this list. An empty list (staff: []) is valid and is what a fresh org has.

repos

Every repository the org owns, and what it is for.

Field Means
name Repo name, resolved against org.
visibility public or private. roster doctor warns when this disagrees with reality.
role brain, product or ops.

role: product is load-bearing: roster hire uses it to fill a new staff member's works_in, and the prompts refer to the product repo by name.

What reads what

Reader Uses
compose.mjs org, name, human, humans, ops_dir, staff
runner-plan.mjs org, staff, and each manifest's works_in and peers
agents.mjs agent, staff
roster hire all of it, plus every existing manifest
roster doctor all of it

Editing it

It is yours. roster upgrade never touches it: it has no template, because a tenant's registry is not something a framework can have an opinion about.

The exception is roster hire --apply, which appends a staff entry and a repos entry. Those are inserted textually under the existing keys rather than by re-serialising the file, so your comments and formatting survive.

Edit this page on GitHub