pub fn resolve_policy(
tool_name: &str,
is_builtin: bool,
launch_overrides: &HashMap<String, ToolPolicy>,
stage_permissions: &HashMap<String, String>,
agent_permissions: &HashMap<String, String>,
global_permissions: &HashMap<String, ToolPolicy>,
) -> ToolPolicyExpand description
Resolve the effective policy for a tool call.
Scope order is narrowest-first - stage, then agent, then the user’s global
config, then the built-in default - but narrower does not mean stronger.
The stage and agent layers come out of agent.leviath, which for any agent
installed with lev add is a file the user downloaded. So a blueprint may
only ever tighten what the user configured, never loosen it: whatever the
user explicitly wrote in [tool_permissions] is a ceiling on how permissive
a manifest can be for that tool.
Only an explicitly configured global entry acts as a ceiling. A tool the
user has said nothing about falls through to default_tool_policy, and a
blueprint is free to set it - otherwise no shipped agent could pre-approve
its own tools (the researcher’s web_fetch = "allow" would stop working) and
the model would become a wall rather than a floor.
A user who wants to grant one specific agent more than their global setting
says so in their own config, keyed by agent name - see
crate::config::Config::permissions_for_agent, which is folded into
global_permissions at spawn.
launch_overrides (--allow/--ask/--deny/--yolo) come from the person
at the terminal, so they may relax Ask to Allow. They may not override
a Deny: a denied tool stays denied under --yolo, matching the guarantee
other agent runtimes make about their deny rules. To lift a Deny, edit the
config that set it.