Skip to main content
Memory Stores

Memory Store data structures

Shared data structures, constraints, and mount rules for the Forward Memory Store API.

The Forward Memory Store endpoints use three shared object types. Their hierarchy is Memory Store → Memory → Memory Version.
LevelID prefixDescription
Memory Storememstore_Container for Memories. It does not store content directly and can be mounted to an (identity, template) pair.
Memorymem_A Memory in a Store, identified by a relative path and containing the actual content.
Memory Versionmemver_Immutable snapshot produced automatically whenever a Memory is created, updated, or deleted.

Memory Store object

{
  "id": "memstore_00mc7mukn7lkxr454tjd",
  "type": "memory_store",
  "name": "project-alpha-memory",
  "description": "Agent knowledge base for project Alpha",
  "status": "active",
  "entry_count": 12,
  "total_size": 4096,
  "metadata": {
    "team": "backend",
    "created_by": "forward"
  },
  "system_managed": false,
  "identity_id": null,
  "created_at": "2026-08-14T10:00:00Z",
  "updated_at": "2026-08-14T10:00:00Z",
  "archived_at": null,
  "binding_info": {
    "identity_template_count": 1
  }
}
FieldTypeDescription
idstringMemory Store ID with the memstore_ prefix.
typestringAlways memory_store.
namestringStore display name.
descriptionstringStore description.
statusstringactive or archived.
entry_countintegerNumber of Memory entries in the Store.
total_sizeintegerTotal size of all Memory content in bytes.
metadataobjectMetadata. Always includes the server-injected created_by=forward.
system_managedbooleantrue for the default Store created automatically for an (identity, template) pair when a Session is created; false for a Store explicitly created by a user.
identity_idstring/nullIdentity that owns a system-managed default Store. null for a user-created Store.
created_atstringCreation time in RFC 3339 format.
updated_atstringLast update time in RFC 3339 format.
archived_atstring/nullArchive time, or null if active.
binding_info.identity_template_countintegerNumber of (identity, template) pairs currently mounting the Store. Archive and delete operations check this value.

Store metadata constraints

ConstraintValue
Maximum keys15
Key length1–64 characters
Value typeMust be a string
Value lengthUp to 512 characters
Reserved keycreated_by is injected by the server as "forward"; supplying it returns 400
The upstream hard limit is 16 keys. Forward injects created_by, which uses one slot, so callers can supply 15 keys.

Memory object

{
  "id": "mem_00mc7mvag5u68kkfvxhy",
  "type": "memory",
  "memory_store_id": "memstore_00mc7mukn7lkxr454tjd",
  "path": "decisions/arch-choice.md",
  "content": "# Architecture decision\n\nUse a microservices architecture.",
  "content_size_bytes": 99,
  "content_sha256": "1712de0d497a5aeef2beeccf4fbb7d5a16944975438d0c25447b9c1fba13099a",
  "metadata": {
    "owner": "backend-team"
  },
  "created_at": "2026-08-14T10:00:00Z",
  "updated_at": "2026-08-14T10:00:00Z"
}
FieldTypeDescription
idstringMemory ID with the mem_ prefix.
typestringAlways memory.
memory_store_idstringParent Memory Store ID.
pathstringCase-sensitive relative path in the Store.
contentstring/nullPlain-text UTF-8 content. Returned only by create, update, and single-get endpoints; omitted from list responses.
content_size_bytesintegerContent size in bytes.
content_sha256stringSHA-256 of the content. It can be used for optimistic concurrency control.
metadataobjectMetadata.
created_atstringCreation time in RFC 3339 format.
updated_atstringLast update time in RFC 3339 format.

Path constraints

ConstraintValue
Must be relativeCannot start with /
Maximum length1,024 bytes
Maximum segments58
Segment lengthUp to 255 bytes
Disallowed segmentsEmpty segments, ., .., or segments with leading or trailing whitespace
Disallowed characters\ and NUL
Case sensitivityCase-sensitive
Valid examples: notes/meeting-2026-08-14.md, config.yaml Invalid examples: /notes/meeting.md, a/../b, notes//x.md

Content constraints

ConstraintValue
EncodingPlain-text UTF-8, not base64
Maximum size100 KiB, measured from the raw request bytes
Control charactersNon-printable control characters (U+0000U+001F and U+007F) are not allowed, except newline \n, carriage return \r, and tab \t

Memory metadata constraints

