Action Restrictions and Permissions › Combining Restrictions, Confirmations, and Permissions

Michael BrenndoerferAugust 14, 20252 min read
AI Agent HandbookAll chapters
Part 13 of 15Safety and Governance - Keeping the Agent Aligned
Chapter 37Action Restrictions and Permissions › Combining Restrictions, Confirmations, and Permissions
Reading section 7 of 11 · Combining Restrictions, Confirmations, and Permissions · 2 minSection 7 of 11 · 2 min

Book contents

Section 7 of 11 · 2 min read

Action Restrictions and Permissions › Combining Restrictions, Confirmations, and PermissionsOne section · Sections in this chapter7 / 11 ↓

The most robust approach combines all three techniques:

  1. Permissions define what the agent is allowed to do in principle
  2. Restrictions limit the scope of allowed actions (which files, which recipients, etc.)
  3. Confirmations require user approval for high-stakes actions

Here's how they work together:

In[11]:
Code
## Using Claude Sonnet 4.5 for comprehensive action safety
class SafeAgent:
    def __init__(self, permissions: Set[Permission]):
        self.permissions = PermissionManager(permissions)
        self.client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
        self.pending_confirmations = {}
    
    def send_email(self, to_address: str, subject: str, body: str) -> str:
        """Send an email with permission check, restriction, and confirmation"""
        # Step 1: Check permission
        self.permissions.require_permission(
            Permission.SEND_EMAIL,
            f"Sending email to: {to_address}"
        )
        
        # Step 2: Check restrictions
        if to_address not in ALLOWED_RECIPIENTS:
            domain = to_address.split('@')[1] if '@' in to_address else ''
            if domain not in ALLOWED_DOMAINS:
                return f"Error: Cannot send email to {to_address}. Not in allowed recipients."
        
        # Step 3: Request confirmation
        confirmation_id = f"email_{len(self.pending_confirmations)}"
        self.pending_confirmations[confirmation_id] = {
            'action': 'send_email',
            'params': {
                'to_address': to_address,
                'subject': subject,
                'body': body
            }
        }
        
        return f"""Ready to send email:

To: {to_address}
Subject: {subject}
Body: {body}

Confirm with: agent.confirm('{confirmation_id}')
Cancel with: agent.cancel('{confirmation_id}')"""
    
    def confirm(self, confirmation_id: str) -> str:
        """Execute a pending action after confirmation"""
        if confirmation_id not in self.pending_confirmations:
            return "No pending action with that ID."
        
        action_data = self.pending_confirmations[confirmation_id]
        
        if action_data['action'] == 'send_email':
            params = action_data['params']
            result = send_email_restricted(
                params['to_address'],
                params['subject'],
                params['body']
            )
            del self.pending_confirmations[confirmation_id]
            return f"Confirmed. {result}"
    
    def cancel(self, confirmation_id: str) -> str:
        """Cancel a pending action"""
        if confirmation_id not in self.pending_confirmations:
            return "No pending action with that ID."
        
        del self.pending_confirmations[confirmation_id]
        return "Action cancelled."

This gives you defense in depth. If one layer fails, the others provide backup protection:

  • If the agent somehow bypasses the permission check, the restriction will still block unauthorized recipients
  • If the restriction is misconfigured, the confirmation gives the user a chance to catch the error
  • If the user accidentally confirms, the permission log provides an audit trail