Why AI agents need ReBAC: governing non-human identities in enterprise systems
Traditional IAM was built for humans who log in. AI agents don’t log in. They delegate, chain, and act autonomously — and that breaks every…
Why AI agents need ReBAC: governing non-human identities in enterprise systems
Traditional IAM was built for humans who log in. AI agents don’t log in. They delegate, chain, and act autonomously — and that breaks every assumption access control has relied on for sixty years

The governance gap nobody planned for
Traditional Identity and Access Management was architected for humans. It was built around the assumption that an identity represents a person who authenticates with credentials, operates within a defined role, and can be held accountable for their actions. The entire apparatus of IAM — directories, approval workflows, access reviews, joiner-mover-leaver lifecycles — was designed with that assumption baked in at every layer.
In 2025, that assumption fully collapsed. Non-human identities now outnumber human ones in enterprise environments. Research from Entro Security found the ratio of non-human to human identities reached 144 to 1 in cloud-native environments by 2025, up from 92 to 1 in the first half of 2024 — a 56% increase in ratio in a single year. In one published audit of a Fortune 500 financial institution, security teams found over 4.2 million non-human identities against approximately 50,000 human user accounts.
And within that population, AI agents represent the fastest-growing and least-governed category. Microsoft Copilot Studio users had collectively created more than one million AI agents by 2025. Gartner named agentic AI the top technology trend of 2025 and projected that 33% of enterprise applications will include agentic AI by 2028, up from less than 1% in 2024.
Yet 91% of organizations already using AI agents report that only 10% have a well-developed strategy for managing these non-human identities. The gap between adoption and governance is not just a risk. It is, as one Okta analysis put it, a massive blind spot in enterprise security.
Why AI agents break every IAM assumption
An AI agent is not a service account with a predefined call graph. It is a reasoning system that decomposes goals, plans multi-step actions, calls tools iteratively, spawns sub-agents, and takes actions whose full scope may not be predictable at the time access is granted. This creates three specific failure modes for traditional IAM models.
Failure 1: roles cannot express dynamic delegation
RBAC assigns a role at provisioning time. A role is static, persistent, and independent of context. An AI agent acting as a code reviewer for a specific pull request does not have a “code reviewer” role in any meaningful sense — it has a temporary, scoped relationship to a specific resource, delegated by a specific human, for a specific purpose. The moment the pull request merges, that relationship should no longer exist.
RBAC cannot model this. It can grant the agent read access to a repository, but it cannot express “this agent has reviewer access to PR #142, delegated by alice, expiring when the PR closes.” That requires a relationship, not a role.
Failure 2: attributes cannot express delegation chains
ABAC adds context — time, department, classification, risk score. It improves on RBAC significantly for conditional access. But it still evaluates access as a function of the agent’s own attributes, not as a function of its position in a delegation chain.
When an orchestrator agent delegates a task to a sub-agent, and that sub-agent calls a tool on behalf of the original human user, the relevant authorization question is not “what attributes does this sub-agent have?” It is “does this sub-agent’s delegation chain trace back to a human who authorized this specific action?” Attributes cannot answer that question. Relationships can.
Failure 3: no model handles agent-spawned agents
Multi-agent architectures compound both failures. An orchestrator agent can spawn specialist sub-agents — a retrieval agent, a code execution agent, a notification agent — each of which may itself call tools, access data, and make decisions. The authorization question at each hop is not just “is this identity permitted?” but “is this action still within the scope that the original human consented to, at this point in this delegation chain?”
This is what ISACA’s 2025 analysis called the looming authorization crisis: traditional IAM was not designed to manage autonomous AI systems that can reason about goals, make independent decisions, and dynamically adapt their actions — and can even spawn other agents to help complete tasks.
Why ReBAC is the natural fit for agent authorization
Relationship-Based Access Control is not just a better RBAC. It is a fundamentally different framing of the access question. Instead of asking “does this identity have permission?”, ReBAC asks “what is the relationship between this identity and this resource, and does that relationship permit this action?”
That framing maps directly onto the structure of agentic systems. An agent acts on behalf of a user. That “on behalf of” is a relationship. It has a subject (the agent), a relation (delegate of), and an object (the user). It can be scoped to a specific resource. It can carry a TTL. It can be revoked. And it can be traversed: if the agent’s delegation traces back through a chain to a human who is authorized to perform the action, the agent is authorized. If the chain is broken or the authorization was never granted, the check fails.
// agent-auth/types.ts — modeling agent identity and delegation
export type AgentRelation =
| 'delegate_of' // agent acts on behalf of user
| 'spawned_by' // sub-agent created by orchestrator
| 'scoped_to' // access limited to a specific resource
| 'authorized_for'; // explicit capability grant
export interface AgentTuple {
subject: string; // 'agent:reviewer-001'
relation: AgentRelation;
object: string; // 'user:alice' | 'pr:142' | 'repo:frontend'
expiresAt?: Date; // TTL — access expires when task completes
grantedBy: string; // who authorized this delegation
}
// agent-auth/store.ts — writing delegation tuples at task creation time
import { AgentTuple } from './types';
const tuples: AgentTuple[] = [];
export function grantDelegation(tuple: AgentTuple): void {
tuples.push(tuple);
}
export function revokeDelegation(agentId: string, relation: string, object: string): void {
const idx = tuples.findIndex(
t => t.subject === agentId && t.relation === relation && t.object === object
);
if (idx !== -1) tuples.splice(idx, 1);
}
export function getActiveTuples(agentId: string): AgentTuple[] {
return tuples.filter(t =>
t.subject === agentId &&
(!t.expiresAt || t.expiresAt > new Date())
);
}
// When alice creates a code review task:
grantDelegation({
subject: 'agent:reviewer-001',
relation: 'delegate_of',
object: 'user:alice',
expiresAt: new Date(Date.now() + 2 * 60 * 60 * 1000), // 2 hours
grantedBy: 'user:alice',
});
grantDelegation({
subject: 'agent:reviewer-001',
relation: 'scoped_to',
object: 'pr:142',
expiresAt: new Date(Date.now() + 2 * 60 * 60 * 1000),
grantedBy: 'user:alice',
});
The delegation chain checker
The authorization check must verify not just whether a tuple exists, but whether the delegation chain traces back to a human with the required permission. This traversal is the core of agent ReBAC:
// agent-auth/checker.ts — verify delegation chain
import { getActiveTuples } from './store';
// Can agentId perform action on resourceId?
// Traverses: agent → delegate_of → user → (check user's own access)
export async function checkAgentAccess(
agentId: string,
resourceId: string,
action: string,
depth = 0
): Promise<{ allowed: boolean; chain: string[] }> {
if (depth > 5) return { allowed: false, chain: ['max delegation depth exceeded'] };
const tuples = getActiveTuples(agentId);
// Check: is this agent directly scoped to this resource?
const scoped = tuples.find(t => t.relation === 'scoped_to' && t.object === resourceId);
if (!scoped) {
return { allowed: false, chain: [`${agentId} not scoped to ${resourceId}`] };
}
// Traverse: find the human this agent delegates from
const delegation = tuples.find(t => t.relation === 'delegate_of');
if (!delegation) {
return { allowed: false, chain: [`${agentId} has no principal — orphaned agent`] };
}
const principal = delegation.object; // 'user:alice'
// If principal is a human user, check their own access
if (principal.startsWith('user:')) {
const userId = principal.replace('user:', '');
const userAllowed = await checkUserAccess(userId, resourceId, action);
return {
allowed: userAllowed,
chain: [agentId, `delegate_of`, principal, action, resourceId]
};
}
// If principal is another agent, recurse (agent-to-agent delegation)
if (principal.startsWith('agent:')) {
return checkAgentAccess(principal, resourceId, action, depth + 1);
}
return { allowed: false, chain: ['unrecognized principal type'] };
}
// Stub — in production, check against your authorization store (OpenFGA, etc.)
async function checkUserAccess(userId: string, resourceId: string, action: string): Promise<boolean> {
// e.g.: does alice have 'reviewer' access to 'pr:142'?
return userId === 'alice' && action === 'review';
}
Enforcing agent access at the tool call layer
The delegation check must run at every tool invocation — not just at agent creation time. An agent’s scope can change mid-task. The resource it is trying to access may not have been in scope when it was created. And a compromised or misbehaving agent may attempt actions outside its original mandate.
// agent-auth/gateway.ts — enforcement at every tool call
import { checkAgentAccess } from './checker';
import { auditLog } from './audit';
interface ToolCall {
agentId: string;
resourceId: string;
action: string;
execute: () => Promise<unknown>;
}
export async function invokeWithAuth(call: ToolCall): Promise<unknown> {
const { allowed, chain } = await checkAgentAccess(
call.agentId,
call.resourceId,
call.action
);
auditLog({
event: allowed ? 'AGENT_ACCESS_GRANTED' : 'AGENT_ACCESS_DENIED',
agentId: call.agentId,
resourceId: call.resourceId,
action: call.action,
chain,
timestamp: new Date().toISOString(),
});
if (!allowed) {
throw new Error(`Access denied: ${chain.join(' → ')}`);
}
return call.execute();
}
// Every tool call goes through the gateway — not just the first one
await invokeWithAuth({
agentId: 'agent:reviewer-001',
resourceId: 'pr:142',
action: 'review',
execute: () => postReviewComment(prId, comment),
});
TTL and lifecycle: when the task ends, the access ends
One of the most dangerous properties of non-human identities is that they outlive their purpose. Service accounts created for a specific project persist for years after the project ends. API keys generated for a single integration remain valid indefinitely. The OWASP Non-Human Identity Top 10 (2025) lists improper offboarding and long-lived credentials among the most critical risks — precisely because these identities are invisible to the access review processes designed for humans.
TTL-scoped delegation tuples solve this structurally. When an agent is created for a task, its delegation relationships carry an expiry time tied to the task lifecycle. When the task completes, the tuples expire. When a pull request merges, the code reviewer agent’s scoped_to relationship to that PR no longer exists. No manual deprovisioning. No stale access. No orphaned agent.
// agent-auth/lifecycle.ts — automated revocation on task completion
interface AgentTask {
agentId: string;
taskType: 'code_review' | 'data_analysis' | 'email_drafting';
resourceId: string;
userId: string;
durationMinutes: number;
}
export function createScopedAgent(task: AgentTask): string {
const expiresAt = new Date(Date.now() + task.durationMinutes * 60_000);
// Delegate from human principal
grantDelegation({
subject: task.agentId,
relation: 'delegate_of',
object: `user:${task.userId}`,
expiresAt,
grantedBy: task.userId,
});
// Scope to specific resource — not the entire system
grantDelegation({
subject: task.agentId,
relation: 'scoped_to',
object: task.resourceId,
expiresAt,
grantedBy: task.userId,
});
auditLog({
event: 'AGENT_PROVISIONED',
agentId: task.agentId,
userId: task.userId,
resource: task.resourceId,
expiresAt: expiresAt.toISOString(),
});
return task.agentId;
}
// On task completion — immediate revocation, no waiting for TTL
export function revokeAgent(agentId: string, reason: string): void {
const tuples = getActiveTuples(agentId);
tuples.forEach(t => revokeDelegation(t.subject, t.relation, t.object));
auditLog({ event: 'AGENT_DEPROVISIONED', agentId, reason });
}
The five properties of correct agent authorization
Based on current research and production deployments, correct authorization for AI agents requires five properties that traditional IAM models do not provide:
- Delegation as a first-class primitive: every agent action must be traceable to a human who explicitly authorized it, through a verifiable chain of delegations — not inferred from a role assignment
- Resource-scoped access: agents must be authorized for specific resources, not resource types. “Can review code” is a role. “Can review PR #142” is a relationship — and it is the only one that preserves least privilege
- TTL-bound relationships: agent access must expire automatically when the task context ends, not when someone remembers to revoke it
- Reuse detection: if the same delegation token or relationship is presented from two different contexts simultaneously, it signals a possible agent compromise and should trigger immediate revocation
- Audit at the relationship level: every access decision must be logged with the full delegation chain, not just the agent identity. The question “why did this agent access that resource?” must always have a traceable answer
How this fits with the broader authorization stack
ReBAC for agent authorization does not replace the other models in your stack — it extends them. RBAC still governs what human roles can do at a coarse-grained level. ABAC still adds contextual constraints (time, classification, risk score). ReBAC handles the relational, delegation-aware layer that neither RBAC nor ABAC can express.
In practice, the pattern that is emerging in mature enterprise deployments is: RBAC for human role baseline, ABAC for context, ReBAC for agent delegation and resource-scoped access, and IBAC (Intent-Based Access Control) as the per-request enforcement layer that prevents prompt injection from expanding an agent’s scope beyond what the user originally authorized.
This is not a theoretical architecture. It is what Gravitee, Permit.io, Red Hat, and OpenFGA are shipping in production today. The MCP specification’s June 2025 update integrated OAuth 2.1 and adopted RFC 9728 for protected resource metadata, enabling agents to dynamically discover authorization requirements rather than relying on hardcoded configurations. The infrastructure is converging around graph-based, relationship-aware authorization — because nothing else captures the structure of delegation.
Summary
- Non-human identities outnumber human ones 144 to 1 in cloud-native environments — and AI agents are the fastest-growing, least-governed category
- RBAC fails for agents because roles cannot express dynamic, resource-scoped, TTL-bound delegation
- ABAC fails because it evaluates the agent’s own attributes, not its position in a delegation chain
- ReBAC is the natural fit: delegation, scope, and chain traversal are all native to a relationship graph
- Every agent action must be traceable to a human principal through a verifiable delegation chain — not inferred from a role
- TTL-bound tuples solve the long-lived credential problem structurally, without depending on manual deprovisioning
—
IAM was built for a world where identities had names, faces, and employment contracts. That world still exists — but it now shares infrastructure with agents that have none of those things. The authorization models we reach for need to change accordingly. ReBAC does not solve every problem in agentic authorization, but it solves the structural one: it makes delegation a first-class, observable, traceable relationship rather than an implicit assumption buried inside a token. And in a world where the fastest-growing identity population is non-human, that traceability is not a feature. It is the foundation.
메타데이터
- post_id
- c2b5a6fc093d
- slug
- why-ai-agents-need-rebac-governing-non-human-identities-in-enterprise-systems-c2b5a6fc093d
- url
- https://medium.com/@henriquebotega/why-ai-agents-need-rebac-governing-non-human-identities-in-enterprise-systems-c2b5a6fc093d
- canonical_url
- https://medium.com/@henriquebotega/why-ai-agents-need-rebac-governing-non-human-identities-in-enterprise-systems-c2b5a6fc093d
- author_url
- https://medium.com/@henriquebotega
- status
- ok
- fetched_at
- 2026-07-10 04:31:59