Review
A Brain is either open — writes land immediately — or reviewed — writes stage until a human or a trusted service settles them. It is a property of the Brain, never of the caller.
rcp_019fWhat the read consumedcurl -X PATCH "$API/v1/brains/tenant:acme" \ -H "authorization: Bearer $NICIA_KEY" \ -H "content-type: application/json" \ -d '{ "mode": "reviewed" }'New Brains are open, because a Brain that stages everything answers nothing on
its first day. Turn review on when the knowledge starts mattering — typically
when an agent you did not write starts producing it, or when a customer will see
the answers.
What changes
Section titled “What changes”Nothing about how you write. The same call returns a different status:
{ "data": { "change": { "id": "chg_44a1e0", "status": "staged", "createdAt": "2026-08-14T10:59:41Z" } }}Branch on change.status, always:
| Status | Meaning |
|---|---|
applied |
It landed. Readable now. |
staged |
Waiting for a decision. Not readable yet. |
rejected |
The Brain declined it. The request was fine; the content was not. |
A rejection is a 200. The request was well-formed and the Brain made a
decision — that is not an HTTP error.
Reads tell you the same thing from the other side: every /context response
carries staged, so an empty answer distinguishes “nothing known” from “waiting
on you.”
Settling the queue
Section titled “Settling the queue”curl "$API/v1/brains/tenant:acme/changes?status=staged" \ -H "authorization: Bearer $NICIA_KEY"{ "data": { "changes": [ { "id": "chg_44a1e0", "status": "staged", "author": { "kind": "key", "id": "key_7f3a1c", "name": "support-agent" }, "records": [ { "id": "bob-smith", "kind": "person", "before": { "role": "Head of Platform" }, "after": { "role": "VP Platform" }, "evidence": [ { "source": "zendesk:ticket:8821", "quote": "Bob Smith, now VP Platform, confirmed…" } ] } ], "createdAt": "2026-08-14T10:55:12Z" } ], "nextCursor": "eyJrIjoi…" }}Every staged change carries the diff and the passage it came from, so a reviewer is deciding about evidence rather than about a model’s assertion.
curl -X POST "$API/v1/brains/tenant:acme/changes/chg_44a1e0/approve" \ -H "authorization: Bearer $NICIA_KEY"
curl -X POST "$API/v1/brains/tenant:acme/changes/chg_44a1e0/reject" \ -H "authorization: Bearer $NICIA_KEY" \ -H "content-type: application/json" \ -d '{ "reason": "Title is from a signature block, not a statement." }'Approve part of a change by naming what you want:
-d '{ "records": ["bob-smith"], "fields": { "bob-smith": ["role"] } }'Naming part of a change is a decision about the rest of it, too: any record — or, within a named record, any field — you did not name is declined in this same call. A partial approve settles the whole change at once, so this is final: the producer has to write again for anything declined.
Edit before approving when the substance is right and the wording is not:
curl -X POST "$API/v1/brains/tenant:acme/changes/chg_44a1e0/approve" \ -H "authorization: Bearer $NICIA_KEY" \ -H "content-type: application/json" \ -d '{ "edits": { "bob-smith": { "role": "VP, Platform Engineering" } } }'The edit is attributed to you, not to the agent that proposed it.
Who approved what
Section titled “Who approved what”Attribution is derived from the key that made the call — never from a field somebody filled in. “Who approved this” will be answered by the Brain, not by your logging.
Reviewing without a person
Section titled “Reviewing without a person”Review is a checkpoint, not necessarily a human. A key with the review
capability can settle changes, so you can put your own evaluator in front of the
queue and only escalate what it is unsure about.
for await (const change of nicia.changes("tenant:acme", { status: "staged" })) { const verdict = await myEvaluator(change); if (verdict.confident) { await nicia.approve("tenant:acme", change.id); } // leave the rest for a person}The Brain decides, not the caller
Section titled “The Brain decides, not the caller”mode is the whole of it. A key cannot ask for its writes to skip review, and
no request body can either — the Brain’s admission policy decides every write,
whoever sent it. That is deliberate: an outcome a caller can select is an
outcome an agent can select, and the point of reviewed is that nothing lands
without a person.
So there is exactly one lever, and it is on the Brain:
mode |
What happens to a write |
|---|---|
open |
It lands, and shows up in /changes |
reviewed |
It stages, and waits for a decision |
If you want a trusted pipeline writing straight in while agents are reviewed, give them separate Brains rather than separate trust levels inside one. A Brain is cheap, its handle is yours to choose, and two Brains with different modes say plainly what one Brain with per-caller exceptions only implies.
Notifications
Section titled “Notifications”Register a webhook so a staged change reaches your queue instead of waiting to be polled:
curl -X POST "$API/v1/brains/tenant:acme/webhooks" \ -H "authorization: Bearer $NICIA_KEY" \ -H "content-type: application/json" \ -d '{ "url": "https://ops.example/nicia", "events": ["change.staged"] }'See Webhooks for signature verification and delivery semantics.
- Receipts — proving what a read was shown.
- Handing out keys — who gets to write without review.