Native Memory API
Native memory records conversations for a peer, derives claims asynchronously,
and returns cited context for later work. The HTTP contract is the semantic
authority for direct HTTP, marrowid==1.0.4 imported as marrow, and
@marrowid/[email protected], and @marrowid/[email protected]. Hosted MCP at
https://mcp.marrow.id and the local marrow mcp compatibility adapter expose
the same memory semantics through the exact 15-tool MCP registry.
These integrations run inside a trusted application process. Keeping the API key in that process protects the credential, but it does not provide prompt-injection isolation for untrusted messages or retrieved text. Treat returned context as data and preserve its status, citations, conflicts, and warnings when another model consumes it.
See the complete machine-readable OpenAPI document.
Credential and scope contract
Every route below accepts only a customer API key in
Authorization: Bearer $MARROW_API_KEY. Browser cookies and CLI session tokens
do not authenticate native memory routes. Workspace, peer, session, claim, and
event identifiers are labels or public handles inside the account selected by
the key; they are not ownership credentials.
| Scope | Minimum use |
|---|---|
memory.write |
Get or create workspace, peer, and session labels; add messages; correct or withdraw claims. |
memory.read |
List and fetch labels, messages, claims, cited context, write events, and queue status. |
Use both scopes for a process that writes a message, polls its event, and then
reads the resulting memory. The current OpenAPI contract admits the default
workspace label.
Lifecycle
- Get or create the workspace, peer, and session labels with
memory.write. - Add one or more peer-attributed messages. The receipt has
status: "processing"and anevent_id. - Poll
GET /v1/workspaces/{ws}/events/{id}withmemory.readuntilEventStatus.statusissucceeded,failed, orquarantined. - After
succeeded, ask for cited evidence or fetch assembled context. A non-ready status is an application outcome, not permission to invent context. - Read the current claim or its history before a user-approved change. Correct
with
PUT; withdraw withDELETE. Send the claim's currenthead_revisionwith either mutation, retain the stable claim id, and inspect history forADD,UPDATE, andDELETEevents.
Exact routes
| Scope | Route | Request | Success response |
|---|---|---|---|
memory.write |
POST /v1/workspaces |
No request fields | Workspace |
memory.read |
POST /v1/workspaces/list |
No request fields | PageWorkspace |
memory.write |
POST /v1/workspaces/{ws}/peers |
LabelUpsertRequest |
Peer |
memory.read |
POST /v1/workspaces/{ws}/peers/list |
No request fields | PagePeer |
memory.read |
GET /v1/workspaces/{ws}/peers/{peer} |
Path labels | Peer |
memory.read |
POST /v1/workspaces/{ws}/peers/{peer}/ask |
AskRequest |
MemoryContext |
memory.read |
GET /v1/workspaces/{ws}/peers/{peer}/context |
Optional session and q query parameters |
MemoryContext |
memory.read |
POST /v1/workspaces/{ws}/peers/{peer}/representation |
No request fields | RepresentationResponse |
memory.write |
POST /v1/workspaces/{ws}/sessions |
LabelUpsertRequest |
Session |
memory.read |
POST /v1/workspaces/{ws}/sessions/list |
No request fields | PageSession |
memory.read |
GET /v1/workspaces/{ws}/sessions/{s} |
Path labels | Session |
memory.write |
POST /v1/workspaces/{ws}/sessions/{s}/messages |
MessagesCreateRequest |
MessagesCreateReceipt |
memory.read |
POST /v1/workspaces/{ws}/sessions/{s}/messages/list |
No request fields | PageMessage |
memory.read |
GET /v1/workspaces/{ws}/sessions/{s}/context |
Required peer; optional q |
MemoryContext |
memory.read |
POST /v1/workspaces/{ws}/claims/query |
ClaimsQueryRequest |
PageClaim |
memory.read |
POST /v1/workspaces/{ws}/claims/list |
ClaimsListRequest |
PageClaim |
memory.read |
GET /v1/workspaces/{ws}/claims/{id} |
Claim id | Claim |
memory.read |
GET /v1/workspaces/{ws}/claims/{id}/history |
Claim id | ClaimHistoryResponse |
memory.write |
PUT /v1/workspaces/{ws}/claims/{id} |
ClaimUpdateRequest |
ClaimUpdateResult |
memory.write |
DELETE /v1/workspaces/{ws}/claims/{id} |
ClaimDeleteRequest |
ClaimDeleteReceipt |
memory.read |
GET /v1/workspaces/{ws}/events/{id} |
Event id | EventStatus |
memory.read |
GET /v1/workspaces/{ws}/queue/status |
Workspace label | QueueStatus |
Message write schemas
MessagesCreateRequest is closed to unknown fields.
| Field | Required | Contract |
|---|---|---|
peer_id |
Yes | Non-empty peer label. |
messages |
Yes | 1 to 100 MessageInput objects. Each has role (user, assistant, system, or tool) and content. |
agent_id |
No | Non-empty agent label. |
infer |
No | Boolean write control. Omit it to use the service default. |
created_at |
No | ISO 8601 date-time for the add event. |
metadata |
No | Application metadata object. The marrow key is reserved and rejected. |
source_ids |
No | Up to 100 succeeded, same-account ingest job IDs. Use public job.id values returned by ingest or job status. |
idempotency_key |
No | Non-empty caller-owned replay key. |
{
"peer_id": "riley",
"messages": [
{
"role": "user",
"content": "Project updates should lead with the decision and keep the open pricing risk visible."
}
],
"infer": true,
"source_ids": ["550e8400-e29b-41d4-a716-446655440000"]
}
MessagesCreateReceipt contains event_id, status, results, authority,
and eligibility. status is processing; it does not mean the derived claim
is ready to read.
Poll the write event
curl -sS "$MARROW_API_BASE_URL/v1/workspaces/default/events/<event-id>" \
-H "Authorization: Bearer $MARROW_API_KEY"
EventStatus contains event_id and one of queued, running, succeeded,
failed, or quarantined. Poll with a bounded interval and deadline. Read
derived memory only after succeeded; surface failed and quarantined
without silently retrying a different write.
Ask and context
POST /v1/workspaces/{ws}/peers/{peer}/ask accepts an AskRequest with required
query plus optional session_id and top_k. Peer context accepts optional
session and q query parameters. Session context requires peer because a
session is subject-partitioned.
All three return MemoryContext:
status:ready,partial,insufficient_evidence,conflicted, orwithheld;contextandmessages: assembled handoff forms;blocks: public text withauthority,state,support_status, and citations;citations:excerpt,source_label,char_offset_start, andchar_offset_end;conflictsandwarnings: visible reasons to narrow, withhold, or request more information.
Use ready or an application-approved partial result only with its cited
support. Treat insufficient_evidence, conflicted, and withheld as
fail-closed outcomes.
Claim changes and history
Fetch a claim before changing it. Claim includes the stable id, content,
peer/session labels, authority, state, eligibility, support_status,
validity times, categories, citations, and the opaque head_revision required
for a guarded change.
Correct the content with:
PUT /v1/workspaces/{ws}/claims/{id}
Content-Type: application/json
{"content":"Project updates should lead with the decision.","head_revision":"rev_VQS3c7WbiwJT_q1bUPQKMzL6t2L8OyvZ65dnp3qGnqA","reason":"User clarified the preference."}
Withdraw it with:
DELETE /v1/workspaces/{ws}/claims/{id}
Content-Type: application/json
{"head_revision":"rev_34mDXjKdEPihJoJXBIbYg4QbHMbmxNT1-vGCAtdHMfk","reason":"The user withdrew this preference."}
The correction receipt returns a successor head_revision and explicitly marks
the corrected head as authority: "correction_memory", state: "current", and
eligibility: "pending_review". Use that successor revision for a later change.
An exact retry is replay-safe; a stale or competing revision returns
409 revision_conflict without mutation.
Then read GET /v1/workspaces/{ws}/claims/{id}/history. History is an array of
entries with event, prior and successor claim text, validity times, and a
deterministic marker. A withdrawn claim remains auditable through history; it
must not reappear as current eligible context.
Negative outcomes
- Missing API key: fail before sending the request.
- Wrong credential class: a browser cookie or CLI session token is rejected.
- Wrong scope: reads require
memory.read; writes requirememory.write. - Revoked or rotated key: replace the host-managed environment value; a stale process must continue to fail until restarted with the current credential.
- Foreign account labels: labels do not cross the key-derived account boundary.
- Unsupported workspace: the current public path admits only
default. - Malformed write: reject missing
peer_id, an empty message array, unknown fields, an unsupported role, or a malformed UUID insource_ids. - Invalid source attachment: reject any
source_idsentry that is missing, belongs to another account, or has not reachedsucceeded; the write creates no event, job, or claim. - Stale claim mutation: reject a missing or stale
head_revision; fetch the current claim and require user approval before retrying against a newer head. - Incomplete processing: do not read derived memory while the event is queued or running, or after it failed or was quarantined.
- Unsupported evidence: preserve
insufficient_evidence, conflicts, warnings, and citations; do not turn retrieved text into privileged instructions.
See App integration for HTTP and Python examples, Marrow CLI for local commands and stdio compatibility, and Quickstart for the source/job/query and hosted MCP paths.