Skip to main content

Permissions API

ToolPermissionContext

Passed to the can_use_tool callback as the third argument.

ToolPermissionContext(
signal: Any | None, # reserved for future abort-signal support; always None
suggestions: list[PermissionUpdate], # advisory rule changes accumulated by the framework
)

The tool name and input are passed as the first two positional arguments to the callback, not via the context object:

async def my_guard(
tool_name: str, # first arg — the tool being requested
tool_input: dict, # second arg — the tool's input dict
ctx: ToolPermissionContext,
) -> PermissionResult:
...

PermissionResultAllow

Allow the tool to execute, optionally with a modified input:

from agentix import PermissionResultAllow

# Simple allow
return PermissionResultAllow()

# Allow with input modification
return PermissionResultAllow(
updated_input={**original_input, "command": sanitized_command}
)
FieldTypeDefaultDescription
updated_inputdict | NoneNoneReplacement input; None = use original
updated_permissionsanyNoneAdvisory permission state changes

PermissionResultDeny

Deny the tool from executing:

from agentix import PermissionResultDeny

# Soft deny — agent receives the message and may retry
return PermissionResultDeny(message="Shell access is disabled.")

# Hard deny — raises AgentixInterruptedError immediately
return PermissionResultDeny(message="Blocked.", interrupt=True)
FieldTypeDefaultDescription
messagestr""Reason shown to the agent
interruptboolFalseTrue = hard abort

CanUseTool protocol

The can_use_tool callback type:

from typing import Awaitable, Callable
from agentix import PermissionResultAllow, PermissionResultDeny, ToolPermissionContext

CanUseTool = Callable[
[str, dict, ToolPermissionContext],
Awaitable[PermissionResultAllow | PermissionResultDeny]
]

PermissionUpdate

Advisory rule change carried in ToolPermissionContext.suggestions and returnable via PermissionResultAllow.updated_permissions:

PermissionUpdate(
type: str | None, # "addRules" | "replaceRules" | "removeRules"
# | "setMode" | "addDirectories" | "removeDirectories"
rules: list[PermissionRuleValue] | None,
behavior: str | None, # "allow" | "deny" | "ask"
mode: str | None,
directories: list[str] | None,
)

Permission modes

See Tools & Permissions guide for the full table.

Change permission mode at runtime:

client.set_permission_mode("bypassPermissions")

PermissionHookContext

Fired via the PermissionRequest hook when a permission decision is made:

PermissionHookContext(
tool_name: str,
decision: str, # "allow" | "deny"
session_id: str,
)