CortexDB Docs
Operations

LLM & Answer Generation

All 18 LLM-related env vars — entity extraction, async enrichment, answer generation, verifier — plus how the fallback chain works.

CortexDB calls LLMs in four distinct places, each independently configurable. Mixing them is the norm — e.g. GPT-4o-mini for cheap entity extraction on every write, a strong model for the answer the user sees, an optional verifier on top.

The four LLM call sites

Call siteWhenDefault modelWhy this one
Entity extractionIn the ingest pipeline, off the write path (does not block the captured ACK)gpt-4o-miniCheap, fast, structured-output-reliable
Async enrichmentBackground job, only if explicitly enabled(none — disabled)Heavyweight KG enrichment; opt-in
Answer generation/v1/answerclaude-opus-4-6Highest score on multi-session in our A/B
VerifierPost-answer cross-check; on whenever OPENAI_API_KEY or CORTEX_VERIFIER_API_KEY is setgpt-4.1Different family → catches model-specific failure modes

Each has its own model, URL, API key, and disable switch — route them to entirely different providers if you need to. The image bakes a URL and model for the extraction (gpt-4o-mini), verifier (gpt-4.1) and answer (anthropic / claude-opus-4-6) lanes, so a bare provider key switches a lane on: OPENAI_API_KEY alone enables extraction and the verifier, and ANTHROPIC_API_KEY alone enables /v1/answer on claude-opus-4-6.

1. Entity extraction LLM

Runs on /v1/experience ingest to seed the knowledge graph. If disabled, fact/belief layers degrade to text-only matching.

Extraction does not block the write

