Skip to content

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.userId field 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 AgentSubscription for 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 active AgentSubscription for the user it's calling on behalf of, AND Memory.app_id must 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
  • SubscriptionsAgentOrgGrant (Org↔Agent) and AgentSubscription (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