For every action, the right access: defining auth for agents
Earlier this year, an AI coding agent working on a routine task went looking for a way to fix an issue: a credential mismatch in the staging environment. It found a Railway API token in an unrelated file and used it to delete a production database volume, backups included, in nine seconds.
The agent was doing what agents are supposed to do. It hit a problem, looked around, and found a path nobody anticipated. The token worked exactly as designed. It just reached far more than the job needed, and nothing on Railway’s side could tell that deleting production had nothing to do with fixing staging.
The incident exposes the assumption that almost every auth system is built on: whoever holds a credential can do anything it allows. That assumption held up when the holder was a person or a service doing one predictable job, but it falls apart with agents. If we want agents running our companies, our software pipelines, and more of our daily lives, auth has to change.
Every action has to map to its intent
Every shift in computing, from the web to the cloud, required a new identity and access model. Until that happened, nobody trusted the new platform with anything important. Agents are the next shift. An agent decides what to do as it goes, often with nobody watching.
An agent like that needs broad capability to do real work on its own, often across many tasks over hours or days. Broad capability is only safe if there’s a straight line from intent to action to access. Every action serves the agent’s task and gets only the access that task requires, for only as long as it’s needed.
Take an incident agent that runs around the clock. At 2am, checkout errors spike, and it needs to read the checkout service’s logs. An hour later, a build server runs out of disk and it needs that server’s metrics. The next alert might be something the agent has never seen before, so there’s no way to list ahead of time what it needs access to.
A static role broad enough to cover everything the agent might need covers far too much. Instead, access has to be given dynamically, based on each task in front of it. The goal is to make this true for every agent an organization runs, whether it’s built or bought, prompted by a person or woken by an event.
Auth for agents comes down to two things:
- Deciding an agent’s access from the full context of the task: who it’s acting for, what the task requires, and what the organization allows.
- Enforcing access as the work happens across every agent and every system it touches, and bringing people back in when an agent needs more.
Deciding access from the full context of the task
When the coding agent sent its delete request, Railway saw a valid token and nothing else. The request needed to mean something much narrower:
This agent, acting for itself or for whoever handed it the work, on this task, can do this one thing right now.
Most of that information already exists around the agent. The prompt or trigger says who it’s acting for and what it’s meant to do. All of it disappears once the work becomes an API call with a token attached. We call that loss the context gap, and closing it is the core of auth for agents.
Who’s acting, and how the work got to them
Most people picture auth for agents as acting on a person’s behalf, but more and more, agents act as themselves or for other agents. No one tells the incident agent what to do. An alert wakes it up, and from there it works under its own identity. If it hands log analysis to another agent, that log agent can read logs on the incident agent’s behalf, and it gets only the access needed for that task.
As teams rely more on multi-agent delegation, the context behind each handoff has to trace back to the original trigger or human who handed over the work. It can’t come from the agent’s own description of its task, or an agent could talk its way into more access. That context also becomes the audit trail, so when something goes wrong, you can trace it back to which agent acted, for whom, on what task, and who approved it.
Today, each agent usually has its own service credentials, but they’re static and don’t consider the task at hand. Across thousands of agents, that becomes a web of standing access nobody can trace back to a piece of work. Instead, each handoff should pass along only what the new piece of work needs.
What the agent can do, and what this task requires
An incident agent built to resolve alerts has no business flipping feature flags or issuing refunds. Within its own work, the right answer still depends on the task. Clearing the checkout cache is the right call when stale data caused the alert, and a disaster while another team is mid-migration on the same service. The agent, the team, and the action are the same; only the work changed.
What the organization never allows
Some rules don’t depend on the task at all. No agent deletes a production volume, any purchase over $10,000 needs a second approval, and no agent reads patient records from outside the HIPAA-scoped environment. The first of those rules alone would have stopped the Railway delete. Rules like these live in policy, outside the agent, where nothing the agent says can change them. As Agent Baseline puts it, “A boundary written in a prompt is an instruction. A boundary enforced by the environment is a control.”
The scope of access is the intersection of what the agent can do with the authority it has and what the task needs, all within the bounds of what the organization allows:
Venn diagram inside a box labeled what the organization allows: one circle is what the agent can do, the other is what the task needs, and their overlap is the access for this task.
So auth for agents has to:
- Make a decision for every action, using the full context of the task.
- Reassess access at every handoff, which can mean denying it or narrowing it to what the receiving agent can do and what its new task requires.
- Enforce hard limits as policy, however convincing the case for bypassing them.
Enforcing access as the work happens
Knowing what an agent should be allowed to do doesn’t help if the systems it touches can’t enforce it. Most can’t today, so enforcement comes down to issuing access per task and bridging what’s already there.
Issuing task-scoped access
Instead of standing access, an agent should be granted short-lived, task-scoped credentials tied to its identity and task. Access expires when the task ends, and can be revoked the moment something looks wrong. When the incident agent resolves the checkout alert and picks up the full disk alert, its access to checkout logs ends and a new credential gives it server metrics instead.
Sometimes the work needs more than the task allows. Partway through freeing up disk space, the agent might find it needs to move old build artifacts into an S3 bucket owned by another team. The agent can’t widen its own access, so the request is denied by default. Policy can allow for escalation, which might look like a Slack message that goes to the team who owns the S3 bucket. Someone can then approve the request, deny it, or change the work. An approval grants another short-lived credential for that task, not a permanent upgrade to what the agent can do. Escalation should be the exception, not the rule, because routing every request to a person just creates approval fatigue, and a tired reviewer approves everything.
Bridge today, federate tomorrow
A single task might take an agent through multiple systems, each with a different interface: a static API key, a half-finished OAuth integration, a database password, and a cloud IAM role. None were built with agents in mind. Even systems with fine-grained scopes have no idea what task an agent is on, and each only secures itself while the agent moves across all of them.
Protocols like token exchange and Cross-App Access already carry some pieces of context between systems, and newer ones like AAuth are emerging to carry more. However, none of them are fully deployed or widely adopted yet, and few systems can enforce access this way today.
Agents will push all of this toward common standards over time. For now, the answer is bridging the gap: brokering existing credentials and enforcing decisions in front of systems that don’t understand task context. It’s the same idea as a sandbox or virtual machine, applied to everything an agent can reach across your systems.
Each kind of agent gets there a little differently:
- Agents that can reach anything through a browser, shell, or network, like coding agents, run in a sandbox. Their only way out is an egress proxy. Secrets stay out of the context window and out of the agent’s hands. A token the agent finds in a file doesn’t change what it’s allowed to do.
- Hosted agents you buy reach your systems through a gateway in front of them. MCP gateways are a start, but they only see MCP traffic. Most don’t tie access to the task or give you one place to register agents, manage their identities, and revoke access when something goes wrong.
- Agents built on task-aware tools can carry their own scoped credentials.
- Some systems can’t take task context at all. For those, a gateway translates the decision into something they understand, like a short-lived OAuth token or a database login for one schema.
Most organizations will run all of these at once. That’s why they need one agent auth system underneath, deciding access the same way on every path.
Bridge today vs. federate tomorrow. Today, a coding agent on a device goes out through a local egress proxy, a hosted agent you bought reaches your resources through a gateway, and an agent you built in the cloud goes out through an egress proxy, each getting short-lived, task-scoped access. Tomorrow, an agent that carries task context reaches federated systems directly with no proxy or translation. All paths exchange tokens with one agent auth system that handles identity and registry, policy, escalation, telemetry and audit, and revocation.
So auth for agents also has to:
- Give every agent a stable identity that can be disabled everywhere it acts.
- Grant short-lived, identity-bound access for each task, and revoke it when the task ends or something looks wrong.
- Deny requests for more access by default, and escalate only when policy allows, to whoever can grant it.
- Enforce access at points agents can’t route around, in terms each system understands.
- Record who acted, for whom, for what task, and who approved it, even when the downstream system only logs a token.
What changes when access follows the work
Making agents predictable was never going to be how we make them safe, since finding unexpected paths is the point. What makes them safe enough to adopt widely is short-lived, task-scoped access that’s derived from the full context of the task and enforced as the work happens. That’s the standard we believe auth for agents has to meet, and it’s what Keycard is built on.
Once access follows the task, agents can take on work nobody has time to supervise, like working incidents overnight or writing new software while we focus on higher-value work. At that point, teams stop asking what an agent might break and start asking what to hand it next.
- Agent on a device Like a coding agent on a laptop The device Sandbox Coding agent No secrets in its context Local egress proxy Agent’s only way out Short-lived, task-scoped access APIs, SaaS, cloud services Anything the agent reaches out to Token exchange with the agent auth system
- Hosted agent you bought The vendor runs the agent and its sandbox Vendor's cloud Hosted agent Vendor’s harness, not yours Gateway In front of your resources Short-lived, task-scoped access Your protected resources Databases, internal APIs, S3 Token exchange with the agent auth system
- Agent you built, in the cloud Runs in your own sandbox Your cloud Sandbox Your agent No secrets in its context Egress proxy Agent’s only way out Short-lived, task-scoped access Cloud and SaaS resources S3, Postgres, GitHub, Slack Token exchange with the agent auth system
- Identity and registry
- Policy
- Escalation
- Telemetry and audit
- Revocation