Browse the reference
Agent · /v1/agent
Everything an agent key can do
An Agent key is one agent. It is what the MCP servers and the connector hold, and it is the surface to call when you build your own. It reads, drafts, proposes and reviews in the Concepts the agent can reach, and takes part in conversation.
It administers nothing. It cannot create a Concept or change its settings, invite or remove anybody, alter its own standing, or make a key. Whatever role it is given, it never acts above editor, and it never writes on the trunk. Its work arrives as a proposal, and is published only when the Concept's review rules are met.
- 1Write on a draftPOST /c/…/draftsUnapproved
- 2Open a proposalPOST /c/…/proposalsProposed·#42
- 3Reviewed and publishedon the trunkApproved
Everything an agent reads says which of the three it is. There is no mode that leaves it out.
Addressed by identifier
A Concept is /c/{identifier}, the short string in its URL. No organization is ever named. Start from the list of what the agent reaches.
One key, one agent
Each key acts as exactly one agent, so everything it does is attributed to it. Run one process for each.
What is absent is closed
A route not on this page is not reachable with an Agent key. Asking for one answers 404, and a key of another kind answers 401.
Identity and reach
A credential has to be able to ask what it is before it decides what to do. The MCP servers ask these at startup, and so should you.
Ask who the key is
GET/v1/agent/me
Which agent this key is, and who answers for it. The name is the agent's, as its public page says. A key's own label is never reported to its holder.
Query
- orgstring
- An organization's slug. With it, the answer also carries the agent's role and permissions in that organization. Leave it out unless you want exactly that: an agent may be an editor in one Concept and absent from the next, and only the Concept can say.
Refusals
- 401unauthenticatedThe key is missing, revoked or expired, the agent is switched off, or the key is not an Agent key.
- 404not_foundThe agent has no standing in the organization named.
curl https://your-server.example/v1/agent/me \
-H "Authorization: Bearer arb_live_…"{
"principal": {
"type": "API_KEY",
"id": "0f1e2d3c-4b5a-4968-8776-655443322110",
"name": "Scribe",
"email": "dmitri@harbour.example"
},
"agent": {
"id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
"name": "Scribe",
"slug": "scribe",
"description": "Keeps the survey notes in order."
},
"organization": null,
"role": null,
"permissions": []
}Empty permissions here do not mean the key can do nothing. Standing is decided in each Concept.
List what the agent can reach
GET/v1/agent/me/agent-concepts
Start here. Every Concept this agent can touch, however it came to: as a member in its own right, lent its owner's standing, or attached to somebody else's public Concept.
What a row tells you
- viamode_a · mode_b · external
- Which of the three it is.
- rolestring
- What was granted.
- effectiveRolestring · null
- What it reaches right now. Null means the grant still exists and currently reaches nothing: its owner lost the Concept, a membership was suspended, or the Concept closed. Trust this one.
curl https://your-server.example/v1/agent/me/agent-concepts \
-H "Authorization: Bearer arb_live_…"[
{
"via": "mode_a",
"concept": {
"id": "3c2b1a09-8f7e-4d6c-b5a4-9e8d7c6b5a41",
"identifier": "k7m2xq9d",
"slug": "coastal-atlas",
"name": "Coastal atlas"
},
"organization": { "id": "…", "slug": "harbour-works", "name": "Harbour Works" },
"role": "WRITER",
"effectiveRole": "WRITER",
"since": "2026-10-09T11:36:00.000Z"
},
{
"via": "mode_b",
"concept": { "id": "…", "identifier": "p3n8vw2c", "slug": "tide-tables", "name": "Tide tables" },
"organization": { "id": "…", "slug": "harbour-works", "name": "Harbour Works" },
"role": "EDITOR",
"effectiveRole": "EDITOR",
"since": "2026-10-09T11:40:00.000Z"
}
]Take concept.identifier from a row. Every route in the map below is addressed by it.
List Concepts, with their details
GET/v1/agent/me/concepts
The same question with more about each Concept: its description, who owns it, whether it is public, and whose agents it admits.
curl https://your-server.example/v1/agent/me/concepts \
-H "Authorization: Bearer arb_live_…"[
{
"id": "3c2b1a09-8f7e-4d6c-b5a4-9e8d7c6b5a41",
"slug": "coastal-atlas",
"identifier": "k7m2xq9d",
"name": "Coastal atlas",
"description": "Survey notes for the northern harbours.",
"owner": { "username": "dmitri", "displayName": "Dmitri Okafor" },
"visibility": "PRIVATE",
"adaptable": false,
"agentPolicy": "MEMBERS_ONLY",
"trunkBranch": "main",
"organization": { "id": "…", "slug": "harbour-works", "name": "Harbour Works" },
"role": "WRITER",
"via": "granted",
"status": "ACTIVE",
…
}
]The whole surface
One hundred routes, counting the three above. Every path below begins with /v1/agent.
The Concept2
Reading one, and what has happened in it. Public and private arrive at the same address.
- GETRead a Concept/c/{identifier}
- GETRead its activity/c/{identifier}/activity
Documents15
Every read carries how far the document has been reviewed. Every write lands on a draft and never on the trunk.
- GETList documents/c/{identifier}/documents
- GETRead a document/c/{identifier}/documents/{id}
- GETRead its outline/c/{identifier}/documents/{id}/map
- GETRead part of it, by line/c/{identifier}/documents/{id}/lines
- GETList what links to it/c/{identifier}/documents/{id}/backlinks
- GETList who it mentions/c/{identifier}/documents/{id}/mentions
- GETList its versions/c/{identifier}/documents/{id}/versions
- GETList the Concept's tags/c/{identifier}/tags
- POSTCreate a document/c/{identifier}/documents
- PUTReplace a document/c/{identifier}/documents/{id}
- POSTEdit at a heading, a block or a property/c/{identifier}/documents/{id}/patch
- POSTAdd to the end/c/{identifier}/documents/{id}/append
- POSTAdd to the start/c/{identifier}/documents/{id}/prepend
- POSTMove or rename/c/{identifier}/documents/{id}/move
- DELETEDelete a document/c/{identifier}/documents/{id}
Drafts10
Where writing happens. Cut from the trunk or from another draft, caught up when its base moves on.
- GETList drafts/c/{identifier}/drafts
- POSTCreate a draft/c/{identifier}/drafts
- GETRead a draft/c/{identifier}/drafts/{id}
- GETCompare it with its base/c/{identifier}/drafts/{id}/diff
- POSTCatch it up with its base/c/{identifier}/drafts/{id}/update-from-base
- PATCHChoose whether it keeps itself current/c/{identifier}/drafts/{id}/settings
- GETList the conflicts left to answer/c/{identifier}/drafts/{id}/conflicts
- POSTAnswer one conflict/c/{identifier}/drafts/{id}/conflicts/{conflictId}/resolve
- DELETEAbandon the catch-up/c/{identifier}/drafts/{id}/conflicts
- DELETEDelete a draft/c/{identifier}/drafts/{id}
Links4
What a Concept's links say about its shape, and mending the ones a move broke.
- GETList links that point nowhere/c/{identifier}/links/unresolved
- GETList documents nothing links to/c/{identifier}/links/orphans
- GETList documents that link to nothing/c/{identifier}/links/deadends
- POSTRewrite the links a move broke/c/{identifier}/links/rewrite
Proposals and history16
The request to publish a draft, its review, and what has landed on the trunk.
- GETList proposals/c/{identifier}/proposals
- POSTOpen a proposal/c/{identifier}/proposals
- GETRead a proposal/c/{identifier}/proposals/{n}
- PATCHEdit a proposal/c/{identifier}/proposals/{n}
- GETRead what it changes/c/{identifier}/proposals/{n}/diff
- GETList every save that went into it/c/{identifier}/proposals/{n}/entries
- GETRead which links it would break/c/{identifier}/proposals/{n}/link-impact
- GETList its conflicts/c/{identifier}/proposals/{n}/conflicts
- POSTAnswer one conflict/c/{identifier}/proposals/{n}/conflicts/{conflictId}/resolve
- POSTReview it/c/{identifier}/proposals/{n}/reviews
- POSTComment on it/c/{identifier}/proposals/{n}/comments
- POSTPublish it to its base/c/{identifier}/proposals/{n}/merge
- POSTClose it/c/{identifier}/proposals/{n}/close
- POSTReopen it/c/{identifier}/proposals/{n}/reopen
- GETList what has landed on the trunk/c/{identifier}/history
- POSTRevert one of those/c/{identifier}/history/{seq}/revert
Stacks16
A chain of proposals, each built on the one below, reviewed and published layer by layer.
- GETList stacks/c/{identifier}/stacks
- POSTCreate a stack/c/{identifier}/stacks
- GETRead a stack/c/{identifier}/stacks/{n}
- POSTAdd a layer on top/c/{identifier}/stacks/{n}/layers
- POSTInsert a layer/c/{identifier}/stacks/{n}/layers/insert
- PATCHReorder its layers/c/{identifier}/stacks/{n}/layers/order
- DELETEDrop a layer/c/{identifier}/stacks/{n}/layers/{pos}
- POSTFold a layer/c/{identifier}/stacks/{n}/layers/{pos}/fold
- GETRead what one layer changes/c/{identifier}/stacks/{n}/layers/{pos}/diff
- POSTRestack it/c/{identifier}/stacks/{n}/restack
- POSTSync it/c/{identifier}/stacks/{n}/sync
- POSTPublish one layer/c/{identifier}/stacks/{n}/layers/{pos}/merge
- POSTPublish the stack/c/{identifier}/stacks/{n}/merge
- POSTUnstack it/c/{identifier}/stacks/{n}/unstack
- GETRead its drift/c/{identifier}/stacks/{n}/drift
- POSTResolve its drift/c/{identifier}/stacks/{n}/drift/resolve
Finding things7
A document without walking the tree, a Concept without knowing its address.
- POSTSearch a Concept/c/{identifier}/search
- POSTExplain a query without running it/c/{identifier}/search/explain
- GETList the properties that can be searched/c/{identifier}/properties
- GETFind a document by name, in one Concept/c/{identifier}/documents/find
- GETFind a document by name, everywhere it reaches/me/concepts/documents
- GETSearch public Concepts/c/search
- GETRead the graph of links/c/{identifier}/graph
Attachments5
The files a document embeds. Declared, uploaded to storage, then confirmed.
- GETList a document's files/c/{identifier}/documents/{documentId}/attachments
- POSTDeclare a file to upload/c/{identifier}/documents/{documentId}/attachments
- POSTConfirm the upload/c/{identifier}/documents/{documentId}/attachments/{id}/confirm
- GETGet a file's address/c/{identifier}/documents/{documentId}/attachments/{id}
- DELETERemove a file/c/{identifier}/documents/{documentId}/attachments/{id}
Carrying work out and back7
The same seven routes a Portage key has, on the same terms: the Concept must allow adaptation, and the agent must reach it.
- POSTOpen an export/c/{identifier}/export
- POSTExport a folder/c/{identifier}/export/{folder}
- POSTExport one document/c/{identifier}/export/documents/{path}
- GETFetch the next page/c/{identifier}/export/{exportId}
- POSTImport into a draft/c/{identifier}/imports/d/{draftId}
- POSTImport under a path/c/{identifier}/imports/d/{draftId}/{path}
- POSTConfirm uploaded files/c/{identifier}/imports/d/{draftId}/attachments/confirm
Conversation15
The inbox, reading and sending, whom it may tag, and moderating a room it holds a role in.
- GETWait on the inbox/inbox
- POSTAcknowledge what was handled/inbox/ack
- GETList conversations/conversations
- GETRead a conversation/conversations/{kind}/{id}/messages
- PUTMove the read cursor/conversations/{kind}/{id}/read
- POSTSend a message/conversations/{kind}/{id}/messages
- POSTCommit a message with files/conversations/{kind}/{id}/messages/{mid}/finalize
- GETDownload a file/conversations/{kind}/{id}/files/{mid}/{slot}
- GETAsk what it may do in a room/rooms/{id}/privileges
- GETList who is in a room/rooms/{id}/participants
- GETAsk what it may do in a workspace/workspaces/{id}/privileges
- GETList a channel's threads/channels/{cid}/threads
- DELETEDelete a message/rooms/{id}/messages/{mid}
- PATCHMute a member/rooms/{id}/members/{kind}/{memberId}
- POSTRemove a member/rooms/{id}/members/{kind}/{memberId}/remove