Memory and coordination for AI agents, with TessariDB inside. Connect by URL over MCP.
2.3K
Memory and coordination for a fleet of AI agents — goals and the evidence behind them, plans, tasks and claims, checklists, decisions, and what each agent learned — as queryable records instead of files. The database it keeps them in, TessariDB, is inside the same image.
An agent connects by URL, like any remote MCP server. The first time it needs to, it opens your browser, you sign in, and from then on every agent on the machine works under that sign-in and renews it by itself.
What it does beyond keeping records:
Recall by words and meaning at once — a memory keeps the vector it arrived with, and a search with text and a vector is ranked by both in one database read, each hit saying which of the two found it.
An answer cache — keep a model's answer for as long as you say, reuse it only above a similarity you name, and get it back marked as reused.
Replay — keep a witness of a recall and later see each hit as it was when the agent read it, beside what it says now.
Teams — a team names people and agents, a grant may name a team, a memory may be kept private or for one team, and one team reads another's facts only through a grant that ends.
Clean by default — credentials are redacted before anything is stored, a repeat re-confirms the memory it repeats instead of adding a copy, and a fact knows when its evidence was withdrawn.
Site — https://tessaridb.com
Documentation — https://docs.tessaridb.com
Choose the first owner's passphrase — it is what you type in the browser when an agent asks to be authorized — then start the container:
mkdir -m 700 -p ~/.tessaridb
read -rs "p?Passphrase for the first owner: " && printf '%s\n' "$p" > ~/.tessaridb/owner-passphrase; unset p
chmod 644 ~/.tessaridb/owner-passphrase
docker run -d --name agent-memory --restart unless-stopped --stop-timeout 30 \
-p 127.0.0.1:39142:39142 \
-v tessaridb-agent-memory:/var/lib/tessaridb \
-v ~/.tessaridb/owner-passphrase:/run/secrets/owner-passphrase:ro \
-e TESSARI_AM_OWNER=ada -e TESSARI_AM_OWNER_IDENTITY=acme \
-e TESSARI_AM_OWNER_PASSPHRASE_FILE=/run/secrets/owner-passphrase \
tessaridb/agent-memory
(read -rs "p?…" is zsh; in bash it is read -rsp "…" p.) --stop-timeout 30 gives
docker stop the time the store needs to close cleanly; Docker's own default is shorter.
With the plugin — it registers this address and carries a skill that says when to use the memory. In Claude Code:
/plugin marketplace add tessaridb/tessaridb-agent-plugins
/plugin install tessaridb-agent-memory@tessaridb
Or register the server yourself:
claude mcp add --transport http -s user --client-id claude-code --callback-port 39143 \
tessaridb-am http://127.0.0.1:39142/mcp
In Claude Code, /mcp → tessaridb-am → Authenticate opens the browser. Sign
in as ada with the passphrase and approve. That is the whole setup:
The same plugin installs in Codex, from the same marketplace; then sign in once:
codex plugin marketplace add tessaridb/tessaridb-agent-plugins
codex plugin add tessaridb-agent-memory@tessaridb
codex mcp login tessaridb-am
The browser returns to 127.0.0.1:39144; sign in as ada and approve. Codex needs
0.3.0-alpha or later, which knows the codex client.
The store is never open. A database with no users runs anything for anybody who
reaches it, so this image always declares one: the account memory, with a password
drawn on the first start and kept in the volume at
/var/lib/tessaridb/db-password. Nothing prints it, and this image ships no default
credential — one would open every store that pulls it with a password the whole
internet knows. Pass TESSARIDB_INITIAL_USER and TESSARIDB_INITIAL_PASSWORD to choose
your own; a password without a user is refused rather than started.
The first owner is created once, on an empty store, from TESSARI_AM_OWNER and
TESSARI_AM_OWNER_IDENTITY, with the passphrase read from the file. Every later start
leaves the owner alone, so the passphrase file can be removed after the first start —
the variables are not a way to reset a passphrase. The owner's machine token is printed
once to docker logs.
| Port | Surface | What speaks it |
|---|---|---|
39142 | HTTP — MCP at /mcp, OAuth, and the JSON API at /v1 | Claude Code and any MCP client, curl |
Only the memory service is published. The database binds to the container's own
loopback; -e TESSARIDB_ADDRESS=0.0.0.0:9080 plus a published 9080 is the deliberate
act that exposes it.
There is no TLS. Publish on 127.0.0.1 as above, or terminate TLS in front.
| Variable | Default | What it does |
|---|---|---|
TESSARI_AM_OWNER | unset | the first owner's name, created once on an empty store |
TESSARI_AM_OWNER_IDENTITY | unset | the identity that owner administers. Both or neither — half is refused |
TESSARI_AM_OWNER_PASSPHRASE_FILE | unset | a file holding that owner's passphrase, for the browser sign-in. A file and never a variable, because variables are readable by docker inspect |
TESSARIDB_INITIAL_USER | memory | the database's own account |
TESSARIDB_INITIAL_PASSWORD | drawn | its password; unset, it is drawn on the first start and kept in the volume |
TESSARIDB_ADDRESS | 127.0.0.1:9080 | the database's wire protocol, inside the container |
TESSARI_AM_HTTP | 0.0.0.0:39142 | the memory service's address |
TESSARIDB_LOG | info | error, warn, info, debug or trace |
/var/lib/tessaridb — the store and the drawn database password, together. Mount the
whole directory so the two survive together. The container runs as uid 10001, so a
bind mount must be owned by it (chown 10001:10001 ./data); a named volume needs
nothing. The passphrase file is mounted read-only and must be readable by that uid.
HEALTHCHECK asks the memory service for its OAuth metadata over HTTP, which needs no
credential. It answers only once the database inside is ready and the service has
started on top of it.
The container holds two processes — the database and the memory service — and stops
when either of them stops, because a container that is half up is harder to notice
than one that is down. docker stop stops the memory service first and the database
second, so the store is closed before the container exits, and a requested stop exits 0.
The database first says not ready for five seconds and then finishes what is in flight,
so give the stop 30 seconds (--stop-timeout 30, or stop_grace_period: 30s in Compose).
services:
agent-memory:
image: tessaridb/agent-memory:latest
restart: unless-stopped
stop_grace_period: 30s
ports:
- "127.0.0.1:39142:39142"
volumes:
- agent-memory:/var/lib/tessaridb
- ~/.tessaridb/owner-passphrase:/run/secrets/owner-passphrase:ro
environment:
TESSARI_AM_OWNER: ada
TESSARI_AM_OWNER_IDENTITY: acme
TESSARI_AM_OWNER_PASSPHRASE_FILE: /run/secrets/owner-passphrase
volumes:
agent-memory:
| Tag | What it is |
|---|---|
latest | the most recent release |
0.4.1-alpha | TessariDB 0.33.1-beta inside; fix: tessari-am read from the command line works again; no schema change, a store written by 0.4.0-alpha opens as it is |
0.4.0-alpha | TessariDB 0.33.1-beta inside; teams, private and team memories, write attribution, readable hits with read, credential redaction, repeats re-confirmed, anchors to files, withdrawn evidence; a store written by 0.3.x gets the new tables on first use |
0.3.2-alpha | TessariDB 0.31.0-beta inside; no schema change, a store written by 0.3.x opens as it is |
0.3.1-alpha | TessariDB 0.20.1-beta inside; status hands back the last context snapshot with its text, and a repeated session_start on one connection resumes the held session |
0.3.0-alpha | TessariDB 0.20.1-beta inside; recall ranks memories and facts as one collection, Codex signs in, and a store written by 0.2.x gets the new search on first use |
0.2.5-alpha | TessariDB 0.19.0-beta inside; no schema change, a store written by 0.2.x opens as it is |
0.2.4-alpha | TessariDB 0.17.1-beta inside; no schema change, a store written by 0.2.x opens as it is |
0.2.3-alpha | TessariDB 0.16.0-beta inside; no schema change, a store written by 0.2.x opens as it is |
0.2.2-alpha | TessariDB 0.11.0-beta inside; docker stop closes the store and exits 0, and MCP results are encoded in one pass |
0.2.1-alpha | TessariDB 0.11.0-beta inside; the HTTP surface no longer queues requests on one lock, and a node too old for fused recall is refused at opening |
0.2.0-alpha | TessariDB 0.9.0-beta inside; fused recall, the answer cache, recall replay, and calls about ten times faster |
0.1.1-alpha | that version, pinned — a session is placed by its folder |
0.1.0-alpha | the first release |
Every tag is a manifest list carrying linux/amd64 and linux/arm64.
Business Source License 1.1, converting to Apache-2.0 on 2030-09-23. All production use is free, including inside a commercial organisation; the one restriction is providing it to third parties as an agent memory service, which needs a commercial licence — [email protected].
Content type
Image
Digest
sha256:156a8cdfe…
Size
41.5 MB
Last updated
8 days ago
docker pull tessaridb/agent-memory