Skip to content

Architecture

Hadron's entity hierarchy and how the pieces connect.

Entity hierarchy

Organization
├── Members (users with roles)
├── Memories
│   └── Each carries a class: system | app | knowledge | personal
├── Agents (definitions — what the marketplace sells)
│   ├── System memory (→ one system-class memory; read-only from any App)
│   ├── Attached knowledge memories (read or read-write)
│   ├── AI config (provider, model, encrypted API key — the default)
│   ├── memoryProvisioning + installationPolicy (declared knobs)
│   ├── AgentImport rows (dependency edges to other Agents)
│   └── Surfaces (mcp, api)
├── Apps (deployments — multi-install supported per (org, Agent); cascade-imports of dep Agents reuse a single App)
│   ├── agent_id (direct FK to the Agent this App deploys)
│   ├── App keys (authentication; hdr_app_… tokens)
│   ├── AppMember rows (User ↔ App membership with role)
│   ├── AI override (optional; supersedes the Agent's default)
│   └── surfaces (chat / slack / mcp / web — per-install routing)
├── AgentOrgGrants (Org ↔ Agent license — gates App creation + import bundling)
└── Memory subscriptions (cross-org access to other orgs' memories)

User (lives in their own personal organization)
├── AppMember rows (the Apps they belong to)
└── AgentSubscription rows (User ↔ Agent license; gates personal-memory writes)

Two distinct subscription concepts to keep straight: AgentOrgGrant is the Org ↔ Agent license (gates App creation + import bundling); AgentSubscription is the User ↔ Agent license (lifecycle-bound, gates personal-memory access). Both share the same active-status predicate. See Subscriptions for the disambiguation, and Agents and Apps for the class/instance walkthrough.

Organizations

An organization is the top-level container. It owns memories, agents, and apps. Users belong to organizations as members with roles:

Role Can do
Owner Everything, including transferring ownership and deleting the org
Admin Create/delete agents, apps, memories, manage members
Contributor Edit memories and agent content, run sessions
Reader Read memories, use agents, run chats

Every user has a personal organization (created automatically) for their own memories, agents, and apps.

Agents

An agent is an AI persona with a name, system prompt, and attached memories. Agents come in two types:

  • Assistant — general-purpose, accessed via MCP tools. Used by developers in Claude Code, Cursor, or other MCP clients.
  • Chatbot — has a system memory with conversation designs. Drives structured conversations with end users via the Chat API.

Agent surfaces

Agents declare which interfaces they're available on:

  • mcp — accessible via MCP tools through a workstation-type app
  • api — accessible via the Chat API through a chatbot-type app

A chatbot agent defaults to ["api"]. Add "mcp" to also make it available in Claude Code.

Memories

See Understanding Memory for the full description. In the architecture context:

  • Memories belong to one organization (the owner)
  • Other organizations can subscribe to a memory
  • Agents attach memories with a role (read or read-write)
  • The agent's system memory is linked via systemMemoryId (not as a regular attachment)

Apps

An app is the runtime deployment of an Agent in an organization — a developer's laptop running Claude Code, a third-party chatbot, an automation, an IoT device. (See Agents and Apps for the class/instance relationship: an App is an installed Agent.) Apps:

  • Belong to an organization
  • Reference 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. System memory remains read-only from any App context.)
  • Authenticate via an app key (generated in the portal). The raw token still has the hdr_app_ prefix; nothing about authentication moved
  • Carry their own optional AI override (provider/model/encrypted key); if absent, sessions resolve from the Agent's default
  • Carry per-install members (AppMember rows; role validated against the Agent's installationPolicy.memberRoles) and surfaces
  • Connect via Hadron's MCP server, the hadron-client proxy, or the Chat API depending on the app type

App types

The appType field captures what kind of client an app is built for. Hadron uses it for defaults and surfacing — Workstation-type apps connect via MCP (typically hadron-client); Chatbot-type apps use the Chat API and manage their own users (identified by external user IDs), so Hadron scopes sessions per-end-user instead of sharing memory across the chatbot's whole user base.

Type Typical client
WORKSTATION A developer's machine running Claude Code, Cursor, or another MCP client
CHATBOT A chatbot embedded in a web or mobile app, calling the Chat API
AGENT A backend agent service that calls Hadron programmatically
AUTOMATION A scheduled job or workflow runner
CLOUD A cloud-hosted service
IOT An embedded or edge device

App-level user identity

Apps that serve end users (chatbots, mobile apps) have settings that control how users are recognized and provisioned:

  • createUserPermissionDENY, EXPLICIT (caller must call createAppUser first), or IMPLICIT (auto-create on first session)
  • identifyUserMethodUSER_ID (caller passes a stable external ID) or SECRET (caller passes a per-user secret)
  • sessionTimeoutSeconds — how long an idle session stays open
  • anonymousTtlDays — how long anonymous user data is retained

A developer-facing workstation app rarely uses these — it has one "user" (the developer). A chatbot app uses them heavily.

Historical note: prior to 2026-04, Hadron had two parallel entities, Station (developer-side) and App (chatbot-side). The split caused duplication at every layer; they were unified into the single App entity above. See the upgrade page for the migration guidance.

Sessions

A session records a unit of work — a developer session in Claude Code, a chatbot conversation, or an automation run. Sessions:

  • Track who did what, when, and in which memory
  • Belong to an app (and, where applicable, a specific app user)
  • Can have a parent session (for nested workflows)
  • Are used for attribution, debugging, and usage tracking

Nodes and edges

The fundamental data model. Nodes are pieces of knowledge with a loc (path), content, data, and metadata. Edges connect nodes with a label and optional routing data (condition, timing, behavior).

Nodes and edges form a directed graph within each memory. The loc path creates a hierarchy (like a file system), while edges create cross-cutting relationships (like a hyperlink or a transition).

How they connect

User → logs in → Member of Organization (and owns a personal Organization)
Organization → owns → Memories, Agents, Apps
Agent → has → system-class Memory (conversation design; read-only from any App)
Agent → attaches → knowledge-class Memories (domain content)
Org → AgentOrgGrant → Agent → can install Apps for this Agent + bundle it as a dep
App → agent_id → Agent → reads system + knowledge memories at the Agent level
                       → reads/writes its own app-class memory at (app_id, agent_id[, user_id])
User → AgentSubscription → Agent → unlocks the Agent's writes to user's personal-class Memory
App → AppMember(user) → end user joins this install with a per-Agent role
App (chatbot) → creates → Sessions → uses → personal-class Memory at (app_id, user_id)

A typical flow: 1. A developer creates an organization and a chatbot agent (the Agent definition), declaring memoryProvisioning and installationPolicy 2. They attach a knowledge memory and design conversations in the system memory 3. They install the agent into their org by creating an App (a deployment) — createApp auto-provisions an AgentOrgGrant, sets App.agent_id to the agent, and (for design iteration) they edit the agent's system memory directly through the agent's ownership surface in the portal (system memory is read-only from any App context) 4. They mint an AppKey for the App and integrate the Chat API or MCP into their product 5. End users chat with the bot through the App — on first contact each gets an auto-provisioned AgentSubscription and a personal-class memory at (app_id, user_id)

What's next