Skip to main content
Requires Python 3.10 or newer.

Client initialization

The client does not read an environment variable automatically. Pass api_key explicitly:
Use it as a context manager so connections close cleanly:

Methods

Every method also has an async_-prefixed counterpart — see Async support.

record

Pass background=True to queue the write instead of waiting. The call then returns a job rather than a stored memory; poll it with get_job.
background=True is about ten times faster, and should be your default. A blocking write waits for a language model to extract facts from the text before it returns. Measured against production, 12-17 seconds versus 1-3 seconds queued. Use a blocking write only when you search for the memory immediately afterwards.
user_id, agent_id and session_id scope the memory inside the space, so only a retrieve carrying the same scope sees it. That is how one space serves many end users. See Scoping. timestamp is when the event happened, not when you are recording it. Set it when importing history so a memory about last June is dated last June. See Searching over time.
A user id passed in metadata is stored but isolates nothing: metadata is returned with results, never filtered on. Use the user_id argument.

retrieve

as_of restricts the search to memories recorded at or before an instant, so you get what the space knew then. query_timestamp moves the “now” that recency scoring and relative dates in the query are measured against, and never removes a result. See Searching over time. Returns the results list directly, and an empty list when nothing matches. A scoped search is strict: it never returns another user’s memories, nor memories stored without a scope. mode="fast" skips the neural rerank pass for lower latency, at some cost to relevance quality. See Latency modes.

retrieve_receipt, get_receipt and explain

retrieve returns a plain list, which has nowhere to carry the id of the receipt for that search. retrieve_receipt is the same search and returns both.
The result iterates and indexes like the list retrieve returns, so len(res), res[0] and for row in res all work and swapping one method for the other rarely means changing the code around it. receipt_detail="full" also asks the search to account for its own cuts, so the receipt can explain memories that were ranked and dropped before limit or a relevance floor ever applied. It can cost latency on the first call for a given query. Leave it "basic" for production traffic. explain answers the question the receipt cannot: why one specific memory is not in your results.
not_retrieved is the one to act on: nothing matched the memory at all, so a bigger limit or a lower floor will not bring it back, and the query wording or the scope you searched is what to change. arms shows which kind of matching found it, and how well: found by keyword but not semantic usually means your query shares words with the memory but not meaning. Every search builds a receipt whether or not you asked for one, so get_receipt and explain also work on a request id you pulled from your own logs. See Context receipts.

reason

Returns the synthesized answer string, or None.

get_user_profile and ask_about_user

Everything a space has learned about one end user, and a question answered from that user’s memories only. Both need user_id to be the same value your writes are scoped with.
ask_about_user returns the whole response rather than the answer string, so model is available: that is the model which actually answered, and what the credits on the call were charged at. It differs from what you asked for whenever you asked for nothing. A user_id nobody has recorded under is not an error: it comes back with memory_count of 0 and an empty memories list, because a user is a scope tag created by the first write naming it rather than a resource you register. An unknown space is still a 404. memory_count can also go down between two reads, since consolidation folds several raw facts into one note and the default view counts the note. Read it as how many distinct things are currently known about this user, not as an ingestion counter. See User profiles.

list_spaces

upload_file

Uploads a file into a space so retrieval can draw on its content. file may be a path, bytes, or a binary file-like object. Ingestion is asynchronous and returns {"job_ids": [...]}; poll each with get_job. Files over 25 MB are rejected client-side, before upload.
Supported formats are PDF, DOCX, DOC, PPTX, PPT, XLSX, XLS, HTML, TXT, Markdown, CSV, JPEG/PNG images, MP3/WAV audio and MP4/MOV/WEBM/MKV video. Images, audio and video are read into text. See Documents.

list_documents and delete_document

Async support

Every method has an async_ counterpart, backed by a separate httpx.AsyncClient.
Use async with AnonaClient(...) as client: for automatic cleanup.

Error handling

See the error reference for every code and which are safe to retry.

Framework adapters

If you already build on an agent framework, you do not need to call record and retrieve yourself. Each adapter wires recall and storage into that framework’s own memory seam, and scopes memories per end user. A complete runnable script for each one is on the Examples page. All six share one MemoryBridge, which resolves scope and owns the failure contract:
Memory failures never raise into your agent. A failed recall or store is logged and the agent runs on without memory, rather than taking your application down. This is deliberate and applies to every adapter. See each guide’s Failure behaviour section for what the agent sees instead.

MCP server

The SDK also ships an MCP server for connecting Anona Memory to Claude Code, Claude Desktop, and other MCP clients. See the MCP guide.

Next steps

Framework adapters

LangChain, CrewAI, LlamaIndex, ADK, Agent Framework, Strands.

MCP

Connect Claude Code and other MCP clients.

API overview

The full REST surface.