When an AI agent acts on your behalf, how much of “you” should it become?
In AI systems, agent impersonation creates security risks by granting overly broad permissions. This post introduces a delegation model using a permission intersection’ pattern, ensuring agents operate under the principle of least privilege with a fully auditable trail. It is the first in a series of posts on implementing zero trust for AI agents on OpenShift.
The simplest approach is impersonation: the agent assumes your full identity, inherits all your permissions, and operates as if it were you. It’s easy to implement—just pass the user’s token—but it creates a dangerous blind spot. If the agent is compromised, the attacker gains access to everything your token allows. If the agent calls other agents downstream, the audit trail disappears into a single identity. This grants the agent permissions it never needed, violating the principle of least privilege.
Delegation takes a different approach. Instead of becoming you, the agent receives a scoped set of privileges—an explicit grant that limits what it can do. The agent’s identity remains separate from yours, every hop in the chain is traceable, and permissions follow the principle of least privilege by design.
This isn’t just an academic distinction; it becomes critical as agentic AI systems scale. A single user might delegate to multiple agents, each calling other agents, each accessing different resources. Without proper delegation, you get an untraceable web of impersonated identities with broad permissions—exactly the kind of implicit trust that zero trust architectures aim to eliminate.
In this post, I’ll walk through a permission intersection pattern we implemented in a zero trust demo on Red Hat OpenShift with Kagenti (an open source project for agent orchestration): an agent’s effective permissions are the intersection of the user’s permissions and the agent’s own capabilities. Agents can only reduce your access, never expand it.
In this post, you’ll learn:
- Why the impersonation model for AI agents creates security risks.
- How a delegation model using a “permission intersection” pattern enforces the principle of least privilege.
- How to maintain a clear audit trail in multi-agent systems.
- Using nested JWT claims.
The permission intersection pattern
The central design principle is simple:
Effective Permissions = User Departments ∩ Agent Capabilities
When a user delegates to an agent, the system computes the intersection of what the user is allowed to access and what the agent is configured to access. Neither side can escalate beyond its own boundaries.
We implemented this with a policy engine that evaluates three concerns:
- User permissions—maps users to their department-based access rights
- Agent capabilities—defines each agent’s allowed scope
- Delegation logic—computes the intersection and makes the allow/deny decision
In our current demo, we use OPA (Open Policy Agent) with Rego policies for this, but the architecture isn’t tied to a specific engine. We’re exploring alternatives like SpiceDB, which implements relationship-based access control (ReBAC)—a natural fit for modeling delegation chains. The key requirement is that the policy engine can compute permission intersections. The specific tool is less important than the core capability: the policy engine must be able to compute these permission intersections.
The agents themselves are auth-unaware. They don’t carry tokens, check permissions, or know anything about the user delegating to them. All authorization happens at the infrastructure level through the policy engine. This “Bring Your Own Agent” design offers maximum flexibility, allowing development teams to use any agent technology without rewriting security logic, as long as it adheres to the A2A (Agent-to-Agent) protocol. The same agent image can be deployed multiple times with different scopes just by changing its policy configuration. A summarizer agent deployed as summarizer-hr gets HR scope; deployed as summarizer-tech, it gets finance and engineering scope.
This separation keeps agents simple and keeps security policy centralized—exactly where you can audit and enforce it.
Tracing delegation through the chain
Delegation solves the permission problem, but it introduces a new question: when an agent accesses a resource, who asked it to? And if that agent called another agent along the way, how do you reconstruct the full chain?
We solved this with nested act claims in JWT tokens, following the pattern from RFC 8693 (OAuth 2.0 Token Exchange). Each time a delegation happens, the token wraps the previous actor inside an act claim:
{
"sub": "summarizer-tech",
"act": {
"sub": "alice",
"departments": ["engineering", "finance"]
}
}
If summarizer-tech delegates further—say, to a reviewer-ops agent for a second opinion—the chain nests one level deeper:
{
"sub": "reviewer-ops",
"act": {
"sub": "summarizer-tech",
"act": {
"sub": "alice",
"departments": ["engineering", "finance"]
}
}
}
When the document service receives this token, it can see the full path: Alice delegated to summarizer-tech, which delegated to . The policy engine evaluates permissions at every level—the effective permissions are the intersection of all actors in the chain, not just the endpoints.reviewer-ops
This gives you two things impersonation can’t: auditability (who asked whom to do what) and progressive permission narrowing (each hop can only reduce permissions, never add them). If you’re investigating an incident, the token itself tells the story.
Permission intersection in practice
Let’s make this concrete. Our demo has three users with different department access and four AI agents with different capability scopes:
| User | Departments |
|---|---|
| Alice | Engineering, Finance |
| Bob | Finance, Admin |
| Carol | HR |
| Agent | Capabilities |
|---|---|
| summarizer-hr | HR |
| summarizer-tech | Finance, Engineering |
| reviewer-ops | Engineering, Admin |
| reviewer-general | All |
Consider Bob. He has direct access to 3 out of 5 protected documents (those requiring Finance or Admin departments). Now he delegates to summarizer-tech, which has Finance and Engineering capabilities. The intersection:
Bob's departments: [Finance, Admin]
summarizer-tech capabilities: [Finance, Engineering]
Effective permissions: [Finance] ← intersection
Bob loses his Admin access through this delegation. The agent acts as a capability limiter:
| Document | Bob direct | Bob + summarizer-tech |
|---|---|---|
| Engineering Roadmap | No Eng | Not in intersection |
| Q4 Financial Report | Has Fin | Both have Fin |
| Admin Policies | Has Admin | Not in intersection |
| HR Guidelines | No HR | Neither has HR |
| All-Hands Summary | Public | Public |
| Total access | 3/5 docs | 2/5 docs (reduced) |
Bob went from accessing 3 documents to 2. This is the principle of least privilege enforced structurally, not by trusting the agent to behave. Even reviewer-general—which has access to all departments—can’t give Bob access to HR documents, because Bob himself doesn’t have HR permissions.
Meanwhile, the policy engine denies any agent request that lacks a user delegation context entirely. Agents cannot act autonomously. No user in the chain means no access, period.
What’s next
The permission intersection pattern gives you a practical framework for zero trust agent delegation: agents reduce permissions rather than inherit them, every hop is traceable through nested act claims, and the agents themselves stay auth-unaware—making this a Bring Your Own Agent architecture.
But identity and authorization are only part of the story. Once an agent has verified, scoped permissions, it still needs to do something—access an S3 bucket, query a database, call an external API. Each of these resources speaks a different authentication language. Translating zero trust tokens into resource-specific credentials is the “last mile” problem, and that’s where things get interesting.
In the next post, I’ll walk through the identity plumbing underneath this pattern: how SPIFFE workload identities, RFC 8693 token exchange, and Kagenti’s agent discovery work together to make delegation flow across services on OpenShift.
This post is part of a series on implementing zero trust for AI agents on OpenShift:
- Part 1: Why delegation beats impersonation (this post)
- Part 2: Wiring zero trust identity—SPIFFE, token exchange, and Kagenti (coming soon)
- Part 3: The last mile—from zero trust tokens to real-world resources (coming soon)
More documentation is available at https://github.com/redhat-et/zero-trust-agent-demo/blob/main/docs/README.md#reading-guide-for-the-blog-series .

