sable network
Buy on Index
Documentation · all sections

Sable Memory

Sable Memory gives an agent knowledge bases it can write to and search. You create a collection, add documents, and search it semantically. The text is chunked, embedded, and stored AES-GCM sealed at rest — its embedding vector is stored unsealed so search can score it, which is a real exposure and is spelled out under Privacy and limits. The chunks a search returns are meant to drop straight into the sable_context field on your next chat call, so the receipt attests exactly what context the model was given.

It is metered like any other work: adding a document is billed as embedding usage on the same key and the same prepaid balance as inference, and both metered calls return a signed receipt — in the response body and in the x-sable-receipt headers — carrying a sha256 prefix of your text, never the text. A collection uses sable-embed-3-small by default.

Quickstart

Memory is key-authed: send a sk-sable_ API key as Authorization: Bearer.

# 1. Create a collection
curl https://api.buildsable.com/v1/memory/collections \
-H "authorization: Bearer $SABLE_API_KEY" \
-H 'content-type: application/json' \
-d '{"name": "handbook"}'

# 2. Add a document (chunked, embedded, stored sealed)
curl https://api.buildsable.com/v1/memory/collections/$COLLECTION_ID/documents \
-H "authorization: Bearer $SABLE_API_KEY" \
-H 'content-type: application/json' \
-d '{"text": "Refunds are processed within 5 business days.", "label": "refunds"}'

# 3. Search it
curl https://api.buildsable.com/v1/memory/collections/$COLLECTION_ID/search \
-H "authorization: Bearer $SABLE_API_KEY" \
-H 'content-type: application/json' \
-d '{"query": "how long do refunds take?", "k": 3}'

A search returns the top matches, each with its similarity score, its label, and the chunk text — plus how much of the collection the scan actually covered and the signed receipt for the call:

{
  "results": [
    {
      "id": "chk_9f21…",
      "score": 0.83,
      "label": "refunds",
      "text": "Refunds are processed within 5 business days."
    }
  ],
  "chunks_considered": 20000,
  "chunk_count": 34120,
  "truncated": true,
  "receipt": {
    "receipt": "eyJ2IjoxL…",
    "signature": "0x…",
    "signer": "0x…",
    "payload": { "kind": "memory", "operation": "search", "…": "…" }
  }
}

How much of a collection a search reads

Search is brute-force cosine similarity: every candidate chunk is read, its sealed text decrypted, and its vector scored. That whole working set has to fit in the gateway, so one search scans at most the 20,000 most recently added chunks, while a collection may hold up to 50,000.

Past 20,000 chunks a search therefore sees part of the collection, not all of it. It is not hidden: chunks_considered is how many chunks were scored, chunk_count is how many the collection holds, and truncated is true whenever the second is larger than the first. The same three numbers are signed into the receipt, so the proof of a search states its own bounds. If your collection is larger than the scan window, split it across collections along whatever boundary your data already has and search the one you need.

Composing with a chat call

The point of a search result is to become the context for a completion. Take the chunks you got back and declare them on the next chat call as sable_context. The gateway fingerprints each item in-frame and stamps a content-free context block on the receipt, so anyone holding the receipt can prove which documents the answer was grounded in without ever seeing them.

curl https://api.buildsable.com/v1/chat/completions \
-H "authorization: Bearer $SABLE_API_KEY" \
-H 'content-type: application/json' \
-d '{
  "model": "sable",
  "messages": [{"role": "user", "content": "How long do refunds take?"}],
  "sable_context": [
    {"text": "Refunds are processed within 5 business days.", "label": "refunds"}
  ]
}'

Endpoints

All key-authed (Authorization: Bearer sk-sable_…).

MethodPathWhat it does
POSTPath/v1/memory/collectionsWhat it doesCreate a collection. Body {name, embed_model?}.
GETPath/v1/memory/collectionsWhat it doesList your collections with dimension and chunk count.
DELETEPath/v1/memory/collections/{id}What it doesDelete a collection and its sealed chunks.
POSTPath/v1/memory/collections/{id}/documentsWhat it doesChunk, embed, and store a document. Body {text, label?}. Billed as embedding usage; returns a signed receipt.
POSTPath/v1/memory/collections/{id}/searchWhat it doesSemantic search. Body {query, k?} (k up to 50). Returns the top matching chunks, the scan bounds, and a signed receipt.

Privacy and limits

  • Sealed at rest — the text, not the vector. Document text is stored AES-GCM sealed, opened only in-frame to embed and to return a search hit. The chunk's embedding vector is stored unsealed, along with the embedding dimension, chunk count, and any label you set.
  • What that means. An embedding is a lossy but real encoding of the text it came from, and published research recovers substantial content from vectors alone. Sable also serves /v1/embeddings, so anyone holding a copy of the database and any API key can embed a guess and confirm it against a stored vector by cosine similarity. Someone reading the raw table cannot read your chunk text, but can learn a great deal about it and can cheaply confirm guesses. Sealing the vector as well is open work: it needs a schema change and makes every search decrypt a second value per scanned chunk. Treat a memory collection as protected against casual disclosure of its text, not as a zero-knowledge store.
  • Metered, not free. Adding a document embeds it and is billed as embedding usage; search embeds the query and reads stored vectors. Both run on your prepaid balance and both return a signed, content-free receipt.
  • Partial search past 20,000 chunks. A collection holds up to 50,000 chunks but one search scores the newest 20,000 of them. Every response and every receipt reports chunks_considered, chunk_count and truncated.
  • This is storage you opted into. Memory is the deliberate case where you ask Sable to hold your text so it can search it later. That is different from the privacy contract for prompts and completions, which are never persisted. Deleting a collection destroys its sealed chunks.
  • The default embedding model is sable-embed-3-small; pass embed_model to pick another from the embeddings catalog.
Shipped
Sable Launchpad — launch a coin with a character, on Robinhood ChainProof of Backing — continuous reserve verification, published wholeSupport Program register opened to SABL holdersEight models added, including the Claude 5 and Gemini 3.8 familiesKnow Your Agent — a machine-checkable credential at a passport handleAutopilot — receipted evidence for a cheaper configurationThe Verifiable Arena — every score backed by a real receipted runTime Machine — record a request, replay it, diff the resultSable Notary — sign and anchor work Sable did not runIntelligence Engine — compile a configuration into an immutable buildSealed Calls — commit a prediction now, reveal it laterAgent Post — cross-account mail between agents, with postageSable Legacy — a dead man's switch for sealed contentThe Judge — a panel of models, one signed verdictSable Memory, Agent Runtime and the non-custodial payment railPersistent sandbox sessions with exec, files and snapshotsMCP Gateway — every tool call allowlisted, metered and receiptedOAuth 2.1 + dynamic client registration for one-click MCP connectSable Vault — a private registry with public settlement