Seven years in identity - first at Auth0, then Okta, now building fraud detection at a fintech - and I keep watching the same mistake play out in new domains. In the OAuth era, teams would create a single client with admin scope because it was easier than thinking through granular permissions. Today, the same teams are deploying AI agents with broad service account permissions because thinking through the right scope is hard.
It is not hard because engineers are lazy. It is hard because nobody has built the right mental model yet. Let me offer one.
The Three-Layer Agent RBAC Model
When I think about access control for multi-agent systems, I see three distinct authorization questions that need separate answers:
Layer 1: Who can invoke the agent?
This is standard RBAC for humans and systems interacting with your agent. Who can trigger a run? What parameters can they pass? Can they override default behavior? This layer looks like your existing IAM system - roles, policies, users. Do not reinvent it; extend what you have.
Layer 2: What resources can the agent access?
This is where service account thinking breaks down. Instead of “what is this identity allowed to read,” the question becomes “what is this agent allowed to read, in what context, with what frequency, for what purpose.” The same underlying data resource might be accessible to an agent in read-only mode during normal operations but completely off-limits when operating outside business hours.
Context-aware authorization is the key concept here. The agent’s permission to access a resource is a function of (the resource) AND (the current context) AND (the agent’s stated purpose). Static ACLs cannot express this; you need something like OPA (Open Policy Agent) with context fed in at evaluation time.
Layer 3: What can the agent delegate to sub-agents?
This is the layer nobody is building correctly. When an orchestrator agent spawns a sub-agent to handle a specific task, what permissions does the sub-agent receive? The only correct answer is: a strict subset of what the orchestrator has, with further constraints appropriate to the sub-task.
The delegation policy needs to be explicit and enforced, not implied. “Agent A can delegate read access to the customer table to sub-agents, but cannot delegate write access regardless of what Agent A itself is authorized to do.” That is a policy statement that needs to live in your authorization system, not in the agent’s prompt.
A Role Hierarchy That Actually Works
Here is the role classification I use when advising teams:
read-only-analyst: Can read data, generate reports, make recommendations. Cannot write to any system, cannot spawn sub-agents. This is your safest class - deploy it broadly.
bounded-executor: Can write to pre-approved endpoints with strict rate limits. Can read broadly but write narrowly. Requires human approval for writes exceeding a defined threshold. Can spawn read-only-analyst sub-agents only.
workflow-orchestrator: Can coordinate multiple bounded-executor agents. Cannot directly write to external systems - must delegate to bounded-executors. Requires explicit human sign-off before activation.
admin-orchestrator: Reserved for agents managing other agents (agent lifecycle, configuration updates). Should almost never exist and requires the highest level of human oversight. If you think you need one of these, think harder.
The key insight: each class can only spawn sub-agents of equal or lower trust class. This is enforced by the platform, not by convention.
The Sub-Agent Delegation Problem
Let me be specific about why most current implementations fail here. In LangGraph, AutoGen, and most orchestration frameworks I have audited, sub-agent spawning looks roughly like this:
orchestrator.spawn_subagent(
agent_class=DataFetcherAgent,
tools=self.available_tools # BUG: passes all parent tools
)
The sub-agent inherits the full tool set of the parent. If the parent has write access, so does the child. This is equivalent to sudo spawning a shell and that shell having root access - not what anyone intends, but common in practice.
The fix requires the orchestration framework to enforce delegation constraints at spawn time. Until the major frameworks build this in, you need to implement it yourself - either by wrapping the framework or by building delegation policies into your tool execution layer.
One Thing I Want Everyone to Internalize
Do not just port your human RBAC model to agents. Human RBAC works partly because humans have judgment and social accountability. A human who gets admin access might not use it inappropriately because they know there are consequences.
An agent has no such inhibitions. It will use every permission it has, every time it thinks it is relevant. Principle of least privilege applies doubly to agents because the agent will always operate at the edge of its permissions envelope.
Design your agent RBAC assuming the agent will do everything it is authorized to do, all the time. If that assumption makes you uncomfortable, tighten the permissions.