Runtime Data Security for Agentic AI: 6-Part Series
Part 1: Why Traditional DLP Breaks in Agentic AI
Part 2: Beyond Masking: The Challenge of Safe Data Reveal ← You are here
Part 3: Authorization Is No Longer Static ← You are here
Part 4: Why Simple Masking Kills AI Accuracy (Coming Week 4)
Part 5: Sensitive Data Is More Than PII (Coming Week 5)
Part 6: From Data Classification to Runtime Data Security for AI (Coming Week 6)
“Is this user allowed to access this resource?” is an incomplete question for agentic systems.
A CEO opens the internal assistant and asks it to draft the quarterly board update. The assistant spins up a drafting agent, which retrieves whatever looks relevant: the product roadmap, the compensation review, and notes from an early-stage M&A discussion. The CEO is allowed to see all of it, the agent is running under the CEO’s session, and every tool call passes its access check. So the draft now contains unannounced acquisition targets, individual salaries, and unreleased roadmap, sitting in a document headed for a dozen inboxes. Every part of the system answered the only question it knew how to ask: is this principal allowed to access this resource?
That is the wrong question for agentic systems. The CEO can access all of that data, but the task, drafting a board update, justifies almost none of it. Static authorization (a permission attached to a principal, checked once, true for the whole session) cannot tell the two apart, because the thing that differs is not who is asking but what they are asking for and why, right now.
This post is about why authorization in agentic systems has to be worked out at runtime, from context, and what the layers of that decision actually are.
What You’ll Learn
- Why user permissions alone are not enough in agentic systems
- The layered runtime decision across Who, What, Agent, Why, Where, and When
- Why agents must not inherit the user’s full permissions by default
- How to authorize the intersection of user, agent, tool, task, and destination
The Runtime Question
Every decision in this series reduces to the same six questions, evaluated at runtime as data moves between parts of the system:
User → Agent → LLM / Tool / MCP → Enterprise systems │ Runtime Data Security Layer (inspects every hop: Who · What · Agent · Why · Where · When)
- Who is asking (the user or caller)
- What data or business context is involved
- Agent is acting (which agent or sub-agent)
- Why it is needed (the task or purpose)
- Where the data is going (the destination)
- When in the workflow (the runtime moment)
How most of us think about this
The standard model is principal-based access control, and it has served us well for decades. A principal (a user, a service account, a role) gets permissions, usually through RBAC or ABAC. At request time you authenticate the principal, look up its permissions, and allow or deny. The grant is fairly stable: a payroll clerk has payroll access today, tomorrow, and every session in between. Authorization is basically a property of the identity, set by a policy that changes slowly.
This works because the assumptions hold in classic systems. The principal is the actor: the person or service making the request is the one whose permissions matter, and there is no gap between “who is allowed” and “who is acting.” The action is implied by the endpoint: hitting GET /payroll is clear, so allowing the principal for that route allows the action. And the principal does one basic thing per session: a payroll clerk logging into the payroll system is there to do payroll. Under those assumptions, “can this principal access this resource?” is the whole question and checking it once per session is fine.
None of this was wrong. It is the right model for systems where identity, action, and intent line up.
Why this breaks in agentic systems
In an agentic workflow, identity, action, and intent come apart. Trace one request:
User (HR director) → Orchestrator agent (acting "as" the user) → Drafting sub-agent (task: write newsletter) → Retrieval tool (MCP) (capability: read corpus) → Vector DB / SharePoint (contains comp deck) → Pricing sub-agent (task: quote a customer) → External pricing API (third party)
Each arrow is a place where static authorization gives a confidently wrong answer, because it can only see the principal.
The principal is no longer the actor. The user authorized the session, but the thing reading the comp deck is a drafting agent. “The user can see salaries” is true and beside the point. The real question is whether this agent, on this task, should. Most agent frameworks default to handing the agent the full set of the user’s permissions, and that is exactly the bug.
The action is not implied. A tool call to a retrieval API does not tell you the purpose. The same search(corpus, query) call serves the comp review and the newsletter. The endpoint no longer carries the intent, so allowing the endpoint allows everything reachable through it.
There is more than one thing happening per session. The same orchestrator runs a newsletter task and a pricing task in one session under one identity. A session-wide grant cannot be right for both. Authorization has to be scoped to the task in front of it, not the session.
And capability flows outward to systems that have no business getting it. The pricing sub-agent calls an external API. Should that third party get the internal discount table just because the user who started the session can see it? Static models have no idea of “this principal may see X, but X must not flow to that destination.” Authorization in agentic systems is as much about where data is going as who asked for it.
The failure has the same shape every time: static authorization answers a question about the principal, but the risk comes from the combination of principal, agent, task, tool, and destination, checked at a specific moment.

