Ingest memories
Async ingest. Returns 202 + job_id by default; the extraction
runs in the background and the caller polls
GET /v1/memories/jobs/{job_id}.
With ?wait=true the server holds the connection up to ~30
seconds waiting for extraction to terminate. If it finishes in
time, the response is 200 OK with the terminal job inline
(status: "succeeded" or "failed"). If the wait window
elapses first, the response falls back to 202 + pending and
the caller resumes the normal polling pattern.
Authorizations
Long-lived org API key. Alternative: Authorization: Bearer <key>.
Query Parameters
When true, hold the connection up to ~30s waiting for extraction to terminate. Returns 200 + terminal job inline on success; falls back to 202 + pending on timeout. Default false → 202 + pending immediately.
Body
POST /v1/memories — async ingest from a message list.
Required entities: user_id and conv_id. user_id scopes
a user's per-user memory namespace, so a user's facts accumulate in
one place rather than fragmenting per-conversation. conv_id
anchors every extracted memory to a conversation for replay, export,
and bulk retract. agent_id and app_id remain optional — set
either, both, or neither. There is no auto-default app_id rule.
extract_artifacts opts in to the artifact-extraction stage
(off by default — the most expensive stage and most callers don't
need it). Episodes are always extracted (conv_id is
guaranteed). Facts are always extracted.
There is no client-facing pipeline hint: the server selects its extraction strategy automatically based on the number of messages.
outcome is the caller's capture-time verdict on this trajectory
("resolved" / "failed"). Pass it only when a real verdict exists — a
harness or CI result, an explicit confirmation. It stamps
source_outcome on extracted directive memories (lessons /
procedures) only: "failed" content is retained but never served as
advice; "resolved" earns confident voice. When in doubt leave it
unset — an unstamped directive serves hedged and can be confirmed
later.
Chat-style turns to extract memories from. Must be non-empty — an empty list returns 400 invalid_messages (the route raises this explicitly so the wire error carries the stable code rather than a generic Pydantic validation message). Server picks live vs batch extraction by length; no client-facing strategy hint.
User identifier. REQUIRED. Keys the per-user session namespace so a user's facts accumulate across their conversations rather than fragmenting per-conv. Also stored as an indexed filter axis on every row.
1"alice"
Conversation identifier. REQUIRED. Anchors every extracted memory to a conversation for replay, export, and bulk retract.
1"conv-2026-05-15-abc"
Capture-time verdict for this trajectory; stamps directive memories only. Omit unless a real verdict exists (wrong 'resolved' turns dead-end advice confident; wrong 'failed' buries a good approach).
resolved, failed Optional agent scope. Indexed alongside the other entity ids.
Optional app scope. Indexed alongside the other entity ids.
Optional strptime format string used to parse each message's date field into a real timestamp on the batch-extraction path (e.g. "%Y-%m-%d %H:%M:%S"). When omitted, or when a date value fails to parse, the turn keeps its raw date string with no parsed timestamp. Only consulted on the batch path (message count above the live threshold); the live path ignores it.
"%Y-%m-%d %H:%M:%S"
When true, extracted artifacts are also stored and returned as artifact memories, in addition to fact + episode extraction. Off by default — most expensive stage and most callers don't need it. Routing (live vs batch) is unaffected and still chosen by message count.
When true, ingest through the agentic (task-aware) path: recall-first extraction + a Stage-2 noise filter + agentic artifact detection + a structured session gist. Intended for tool-using / coding-agent transcripts. Off by default (conversational extraction).
Namespace this session belongs to — the working context, e.g. a coding agent's repo, a support agent's customer account, an ops agent's service. Captured lesson/procedure directives are written under it, so recall with the same namespace (see POST /v1/memories/trigger) surfaces them there instead of in every context. Directives ingested without one are global. Unrelated to the tenancy axes (user_id/agent_id/group_ids).
256"MemHub-Backend"
Optional list of group ids the client wants associated with this ingest. Each id must be a registered group on the org (see POST /v1/groups). Ids that are unknown or archived are dropped silently and echoed back in result.ignored_group_ids — a single stale id will not fail the ingest, since the chat path tolerates partial tagging better than a hard reject. After extraction, a classifier judges each memory personal-vs-shareable: personal memories are never group-tagged (they stay in the author's personal scope); shareable memories are tagged with every prompt-less (catch-all) group in the valid subset, plus whichever prompted groups the classifier matched. Tagged rows become reachable via filters: {group_ids: <id>} on search. The capped length is MAX_GROUP_IDS_PER_INGEST.
Response
Inline terminal response. Returned when ?wait=true is set and the extraction pipeline completes inside the wait window (~30s). Body is the terminal IngestJobResponse with status: "succeeded" (carrying result) or "failed" (carrying error).
Returned by POST /v1/memories (with status 202 by default,
200 when ?wait=true succeeds inline) and by
GET /v1/memories/jobs/{job_id}. Same wire shape across
every read of a job's lifecycle.
Opaque job id of the form job_<32-hex-chars>.
"job_a1b2c3d4e5f6071829304a5b6c7d8e9f"
Lifecycle state. pending → enqueued. running → extraction in progress. succeeded → result is set. failed → error is set. Terminal jobs (succeeded / failed) are retained for 24h before TTL sweep returns 404 job_not_found.
pending, running, succeeded, failed ISO-8601 timestamp the job was created.
Constant discriminator for the resource type.
"ingest_job"ISO-8601 timestamp of the most recent state transition.
Populated when status = succeeded; null otherwise.
Populated when status = failed; null otherwise.