Roster
Browse the docs

staff.yaml reference

Every field in a staff member's manifest.

A staff member's manifest: the machine-readable half of their charter. Lives at the root of their brain repo.

roster lint fails if this and CHARTER.md disagree. Same strict YAML subset as org.yaml.

A complete example

handle: cto
name: Chief Technology Officer
mention: "@cto"
brain: acme/technology
status_issue: 15
 
schedule: "0 7 * * 1-5"
model: claude-opus-5
timeout_minutes: 90
mention_timeout_minutes: 90
 
bot: acme-cto[bot]
public_bot: acme-robot[bot]
public_token_env: PIPWEB_TOKEN
agent_secret: CLAUDE_CODE_OAUTH_TOKEN
 
identities:
  - { app: acme-cto, secret_prefix: CTO, scope: private }
  - { app: acme-robot, secret_prefix: BOT, scope: public }
 
works_in:
  - { repo: acme/acme-web, role: contributor, checkout: true }
 
peers:
  - { handle: cmo, brain: acme/marketing, label: from-cto }
 
surfaces:
  - { path: memory/, render: memory }
  - { path: strategy/, render: doc }
  - { path: assets/, render: gallery }
  - { path: data/, render: table }
 
labels:
  owner: [will, cto, cmo]
  kind: [decision, setup, build, blocked]

Identity

Field Required Means
handle yes Must match org.yaml. The composer looks them up by the org.yaml one, so a mismatch composes the wrong brain.
name yes Role name in prose.
mention yes What wakes them, as in @cto. The caller's condition tests for this string.
brain yes owner/name of this repo. Without it nothing can check secrets, labels or runs.
status_issue yes in practice Number of the pinned status issue. The prompts reference it, so a run cannot compose without it. roster hire --apply writes it.

Schedule and limits

Field Default Means
schedule none Cron for the daily run. Rendered into the caller.
model org default Model id.
timeout_minutes 90 Ceiling on the daily session.
mention_timeout_minutes 90 Ceiling on a mention run.

The three ceilings are separate on purpose. Raising the daily one because sessions have grown should not double the budget for a PR amendment. A job killed by a ceiling is reported by GitHub as cancelled; see troubleshooting.

These are the source of truth. The caller workflow carries a rendered copy, so change the manifest and run roster upgrade, not the other way round.

Identities

Field Means
bot Login this staff member posts as on private trackers, as in acme-cto[bot].
public_bot Login it posts as on the public product repo.
public_token_env Environment variable holding the public token inside a run.
agent_secret Repo secret holding the coding agent's credential.
identities One entry per App.

Each identities entry:

Field Means
app The GitHub App slug. Carries the house naming scheme, so it is inferred from a sibling rather than built from the handle.
secret_prefix Secrets are <prefix>_APP_ID and <prefix>_APP_PRIVATE_KEY.
scope private (this staff member's own) or public (shared by everybody).

The public identity is shared deliberately. A bot opening a pull request on a public repo is unremarkable; a bot signing itself with a job title is a tell.

The [bot] suffix is how a manifest spells it and not how GitHub reports it. An issue authored by the App has author acme-cto. roster normalises this; if you are matching on it yourself, strip the suffix.

Relationships

works_in

Repos this staff member contributes to but does not own.

Field Means
repo owner/name.
role Prose. contributor in practice.
checkout Whether the runner clones it.

The first entry becomes {{staff.product}} in prompts. A staff member with an empty works_in has no product, and any prompt fragment referring to one must guard with {{#if staff.product}}.

peers

The other staff members this one files work with.

Field Means
handle Their handle.
brain Their repo.
label The label this staff member uses when filing on that tracker.

The label is not symmetric. In the CTO's manifest the entry for the CMO carries from-cto, and that label lives on acme/marketing, because that is where the CTO's asks land. roster hire writes both directions and roster doctor checks the label exists on the peer's repo, not this one.

surfaces

What this staff member keeps, and how the portal renders it.

render Shows as
memory Parsed fact cards
doc Markdown, rendered
gallery Image grid
table CSV as a table
code Monospace, syntax preserved

A surface is a promise: roster doctor warns when one is declared and not on disk.

labels

Labels this staff member expects to exist on its own tracker, grouped for readability. Every value across every group is checked by roster doctor. An agent applying a label that does not exist gets an API error mid-run.

What roster upgrade does to this file

Nothing. It is scaffold class: written once by roster hire, and yours from that moment. A framework change that adds a manifest field will not reach an existing staff member, which is a deliberate trade against the risk of merging into a file a working agent has rewritten.

Edit this page on GitHub