Skip to content
BotServBotServ
Tool PermissionsLeast PrivilegeSecurityAI AgentsAccess Control

Tool Permissions for AI Agents

Configure tool permissions for AI agents. Least privilege, roles, access control, audit, and best practices.

S

schutzgeist

8 min read
Tool Permissions for AI Agents

Tool Permissions for AI Agents

What this article covers

  • How to configure tool permissions for AI agents
  • How to implement least privilege, roles, and approvals
  • How to restrict, monitor, and audit tool access
  • Practical examples for filesystem, network, and shell tools
  • Best practices for security, hierarchy, and human-in-the-loop

Introduction: Understanding tool permissions for AI agents

AI agents call tools to accomplish tasks: reading files, sending emails, executing shell commands. Each tool is a capability the agent can use. Give an agent too many tools and it can do too much. Give it too few and it cannot complete its mission. Tool permissions constrain agent access to only those tools it actually needs.

This article is for developers building and securing AI agents. You should be familiar with AI agents and how function calling works. Python fundamentals are available on IRC-Coding.de.

Why do you need tool permissions?

Imagine building an agent to answer emails. You give it tools for email sending, filesystem access, and shell execution. The agent should only reply to emails, yet now it can delete files or run arbitrary shell commands. If the agent is compromised via prompt injection, it could perform destructive actions.

Tool permissions solve this: the agent gets only the tools needed for its task. An email agent gets email tools, not shell access. A file agent gets read permissions, not write permissions. This principle is called least privilege.

Tool permissions explained

Tool permissions control what tools an agent can access. The agent receives only those tools it needs for its assigned task, with the minimum rights necessary. This follows the principle of least privilege: as many permissions as required, as few as possible.

The core idea: an agent whose job is to answer emails needs no shell access.

Who should read this

  • Developers building and securing AI agents
  • Security teams defining agent permissions
  • System administrators running agents in production
  • Organizations deploying agents safely

Prerequisites include experience with Python, AI agents, and function calling.

Key concepts

  • Tool permission - right to use a specific tool. Use when: establishing baseline access control
  • Least privilege - principle of minimal permissions. Use when: implementing security standards
  • Role - collection of permissions. Use when: managing access across multiple agents
  • Approval - human confirmation for a tool call. Use when: guarding critical actions
  • Audit - logging all tool invocations. Use when: demonstrating accountability
  • AI agents - programs that invoke tools. Use when: determining what needs protection
  • Function calling - structured AI responses. Use when: understanding how tools are invoked
  • Human approval - human-in-the-loop verification. Use when: controlling sensitive operations
  • Sandbox environments - isolated execution. Use when: running untrusted code
  • Prompt injection protection - defense against manipulation. Use when: permissions alone are insufficient

Permission levels

Tools can be offered at different levels:

LevelDescriptionExample
Full accessAgent can use tool without approvalread_file for logs
Approval requiredAgent can use tool, but human must confirmsend_email
RestrictedAgent can use tool with parameter limitsread_file only in /data/
DisabledTool is unavailableexecute_shell for email agent

Implementing a permission system

Tool definition with permissions

from enum import Enum

class Permission(Enum):
    ALLOWED = "allowed"
    REQUIRES_APPROVAL = "requires_approval"
    RESTRICTED = "restricted"
    DISABLED = "disabled"

class Tool:
    def __init__(self, name, description, permission, parameters=None, restrictions=None):
        self.name = name
        self.description = description
        self.permission = permission
        self.parameters = parameters or {}
        self.restrictions = restrictions or {}

    def can_execute(self, parameters=None):
        if self.permission == Permission.DISABLED:
            return False
        if self.permission == Permission.RESTRICTED:
            return self.check_restrictions(parameters)
        return True

    def check_restrictions(self, parameters):
        for key, allowed_values in self.restrictions.items():
            if key in parameters:
                if parameters[key] not in allowed_values:
                    return False
        return True

Defining roles

class Role:
    def __init__(self, name, tools):
        self.name = name
        self.tools = {t.name: t for t in tools}

    def get_tool(self, tool_name):
        return self.tools.get(tool_name)

    def can_use(self, tool_name):
        return tool_name in self.tools and self.tools[tool_name].permission != Permission.DISABLED

