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 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.
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 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 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 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.