Arjun Khera

How a capture becomes knowledge

Engram takes the thought first and decides what it means later.
1 Sep 2026
updated 1 Sep · v1
7 min read

Save first, decide later

I keep a personal knowledge graph called Engram. It holds typed entities — notes, tasks, journals, people, projects — joined by directed edges. Every edge carries an intent, so the graph records what one thing is to another, not only that a line exists between them.

Storage is not the hard part. The hard part is the moment a thought arrives, because a thought arrives half formed. If the system asks me what type it is before it agrees to keep it, I lose the thought. So Engram keeps it first and asks later. The rule has a name: capture first.

A capture is raw. It is text, sometimes a link, sometimes a file, plus the little context the client already knows: where it came from and when. It is not knowledge yet. This post follows one capture from that moment to the point where it becomes part of the graph.

Nothing writes to the graph directly

Every client — a chat window, the command line, the web app — talks to one tool layer, and that layer talks to one REST API. The API checks the shape of the request and stores it. It does not touch the graph.

The graph sits behind one more step. Any write that would change something already in the graph lands in a proposal queue instead. Media takes a path of its own, addressed by its content, so the same file is never stored twice.

The picture answers where. It does not answer who is allowed to do what, and that turns out to be the load-bearing question.

Two kinds of writer

Engram tells two kinds of caller apart. A user principal is me. An agent principal is a program acting on my behalf.

A user principal may write to the graph. It can link two entities, retag one, archive one, or apply a type. An agent principal may not. It can read everything, and it can capture. To change anything that already exists, it has to ask.

The ask is a proposal. The write lands as a proposal, not a fact, and it carries the change it intends plus a confidence score. Nothing about it is true yet.

Why capture is exempt

Capture creates something new. It touches nothing that already exists, so it can never overwrite a fact or bend a meaning. That is what makes it safe to hand out freely, and it protects the property that matters most: no signal is ever dropped because nobody could decide where it belonged.

Two rules keep the asking honest. Each proposal declares one action class, and every operation inside it must belong to that class; mix them and the API refuses the whole proposal. And the number of proposals waiting for review is capped to what I can actually get through. When the queue is full, the next proposal is refused with a plain answer: the backlog is at capacity, come back later. No agent can bury me in requests.

What can happen to a proposal

A proposal has four states and no others. It waits. It is applied. It is rejected. Or it expires.

Approval writes the change into the graph and records who decided. Rejection refuses the change, and the refusal is not thrown away: the correction becomes input the system learns its filing behaviour from. A rejected proposal is a lesson, not a dead end.

Expiry is not rejection

A proposal nobody decides does not wait forever. When its time-to-live runs out it moves to expired. Expired is not a refusal. It is an admission that the queue got ahead of the reviewer. Only I can bring one back, and a reopened proposal returns with its content unchanged.

Without that path, a long backlog would quietly turn every unread proposal into a permanent no. Silence would become a decision, and it would be my worst one.

The narrow path that applies itself

Most proposals wait for me. A few do not.

Two gates guard the self-applying path. The first asks whether the system is confident enough in its own read of the change. The second asks whether the review queue still has room. A proposal has to pass both. Fail either one and it goes to the queue, where a human sees it first.

The second gate is the one worth defending. Confidence alone is not enough, because a stream of confident writes landing without review is exactly the failure the queue exists to prevent.

One capture, end to end

Back to the plain case: a new thought, nothing existing changed, no proposal needed.

The client sends the text. The tool layer wraps it as one request. The API checks the shape and hands it to the store, and the store answers with an id. The same text always hashes to the same id, so a second capture of the same words writes nothing and returns the first id.

The receipt is the point. I get an id back before any type, any tag, or any edge exists. The thought is safe first. Structure is a later conversation.

What the friction buys

This is more machinery than a notes app needs, and the friction is real. Every structural change an agent wants costs me a decision.

It buys one property, and only one: nothing enters the graph that I did not agree to. A system that files things for you is useful only while you still trust what it filed. The queue is where that trust is kept.

The graph is small. The rule is not. Save the thought first, decide what it means second, and never let the second step lose the first.

Discuss · 1
Arjun Khera · 1 Sep · general
this is nice take, while system like tana and roam are more UI first, this is an agent first take on note taking, love this
Arjun Khera · 1 Sep
also, any updates on whn it will be GA?
Reply · 1 in thread
Add a message…