Skip to main content
A board’s team is a queryable data structure, not prose. It lets you describe which personas are associated with which stages of a workflow and surface that context to agents and the UI. The team is optional and purely additive — nothing in Substrate gates a write based on team membership.

The registry (project-level identity)

Each member is defined once in a file at .substrate/members/<id>.json. Define it once; reference it from any number of boards.
.substrate/members/oversight.json

Member file fields

string
required
Unique identifier. Must match the filename (oversight.json"id": "oversight").
string
required
Display name for the UI and for get_board_substrate responses.
string
Prose depth — what this persona is for, how it reasons, what it owns.
string[]
Array of trait statements. Used to drive chips in the UI and to inform orchestration queries.
string[]
Array of concern statements. Same intent as traits — surface what this persona watches for.
string
A pointer to a git-committed folder containing this persona’s memory or context files. Substrate stores the path and never reads its content.

The board binding

Each board nests a thin team array: a member reference and the groups it is associated with on that board.
get_board_substrate returns the team with each member resolved from the registry — name, traits, concerns, and memory_dir — alongside the binding’s group list. The web UI renders this as a Team card on the board view.

Advisory, never enforced

groups in a team binding is a hint for orchestration and display. It is many-to-many, grants nothing, and never gates a write or a move. A member listed for ["spec", "review"] does not prevent any other agent from writing to those groups.
A member is also distinct from the agent_name / created_by_agent actor tag on a write. A member is a persona — a description of a role. An actor tag records who performed a specific write. They are not the same concept.

Integrity problems are warnings, not errors

None of the following conditions fail a substrate load, a substrate validate run, or any write:

Unresolved member

A team[].member value with no corresponding registry file. The binding is kept with unresolved: true rather than dropped.

Unknown group

A binding references a group id that isn’t on the board. Archived groups are fine — active groups that don’t exist produce a warning.

Duplicate member id

Duplicate id in the registry, or the same member listed twice in a board’s team array. Warned and the duplicate is skipped.

Malformed file

A member file that fails to parse is warned and skipped. The rest of the substrate loads normally.
There are no member write tools in v0.7.0. Author the registry files and board bindings directly as JSON.