Skip to main content
Canonical reference for configuring cognee-rust. The complete, field-level source of truth is the 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 a Settings 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:
  1. Defaults — Settings::default() in crates/lib/src/config.rs.
  2. Persisted config file (CLI only) — JSON at ~/.config/cognee-rust/config.json ($XDG_CONFIG_HOME/cognee-rust/config.json), managed by cognee-cli config. See crates/cli/src/config_store.rs.
  3. .env file — loaded into the process environment by Settings::overlay_from_env() (via cognee_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.
  4. Process environment — bound by Settings::overlay_from_env().
  5. Explicit code — ConfigManager setters (below), a binding’s constructor settings object, the binding config APIs, and CLI --flags.
So: defaults < config.json < .env < env < code. Parsing notes:
  • Booleans accept true|1|yes|on and false|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, -1 or 5000000000 keeps 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, 0 included; 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 in Settings. 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.
The component’s factory returns the section from 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 same ConfigManager::set, binding set and 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(&registry.config_schema()?);
  • HandleState::from_env_with_registry(registry) in the bindings;
  • Settings::load_from_env_with_schema(&cognee::config::schema_with(…)?), or the CLI’s load_settings_with_schema.
Adding the sections afterwards makes their keys settable, but cannot read their env vars. Section values travel inside 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 own Debug with embedded credentials masked (cognee_config_core::redact_credentials): the password of a URL (postgres://cognee:***REDACTED***@db/cognee) and the value of a password-like key=value pair (a query parameter such as sslpassword=, or a libpq keyword DSN such as host=db password=…). This covers the connection URLs (relational.url / DATABASE_URL, relational.migration_url, vector.url, graph.url), which are not marked secret because they are mostly not credentials;
  • Settings prints every setting as JSON with the same masking. A sections entry 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;
  • LlmConfig and EmbeddingConfig mask their API keys and their endpoint’s credentials; AwsInputs / AwsSettings mask their credentials;
  • cognee_observability::EnvSettingsView (the process-level OTEL settings every binding builds) masks its OTLP headers, like otel_exporter_otlp_headers in Settings, and its endpoint’s credentials.
The masking is best effort for the shapes above; a credential in a free-form value of some other shape is not recognised.

Resolving from something other than the process environment

The boundary loaders read through an EnvSource (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 as overlay_from_env() (only set, non-empty variables change a field), but it reads only the source it is given and does not load .env. EnvSource and MapEnv are re-exported as cognee::config::{EnvSource, MapEnv}.
  • LoggingConfig::from_env_source(&dyn EnvSource)
  • EnvSettingsView::from_env_source(&dyn EnvSource) (observability; and overlay)
  • TelemetryConfig::from_env_source(&dyn EnvSource) (product analytics)
The 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 (each Settings field name, plus aliases such as embedding_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 JSON null clears the optional settings (chunk_size, llm_temperature, summarization_schema). Setting system_root_directory also 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_config and set_graph_db_config.
  • Introspection: read(), version(), get_settings() (secrets masked). Settings::get_key / set_key / reset_key work on a plain Settings, cognee::config::keys() lists the registry, and ConfigManager::schema() the component sections it knows. ConfigManager::apply_patch applies a settings object in bulk, which is how the C and Python constructors take theirs.
Full signatures are in the 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: