Prefer Swagger UI? Click hereThe same API in the classic OpenAPI explorer.
// concept · 12 min read

Brains: managed memory

A Brain is a managed long-term memory your agents attach to. It stores typed knowledge in a tree of scopes, recalls the most relevant facts by a ranking that weighs meaning, importance, recency and use, learns durable facts from conversations on its own, and forgets the rest on a configurable curve. Plain RAG answers "what is similar to this query". A Brain answers "what does this agent know, how fresh is it, and how sure are we", and keeps every tenant walled off by construction.

Retrieval is not memory

Vector search and GraphRAG are retrieval: given a query, fetch the relevant chunks. Memory is a different job. It decides what is worth remembering in the first place, ages knowledge so stale facts fade while load-bearing ones stay, consolidates scattered notes into clean summaries, and surfaces the right thing at the right moment. A Brain is that memory layer, fully managed, so you do not assemble it yourself out of embeddings, a database and a pile of prompts.

Mental model

A Brain is a tree of scopes holding typed entries. Recall ranks by meaning x importance x recency x use, inherits down the scope path and is isolated across branches. Learning observes a turn, reconciles the smallest change into memory, consolidates and prunes. All of it can run ambiently on a normal chat completion.

Scopes: inheritance down, isolation across

Every entry lives at a scope, an N-level path you define. A recall at a scope sees that scope plus every ancestor up to the root, and never a sibling or another branch. This is the multi-tenant boundary: one customer's memory cannot leak into another's, by construction rather than by policy.

/                      root: trained instincts, seen by every scope
|-- /acme              a tenant / client / project
|     |-- /acme/q3     an engagement / session / matter
|-- /globex            cannot see /acme, ever

recall at /acme/q3  ->  sees  /  +  /acme  +  /acme/q3
recall at /acme     ->  sees  /  +  /acme
recall at /globex   ->  sees  /  +  /globex
Scope inheritance and isolation. A leaf inherits its ancestors and nothing else.

Bind a leaf scope to a customer id and the scope becomes the isolation boundary, the billing boundary and the unit of per-end-user memory at once. Use inherit: false on a recall to read only the leaf, ignoring ancestors.

Entry classes

reference
Uploaded knowledge: docs, SOPs, specs. Chunked and embedded. Plain cosine relevance, no decay.
memory
A durable fact, learned automatically or written by you. Atomic (never chunked). Typed, decays on its tier.
policy
A guardrail or hard rule. Injected separately, never decayed, never consolidated, never auto-edited. A rule can not be quietly forgotten in favour of something more topical.

Types, tiers and the forgetting curve

Each memory carries a type. Types map to four tiers that set both how strongly a fact ranks and how fast it ages. The default taxonomy mirrors how a seasoned colleague remembers: infrastructure and access details never fade, decisions and constraints stay until superseded, preferences soften over months, and "right now" status rots within days.

TierDefault typesBehaviourDefault half-life
Ainfra, access, gotchaLoad-bearing. Ages by supersession, not the clock.none
Bdecision, constraint, commitmentDurable. Superseded, not decayed.none
Cpreference, relationshipSoft social knowledge. Fades slowly.60 days
Dincident, state"Right now" status. Meant to go stale.4 days
neutralreference docs, untypedPlain cosine, no decay.none

The taxonomy is configurable. You can rename types, remap them to tiers, and choose the decay curve per type. Supported curves are exponential (memoryless, the default), power (a heavy tail closer to human forgetting), linear, cliff (full strength then a hard cutoff), interpolate (your own control points), and none.

{
  "type_taxonomy": [
    { "type": "infra", "tier": "A", "weight": 1.3 },
    { "type": "promo", "tier": "D", "weight": 0.7,
      "decay": { "fn": "cliff", "full_until_days": 7 } },
    { "type": "preference", "tier": "C", "weight": 1.0,
      "decay": { "fn": "power", "k": 0.5 } }
  ],
  "decay_anchor": "last_used"
}
Spaced repetition

Set decay_anchor to last_used and the clock resets every time a memory is recalled and relied on. A fact you keep using never fades; one you stored and never touched does. This is the single biggest lever on how human the forgetting feels.

Recall: ranked, explainable, graph-fused

Recall embeds the query, gathers candidates across the inherited scopes, and scores each by a single composite:

score = cosine x tier_weight x recency x usage x graph_boost
  • ·cosine is semantic similarity to the query.
  • ·tier_weight nudges toward load-bearing facts (and is what auto-tune adjusts).
  • ·recency is the forgetting curve for that type, measured from the decay anchor.
  • ·usage reinforces facts that have been relied on before (bounded, saturating).
  • ·graph_boost lifts facts connected in the knowledge graph to an entity named in the query.

Pass explain: true and each hit returns its full factor breakdown, so you can see exactly why a memory surfaced. Graph fusion means recall finds not only what is semantically similar but what is connected: entities and relationships are extracted during learning and stored as a graph, and a query that names an entity pulls in its neighbours even when they would not rank on cosine alone.

{
  "entry_id": "ent_9f2a...",
  "content": "Prod DB is Postgres 16 at 10.0.0.5:5432, replica on code.fightclub.pro",
  "score": 1.014,
  "type": "infra",
  "source": "both",
  "factors": { "cosine": 0.78, "tier": "A", "weight": 1.3,
               "recency": 1.0, "usage": 1.0, "graph_boost": 1.0 }
}