ConstraintValue
Maximum keys16
Key length1–64 characters
Value typeMust be a string
Value lengthUp to 512 characters
Reserved keysNone. Forward does not inject created_by for entries. Callers may use that key, and its value is stored and returned unchanged.
When the Agent writes a Memory, it replaces the entry metadata with {"source":"agent"}. Normal Agent activity can therefore clear metadata set through this API.

Memory Version object

{
  "id": "memver_00mc7mw0t337kbcx5q52",
  "type": "memory_version",
  "memory_store_id": "memstore_00mc7mukn7lkxr454tjd",
  "memory_id": "mem_00mc7mvag5u68kkfvxhy",
  "path": "decisions/arch-choice.md",
  "content": "# Architecture decision\n\nUse a microservices architecture.",
  "content_size_bytes": 99,
  "content_sha256": "1712de0d497a5aeef2beeccf4fbb7d5a16944975438d0c25447b9c1fba13099a",
  "operation": "updated",
  "redacted": false,
  "redacted_at": null,
  "created_at": "2026-08-14T10:00:00Z"
}
FieldTypeDescription
idstringMemory Version ID with the memver_ prefix.
typestringAlways memory_version.
memory_store_idstringParent Memory Store ID.
memory_idstringParent Memory ID.
pathstringMemory path captured by this version.
contentstring/nullVersion content. Returned only by the single-get endpoint and omitted from list responses. null for a redacted version.
content_size_bytesintegerVersion content size in bytes.
content_sha256stringSHA-256 of the version content.
operationstringOperation that produced the version: created, updated, or deleted.
redactedbooleanWhether the version is redacted.
redacted_atstring/nullRedaction time, or null if not redacted.
created_atstringVersion creation time in RFC 3339 format.

Memory Store mount object

A mount record on an (identity, template) pair.
{
  "memory_store_id": "memstore_00mc7mukn7lkxr454tjd",
  "identity_id": "idn_63ee28747a35cff93771c491",
  "template_id": "tmpl_eb3377fb74ad413e17b3d755",
  "access": "read_only",
  "system_managed": false,
  "name": "team-a",
  "status": "active",
  "entry_count": 12,
  "created_at": "2026-08-14T10:00:00Z"
}
FieldTypeDescription
memory_store_idstringID of the mounted Memory Store.
identity_idstringIdentity that owns the mount.
template_idstringTemplate that owns the mount.
accessstringread_write or read_only. See the access rules below.
system_managedbooleantrue for the default Store slot created automatically by the system.
namestringDisplay name of the mounted Store, taken from the Store entity. Best effort: an empty string if the Store cannot be read.
statusstringStatus of the mounted Store (active or archived), taken from the Store entity. Best effort: an empty string if the Store cannot be read.
entry_countintegerNumber of Memory entries in the mounted Store, taken from the Store entity. Best effort: 0 if the Store cannot be read.
created_atstringMount creation time in RFC 3339 format.

Access rules and mount limits

RuleDescription
Only writable StoreThe system-managed default Store (system_managed=true) is the only Store injected into a Session with read_write.
Explicit-mount accessUser-mounted Stores always use read_only. The Agent can read but cannot write to them.
Mount limitAn (identity, template) pair can have at most 10 explicit mounts, excluding the default slot.
List orderThe default Store is first; explicit mounts follow in ascending mount-time order.
Forward enforces exactly one writable Store because the upstream query that selects a write target has no deterministic ordering when multiple writable Stores are mounted.

Visibility in a Session

When a Session is created, Forward injects all active mounts for its (identity, template) pair into the Session resources. Memories from all Stores are merged by path into a flat namespace in the sandbox:
/data/.qoder/awareness/<memory.path>
The sandbox does not expose the memory_store or mem_ hierarchy, so the Agent reads files directly by path. The same path in multiple Stores can shadow another entry. Shadowing order is stable based on mount creation time but is not intuitive, so use distinct path prefixes for different Stores.
Not loaded in self-hosted Environments: When a Session runs in a self-hosted Environment (config.type=self_hosted), Forward does not inject any Memory Store into the Session. Mount relationships are unaffected: mount APIs continue to return normally, and Stores and entries remain available through the Memory Store APIs. The Agent simply cannot see these Memories in the sandbox. To make Memories available to the Agent, run the Session in a managed (cloud) Environment.
Memory Store data structures - Qoder