The mental model
Ingest is asynchronous by default. Extraction is LLM-bound — typically 3–10 seconds — so the API returns a job immediately and does the work in the background. Your code polls or opts into sync mode.Required fields
Every ingest needs:messages— array of{ role, content }. Empty array → 400.user_id— keys the per-user session namespaceconv_id— anchors every extracted memory to a conversation (for replay, export, bulk retract)
agent_id, app_id, group_ids (tag the extracted memories to shared groups — memories judged personal, e.g. health or finances, are never group-tagged), timestamp_format (a strptime format for parsing dated turns on the batch path), extract_artifacts (defaults to true — pass false to skip the artifact-extraction stage, the most expensive part of the pipeline).
Async ingest (default)
Sync ingest (wait: true)
Useful for demos, one-shot scripts, or any code where you want the result inline:
succeeded or failed). If the budget elapses, you get a pending/running job back and have to poll — same as async mode.
What gets extracted
You pass messages; you don’t pre-decide what’s a fact vs an artifact vs an episode. The server’s extraction pipeline decides:
The
result.memories_created array tells you what landed; each entry is a thin reference ({id, type, text}). For the full row, call client.memories.get(id).
Tagging memories to groups
Passgroup_ids to associate this ingest with one or more groups — shared tagging targets you register up front (see Groups). At extraction time a classifier tags each extracted memory: prompted groups get the memories their prompt matches, and catch-all groups (registered without a prompt) get every shareable memory. Other members of the group can then surface those memories with a group search.
- The classifier tags each extracted memory with the subset of
group_idsit belongs to — a memory can land in several groups, one, or none. Untagged extraction still happens as usual; tagging is additive. - Memories judged personal (private/sensitive: health, family matters, finances, credentials) are never group-tagged — they stay in the author’s personal scope, fully retrievable there. See the personal gate.
- Unknown or archived ids are soft-skipped — they never fail the ingest, and come back in
result.ignored_group_idsso you can prune stale ids client-side. - Up to 20 group ids per ingest; more returns
422.
Failure modes
Extraction can fail for various reasons — upstream LLM hiccup, content that doesn’t yield extractable facts, rate limits. The job lands instatus: "failed" with an error.code and error.message. Retry by submitting the same body again; we don’t auto-retry server-side.
Common failure codes:
See also
- Searching memories — query what you just ingested
- API Reference → Memories → Ingest — full request/response schemas