RememberStackremember.dev/docs

Models and providers

RememberStack calls language models to read your documents and an embedding model to make them searchable. A self-hosted deployment sends every one of those calls through OpenRouter with the key in REMEMBERSTACK_OPENROUTER_API_KEY, and pays for them on that account. This page lists each place a model is used (a seat), what it does, and the settings that shape the calls.

Retrieval itself calls no language model. A search embeds your query text once; the operations, graph and SQL queries then read the database.

Model seats

Each seat is one environment variable holding an OpenRouter model id. The defaults are the values compose.yaml passes when .env leaves them unset.

SeatVariableDefaultWhat it does
Structure fallbackREMEMBERSTACK_STRUCTURER_MODELopenai/gpt-5.6-lunaProposes section anchors when a document's own headings do not give a usable outline. A document whose headings pass the structure checks never reaches this seat.
Skeleton checkREMEMBERSTACK_SKELETON_CHECK_MODELz-ai/glm-4.7-flashChecks a proposed section outline, independently of the model that proposed it.
Section roleREMEMBERSTACK_ROLE_MODELz-ai/glm-4.7-flashClassifies what each section is for, from its title.
Section summaryREMEMBERSTACK_SUMMARY_MODELz-ai/glm-4.7-flashWrites the short summary of each section.
Claim extractionREMEMBERSTACK_E2_EXTRACT_MODELopenai/gpt-5.6-lunaSelects the sentences that state something and turns them into claims. Used by both the extract_claims and ground_claims workers.
Relation normalisationREMEMBERSTACK_E3_NORMALIZE_MODELopenai/gpt-5.6-lunaTurns claims into relations between entities.
Entity resolutionREMEMBERSTACK_OBS_SMALL_MODELopenai/gpt-5.6-lunaDecides between candidate entities when the deterministic name matching cannot.
Fact adjudicationREMEMBERSTACK_FACT_MODELopenai/gpt-5.6-lunaDecides whether a new statement confirms, contradicts or replaces a fact the memory holds.
EmbeddingsREMEMBERSTACK_P1_EMBEDDING_MODELqwen/qwen3-embedding-8bEvery vector: chunks, claims, facts, entity profiles, and the query text of each search.

GET /deployment reports the models the running deployment is bound to under model_bindings, so you can check what is serving:

curl http://localhost:8000/deployment

Fact adjudication

Fact adjudication decides what the memory holds true, so it has two extra settings:

VariableDefaultMeaning
REMEMBERSTACK_FACT_ADJUDICATION_ENGINEpromptprompt asks REMEMBERSTACK_FACT_MODEL through OpenRouter. jev asks a TypeSafe AI System One model instead.
REMEMBERSTACK_FACT_CONFIDENCE_FLOOR0.75Below this confidence the adjudicator does not replace or contradict anything: the new statement and the existing fact are both kept.

The jev engine needs its own key and settings:

VariableDefault
REMEMBERSTACK_TYPESAFE_API_KEYnone (required with jev; the fact workers refuse to start without it)
REMEMBERSTACK_TYPESAFE_MODELjev-latest
REMEMBERSTACK_TYPESAFE_BASE_URLhttps://api.typesafe.ai/v1
REMEMBERSTACK_TYPESAFE_TIMEOUT_S30.0
REMEMBERSTACK_FACT_FALLBACK_TO_PROMPTfalse. When true, a failed TypeSafe call falls back to the prompt engine instead of failing the work item.

Change a model

Put the new model id in .env and apply it:

# .env
REMEMBERSTACK_E2_EXTRACT_MODEL=openai/gpt-5.6-sol
docker compose up -d

Use exact model ids. A rotating router id such as openrouter/free makes results impossible to reproduce and to attribute. A chat seat needs a model that supports structured (JSON schema) output, because every seat asks for a typed answer and rejects one that does not match.

A new model applies to work done from then on. Documents already processed keep what the old model produced; RememberStack does not re-run them on its own.

Changing the embedding model

Every vector in RememberStack has 1,536 dimensions. The column types, the search channels and every request are fixed at that size: the engine asks the provider for 1,536 dimensions and rejects a response of any other length. An embedding model can replace qwen/qwen3-embedding-8b only if it can return 1,536-dimension vectors on request.

