Saxeo Memory
Saxeo 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 saxeo-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://www.saxeonetwork.tech/__api/v1/memory/collections \
-H "authorization: Bearer $SAXEO_API_KEY" \
-H 'content-type: application/json' \
-d '{"name": "handbook"}'
# 2. Add a document (chunked, embedded, stored sealed)
curl https://www.saxeonetwork.tech/__api/v1/memory/collections/$COLLECTION_ID/documents \
-H "authorization: Bearer $SAXEO_API_KEY" \
-H 'content-type: application/json' \
-d '{"text": "Refunds are processed within 5 business days.", "label": "refunds"}'
# 3. Search it
curl https://www.saxeonetwork.tech/__api/v1/memory/collections/$COLLECTION_ID/search \
-H "authorization: Bearer $SAXEO_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://www.saxeonetwork.tech/__api/v1/chat/completions \
-H "authorization: Bearer $SAXEO_API_KEY" \
-H 'content-type: application/json' \
-d '{
"model": "saxeo",
"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_…).
| Method | Path | What it does |
|---|---|---|
| POST | Path/v1/memory/collections | What it doesCreate a collection. Body {name, embed_model?}. |
| GET | Path/v1/memory/collections | What it doesList your collections with dimension and chunk count. |
| DELETE | Path/v1/memory/collections/{id} | What it doesDelete a collection and its sealed chunks. |
| POST | Path/v1/memory/collections/{id}/documents | What it doesChunk, embed, and store a document. Body {text, label?}. Billed as embedding usage; returns a signed receipt. |
| POST | Path/v1/memory/collections/{id}/search | What 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. Saxeo 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_countandtruncated. - This is storage you opted into. Memory is the deliberate case where you ask Saxeo 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
saxeo-embed-3-small; passembed_modelto pick another from the embeddings catalog.