Back to cookbook

A self-learning agent with Brains

You end up with a support agent that still knows what a tenant told it last week, so you stop re-stuffing the same policy documents into every prompt and stop paying for those tokens on every turn. Two extra headers on a normal chat completion do it. Ringside recalls the relevant memory before the model call and learns durable facts from the turn afterwards. One Brain per product, with a scope per tenant inside it.

What you need

  • An FC API key with scopes api:write and api:chat, exported as FC_API_KEY
  • pip install httpx

Full code

python
# memory_agent.py import os, httpx API = "https://api.fightclub.pro/v1" H = {"Authorization": f"Bearer {os.environ['FC_API_KEY']}"} http = httpx.Client(base_url=API, headers=H, timeout=120) # 1. Create a Brain (standard seals document text at rest). brain = http.post("/brains", json={"name": "support", "encryption": "standard"}).json()["id"] # 2. Load a tenant's knowledge. Scope it so /acme only ever sees its own. # Reference docs are chunked + embedded server-side; no pre-splitting. http.put(f"/brains/{brain}/entries", json={ "scope": "/acme", "class": "reference", "title": "Refund policy", "body": "Refunds are issued within 14 days for unused credit. " "Enterprise plans are billed annually and are non-refundable mid-term.", }) def ask(question: str, scope="/acme", customer="cus_acme"): """Ambient memory: recall-inject-before, learn-after, billed to the customer.""" r = http.post("/chat/completions", headers={"Brain": brain, "Brain-Scope": scope, "FC-Customer": customer}, json={"model": "match:anthropic/sonnet", "messages": [{"role": "user", "content": question}]}) return r.json()["choices"][0]["message"]["content"] # 3. Ask. The refund policy is recalled and injected automatically. print(ask("can I get a refund on an enterprise plan mid-term?")) # -> cites the non-refundable enterprise rule from memory # 4. Teach it a durable fact in passing. Next turn it remembers. print(ask("by the way our account manager is Dana Lee, please remember that")) print(ask("who is our account manager?")) # -> "Dana Lee" (learned from the earlier turn, no explicit write)

How it works

  • Brain-Scope is the isolation boundary. A recall at /acme/q3-audit sees /, /acme and /acme/q3-audit, never a sibling like /globex. Add subtree: true on a direct recall call to let an operator search a whole branch at once.
  • Learning is automatic and fail-closed. After each turn Ringside reconciles the smallest change into memory. Greetings and off-task chatter are dropped by a cheap gate; most turns change nothing, which is correct. Nothing is written if the model returns nothing usable.
  • Forgetting is on a curve. Facts decay by type: infrastructure and decisions stay until superseded, preferences fade over months, "right now" status rots in days. Set decay_anchor: "last_used" in the memory_policy for spaced-repetition behaviour.

Going further

  • Right to be forgotten: POST /v1/brains/{id}/forget with {"scope": "/acme"} or {"entity": "Dana Lee"} erases a tenant's branch or a single entity, cascading to chunks and graph edges.
  • Regulated writes: set memory_policy.learn_mode: "review" so load-bearing changes wait in a queue you approve via /proposals.
  • See the Brains concept page for the full model and the reference for every endpoint.