An AI agent that can send emails, query databases, and execute code is a privileged insider — and like any insider, it should operate on a need-to-know basis. Classic security got this right decades ago: least privilege. Here's what that looks like when the "user" is a model with tools. For the full inventory-to-enforcement method, see Least Privilege for AI Agents: From Entitlement Mapping to Enforcement.
Step 1: Enumerate Capabilities as Bits
Give every capability a bit in a 64-bit mask: send emails (bit 0), generate code (bit 1), read DB (bit 2), write DB (bit 3), access PII (bit 4)… Roles become masks; users get the OR of their roles. The mask travels with the request — no prompt can change it.
Step 2: Gate Tools at Generation Time
If a user lacks the bit for a tool, don't wait for the tool call to fail — ban the tool's trigger phrases in generation. The model literally cannot produce send_email(. This is how reskSecure and ReskSafety do it: trigger phrases are compiled into the hard-block list alongside banned content. Tool gating is one pillar of agent security — the AI agent security hub covers identity, memory and observability too.
Step 3: Verify After Generation
Defense in depth: a post-generation check (verify_tool_action()) re-validates every tool call against the caller's mask. Two independent layers, one assumption: the mask, not the prompt, is the source of truth.
Step 4: Audit Everything
Log every call — function, parameters, result — and stream it to your observability stack. ReskPoints ships this for agents; ReskSafety's console surfaces it per user.
A Concrete Policy
A least-privilege policy is declarative, reviewable and testable. Here is what one looks like in YAML:
roles:
support_agent: # can read tickets, never write
capabilities: [read_db, send_email]
confirm: [] # nothing needs human approval
ops_agent: # can act, but destructive calls need approval
capabilities: [read_db, write_db, execute_code]
confirm: [drop_table, delete_record]
auditor: # read-only, PII visible
capabilities: [read_db, access_pii]
confirm: []
default: deny # anything not granted is blockedThree properties make this pattern work: deny by default (new tools are inert until granted), irreversibility gating (destructive tool calls require a human confirmation outside the model's reach), and per-caller identity (the agent acts as the user who launched it — never as a shared service account).
The Four Mistakes We See Most
1. Gating at the prompt level only. "You may only use the read tools" is an instruction, not a control — one injection away from being ignored. Gate in generation and verify after; treat the prompt as untrusted input.
2. One shared identity for all agents. If every agent shares a god-mode service account, a compromise of the weakest agent is a compromise of everything. Per-caller bitmasks make blast radius a design choice.
3. No confirmation for irreversible actions. Reads can be audited; sends and deletes cannot be un-sent. Anything irreversible should require a human-in-the-loop step the model cannot fabricate.
4. Permissions drift. Capabilities accumulate ("just add this one bit") with no review. Tie bitmask changes to the same PR review process as code, and diff them in CI.
Does Least Privilege Break Agent Usefulness?
No — it trades a small capability tax for a bounded blast radius. In practice, most blocked calls fall into three buckets: prompt-injection attempts from untrusted content, hallucinated tool calls for tools that don't exist, and genuine user errors. The agent stays useful; the failures become visible instead of silent.
FAQ
How do you control AI agent tool permissions? Assign every capability a bit in a mask, derive masks from roles, enforce the mask during generation, verify every call after generation, and log everything. The mask — not the prompt — is the source of truth.
Can prompt injection bypass tool permissions? Not if enforcement is outside the prompt. Injection rewrites instructions; a generation-time ban on trigger phrases and a post-generation verifier both ignore instructions entirely. Prompt-level "rules" in the system prompt are the bypassable part.
What is least privilege for AI agents? Each agent (or each caller) gets only the tools its role requires, for as long as the task needs them — the same principle that governs human IAM, applied to model-generated tool calls.
Should agents have their own identity? Yes. An agent should act as the user who launched it, with a mask equal to or narrower than that user's own permissions — never as a shared superuser.
See It Live
The hosted ReskSafety demo at demo.resk.fr lets you create roles with different capability masks and watch tool calls get blocked in real time.