Agent memory that shows its sources
memspine keeps each agent's conversation turns, tool calls and conclusions in a separate database for every customer. It returns a conclusion with the events it came from and erases any event from disk on request. It runs as one binary in your own infrastructure.
- turnAna: we adopted a greyhound called Pixel last weekend
- turnAna: she needs a vet, somewhere open on Saturdays
- tool_callfind_vets(city=Lisbon, open=saturday) -> Clinica Arroios, VetLuz
- turnAna: book Clinica Arroios for this Saturday at ten
- tool_callbook_vet(Clinica Arroios, 2026-10-10 10:00) -> confirmed A-2291
- factAna owns a greyhound named Pixel
- factAna prefers Saturday appointments
- factPixel has a vet appointment at Clinica Arroios on 2026-10-10 at 10:00, booking A-2291
- turnAna: my number is 912 555 019, text me the day before
- factText Ana the day before the vet appointment
One agent session as memspine stored it: the customer's turns, the agent's tool calls and the facts it concluded. The lines at the left tie each conclusion to the events it came from. Eight of the ten arrived in the two requests below, the last two in one request each.
$ curl -s localhost:7777/v1/memory/events -H "$K" -H "$J" -d @turns.json; echo
{"event_ids":["75173310-8a48-40bc-8b49-8c2ab8c7dc0c","9509bd23-a670-42e0-bbe0-b87e994b0617","697ea0fa-fa50-4d51-9aa8-417263290f08","b8533f46-b491-4c20-a078-b0ca2e039926","740c7d03-9b97-4854-8799-6d66524cf3fe"]}
$ curl -s localhost:7777/v1/memory/events -H "$K" -H "$J" -d @facts.json; echo
{"event_ids":["d53b6b8b-5c0e-4785-982b-db4f145dd1d9","b41bdb35-2dcc-4452-af6e-2dba054958ce","3dce87e5-4b2c-4cc0-96bc-338ce95f158f"]}
Ask in words, by meaning, or both. This request asks in words for the top two of the ten events and gets them back ranked.
$ curl -s localhost:7777/v1/memory/recall -H "$K" -H "$J" \
-d '{"text":"vet appointment booking","k":2}' \
| jq -r '.hits[] | [(.score*1e4|round/1e4), .kind, .event_id[0:8], .text[0:44]] | @tsv'
3.2165 fact 3dce87e5 Pixel has a vet appointment at Clinica Arroi
2.5492 fact c3d7a7af Text Ana the day before the vet appointment
The same question, with its sources. The first answer comes back with the customer's instruction and the tool call it was derived from, so a reviewer can see what the agent knew. A request adds at most k source events, and this one asked for two.
$ curl -s localhost:7777/v1/memory/recall -H "$K" -H "$J" \
-d '{"text":"vet appointment booking","k":2,"hops":1}' \
| jq -r '.hits[] | [.kind, .event_id[0:8], (.via // "-")[0:8], .text[0:52]] | @tsv'
fact 3dce87e5 - Pixel has a vet appointment at Clinica Arroios on 20
fact c3d7a7af - Text Ana the day before the vet appointment
turn b8533f46 3dce87e5 Ana: book Clinica Arroios for this Saturday at ten
tool_call 740c7d03 3dce87e5 book_vet(Clinica Arroios, 2026-10-10 10:00) -> confi
The customer asks for their phone number to be removed. One request deletes the event from every answer and from the files on disk; the search of the data directory that follows finds nothing.
$ grep -rl "912 555 019" data
data/00000000-0000-0000-0000-000000000042/events.ffs.qlog
$ curl -s -X DELETE "localhost:7777/v1/memory/event/$E9?purge=true" -H "$K"; echo
{"deleted":true,"purged":true}
$ grep -rl "912 555 019" data; echo "grep exit $?"
grep exit 1
A real session against memspine 0.2.2. The full transcript has every request and response.
of the evidence found on LoCoMo, a public benchmark, at 20 results per query with client-side fact extraction; 79.4% on raw turns
median time to search a customer's 10,000 stored events
confirmed writes lost when the server is killed; every write is on disk before the reply
default interval between purge passes, which rewrite a customer's files without its deleted events
How each figure was measured, and where the numbers are weaker, is on the results page.
What it gives a business
How each operation works ->An answer you can trace
When an agent states something, the fact it relied on links to the conversation turns and tool calls it was derived from. One request returns the hits and up to k of the events they were derived from.
Your infrastructure
One server binary for Linux or macOS. No other services to run. The server makes no outbound network calls.
Each customer kept apart
Every customer is a separate database with its own keys and limits. A key reads and writes one customer's memory.
$ grep -rl "912 555 019" data; echo "grep exit $?"
grep exit 1Deletion that reaches the disk
Forgetting an event removes it from every answer at once. Its bytes leave the files on disk at the next purge, which runs every 60 seconds by default, or before the reply when the request asks for it. The tests check that the bytes are gone.
Nothing confirmed is lost
A write is on disk before the server replies. In the recorded session the server is stopped with kill -9, started again, and returns the last event it had confirmed.
Where it fits
Three worked examples ->Customer support agents
Keep each customer's history across sessions. When a case is escalated, show what the agent was told and what it looked up before it answered.
Operations agents
Record every action an agent takes in your systems together with the instruction and the data behind it, so the action can be audited later.
Assistants with long-running work
Carry what an assistant learned in one session into the next without replaying whole transcripts into the prompt.
Measured results
Method, tables and caveats ->Retrieval is scored on LoCoMo: 1,540 questions over 10 long conversations, of which 1,536 name evidence to find. The score is the share of that evidence among the events returned, 20 per query.
With the client extracting facts and rewriting each question into as many as four queries, as the benchmark harness does, memspine retrieves 0.889 of the evidence. Storing raw turns and sending the question as it is, 0.794.
End to end, with a model answering from the retrieved events and a judge marking it under a published rubric, 0.786 of answers were accepted in a June run on an earlier version of the engine.
Evidence recall on LoCoMo at 20 results per query, 10 conversations, 1,536 scored questions, text-embedding-3-small at 384 dimensions.
Install
Full quickstart ->$ curl -fsSL https://memspine.com/install.sh | sh
Downloading memspine-macos-arm64.tar.gz ...
Checksum OK.
Installed memspine-server and memspine-admin to ~/.local/bin
Start the server:
MEMSPINE_BIND=127.0.0.1:7777 ~/.local/bin/memspine-server
- Version 0.2.2 for Linux x86_64 (built for glibc 2.17; run after each release on AlmaLinux 8 and Ubuntu) and macOS arm64.
- The server and its admin tool,
memspine-admin, in~/.local/bin, checked against a published checksum. - No root.
- As installed, any UUID is a customer and its own key, which is for local use.
memspine-admin initturns on issued keys.
$ MEMSPINE_BIND=127.0.0.1:7777 MEMSPINE_EMBEDDING_DIM=4 \
~/.local/bin/memspine-server > memspine.log 2>&1 &
$ sleep 1; curl localhost:7777/health
{"service":"memspine-server","status":"ok","version":"0.2.2"}
$ K="Authorization: Bearer 00000000-0000-0000-0000-000000000042"
$ J="Content-Type: application/json"
$ TURN=$(curl -s localhost:7777/v1/memory/event -H "$K" -H "$J" \
-d '{"kind":"turn","embedding":[0.9,0.1,0.2,0.1],
"text":"Ana: we adopted a greyhound called Pixel last weekend"
}' | jq -r .event_id)
$ curl -s localhost:7777/v1/memory/event -H "$K" -H "$J" \
-d '{"kind":"fact","embedding":[0.8,0.2,0.1,0.1],
"text":"Ana owns a dog named Pixel","properties":{
"source_event_ids":["'"$TURN"'"]}}'
{"event_id":"b5ea3003-7681-4632-a015-5ec4fdec7595"}
$ curl -s localhost:7777/v1/memory/recall -H "$K" -H "$J" \
-d '{"text":"which dog does Ana have","k":1,"hops":1}' \
| jq -c '.hits[] | [.kind, .text]'
["fact","Ana owns a dog named Pixel"]
["turn","Ana: we adopted a greyhound called Pixel last weekend"]
How it is checked
162 automated tests
Every change runs these, the linters and a container that is started and written through. The Python and TypeScript SDK suites hold 50 more and are not part of that run.
2 releases of fixes from an independent review
An independent review of 0.1.0 and 0.2.0 went looking for defects. 0.2.1 and 0.2.2 are the fixes, and the changelog lists each one.
3 systems the installer is run on
After every release the install command is run on Ubuntu, AlmaLinux 8 and macOS, and the installed binaries store, recall and delete an event.
What it does not do
It does not call an embedding model or a language model. Your application supplies embeddings and decides what to store.
It keeps one copy of the data on one machine. There is no replication yet.
Search compares against every stored embedding, which suits a customer with up to about 100,000 events.
It speaks plain HTTP. Put TLS in front of it with a reverse proxy.
Join the waitlist
Tell us which agents you would give memory, and we will be in touch when there is room for your team.
The form needs JavaScript. Open the early access form instead.
Running agents for your customers?
memspine is built by ERP.AI. If you are putting memory under agents that serve your customers, talk to us.