Each stored vector is stamped with the model that produced it, and search compares a query only with vectors of the same model. Nothing re-embeds stored chunks, claims and facts, so the embedding model is fixed once anything has been embedded:

  • Before the first document is embedded, you can change REMEMBERSTACK_P1_EMBEDDING_MODEL freely.
  • After that, setup refuses to run with a different model. It exits with an error that names the configured model and the stored one, and the API and workers do not start. Set the variable back to the stored model.

To change it before anything is embedded, stop the workers first (docker compose stop), then change the variable and run docker compose up -d. A worker still running on the old model could otherwise embed with it after the switch; the next setup would then refuse the new model.

To use a different embedding model, start a new deployment and send the documents again.

OpenRouter routing and limits

These settings apply to every call through OpenRouter.

VariableDefaultMeaning
REMEMBERSTACK_OPENROUTER_CHAT_PROVIDER_ORDERunsetComma-separated provider slugs to try first for chat calls. Other providers remain a fallback.
REMEMBERSTACK_OPENROUTER_CHAT_PROVIDER_ONLYunsetComma-separated provider slugs that are the only ones allowed. A call they cannot serve fails. Cannot be combined with the order.
REMEMBERSTACK_OPENROUTER_EMBEDDING_PROVIDER_ORDERunsetProvider slugs to try first for embeddings, with fallback, for example nebius,deepinfra,siliconflow.
REMEMBERSTACK_OPENROUTER_EMBEDDING_PROVIDERunsetOne provider slug that embeddings must use, with no fallback. The order wins if both are set.
REMEMBERSTACK_OPENROUTER_ZDRfalseRestricts chat calls to zero-data-retention endpoints.
REMEMBERSTACK_OPENROUTER_REASONING_EFFORTunset (model default)One of none, minimal, low, medium, high, xhigh, max, applied to every chat call.
REMEMBERSTACK_OPENROUTER_REASONING_EFFORT_MAPunsetA JSON object of model id to effort. An entry wins over the global value for that model.
REMEMBERSTACK_OPENROUTER_MAX_COMPLETION_TOKENS32000Output allowance per chat call, reasoning included.
REMEMBERSTACK_OPENROUTER_TIMEOUT_S120Per-request timeout in seconds.
REMEMBERSTACK_OPENROUTER_CHAT_THROTTLE_RETRIES3How many times a chat call that gets HTTP 429 is retried, moving to the next listed provider. These retries do not count against the work item's attempts.
REMEMBERSTACK_OPENROUTER_CHAT_UPSTREAM_OVERLOAD_MAX_RETRY_AFTER_S30The longest single wait before retrying an overloaded provider.
REMEMBERSTACK_OPENROUTER_BASE_URLhttps://openrouter.ai/api/v1The OpenRouter API address.

When you set a provider list or ZDR, each chat call also tells OpenRouter not to route to providers that collect data (data_collection: deny). With none of them set, OpenRouter applies your account's own routing settings.

Lowering reasoning effort makes extraction faster and cheaper; the comment in .env.example notes that none can reduce adjudication quality and that some models reject it. A map lets you turn it off for the small models only:

REMEMBERSTACK_OPENROUTER_REASONING_EFFORT_MAP={"z-ai/glm-4.7-flash":"none","openai/gpt-5.6-luna":"high"}

For debugging, REMEMBERSTACK_OPENROUTER_INVALID_COMPLETION_CAPTURE_DIR (an absolute path, for example /var/lib/rememberstack/openrouter-invalid-completions) keeps every model answer that failed schema validation, one file each, readable only by the engine user. Those files can repeat text from your documents; treat the directory as customer data and leave the setting off otherwise.

Cost

Every document costs model calls: section work during structuring, claim extraction for every chunk, relation normalisation, entity resolution and fact adjudication for what it says, and embeddings for its chunks, claims and facts. Each search costs one query embedding. The size of the bill depends on your documents and the models you choose; RememberStack has published no per-document cost figures.

Every billed call is written to the cost ledger with its model, tokens, cost in US dollars and the pipeline stage that made it. Read it with the cost export, and cap it per stage with spend budgets. The provider account's own limit is the final monetary boundary.