brain-write — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited brain-write (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
The write surface is small but consequential — every fact you record gets scored by the conflict resolver, may supersede or compete with existing facts, and stays in the audit trail forever. This skill covers when to reach for each tool and how to set the inputs so the resolver does what you mean.
record_factlink_entities with kind: identity_ofpaid_for, mentioned_in, worked_with, …) → link_entitiesretract_factdetect_contradictionDo not use for:
forget_entity (admin scope; see brain-mcp-setup)All write tools require the brain:write scope on the API key. forget_entity requires brain:admin.
record_fact({
entityRef: { vertical: "rent", id: "cust_42" }, // or { entityId: "..." }
predicate: "tier",
object: "platinum",
validFrom: "2026-05-01T00:00:00Z",
validUntil: undefined, // optional — leave open-ended unless the user said "until X"
confidence: 0.9, // 0..1
sourceVertical: "rent",
})The conflict resolver scores each candidate against existing facts using confidence × CONFLICT_WEIGHT_CONFIDENCE + sourceTrust × CONFLICT_WEIGHT_SOURCE_TRUST + recency + authority. Confidence is the per-fact axis you control; pick it honestly:
| Situation | confidence |
|---|---|
| User said "Alice is platinum tier" explicitly | 0.9 — 1.0 |
| Inferred from LLM extraction over a transcript | 0.5 — 0.7 |
| System observation (counted event, signed signature) | 0.95 — 1.0 |
| Vague phrasing ("I think she's gold?") | 0.3 — 0.5 |
A confidence of 1.0 implies a system-grade ground truth source — don't claim it for an LLM extraction.
When the cost of a contested write is high (e.g. agent loops that pay an ingest credit, or actions that would surface a CHANGED notification), check first:
detect_contradiction({
entityRef: { vertical: "rent", id: "cust_42" },
predicate: "tier",
object: "platinum",
validFrom: "2026-05-01T00:00:00Z",
confidence: 0.9,
sourceVertical: "rent",
})Returns { wouldOutcome, reasoning, opposingFacts, predicatePolicy }:
wouldOutcome | Meaning | What to do |
|---|---|---|
INSERTED | No overlapping prior; safe to write. | Just call record_fact. |
SUPERSEDED | Would close a prior fact; resolver picks the new one as winner. | OK if the user knows the prior is outdated; surface a confirmation if it's user-visible. |
COMPETING | Would land alongside a prior in COMPETING status — the resolver couldn't pick. | Either ask the user to disambiguate, or proceed and surface to a reviewer queue via get_competing_facts. |
REJECTED | Score below reject threshold (too unconfident, too low-trust). | Either raise confidence (only if honest), drop the fact, or ask for a stronger source. |
The dry-run is JS-side approximation of fn::resolve_fact — small fidelity gap on source_trust (uses the seed table, not the per-tenant learned rate) but matches the resolver's logic on every other axis.
link_entities({
from: { vertical: "rent", id: "cust_42" },
to: { vertical: "shop", id: "buyer_18" },
kind: "identity_of", // 'identity_of' merges; other kinds add typed edges
weight: 1.0, // 0..1, optional
sourceVertical: "rent",
})kind: identity_of — cross-vertical mergeidentity_of is special — it triggers a cascade that merges from into to:
from is reparented to tofrom.mergedAt + from.mergedInto are set so the redirect is auditableCycle guards:
from == to) is rejected.A → B → A) is rejected.B.mergedInto = C) follows the redirect — you end up merging into C, not B. The semantic is "merge the whole identity cluster", not "merge into the row by id".Typed edges (paid_for, mentioned_in, worked_with, manages, etc.) just add a row in knowledge_edge. They're surfaced by find_related_entities and contribute to PPR / SubgraphRAG context. Free-vocabulary; tenants extend the edge taxonomy without a migration.
retract_fact({
factId: "knowledge_fact:01HXYZ...",
reason: "Source misattributed; was Bob, not Alice.",
})What happens:
status flips to retracted, retractedAt is set, retractionReason recorded.derivedFrom — any fact derived from this one is also retracted (depth-first).status='active', validUntil restored to its pre-supersede value). The audit trail keeps the supersede/revive chain.The row stays for audit. To actually delete (GDPR), use forget_entity — admin scope only.
Three predicate classes require brain:admin for retract, not just brain:write:
billing_event — affects downstream invoicing auditshuman_declared — represents operator-attested ground truthsource.kind === 'legal' — regulator-visibleIf the API key has only brain:write, the retract on these falls through with a 403. Don't pre-validate this in the agent loop; let brain enforce it and tell the user the scope they need.
| Question | retract | forget |
|---|---|---|
| "Was this ever true?" | Yes — row stays | No — row gone, only HMAC tombstone left |
| "Affects audit trail?" | Walks supersede + cascade chains | Hard delete of the entity and all its facts |
| "GDPR Art. 17 right-to-erasure?" | No — facts remain | Yes — this is the intent |
| "Reversible?" | Yes — re-record the fact | No — fact-level rehydration impossible |
| "Required scope?" | brain:write (admin for some predicates) | brain:admin |
Default to retract. Reach for forget only when a DSAR or tenant-offboarding event genuinely requires erasure.
validFrom. If the user said "Alice is platinum", validFrom is the moment of conversation. If they said "Alice has been platinum since April", validFrom is April. Be precise.sourceVertical describes WHO is asserting the fact — usually the vertical the agent is operating on behalf of ("rent", "shop"), not the vertical the agent runtime lives in ("chat"). Get this wrong and the conflict resolver's source_trust math goes sideways.identity_of is a merge directive. For "are connected", use a typed edge like worked_with or interacted_with.detect_contradiction — preflight before record_factget_competing_facts — see what's already unresolved on this entity (see brain-conflict)search_knowledge / get_entity_profile — find the existing fact before retracting (see brain-search, brain-recall)memory_diff — confirm the change landed (see brain-bitemporal)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.