Agents are moving to the edge.
Their memory should too.
AI agents are moving to the edge. Embedding models that needed a dedicated GPU cluster a couple of years ago now run fine on a laptop with decent CPU/GPU. Small language models are getting better every few months or so. More and more of an agent can live on the machine it works on.
Memory is the piece that has not caught up. Most agent stacks still put memory on a big self-hosted search cluster or in a managed cloud service. Either way the agent drags along a network dependency, hardware, and operational cost, and in the managed case its memory sits on someone else's servers.
This should change, or at least get much simpler.
The local agent needs local memory: durable, searchable, typed, and able to survive the process around it being killed or restarted. That is not what I originally designed Polign/polign_db for. I wanted it to serve search from object storage with as little resident state as possible, and with query costs that do not grow with the size of the data. It turns out that those properties map well to edge hardware.
The model can be probabilistic. Memory shouldn't have to be.
There is a fundamental problem with asking an LLM to manage its own memory. The model has to decide whether a statement is new or a correction, whether it contradicts something already stored, whether a value is a number or a string, and whether a new value should replace an old one.
Those are database questions.
A typed memory store moves those decisions out of the model and into the schema. The model extracts a fact; the database determines what that fact means.
Take two memories: prefers_editor = "vim" and
daily_step_goal = 9000. The schema says prefers_editor holds
one value, so when the user switches to emacs, the new value replaces
vim and the old record is kept as history. The schema also says
daily_step_goal is a number, so "8000" as a string gets
rejected, and 9000 goes in as a real number you can hit with a range
filter later.
The model never has to notice the contradiction or remember that the value is a number. The store does that. This split matters more as models get smaller. Instead of hoping a model infers the right semantics from a pile of retrieved text, the rules live in the database.
Why a cold-first database fits on small hardware
The design decision that makes this possible is described on the how it works page: in polign_db, the bucket is the database. The server holds nothing durable. Vectors, indexes, text, and metadata all live in the store; the server reads what a query needs, caches what is hot, and comes back from a restart with nothing to rebuild.
I made that choice for cost and operational reasons, at a small cost of initial latency. At the edge it solves a different set of problems.
The footprint is small. The server is one lightweight binary with one flag:
polign-server -store .... The
Wikipedia demo serves 12.5 million
passages from S3 while the server idles at about 37 MiB RSS, and the whole demo,
embedder and web app included, fits on a 2 GB ARM machine.
The store can be local. -store takes S3, GCS, an
S3-compatible server like MinIO, or a plain directory:
fs:/var/lib/polign. Point it at a directory and the device itself holds
the durable state. Nothing more.
The failure model is simple. Edge machines get rebooted, crash, and lose power. All it needs is to restart the server on the same bucket and everything is still there.
The contract does not change with the store. Code written against a local directory works against an S3 bucket, because the durable state was never inside the server to begin with.
The memory demo
To make this concrete I built a memory demo: a terminal agent whose memory is a typed database instead of retrieved text.
Each memory is a record: kind, subject, predicate, value, confidence, status.
Predicates come from a registry that says what type each value is and whether it
holds one value or many. So prefers_editor holds one value, and
daily_step_goal is a number.
You need three things to run it:
polign-server:curl -fsSL https://get.polign.com | sh- Go, since the demo runs with
go run - an Anthropic or OpenAI API key, exported as
ANTHROPIC_API_KEYorOPENAI_API_KEY
Then point the demo at a local directory:
./run-demo.sh fs:./demo-bucket
Claude models are the default. To use an OpenAI model instead, pass the model id and the provider is inferred from it:
./run-demo.sh fs:./demo-bucket -model gpt-5
Tell it something:
you> I use Vim as my editor.
→ remember_preference({"subject":"user","predicate":"prefers_editor","value":"vim"})
← {"stored":{"id":"m-...","value":"vim","status":"active",...}}
Numbers work as numbers:
you> Is my step goal above 8000?
→ recall({"subject":"user","predicate":"daily_step_goal","value_min":8000})
← {"count":1,"records":[{"value":9000,...}]}
That comparison ran in the database. The model never had to look at a paragraph and decide whether 9000 is more than 8000.
Semantic recall sits next to the filters. The demo embeds queries with a small local model (a one-time download, about 43 MB) and searches the same records. Embedding, validation, indexing, storage: all of it happens on the box.
The language model is still a cloud API in the current demo, so this is a local memory layer, not a fully local agent. But the part that has to survive never leaves the device.
What happens when the server dies?
The demo doubles as a durability test. Kill the agent process and ask again. It still knows. Then kill the database server too and restart it from the bucket. The memory is still there, and the step goal is still a number.
On a cloud VM this is a party trick. On a device that gets unplugged at closing time, it is the requirement. Losing the server process does not mean losing the memory.
Where this is useful
A few places where local typed memory beats a memory API on the other side of a WAN link.
Your personal agent
A local agent keeps your preferences, contacts, and history in a directory you control. Moving to a new machine is copying the directory. Backing up is syncing it to storage you own.
The demo still talks to a cloud model, but the memory already has the property that matters: it belongs to your machine, not to a memory service.
The machine that remembers itself
An agent sitting on industrial equipment stores calibration values, tolerances, and observations as typed records. When someone asks "has vibration ever exceeded the limit we set?", that is a numeric range query over local records, not a semantic search through months of text.
When a setpoint changes, the old value stays as superseded history, and the gateway can answer questions about its own past with the network down.
The assistant in the building
A store, clinic, or restaurant accumulates local operational facts: which supplier substitution got approved, what the fridge threshold is, which register drawer sticks. Those facts belong on site. The agent keeps answering through an ISP outage, and one location's data moves or backs up with ordinary file tools.
Why not SQLite?
SQLite is excellent at what it does. The difference is where durable state lives. SQLite's durable state is the database file. polign_db's durable state is an object store, and the server is just a disposable node.
That matters when the same database has to run against a local directory today and S3
tomorrow without the application changing, or when hundreds of agents connect to the same memory.
The whole deployment spectrum is fs:/var/lib/polign → MinIO → S3.
Why not just use a vector database?
Vector databases or graph databases work to some extent, but agent memory is not only semantic similarity. "What editor does the user prefer?" is a retrieval question. "Is the user's step goal above 8000?" is a database query.
Agent memory needs both, plus things similarity search has no way to express: types, cardinality, supersession, history, exact predicates, numeric comparisons. Semantic search is good at finding memories. It should not be the thing that defines what a memory means.
What I have not solved
None of this means local agents are solved.
The model in today's demo is still Claude or GPT. With the uplink down, recall works but conversation does not, until a local model goes in. But that is not what I was trying to demonstrate.
Cold reads are slower than a RAM-resident database; a local filesystem takes the WAN out of that path but not the penalty. And one device is still one serving point, even if the data survives it.
The local agent stack
The stack I expect to see more of is a pile of small, boring parts:
┌─────────────────────────────┐
│ Local LLM │
│ conversation │
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ Typed memory │
│ │
│ validation │
│ supersession │
│ structured filtering │
│ semantic recall │
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ Durable local store │
│ /var/lib/agent │
└─────────────────────────────┘
Two of the three already run on small hardware today: the embedder and the database.
As local models improve, the whole agent moves onto the device. At that point its memory does not need an account with anyone. It is just storage you own.
The same engine serves 12.5 million Wikipedia passages from S3 in the cloud demo. That is the part I find interesting. The edge and the cloud do not need two database products. They are two places to put the bucket.
For an agent, that means memory can stay on the machine, move with it, or move between local and cloud storage, and nothing about what the agent thinks a memory is has to change.
Sign up
None of this needs an account. The downloads are not gated, everything runs on your own machines, and the bucket is yours. The getting started guide covers the install.
If you want a hand getting started, a managed deployment in your own cloud, or a note when the local-agent pieces ship, leave your email on the signup page and we are happy to follow up!