How to Use Tool Allow/Deny Lists with AllowToolsPolicy in aisuite
The AllowToolsPolicy class in aisuite implements a runtime whitelist that permits only specified tool names while rejecting all others, returning a ToolPolicyDecision that blocks unauthorized invocations before they execute.
aisuite provides a structured policy framework for controlling large language model (LLM) agent behavior at the tool level. By implementing tool allow/deny lists with AllowToolsPolicy in aisuite, you can enforce strict security boundaries, ensuring agents invoke only explicitly authorized Python functions while maintaining audit trails through decision metadata.
How AllowToolsPolicy Implements Whitelisting
The AllowToolsPolicy class, defined in aisuite/agents/policies.py (lines 30-40), operates as a gatekeeper between the LLM and your registered functions. When an agent attempts a tool call, the framework passes a ToolPolicyContext object—defined in aisuite/agents/types.py—containing the agent name, tool name, and arguments to the policy's evaluate method.
The constructor signature requires a list of permitted tool names:
def __init__(self, allowed_tools: list[str], reason: Optional[str] = None):
self.allowed_tools = set(allowed_tools) # Converted to set for O(1) lookup
self.reason = reason
The evaluate method returns a ToolPolicyDecision containing an allowed boolean and optional reason string:
def evaluate(self, context: ToolPolicyContext) -> ToolPolicyDecision:
allowed = context.tool_name in self.allowed_tools
return ToolPolicyDecision(
allowed=allowed,
reason=None if allowed else self.reason or "tool not in allowlist",
)
This design ensures that unauthorized tool calls return immediately with a denial reason, preventing the underlying Python function from ever executing. The test suite in tests/agents/test_tool_metadata_policy.py validates these behaviors against concrete scenarios.
Configuring Tool Allow Lists
To restrict an agent to specific capabilities, instantiate AllowToolsPolicy with an explicit list of permitted tool names. The framework matches these names against the tool_name attribute in the ToolPolicyContext, which corresponds to the function name or metadata override specified via the @tool decorator.
from aisuite.agents.policies import AllowToolsPolicy
# Permit only file reading operations
policy = AllowToolsPolicy(
allowed_tools=["read_file"],
reason="Security policy restricts file system access"
)
If you omit the reason parameter, the policy defaults to the message "tool not in allowlist" when denying requests.
Implementing Deny Lists and Alternative Policies
While AllowToolsPolicy provides whitelist functionality, aisuite supports complementary restriction strategies through the same tool_policy interface:
DenyAllToolPolicy: Located in aisuite/agents/policies.py, this class rejects every tool invocation unconditionally, useful for creating read-only agents or testing modes.
Custom ToolPolicy: Implement the ToolPolicy protocol by defining an evaluate method that accepts ToolPolicyContext and returns ToolPolicyDecision. This approach enables complex logic such as time-based restrictions, argument validation, or category-based filtering using metadata attached via the @tool decorator in aisuite/utils/tools.py.
from aisuite.agents.types import ToolPolicyContext, ToolPolicyDecision
class CustomDenyPolicy:
def evaluate(self, context: ToolPolicyContext) -> ToolPolicyDecision:
# Block tools with "delete" in the name
allowed = "delete" not in context.tool_name.lower()
return ToolPolicyDecision(
allowed=allowed,
reason=None if allowed else "Delete operations prohibited"
)
Attaching Policies to Agents
Associate your policy with an agent using the tool_policy parameter in the Agent constructor. You may also pass policies directly to Client.run calls for temporary overrides.
from aisuite import Agent
from aisuite.client import Client
from aisuite.utils.tools import tool
from aisuite.agents.policies import AllowToolsPolicy
@tool
def read_file(path: str) -> str:
"""Read a text file and return its contents."""
with open(path, "r", encoding="utf-8") as f:
return f.read()
@tool
def delete_file(path: str) -> str:
"""Delete the specified file."""
import os
os.remove(path)
return f"Deleted {path}"
# Configure agent with whitelist
agent = Agent(
name="SecureFileAgent",
model="gpt-4o-mini",
tools=[read_file, delete_file],
tool_policy=AllowToolsPolicy(["read_file"]) # delete_file implicitly blocked
)
client = Client()
Complete Working Example
The following implementation demonstrates the full lifecycle: tool registration, policy application, and differentiated execution outcomes based on the allow list.
from aisuite import Agent
from aisuite.client import Client
from aisuite.utils.tools import tool
from aisuite.agents.policies import AllowToolsPolicy
# Step 1: Define tools with optional metadata
@tool(metadata={"risk_level": "low"})
def read_file(path: str) -> str:
"""Read a text file and return its contents."""
with open(path, "r", encoding="utf-8") as f:
return f.read()
@tool
def list_files(directory: str) -> list[str]:
"""Return a list of file names in the directory."""
import os
return os.listdir(directory)
# Step 2: Create agent with explicit allow list
agent = Agent(
name="FileReaderOnly",
model="gpt-4o-mini",
tools=[read_file, list_files],
tool_policy=AllowToolsPolicy(["read_file"]) # Only read_file permitted
)
client = Client()
# Step 3: Execute allowed tool
result = client.run(
agent,
"Please read the content of the file example.txt"
)
print(result.final_output) # Returns file contents
# Step 4: Attempt denied tool
result = client.run(
agent,
"List all files in the current directory"
)
print(result.final_output) # Returns: "Tool call denied: tool not in allowlist"
In this workflow, the read_file invocation succeeds because it appears in the allowed_tools set, while list_files triggers the denial path defined in aisuite/agents/policies.py.
Summary
AllowToolsPolicymaintains an internalsetof permitted tool names initialized via theallowed_toolsparameter, enabling O(1) membership checks during runtime.- The policy evaluates each invocation against
aisuite/agents/policies.pylogic, returning aToolPolicyDecisionwithallowed=Trueonly for whitelisted functions defined in the agent's tool registry. - Attach controls via the
tool_policyargument when constructing anAgentor runningClient.run, with denied calls returning structured reasons before function execution. - Complementary strategies include
DenyAllToolPolicyfor complete restriction or custom implementations of theToolPolicyprotocol defined inaisuite/agents/types.py.
Frequently Asked Questions
What parameters does the AllowToolsPolicy constructor accept?
The __init__ method in aisuite/agents/policies.py accepts two parameters: allowed_tools (a list[str] of permitted tool names) and an optional reason (Optional[str]). The constructor converts the list to a Python set for efficient lookup during evaluation.
How does AllowToolsPolicy determine whether to allow a tool call?
During execution, the policy's evaluate method receives a ToolPolicyContext object containing metadata about the requested invocation, including tool_name. It checks whether context.tool_name exists within self.allowed_tools (the internal set), returning a ToolPolicyDecision with allowed=True only upon match.
Can AllowToolsPolicy function as a deny list instead of an allow list?
No, AllowToolsPolicy specifically implements whitelist functionality. To create a deny list, you must either implement a custom policy class satisfying the ToolPolicy protocol or use DenyAllToolPolicy (which blocks everything) combined with selective overrides. The protocol requires only an evaluate method accepting ToolPolicyContext and returning ToolPolicyDecision.
Where are the ToolPolicyContext and ToolPolicyDecision types defined?
These data structures are defined in aisuite/agents/types.py. ToolPolicyContext encapsulates runtime information including the agent name, tool name, and arguments, while ToolPolicyDecision contains the boolean allowed flag and optional reason string consumed by the framework's execution engine.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →