Skip to content

Permissions

The permissions module provides the authorization framework for controlling tool execution in ToolRegistry. It implements a rule-based policy engine with handler protocols for interactive authorization.

Overview

The module consists of four main components:

  • PermissionResult -- Three-state enum (ALLOW, DENY, ASK)
  • PermissionRule -- Match predicate paired with a result
  • PermissionPolicy -- Ordered rule collection with first-match-wins evaluation
  • PermissionHandler / AsyncPermissionHandler -- Protocols for resolving ASK results

For usage guide and examples, see Permission System.

Types

toolregistry.permissions.types

Core types for the permission system.

PermissionRequest

Bases: BaseModel

Context passed to a PermissionHandler when a rule returns ASK.

Attributes:

Name Type Description
tool_name str

Name of the tool being invoked.

parameters dict[str, Any]

Arguments the caller intends to pass.

reason str

Human-readable explanation of why confirmation is needed.

rule_name str

Name of the rule that triggered the ASK result.

metadata ToolMetadata

The tool's ToolMetadata for handler reference.

PermissionResult

Bases: str, Enum

Three-state permission decision.

Attributes:

Name Type Description
ALLOW

The tool call is permitted.

DENY

The tool call is rejected.

ASK

The decision should be delegated to a PermissionHandler.

Handler Protocols

toolregistry.permissions.handler

Permission handler protocols for tool authorization.

AsyncPermissionHandler

Bases: Protocol

Asynchronous handler invoked when a permission rule returns ASK.

Same contract as PermissionHandler but for async contexts.

Example
class WebSocketPermissionHandler:
    async def handle(self, request: PermissionRequest) -> PermissionResult:
        response = await ws.ask_user(request.tool_name, request.reason)
        return PermissionResult.ALLOW if response == "yes" else PermissionResult.DENY

PermissionHandler

Bases: Protocol

Synchronous handler invoked when a permission rule returns ASK.

Implementations decide whether to allow or deny a tool call, typically by prompting the user or consulting an external policy service.

Example
class CLIPermissionHandler:
    def handle(self, request: PermissionRequest) -> PermissionResult:
        answer = input(f"Allow {request.tool_name}? [y/N] ")
        return PermissionResult.ALLOW if answer.lower() == "y" else PermissionResult.DENY

Policy and Rules

toolregistry.permissions.policy

Permission policy: composable rules with first-match-wins evaluation.

PermissionPolicy

Bases: BaseModel

An ordered collection of permission rules with a fallback.

Evaluation follows first-match-wins semantics: rules are checked in list order and the first rule whose match returns True produces the final decision (subject to handler resolution for ASK). If no rule matches, fallback is used.

Attributes:

Name Type Description
rules list[PermissionRule]

Ordered list of permission rules.

fallback PermissionResult

Result when no rule matches. Defaults to DENY (safe by default).

handler PermissionHandler | AsyncPermissionHandler | None

Optional handler invoked when a rule returns ASK. Takes precedence over the registry-level handler set via set_permission_handler().

evaluate

evaluate(tool: Tool, parameters: dict[str, Any]) -> PermissionResult | PermissionRule

Evaluate rules against a tool call.

Returns:

Type Description
PermissionResult | PermissionRule

The matched PermissionRule if a rule matches, or the

PermissionResult | PermissionRule

fallback PermissionResult if no rule matches.

Source code in src/toolregistry/permissions/policy.py
def evaluate(
    self, tool: Tool, parameters: dict[str, Any]
) -> PermissionResult | PermissionRule:
    """Evaluate rules against a tool call.

    Returns:
        The matched ``PermissionRule`` if a rule matches, or the
        ``fallback`` ``PermissionResult`` if no rule matches.
    """
    for rule in self.rules:
        if rule.match(tool, parameters):
            return rule
    return self.fallback

PermissionRule

Bases: BaseModel

A single permission rule that maps a match predicate to a result.

Rules are evaluated in order; the first rule whose match returns True determines the outcome.

Attributes:

Name Type Description
name str

Human-readable identifier for this rule.

match Callable[[Tool, dict[str, Any]], bool]

Predicate receiving (tool, parameters) and returning True when this rule applies.

result PermissionResult

The permission decision when the rule matches.

reason str

Explanation surfaced in PermissionRequest when the result is ASK or DENY.

Built-in Rules

toolregistry.permissions.builtin_rules

Built-in permission rules for common tool classification patterns.