Tenant Write & Retrieval Operations
The remaining tenant-addressed operations: extraction-gated writes, two retrieval variants, summarization, deletion, and prompt composition — all addressing tenant and user explicitly in the body.
Add Memory (tenant-addressed)
The tenant-addressed sibling of Add Memory. Every input runs through fact extraction, and only the durable facts it contains are stored, as memories with their own ids. Extraction is asynchronous, so the response confirms the write rather than listing what was stored. Nothing stores the raw input as a memory: to send one conversation turn use Add Conversation Turn, and to keep a transcript your code reads back use Conversation History & State.
| Field | Type | Contract |
|---|---|---|
tenant_id | string | Required tenant identifier. |
user_id | string | Required end-user identifier. |
text | string | The raw input. Provide exactly one of text or messages — never both. |
messages | object[] | Conversation transcript as {role, content} turns. Provide exactly one of text or messages. |
source | string | Optional origin label: chat, event, or file. Defaults to chat. |
metadata | object | Optional metadata persisted with each stored candidate. |
{"memory_id":null,"status":"processing","processing_status":"pending","memory_ids":null,"candidates_extracted":null,"candidates_discarded":null,"candidates_stored":null,"candidates_updated":null,"candidates_deduped":null,"candidates_rejected":null,"deduplicated_against":null,"reason":null,"request_id":"9f3a51c0e2d84b7a"}
statusisprocessingwhile the facts are extracted, oracceptedwhen extraction already ran.memory_id,memory_idsand thecandidates_*counts arenull, because the response is sent before extraction finishes.- The extracted memories get their own ids and appear in List Memories shortly after;
request_idcorrelates the extraction. Input with nothing worth keeping stores nothing. - Requires an API key whose scopes allow writes; the key must belong to the organization that owns the tenant.
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",project_id=os.environ["MEMORYSYNC_PROJECT_ID"],end_user_id="usr_7f3a9c2e",)# No dedicated SDK method — call over HTTPS from your backend.
Query Memory (tenant-addressed)
Ranked semantic retrieval scoped by explicit tenant and user. Returns records; use Retrieve below when you want a prompt-ready block instead.
| Field | Type | Contract |
|---|---|---|
tenant_id | string | Required tenant identifier. |
user_id | string | Required end-user identifier. |
prompt | string | Required natural-language query. |
k | integer | Optional result ceiling, 1–100. Defaults to 8. |
rerank | boolean | Optional. The rerank pass defaults to on; set false to bypass it. |
weights | object | Optional custom ranking weights {semantic, recency, importance}; values 0–1, normalized server-side. |
summaries_only | boolean | Optional. Return only summary memories. Defaults to false. |
{"memories":[{"memory_id":"m_311","tenant_id":"acme","user_id":"usr_7f3a9c2e","source":"chat","raw_text":"Prefers the aisle seat on long-haul flights.","summary":null,"metadata":null,"created_at":"2026-08-22T10:00:04Z","score":0.87,"importance":0.6}],"latency_ms":41.7}
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",project_id=os.environ["MEMORYSYNC_PROJECT_ID"],end_user_id="usr_7f3a9c2e",)# No dedicated SDK method — call over HTTPS from your backend.
Retrieve Context (tenant-addressed)
The simpler retrieval sibling: a fixed deterministic ranker (semantic 0.5 / recency 0.3 / importance 0.2 with a 30-day staleness penalty), semantic dedup, and a pre-built context block you can place straight into a prompt.
| Field | Type | Contract |
|---|---|---|
tenant_id | string | Required tenant identifier. |
user_id | string | Required end-user identifier. |
query | string | Required natural-language query. |
top_k | integer | Optional result ceiling, 1–8 (hard cap 8). Defaults to 5. |
token_budget | integer | Approximate token ceiling for the rendered context block, 100–4000. Defaults to 800. |
{"memories":[{"memory_id":"m_311","type":"preference","key":null,"value":"Prefers the aisle seat on long-haul flights.","score":0.79,"semantic":0.88,"recency":0.71,"importance":0.6,"staleness_penalty":0.0}],"context":"- Prefers the aisle seat on long-haul flights.","candidate_count":14,"selected_count":1,"latency_ms":38.2,"query_hash":"q_ab12"}
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",project_id=os.environ["MEMORYSYNC_PROJECT_ID"],end_user_id="usr_7f3a9c2e",)# No dedicated SDK method — call over HTTPS from your backend.
Summarize Memories (tenant-addressed)
Collapse the user's most recent raw memories into one summary row. Counts as one add.
| Field | Type | Contract |
|---|---|---|
tenant_id | string | Required tenant identifier. |
user_id | string | Required end-user identifier. |
threshold | integer | Minimum raw (non-summary) memories required, and the number summarized. Defaults to 5; a 400 is returned when fewer exist. |
{"summary_id":"m_340","summary_text":"Travel preferences: aisle seat, morning departures.","child_memory_ids":["m_311","m_312","m_318","m_322","m_325"]}
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",project_id=os.environ["MEMORYSYNC_PROJECT_ID"],end_user_id="usr_7f3a9c2e",)# No dedicated SDK method — call over HTTPS from your backend.
Forget Memories (tenant-addressed)
Delete specific memories with an audit-log entry (GDPR-supporting). Unlike the header-scoped `DELETE /memory/forget`, this variant is a POST that addresses tenant and user in the body. Like every delete route, it needs an API key that can delete memories (the memories:delete scope).
| Field | Type | Contract |
|---|---|---|
tenant_id | string | Required tenant identifier. |
user_id | string | Required end-user identifier. |
memory_ids | string[] | Required memory IDs to delete (the m_… form returned by writes and queries). |
{"deleted_ids":["m_311","m_312"],"audit_log_id":9021}
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",project_id=os.environ["MEMORYSYNC_PROJECT_ID"],end_user_id="usr_7f3a9c2e",)# No dedicated SDK method — call over HTTPS from your backend.
Compose Prompt (tenant-addressed)
Recall relevant memories and fill your {context} template placeholder within a token budget — the tenant-addressed sibling of Compose Prompt.
| Field | Type | Contract |
|---|---|---|
tenant_id | string | Required tenant identifier. |
user_id | string | Required end-user identifier. |
prompt_template | string | Required template containing a {context} placeholder. |
recall_k | integer | Optional memories to recall, 1–100. Defaults to 8. |
token_budget | integer | Context token ceiling, 100–16000. Defaults to 4000. |
{"composed_prompt":"You know this about the user:\n- Prefers the aisle seat…\n\nUser: Book me a flight","memories_used":3,"token_count":214,"truncated":false}
import osfrom memorysync import MemorySyncClientclient = MemorySyncClient(api_key=os.environ["MEMORYSYNC_API_KEY"],base_url="https://api.memorysync.io",project_id=os.environ["MEMORYSYNC_PROJECT_ID"],end_user_id="usr_7f3a9c2e",)# No dedicated SDK method — call over HTTPS from your backend.
Quota behaviour
Errors and next action
A 422 means a missing or contradictory field (for add: provide exactly one of text or messages). A 403 means the API key cannot act for that tenant or lacks the required scope: forget needs memories:delete, and writes need write scope. A 400 from summarize means fewer than threshold raw memories exist. For 429 or 5xx, retry writes with the same payload after a delay.