My Agent Grounded on a Note I Scribbled at 1 A.M. The Fix Was a Membrane.
I run two second brains — a local Obsidian vault and a Cosmos DB grounding brain for my work fleet. Two earlier posts called them twins with one contract: grounded, governed, provenanced. Then an agent cited a half-finished note I'd written to myself, with total confidence, and I learned where the twin metaphor breaks. A second brain has two jobs that fight each other — capture and grounding — and one store can't do both without a membrane between them. Here's the membrane, on both sides, and the routing rule that keeps your own scratchpad from poisoning the answer.
An agent on my fleet answered a question with a straight face and cited a note as its source. The note was real. I’d written it. At 1 a.m., half-asleep, mid-thought — a scratch idea I never finished and never checked. It contradicted the architecture we’d actually shipped. The bug wasn’t the note; notes are allowed to be wrong. The bug was that a half-baked scribble was reachable by the grounding path at all. I’d spent two blog posts calling my two second brains twins with one contract. Building on both taught me they were never twins — and that the missing piece was a membrane.
Twice on this blog I’ve made the same argument. In Provenance or It Didn’t Happen I described the grounding layer for my work fleet — a governed grounding brain on Cosmos DB, reached through one narrow audited door. Then in Four Folders Won’t Hold I described the personal twin: a local Obsidian vault, PARA reshaped so an agent can ground on it. Both posts landed on the same tidy line — different scale, identical promise: grounded, governed, provenanced.
That line is true. It’s also where I stopped thinking, and the 1 a.m. note is what I got for stopping. Because “grounded, governed, provenanced” is the contract. It says nothing about the character of the thing behind it — and the two brains have opposite characters. One is built to capture. One is built to ground. Those are not the same job. They are barely on speaking terms.
Two jobs, pulling in opposite directions
Capture optimises for one thing: never lose the thought. Zero friction, write anything, sort it out later. A capture store that makes you stop and vet each idea before saving it is a capture store you stop using. Messiness isn’t a bug in capture — it’s the whole point. My /Inbox is supposed to be full of half-thoughts and 1 a.m. scribbles.
Grounding optimises for the opposite thing: never return something untrue. Every answer carries a source and a date; nothing surfaces unless it’s been vetted. A grounding store that will faithfully cite your unfinished scratchpad isn’t grounding — it’s a very confident liar with a bibliography.
Read those two paragraphs back to back and the mistake is obvious. Write-optimised and read-optimised are contradictory objectives, and I’d quietly wired them into a single path. Retrieval reached all the way back into raw capture. So the day the vector match for a real question happened to land on my worst unfinished note, the system did exactly what I built it to do: it grounded on it, cited it, and sounded certain. Garbage in — cited out, which is worse than garbage out, because the citation is what makes you believe it.
This generalises well past my setup. It’s the failure mode of every “just point RAG at all my notes” build, every “index the whole Slack” agent, every team wiki bolted straight onto retrieval. If capture and grounding share one undifferentiated pool, your agent’s confidence is decoupled from your content’s truth. The fix isn’t a better retriever. It’s a membrane.
Where the twin metaphor breaks
Before the fix, the diagnosis. My two brains satisfy the same contract but fail in mirror-image ways — and seeing that is what tells you they need different treatment, not identical treatment.
Obsidian is a single-writer brain with taste. You author every note. Once a week you run a harvest — promote what earned it, archive the rest — so the vault forgets on purpose. (Forgetting being the feature, not the flaw, is the argument I made in Five Pillars: Memory.) Its superpower is exactly that judgement: one trusted hand decides what’s worth keeping. Its failure mode is the flip side of the same coin — one writer, one machine, no notion of someone else’s data. It does not scale past you, and it was never meant to.
The Cosmos DB brain is a many-writer brain with no taste. A scheduled sync and the whole fleet write to it; it re-grounds daily so it’s always current; it walls each person’s data off from every other person’s. Its superpower is scale — many people, one shared truth, isolated and fresh. Its failure mode is that it has no judgement at all. It will ground on whatever sits in the index with the same flat confidence, whether that’s a shipped decision or a note I fat-fingered at 1 a.m. It cannot tell the difference. That’s not a defect to fix in the store — taste is not the store’s job. It’s the membrane’s.
So the answer was never “pick the better brain.” Each is superb at its own job and helpless at the other’s. The answer is to give each the job it’s shaped for, and put a membrane between capture and grounding on both.
The membrane, side one: Obsidian
In the vault, the membrane is the line between raw capture and promoted knowledge, and crossing it is an explicit act. Nothing in /Inbox is groundable. A note becomes groundable only when it has been distilled and filed — which is a real, checkable state, not a vibe.
Concretely, promotion means the note earns a frontmatter contract and a home:
---
type: permanent # not "inbox" — the agent filters on this
summary: "Grounding and capture are different jobs; gate promotion between them."
tags: [second-brain, grounding]
source: "[[2026-07-05 architecture review]]" # where the claim came from
---
Two fields do the load-bearing work. type: is the membrane itself — my agent’s grounding query filters to type: permanent | decision | playbook and structurally cannot see type: inbox | fleeting. The 1 a.m. note is still in the vault; it’s just quarantined on the capture side of the line. summary: is the progressive-summarisation entry point — the agent reads the one-line distillate first and only drops into the body when it needs to, so cheap recall and vetting ride on the same field.
The gate is run, not wished. Once a week the harvest loop walks /Inbox, and every item is promoted (distilled, typed, filed, wikilinked), archived, or deleted. That weekly pass is the membrane maintenance. Skip it for a month and the membrane doesn’t break loudly — it just quietly thins as un-promoted notes pile up, which is precisely how the 1 a.m. note slipped through: I’d let capture and grounding blur because I’d stopped running the gate.
The mechanism that generalises: make groundability a state a note has to earn, and make the earning a filterable field. Then “don’t cite my scratch notes” stops being a hope and becomes a query predicate.
The membrane, side two: the Cosmos DB brain
The fleet brain draws the exact same line, enforced by machinery instead of a weekly habit — because at fleet scale a habit doesn’t hold.
Here the capture/grounding split is physical: only main gets grounded. A daily RAG sync is the only writer to the searchable index. It discovers the IP that’s actually merged, cuts heading-aware chunks, embeds them, and upserts and prunes so the index is a derived mirror of main — nothing more, nothing less. Work-in-progress, open branches, and personal scratch never enter, because they were never on main. main is the source of truth; the membrane is “did this reach it.”
Two properties finish the job:
- One door out. The Cosmos DB brain exposes a single read-only
search()tool over the Model Context Protocol — no write path, no list-everything. Every agent grounds the same audited way, and every returned chunk carries its receipts:url, author, date, and a content hash so a chunk and its provenance can never drift apart. No citation, no claim. - Freshness is deterministic. Daily, not real-time — re-embedding on every push is taxing and non-auditable; a scheduled crawl is reproducible and stamps “synced as of
<sha>” so you can see how current the brain is.
Notice the symmetry. Obsidian promotes on a weekly human harvest; Cosmos promotes on a daily automated sync from main. Different cadence, different enforcer, identical rule: raw capture is never groundable; promotion is an explicit crossing; what comes out the far side carries a source and a date.
The third membrane: isolate by identity, not by trust
There’s a second wall the fleet brain needs that the personal one doesn’t, and it’s the one people skip because the app looks like it already handles it. Obsidian’s isolation is trivial — it’s local; the notes never leave the machine, so “whose data is this” has one answer. The moment memory is a shared cloud service, that question has thousands of answers, and app-layer checks are not enough to keep them straight.
The naïve version partitions each user’s data by a userId the app passes along and trusts. That holds right up until one bug — a missing partition key, a userId read from the request body, a stray cross-partition query — hands one person’s profile to another. “Logical” isolation is not “absolute” isolation. And Cosmos data-plane RBAC scopes to a container, not a partition, so the credential the agent holds can, by default, read every row in the container.
So the membrane here is drawn at the data plane, in layers:
- Composite identity key. Partition on
pk = "${tid}:${oid}", derived from the validated principal — never from the request body. Client-supplied ids are rejected. Cross-tenant collision becomes impossible. - One guarded data layer. A single
ProfileStoreinjectspartition_key = callerKeyon every read and write and forbids cross-partition queries in user containers. There is no raw container access anywhere else to bypass it. - A per-request resource token. The brain brokers a Cosmos resource token scoped to the caller’s partition, so even the credential the agent carries can only touch that one partition. The agent literally cannot read someone else’s row — not “is checked and denied,” but “was never handed the reach.”
The throughline with the first two membranes is the same discipline: don’t rely on the app remembering to be careful. Make the safe thing structural — a filter the query can’t skip, a sync that only sees main, a token that can’t reach past one partition.
The Membrane: four rules that hold at any scale
Collapse all of it — personal and fleet, weekly and daily, notes and rows — into four rules. This is the framework I wish I’d had before the 1 a.m. note:
- Capture and grounding are different stores, or at least different states. Never let raw capture be groundable.
/Inboxis not/Knowledge; a branch is notmain. Keep write-optimised and read-optimised on opposite sides of a line. - Promotion is an explicit, gated act — never a side effect. A memory earns groundability by being distilled and filed (weekly, by you) or synced from the source of truth (daily, by a job). If saving a note silently makes it citable, you have no membrane.
- One narrow door in, provenance on the way out. One read-only
search()— or one local grounding query — and every result carries a source and a date. No citation, no claim. - Isolate by identity, not by trust. Personal stays local. Shared memory walls each person off at the data plane — composite key plus resource token — so a forgotten check in the app can’t leak one profile into another.
Steal this: which brain does this belong in?
The rule I now run before anything lands in either brain. Two questions — who authored it and is it vetted — route every memory:
| The memory is… | Not yet vetted (capture) | Vetted / promoted (grounding) |
|---|---|---|
| Yours, personal | Obsidian /Inbox — quarantined, type: fleeting | Obsidian /Knowledge — type: permanent, summarised, wikilinked |
| Yours, work | a branch / a draft PR — not on main | merged to main → next daily sync → search() |
| Someone else’s, shared | — (never capture into shared) | company grounding index, read-shared, provenance-stamped |
| Per-person state | — | Cosmos, partition pk = "${tid}:${oid}", resource-token scoped |
And the promotion checklist — a note may cross the membrane only when all of these are true:
- It has a
type:that the grounding query includes (notinbox/fleeting). - It has a one-line
summary:— the cheap-recall entry point. - It cites where the claim came from (
source:/ a[[wikilink]]/ asha). - It’s been distilled at least once, so it states a conclusion, not a raw thought.
- For shared memory: it reached the source of truth (
main), not just someone’s scratch.
Copy that into your own vault or your own retrieval config and the 1 a.m. note stops being a landmine. It’s still there when you want it — it just can’t be mistaken for the truth.
What the membrane unlocks
Drawing the line changed what each brain is for, and that’s the real payoff. Obsidian gets to be gloriously messy again, because mess on the capture side is free — nothing there can be cited until I promote it, so I can scribble at 1 a.m. without arming a landmine. The Cosmos DB brain gets to be ruthlessly literal, because I’ve stopped asking it to have taste it was never going to have; its only job is to return vetted main, per identity, with receipts. The two brains stopped competing to be “the memory” and became a capture organ and a grounding organ with a valve between them.
The honest cost: a membrane is not free, and it is never done. The weekly harvest is a tax you keep paying; the daily sync is a job you keep watching; the isolation layers are architecture you keep testing with a red-team read. Skip the upkeep and the line thins — quietly, exactly like it did the week the 1 a.m. note escaped. But that’s the deal with any memory worth grounding on: the value isn’t in what you let in, it’s in what you make earn its way across. Capture everything. Ground on almost none of it. The membrane is where a second brain stops being a junk drawer and starts being something an agent can trust.