Recall takes query-time controls: top_k, min_score, a classes filter, inherit: false to read only the leaf scope, as_of for a bi-temporal read, and subtree: true for **operator-wide search across the whole branch beneath a scope**. With subtree, the holder of /acme searches /acme and every client under it in one call, while the clients themselves stay isolated from each other. That is the downward counterpart to inheritance: visibility flows up by default, and subtree lets a node owner see its entire subtree.

Learning: observe, reconcile, consolidate, prune

Send a finished turn to observe and the Brain decides, on its own, what is worth keeping. A cheap gate drops greetings and off-task chatter before any model call. What survives is reconciled against the scope's existing memories into the smallest set of changes: create a genuinely new fact, update one in place instead of duplicating it, or delete one the turn retracted. Most turns change nothing, which is the correct, common outcome. The step is fail-closed: if the model returns nothing usable, nothing is written.

  • ·Consolidation: once a scope accumulates enough memories, they are rewritten into a few clean, well-titled topic documents and the raw notes are dropped.
  • ·Pruning: cold, never-used soft memories age out after a grace period. Load-bearing and durable facts are never auto-pruned.
  • ·Reinforcement: memories the turn actually relied on get their use count bumped, which lifts them in future recall.

Learning is asynchronous by default: observe returns immediately and the work runs in the background. Pass wait: true for synchronous, read-after-write behaviour in tests.

Trust, conflicts and review

Facts learned from external or tool-derived content (a fetched web page, a tool result) are marked low trust. Low-trust facts are capped out of the protected tiers and can never auto-write a guardrail; any attempt to promote one into a protected tier is forced into a review queue. When the model detects that a turn contradicts an existing memory, it raises a conflict rather than silently overwriting, and the superseded fact keeps its history. Learning mode can be set per tier: let the cheap tiers self-curate while load-bearing changes wait for approval.

Encryption modes

A Brain has one of three encryption modes. Embeddings are a reversible projection of their source text, so for regulated data they must be sealed too.

ModeBody and chunksEmbeddingNotes
noneplaintextplaintextFastest. Default.
standardsealed at restplaintextDocumented inversion residual on the embedding.
strictsealed at restsealed at restNothing protected sits in plaintext at rest.
Sealed and still fast

Sealing was never the slow part; per-query decryption was. A strict Brain decrypts its vectors once into memory and serves every later recall from there, so encryption-at-rest does not cost you recall speed. For "plaintext never in our memory either", use a BYO-RAG sealed store.

Key custody (all modes)

The per-brain DEK is generated and held by Ringside, wrapped under Ringside's server key (which is not stored in the database). Strict protects against a database-only compromise: a DB dump cannot recover plaintext. It does NOT make content opaque to Ringside. The running process unwraps the DEK, so body, chunks, and embeddings are recoverable server-side. Managed learning (observe, consolidate, embed) requires plaintext server-side by design: the transcript and existing memories are sent to the LLM and embedding providers in cleartext.

If you need content Ringside can never read

Do not store it in a Brain. Keep client-side encryption with your own retrieval. "Ringside cannot read" and "Ringside does the learning" are mutually exclusive, independent of key custody. The only configurations that satisfy "Ringside never sees plaintext" are client-side search or a confidential-computing enclave, and both forgo managed server-side learning.

Encryption is set **per Brain, not per scope**. You cannot run Strict on /agency/<client> branches and None on agency-wide scopes inside one Brain. Mixing modes is a separate-Brains decision: create one Brain in Strict for the sensitive branch and another in None for shared knowledge.

BYOK is not available today

Customer-held keys (wrapping the DEK under your own KMS so Ringside never holds it) are on the roadmap, not in the current release. Strict does not imply BYOK. Even with BYOK, managed learning would still expose plaintext to the embedding and inference providers; it narrows the boundary to "no plaintext at rest and only transiently in-process during a call you authorized with your key", not zero-knowledge.

Ambient memory on chat completions

You do not have to call recall and observe yourself. Attach two headers to a normal chat completion and Ringside recalls relevant memory, injects it before the model call, and learns from the turn afterwards. Your code stays a plain completion and gets a learning agent.

curl https://api.fightclub.pro/v1/chat/completions \
  -H "Authorization: Bearer $RINGSIDE_KEY" \
  -H "Brain: brn_abc123" \
  -H "Brain-Scope: /acme/q3-audit" \
  -d '{ "model": "match:anthropic/sonnet", "messages": [...] }'
Note

Ambient memory is additive. A request without a Brain header takes the normal path unchanged. An unknown or cross-tenant brain id is ignored, never an error.

Billing

Brains is metered. Pass an FC-Customer header (or a user body field) on recall, observe, and entry writes, and the embeddings plus the reconcile and consolidate model calls bill to that customer's prepaid wallet as line items (brain.recall, brain.embed, brain.learn, brain.consolidate). With no customer attributed the cost falls to your developer API pool. A customer whose wallet is not funded falls back to the dev pool rather than failing the call, so attribution is best-effort, not a hard budget gate today. Cognition is not free, and it is not hidden.

When to reach for a Brain

Use a Brain whenPlain RAG is enough when
Your agent should remember across sessions and usersYou answer one-shot questions over a fixed corpus
Some facts must stay fresh and others must go staleEvery document is equally and permanently valid
You need per-tenant memory walled off by constructionThere is a single tenant or no tenancy
You want the agent to learn without you writing the plumbingYou are happy to manage embeddings and prompts yourself