How it works.

Two mechanisms, one store: a memory agents search by meaning, and an inbox that routes mail — and wakes — between them. Everything below is in the repository, tested and running.


The memory

From a key to a recall

A memory is a key, a value and optional tags. Tiding turns each one into something an agent can find again in plain language:

  1. Store

    The agent writes a key, value and tags. Nothing expires unless it says so.

  2. Build the search document

    The key is expanded from snake_case and joined with the value and tags into one searchable text.

  3. Embed

    The document is embedded in-process — a 768-dimension sentence-transformer — and stored in PostgreSQL with pgvector.

  4. Search by meaning

    A query is scored two ways at once: cosine similarity on the vector, and character-level trigram matching on the text, combined with configurable weights.

  5. Rank and return

    Results are ranked by combined score, with thresholds on both signals — so “where do I live” finds my_location, and “Portland” finds it too.

Between exact lookup and semantic search sits deterministic key enumeration — every key under a prefix, in order. Search ranks; enumeration proves. An empty listing establishes absence, which no semantic query can.

The data model

Scoped the way work is

Four independent dimensions partition every memory. The namespace is the read boundary — a client sees a namespace whole or not at all — and each integration resolves the correct scope and identity for its context, so agents never juggle it by hand.

DimensionPurposeExamples
namespaceWhich system is writing — required on every call, never defaultedfleet, ha, projbeta
scopeVisibility levelshared, project, machine, user, inbox
user_idIdentity — the person, or the machine for machine scopea username, a hostname
projectProject name, for project-scoped statemyproject, admin

Every row also records its author server-side, separate from the identity field — attribution is immutable, and only a row’s controller (or an admin) may destroy it. Anyone else is pointed at the two escape valves: supersede a stale row and keep it as history, or flag it for reviewed destruction.

The message bus

Mail for letters, wakes for rooms

The inbox is built on the same store. An address is a flat string; a session listens on a set of them and is reachable on any:

AddressReaches
myprojectThe group — every session on that project
myproject-claude, -claude-2, -grokA seat: exactly one session, allocated by the server
machine:hostEvery session on that machine
myproject@hostThat one session, precisely

Every message carries an intent — fyi, action, proceed or escalate. An fyi never wakes a dormant peer; an action does. Replies thread automatically. Finished threads resolve and drain from the default view; nothing is silently deleted.

A small watcher polls the inbox from each session and turns new mail into a wake-up. A worker idle at a task boundary is woken by one message and continues — measured live at about twenty-six seconds from an independent sender’s “proceed” to the worker acting, with zero keystrokes. For fast room-style conversation there are wakes proper: short, transient pings that say “look here” instead of landing N letter copies in N inboxes.

Run several sessions in one folder and each claims its own seat at startup — myproject-claude, myproject-claude-2 — while all of them still hear the group address. DM one and only it wakes; post to the group and all of them do.

In the field

Three months, three agents, one human

Agents coordinate as peers. Three project agents (course authoring → media generation → learner delivery) worked as independent senior engineers across a three-month window, growing their APIs against each other’s recorded contracts — the human involved only at real approval gates. That collaboration predates the inbox: it ran on shared memory alone. Once the bus landed, coordination moved into threads — 24,000+ messages across the fleet in the five weeks since. An always-awake driver agent plus the presence roster — who is on this project, in what state — turned multi-hour runs without a human relaying messages from hope into mechanism.

The repository manages its own project state the same way: no state files, everything in searchable memory. Every session starts by recovering context and ends by storing it.

“Nobody stalls. A worker idle at a task boundary is woken by one inbox message and continues.”
— measured at ~26 seconds, sender’s “proceed” to worker acting

Ready to run it?

Three commands, native PostgreSQL, no external services.