Home/AI Agent Permissions

AI Agent Permissions: Capability-Level Access Control

Not who the agent is. Not what role it belongs to. What it can do, with what arguments, right now. Agent permissions operate at the tool-call boundary, where identity stops and capability begins.

Last updated: April 2026

What are AI agent permissions?

AI agent permissions are capability-level controls that govern which tools an autonomous agent can invoke, with which arguments, and under what conditions. They operate below identity (who) and below roles (what group). They answer the question traditional access control never had to ask: should this specific function call, with these specific parameters, be allowed right now?

Why traditional permission models fail for agents

RBAC was designed for humans clicking buttons in web applications. A human with the "support" role clicks "Issue Refund" maybe ten times a day. The risk surface is small, the actions are deliberate, and a manager reviews the activity weekly. None of these assumptions hold for agents.

Agents operate at machine speed

A human support agent processes 40 tickets per day. An AI agent processes 40 per minute. The same role that was safe for a human becomes dangerous at 1,000x velocity. A "support" role with refund permission becomes a financial liability when the agent can issue thousands of refunds before anyone notices.

Roles do not capture argument risk

In RBAC, "can issue refunds" is a binary capability. But a $5 refund and a $50,000 refund are fundamentally different operations with different risk profiles, different approval requirements, and different audit implications. The tool is the same. The arguments change everything. Roles cannot express this without exploding into thousands of micro-permissions that are impossible to manage.

Agents can be hijacked

A human with the "admin" role will not suddenly start deleting production databases because a customer sent a cleverly worded email. An agent will. Prompt injection can redirect an agent's behavior while its identity and role remain unchanged. Permissions must evaluate the action itself, not just who is taking it.

Context changes the answer

The same tool call can be safe or dangerous depending on context. Deleting a record in a dev environment is routine. Deleting a record in production is an incident. Sending an email to an internal address is fine. Sending an email to a competitor's domain is a data breach. Static roles treat all invocations identically. Agent permissions evaluate each call in context.

What agent permissions look like

Agent permissions are declarative rules that match on tool name, argument values, and runtime context. They are evaluated before the tool executes. The agent never sees the policy. Here is a Veto policy that controls a support agent's ability to issue refunds:

policies:
  - name: allow-small-refunds
    tool: issue_refund
    effect: allow
    conditions:
      - field: args.amount
        operator: lte
        value: 500
      - field: args.currency
        operator: eq
        value: "USD"

  - name: escalate-large-refunds
    tool: issue_refund
    effect: escalate
    conditions:
      - field: args.amount
        operator: gt
        value: 500
    escalation:
      channel: slack
      approvers: ["finance-team"]
      timeout: 30m

  - name: block-production-deletes
    tool: delete_record
    effect: deny
    conditions:
      - field: context.environment
        operator: eq
        value: "production"

Three rules. Three different outcomes for three different situations. The first allows routine small refunds without friction. The second pauses large refunds and sends them to a Slack channel for human approval. The third blocks production deletes entirely. No role definitions. No group memberships. Just direct statements about what is allowed, when, and why.

Four levels of agent permissions

Not all permission granularity is the same. The industry is converging on four levels, each building on the one before it. Most teams start at level one and move down as their agents take on higher-stakes operations.

Level 1: Tool-level allow/deny

Coarsest granularity

Binary access: the agent can or cannot call a given tool. Allow read_file. Deny delete_database. This is the equivalent of a firewall allowlist. Simple to reason about, fast to implement, but too coarse for most production scenarios. It cannot distinguish between safe and dangerous uses of the same tool.

Dead simple to configure
Cannot distinguish safe vs dangerous uses
Near-zero evaluation cost
All-or-nothing: over-permits or over-restricts

Level 2: Argument-level policies

Medium granularity

Policies inspect the arguments of each tool call. Allow send_email but only when to matches *@company.com. Allow issue_refund but only when amount <= 500. This is where permissions start earning their keep. The same tool gets different treatment based on what the agent is actually trying to do with it.

Separates safe from dangerous uses
Static: does not account for runtime context
Readable, auditable rules
Cannot express cross-call patterns

Level 3: Context-aware policies

Fine granularity

Policies evaluate runtime context alongside arguments: environment (dev vs production), time of day, cumulative spend in the current session, the number of similar actions already taken, the agent's conversation history. The same tool call with the same arguments can produce different outcomes depending on when, where, and how often it happens. This is what makes agent permissions fundamentally different from traditional ACLs.

Adapts to runtime conditions
Requires context propagation in your stack
Catches velocity and accumulation attacks
More complex policies to test and maintain

Level 4: Human-in-the-loop escalation

Maximum control

