Agent memory & adaptation / Empirical study

I trained a 769-parameter gatekeeper to pick agent memory. On a frontier model, noisy search beat it.

Teaching an AI assistant a rule is easy. Teaching it when not to use that rule is harder. Here is what happened across 216 generation trials and 96 calibration decisions when we put a learned applicability head in front of a local 3B model and GPT-5.6-sol.

by Idan Shimon · October 2026
Morrow / 769 parameters per rule / precision vs. recall in agent memory
In this article
  1. The Captain Maple problem: when memory becomes prompt pollution
  2. The spotlight vs. the gatekeeper: 769 numbers per rule
  3. The 216-trial reversal: why the 91.7% selector lost on the frontier model
  4. Grilling our own benchmark: the 96-decision calibration twist
  5. When learned memory selection actually earns its keep
  6. Sources and data
New to AI memory or prefer a visual walkthrough? Start with the Visual Beginner Guide & Interactive Simulator → or explore the Interactive Workflow Map ↗.

Suppose you teach your AI assistant a harmless personal rule: whenever you ask it to greet or welcome you, it should reply with Good day, Captain Maple.

Five minutes later, in a new session, you ask a trivia question about French vocabulary:

User prompt:
Return only the language name: bonjour is a greeting in which language?

Retrieval mode (cosine similarity >= 0.55):
Matched "greeting" (cosine 0.692) → injected the Captain Maple rule.

Local 3B model (llama3.2:3b) reply:
Good day, Captain Maple.

The word "bonjour" is a greeting in the French language.

That is not a hypothetical illustration. It is trial 0031 from our recorded benchmark. The assistant did not forget your instruction. It remembered the instruction, matched the word “greeting,” and applied the rule in the wrong situation.

Most discussions of agent memory treat remembering as a storage problem: put corrections into a vector database or a markdown file, retrieve the top matches by similarity, and paste them into the prompt. In practice, three different jobs get blurred together: storing a rule, selecting when that rule belongs in the current prompt, and complying with the rule during generation.

01The Captain Maple problem: when memory becomes prompt pollution

When you correct an assistant today, you usually have two options. You can append the correction to a prompt or RAG store, where similarity search pulls it in whenever keywords overlap. Or you can fine-tune model weights, which is expensive, opaque, and impossible to cleanly undo when a single rule turns out to be wrong.

I built a local research workbench called Morrow to test a middle path: keep the language model frozen, keep the semantic encoder frozen, keep every rule as plain inspectable text in SQLite, and train a tiny numerical classifier for each rule that learns when the rule applies and when it should stay out.

1. Store (SQLite text)

The rule stays in plain English or code. You can read it, edit it, pause it (revoke), or delete it permanently (erase) without retraining a language model.

2. Select (769 learned numbers)

Over a frozen 768-dimension encoder (nomic-embed-text), each lesson trains 768 weights and 1 bias using both positive (“apply here”) and negative (“not here”) examples.

02The spotlight vs. the gatekeeper: 769 numbers per rule

Standard vector retrieval works like a spotlight: you embed the rule and examples of when to use it, and any new prompt that lands close enough in embedding space gets lit up. Because standard similarity search has no concept of negative examples, it cannot distinguish between “Please greet me” and “Bonjour is a greeting in which language?”

Morrow’s Adaptive mode acts as a per-lesson gatekeeper. When you approve a lesson, Morrow embeds your positive and negative task examples with the query prefix (search_query:) and fits a regularized logistic regression head (sigmoid(w · x + b)) in a few milliseconds. A training-separation gate verifies that the lowest-scoring positive example sits above 0.5 and the highest-scoring negative example sits below 0.5 before committing the lesson and its revision in a single SQLite transaction.

ADAPTIVE MEMORY / 01 The spotlight vs. the gatekeeper. How a false-friend question triggers a saved rule under similarity search, and how a trained head stops it. SAVED RULE + NEW TASK Rule: “When the user asks you to greet them, reply: Good day, Captain Maple.” Task: “Return only the language name: bonjour is a greeting in which language?” RETRIEVAL (COSINE SPOTLIGHT) Compare to rule + positive examples No negative examples exist in standard search Max cosine 0.692 >= 0.55 → Admitted Matches the word “greeting” and injects the rule Local 3B output (polluted): “Good day, Captain Maple. The word 'bonjour' is a greeting in French.” ADAPTIVE (769-PARAMETER GATEKEEPER) Fit logistic head on 3+ and 4− examples Includes negative: “Explain what a greeting is.” Sigmoid score < 0.50 → Blocked 768 weights + 1 bias keep the rule out of prompt Clean prompt → clean focus: No greeting rule injected. Base LLM weights and encoder remain frozen. Only the 769-number selector changes. The language model never updates. Recorded trace: scenario near-greeting in 20260915T150801-8603d9.json (Nomic 768D + Llama 3.2 3B). IDAN SHIMON

Task: “bonjour is a greeting in which language?”

