Privilege Rings: Scoping What an Agent Can Do Without Asking
Privilege rings are a tiered permission model for agent tools: low-risk actions run freely, mid-risk actions need soft gates, and high-risk actions require explicit human approval.
The model is inspired by OS protection rings and capability security, but applied to what the agent may invoke, not only who the human is.
Summary
- Map every tool (or tool mode) to a risk ring. The host enforces which rings auto-run and which pause for a human.
- Insight: A single flat allowlist either blocks useful work or silently allows irreversible damage. Rings make autonomy proportional to blast radius.
- Key Concepts: ring levels, auto-run vs gated, tool capability, blast radius, approval policy, least privilege.
- When to Use: Any agent that can send messages, write data, spend money, change infra, or call external systems with side effects.
- Limitations/Trade-offs: Too many rings create rubber-stamp fatigue. Too few rings collapse back into "all or nothing." Ring assignment needs owners and review, not ad hoc gut feel.
- Related Topics: approval gates, kill switches, escalation paths, audit trails, least-privilege tool design.
Foundations
An agent without privilege rings typically has one of two defaults:
- Everything allowed - the model may call any registered tool whenever it wants.
- Everything gated - every tool call waits on a human, so operators approve noise until they stop reading.
Privilege rings sit between those extremes. They answer a design question for each capability: Can this action auto-run, or must a human see it first?
A practical four-ring model for product agents:
| Ring | Typical actions | Default policy |
|---|---|---|
| R0 - Observe | Read docs, search, list tickets, fetch public data | Auto-run |
| R1 - Draft | Write drafts, propose plans, create private notes | Auto-run or soft notify |
| R2 - External / mutate | Send email, update CRM, open PRs, post to chat | Approval gate |
| R3 - Irreversible / high cost | Refunds, deletes, deploys, payments, secret access | Dual control or senior approval |
Rings are host policy, not model manners. The LLM may want to send mail; the runtime must refuse or pause until the policy is satisfied.
Rings compose with identity. The same tool can be R1 for an internal admin agent and R3 for a customer-facing bot.
Mechanics & Interactions
Assign rings at the capability boundary
Prefer rings on capabilities (for example email.send, crm.update, payments.refund) rather than on raw HTTP verbs alone.
A tool that can both draft and send should expose two modes or two tools so draft stays R1 and send is R2.
from enum import IntEnum
from dataclasses import dataclass
class Ring(IntEnum):
OBSERVE = 0
DRAFT = 1
MUTATE = 2
IRREVERSIBLE = 3
@dataclass(frozen=True)
class Capability:
name: str
ring: Ring
description: str
CAPS = {
"search_docs": Capability("search_docs", Ring.OBSERVE, "Read-only knowledge search"),
"draft_reply": Capability("draft_reply", Ring.DRAFT, "Write a reply draft"),
"send_email": Capability("send_email", Ring.MUTATE, "Send external email"),
"issue_refund": Capability("issue_refund", Ring.IRREVERSIBLE, "Post a refund"),
}Policy: max auto-run ring
Each run, role, or environment sets max_auto_ring. Anything above that ring enters an approval queue (or is denied).
def authorize(cap_name: str, max_auto_ring: Ring) -> str:
cap = CAPS[cap_name]
if cap.ring <= max_auto_ring:
return "allow"
if cap.ring == Ring.IRREVERSIBLE:
return "require_senior_approval"
return "require_approval"Typical environments:
- Dev sandbox: high auto-run ring, no real credentials.
- Staging with real integrations: lower auto-run ring; synthetic money still gated.
- Production: R0-R1 auto; R2-R3 gated; R3 may require two approvers.
Interaction with tools and prompts
Rings do not replace least privilege. An agent that never needs refunds should not load issue_refund into its tool schema at all.
Prompt text like "be careful with refunds" is not a ring. Enforcement lives in the tool dispatcher before side effects run.
Interaction with human-in-the-loop gates
When authorize returns require_approval, the host:
- Freezes the run (or that tool branch).
- Surfaces a decision packet: capability, args summary, ring, reason, risk notes.
- Waits for approve / reject / edit.
- Resumes only with a recorded decision id.
See Building an Approval Gate Before Irreversible Actions.
Interaction with kill switches and audit
A kill switch is orthogonal: it stops any ring mid-run when something is wrong.
Audit logs should record ring, capability, decision, and actor so post-incident review is possible without replaying model vibes.
Advanced Considerations & Applications
Dynamic ring elevation
Some systems temporarily raise a ring after a successful verification step (for example user confirmed an amount in chat).
Treat elevation as short-lived and scoped: elevate send_email for one recipient and one body hash, not "all mutate tools for 24 hours."
Dual control for R3
High-blast actions often need two humans or human-plus-policy (for example amount over a threshold plus manager approval).
Dual control is still a privilege ring pattern; the gate just requires two distinct decision records.
Trade-offs
| Approach | Strength | Weakness |
|---|---|---|
| Single allowlist, all auto | Fast demos | Incidents at first real side effect |
| Gate every tool | Feels safe | Operator fatigue, rubber stamps |
| 3-4 fixed rings + env policy | Clear, reviewable | Needs ownership of mappings |
| Per-arg dynamic risk scores | Nuanced | Hard to explain and test |
Prefer fixed rings with a few arg-based overrides (amount > $X, production env, external domain) rather than opaque ML risk scores as the only gate.
Multi-agent rings
Specialists inherit rings from their tool sets. A research agent stays R0-R1. An executor agent may hold R2 tools but still hit approval for R2+.
Do not let handoff expand privileges silently. The handoff packet should not re-register admin tools on a low-privilege worker.
Common Misconceptions
- "The model will only call safe tools if we say so." Models optimize for task completion, not your liability policy.
- "OAuth scopes replace rings." Scopes limit what the credential can do; rings decide when the agent may use that credential without a human.
- "More rings always means more safety." Beyond about four levels, humans stop distinguishing them.
- "Draft tools are always safe." Drafts that land in shared systems or customer-visible queues may already be R2.
- "Rings only matter in production." Staging with production-like integrations needs nearly the same R2-R3 discipline.
FAQs
How many rings should we start with?
Three or four. Observe, draft, mutate, irreversible is enough for most products. Split only when ops cannot write clear policy without another level.
Who owns ring assignment for a new tool?
The feature owner proposes a ring; security or platform reviews it. Record the decision next to the tool registration, not only in chat.
Can ring policy live only in the system prompt?
No. Prompts help the model prefer good tools. The host must still refuse or gate out-of-policy calls.
How do rings differ from RBAC for human users?
RBAC answers "what may this human do in the product." Rings answer "what may this agent run without pausing for a human." Both layers usually apply.
Should read tools ever be gated?
Usually auto-run, unless the read itself is sensitive (PII export, secret store list, competitor scrape under legal limits). Then treat as a higher ring or a separate allowlist.
How do we avoid approval fatigue?
Keep R0-R1 wide enough that only meaningful risk hits the queue. Batch low-value R2 items carefully, or auto-approve only with strict arg templates.
What about scheduled agents with no human online?
Either keep max auto-ring at R1, queue R2+ for business hours, or require a pre-approved plan with a fixed arg envelope.
Do framework "human nodes" replace privilege rings?
They implement the pause. You still design which tools enter those nodes. LangGraph interrupt nodes, AI SDK tool-approval states, and custom queues are mechanisms, not the policy model.
How should open-source agents document rings?
Ship a capability table in the repo: tool name, ring, default env policy, and whether credentials are loaded. Reviewers should see this before merge.
What is the first ring to implement if we only ship one gate?
Gate external side effects (send, pay, delete, deploy) as a single high ring, and keep reads auto-run. Expand to finer rings once volume justifies it.
Can users self-approve agent actions?
Yes for low-stakes personal agents. For enterprise risk, self-approval of R3 by the requesting user is often insufficient; use separation of duties.
How do rings interact with MCP tools?
Treat each MCP tool (or server) as a capability with an assigned ring before it is exposed to the model. Do not auto-import a whole server as R0.
Related
- Human-in-the-Loop Basics - first approval gate
- Building an Approval Gate Before Irreversible Actions - gate recipe
- Kill Switches: Stopping a Runaway Agent Mid-Execution - emergency stop
- Common Guardrail Mistakes That Undermine Human Oversight - anti-patterns
- Human-in-the-Loop Best Practices - checklist
- The Principle of Least Privilege Applied to Agent Tools - tool surface scoping
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.