---
title: "Primitive Memories"
description: "Store durable JSON key-value state for agents and Functions with org and function scope, TTLs, version checks, search, and usage billing."
canonical: "https://docs.primitive.dev/docs/memories"
last-updated: "2026-05-17T00:00:00.000Z"
---

# Primitive Memories

Primitive Memories are durable JSON key-value records for agent state. Use them when an agent or Function needs to remember compact structured state across turns, emails, retries, or process restarts without bringing its own database.

Common uses:

- Remember the last processed email or thread id.

- Persist workflow checkpoints such as `{ "step": 2 }`.

- Share small org-scoped state across tools or agents.

- Keep Function-local state scoped by immutable Function id.

- Coordinate retries with `if_absent` or `if_version`.

Memories are not a replacement for bulk storage or document search. Values are JSON, keys are caller-defined strings, and search is by key prefix.

## Scopes

Every memory belongs to exactly one organization. Within that organization it is resolved under one of two scopes:

ScopeUse it forHow to select itOrgState shared by the organization.Default for normal API, SDK, and CLI calls.FunctionState private to one Primitive Function.Pass a Function id UUID, not a function name.

When a request is already authenticated as a Function, Primitive uses that Function id automatically. Outside a Function, pass an explicit function scope (CLI users can pass `--function <function-id>`). A Function scope is available only to that Function's own credential, to an org-wide API key that can manage the Function, or to a person that can manage the Function. Other credentials, such as narrowed keys, connected agent keys and agent signup tokens, get `403 forbidden`.

Function names are mutable and are never accepted as scope identifiers.

## CLI

Use the `primitive memories` commands for terminal and agent workflows:


```
primitive memories set thread:latest '{"email_id":"em_123"}'
primitive memories get thread:latest
primitive memories search thread: --metadata-only
primitive memories delete thread:latest
```


Values must be valid JSON. Strings must be quoted as JSON strings:


```
primitive memories set greeting '"hello"'
```


Function-scoped memories:


```
primitive memories set state '{"step":2}' --function <function-id>
primitive memories get state --function <function-id>
primitive memories search state: --function <function-id>
primitive memories delete state --function <function-id>
```


Read a value from a file:


```
primitive memories set agent:state --value-file ./state.json
```


## REST API

All endpoints live under `https://api.primitive.dev/v1` and use the standard Primitive bearer auth header.

Set a memory:


```
curl -X PUT https://api.primitive.dev/v1/memories \
  -H "Authorization: Bearer $PRIMITIVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key":"thread:latest","value":{"email_id":"em_123"}}'
```


Get a memory:


```
curl "https://api.primitive.dev/v1/memories?key=thread:latest" \
  -H "Authorization: Bearer $PRIMITIVE_API_KEY"
```


Search by key prefix:


```
curl "https://api.primitive.dev/v1/memories/search?prefix=thread:&include_value=false" \
  -H "Authorization: Bearer $PRIMITIVE_API_KEY"
```


Delete a memory:


```
curl -X DELETE "https://api.primitive.dev/v1/memories?key=thread:latest" \
  -H "Authorization: Bearer $PRIMITIVE_API_KEY"
```


Function scope over REST:


```
curl -X PUT https://api.primitive.dev/v1/memories \
  -H "Authorization: Bearer $PRIMITIVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "state",
    "value": { "step": 2 },
    "scope": { "type": "function", "id": "<function-id>" }
  }'
```


For get, delete, and search, use query scope:


```
curl "https://api.primitive.dev/v1/memories?key=state&scope_type=function&scope_id=<function-id>" \
  -H "Authorization: Bearer $PRIMITIVE_API_KEY"
```


## SDKs

In Node.js, use the high-level client:


```
import { createPrimitiveClient } from '@primitivedotdev/sdk/api';


const client = createPrimitiveClient({
  apiKey: process.env.PRIMITIVE_API_KEY,
});


await client.memories.set({
  key: 'thread:latest',
  value: { email_id: 'em_123' },
});


const memory = await client.memories.get('thread:latest');


const page = await client.memories.search({
  prefix: 'thread:',
  includeValue: false,
});


await client.memories.delete('thread:latest');
```


