← all writing

Identity and Access for AI Agents: Who Is This Agent Allowed to Be?

Identity and Access for AI Agents: Who Is This Agent Allowed to Be?

The question nobody asks until it is too late

Ask a team that has shipped an agent into production a simple question: when your agent calls the calendar API, the email API, and the internal billing system, whose identity is it using? A surprising number of teams answer with a shrug and a service account, one shared API key with broad permissions, dropped into an environment variable, used by every agent, every task, every user, indistinguishably. It works, in the sense that requests succeed. It also means that if the agent is tricked into taking an action it should not take, or a bug sends it down the wrong path, or the key leaks, there is no meaningful boundary anywhere in the system that would have stopped it, and no clean record afterward of which task, which user, or which decision was actually responsible.

This is not a hypothetical gap. It is the default state of most agent deployments today, and it exists because identity and access management was designed, over several decades, around a specific assumption: the thing requesting access is either a human sitting at a keyboard or a service doing one narrow, predictable job. An agent fits neither. It acts continuously rather than in a single session, it takes actions a human authorized in only the loosest sense, or delegated, and its behavior is not fully predictable even to the team that built it. The access control systems built for humans and for static services do not have a natural slot for something in between, and until recently, most teams have simply forced agents into the service-account slot and hoped the mismatch would not matter.

It matters. As agents move from answering questions to taking actions, booking things, sending things, changing things, deleting things, the question of what an agent is allowed to be, whose authority it carries, and how that authority can be checked, scoped, and revoked, stops being an afterthought and becomes one of the load-bearing design decisions in the whole system. This is the part of agent engineering that gets the least attention relative to how much damage a wrong answer can do, and it deserves the same deliberate treatment as the model, the tools, and the loop.

An agent is not a person and not a static service. The identity systems built for both do not have a natural slot for it, and most teams have quietly forced the fit rather than solving it.

Three questions that are not the same question

A useful place to start is separating three things that get casually collapsed into the single word "access," because each one fails differently and needs a different fix. Authentication answers who, or what, is making this request, and is it really them. Authorization answers is this specific identity allowed to take this specific action on this specific resource. Delegation answers on whose behalf is this action being taken, and does that person's own authority actually cover it.

A shared service account answers the first question badly, since every agent and every task looks identical to anything downstream trying to tell them apart. It answers the second question either not at all, one key with one broad scope covering everything, or only through hand-rolled logic buried somewhere in application code that nobody audits. And it cannot answer the third question at all, because a shared credential has no concept of the person on whose behalf a particular action was taken; that context, if it exists anywhere, lives in an application log that a security review will not think to check until well after something has gone wrong.

Getting agent identity right means building a real answer to all three, not just picking the one that is easiest to bolt on. Authentication needs to identify the agent instance, ideally down to the specific run or session, not just "the agent system" as an undifferentiated whole. Authorization needs to be scoped to the narrowest set of actions that specific task actually requires, not the broadest set the agent might ever conceivably need. And delegation needs to be an explicit, checkable chain: this action was taken by this agent, running this task, on behalf of this person, whose own permissions were the ceiling the agent's effective permissions could never exceed.

Why the human model does not transfer

It helps to be concrete about why the identity patterns built for people do not simply carry over. A human employee has one identity that persists across contexts, authenticates through a login flow that includes friction on purpose, a password, a second factor, sometimes biometrics, and operates within permissions that a human administrator assigned to them personally and can review, adjust, or revoke by looking at one account. The friction is a feature: it exists specifically because a human is capable of pausing, noticing something is wrong, and stopping before doing damage, and the login flow is designed to give them that pause.

An agent has none of the properties that make that model work. It does not benefit from login friction, since there is no human on the other end who might notice something is off mid-flow; the friction just becomes latency. It often needs to act across many different tasks and contexts within a single deployment, sometimes on behalf of different users in the same hour, which a single static identity was never built to represent cleanly. And crucially, it can be wrong at a scale and speed a human cannot: a confused human employee makes one mistake and then, usually, notices; a confused agent can make the same mistake correctly and repeatedly, at machine speed, for as long as nothing stops it.

The service-account model, built for narrow, predictable, machine-to-machine integrations, transfers a little better but still falls short in an important way: it assumes the thing on the other end does one job, in one context, with one fixed and reviewable purpose. A payment-processing service account that only ever calls the payments API to reconcile invoices is a reasonable thing to grant broad, standing access to, because its behavior is fully determined by code a human wrote and reviewed. An agent's behavior is determined, in the moment, by a model reasoning about a task, which is a fundamentally less predictable thing to grant standing access to, even when the agent's code and tools were reviewed just as carefully, because the decision about which tool to call and with what arguments is made live, not fixed in advance.

This gap is why a new discipline, generally described under the banner of non-human identity, has emerged specifically to handle the space between a human user and a narrow static service: identities that act autonomously, need to be individually distinguishable, need permissions that are tightly scoped and often short-lived, and need an auditable link back to whatever, or whoever, is ultimately accountable for what they did.

Scoping: the permission an agent should never have is the one it does not need

The single highest-leverage decision in agent access design is also the simplest to state and the hardest to actually do well: give the agent the smallest set of permissions that lets it complete its actual task, and nothing more. This sounds like an obvious restatement of the general security principle of least privilege, because it is, but it is worth pausing on why it matters more for agents specifically than it does for a typical piece of software.

A conventional program's behavior is fixed by its code. If a billing service only ever calls three specific, well-understood endpoints, granting it broad account-wide access is unnecessary but also, in practice, rarely catastrophic, because the code simply never exercises the extra permissions no matter how broad they are. An agent's behavior is not fixed the same way. It is reasoning, at runtime, about which of the tools available to it to use, and a sufficiently capable model handed a broad permission and an ambiguous or adversarial situation will, eventually, find a way to exercise that permission that nobody specifically anticipated. Broad standing access granted to an agent is not a permission that merely sits unused most of the time; it is a permission that will eventually get exercised, by design, because exercising available permissions in pursuit of a goal is exactly what an agent is built to do.

This argues for scoping permissions not just narrowly but dynamically: an agent booking a single meeting room does not need standing access to the entire calendar system for every user in the company, it needs the ability to read availability and write one event, ideally only for the specific room and time window the task actually concerns, for the duration of that one task, and no longer. In practice this means moving away from provisioning agents with a fixed permission set at deployment time, the way a human employee's account is set up once and adjusted occasionally, and toward provisioning permissions per task, computed from what the specific task actually requires, granted just before the agent needs them, and expired the moment the task completes.

The permission an agent never had is the one it cannot misuse, whether the misuse comes from a bug, a bad prompt, or a deliberate attack. Scope first, and scope again for every task, rather than once at deployment.

Delegated authority: acting as someone, not as something

Most useful agent tasks are not really the agent's own action at all; they are the agent doing something a specific person authorized, on that person's behalf, using some slice of that person's own authority. An assistant that reschedules your meetings is not supposed to have some independent standing right to touch your calendar; it is supposed to be exercising a scoped, revocable slice of your right to touch your own calendar, and the distinction matters enormously the moment something goes wrong, because one framing has a clear, accountable chain back to a person and the other does not.

The technical pattern that makes this work cleanly is a form of token exchange sometimes called on-behalf-of delegation: rather than an agent authenticating with its own broad, standing credential and then separately, informally, keeping track of which user it is currently helping, the agent instead exchanges evidence that a specific user authorized this specific task for a narrowly scoped, short-lived credential that is explicitly stamped with that user's identity and explicitly limited to what that task needs. Every downstream system the agent calls sees not "the agent system, acting with its usual broad rights" but "this specific agent instance, acting on behalf of this specific person, authorized for this specific narrow purpose, expiring at this specific time."