# Define roles
email_agent_role = Role("email_agent", [
    Tool("read_email", "Read email", Permission.ALLOWED),
    Tool("send_email", "Send email", Permission.REQUIRES_APPROVAL),
    Tool("classify_email", "Classify email", Permission.ALLOWED),
    Tool("execute_shell", "Execute shell command", Permission.DISABLED),
])

file_agent_role = Role("file_agent", [
    Tool("read_file", "Read file", Permission.RESTRICTED, restrictions={
        "path": ["/data/", "/tmp/"]
    }),
    Tool("write_file", "Write file", Permission.REQUIRES_APPROVAL, restrictions={
        "path": ["/data/"]
    }),
    Tool("delete_file", "Delete file", Permission.REQUIRES_APPROVAL),
    Tool("execute_shell", "Execute shell command", Permission.DISABLED),
])

Agent with permissions

class SecureAgent:
    def __init__(self, role, model="llama3.1"):
        self.role = role
        self.model = model

    def call_tool(self, tool_name, parameters):
        # Check permission
        tool = self.role.get_tool(tool_name)
        if not tool:
            raise PermissionError(f"Tool {tool_name} not available in role {self.role.name}")

        if not tool.can_execute(parameters):
            raise PermissionError(f"Tool {tool_name} cannot execute with these parameters")

        # Approval needed?
        if tool.permission == Permission.REQUIRES_APPROVAL:
            approved = request_human_approval(tool_name, parameters)
            if not approved:
                return {"status": "denied", "reason": "Human approval denied"}

        # Execute tool
        result = execute_tool(tool_name, parameters)

        # Audit log
        audit_log(tool_name, parameters, result)

        return result

Practical Example 1: Email Agent with Permissions

# Define role
email_role = Role("email_agent", [
    Tool("read_email", "Read email", Permission.ALLOWED),
    Tool("send_email", "Send email", Permission.REQUIRES_APPROVAL),
    Tool("delete_email", "Delete email", Permission.REQUIRES_APPROVAL),
    Tool("execute_shell", "Shell", Permission.DISABLED),
    Tool("read_file", "Read file", Permission.RESTRICTED, restrictions={
        "path": ["/data/templates/"]
    }),
])

# Create agent
agent = SecureAgent(email_role)

# Allowed: read email
agent.call_tool("read_email", {"id": 123})

# Allowed with approval: send email
agent.call_tool("send_email", {"to": "user@example.com", "subject": "Test"})

# Forbidden: execute shell
try:
    agent.call_tool("execute_shell", {"command": "rm -rf /"})
except PermissionError:
    print("Shell execution forbidden")

Practical Example 2: File Agent with Path Restrictions

file_role = Role("file_agent", [
    Tool("read_file", "Read file", Permission.RESTRICTED, restrictions={
        "path": ["/data/", "/tmp/"]
    }),
    Tool("write_file", "Write file", Permission.RESTRICTED, restrictions={
        "path": ["/data/"]
    }),
])

agent = SecureAgent(file_role)

# Allowed: read file in /data/
agent.call_tool("read_file", {"path": "/data/document.txt"})

# Forbidden: read file in /etc/
try:
    agent.call_tool("read_file", {"path": "/etc/passwd"})
except PermissionError:
    print("Access to /etc/ forbidden")

Practical Example 3: Code Agent with Sandbox

code_role = Role("code_agent", [
    Tool("write_code", "Write code", Permission.ALLOWED, restrictions={
        "language": ["python", "javascript"]
    }),
    Tool("run_code", "Run code", Permission.REQUIRES_APPROVAL, restrictions={
        "sandbox": ["docker", "firejail"]
    }),
    Tool("read_file", "Read file", Permission.RESTRICTED, restrictions={
        "path": ["/workspace/"]
    }),
    Tool("write_file", "Write file", Permission.RESTRICTED, restrictions={
        "path": ["/workspace/"]
    }),
])

# Code execution only in sandbox
agent = SecureAgent(code_role)
agent.call_tool("run_code", {
    "code": "print('Hello')",
    "sandbox": "docker"
})