When policy alone cannot determine whether an action is safe, the system pauses execution and routes the decision to a human. The agent waits. A human reviews the tool call, its arguments, the surrounding context, and the matched policy. They approve, deny, or modify. This is the escape valve for high-stakes operations where the cost of a wrong automated decision exceeds the cost of waiting for a human.

Handles ambiguous, high-stakes decisions
Builds trust incrementally with stakeholders
Satisfies regulatory human oversight requirements
Approval via Slack, email, or dashboard

Traditional permissions vs agent permissions

Traditional access control was designed for a world where humans perform discrete actions through predetermined UIs. Agent permissions are designed for a world where autonomous software makes thousands of decisions per hour through arbitrary tool calls.

DimensionTraditional (RBAC/ABAC)Agent permissions
GranularityResource or endpoint levelTool call + argument values
Decision inputIdentity, role, resourceTool, arguments, context, history
Velocity assumptionHuman speed (seconds per action)Machine speed (milliseconds per action)
Bypass riskSocial engineeringPrompt injection, jailbreaks
Context awarenessStatic attributesDynamic runtime context
EscalationOut-of-band (tickets, emails)Inline (pause, route, resume)
AuditAccess logs (who accessed what)Decision logs (what was attempted, why it was allowed/denied)
Policy languageIAM policies, OPA Rego, CedarDeclarative YAML matching tool-call structure

Traditional access control is not wrong. It handles identity and resource-level access well. But it was never designed to evaluate the arguments of a function call in real time or to pause execution and ask a human whether a specific parameter value is acceptable. Agent permissions sit on top of traditional access control, adding the layer that agents require.

How Veto implements agent permissions

Veto is an open-source SDK that wraps your agent's tools and evaluates declarative policies before any tool executes. The agent's code does not change. The model does not know permissions exist.

1

Define policies in YAML

Declarative rules that match on tool name, argument values, and context. Version-controlled alongside your code. Or generate them from natural language in the Veto dashboard.

2

Wrap tools with protect()

Two lines of code. Import the SDK and wrap your tool functions. Every tool call is intercepted before execution. Your agent code does not change. The authorization layer is invisible to the model.

3

Evaluate locally in under 5ms

Policy evaluation runs in-process. No network call. No external service dependency on the critical path. The SDK matches the tool call against your policies and returns allow, deny, or escalate.

4

Log every decision

Tool name, arguments, matched policy, outcome, timestamp, and approver (if escalated). Exportable for SOC 2, HIPAA, and EU AI Act compliance. Searchable in the Veto dashboard.

Frequently asked questions

Why can't I just use RBAC for my AI agents?
Because RBAC assigns a role and grants everything that role can do. An agent with the 'support' role can issue a $10 refund or a $10,000 refund — same role, same permission, wildly different risk. Agent permissions evaluate the actual arguments on every call. Same tool, different amount, different outcome. RBAC can't express that without fragmenting into hundreds of micro-roles nobody can maintain.
My agent only reads data. Do I really need permissions?
An agent with unrestricted read access to your customer database can exfiltrate every record in minutes. Read access means: bulk extraction, PII exposure, competitive intelligence leaks, GDPR violations. Permissions constrain which tables it queries, how many rows per call, and whether it touches PII columns at all.
What's the difference between permissions and guardrails?
Guardrails is the umbrella — input filtering, output validation, rate limiting, and permissions are all types. Permissions are the guardrail that answers: is this specific action, with these specific arguments, allowed right now? Prompt injection detection protects the model. Permissions protect the world the model acts on.
How granular can these get?
Down to individual argument values. Allow send_email but only to internal domains. Allow issue_refund but only under $500. Allow delete_record only during business hours, only in non-production environments, only if a human approved within the last 30 minutes. Combine any conditions. The policy is YAML — you can read it, version it, review it in a PR.
What happens when an agent hits a permission boundary?
Three outcomes. Allow: the tool runs. Deny: the call is blocked, the agent gets a configurable error. Escalate: the action pauses and routes to a human approver via Slack, email, or the Veto dashboard. Every decision — allowed, denied, or escalated — is logged with full context.
Does this add latency?
Under 5ms. Policy evaluation is deterministic YAML matching, in-process, no network call. For comparison, the LLM that decided to make the tool call took 500–2,000ms. The permission check is noise.
Are agent permissions required for compliance?
The EU AI Act requires risk mitigation and human oversight. SOC 2 requires access controls and audit trails. HIPAA requires PHI access controls. None of them say 'agent permissions' — but all of them mandate exactly what tool-level permission enforcement provides. If you're deploying agents in a regulated industry, this is how you demonstrate control.

Your agent has tools. Now give it boundaries.

Open source. Two lines of code. Under 5ms.