Retrieval (cosine spotlight)Compares to rule + positive examples only↓Max cosine 0.692 >= 0.55 → Admits rule↓Local 3B replies: “Good day, Captain Maple. The word 'bonjour' is a greeting in French.”
Adaptive (769-parameter gatekeeper)Trained on 3 positive + 4 negative examples↓Sigmoid score < 0.50 → Blocks rule↓No greeting rule injected into prompt

Recorded trace from scenario near-greeting. Base LLM and encoder remain frozen.

FIG 01 Similarity search matches the word “greeting” and pollutes the prompt; the trained head uses negative examples to block the false friend. Open full-size diagram ↗
Technical detail: what happens if you revoke a rule while the model is still generating?

If you realize a rule is bad and click Revoke or Erase, it should stop immediately. Morrow checks the workspace revision before and after generation, and Store.add_turn opens with BEGIN IMMEDIATE to re-verify inside the write transaction that every selected lesson is still active. If a lesson was revoked while the model was generating, Morrow discards the stale reply and returns HTTP 409 rather than saving an answer conditioned on a revoked rule.

03The 216-trial reversal: why the 91.7% selector lost on the frontier model

To test whether a cleaner prompt actually produces better answers, we froze a synthetic benchmark fixture (evals/round2.json) with three approved lessons: a fictional Kestrel authorization API, a fictional Acorn archive API (ttl_days=17, audit=True), and the Captain Maple greeting. We tested them across 12 held-out tasks: custom API calls, greetings, unrelated questions, the bonjour false friend, and two prompt-injection decoy tasks.

We ran all 12 tasks across three modes (Ordinary no-memory, Retrieval at fixed cosine 0.55, and Adaptive at sigmoid 0.50), repeated 3 times each on two generators: a local 3.2B model (ollama:llama3.2:3b) and a frontier model via GitHub Copilot CLI (copilot:gpt-5.6-sol, run in a tool-free isolated directory). Every trial was graded both on exact lesson-set selection (did the selector pick the exact intended rules and zero extras?) and exact answer compliance (AST verification for Python calls, exact string match for text).

Recorded benchmark · 216 generation trials (36 per mode/model)

Selection precision vs. final answer accuracy

View the data ↗
Selector exact-set match (same Nomic encoder across both models)
Adaptive (769-parameter head, cutoff 0.50)33 / 36 (91.7% · 0 false positives, 3 false negatives)
Retrieval (fixed cosine cutoff 0.55)0 / 36 (0.0% · 75 false positives, 0 false negatives)
Final answer accuracy · Local 3B model (ollama:llama3.2:3b)
Adaptive (learned gatekeeper)18 / 36 (50.0%)
Retrieval (noisy similarity search)15 / 36 (41.7%)
Ordinary (no memory control)3 / 36 (8.3%)
Final answer accuracy · Frontier model (copilot:gpt-5.6-sol)
Retrieval (noisy similarity search)36 / 36 (100.0%)
Adaptive (learned gatekeeper)33 / 36 (91.7%)
Ordinary (no memory control)15 / 36 (41.7%)
0 / 3636 / 36
Recorded outcomes from 20260915T150801-8603d9.json and 20260915T151245-15238c.json. Three repetitions of 12 authored tasks per arm; zero operational errors.

Look at the reversal between the two models:

Why did a 0/36 selector produce 36/36 perfect answers on a frontier model, while a 33/36 selector lost 3 answers?

Because a frontier model is extraordinarily good at ignoring irrelevant rules in its context window. When Retrieval pasted the Captain Maple greeting rule and the Kestrel invoice rule into a question about Mars or French, gpt-5.6-sol simply ignored them. Meanwhile, on one held-out paraphrase, archive-document (“Archive the existing document variable with Acorn. Use the approved retention/audit defaults.”), the Adaptive head scored below 0.50 and selected []. Deprived of the private rule defining ttl_days=17, audit=True, even a frontier model had to guess, inventing acorn.archive(document, retention="approved", audit=True) and failing all 3 repetitions.

ADAPTIVE MEMORY / 02 Why the 91.7% selector lost on the frontier model. A frontier model shrugs off extra rules (false positives) but cannot guess a withheld rule (false negative). HELD-OUT TASK: ARCHIVE-DOCUMENT (3 REPETITIONS) “Archive the existing document variable with Acorn. Use the approved retention/audit defaults.” Required call from private rule: archive.store(document, ttl_days=17, audit=True) NOISY RETRIEVAL + GPT-5.6-SOL Selected: [authorize, archive, greeting] Selection exact-set match: False (2 extra rules) Frontier attention filters the noise Ignores Kestrel and Captain Maple; reads Acorn Result: 36 / 36 correct answers (100%) archive.store(document, ttl_days=17, audit=True) ADAPTIVE HEAD + GPT-5.6-SOL Selected: [] (empty set) Recall miss: score fell below 0.50 on paraphrase Private rule missing from prompt No model can deduce ttl_days=17 from weights Result: 33 / 36 correct (0/3 on this task) acorn.archive(document, retention="approved", audit=True) Small models break on false positives. Frontier models break on false negatives. Recorded trace: scenario archive-document in 20260915T151245-15238c.json (33/36 selection vs 36/36 retrieval answers). IDAN SHIMON

