Aletheia

Model providers: none, Claude CLI, OpenAI-compatible and Ollama

Aletheia (aletheia-mem) runs without any model. A model provider is optional, and it only changes how facts are extracted from your session summaries and notes. This page lists the providers, the environment variables, what leaves your machine, and what the measurements say.

The default: no provider

With nothing set, ALETHEIA_PROVIDER is none. Extraction uses a rule extractor that makes no network call. It accepts a plain "subject verb object" sentence and skips everything else, so it is quiet rather than clever.

aletheia compress
Extraction mode: rules; keyword only
queue: {"pending":0,"running":0,"done":1,"failed":0,"oldestPendingEpoch":null}
last: 1 memories, 1 window(s), 0 new fact(s), 0 rejected, 0 embedded

The measured limits, from the project README (retrieval numbers on LoCoMo, not answer accuracy):

See Benchmarks for the full table.

What a provider is used for

I read the code for every place a provider is called.

UseTriggerNeeds
Fact extractionThe server's background worker, and aletheia compressA provider from ALETHEIA_PROVIDER or ALETHEIA_PROVIDERS
Compress events into observationsThe Compress now button in Knowledge, Import and exportALETHEIA_PROVIDER other than none
Work view refresh (goals, grouping, reviews, story)The server, every 10 minutes, when ALETHEIA_PROVIDER is not noneThe claude-mem database and python3
Plain-language card text ("human copy")The server, when both ALETHEIA_OPENAI_API_KEY and ALETHEIA_OPENAI_MODEL are setThose two variables. It ignores ALETHEIA_PROVIDER.

Not model calls:

If you want a provider for extraction only, turn the Work view refresh off. Without this, ALETHEIA_PROVIDER=openai on the server prints refresh : on (openai, every 10 min).

ALETHEIA_AUTO_REFRESH=false

Providers and presets

ALETHEIA_PROVIDER takes one of these values. Anything else stops with Unknown provider "<name>". Use one of: none, local, openai, openrouter, claude-cli, fake. The value fake is for tests.

ValueWhat it calls
noneNothing. Rule extractor only.
localAn OpenAI-compatible endpoint at ALETHEIA_LOCAL_BASE_URL. The default is Ollama's http://127.0.0.1:11434/v1/chat/completions.
openaiALETHEIA_OPENAI_BASE_URL, default https://api.openai.com/v1/chat/completions, with ALETHEIA_OPENAI_API_KEY.
openrouterhttps://openrouter.ai/api/v1/chat/completions with ALETHEIA_OPENAI_API_KEY.
claude-cliThe claude program in print mode.

ALETHEIA_PROVIDERS takes an ordered list of presets: ollama, lmstudio, llamacpp, local, openai, openrouter, claude-cli and anthropic-compatible. ALETHEIA_PROVIDER=ollama is not valid; ollama is a preset name for the list only.

PresetURL
ollamahttp://127.0.0.1:11434/v1/chat/completions
lmstudiohttp://127.0.0.1:1234/v1/chat/completions
llamacpphttp://127.0.0.1:8080/v1/chat/completions
localALETHEIA_LOCAL_BASE_URL
openai, openrouterThe public endpoints above, API key required
anthropic-compatibleALETHEIA_ANTHROPIC_BASE_URL. There is no default, because Anthropic publishes no OpenAI-shaped chat endpoint. Point it at a gateway that has one.

A selected provider that is incomplete stops with a message that names the setting:

Provider "openai" needs a model: set ALETHEIA_OPENAI_MODEL or ALETHEIA_EXTRACT_MODEL.
Provider "ollama" needs a model: set ALETHEIA_OPENAI_MODEL or ALETHEIA_EXTRACT_MODEL.
Provider "anthropic-compatible" needs a URL: set ALETHEIA_ANTHROPIC_BASE_URL.

The extraction worker in the server does not stop on a bad provider setting. It falls back to the rule extractor. The Work view refresh is different: with ALETHEIA_PROVIDER=openai and no model, aletheia-server printed the needs a model error and exited in my test. Set ALETHEIA_AUTO_REFRESH=false to avoid that path.

Set one up

Local model with Ollama. Pull a model first with Ollama. The model name is yours to choose.

ALETHEIA_PROVIDER=local ALETHEIA_OPENAI_MODEL=llama3.2:1b aletheia compress

The variable ALETHEIA_OPENAI_MODEL names the model for every provider except claude-cli. Use ALETHEIA_EXTRACT_MODEL to name a different model for extraction.

OpenAI-compatible hosted API:

ALETHEIA_PROVIDER=openai \
ALETHEIA_OPENAI_API_KEY=<your key> \
ALETHEIA_OPENAI_MODEL=<model name> \
aletheia compress