This pattern solves a problem that a shared service-account model cannot solve at all: the confused deputy problem, where a system with broad legitimate authority is tricked into using that authority for a purpose the party who granted it never intended. An agent holding its own broad standing credential is a textbook confused deputy waiting to happen, because nothing in the credential itself distinguishes a legitimate request from a manipulated one; the credential just works, for anything within its scope, regardless of why it is being invoked. An agent holding a narrowly scoped, delegated, short-lived credential tied to one specific authorized task is structurally far harder to turn into a confused deputy, because even a successfully manipulated request is boxed in by a scope that was set before the manipulation happened, not one the agent or an attacker gets to expand after the fact.

Delegation also has to be genuinely bounded by the delegator's own authority, not just scoped narrowly in the abstract. An agent acting on behalf of a specific employee should never be able to do something that employee themselves could not do directly; if the employee has no permission to approve their own expense reports, an agent acting on their behalf has no business being able to do it either, however useful that might superficially seem. This sounds obvious stated plainly, but it is a surprisingly easy property to lose in practice, because agent tooling is often built against a broad service credential for convenience, and the check that the acting user's own permissions actually cover the requested action gets left as an assumption rather than enforced as a hard constraint at every call.

Access control diagram

Short-lived credentials and the problem with standing access

A theme runs through everything above: durations matter as much as scopes. A permission that is both narrow and permanent is still a liability, because permanent means it sits somewhere, in a config file, an environment variable, a secrets vault, indefinitely, as a target for exfiltration and a thing that has to be manually noticed and revoked if it should no longer apply. A permission that is broad but expires in minutes is, perhaps counterintuitively, sometimes the lesser risk, because its window of exploitability is small and closes on its own without anyone having to remember to close it.

The practical implication is that agent credentials should default to short-lived, task-scoped tokens issued just before they are needed and expiring shortly after the task that needed them is expected to finish, rather than long-lived credentials issued once and left to sit. This is a real engineering cost: it means building or adopting infrastructure that can issue these tokens on demand, quickly enough that the added latency does not become its own problem, and it means every downstream system the agent talks to has to actually validate token expiry rather than treating a credential as valid until someone notices otherwise and revokes it.

The payoff is that the most common way agent credentials actually get compromised, a leaked key that sits in a log file, a config repository, or a debugging screenshot for weeks or months before anyone notices, stops being nearly as dangerous, because a leaked token that expired ten minutes after the task it was issued for completed is a much smaller prize than a leaked key that will keep working until somebody actively revokes it. Short-lived credentials do not make credential leakage impossible, nothing does, but they shrink the blast radius of the leaks that will inevitably happen from indefinite to bounded, which is close to the best a real system can actually promise.

This same logic extends to a related idea worth naming directly: just-in-time access, where even a legitimate, correctly scoped permission is not granted until the specific moment the agent is actually about to use it, rather than provisioned ahead of time and left available for whenever it might be needed. An agent that requests write access to a specific record only at the moment it is actually about to write to that record, rather than holding that permission for the entire duration of a longer task, narrows the window during which a mistake, a manipulation, or a leak could actually make use of that permission to almost nothing.

Auditability: knowing who the agent was, every single time

None of the scoping and delegation machinery above is worth much if it cannot be checked afterward, and checking it afterward requires a complete, structured record of every identity claim an agent made and every action it took under that claim: which agent instance, running which task, authenticated as whom, delegated by which user, authorized for which specific scope, took which specific action, against which specific resource, at which specific time. This is a different, and more demanding, standard than the general observability trace that a well-built agent loop already keeps for debugging behavior, because an identity audit trail has to hold up not just for understanding why the agent did something, but for proving, to an auditor, a security team, or a court if it ever comes to that, exactly whose authority was actually behind a given action.