A write returns captured (202) at the durable WAL accept point in ~10 ms — before any extraction. The gpt-4o-mini extraction runs as a pipeline stage after that ACK (it can't complete inside a 10 ms write), and heavier fact/belief consolidation is fully asynchronous. Pass ?wait=indexed or ?wait=consolidated to block the client until those later stages finish. See Lifecycle.

Env varDefaultWhat it controls
CORTEX_LLM_DISABLE(unset)Set to 1/true to skip extraction. Faster writes; weaker recall.
CORTEX_LLM_URLhttps://api.openai.com/v1Endpoint. Any OpenAI-compatible API.
CORTEX_LLM_MODELgpt-4o-miniModel name passed to the provider.
CORTEX_ENTITY_API_KEY(falls back to OPENAI_API_KEY)Separate extraction key.

Change it for benchmarks (CORTEX_LLM_DISABLE=1 for pure-text recall), systematic extraction errors (CORTEX_LLM_MODEL=gpt-4o, ~10× cost), or local extraction (CORTEX_LLM_URL=http://localhost:11434/v1 + a local model).

2. Async enrichment LLM (optional)

A heavyweight pipeline doing deeper KG enrichment (multi-hop fact linking, cross-session entity disambiguation). Off by default — it needs the model, an endpoint key and CORTEX_ENRICHMENT_DELAY_SECONDS; without the delay variable the boot log says enrichment OFF and Facts/Beliefs stay empty even with the model and key set.

Env varDefaultWhat it controls
CORTEX_ENRICHMENT_MODEL(empty = disabled)Model name.
CORTEX_ENRICHMENT_DELAY_SECONDS(unset = enrichment off)Seconds after a write before enriching; required to turn the scanner on (0 = as fast as allowed).
CORTEX_ENRICHMENT_URL(falls back to CORTEX_LLM_URL)Endpoint.
CORTEX_ENRICHMENT_API_KEY(falls back to OPENAI_API_KEY / LLM_API_KEY, not CORTEX_ENTITY_API_KEY)Separate key.

Enrichment is what populates Facts/Beliefs on a self-host

On a content-only self-hosted instance, the Facts/Beliefs/Understanding layers stay empty until enrichment is enabled here. The async pipeline drains on the scheduler's enrichment_drain_interval_secs (default 30 s). See Self-hosting defaults.

export CORTEX_ENRICHMENT_MODEL=gpt-4o-mini
export CORTEX_ENRICHMENT_URL=https://api.openai.com/v1
export CORTEX_ENRICHMENT_API_KEY=sk-...
export CORTEX_ENRICHMENT_DELAY_SECONDS=5

gpt-4o-mini is the recommended enrichment model: the cheapest reliable extraction model, about $0.40 per 1,000 events. See Cost Planning.

3. Answer generation LLM

Used by POST /v1/answer to turn a recall pack into a cited natural-language answer.

Env varDefaultWhat it controls
CORTEX_ANSWER_PROVIDERanthropicanthropic, openai, google, bedrock, ollama
CORTEX_ANSWER_MODELclaude-opus-4-6Model name. Provider-specific.
CORTEX_ANSWER_URL(provider default)Override endpoint (proxies, gateways).
CORTEX_ANSWER_API_KEY(falls back to provider-specific env)ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.
CORTEX_ANSWER_MAX_TOKENS1500Generation budget.
ANTHROPIC_API_KEY(none)Fallback when provider is anthropic and CORTEX_ANSWER_API_KEY unset.

Self-hosted, the answer lane must be set — the default model is a cloud value

claude-opus-4-6 is the managed-cloud default. Self-hosted, /v1/answer is disabled (returns 503 ANSWER_UNAVAILABLE) until you set the CORTEX_ANSWER_* group to your own provider; the model name resolves to whatever you configure. Setting ANTHROPIC_API_KEY alone also enables it, on the baked claude-opus-4-6. Setting only CORTEX_LLM_* does not route /v1/answer — that's the extraction lane. See Self-hosting defaults.

Recommended (September 2026): gpt-5.6-terra for answers (about 2 to 4 cents each), gpt-5.6-luna for high-volume or simple questions (about 0.2 to 0.4 cents), and gpt-5.6-sol or gpt-6-astra only where answer quality is the product. Terra, Luna and Sol all work as CORTEX_ANSWER_MODEL with CORTEX_ANSWER_PROVIDER=openai. For premium answers use Sol: gpt-6-astra expects max_completion_tokens rather than the max_tokens CortexDB sends, so it isn't usable on the answer lane yet. Costs, monthly estimates and the price-book caveat are on Cost Planning.

Earlier model choices (internal A/B deltas on a 150-question slice — directional, not definitive; the GPT-5.6 models have no published delta on this slice):

ModelProviderPer-query costLongMemEval-S delta vs Opus 4.6
claude-opus-4-6Anthropic~$0.030 (baseline, 93.8%)
claude-sonnet-4-6Anthropic~$0.006~-2 pp
gpt-4oOpenAI~$0.015~-3 pp
gpt-4o-miniOpenAI~$0.001~-8 pp
gemini-2.0-flashGoogle~$0.002~-5 pp (estimated)

Provider notes. Anthropic: set CORTEX_ANSWER_URL to a Bedrock/Vertex endpoint to route hosted Claude. OpenAI: CORTEX_ANSWER_PROVIDER=openai, CORTEX_ANSWER_MODEL=gpt-5.6-terra. Bedrock/Google: set CORTEX_ANSWER_URL to the regional endpoint; auth via the provider's native env vars. Ollama: CORTEX_ANSWER_PROVIDER=ollama, CORTEX_ANSWER_URL=http://localhost:11434, CORTEX_ANSWER_MODEL=qwen2.5:14b (~3–15 s / answer).

4. Verifier LLM (on whenever an OpenAI key is present)

A second LLM call that critiques the answer for hallucination against the citation pack. Doubles latency and cost when enabled. The image bakes CORTEX_VERIFIER_URL=https://api.openai.com/v1 and CORTEX_VERIFIER_MODEL=gpt-4.1, so it switches on as soon as OPENAI_API_KEY (or CORTEX_VERIFIER_API_KEY) is set; set CORTEX_VERIFIER_URL= (empty) to keep it off.

Env varDefaultWhat it controls
CORTEX_VERIFIER_MODELgpt-4.1Use a different family from the answer model.
CORTEX_VERIFIER_URLhttps://api.openai.com/v1 (baked into the image)Endpoint; set empty to disable the lane.
CORTEX_VERIFIER_API_KEY(falls back to OPENAI_API_KEY, not CORTEX_ANSWER_API_KEY)Key.
CORTEX_VERIFIER_MAX_TOKENS16384Verifier output budget.

Configure the lane to use it:

export CORTEX_VERIFIER_URL=https://api.openai.com/v1
export CORTEX_VERIFIER_API_KEY=$OPENAI_API_KEY
export CORTEX_VERIFIER_MODEL=gpt-4.1

Using a different family from the answer model avoids sharing the generator's blind spots.

Configuring the verifier

The verifier is configured only by the four CORTEX_VERIFIER_* variables above; setting them turns it on for every question. There is no separate enable flag or per-question-type setting (names such as CORTEX_ANSWER_USE_VERIFIER have no effect).

The fallback chain (in cortex.toml)

The [llm] section declares a fallback chain any LLM call can use when the primary provider is unreachable:

[llm]
provider = "openai"
endpoint = ""                      # empty → resolve from provider default
api_key = ""                       # empty → resolve from OPENAI_API_KEY env
model = "gpt-4o-mini"

fallback_provider = "anthropic"
fallback_endpoint = ""             # empty → https://api.anthropic.com/v1
fallback_api_key = ""              # empty → ANTHROPIC_API_KEY env
fallback_model = "claude-sonnet-4-6"

fallback_chain = ["openai", "anthropic", "google"]   # tried in order on cascading failures

max_extraction_batch_size = 8      # entity-extraction items per LLM call
extraction_timeout_ms = 30000      # per-call timeout

Resolution: TOML api_key wins, else the env var for the named provider (OPENAI_API_KEY/ANTHROPIC_API_KEY/LLM_API_KEY); same for endpoint. Call-site CORTEX_* overrides take precedence over the TOML defaults — the TOML chain is a floor, the env vars a ceiling.

Cost ladder

Estimated monthly model spend for an agent writing 10K events a day (300K a month) and answering 1K questions a day (30K a month), using the per-event and per-answer figures on Cost Planning (enrichment about $0.40 per 1,000 events; answers at the rates listed there; OpenAI list prices, September 2026).

ConfigurationEmbeddingEnrichmentAnswerTotal
Content-only, answers on Lunanegligible—~$60–120~$60–120
Enrichment on, answers on Lunanegligible~$120~$60–120~$180–240
Recommended: enrichment on, answers on Terranegligible~$120~$600–1,200~$720–1,320
Premium answers on Solnegligible~$120~$1,200–2,100~$1,320–2,220
Premium answers on GPT-6 Astranegligible~$120~$3,300–5,400~$3,420–5,520

Question volume drives the cost, not corpus size: choosing the answer model (and routing simple questions to Luna) is the largest cost lever. The previous version of this table, inherited from the v1 docs, was internally inconsistent on the answer column.

Diagnostics

The model is at diagnostics.answer_model — there is no model_used field

The /v1/answer response top-level keys are { pack_id, answer, citations, provenance, diagnostics, as_of }. The model is reported at diagnostics.answer_model — there is no top-level model_used field.

Choosing the answer model

The answer lane always calls its configured CORTEX_ANSWER_MODEL. /v1/answer accepts an answer_model field (and the SDKs expose it), but it is only echoed in diagnostics.answer_model. To answer with a different model, change CORTEX_ANSWER_MODEL (or run a second deployment).

{
  "answer": "...",
  "citations": [ "..." ],
  "diagnostics": { "answer_model": "gpt-5.6-terra", "recall_ms": 42, "llm_ms": 830, "...": "..." }
}

Without a per-request override, if diagnostics.answer_model doesn't match what you set: a typo made the binary fall back to the compiled default; the fallback chain triggered (primary provider unreachable); or a scope-level policy override is forcing a different model — check /v1/policy/effective?actor=….

Next steps

On this page