Set ALETHEIA_OPENAI_BASE_URL to use another OpenAI-style endpoint with the openai value.

Claude CLI:

ALETHEIA_PROVIDER=claude-cli aletheia compress

The code runs claude -p --output-format json --no-session-persistence --tools "" --setting-sources "" and sends the prompt on standard input. It uses haiku for extraction and sonnet for summaries unless you set ALETHEIA_EXTRACT_MODEL or ALETHEIA_SUMMARY_MODEL. ALETHEIA_CLAUDE_BIN names the program. I did not run this provider for this page.

For the server, set the same variables in the environment of the process. For a systemd service that means Environment= lines. See Run as a service.

The Settings page also has provider fields. I found no code that reads the saved values when the provider is built. Use environment variables.

Fallback chain

ALETHEIA_PROVIDERS=ollama,openai tries the providers in order.

One display quirk: with only ALETHEIA_PROVIDERS set, the server banner prints extraction: worker on (rule-based) and aletheia compress prints Extraction mode: none. Both read ALETHEIA_PROVIDER. The chain is still used for the calls.

Environment variables

VariableDefaultMeaning
ALETHEIA_PROVIDERnoneOne provider, see above.
ALETHEIA_PROVIDERSemptyOrdered chain of presets. Wins over ALETHEIA_PROVIDER when set.
ALETHEIA_OPENAI_API_KEYemptyKey for openai, openrouter and the presets with a key.
ALETHEIA_OPENAI_MODELemptyModel for extraction.
ALETHEIA_OPENAI_BASE_URLhttps://api.openai.com/v1/chat/completionsEndpoint for openai. The README table lists an OpenRouter URL as the default; the code uses the OpenAI URL.
ALETHEIA_LOCAL_BASE_URLOllama URLEndpoint for local.
ALETHEIA_ANTHROPIC_BASE_URLemptyGateway for anthropic-compatible.
ALETHEIA_EXTRACT_MODEL, ALETHEIA_SUMMARY_MODELemptyPer-stage model names.
ALETHEIA_CLAUDE_BINclaudeThe Claude CLI program.
ALETHEIA_FACT_MAX_EPISODES20Episodes per request.
ALETHEIA_FACT_CHAR_BUDGET12000Characters per request.
ALETHEIA_PRICE_IN_PER_1K, ALETHEIA_PRICE_OUT_PER_1K0Your own prices, for the cost estimate.
ALETHEIA_MODEcodeExtraction style: code, chill, language-en or language-es.
ALETHEIA_OUTPUT_LANGUAGEemptyOutput language, see below.
ALETHEIA_AUTO_REFRESHonfalse turns the Work view refresh off.

What is sent to the model

I started a local mock endpoint, pointed ALETHEIA_PROVIDER=local at it, queued one job and recorded the request body. A hosted provider receives the same body.

The request has the keys model, stream, temperature and messages. The message holds:

The sources are session summaries (the last assistant message that the Stop hook captured) and saved notes. Prompts and tool events are not fact sources, so they are not sent by this path.

The text is redacted again right before the call. In the test, a summary imported from claude-mem held a fake AWS key id, and the request carried [redacted:aws-key-id]. The Authorization header was absent because no key was set. Facts that come back are redacted again before storing.

What the redaction does not cover:

Cost and privacy notes

Embeddings are separate

Semantic search and fact vectors use an optional package, @huggingface/transformers. They need no provider. They run from aletheia embed and aletheia search --semantic (which you start on purpose) and, only if you set ALETHEIA_EMBED_FACTS=1, from aletheia compress. The first use downloads a model, about 35 MB according to the code comment, into ~/.aletheia/models. Without the package installed, none of this runs. aletheia compress creates no embeddings by default, so it makes no download.

Output language

ALETHEIA_OUTPUT_LANGUAGE and aletheia language set the language of extracted facts. The setting adds one line to the model prompt. It has no effect on the rule extractor, which does not translate.

aletheia language set es --project shop
aletheia language set pt_BR
aletheia language
aletheia language set "" --project shop
Output language for shop: es
Output language for default: pt-br
shop                     es
default                  pt-br
Cleared the output language for shop; it follows the extraction mode.

A language tag is checked when you set it. Use a BCP 47 tag such as en, es or pt-BR. The tag is stored in lower case. A bad tag stops with "<text>" is not a language tag.

The order of precedence is: the project's saved language, then the saved default language, then ALETHEIA_OUTPUT_LANGUAGE, then the extraction mode. An empty value clears a saved language. The prompt keeps code, paths, names and identifiers unchanged.

Next steps