The practical requirement this creates is that every credential an agent uses should carry enough structured metadata to answer that whole chain of questions on its own, without requiring someone to reconstruct it after the fact from scattered application logs that were never designed to answer an identity question in the first place. A token that simply proves "this request came from the agent system" and nothing more forces exactly that kind of reconstruction, if it is even possible at all, at precisely the moment, an incident, a dispute, a compliance audit, when the answer needs to be fast, complete, and trustworthy rather than an approximate best guess stitched together from whatever logs happened to survive.

This is also where a subtlety about revocation becomes concrete rather than abstract. If a specific user's own access is revoked, everything they had delegated to any agent acting on their behalf needs to be revoked along with it, immediately, not on whatever schedule the agent's own credentials happen to expire. A departing employee whose account is disabled but whose delegated agent tokens keep working for another few hours because nobody wired the two systems together is not a hypothetical edge case; it is exactly the kind of gap that shows up the first time a real offboarding process meets a real agent deployment that was built without this connection in mind from the start.

A credential that only proves "this came from the agent" forces you to reconstruct who it was really acting for after the fact, at exactly the moment you can least afford an approximate answer.

Business travel booking on a laptop screen

A worked example: an agent that manages business travel

It helps to make all of this concrete against a task that sounds mundane precisely because that is where most of the real risk actually lives: an agent that books flights and hotels for employees, files the resulting expenses, and updates their calendars, on request. Nothing about this task is exotic, and that is exactly why it is a good test of whether the identity architecture actually holds up, because a task this ordinary is exactly the kind of thing that gets built quickly, with a single broad service account, by a team focused on making the booking flow work rather than on the access model underneath it.

Done with real delegated identity, the flow looks like this. An employee asks the agent to book a specific trip. The system exchanges evidence of that specific, authorized request for a short-lived, narrowly scoped credential, explicitly stamped as acting on behalf of this employee, for this trip, expiring once the booking is expected to be complete. The agent uses that credential, and only that credential, to search flights, make the booking, file the expense, and update the calendar; at no point does it hold, or need, a standing credential that could book travel for anyone else, file expenses against a budget it was not authorized to touch, or read any calendar besides the one belonging to the employee who asked.

Every one of those four actions, the flight booking, the hotel booking, the expense filing, the calendar update, is logged with the full chain intact: this agent instance, this task, this employee, this scope, this specific action, this timestamp. If the trip is later flagged during an expense audit, there is a complete, structured answer to who authorized it and under what constraints, rather than an application log that merely shows "the travel agent booked something" and forces someone to go dig through unrelated systems to reconstruct the rest by hand.

Now consider the same task built the common way, against one shared, broad service account used by the whole travel agent system for every employee, every trip, indefinitely. It works exactly the same way from the employee's point of view, and it will keep working right up until something goes wrong: a prompt injection embedded in a hotel confirmation email tricks the agent into filing an expense for a trip nobody actually took, or a bug causes it to book travel for the wrong employee entirely. In the delegated model, that failure is bounded, the blast radius is one narrowly scoped credential for one task that has already expired, and the audit trail shows exactly what happened and to whom. In the shared-credential model, the same failure has access to everything the service account can touch, for as long as nobody notices, and the audit trail, if it exists at all, is an application log that was never built to answer an identity question under real scrutiny.

Cross-agent delegation and the length of the chain

Multi-agent systems add a wrinkle worth calling out specifically, because delegation does not stop being a concern just because the thing being delegated to is another agent rather than a person. When an orchestrator agent hands a subtask to a worker agent, that handoff is itself a delegation, and it deserves the same discipline as a human-to-agent delegation: the worker should receive a credential scoped to exactly the subtask it was given, carrying an intact record of the full chain back to whichever original human authority the whole task ultimately traces to, not a broader credential that happens to be convenient to pass along because the orchestrator already had it.

