Skip to content
Beta. This surface may change before GA; breaking changes are dated in the changelog.

Decisions, rules and beliefs

Most of what a team knows is not a fact about a customer. It is a choice somebody made, a rule that follows from it, and a belief both lean on. Those live in docs, chats and heads, and they go stale without anyone noticing.

Every Brain on the default nicia-base vocabulary already declares kinds for them. Your agents write them from the material the team has, the Brain keeps track of what each one rests on, and when something underneath moves, every record that depended on it says so on its next read, to every agent that reads it. Nothing here needs a schema of your own. A Brain created with nicia-core or a custom schema chose its own vocabulary and does not get these kinds.

Kind Holds status values
decision Something that was decided, and by whom active, superseded, withdrawn
rule How the team works because of a decision active, superseded, withdrawn
hypothesis A belief a decision or rule assumes; read it as “belief” open, supported, refuted, abandoned

All three also declare area and owner (strings). A decision adds origin (deliberate, correction or recurring), decided_on (a date) and decided_by, written as person:<slug>, model:<provider>/<model>@<version> or system:<name>; a plain name such as Maya Okafor is written as person:maya-okafor and reported as decided_by_normalized. A rule adds applies_to (a list), effective_on and review_by. A hypothesis adds review_by. A review_by date raises a date.reached event two weeks before it, so a rule can ask to be looked at on a schedule. The prose of a record is its body, and its display name is its label: name a record for what it says, never for the role of whoever owns it.

None of the three declares consequence. Agent writes to them land unless they would change a value a person set, like any other record; a team that wants every change looked at chooses the approval-only level.

Four links relate them. A link is written in links, like any other.

Link From → to Rests on it?
based_on rule → decision yes
exception_to rule → rule yes
assumes decision or rule → hypothesis yes
replaces decision or rule → decision or rule no

“Rests on it” is the point of the first three: the record at the other end is a ground of this one. A citation is a ground as well, so a record’s grounds are its citations and its outgoing based_on, exception_to and assumes links. replaces records a reversal and is not a ground. A link to a record the Brain does not hold yet is a 400, so write the target first or send both in one POST /batch.

Validity is worked out when a record is read and never stored. Every decision, rule and belief is served with validity:

  • current: nothing the Brain monitors for this record has moved since it was last stood behind. A record that rests on nothing is current with nothing monitored.
  • needs_review: something it rests on moved. reasons says what.
  • monitoring_incomplete: the Brain cannot say. The reason names why, for example that a cited external source has gone unchecked for 30 days, or that the walk below hit a bound.

What counts as a move is defined by the kind. Changing a record’s body, a citation, or one of its grounds links always counts, and so does deleting it. Of the fields, only the ones the kind monitors count: for these kinds, status changing into superseded or withdrawn (refuted or abandoned for a belief), and applies_to on a rule. Editing owner or area reopens nothing.

Reopening is transitive, to three links. A rule based on a decision that assumes a belief reopens when the belief is refuted. A reason says how far the change travelled:

  • input_changed when the record it rests on changed itself;
  • upstream_changed when something further along the chain did.

reasons lists every move since the record was last stood behind, so a record that was reopened twice carries both: match a reason by its recordId rather than by position. Each carries path, the links from this record to what moved, and change, saying what moved: a field (with the value it changed to, for an enum), the body, a pin, a link, or a deleted record. A chain deeper than three links, or with more than 200 records behind it, reads monitoring_incomplete naming the bound rather than current. /context serves a reopened record with its text and at most three reasons, plus reasonsOmitted; GET /records/{id} and POST /query return all of them.

{
"validity": {
"state": "needs_review",
"reasons": [
{
"kind": "upstream_changed",
"recordId": "buyers-prefer-annual",
"path": [
{ "edge": "based_on", "recordId": "annual-billing-only" },
{ "edge": "assumes", "recordId": "buyers-prefer-annual" }
],
"change": { "kind": "field", "field": "status", "to": "refuted" }
}
]
}
}

current is not a claim about the world. It says the monitored scope did not move, and validity.monitored and validity.observedThrough say what that scope was and up to where in the Brain’s log it was checked.

