pub struct Config {Show 27 fields
pub default_provider: String,
pub providers: ProviderConfig,
pub agent_paths: Vec<PathBuf>,
pub openrouter_api_key: Option<String>,
pub ollama_base_url: Option<String>,
pub mcp_servers: Vec<MCPServerConfig>,
pub default_model: Option<String>,
pub model_capabilities: HashMap<String, ModelCapabilityOverride>,
pub model_providers: HashMap<String, ModelProviderConfig>,
pub tool_permissions: HashMap<String, ToolPolicy>,
pub agent_tool_permissions: HashMap<String, HashMap<String, ToolPolicy>>,
pub safe_commands: SafeCommands,
pub agent_safe_commands: HashMap<String, AgentSafeCommands>,
pub title: TitleConfig,
pub request_timeout_secs: Option<u64>,
pub rate_limits: HashMap<String, RateLimitConfig>,
pub taint_tracking: bool,
pub limits: LimitsConfig,
pub batch_tool_hint: bool,
pub shell_hint: bool,
pub nudge: NudgeConfig,
pub webhook: WebhookConfig,
pub observability: ObservabilityConfig,
pub sandbox: Option<ToolSandboxConfig>,
pub tool_script_permissions: ScriptToolPermissions,
pub security: SecurityConfig,
pub agent_read_paths: HashMap<String, ReadPathGrants>,
}Expand description
CLI configuration.
Fields§
§default_provider: StringDefault provider
providers: ProviderConfigProvider API keys
agent_paths: Vec<PathBuf>Agent project paths
openrouter_api_key: Option<String>OpenRouter API key
ollama_base_url: Option<String>Ollama base URL (default http://localhost:11434)
mcp_servers: Vec<MCPServerConfig>MCP server configurations
default_model: Option<String>Default model override
model_capabilities: HashMap<String, ModelCapabilityOverride>Per-model capability overrides. Key is model ID (e.g. “my-local-llama”). Takes precedence over the provider’s built-in capability table.
model_providers: HashMap<String, ModelProviderConfig>Optional overrides for Rhai script providers. Key is the
provider name an agent references (e.g. "groq"). A script activates by
being referenced + its .rhai file existing in the providers dir; an
entry here only supplies overrides (an API key not read from env, a
base_url, a rate_limit, a differently-named script, or extra keys
forwarded to the script’s initialize).
tool_permissions: HashMap<String, ToolPolicy>Global tool permission overrides.
Keys are tool names (e.g. "bash", "write_file"). Values override the
built-in defaults, and act as a ceiling that a blueprint’s own
[tool_permissions] may tighten but never loosen - see
crate::tools::resolve_policy. To grant one agent more than this
without loosening it everywhere, use Self::agent_tool_permissions.
agent_tool_permissions: HashMap<String, HashMap<String, ToolPolicy>>Per-agent tool permission grants, keyed by agent name.
[agent_tool_permissions.coder]
shell = "allow"This is the escape hatch for the ceiling in Self::tool_permissions.
Because a blueprint may only tighten what the user configured, a global
shell = "ask" would otherwise stop a trusted agent from pre-approving
its own shell. Naming the agent here is the user saying “I trust this
one” - a decision that lives in the user’s config, not the downloaded
manifest’s. Entries replace the global value for that agent, and are then
the ceiling the blueprint is clamped against.
safe_commands: SafeCommandsWhat a run may do without asking, for tools whose policy is ask.
ask is all-or-nothing per tool name, which for the shell means
choosing between a prompt on every ls and no prompt on
curl evil | sh. Entries here are argument-scoped, in the same key space
a “for this run” grant uses:
[safe_commands]
defaults = true # ship the read-only verb list
tools = ["read_files"]
shell = ["cargo test", "rg"] # `cargo test` never covers `cargo publish`A safe entry can only ever turn ask into allow. It never reaches a
configured deny.
agent_safe_commands: HashMap<String, AgentSafeCommands>Per-agent additions to Self::safe_commands, keyed by agent name.
[agent_safe_commands.coder]
shell = ["./gradlew", "ninja"]
allow_blueprint = trueMirrors Self::agent_tool_permissions and Self::agent_read_paths:
naming the agent is the user saying “I trust this one”.
title: TitleConfigTitle-generation configuration.
Controls whether a short human-readable title is auto-generated from the task prompt at worker startup.
request_timeout_secs: Option<u64>Request timeout in seconds for HTTP calls to provider APIs. Unset, the
providers fall back to the unified 15-minute ceiling
(leviath_providers::DEFAULT_INFERENCE_TIMEOUT_SECS) - there is
always SOME timeout, because a call that never completes wedges its
run with no error. A stage’s [stages.<name>.model] request_timeout_secs overrides either value for that stage’s requests.
rate_limits: HashMap<String, RateLimitConfig>Client-side rate limits for the built-in providers, keyed by provider
name (anthropic, openai, google, openrouter).
[rate_limits.anthropic]
requests_per_minute = 50
tokens_per_minute = 40000Script providers configure theirs via
[model_providers.<name>] rate_limit instead.
taint_tracking: boolGlobal master switch for taint tracking / data-flow enforcement.
Off by default (opt-in). When true, every agent enforces taint
tracking by default; individual agents or stages can opt out via a
[security] taint_tracking = false block. When false, an agent still
opts in by setting taint_tracking = true in its own [security].
limits: LimitsConfigRuntime resource limits (inference concurrency + iteration caps).
batch_tool_hint: boolGlobal master switch for the batch-tool-calls system-prompt hint.
On by default (opt-out). When true, every stage’s request carries a
short hint telling the model it may emit several tool_use blocks in one
response and should batch independent operations (but never dependent
ones) to cut API round trips. Individual agents or stages can opt out by
setting batch_tool_hint = false in their [agent] / [stages.<name>]
blocks; when this global is false, they opt back in by setting it to
true at the narrower scope.
shell_hint: boolGlobal master switch for the platform shell hint.
On by default (opt-out). When true, a stage that advertises the
shell tool carries a short system block describing the shell it will
actually get, so the model doesn’t spend iterations discovering it. The
hint is emitted only where the platform warrants one (today: Windows,
where commands run through cmd.exe /C rather than a POSIX shell), so
on Linux and macOS this toggle costs nothing either way. Individual
agents or stages override it with shell_hint in their [agent] /
[stages.<name>] blocks.
nudge: NudgeConfigMachine-wide defaults for the empty-response nudge ([nudge]): the
[System] message injected when a stage’s model replies with text
before making any tool call. All three keys (enabled, max, text)
are optional; an agent’s [agent.nudge] or a stage’s
[stages.<name>.nudge] overrides each field independently. See
leviath_core::resolve_nudge.
webhook: WebhookConfigCompletion-webhook delivery tuning (retry/backoff/timeout).
observability: ObservabilityConfigStructured observability export (OpenTelemetry). Off by default; when
enabled the daemon exports run/stage/inference/tool spans, metrics, and
trace-correlated log records for every agent run. The standard
OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_SERVICE_NAME env vars fill any
hole the file leaves, same as the provider keys.
sandbox: Option<ToolSandboxConfig>Machine-wide default sandbox for tool execution. An agent’s own
[sandbox] (or a stage’s) overrides this; when unset, agents run tools
on the host unless they opt in themselves. See
leviath_core::resolve_sandbox.
tool_script_permissions: ScriptToolPermissionsPer-host-function permissions for Rhai script tools (Layer 3). Gates what a registered script tool may do (network, shell, file, env access).
security: SecurityConfigMachine-wide security switches that aren’t part of the per-tool
permission cascade. (The global taint master switch stays the top-level
Self::taint_tracking key for back-compat.)
agent_read_paths: HashMap<String, ReadPathGrants>Per-agent read grants, keyed by agent name - the itemized counterpart
of SecurityConfig::allow_blueprint_read_paths, analogous to
Self::agent_tool_permissions:
[agent_read_paths.cto]
allow = ["~/.leviath/runs", "glob:~/design-docs/**"]Naming the agent here is the user saying “I trust this one to read
these” - a decision that lives in the user’s config, not the
downloaded manifest. As with [security] read_paths, a grant only
takes effect for a path the blueprint also declares.
Implementations§
Source§impl Config
impl Config
Sourcepub fn permissions_for_agent(
&self,
agent_name: &str,
) -> HashMap<String, ToolPolicy>
pub fn permissions_for_agent( &self, agent_name: &str, ) -> HashMap<String, ToolPolicy>
The permission ceiling to apply to agent_name: the global
[tool_permissions] with that agent’s [agent_tool_permissions.<name>]
entries laid over it.
Returned by value (rather than as two maps threaded through
crate::tools::resolve_policy) so the ceiling is resolved exactly once,
at spawn, and every later lookup reads a single flat map.
Sourcepub fn safe_keys_for_agent(
&self,
agent_name: &str,
blueprint: Option<&SafeCommandsConfig>,
) -> BTreeMap<String, SafeSource>
pub fn safe_keys_for_agent( &self, agent_name: &str, blueprint: Option<&SafeCommandsConfig>, ) -> BTreeMap<String, SafeSource>
The safe-command keys in effect for agent_name, and where each came
from. Resolved once at spawn, mirroring Self::permissions_for_agent.
blueprint is the manifest’s own [safe_commands], which contributes
only when the user opted in - see
crate::approvals::resolve_safe_keys.
Sourcepub fn read_path_grants_for_agent(&self, agent_name: &str) -> Vec<String>
pub fn read_path_grants_for_agent(&self, agent_name: &str) -> Vec<String>
Every read-path grant that applies to agent_name: the machine-wide
[security] read_paths list plus that agent’s
[agent_read_paths.<name>] entries. Resolved once at spawn, mirroring
Self::permissions_for_agent.
Sourcepub fn load() -> Result<Self>
pub fn load() -> Result<Self>
Load configuration from the default location (~/.leviath/config.toml).
After loading from file (or using defaults), environment variables are checked as fallbacks. Env vars override config file values if set.
Sourcepub fn unread_keys_at(path: &Path) -> Vec<String>
pub fn unread_keys_at(path: &Path) -> Vec<String>
Keys in the config file at path that nothing reads.
The same answer the start-up warning gives, available to anyone who
wants to ask rather than having to catch it scrolling past - which is
what lev doctor does with it. An unreadable or absent file has no
unread keys, because that is a different problem and one the caller has
already reported.
Sourcepub fn load_from_path_public(path: &Path) -> Result<Self>
pub fn load_from_path_public(path: &Path) -> Result<Self>
Load a config from an explicit path (lev mcp uses this to read the
file it is about to rewrite). Public wrapper over the tested load_from_path.
Sourcepub fn save_to_path_public(&self, path: &Path) -> Result<()>
pub fn save_to_path_public(&self, path: &Path) -> Result<()>
Save a config to an explicit path. Public wrapper over save_to_path, for lev mcp rewriting the config file.
Sourcepub fn config_path() -> PathBuf
pub fn config_path() -> PathBuf
Get the path to the config file.
Two overrides, narrowest first: LEVIATH_CONFIG_PATH names this file
exactly, and LEVIATH_HOME (via leviath_core::data_dir) redirects it
along with every other home-relative path.
Honoring both matters. LEVIATH_HOME’s whole purpose is to “redirect
every home-relative path at once” - that is what its doc says and what
tests, sandboxed runs and scratch environments rely on - so a config
path that quietly ignored it would let a run that believes it is
isolated read and write the developer’s real ~/.leviath/config.toml,
the file holding every provider API key. Found by doing exactly that
during live testing.
Sourcepub fn validate_keys(&self) -> Vec<String>
pub fn validate_keys(&self) -> Vec<String>
Validate API key formats and return warnings for suspicious keys.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Config
impl<'de> Deserialize<'de> for Config
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for Config
impl RefUnwindSafe for Config
impl Send for Config
impl Sync for Config
impl Unpin for Config
impl UnsafeUnpin for Config
impl UnwindSafe for Config
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> ConditionalSend for Twhere
T: Send,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> FromTemplate for T
impl<T> FromTemplate for T
Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self using default().
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> Serialize for T
impl<T> Serialize for T
fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>
fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>
Source§impl<T> Template for T
impl<T> Template for T
Source§fn build_template(
&self,
_context: &mut TemplateContext<'_, '_>,
) -> Result<<T as Template>::Output, BevyError>
fn build_template( &self, _context: &mut TemplateContext<'_, '_>, ) -> Result<<T as Template>::Output, BevyError>
entity context to produce a Template::Output.Source§fn clone_template(&self) -> T
fn clone_template(&self) -> T
Clone.