CortexDB Docs
Core Concepts

The Experience Envelope

The single structured payload for everything CortexDB ingests — messages, observations, tool results, documents, and triples.

The Experience Envelope is one structured shape used to ingest all forms of agent experience — messages, observations, tool results, documents, and raw triples — into lossless event-sourced memory. One shape covers every data type, so ingestion isn't fragmented across formats.

CortexDB separates the payload into functional slots: identity (who), content (the data), context (temporal/spatial grounding), and operational directives (how to process it).

Minimal envelope

{
  "scope": "org:acme/dept:eng/user:alice",
  "modality": "conversation",
  "content": { "kind": "message", "role": "user", "text": "Just got off a call with Priya at Acme." }
}

Required fields

Only scope, modality, and content are required. context (and context.observed_at) and idempotency_key are optional — a write without them returns 202. (Older docs marked observed_at and idempotency_key as required; they are not.)

Identity slots

Up to three identities; each defaults to the previous for the common "narrating yourself" case.

SlotDefaultCapability needed when set explicitly
CallerImplicit (from token)always
Observed actor= callerscope.write.on_behalf_of when ≠ caller
Subject= observed_actorscope.write.about_other when ≠ observed_actor

This supports bots writing on behalf of a user (observed_actor) and writing memories about other entities (subject).

Content kinds

content is a discriminated union — pick the shape that matches your data:

KindShapeUse for
message{ role, text, media[] }Conversational turns
text{ text }Free-form text observations
json{ data }Structured tool outputs, sensor readings
blob_ref{ blob_id }Reference an already-uploaded blob
triple{ subject, predicate, object }Direct fact insertion (object needs type+datatype+value)

The role enum is enforced: user, assistant, tool, system (anything else → 422).

Modalities and extraction

ModalityTriggers extraction?Notes
conversationyesFact + episode extraction
documentyesDocument chunking + entity extraction
tool_resultyesJSON inspection
observationyesGeneric
feedbacknoSupporting evidence only
importedyes (with mapping)Used by /v1/import/*

The modality enum is not enforced — unknown values are stored verbatim but don't trigger structured extraction. (Extraction into Facts/Beliefs also requires enrichment to be configured — see Self-hosting defaults.)

Context

{
  "observed_at":        "2026-05-15T10:42:00Z",
  "source_recorded_at": "2026-05-15T10:41:58Z",
  "location":           { "city": "Bangalore" },
  "preceded_by":        ["evt_01HX..."],
  "intent":             "deal_status_update",
  "labels":             ["acme", "renewal"]
}

All context fields are optional. preceded_by chains experiences by CortexDB event id (evt_…) so the episode builder recognizes a sequence.

Idempotency

idempotency_key (≤ 64 chars) is optional but recommended for safe retries. Same key + same body → no-op; same key + different body → 409 IDEMPOTENCY_CONFLICT. Use a deterministic key per source-system message (e.g. slack:C123:T456:1747293720). Idempotency records persist across restarts, so a retry after a crash replays the same event_id (replayed_from_idempotency: true) rather than duplicating. Keys are global (not per-scope) and expire after ~24 h.

Operational directives

{
  "directives": {
    "extract": ["facts", "beliefs"],
    "consolidate_into": "org:acme/dept:eng",
    "confidence_floor": 0.7,
    "ttl_for_belief_layer": "P30D",
    "embed": "eager"
  }
}
FieldNotes
extractSubset of facts, entities, beliefs, episodes, understanding
consolidate_intoMerge derived layers into a different scope (requires scope.write on both)
confidence_floorDrop derived records below this confidence
ttl_for_belief_layerISO-8601 duration. Stored but not enforced yet — records do not auto-expire
embedeager / lazy / none

FAQ

Does the envelope block the write path? No — it returns 202 after the capture phase; extraction and consolidation run asynchronously.

Can it handle tool outputs? Yes — the json content kind ingests structured tool outputs / sensor readings.

How does it handle identity? Three slots (caller, observed actor, subject) let bots act on behalf of a user or write about other entities.

See also

On this page