# AllowToolsPolicy vs DenyAllToolPolicy in aisuite: Whitelist vs Block-All Tool Security

> Understand the core difference between AllowToolsPolicy and DenyAllToolPolicy in aisuite. Learn how to whitelist specific tools or block all tool requests for robust security.

- Repository: [Andrew Ng/aisuite](https://github.com/andrewyng/aisuite)
- Tags: security-comparison
- Published: 2026-07-27

---

**AllowToolsPolicy creates a selective whitelist that permits only specified tools while rejecting all others, whereas DenyAllToolPolicy unconditionally blocks every tool request regardless of the tool name.**

Both classes implement aisuite's tool-execution gating system, providing granular security controls for AI agents. The functional difference lies in their filtering logic: one applies a positive list for fine-grained access control, while the other acts as a universal kill switch for tool usage.

## Understanding the Tool Policy Interface

Tool policies in aisuite enforce security boundaries by implementing a common evaluation contract. Each policy defines an `evaluate(context)` method that receives a `ToolPolicyContext` object and returns a `ToolPolicyDecision`. This decision contains an `allowed` boolean flag and an optional `reason` string explaining any denials. Both `AllowToolsPolicy` and `DenyAllToolPolicy` inherit this interface, allowing them to be swapped transparently when configuring agents.

## AllowToolsPolicy: Selective Tool Whitelisting

**AllowToolsPolicy** grants execution permission exclusively to tools explicitly listed in its constructor, rejecting any tool calls that fall outside this predefined set.

### Implementation Details

In [`aisuite/agents/policies.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/agents/policies.py) (lines 30-41), the class stores the allowed tool names in an internal set during initialization. When `evaluate(context)` is called, it compares `context.tool_name` against this allow-list. If the tool appears in the set, the method returns a `ToolPolicyDecision` with `allowed=True`; otherwise, it returns `allowed=False` accompanied by either a default or custom rejection reason.

### Use Cases

Deploy this policy when you need surgical control over tool access. For example, allow `read_file` operations while blocking potentially destructive tools like `write_file` or `execute_shell`. This approach follows the principle of least privilege, ensuring agents can only access functionality explicitly deemed safe for a specific workflow.

## DenyAllToolPolicy: Universal Tool Blocking

**DenyAllToolPolicy** functions as a complete circuit breaker, automatically rejecting every tool request without inspecting the tool name or arguments.

### Implementation Details

The implementation in [`aisuite/agents/policies.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/agents/policies.py) (lines 22-27) contains minimal logic: the `evaluate()` method always instantiates and returns a `ToolPolicyDecision` where `allowed=False`. You can optionally supply a reason parameter during construction to customize the denial message, but the rejection logic remains unconditional regardless of context.

### Use Cases

Use this policy for sandboxed environments, testing scenarios, or security-critical executions where tool usage must be completely disabled. It serves as the simplest "deny-everything" default when constructing agents that should operate in reasoning-only mode without external side effects.

## Runtime Execution Flow

When an agent attempts to invoke a tool, the execution flow in [`aisuite/agents/runner.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/agents/runner.py) intercepts the call and instantiates a `ToolPolicyContext` containing the `tool_name` and relevant metadata. The configured policy's `evaluate()` method receives this context and renders its decision. If the decision indicates `allowed=False`, the runtime immediately raises a `ToolDeniedError` and prevents the tool function from executing. This architecture ensures that policy checks occur at the boundary before any tool logic runs.

## Practical Implementation Examples

```python
from aisuite.agents import AllowToolsPolicy, DenyAllToolPolicy
from aisuite import aisuite as ai

# Whitelist approach: only permit file reading

whitelist_policy = AllowToolsPolicy(
    allowed_tools=["read_file"],
    reason="Only read_file is permitted in this run"
)

# Block-all approach: disable tool usage entirely

deny_all_policy = DenyAllToolPolicy(
    reason="Tool usage disabled for this sandboxed session"
)

# Apply policy when constructing an agent

agent = ai.Agent(
    name="secure_agent",
    tools=[ai.tool(my_read_function), ai.tool(my_write_function)],
    tool_policy=whitelist_policy  # Swap to deny_all_policy for complete lockdown

)

# Runtime behavior: read_file executes, write_file raises ToolDeniedError

```

## Summary

- **AllowToolsPolicy** provides positive security by maintaining an allow-list of permitted tools, checking `context.tool_name` against this set before granting execution rights.
- **DenyAllToolPolicy** implements negative security by unconditionally returning `allowed=False` for every request, effectively creating a tool-free execution environment.
- Both policies reside in [`aisuite/agents/policies.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/agents/policies.py) and share the `evaluate(context)` interface defined in [`aisuite/agents/types.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/agents/types.py).
- The runtime enforces these decisions through [`aisuite/agents/runner.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/agents/runner.py), raising `ToolDeniedError` when policies reject tool invocations.
- Policy selection determines whether an agent operates with limited capabilities, specific capabilities, or no external tool access whatsoever.

## Frequently Asked Questions

### How do I configure custom rejection messages for tool denials?

Both `AllowToolsPolicy` and `DenyAllToolPolicy` accept an optional `reason` parameter in their constructors. When a tool request is denied, this string propagates to the `ToolPolicyDecision` and appears in the resulting `ToolDeniedError`. For `AllowToolsPolicy`, this explains why non-listed tools were rejected; for `DenyAllToolPolicy`, it provides the universal explanation for the blanket denial.

### Can I combine multiple policies or create custom logic?

Yes. The policy interface in [`aisuite/agents/types.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/agents/types.py) defines the contract that any custom policy must implement. You can create composite policies that wrap `AllowToolsPolicy` for whitelisting while adding additional runtime conditions, or implement the `evaluate()` method with custom business logic such as time-based restrictions or user-role validation before returning a `ToolPolicyDecision`.

### What happens when a tool request is denied at runtime?

When the policy's `evaluate()` method returns a decision with `allowed=False`, the agent runner in [`aisuite/agents/runner.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/agents/runner.py) immediately raises a `ToolDeniedError` exception. This prevents the actual tool function from executing, ensuring that no side effects occur when security policies block a request. The error includes the reason string provided by the policy for debugging and logging purposes.

### Which policy should I use for production AI agents?

For production deployments, `AllowToolsPolicy` is generally recommended because it follows the principle of least privilege by explicitly enumerating permitted capabilities. `DenyAllToolPolicy` serves best for specialized scenarios such as dry-run testing, compliance audits, or debugging sessions where you must guarantee zero tool execution. Many production configurations combine these with approval callbacks using `RequireApprovalPolicy` for sensitive operations requiring human oversight.