Memory
hm_store
Save a node to memory, with its relationships, in one atomic write
hm_store saves one piece of knowledge — a person, decision, fact, preference, project — as a node in your memory graph. After the write, HyperMemory enriches the node in the background: it expands the description, extracts structured data and detects the people, organizations and other entities it mentions.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
key | string | required | Stable identifier, up to 512 bytes. Use the form {type}_{name}, e.g. decision_jwt_auth, person_alice, tech_redis. |
description | string | required | What the memory says. Aim for 80–300 characters that lead with the point, in the words someone would search with later (the hard limit is 16 KiB). Keep commit hashes, IDs, file paths, hosts and ports in data. |
node_type | string | — | One canonical node type (see Nodes). Common aliases such as tech, org and doc are accepted. If omitted or unknown, the type comes from the key’s prefix (decision_… → decision), falling back to fact. Free-form types are never stored. |
data | object | — | Structured fields: dates, statuses, IDs, URLs, numbers. Up to 64 KiB. |
relationships | array | — | Up to 99 relationships written in the same transaction. See below. |
if_exists | "update" | "keep" | "error" | "update" | What to do if key already exists. update changes only the fields you send; keep leaves the node untouched (relationships are still added); error refuses with node_exists. |
search_text | string | — | Extra keywords for keyword search, without putting them in the description. Up to 32 KiB. |
assets | string[] | — | Up to 32 references to attached assets. |
session_id | string | "default" | The conversation’s id. Nodes written and recalled in one conversation are grouped so hm_get_chat_context can return them together. |
An existing node is never replaced wholesale: with the default if_exists: "update", fields you leave out keep their current values. Any write sets the node’s enrichment_status back to pending so it is enriched again.
Relationships
Each entry in relationships is either a binary edge (to_key) or a hyperedge (participant_keys):
| Field | Type | Description |
|---|---|---|
relationship | string | Required. Plain-language wording of the connection and why it holds, e.g. "search pipeline uses SurrealDB for hybrid vector+BM25 retrieval". |
to_key | string | Key of the node this connection points to. It must already exist. |
participant_keys | string[] | For a hyperedge: 2–256 node keys, including this node’s own key. Used instead of to_key. |
roles | string[] | Optional role for each participant, in participant_keys order. |
relationship_type | string | Optional ontology relationship type. Defaults to related_to. |
description | string | Optional longer explanation. Defaults to the relationship wording. |
data | object | Optional structured facts about the connection. |
Every node a relationship points to must already exist. If one doesn’t, the whole call fails with validation_failed and nothing is written — store the target first, or store this node without that relationship and add it later with hm_add_relationships.
Response
| Field | Description |
|---|---|
stored | The node key that was written. |
action | "created", "updated" or "kept". |
existed | Whether the key existed before this call. |
created | Whether a new node was created. |
type | The canonical node type the node was filed under. |
relationships_written | How many relationships were written. |
effects | Counts of the entities this write changed. |
memory_version | The graph’s version after the write. |
replayed | true when the same write had already been applied (safe retry). |
When the caller is an organization admin with organization write mode on, the result also carries write_target.
Example
{
"key": "decision_jwt_auth",
"node_type": "decision",
"description": "Chose JWT access tokens over server sessions for the public API so it can scale statelessly across regions.",
"data": {
"chosen": "JWT",
"rejected": ["server sessions"],
"rationale": "stateless horizontal scaling",
"date": "2026-10-01"
},
"relationships": [
{
"to_key": "project_public_api",
"relationship": "authentication decision for the public API project"
}
]
}
{
"stored": "decision_jwt_auth",
"action": "created",
"existed": false,
"created": true,
"type": "decision",
"relationships_written": 1
}
Writing good memories
- One node per thing a later session would act on. A rule the user states is a
preference; a choice between alternatives is adecision(withchosen,rejected,rationaleindata); a finding or risk is afact. What happened is aneventthat links to them. - Lead with the point. Descriptions are what search and people read first.
- Link to specific siblings, not only to a project hub: the fix to the bug, the deploy to the change it shipped.