The risk of skipping this discipline compounds specifically because it compounds: a chain of three or four agents, each one handing off to the next with progressively less scrutiny about exactly what authority is actually being passed forward, can end with a worker agent several hops removed from the original request holding effective access far broader than the original task ever justified, and an audit trail that, if it exists at all, has degraded at every hop into something closer to "an agent asked another agent to do a thing" than a traceable chain of accountable authority.

The fix is the same principle applied recursively: every hop in a multi-agent chain re-scopes down to what the next step actually needs, never simply forwards what it happens to be holding, and every hop preserves, rather than drops, the full delegation chain back to the human who is ultimately accountable for the outcome.

This matters more, not less, as agents increasingly need to interact with agents belonging to other organizations entirely, a supplier's ordering agent talking to a buyer's procurement agent, for instance, where there is no shared internal identity system to lean on at all and the entire relationship has to be built on credentials, scopes, and delegation chains that both sides can independently verify without trusting the other party's internal infrastructure. This is a genuinely unsolved problem at the scale the industry is heading toward, and it is one of the more consequential pieces of missing infrastructure in the agentic AI stack today, discussed further below.

Common failure modes

A handful of recurring mistakes account for most of the real-world damage in this space, and each one maps to a specific, well-understood, missing piece of discipline described above. Credential sprawl happens when every new agent or integration gets its own new standing key, provisioned quickly to unblock a project, and never consolidated, reviewed, or retired, until nobody in the organization can actually produce a complete list of what credentials exist, what they can access, and whether they are still needed; the fix is centralizing issuance through a system built specifically to track this, rather than letting each team mint its own keys ad hoc.

Over-scoped tokens happen when a team requests broad access up front because it is faster than figuring out the precise narrow scope a task actually needs, and then never revisits that decision once the deadline pressure that caused it has passed; the fix is treating scope minimization as a first-class requirement of shipping the feature at all, not a cleanup task to get to later that realistically never happens. Impersonation happens when a compromised or manipulated agent successfully takes an action as if it were a different, more privileged identity than it should have been able to claim, which delegated, narrowly scoped, short-lived credentials are specifically designed to make hard, precisely because a stolen or manipulated credential that only ever claimed a narrow scope for a short window cannot be stretched into claiming a broader one after the fact.

The silent standing grant is a subtler version of over-scoping: a permission requested for one specific task that is never actually revoked once that task is done, quietly becoming permanent simply because nobody built the corresponding revocation step into the system; the fix is making expiry the automatic default rather than something a human has to remember to do manually days or weeks after the task that needed the access has already been forgotten. And broken revocation chains happen when a user's own access changes, is reduced, or is removed entirely, but everything that user had previously delegated to an agent keeps working regardless, because the two systems, human identity and agent delegation, were never actually wired together; the fix is treating delegated access as strictly derivative of, and therefore automatically bounded by, the delegator's own current access, checked continuously rather than only at the moment delegation was first granted.

What is still missing is the layer specifically built for agents: standardized, portable ways to describe an agent's scope and delegation chain that work the same way across different vendors' agent platforms and different organizations' internal systems, the way a small number of shared protocols now let very different tools interoperate on the tool-calling side of agent architecture.

This gap will very likely close over the next few years, in roughly the way similar gaps have closed before: a handful of large platforms will ship their own version first, informal conventions will emerge from real production usage across many teams solving the same problem independently, and a shared standard will eventually crystallize out of whichever conventions actually proved durable under real adversarial pressure rather than merely convenient in a demo. Teams building agent systems today do not have the luxury of waiting for that standard to arrive before shipping, but they can, and should, build toward the principles it will almost certainly encode, since narrow scoping, short lifetimes, explicit delegation, and complete auditability are not clever anticipations of a future standard so much as they are the same handful of ideas that every mature access control system eventually converges on, independent of which specific protocol ends up carrying them.

A practical starting checklist