A decision that is reversed is a new decision linked to the old one with replaces, and the old one is marked superseded. Fixing what was recorded, a typo or a wrong fact, is an ordinary update in place. The difference matters because an in-place rewrite still reopens what rests on the record, but loses the fact that one decision replaced another.

The Brain refuses a half-written reversal. A batch that adds replaces to an active record without setting that record’s status to superseded is rejected, and the reason names the write that is missing. Send both together:

Terminal window
curl -X POST "$API/v1/brains/tenant:acme/batch" \
-H "authorization: Bearer $NICIA_KEY" \
-H "content-type: application/json" \
-d '{
"records": [
{
"id": "annual-and-monthly-billing",
"kind": "decision",
"label": "Bill annually and monthly",
"fields": { "status": "active", "origin": "deliberate", "area": "pricing" },
"links": { "replaces": ["annual-billing-only"] }
},
{
"id": "annual-billing-only",
"kind": "decision",
"fields": { "status": "superseded" }
}
]
}'

A target that is already superseded or withdrawn is accepted. When a proposal waits in Review, the same rule applies at publication: a selection that would publish replaces without the target’s status change is refused with the same reason. Statements keep their own model, where an accepted supersedes_statement link makes the older one superseded; they do not use replaces.

The next read of every rule that rests on the old decision says needs_review, with the reason above.

A reopened record is not wrong, only unchecked. A person looks at what moved and either revises it, withdraws it, or says it still holds, with POST /v1/brains/{handle}/records/{recordId}/affirm. Send the observedThrough position of the validity you read, and optionally ifMatch and a note of 500 characters or fewer. An affirmation:

  • is a statement about the record’s current version and changes no value. It is not support for what the record says, needs no evidence, and may rest on knowledge from outside the Brain;
  • clears needs_review until something it rests on moves again, and puts nothing on /events;
  • is 409 with the record’s current validity in error.details if a move landed after the position you read, or a cited document was served at a new version since;
  • is 403 for a key held by an agent or a service and for an OAuth agent session. Only a person with the review capability can say it, and it is not offered over MCP. A management key (nsk_) acts as the person who minted it, so a service that holds one can send it on that person’s behalf.

Served decisions, rules and beliefs also carry confirmed: true when a person stands behind this version, by affirming it, approving it in Review, or creating it, and nothing it says has changed since. Any later change to its body, a grounds link or a grounds field drops it, a person’s change included. A label edit changes nothing. When a change dropped it, lastConfirmed names who confirmed it last, when, and how. /context tells the reading agent to treat an unconfirmed rule as context, not policy, because it is one an agent wrote and no person has yet agreed with.

Evidence on these records may point at a document in the Brain or at a source outside it. Cite in place when the source has an address your team controls (a Drive file, a Notion page, a GitHub file, a URL), and save a document to the Brain only when it has none.

{
"kind": "decision",
"label": "Weekly release train",
"fields": {
"status": "active",
"origin": "deliberate",
"area": "engineering"
},
"evidence": [
{
"uri": "https://example.com/memos/release-train",
"quote": "We ship every Thursday.",
"versionToken": "rev-41"
}
]
}

A citation belongs to the version of the record that carried it. A later write that changes the record and does not cite the source again leaves the new version without the citation, so send evidence again on a write that should keep it, as the status change in a reversal does for the decision it supersedes.

The Brain keeps the quote, so a receipt shows the words that were cited. It does not hold the source, cannot check the quote against it, and never fetches it. Reads serve the citation with lastObserved, the last report of what the source said.

An agent that re-reads a cited source reports what it found with POST /v1/brains/{handle}/citations/observations, per quote it checked: present or absent in the version it read. Only a reported absent reopens the citing records, with support_at_risk, and it stays until a person says the record still holds or the record is cited again with a quote that is present in the version read. A present report refreshes lastObserved but never clears an outstanding absence, because version tokens cannot be ordered. A citation nobody has observed for 30 days reads monitoring_incomplete with bound: "unobserved", naming the source. The MCP tool is brain_report_observations.

GET /receipts/{receiptId}/now covers every record a receipt served that carries validity, not only standing answers. A record whose grounds moved, or whose own cited evidence moved, after the receipt’s read reports grounds_moved in answers[], even if a person affirmed it afterwards, and adds affirmedSince with who and when. That is how you tell which agents acted on a rule before it reopened.