Function-scoped writes pass `scope: { type: 'function', id: '<function-id>' }`. Function-scoped reads, deletes, and searches pass `scope_type: 'function'` and `scope_id: '<function-id>'`.

`client.memories.search` is key prefix search, not free-text or semantic search. Use `client.semanticSearch(...)` for mail search. The generated SDK clients still expose lower-level OpenAPI operation ids `setMemory`, `getMemory`, `deleteMemory`, and `searchMemories` for callers that need the exact REST operation shape.

## JSON and Limits

Values can be any valid JSON value:

- object

- array

- string

- number

- boolean

- `null`

Limits:

FieldLimitKey512 UTF-8 bytesValue65,536 UTF-8 bytes after JSON serializationSearch page size1 to 100, default 50TTL1 second to 31,536,000 seconds

The API rejects values that do not serialize as JSON.

## Metadata and Versions

Memory records include metadata agents can use for coordination:

FieldMeaning`id`Stable memory record id.`key`Caller-defined key.`scope`Resolved org or function scope.`value`JSON value, omitted when search uses `include_value=false`.`version`Monotonic version serialized as a string.`created_at` / `updated_at`Creation and last write timestamps.`last_read_at`Last read timestamp, or `null`.`read_count` / `write_count`Counters serialized as strings.`expires_at`Expiration timestamp, or `null`.`created_by` / `updated_by`Actor that created or last updated the record.

Use `version` with compare-and-set when multiple workers may update the same key.

## TTLs

Set an expiration with `ttl_seconds` or `expires_at`:


```
curl -X PUT https://api.primitive.dev/v1/memories \
  -H "Authorization: Bearer $PRIMITIVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key":"lock:agent","value":{"owner":"agent-1"},"ttl_seconds":300}'
```


On update, existing TTL is preserved unless you pass `ttl_seconds`, `expires_at`, or `clear_ttl`.

## Version Checks

Create only if the key is absent:


```
primitive memories set lock '{"owner":"agent-1"}' --if-absent
```


Update only if the current version matches:


```
primitive memories set state '{"step":3}' --if-version 2
```


Delete only if the current version matches:


```
primitive memories delete state --if-version 3
```


Stale version checks return `409 memory_conflict`.

## Search

Search lists active memories in lexicographic key order by prefix:


```
primitive memories search thread: --limit 100 --metadata-only
```


REST search parameters:

ParameterDescription`prefix`Key prefix to match. Omit to list all active memories in scope.`cursor`Continuation cursor from `meta.cursor`.`limit`Page size, 1 to 100, default 50.`include_value``true` or `false`, default `true`.`updated_after`Only include memories updated at or after this timestamp.`updated_before`Only include memories updated at or before this timestamp.`scope_type` / `scope_id`Optional scope selection.

Use `include_value=false` when an agent only needs keys and metadata.

## Billing

Primitive Memories are metered through the same usage billing system as the rest of Primitive:

- `memory.storage.gb_day` for stored memory size over time.

- `memory.read` for get and search operations.

- `memory.write` for set and delete operations.

On Developer, billable actions draw from the monthly usage credit grant and can return `402 developer_usage_credit_exhausted` when credits are exhausted. Paid plans accrue usage overage instead of stopping at monthly credits. See [Pricing](/pricing) and [Limits & Quotas](/docs/limits).

## Related Pages

- [CLI](/docs/cli): `primitive memories` terminal commands.

- [SDKs](/docs/sdks): generated client imports and examples.

- [REST API](/docs/api): OpenAPI discovery, auth, and envelope shape.

- [Functions](/docs/functions): hosted JavaScript handlers that can use function-scoped Memories.

Maintained by the [primitive.dev team](/about) · [Trust & security](/trust)Last updated: May 17, 2026
