Understanding Memory¶
Memory in Hadron is a graph of nodes — structured pieces of knowledge connected by edges. This page explains what memory can be and what it can do, without getting into how-to steps.
What a memory contains¶
A memory is a named, versioned collection of nodes. Think of it as a knowledge base with structure. Each node has:
- loc — a path-like address (e.g.,
conversations:onboarding:welcome) - name — human-readable label
- content — markdown text (prompts, descriptions, articles)
- data — structured JSON (configuration, extracted facts, metadata)
- tags — labels for filtering and search
- nodeType — what kind of node it is (see below)
- edges — connections to other nodes (relationships, transitions)
Nodes are hierarchical: conversations:onboarding:welcome is a child
of conversations:onboarding, which is a child of conversations.
Node types¶
| Type | Purpose | Examples |
|---|---|---|
system |
Agent configuration | Conversations, stages, prompts, topics |
record |
Stored data | Chat sessions, messages, user profiles |
info |
Reference content | Articles, guides, extracted facts |
abstract |
Summaries | Chat summaries, topic summaries |
Memory classes¶
Every memory has a class — one of four values. The class tells you what kind of content the memory holds and (most importantly) who is allowed to read or write it.
| Class | Purpose | Examples |
|---|---|---|
system |
The Agent's own definition: conversation designs, stages, prompts, partials, topics. | The "brain" of a chatbot — how it greets users, how it routes between stages. |
app |
Records the App writes through the Agent — collaborative, shared by all callers of this App↔Agent pair. | A film-crew preproduction Agent's vendor lists, schedules, prop manifests. |
knowledge |
Reference content the Agent reads from. Read-mostly, non-user-specific. | A therapy-techniques memory; a sustainable-packaging knowledge base; industry research. |
personal |
Per-user records: chat history, preferences, private notes. Owned by the user, not the Agent or the App. | A user's individual chat history with a chatbot; the director's private notes on cast members. |
System memories are special in two additional ways: they're hidden from the main memory list (they appear under "System memories" if the user toggles that view), and they're linked only via Agent.systemMemoryId rather than as a regular memory item.
For the full access semantics of each class — who can read, who can write, what cross-org rules apply — see Memory access.
Where chat content lives¶
A chat is a subtree of nodes (the chat-root plus its messages and any facts the agent extracts during the conversation). Where the subtree gets stored depends on the chat's scope:
- Private chats — stored in your
personal-class memory. Only you can see them. - Shared chats — stored in the App's
app-class memory. Every member of the App can read them.
You pick the scope at chat creation (see Chatting with an agent). The scope is then immutable for the lifetime of that chat — facts the agent extracts during the conversation are written to whichever memory the chat lives in. If you mis-tier a chat, the recourse is to delete it and start a new one in the correct tier.
Personal memories — per-user, user-owned¶
When a chatbot agent talks to users, each user gets their own personal memory — created automatically on their first chat. This memory holds:
- Chat sessions and message history
- Data extracted during conversations (name, goals, preferences)
- Goal stack and route history
Personal memories are:
- Owned by the user. The
Memory.userIdfield points at the User row. Even an ADMIN of the Agent's owning organization cannot read another user's personal memory — strict ownership applies. - Scoped to the (user, agent) pair. Each user has a separate personal memory per Agent they use. Alice's Sage memory is distinct from Alice's Juno memory.
- Hosted in the user's personal organization. Every user has one (created automatically at signup, hidden from the user). Personal memories live there, not in the Agent's owning org.
- Encryptable — can be encrypted with a user-controlled key. The server never stores the plaintext key.
- Gated by the user's
AgentSubscriptionfor the App-keyed write path. The Agent can only write into the user's personal memory while the user holds an active subscription. See Subscriptions for the lifecycle.
How memory is stored¶
Nodes are stored in a PostgreSQL database with full-text search. Each node belongs to exactly one memory. Edges connect nodes within or across memories.
For git-backed memories, nodes can also be synced to/from a GitHub repository, enabling version control and collaborative editing.
How memory is shared¶
Within an organization¶
All memories belonging to an organization are visible to its members (subject to role-based access: Admin, Contributor, Reader, Consumer).
Across organizations¶
A memory can be subscribed to by another organization: - Read-only subscription — the subscriber can read but not modify - Contributor subscription — the subscriber can add content
This enables knowledge sharing: a sustainability research org publishes a memory, and multiple chatbot operators subscribe to it.
Via agents¶
Agents attach memories with a role: - read — the agent can reference the memory but not modify it - read-write — the agent can both read and write
A typical chatbot agent has: - A system memory (read-write, owns the conversation design) - A knowledge memory (read-only, domain content) - Per-user memories (read-write, created automatically per user)
Via apps¶
Apps (client connections like Claude Code or a third-party chatbot) deploy one or more Agents via the AppAgent join table. (Spec 008 had briefly replaced the join with App.agent_id; the 008-amendment in spec-kits #43 reintroduces the join — without the legacy role column — to support multi-Agent Apps under one credential.) What that gets you:
- System memory — read-only from any App context. Edits to the conversation design happen in the Agent's ownership surface, never through an App.
- App memory — keyed on
(app_id, agent_id)(or(app_id, agent_id, user_id)for per-user-app-memory Agents). Per install — sibling installs of the same Agent get distinct rows. - Attached knowledge memories — gated per-memory by
AgentMemoryItem.role. Per-Agent (not per-install) — same Agent shared across two installs sees the same knowledge memory. - Personal memories — keyed on
(app_id, user_id). The App needs an activeAgentSubscriptionfor the user it's calling on behalf of, ANDMemory.app_idmust match the calling App's id (so Mike's data at Juno-on-MicroMentor is isolated from his data at Juno-on-Company-X). See Subscriptions.
Encryption¶
Hadron supports memory encryption at rest: - Memories can be marked as encrypted - Node content and data fields are encrypted with AES-256-GCM - Encryption keys can be user-controlled (the server never stores the plaintext key) - Encrypted memories require the key to be provided at session start
This is important for sensitive data — therapy notes, financial information, personal health data — where the user must control who can read their memory.
What's next¶
- Agents and Apps — the class/instance relationship between Agents and Apps and why the per-install isolation matters
- Memory access — the full cross-organization rules: who can read what, when, and why
- Subscriptions —
AgentOrgGrant(Org↔Agent) andAgentSubscription(User↔Agent), the two grants that gate the cross-org chain - Architecture — how the entities (organizations, agents, memories, apps) relate to each other
- Building an Agent — create your first agent with memories