Decides whether a tool call is allowed.
Every tool call runs through check/4 before execution. The check combines
three sources — in this order, first decisive wins:
disallowed_tools— an explicit blocklist. Always denies.allowed_tools— an explicit allowlist. If non-nil, denies anything not in it.phase— the current permission mode::plan— read-only. Writes and shell execution are denied.:default— read + write.can_use_toolcallback (if supplied) can ask the user.:bypass_permissions— everything allowed without asking.
The can_use_tool callback is a function (tool_name, arguments, ctx -> :allow | :deny | {:deny, reason}) that the loop calls in :default mode
for anything the caller marked as sensitive. See Permissions.Opts below.
Summary
Functions
Check whether tool_call is allowed under opts. Returns :allow or
{:deny, reason}.
Static list of read-only tool names the :plan phase permits.
Types
@type opts() :: %{ optional(:phase) => ExAthena.ToolContext.phase(), optional(:allowed_tools) => [String.t()] | nil, optional(:disallowed_tools) => [String.t()] | nil, optional(:can_use_tool) => (String.t(), map(), ExAthena.ToolContext.t() -> result()) }
@type result() :: :allow | {:deny, reason :: term()}
Functions
@spec check(ExAthena.Messages.ToolCall.t(), ExAthena.ToolContext.t(), opts()) :: result()
Check whether tool_call is allowed under opts. Returns :allow or
{:deny, reason}.
@spec readonly_tools() :: [String.t()]
Static list of read-only tool names the :plan phase permits.