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.
The upstream hard limit is 16 keys. Forward injects
Valid examples:
When the Agent writes a Memory, it replaces the entry metadata with
A mount record on an
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.
When a Session is created, Forward injects all active mounts for its
The sandbox does not expose the
| Level | ID prefix | Description |
|---|---|---|
| Memory Store | memstore_ | Container for Memories. It does not store content directly and can be mounted to an (identity, template) pair. |
| Memory | mem_ | A Memory in a Store, identified by a relative path and containing the actual content. |
| Memory Version | memver_ | Immutable snapshot produced automatically whenever a Memory is created, updated, or deleted. |
Memory Store object
| Field | Type | Description |
|---|---|---|
id | string | Memory Store ID with the memstore_ prefix. |
type | string | Always memory_store. |
name | string | Store display name. |
description | string | Store description. |
status | string | active or archived. |
entry_count | integer | Number of Memory entries in the Store. |
total_size | integer | Total size of all Memory content in bytes. |
metadata | object | Metadata. Always includes the server-injected created_by=forward. |
system_managed | boolean | true 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_id | string/null | Identity that owns a system-managed default Store. null for a user-created Store. |
created_at | string | Creation time in RFC 3339 format. |
updated_at | string | Last update time in RFC 3339 format. |
archived_at | string/null | Archive time, or null if active. |
binding_info.identity_template_count | integer | Number of (identity, template) pairs currently mounting the Store. Archive and delete operations check this value. |
Store metadata constraints
| Constraint | Value |
|---|---|
| Maximum keys | 15 |
| Key length | 1–64 characters |
| Value type | Must be a string |
| Value length | Up to 512 characters |
| Reserved key | created_by is injected by the server as "forward"; supplying it returns 400 |
created_by, which uses one slot, so callers can supply 15 keys.
Memory object
| Field | Type | Description |
|---|---|---|
id | string | Memory ID with the mem_ prefix. |
type | string | Always memory. |
memory_store_id | string | Parent Memory Store ID. |
path | string | Case-sensitive relative path in the Store. |
content | string/null | Plain-text UTF-8 content. Returned only by create, update, and single-get endpoints; omitted from list responses. |
content_size_bytes | integer | Content size in bytes. |
content_sha256 | string | SHA-256 of the content. It can be used for optimistic concurrency control. |
metadata | object | Metadata. |
created_at | string | Creation time in RFC 3339 format. |
updated_at | string | Last update time in RFC 3339 format. |
Path constraints
| Constraint | Value |
|---|---|
| Must be relative | Cannot start with / |
| Maximum length | 1,024 bytes |
| Maximum segments | 58 |
| Segment length | Up to 255 bytes |
| Disallowed segments | Empty segments, ., .., or segments with leading or trailing whitespace |
| Disallowed characters | \ and NUL |
| Case sensitivity | Case-sensitive |
notes/meeting-2026-08-14.md, config.yaml
Invalid examples: /notes/meeting.md, a/../b, notes//x.md
Content constraints
| Constraint | Value |
|---|---|
| Encoding | Plain-text UTF-8, not base64 |
| Maximum size | 100 KiB, measured from the raw request bytes |
| Control characters | Non-printable control characters (U+0000–U+001F and U+007F) are not allowed, except newline \n, carriage return \r, and tab \t |
Memory metadata constraints
| Constraint | Value |
|---|---|
| Maximum keys | 16 |
| Key length | 1–64 characters |
| Value type | Must be a string |
| Value length | Up to 512 characters |
| Reserved keys | None. Forward does not inject created_by for entries. Callers may use that key, and its value is stored and returned unchanged. |
{"source":"agent"}. Normal Agent activity can therefore clear metadata set through this API.
Memory Version object
| Field | Type | Description |
|---|---|---|
id | string | Memory Version ID with the memver_ prefix. |
type | string | Always memory_version. |
memory_store_id | string | Parent Memory Store ID. |
memory_id | string | Parent Memory ID. |
path | string | Memory path captured by this version. |
content | string/null | Version content. Returned only by the single-get endpoint and omitted from list responses. null for a redacted version. |
content_size_bytes | integer | Version content size in bytes. |
content_sha256 | string | SHA-256 of the version content. |
operation | string | Operation that produced the version: created, updated, or deleted. |
redacted | boolean | Whether the version is redacted. |
redacted_at | string/null | Redaction time, or null if not redacted. |
created_at | string | Version creation time in RFC 3339 format. |
Memory Store mount object
A mount record on an (identity, template) pair.
| Field | Type | Description |
|---|---|---|
memory_store_id | string | ID of the mounted Memory Store. |
identity_id | string | Identity that owns the mount. |
template_id | string | Template that owns the mount. |
access | string | read_write or read_only. See the access rules below. |
system_managed | boolean | true for the default Store slot created automatically by the system. |
name | string | Display name of the mounted Store, taken from the Store entity. Best effort: an empty string if the Store cannot be read. |
status | string | Status of the mounted Store (active or archived), taken from the Store entity. Best effort: an empty string if the Store cannot be read. |
entry_count | integer | Number of Memory entries in the mounted Store, taken from the Store entity. Best effort: 0 if the Store cannot be read. |
created_at | string | Mount creation time in RFC 3339 format. |
Access rules and mount limits
| Rule | Description |
|---|---|
| Only writable Store | The system-managed default Store (system_managed=true) is the only Store injected into a Session with read_write. |
| Explicit-mount access | User-mounted Stores always use read_only. The Agent can read but cannot write to them. |
| Mount limit | An (identity, template) pair can have at most 10 explicit mounts, excluding the default slot. |
| List order | The default Store is first; explicit mounts follow in ascending mount-time order. |
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:
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.