See Sandbox Environments for details.

Human-in-the-Loop for Critical Actions

def request_human_approval(tool_name, parameters):
    print(f"\n--- Approval Required ---")
    print(f"Tool: {tool_name}")
    print(f"Parameters: {parameters}")
    print(f"Approve? (y/n): ")

    response = input().strip().lower()
    return response == "y"

# In practice: web UI, Slack bot, email confirmation

See Human Approval for details.

Audit Logging for Tool Calls

import json
from datetime import datetime

def audit_log(tool_name, parameters, result, agent_id="default"):
    entry = {
        "timestamp": datetime.now().isoformat(),
        "agent_id": agent_id,
        "tool": tool_name,
        "parameters": parameters,
        "result_status": result.get("status", "unknown"),
        "approved": True
    }
    with open("/var/log/agent_audit.log", "a") as f:
        f.write(json.dumps(entry) + "\n")

See Logging for details.

Security Best Practices

  • Least Privilege: Give the agent only the tools it needs. No shell access for email agents.
  • Approval for Critical Actions: Deletion, sending, and execution should require approval.
  • Audit Logging: Log all tool calls with parameters and results.
  • Prompt Injection Protection: Permissions alone are not enough. Protect against manipulation. See Prompt Injection Protection.
  • Sandbox for Code Execution: Code agents must run in a sandbox. See Sandbox Environments.
  • Parameter Validation: Check tool parameters, not just tool names. Path restrictions, command whitelists.
  • Regular Review: Check permissions regularly. Does the agent still need all its tools?

Common Pitfalls

  • Too Many Tools: The agent gets all tools because it’s easier. Security risk.
  • No Approval for Critical Actions: Deletion without approval is dangerous.
  • No Parameter Validation: Tool is allowed, but parameters are not checked. Path traversal becomes possible.
  • No Audit Logging: Without logs, there’s no accountability.
  • Permissions Never Reviewed: The agent no longer needs a tool, but keeps it anyway.
  • Prompt Injection Overlooked: The agent gets manipulated, permissions bypassed.

Further Reading and Resources on Tool Permissions

Key Takeaways:

  • Tool permissions restrict an agent’s access to tools.
  • Least Privilege: as much access as necessary, as little as possible.
  • Require approval for critical actions: deletion, sending, execution.
  • Validate parameters: check not just tool names, but also parameters.
  • Audit log all tool calls.

FAQ: Tool Permissions for AI Agents - Common Questions

What are tool permissions?

Tool permissions are a concept for restricting an AI agent’s access to tools. The agent receives only the tools it needs, with minimal privileges.

What is Least Privilege?

Least Privilege is the principle of granting an agent only the minimum rights needed to perform its task. As much access as necessary, as little as possible.

When do I need human-in-the-loop?

For critical actions: deletion, sending, code execution, database changes. The agent executes the action only after a human approves it.

Why parameter validation?

A tool can be allowed, but its parameters can be dangerous. For example, read_file is allowed, but the path /etc/passwd is forbidden. Always validate parameters as well.

How do I define roles?

A role is a set of tools with permissions. An email agent gets email tools, a file agent gets file tools, a code agent gets code tools with sandbox.

Why audit logging?

Audit logging records all tool calls with parameters and results. This lets you trace what the agent did, which is critical for security and compliance.

Do permissions protect against prompt injection?

Partially. Permissions restrict which tools the agent can call. But prompt injection can trick the agent into misusing allowed tools. Combine permissions with prompt injection protection.

When do I need a sandbox?

When the agent executes code. Code execution must run in an isolated environment (Docker, Firejail) so the agent cannot harm the host system.

How often should I review permissions?

Regularly, for example monthly. Check whether the agent still needs all its tools. Remove tools that are no longer required. Least Privilege is an ongoing process, not a one-time setup.

How many tools should an agent have?

As few as possible, as many as necessary. An email agent needs 3 to 5 tools. A code agent needs 5 to 10 tools. More tools means more attack surface.

References and Further Reading

Back to Blog
Share:

Related Posts