Canonical manifest and resolver for every user-tunable scalar config option.
This module is the single source of truth for the configuration surface: the
set of options, their types, typed defaults, env-var names, and config.toml
locations. The typed defaults for config-file-only options (notably the
[interpreter] section) live here as module constants, and Settings derives
its dataclass defaults from them — so a default is defined in exactly one place.
resolve_scalar is the shared resolution engine used both by the runtime
(Settings.from_environment) and by the config CLI command, so introspection
can never drift from what the app actually reads. Resolution precedence mirrors
the loaders: a DEEPAGENTS_CODE_-prefixed env var beats the canonical name,
env beats config.toml, and the typed default is the final fallback. A
malformed numeric/list/PTC value, an unrecognized boolean token, or a
wrong-typed TOML value is logged and falls back to the next layer rather than
raising, so a bad config never blocks startup.
Structured, user-defined config is not a flat scalar option and is parsed by
dedicated typed loaders elsewhere. The manifest references [threads].columns
and [warnings].suppress as STRUCTURED options for discovery; other tables
such as [models.providers.*] and [themes.*] are handled entirely by their
own loaders and the manifest does not enumerate them at all.
Import discipline: the module top level stays stdlib + _env_vars only (both
light) so it is safe to import from config.py at class-definition time without
pulling the heavy model_config/agent runtime onto the startup fast path.
Anything needing model_config (provider credentials, the config path, env-var
prefix resolution) is imported lazily inside functions.
Default wall-clock budget for one Auto classifier decision batch.
Single source of truth shared by the manifest option, the middleware default, and the resolver, so the three cannot drift (pinned by test).
Smallest accepted Auto classifier timeout.
A sanity bound, not a workable budget: at least a second is required for any
provider round trip to have a chance, and below that every gated batch would be
denied as classifier_unavailable. A resolved value under the floor is rejected
and falls through to the next layer / default.
Largest accepted Auto classifier timeout.
The deadline is what stops a stalled classifier from hanging every gated tool call indefinitely, so it stays bounded: a mistyped or hostile override cannot effectively remove it. A resolved value above the ceiling is rejected and falls through to the next layer / default.
Default LangGraph recursion_limit for the main agent.
Single source of truth shared by the runtime.recursion_limit option, the
config.config runnable-config default, and resolve_recursion_limit. Raised
above the LangGraph/SDK default (25) to accommodate deeply nested agent graphs
in long-running sessions without hitting GRAPH_RECURSION_LIMIT.
Smallest accepted recursion_limit; matches the LangGraph default ceiling.
A value below this would break otherwise-valid runs, so a resolved value under the floor is rejected and falls through to the next layer / default.
Largest accepted recursion_limit.
Bounds the graph step budget so a mistyped or hostile override cannot request effectively unbounded traversal. A resolved value above the ceiling is rejected and falls through to the next layer / default.
Context size above which a resumed thread is offered compaction.
Zero or negative disables the suggestion.
Project agent traces fall back to when no project env var is set.
Single source of truth shared by the tracing.langsmith_project option and
config.get_langsmith_project_name.
Visual style for the chat input cursor (a block cell or an underline).
Allowlist derived from CursorStyle so the two never drift.
_env_vars constants intentionally excluded from the option catalog.
Classify a raw env-var string as a truthy, falsy, or unrecognized token.
The single source of truth for which strings count as boolean on/off
values; is_env_truthy and the config resolver both build on it so they
agree on what "recognizably boolean" means.
Load ~/.deepagents/config.toml.
Resolve an option against the environment then config.toml.
Resolve the [interpreter] options into Settings constructor kwargs.
Only the interpreter group is resolved through the manifest. Credentials,
the shell allow-list, and the LangSmith project keep their dedicated
loaders in config.py (their empty-string-to-None and reload semantics
do not fit the generic resolver), so this stays scoped to the section whose
defaults this module owns.
Resolve the Auto classifier decision-batch budget and its source.
Resolve the wall-clock budget for one Auto classifier decision batch.
Resolves models.auto_classifier_timeout through the standard env →
config.toml → default precedence. An out-of-range value (below
AUTO_CLASSIFIER_TIMEOUT_FLOOR or above AUTO_CLASSIFIER_TIMEOUT_CEILING)
is discarded with a logged warning and the next lower-precedence layer is
tried, so a bad higher-precedence override cannot mask a valid TOML setting
(or the default) and can never remove the deadline that keeps a stalled
classifier from hanging every gated tool call.
Resolve the effective main-agent recursion_limit.
Resolves runtime.recursion_limit through the standard env → config.toml
→ default precedence. An out-of-range value (below RECURSION_LIMIT_FLOOR
or above RECURSION_LIMIT_CEILING) is discarded with a logged warning and
the next lower-precedence layer is tried, so a bad higher-precedence
override cannot mask a valid TOML setting (or the default).
Return the deepagents-code extra that installs provider, if known.
Return the PyPI distribution that provides provider, if known.
Derived from the provider's integration import module by replacing
underscores with hyphens (e.g. langchain_google_genai ->
langchain-google-genai), which matches the distribution name for every
curated entry -- see the _PROVIDER_DEPENDENCIES docstring. This is not
PEP 503 normalization, and the result is not validated against PyPI.
Return whether provider's integration package is importable.
Providers without a curated extra (no _PROVIDER_DEPENDENCIES entry) are
reported as installed — they manage their own dependencies, so the app
should never prompt to install an extra for them.
Return every option, credentials-first then by domain group.
Cached: provider credentials are generated once from PROVIDER_API_KEY_ENV
on first call (which lazily imports model_config). The cache assumes that
registry is an immutable module constant; a test that monkeypatches it must
call get_config_options.cache_clear() (and _options_by_key.cache_clear()).
Return the manifest entry for key, or None when unknown.
Return every manifest key in definition order.
Return every option whose key sits under the dotted prefix section.
Matching is exact on segment boundaries: credentials matches
credentials.openai but credential matches nothing, so config get can
accept a section name without also accepting truncated guesses.
Matching is case-insensitive, and key prefixes are the only section
namespace: display group titles (Credentials, Tools) are not accepted,
since several headings (Models, Tools) name a different set of options
than the same word as a prefix — one namespace keeps a section unambiguous.
Return group names from options in first-seen order.
How an option's raw env/TOML value is coerced to a typed value.
All kinds flow through resolve_scalar. The scalar kinds (BOOL,
BOOL_PRESENCE, INT, FLOAT, STR) are coerced inline by
_coerce_env/_coerce_toml. LOG_LEVEL_DELEGATE, SHELL_LIST_DELEGATE,
SKILLS_DIRS_DELEGATE, PTC_DELEGATE, and STARTUP_MODE_DELEGATE defer to
bespoke parsers (their semantics — dynamic debug fallback, colon-split Path
resolution, comma + recommended/all sentinels, and the PTC/startup-mode
allowlists — do not compress into a generic coercion). THEME_DELEGATE is
resolved separately at the top of resolve_scalar and never reaches the
inline coercers. STRUCTURED marks user-defined tables that the scalar
resolver only passes through for display.
One user-tunable configuration option and where it can be set.