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 site | When | Default model | Why this one |
|---|---|---|---|
| Entity extraction | In the ingest pipeline, off the write path (does not block the captured ACK) | gpt-4o-mini | Cheap, fast, structured-output-reliable |
| Async enrichment | Background job, only if explicitly enabled | (none — disabled) | Heavyweight KG enrichment; opt-in |
| Answer generation | /v1/answer | claude-opus-4-6 | Highest score on multi-session in our A/B |
| Verifier | Optional, post-answer cross-check | gpt-4.1 | Different 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.
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 var | Default | What it controls |
|---|---|---|
CORTEX_LLM_DISABLE | (unset) | Set to 1/true to skip extraction. Faster writes; weaker recall. |
CORTEX_LLM_URL | https://api.openai.com/v1 | Endpoint. Any OpenAI-compatible API. |
CORTEX_LLM_MODEL | gpt-4o-mini | Model 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 — set the model env var to turn it on.
| Env var | Default | What it controls |
|---|---|---|
CORTEX_ENRICHMENT_MODEL | (empty = disabled) | Set to a model name to enable. |
CORTEX_ENRICHMENT_URL | (falls back to CORTEX_LLM_URL) | Endpoint. |
CORTEX_ENRICHMENT_API_KEY | (falls back to 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
export CORTEX_ENRICHMENT_URL=https://api.openai.com/v13. Answer generation LLM
Used by POST /v1/answer to turn a recall pack into a cited natural-language answer.
| Env var | Default | What it controls |
|---|---|---|
CORTEX_ANSWER_PROVIDER | anthropic | anthropic, openai, google, bedrock, ollama |
CORTEX_ANSWER_MODEL | claude-opus-4-6 | Model 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_TOKENS | 1500 | Generation 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, provider anthropic) until you set the CORTEX_ANSWER_* group to your own provider; the model
name resolves to whatever you configure. Setting only CORTEX_LLM_* does not route /v1/answer —
that's the extraction lane. See Self-hosting defaults.
Model choices (internal A/B deltas on a 150-question slice — directional, not definitive):
| Model | Provider | Per-query cost | LongMemEval-S delta vs Opus 4.6 |
|---|---|---|---|
claude-opus-4-6 | Anthropic | ~$0.03 | 0 (baseline, 93.8%) |
claude-sonnet-4-6 | Anthropic | ~$0.006 | ~-2 pp |
gpt-4o | OpenAI | ~$0.015 | ~-3 pp |
gpt-4o-mini | OpenAI | ~$0.001 | ~-8 pp |
gemini-2.0-flash | ~$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-4o. 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 (optional, off by default)
A second LLM call that critiques the answer for hallucination against the citation pack. Doubles latency and cost when enabled.
| Env var | Default | What it controls |
|---|---|---|
CORTEX_VERIFIER_MODEL | gpt-4.1 | Use a different family from the answer model. |
CORTEX_VERIFIER_URL | (falls back to CORTEX_ANSWER_URL) | Endpoint. |
CORTEX_VERIFIER_API_KEY | (falls back to CORTEX_ANSWER_API_KEY) | Key. |
CORTEX_VERIFIER_MAX_TOKENS | 16384 | Verifier 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.1Using a different family from the answer model avoids sharing the generator's blind spots.
There is no verifier enable flag or per-question-type gating
The v1 docs describe CORTEX_ANSWER_USE_VERIFIER and CORTEX_ANSWER_VERIFIER_TYPES (a
comma-separated list of question types). Neither name is read by the server — verified against the
shipped v0.9.8 and v0.9.9 binaries, whose only verifier variables are the four CORTEX_VERIFIER_*
above. Setting them has no effect, and you cannot scope the verifier to particular question types on
v0.9.9; configure the CORTEX_VERIFIER_* lane instead.
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 timeoutResolution: 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
Sample monthly cost for an agent writing 10K events/day, answering 1K queries/day:
| Configuration | Embedding | Extraction | Answer | Verifier | Total |
|---|---|---|---|---|---|
| Cost-Optimized (all GPT-4o-mini) | $5 | $8 | $10 | — | $23 |
| Default (sm embed + 4o-mini ext + Opus ans) | $5 | $8 | $90 | — | $103 |
| With verifier on multi-session | $5 | $8 | $90 | $30 | $133 |
| Premium (lg embed + 4o ext + Opus + verifier) | $20 | $80 | $90 | $30 | $220 |
The answer call dominates; cutting it is the largest cost lever.
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 that produced the answer is diagnostics.answer_model — there is no
top-level model_used field.
{
"answer": "...",
"citations": [ "..." ],
"diagnostics": { "answer_model": "gpt-4o", "recall_ms": 42, "llm_ms": 830, "...": "..." }
}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
- Embeddings — the vector side of the inference bill
- Recall Tuning — feed the answer model better context
- Profiles & Presets — the Cost-Optimized profile for an all-mini deployment