Skip to main content
The team board is the durable half of a team — a coordinator’s transcript scrolls away, the card that says who holds what does not. These are the routes a person, a script or a dashboard reads and writes it through; the agents themselves use the board_read and board_write tools, against the same rows.

Addressing a board

A board is addressed by its brd_ id or by the agt_ id of the agent that owns it. That is not a convenience. A board is minted on first use, one per agent, and a board with no cards has never told anyone its brd_ id — so on a brand-new team the agent id is the only reference a caller can have. One board per agent — unique (org_id, agent_id) — so POST /v1/boards is an ensure, not a create that can conflict. It is also not the only way a board comes into being: the first read or write against the agt_ spelling mints one too.
There is no delete call. A card is never removed: a finished card is the record of what the team was asked to do, and a task that vanishes takes the answer to “what happened here” with it. Move it to done instead.
Every route here is gated by agents:read for reads and agents:write for writes: a board belongs to an agent, and the scope grammar is fixed.

The board object

string
Unique id (brd_…).
string
Always board.
string
The agent that owns the board (agt_…). One board per agent.
object
How many cards stand in each column: { "todo": n, "doing": n, "blocked": n, "done": n }. All four keys are always present, so 0 and “absent” never read the same. This is a real aggregate over the board, not the length of a page — which is the one fact a page of cards cannot state, because a page is truncated and a count is not.
string
Creation timestamp.

The card object

string
Unique id (crd_…). Derived from the board, the writing session and the title, so a retried write collides with the row it already made rather than duplicating it.
string
Always board_card.
string
The board this card is on (brd_…).
string
Short label, 1–200 characters.
string
The card’s notes — what was done and what is left. A member cannot see another member’s conversation, so this is the hand-off.
string
One of todo, doing, blocked, done. Fixed — not configurable columns.
string | null
A roster member’s name, not an id. null is unclaimed.
string[]
The crd_ ids this card waits on. A blocked card with an empty list is stuck on the world. When every card in the list reaches done, this card is promoted back to todo on the next read.
string
Creation timestamp.
string
Last modification timestamp.

The comment object

string
Unique id (bcm_…).
string
Always board_comment.
string
The card commented on (crd_…).
string
Who wrote it, as an id the server derived — never a name the caller supplied. A person’s comment carries their usr_ or key_ principal; a member’s, written through board_write, carries the ses_ id of the thread. The prefix is what lets a reader tell an agent’s comment from a person’s.
string
The comment text.
string
Creation timestamp.

Ensure a board

POST /v1/boards → the board object. 201 Created when this call minted the row, 200 OK when it found one already there.
string
required
The agent that owns the board (agt_…). 404 not_found if this organization has no such agent.
Calling it twice is not a conflict. There is one board per agent, so the second call answers the same board and the status code is the only difference between the two outcomes — a caller that does not care ignores it and reads the same board either way.

Get a board

GET /v1/boards/{id} → the board object. {id} is a brd_ id or the owning agt_ id. This is the read that answers a board’s own id, its owner and how much work stands on it. The cards routes answer cards.

Read an agent’s board

GET /v1/agents/{id}/board → the agent’s cards, in column order (todo, doing, blocked, done) and then oldest first. Mints the board if the agent has none, so a team that has not started answers an empty page rather than a 404. The response is the standard pagination envelope of card objects.

List a board’s cards

GET /v1/boards/{id}/cards → the same cards, addressed by board reference. {id} is a brd_ id or the owning agt_ id. Same envelope, same column order.

Add a card

POST /v1/boards/{id}/cards201 Created with the card object.
string
required
1–200 characters.
string
The card’s notes, up to 8192 characters.
string
todo (default), doing, blocked or done.
string | null
A roster member’s name, up to 128 characters. Defaults to null.
string[]
Up to 50 crd_ ids this card waits on.

Get one card

GET /v1/boards/{id}/cards/{cid} → the card object. A card that is not on the named board answers 404 not_found, even if the id exists elsewhere in your organization.

Update a card

PATCH /v1/boards/{id}/cards/{cid} → the updated card object. Every field of the create body is accepted and every one is optional, so a move is {"status": "doing"} and nothing else. "assignee": null unclaims the card; omitting the key leaves the current holder alone.
This is an operator’s override, and it is deliberately more powerful than the agents’ own board_write. A person has the card on screen and outranks the claim guards, which exist only to stop two members stepping on each other — and this is the only way to retitle or reassign a card, because through the tool those are set at create.

Read a card’s comments

GET /v1/boards/{id}/cards/{cid}/comments → the card’s comments, oldest first, in the standard pagination envelope. A card’s comments are a conversation, so they are not reversed the way a feed is. A cid that is not on the named board answers 404 not_found, the same guard the card read sits behind.

Comment on a card

POST /v1/boards/{id}/cards/{cid}/comments201 Created with the comment object.
string
required
The comment text, 1–8192 characters.
There is no author field, and sending one is a 400 invalid_request. The server signs the comment with the principal behind your key, so nobody has to invent a name for themselves — or for anyone else. Nothing used to stop an operator signing a comment fact-checker.

The board, in concept

The four statuses, the two tools agents call, and how the board composes with delegation.