Python Quickstart
Get from zero to a working stratified pack in under 5 minutes with the Python SDK.
Self-hosting? Skip the signup below
The recommended way to run CortexDB is to host it yourself. Against a
self-hosted dev server (started with CORTEX_INSECURE_NO_AUTH=1) you need no token — construct
the client with api_url="http://localhost:3141", actor="user:local", and jump to step 4. On a keyed
server pass bearer="<your CORTEX_API_KEY>". The signup flow below is for the managed cloud.
1. Install
pip install cortexdbai| Package | Name |
|---|---|
| PyPI package | cortexdbai |
| Python import | cortexdb.v1 |
Requires Python 3.10+ (current release: 0.11.2). The HTTP dependencies (requests, httpx) are
installed automatically with the package.
2. Sign up — no email, no card
The fastest way to get a working token is one anonymous POST. No form, no email, no redirect.
import requests
r = requests.post("https://api-v1.cortexdb.ai/v1/auth/signup", json={}).json()
TOKEN = r["token"] # PASETO v4 bearer (7-day TTL on the free tier)
ACTOR = r["user_id"] # e.g. "user:u_019e..."
SCOPE = r["scope"] # your default scope path
print(r["expires_at"]) # ISO 8601; renew before thisIf you already have a permanent CortexDB account, your IdP issues PASETO tokens the same way — substitute
its URL for /v1/auth/signup. The CLI command cortexdb auth tokens mint is the operator-side equivalent.
3. Open a client
from cortexdb.v1 import V1Client
client = V1Client(
api_url="https://api-v1.cortexdb.ai",
actor=ACTOR,
bearer=TOKEN,
)
print(client.whoami()["effective_capabilities"])api_url defaults to http://localhost:3141 (a locally running server) as of cortexdbai 0.11.0
(it was 3142 in ≤0.10.0). Pass the cloud URL explicitly, as above, when using the hosted platform.
4. Capture an experience
result = client.experience(
scope=SCOPE,
text="Just got off a call with Priya at Acme. They upgraded to 200 seats.",
role="user",
observed_at="2026-05-16T10:42:00Z",
idempotency_key="alice-chat-001",
)
print(result["event_id"]) # "evt_01HX..."
print(result["status"]) # "captured"The SDK infers modality — pass role= and the SDK builds the right envelope. There is no modality=
parameter on experience().
Returns 202 Accepted as soon as the WAL append succeeds. Pass wait="indexed" to block until BM25 +
HNSW indexes have the event (30 s ceiling). wait is sent as ?wait=indexed and works from every SDK and
from raw REST; for longer waits use GET /v1/lifecycle/stream?event_id=evt_… (see Lifecycle).
5. Recall a stratified pack
pack = client.recall(
scope=SCOPE,
view="holistic",
query="What did we decide about Acme's renewal?",
include=["events", "beliefs", "facts", "episodes"],
budgets={"max_tokens": 4000},
diagnostics="none", # free-tier tokens don't hold diagnostics.read
)
print(pack.get("context_block", ""))
for fact in pack["layers"].get("facts", []):
print(fact["predicate"], "=", fact["object"]["value"])Free-tier capabilities. diagnostics="summary"/"full" require the diagnostics.read capability,
which the free-tier token doesn't include — pass diagnostics="none" on the free tier.
Views. Free-tier tokens hold scope.read.local, scope.read.holistic, and scope.read.descend, so
view="holistic" works out of the box. The accepted recall views are raw, granular (alias
local), holistic, descend, lineage, structured — local is accepted and normalizes to
granular.
6. Recall + LLM in one call
answer = client.answer(
scope=SCOPE,
question="Did Acme renew?",
view="holistic",
temporal={"natural": "last 30 days"},
diagnostics="none",
)
print(answer["answer"])
for c in answer["citations"]:
print(f" {c['marker']} → {c['layer']}:{c['id']}")answer() is natural-language Q&A with full citations back to the events that supported the answer — build
your UI around this.
7. Inspect why a belief exists
Facts populate within ~5–30 s of a write (LLM-extracted; requires enrichment configured — on a bare
self-hosted instance the Facts/Beliefs layers stay empty, see Self-hosting defaults).
Beliefs and Understanding are synthesized async (minutes+). Use client.facts(scope=…) as a smoke-test
that extraction is running.
beliefs = client.beliefs(scope=SCOPE)
if beliefs["items"]:
top = beliefs["items"][0]
trail = client.belief_why(top["id"]) # belief items key their id as `id`, not `belief_id`
print(trail["narrative"])What's next
- The Experience Envelope — full shape, content kinds, directives
- The Five Memory Layers — when to read which layer
- Scopes · Bi-temporal queries · Lifecycle
- Python SDK reference
Async variant
from cortexdb.v1 import AsyncV1Client
async with AsyncV1Client(
api_url="https://api-v1.cortexdb.ai",
actor=ACTOR,
bearer=TOKEN,
) as client:
pack = await client.recall(scope=SCOPE, view="holistic", diagnostics="none")