The moment two agents of different tiers call the same tool, the tool needs one piece of information it probably never had: who is asking. Most tool implementations were written for one caller. A function that reads a ticket, refunds a payment or updates a CRM record usually authenticates with a single service credential stored in an environment variable, and that credential carries the union of everything any caller might need. The function does not care who invoked it because it was never designed to.
Agent frameworks make this worse by design. In the agents-as-tools pattern, an orchestrator agent wraps specialized agents as callable functions and lets the model choose which one to invoke at runtime, so the call path is decided by a language model rather than by a fixed code route. That is a useful structure, but it means the tool cannot infer its caller from the call stack alone. See how the pattern is built in this Strands walkthrough and how tool-calling interaction patterns multiply the number of callers in this analysis.
The access control problem is not abstract. Writeups on agent access control note that an agent's effective role can change from moment to moment within a single task, and a request that starts as read-only can evolve into an action that needs write rights, which pushes teams to grant one oversized role that covers every combination (Auth0). Once that oversized role lives in a shared tool, every caller inherits it.
The failure has two shapes, and both are common in production:
| Failure shape | What happens | Who is exposed |
|---|---|---|
| Privilege leak | Low-tier caller invokes a tool that authenticates with a high-tier service credential | The caller can do things its tier forbids |
| Privilege hop | Low-tier agent hands a task to a high-tier agent, which calls the tool using its own identity | The low-tier request completes at high tier |
| Confused deputy | Tool trusts a caller-supplied identifier without verifying it | Any caller can claim any identity |
| Stale grant | Tool caches the first successful authorization and reuses it | Every later caller rides the cached grant |
A useful decision rule: if the tool cannot answer "which caller tier is asking, proven cryptographically, for this specific resource, right now" in under one step, it is not enforcing permissions. It is hoping the orchestrator did.