For a team adding identity and access controls to an agent system today, rather than trying to solve the entire problem space at once, a small number of concrete steps deliver most of the real protection. Retire shared, standing service accounts wherever an agent's actions can plausibly be tied back to a specific initiating user, and replace them with delegated, on-behalf-of credentials scoped to that user's own authority, even where the ceiling on scope is a real ceiling. Default every credential to short-lived, and treat any request for a long-lived or standing credential as something that needs a specific, documented justification rather than the default, easy path.

Scope permissions per task rather than per deployment, computing what a specific run actually needs at the moment it needs it rather than provisioning a fixed set once when the agent is first set up and leaving it unchanged indefinitely afterward. Build the audit trail as a first-class requirement from day one, capturing the full identity chain, agent instance, task, delegating user, granted scope, specific action, on every single call, not just the ones that happen to look consequential in hindsight, because the calls that turn out to matter are rarely the ones anyone would have guessed in advance.

Wire agent access into the same revocation lifecycle as the humans it acts on behalf of, so that disabling a user's account, or narrowing what they are allowed to do, automatically and immediately narrows what any agent acting on their behalf can do too, rather than leaving that connection as a manual step someone has to remember during an offboarding checklist. And in multi-agent systems, re-scope explicitly at every handoff between agents rather than forwarding whatever credential happens to be convenient, preserving the full chain back to the original human authority at every single hop rather than letting it quietly degrade a little at each step.

Why this is worth the engineering cost

All of this is more work than dropping one API key into an environment variable and moving on, and it is fair to ask whether that extra work is actually worth it for a given system. The honest answer scales with two things: how consequential the actions the agent can take actually are, and how many different people or contexts the agent operates across. An agent that only ever reads public information and summarizes it for one person can reasonably get away with a fairly light identity model, because the cost of it going wrong is genuinely small. An agent that can send money, delete records, send messages on someone's behalf, or act across many different users' data cannot, because the cost of a single confused, compromised, or manipulated action multiplied across everyone that agent has standing access to is exactly the kind of tail risk that a shared, broad, standing credential does nothing to bound.

The deeper reason this is worth building properly, rather than adding as an afterthought once something has already gone wrong, is that identity is one of the few pieces of agent infrastructure that is genuinely hard to retrofit. A model can be swapped, a prompt rewritten, a tool redesigned, mostly without touching anything else in the system. An identity architecture is load-bearing in a different way: every tool, every integration, every downstream system the agent touches ends up depending on the assumptions baked into how the agent authenticates and what it is authorized to do, and unwinding a shared, broad, standing-credential model after dozens of integrations have been quietly built against its assumptions is a substantially larger undertaking than building the narrower, delegated model correctly the first time, before anything else in the system has come to depend on the shortcut.

Where this leaves agent builders

Agent identity is not a solved problem in the way that, say, basic tool-calling conventions increasingly are, and teams building real systems today are, to a meaningful extent, building the practices this piece describes slightly ahead of the standards that will eventually formalize them. That is an uncomfortable position to build in, but it is not a reason to default back to the shared service account, because the underlying principles, narrow scope, short lifetime, explicit delegation, complete auditability, do not depend on which specific standard eventually wins; they are the same handful of ideas every mature access control discipline has converged on before, applied to a kind of actor, one that reasons, acts, and sometimes errs, that access control has not had to seriously reckon with until now.

The teams that get burned by this are rarely the ones building genuinely exotic, high-autonomy agents operating in adversarial environments; the risk there is at least visible enough that someone usually thinks about it. The teams that get burned are far more often the ones who built something that felt too mundane to warrant the extra care, a scheduling assistant, an internal support bot, a travel booking tool, using one convenient, broad, standing credential because the task itself seemed low-stakes, right up until an ordinary bug, an ordinary prompt injection, or an ordinary compromised key turned an unremarkable convenience into an incident with a blast radius nobody had actually bounded, because nobody had gotten around to asking, early enough to matter, exactly who this agent was allowed to be.