Settings struct and the
ConfigManager runtime API — build the rustdoc with
cargo doc -p cognee --no-deps --open to browse every field and setter with
its type. This page explains how settings resolve and how to change them at
runtime. The env-var name, config key and default of every field are on the
subsystem pages:
- LLM & embedding: LLM and embedding providers.
- Storage: vector, graph and relational databases, file storage.
- Cognify: chunking, graph extraction, ontology, failure handling, incremental loading.
- Search: search, the triplet and hybrid retrievers, search history, the improve loop, feedback and personalization.
- Datasets & access: system paths, the default user and dataset, per-dataset storage, access control.
- Sessions, logging & telemetry: session cache and rate limiting, logging, observability, the HTTP server, cloud.
Configuration model
Every behaviour knob is a field on a typed config struct. The environment is a source of defaults for those fields, not the only way to set them: a variable bound to aSettings field is also settable from code (the Rust API, the language
bindings, and the CLI). Env vars are read only at a configuration boundary,
the one place that turns the environment into a config struct. Adapters,
retrievers and pipelines receive resolved values through constructors and
BackendBuildContext, and never read the process environment themselves.
Precedence
Lowest precedence first:- Defaults —
Settings::default()incrates/lib/src/config.rs. - Persisted config file (CLI only) — JSON at
~/.config/cognee-rust/config.json($XDG_CONFIG_HOME/cognee-rust/config.json), managed bycognee-cli config. Seecrates/cli/src/config_store.rs. .envfile — loaded into the process environment bySettings::overlay_from_env()(viacognee_config_core::load_dotenv). The file is found in the working directory or any ancestor. Variables already set in the process environment win over.env.- Process environment — bound by
Settings::overlay_from_env(). - Explicit code —
ConfigManagersetters (below), a binding’s constructor settings object, the binding config APIs, and CLI--flags.
defaults < config.json < .env < env < code.
Parsing notes:
- Booleans accept
true|1|yes|onandfalse|0|no(cognee_utils::parse_env_bool). - Empty env values are treated as unset.
- Numeric vars that fail to parse are ignored, and the previous value (usually
the default) stays in effect. A value outside the field’s integer type counts
as a parse failure, so a port of
70000,-1or5000000000keeps the default. Every integer key ignores an out-of-type value this way. The port keys (VECTOR_DB_PORT,GRAPH_DATABASE_PORT,DB_PORT,CACHE_PORT) accept any in-range value as-is,0included; some other integer keys then clamp or adjust an in-range value (see the pgvector, cognify and telemetry keys).
Two scopes
Component config sections
Settings that belong to one component are declared by that component, not inSettings. A section is a typed struct declared with
cognee_config_core::config_section!. Each
field becomes a setting with:
- a canonical, namespaced key:
"<section>.<field>", e.g.graph.ladybug.max_db_size; - its env vars, in priority order;
- optional plain aliases, typically the Python SDK’s flat name, e.g.
graph_max_db_size; - a secret flag.
config_sections(). Registering
the factory registers its settings. ComponentRegistry::config_schema() collects
the sections of every registered factory, plus any added with
register_config_section (for settings that no factory owns, e.g. a server
module’s).
So the settings a build accepts follow the components it contains:
- a factory compiled out by a disabled feature brings no keys: its env vars are not read, and setting its keys is an unknown-key condition;
- a downstream build that registers its own factory (
register_llm,register_vector,register_storage,register_ontology_resolver,register_graph_extractor,register_relational,register_session_store, …) brings that factory’s keys, settable through the sameConfigManager::set, bindingsetand config files as the built-in ones.
ComponentManager::with_registry adds the registry’s sections to its
ConfigManager. cognee::config::builtin_schema() is the schema of a default
build. A process built on a custom registry must load the environment with the
full schema, so the env vars of the registry’s own sections are read too:
ConfigManager::from_env_with_schema(®istry.config_schema()?);HandleState::from_env_with_registry(registry)in the bindings;Settings::load_from_env_with_schema(&cognee::config::schema_with(…)?), or the CLI’sload_settings_with_schema.
Settings, in its flattened sections map, so
config files and binding settings objects carry them unchanged. A factory reads
its typed section from the build context with ctx.section::<T>(). A section key,
its canonical key and its aliases are all accepted by ConfigManager::set /
get; set and unset also clear any alias spelling of the setting. When a
loaded config carries one setting under both its canonical key and an alias, the
canonical value wins and the alias is dropped with a warning, so a stale flat key
(llm_api_key from an older config file) never overrides what an env var, a CLI
flag or set wrote under llm.api_key. cognee-cli rewrites those flat keys to
canonical ones when it loads a pre-v4 config file.
The TS and Java constructors also accept a section key with its dots flattened to
underscores (llm_debug_requests), so the camelCase keys a TS config.get()
returns can be passed back to new Cognee(...): a section key with a Python alias
reads back under the alias’s camelCase (llm.auto_rate_limit -> autoRateLimit),
one without an alias with its dots as word breaks (llm.debug_requests ->
llmDebugRequests). Two sections claiming the same key, alias or primary env var
is a registration error. So is a section claiming a Settings key.
Unknown keys and strict mode
A key can be unknown because it is misspelled, or because the component that owns it is not compiled into, or registered with, this build. The two look the same, so the policy is a setting:cognee-cli config unset <key> removes a stale entry even in strict mode, so a
config can always be repaired. cognee-cli config set / unset see strict mode
the way every other command does: the saved strict_config with
COGNEE_STRICT_CONFIG overlaid.
A value of the wrong type for a known key is always an error. From set it fails
the call; in a loaded config it is dropped (the setting keeps its default) and the
error is raised at first use, as for an unknown key in strict mode, until the key
is set again. A loaded config may also carry keys under a name serde does not
know: a section key’s flat alias (such as llm_args for llm.args, or
embedding_model for embedding.model) or the in-memory summarization_schema
setting. Those are applied as the setting they name, not treated as unknown.
A setting marked secret (a registry row or a section key) is masked as
***REDACTED*** (cognee_config_core::REDACTED) in every binding’s
config.get() output when it is set. An unset secret (null, or "" for a
string-typed one) is shown as itself: its emptiness reveals nothing, and the
marker would claim it is set (cognee_config_core::secret_is_set /
mask_secret).
Debug output follows the same rule, so {:?} of a configuration does not
print credentials:
- a
config_section!struct prints a set secret field as***REDACTED***and an unset one as itself (None,""). Every other field prints its ownDebugwith embedded credentials masked (cognee_config_core::redact_credentials): the password of a URL (postgres://cognee:***REDACTED***@db/cognee) and the value of a password-likekey=valuepair (a query parameter such assslpassword=, or a libpq keyword DSN such ashost=db password=…). This covers the connection URLs (relational.url/DATABASE_URL,relational.migration_url,vector.url,graph.url), which are not markedsecretbecause they are mostly not credentials; Settingsprints every setting as JSON with the same masking. Asectionsentry no built-in section owns (a custom registry’s, or a stale one) is masked when it is a non-empty string, because only its owner knows whether it is a credential;LlmConfigandEmbeddingConfigmask their API keys and their endpoint’s credentials;AwsInputs/AwsSettingsmask their credentials;cognee_observability::EnvSettingsView(the process-level OTEL settings every binding builds) masks its OTLP headers, likeotel_exporter_otlp_headersinSettings, and its endpoint’s credentials.
Resolving from something other than the process environment
The boundary loaders read through anEnvSource (from the
cognee-config-core
crate), so you can hand them a MapEnv — an in-memory set of variables — instead
of mutating the shared process environment:
Settings::overlay_from(&dyn EnvSource)— same rules asoverlay_from_env()(only set, non-empty variables change a field), but it reads only the source it is given and does not load.env.EnvSourceandMapEnvare re-exported ascognee::config::{EnvSource, MapEnv}.LoggingConfig::from_env_source(&dyn EnvSource)EnvSettingsView::from_env_source(&dyn EnvSource)(observability; andoverlay)TelemetryConfig::from_env_source(&dyn EnvSource)(product analytics)
from_env() / overlay_from_env() entry points are thin boundaries over these.
A few conventional variables are deliberately read straight from the environment
and are not part of any config struct: proxy variables, HOME, the AWS default
credential chain, COGNEE_CONFIG_HOME (it locates the config file itself),
COGNEE_BINDING_SUPPRESS_LOGS (read at module load, before user code runs) and
LOG_FILE_NAME (hands the log file to child processes).
Inside cognee-rs, the rule is enforced by clippy::disallowed_methods in the root
clippy.toml and
the scripts/check_env_boundary.sh
ratchet. Contributors adding a setting should follow the checklist in
upstream docs/configuration.md § Adding a setting.
Runtime configuration API
ConfigManager (Arc<RwLock<Settings>>) is the runtime API that the bindings
and the CLI use.
- Generic setter:
set(key, value)accepts every key in the key registry (eachSettingsfield name, plus aliases such asembedding_model) and every key of a registered component section, canonical or alias (see Component config sections). An unknown key follows strict mode.get(key)reads any of them. A JSONnullclears the optional settings (chunk_size,llm_temperature,summarization_schema). Settingsystem_root_directoryalso moves the graph and vector paths derived from the old root. - Typed setters for the common keys, in the families
set_llm_*,set_embedding_*,set_vector_db_*,set_graph_*,set_chunk_*,set_relational_db_*,set_*_root_directory,set_ontology_*,set_classification_model/set_summarization_model/set_summarization_schema. - Bulk setters:
set_llm_config,set_embedding_config,set_vector_db_configandset_graph_db_config. - Introspection:
read(),version(),get_settings()(secrets masked).Settings::get_key/set_key/reset_keywork on a plainSettings,cognee::config::keys()lists the registry, andConfigManager::schema()the component sections it knows.ConfigManager::apply_patchapplies a settings object in bulk, which is how the C and Python constructors take theirs.
ConfigManager rustdoc.
The binding ergonomics (granular JS setters vs generic set in Python/C/Java) are
documented in Language bindings: configuration.
CLI config subcommand
cognee-cli config get|set|unset|list|reset reads/writes the persisted JSON file.
The settable keys are the registry keys whose value is saved in that file
(every Settings field except llm_args and summarization_schema), plus the
keys of the component sections compiled into this build. cognee-cli config list
prints them. Example: