Action Restrictions and Permissions › Designing a Permission System
Michael BrenndoerferAugust 14, 20252 min read
AI Agent HandbookAll chapters Part 13 of 15Safety and Governance - Keeping the Agent Aligned
Action Restrictions and Permissions › Designing a Permission SystemOne section · Sections in this chapter6 / 11 ↓
Sections in this chapter11
As your agent grows more capable, you'll want a more structured approach to permissions. Instead of hardcoding restrictions in each tool, you can create a permission system that manages what the agent can do.
Here's a simple permission system:
In[9]:
Code## Using Claude Sonnet 4.5 with a structured permission system
from enum import Enum
from typing import Set, Dict, Any
class Permission(Enum):
READ_FILES = "read_files"
WRITE_FILES = "write_files"
SEND_EMAIL = "send_email"
MAKE_API_CALLS = "make_api_calls"
DELETE_DATA = "delete_data"
class PermissionManager:
def __init__(self, granted_permissions: Set[Permission]):
self.granted_permissions = granted_permissions
self.permission_log = []
def check_permission(self, permission: Permission, action_details: str) -> bool:
"""Check if a permission is granted and log the check"""
has_permission = permission in self.granted_permissions
self.permission_log.append({
'permission': permission.value,
'action': action_details,
'granted': has_permission
})
return has_permission
def require_permission(self, permission: Permission, action_details: str):
"""Raise an error if permission is not granted"""
if not self.check_permission(permission, action_details):
raise PermissionError(
f"Action requires {permission.value} permission: {action_details}"
)
class PermissionedAgent:
def __init__(self, permissions: Set[Permission]):
self.permissions = PermissionManager(permissions)
self.client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
def read_file(self, filename: str) -> str:
"""Read a file if permission is granted"""
self.permissions.require_permission(
Permission.READ_FILES,
f"Reading file: {filename}"
)
# Permission granted, proceed with reading
with open(filename, 'r') as f:
return f.read()
def send_email(self, to_address: str, subject: str, body: str) -> str:
"""Send an email if permission is granted"""
self.permissions.require_permission(
Permission.SEND_EMAIL,
f"Sending email to: {to_address}"
)
# Permission granted, proceed with sending
return send_email_restricted(to_address, subject, body)
def get_permission_log(self) -> list:
"""Get a log of all permission checks"""
return self.permissions.permission_logNow you can create agents with different permission levels:
In[10]:
Code## Create a read-only agent
read_only_agent = PermissionedAgent({
Permission.READ_FILES,
Permission.MAKE_API_CALLS
})
## Create a full-access agent
full_agent = PermissionedAgent({
Permission.READ_FILES,
Permission.WRITE_FILES,
Permission.SEND_EMAIL,
Permission.MAKE_API_CALLS
})
## Try to send an email with the read-only agent
try:
read_only_agent.send_email('alice@example.com', 'Test', 'Hello')
except PermissionError as e:
print(f"Permission denied: {e}")
# Output: Permission denied: Action requires send_email permission:
# Sending email to: alice@example.comOut[10]:
ConsolePermission denied: Action requires send_email permission: Sending email to: alice@example.com
This system gives you several benefits:
Centralized control: All permission logic is in one place, making it easy to audit and modify.
Clear permissions: You can see at a glance what each agent is allowed to do.
Audit trail: The permission log shows every action the agent attempted and whether it was allowed.
Flexible configuration: You can easily create agents with different permission levels for different use cases.