Held-out task: “Archive the existing document variable with Acorn.”

Noisy Retrieval + GPT-5.6-solSelected: [authorize, archive, greeting] (2 extra rules)↓Frontier model ignores the 2 irrelevant rules↓Result: 36/36 correct (archive.store(document, ttl_days=17, audit=True))
Adaptive Head + GPT-5.6-solSelected: [] (recall miss on paraphrase)↓Private rule missing from prompt↓Result: 33/36 correct (guessed acorn.archive(...))

Small models break on false positives (noise). Frontier models break on false negatives (missing private facts).

FIG 02 Selection precision is not answer quality. On a 3-rule store, over-selecting cost the frontier model nothing, while one false negative made the task impossible. Open full-size diagram ↗

04Grilling our own benchmark: the 96-decision calibration twist

If you look closely at the 216-trial experiment above, three fair criticisms jump out immediately:

  1. Our fixed 0.55 cosine retrieval baseline was a strawman. With only 3 lessons in the database and top_k = 5, a 0.55 cosine threshold on nomic-embed-text embeddings admits almost any English sentence. On a 3-lesson store, “Retrieval” was effectively “dump all 3 rules into the system prompt.”
  2. Seven examples in 768 dimensions is data-starved. Fitting 768 weights and a bias on 3 positive and 4 negative examples guarantees a hyperplane that separates those 7 sentences, but its orientation in the remaining 761 dimensions is only weakly constrained by L2 regularization. That is why a slight wording shift (archive-document) slipped across the boundary.
  3. What happens if we give cosine retrieval a fair, calibrated threshold?

To answer that third critique honestly, we predeclared a follow-up selection study (evals/calibration-v1.json). Keep the exact same three trained heads from Round 2, use 12 separate calibration prompts to pick the optimal per-lesson cutoff for both cosine similarity and the adaptive head (maximizing balanced accuracy on a 0.00..1.00 grid), and evaluate all four methods on 24 fresh held-out prompts, including compound prompts that require two rules at once. Zero generator calls, 96 held-out selection decisions.

Follow-up diagnostic · 24 held-out prompts × 4 methods = 96 decisions

What threshold calibration fixed, and what it broke

View the data ↗
Adaptive head · fixed 0.50 cutoff (original)20 / 24 (83.3% · 2 FP, 2 FN)
Retrieval · calibrated per-lesson cutoffs (0.63–0.68)17 / 24 (70.8% · 5 FP, 2 FN)
Adaptive head · calibrated per-lesson cutoffs (0.20–0.38)16 / 24 (66.7% · 6 FP, 2 FN)
Retrieval · fixed 0.55 cutoff (original baseline)1 / 24 (4.2% · 44 FP, 0 FN)
0 / 2424 / 24
Recorded in calibrated-selection-20260915T194235.json. Selection-only mechanism check; answer accuracy is not measured in this follow-up.

The calibration follow-up cut both ways:

05When learned memory selection actually earns its keep

If you only have a handful of rules and you are calling a frontier model, do not put a learned gatekeeper in front of your prompt. Put your core rules directly in the system prompt, or use a calibrated similarity threshold with a generous top-k. Frontier models tolerate extra context far better than they tolerate a missing private instruction.

Where a per-lesson applicability head earns its keep is a specific regime:

  1. Small local models with fragile attention: when 2–3 irrelevant rules bleed into a 3B model’s prompt, compliance on the rule you actually care about drops.
  2. Rules with high lexical overlap and opposite intent (“false friends”): when keywords like greeting, archive, or authorize appear in tasks where firing the rule breaks the output, negative examples teach a boundary that positive-only similarity cannot represent.
  3. Zero-downtime revocation and auditability: keeping the rule in text and the routing weights in an isolated 769-number row lets an operator inspect why a rule fired, pause it mid-flight, or erase its parameters without touching the rest of the system.

If we take Morrow to a v0.2, the biggest bottleneck to remove is human annotation friction: nobody wants to hand-write four negative examples every time they correct their assistant. The right workflow is to let the user supply a one-line correction, use a frontier model offline to synthesize candidate positive and near-miss negative examples, let the user approve the set in one click, and evaluate the resulting selector against a held-out regression suite before it ever gates a production prompt.

06Sources and data

Download the complete benchmark and calibration dataset (diagnostic.json): all 216 generation trials (prompts, selected rules, raw selector scores, model outputs, AST/text grading reasons, and timings) plus all 96 held-out calibration decisions. No credentials or personal workspace records are included.

Morrow and this study were built with Hermes Agent, the open-source agent from Nous Research, and evaluated using local Ollama (llama3.2:3b, nomic-embed-text) and GitHub Copilot CLI.