The core of it: the layers of a runtime authorization decision
Treating “is this allowed?” as a single yes-or-no keyed to identity is the root mistake. In agentic systems the decision is several authorizations stacked together, each of which can deny on its own, and all of which have to be checked at the moment of the call, not cached for the session.
Layer 1: user authorization
The classic layer, still needed. Does the person (or starting principal) have the underlying right? This is the floor: if the user cannot see salary data at all, nothing downstream can grant it. But it is only the floor. Passing it means “not forbidden,” not “allowed for this purpose.”
Layer 2: agent authorization
Does this agent have the right to do this kind of action, separate from the user? Agents should carry their own identity and their own grants, not silently inherit the user’s. A newsletter-drafting agent should be set up with access to public and marketing content and nothing else, so that even when a director with full access calls it, the agent’s own ceiling stops it from touching comp data. This is the single most effective control, and it is the one that “act as the user” skips. The right mental model is least privilege for the agent, intersected with the user’s rights, never the union.
Layer 3: tool authorization
Does this tool, on this call, have the right to reach this data or system? A tool is a capability, and capabilities should be scoped per call. The retrieval tool may be allowed to search the marketing corpus for a newsletter task but not the HR corpus, even though the connector underneath can technically read both. Tool authorization is where you limit the blast radius of one capability being reused for many purposes.
Layer 4: task and runtime context authorization
Does the current task justify this access? This is the layer static systems do not have at all, and the one that settles the opening example. Same agent, same user, same tools, but the task is “draft a board update,” and that task does not justify surfacing salaries, M&A notes, or unreleased roadmap. Task is the missing piece that lets you tell apart two requests that are identical in principal, agent, and endpoint. It requires the system to carry a record of intent (a task or purpose label, ideally structured and checkable) alongside the request, so the decision can use it.
Does the current moment justify it? Reveal the full MRN only for the payment-network reversal that needs it, and only while the dispute case is open. Allow the export only from the corporate network. Permit the cross-region data flow only if the user’s data-residency settings allow it. And, importantly, where is the data going next? Authorization has to look at the destination: the internal discount table may be readable by the user but must not flow into an external pricing API call. This layer makes authorization depend on state and direction, not just identity.
A real decision is the stack: allow only if the user may, and the agent may, and the tool may, and the task justifies it, and the moment permits it, and the destination is acceptable. Any single layer can deny. This costs more than a session-cached yes-or-no, which is the honest tradeoff, and it is why this belongs in an enforcement layer rather than scattered across agent code.
Design tradeoffs
Where the decision lives. Build it into each agent and you get low latency and rich context, but every team rebuilds authorization, policy drifts apart, and a prompt-injected agent is also your decision point. Put it in one enforcement layer the calls pass through and you get one policy, one audit trail, and independence from the agent that can be tricked, at the cost of a hop and the work of feeding the layer enough context (user, agent, task, tool, destination) to decide. Serious systems centralize, for the same reason we centralized authentication into IAM instead of letting every app roll its own.
How intent is represented. Task authorization only works if intent is readable by the policy engine. A free-text “I’m drafting a newsletter” can be faked by the very input you are guarding against. A structured, system-assigned task context built from the call is much harder to spoof. Treat the task label as security-relevant data, not a hint.
Fail-open versus fail-closed. When the layer cannot work out the task or loses context, denying breaks workflows and allowing leaks. Default to deny for sensitive reveals, and to mask-rather-than-block for reads where a safe limited view exists, so a context failure cuts usefulness instead of either leaking or hard-stopping.
Failure modes
Permission inheritance by “act as the user”: the agent runs with the user’s full rights, so every task sees everything the user can. Over-broad tool scope: one connector credential used for all corpora, so task-level intent cannot limit it. Session-cached decisions: authorization checked once at session start, so a later sensitive task rides the earlier grant. Intent spoofing: a prompt-injected task label talks the engine into allowing access. Destination blindness: data the user may read flows to an external system that should never get it.
Real examples
HR. The newsletter case. User authorization passes (director). Agent authorization fails: the newsletter agent has no comp-data grant, so the comp deck is never reachable on this task no matter who called it. The comp-review agent, on a comp-review task, passes all five layers and proceeds.
Banking. A relationship-management agent may read a client’s holdings for a portfolio review (task and tool line up), but the same agent, on a marketing-segmentation task, is denied account-level detail and gets aggregates only. The user (the banker) can see both. The task decides.
Customer support. A refund agent is allowed to reveal a payment credential into the payment tool for an open refund task. The same agent, asked in a later turn to summarize the ticket, is denied the reveal because the summarization task does not justify it, even though nothing about the user or the agent changed.
Enterprise search / RAG. The same query from a full-time employee and a contractor returns different reveals from the same index, because user attributes plus task plus destination produce different decisions at query time. Authorization is checked per query, not baked into the index.
What to build
Give agents their own identities and least-privilege grants. Do not let agents inherit the user’s full permissions by default. Set up each agent with the narrowest set of capabilities its role needs, and authorize the intersection, never the union: user rights ∩ agent rights ∩ tool rights ∩ task justification ∩ destination policy. A request is allowed only where all of them agree.
Make authorization a runtime stack, not a session yes-or-no. Check user, agent, tool, task, moment, and destination at the time of each sensitive call. Any layer can deny. Do not cache the decision across tasks.
Carry intent as first-class, hard-to-spoof context. Pass a structured task or purpose label built from the call, and treat it as security-relevant. Task authorization is the layer that tells otherwise-identical requests apart, and it is only as good as the integrity of the intent signal.
Decide where data is allowed to flow next. The right to read is not the right to forward, especially to external tools, APIs, and model providers.
Centralize the decision in an enforcement layer independent of the agent. One policy, one audit trail, and a decision point a tricked agent cannot get around. Log every decision with the full context that produced it.
Protecto is one example: it checks authorization at runtime across user, agent, tool, task, and destination (Context Based Access Control) in a layer the agent cannot route around, and logs each decision. The point is the model, not the product: authorization is a context-based runtime stack, owned outside the agent.