Skip to main content
A Substrate board is shared state. Multiple agents, multiple sessions, and human teammates all read and write the same data. The conventions below are what separate a board that stays coherent from one that drifts into noise. They are not suggestions — a board where any one of these is consistently violated stops being a reliable source of truth.

Do

Pass agent_name on every write

Use a stable identifier for yourself — for example, "claude-code". It is an audit tag, not authentication, but a board where every write is attributable is the difference between a log and a guess.

Use optimistic concurrency properly

update_task, update_board, update_group, update_policy, and update_project all require the version from your most recent read. On a version_mismatch error: re-read, reconcile, then retry. Never blindly overwrite.

Read before you write

Resolve real board and group ids from whoami and get_board_substrate. Do not guess an id — a guessed id that happens to match an unrelated entity is silent corruption.

Merge custom_data key-by-key

Send only the keys you are changing. Pass null for a key to delete it. You do not need to resend the whole object — Substrate merges at the key level.

Put decisions in comments, state in fields

A policy can read a field; nothing reads prose. If a gate depends on a value, that value must be a field.

Do Not

Do not invent board or group ids

Resolve them from reads. An invented id that silently matches something else is worse than a clear error.

Do not skip agent_name or omit version on an update

Both are required for attribution and concurrency correctness. Omitting either is the most common cause of confusing audit logs and unexpected overwrites.

Do not duplicate a board or group that already fits

Extend the existing substrate. Two boards modelling one flow is how a substrate stops being a single source of truth.

Do not treat a block or a suggestion as noise

A transition_guard block and an agent_responsibility message are the point of the system, not friction in it. Read them and act.

Do not try to set a human_only field

Your tools refuse it. That refusal is what makes the gate real. Report it instead — see list_pending_approvals.

Your Own Error Trail

Handled tool errors from your session are recorded to .substrate/logs/substrate.log. To surface only the errors:
Routine gate blocks and stale-version retries are intentionally excluded from this log — they are normal operation, not faults. What remains is worth reading when something is not behaving as expected, and worth attaching to a bug report alongside substrate diagnose.