A support agent we reviewed last quarter had one job: look up an order, check the refund policy, and either issue the refund or escalate. It worked well. Then somebody asked what would happen if a customer pasted a crafted message into the chat. The answer was uncomfortable. The agent held a Salesforce integration token copied from a service account that the ops team had set up in 2023. That token could read every contact record in the org, modify opportunity stages, and delete cases. Nothing in the agent's design used those permissions. Nothing in the agent's design prevented them either.
This is the normal state of agent deployments right now. Not a design failure by careless engineers, but the path of least resistance: you need the agent to call an API, you have a token that works, you paste it into the environment config, and the demo ships. The credential outlives the demo. It outlives the person who created it. And by the time you have twelve agents in production, you have twelve copies of the same over-privileged secret sitting in environment variables, container images, and somebody's .env file.
The fix is not better prompts. Prompt-level guardrails are probabilistic controls on a nondeterministic system, which is a bad place to put your last line of defense. The fix is identity: every action an agent takes should carry a credential that was minted for that action, expires in minutes, and can be traced back to a human or a policy decision.
The credential your agent holds is the credential an attacker gets
Start with the threat model, because it is simpler than the vendor pitches suggest. An agent is a program that takes untrusted input, makes decisions about what to do, and calls tools with whatever authority it has. Simon Willison's lethal trifecta framing covers the data exfiltration path: private data plus untrusted content plus an outbound channel. Credential exposure is the same shape one layer down. If the agent's process can read a token, then anything that can influence the agent's process can use that token.
That includes prompt injection, but it also includes far more boring things: a logging misconfiguration that writes the environment to stdout, a debugging endpoint left open, a compromised dependency in the agent's own toolchain, or an engineer with production access who should not have had it. Credential abuse has consistently ranked as the leading initial access vector in Verizon's Data Breach Investigations Report, and agents multiply the number of places credentials live without adding any new controls by default.
The scale problem is worse than the exposure problem. Non-human identities already outnumber human ones in most enterprises by a wide margin, and agents accelerate that curve because each agent instance, each sub-agent, and each MCP server connection wants its own access path. OWASP now maintains a Non-Human Identities Top 10 specifically because the failure modes differ from human identity: no MFA, no offboarding process, no natural expiry, and secrets that get shared across environments because rotation is painful.
Security capital is following the problem. Zenity raised a $125M round for agent security tooling this year, and the category is filling up fast, which usually means the patterns are not settled yet. That is the right time to pick an architecture based on standards rather than on whichever platform is loudest.
Four properties, and why your current setup has none of them
Here is the mental model worth keeping. An agent credential needs four things:
| Property | What it means | What static tokens do |
|---|---|---|
| Ephemeral | Expires in minutes, not never | Live until manually rotated |
| Scoped | Grants one operation on one resource | Grant whatever the service account has |
| Bound | Tied to the user or task that triggered the action | Anonymous, indistinguishable across callers |
| Revocable | Killable without redeploying the agent | Revoking breaks every agent using the copy |
Most teams get partial credit on the first one because their secrets manager supports TTLs. Almost nobody gets the third one, and the third one is where the value is. Binding means that when your agent updates a Zendesk ticket, the audit log shows the action was taken on behalf of a specific customer service rep, through a specific agent, for a specific task. Without binding, you get a log line saying api-integration-svc did something, which is exactly as useful as no log line at all when compliance asks.
Role-based access control does not save you here. RBAC assumes a stable mapping between an actor and a set of permissions, defined ahead of time. An agent's required permission set is a function of the task it was handed, which is a function of what a user typed. You cannot enumerate roles for that. What you can do is move the decision to call time, which is the same conclusion NIST reached for network access in SP 800-207: stop granting access based on where the request came from, and evaluate each request against policy at the moment it happens. Agents make that principle unavoidable rather than aspirational.
We wrote about the tool-design side of this in least-privilege tools for AI agents. Identity is the enforcement layer that makes those tool boundaries real instead of advisory.
The broker pattern, concretely
The architecture is not new. It is the same one your CI system uses, and if you run GitHub Actions with cloud deployments you are already running it in production.
The flow has four participants: the agent workload, an identity provider that can attest the workload, a broker that applies policy and mints credentials, and the downstream tool. Nothing about it is agent-specific, which is the point.
Step one: the workload proves what it is. The agent does not present a secret. It presents a cryptographic identity issued by the platform it runs on. SPIFFE defines this as an SVID, a short-lived X.509 certificate or JWT with an identity like spiffe://prod/agents/support-triage. Kubernetes projected service account tokens, AWS IAM roles for pods, and GitHub's OIDC tokens all do the same job. The GitHub OIDC documentation is the clearest short explanation of why this beats stored secrets: nothing long-lived exists to steal.
Step two: the broker exchanges identity for authority. This is where RFC 8693, OAuth 2.0 Token Exchange, does the work. The agent sends its workload token plus the user's session token as an actor_token and subject_token pair. The broker validates both, checks policy, and returns an access token scoped to one audience with one set of scopes. The delegation semantics are already specified: the resulting token can carry an act claim showing that the agent acted on behalf of the user, which is exactly the audit primitive you need and exactly the thing teams reinvent badly when they skip the standard.
A request looks roughly like this:
POST /token HTTP/1.1
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=<user session token>
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&actor_token=<agent SPIFFE JWT>
&actor_token_type=urn:ietf:params:oauth:token-type:jwt
&audience=https://api.zendesk.com
&scope=tickets:read tickets:comment
Step three: policy runs at call time. The broker is where you answer questions the agent framework cannot: does this user actually have access to this ticket, is this agent version approved for write operations, is this the fourth refund this hour from a session that started ten minutes ago. Policy engines like Open Policy Agent handle the evaluation; the important design choice is that the answer is computed per call, not baked into a role.
Step four: the token dies. Five minute TTL, single audience, and ideally sender-constrained so a stolen token is useless from a different workload. DPoP, RFC 9449, or mutual TLS binding both accomplish this. If you do nothing else from this article, shortening TTLs and setting a single audience per token removes most of the blast radius.
Cloudflare's open-sourced agent workspace platform, released this month, builds its whole isolation story on this claim: the agent process never receives long-lived credentials, and every outbound call goes through a mediating layer. Their engineering blog is worth reading for the sandboxing details, but the identity design is the part other teams should copy first.
If you are on a major cloud, most of this exists already. Google Cloud's workload identity federation and its AWS and Azure equivalents will trade an external OIDC token for short-lived cloud credentials without any stored keys. Start there before you build anything.
What actually breaks when you ship this
Four failure modes show up in every migration.
Long-running tasks hit token expiry mid-run. A research agent working for forty minutes with a five minute token will fail on its ninth tool call. The wrong fix is a longer TTL. The right fix is to request a credential per tool call and treat a 401 as retryable. That means your tool wrapper needs a refresh path, and your agent loop needs to not surface auth errors to the model as task failures. Budget a day for this.
Sub-agents inherit too much. When a planner spawns workers, the naive implementation passes the parent's token down. Now the worker that only summarizes documents can also issue refunds. Token exchange handles this properly: the sub-agent performs its own exchange with a narrower scope request, and the delegation chain stays visible in the act claim. Multi-agent systems without scope attenuation are the single most common place we find privilege escalation.
MCP servers become a credential aggregation point. An MCP server connected to eight tools holds eight sets of credentials, and the agent's authority becomes the union of all of them. The MCP authorization specification addresses this by treating the server as an OAuth resource server, but plenty of deployed servers predate it and still use static config. Audit your MCP servers separately from your agents.
Nobody can revoke anything quickly. Short TTLs give you revocation by expiry, which is fine for most cases and useless during an active incident. You want a kill switch at the broker that stops issuing for a given agent identity, workload, or user, and you want somebody to have tested it. A revocation path you have never exercised is not a control.
The audit trail question deserves its own attention, particularly for regulated deployments. We covered what evidence supervisors expect in AI agent audit trails, and the short version is that brokered credentials give you the linkage between human authorization and machine action that reconstructing from application logs never quite does.
A migration path that does not stall
You do not need to rebuild everything. Sequence it:
- Inventory. Every credential reachable by every agent, with expiry, scope, and owner. One day of work, and it usually settles the prioritization argument by itself.
- Shorten and scope. Before touching architecture, cut TTLs and split the shared service account into per-agent accounts with the minimum permissions each one actually uses. Instrument first so you know what they actually use.
- Put a broker in front of one tool. Pick the highest-risk write path. Route it through token exchange while everything else stays as-is. This proves the pattern against your real latency and error handling.
- Add user binding. Once the broker exists, pass the user context through and start writing the delegation claim into your logs. This is where compliance value appears.
- Migrate remaining tools, then delete the static secrets. The deletion step matters. Unused credentials that still work are still a breach vector.
Teams that try to do all five at once tend to stall at step three because the error handling surprises them. Teams that do them in order ship the first two in a week.
How OpenNash Can Help
Identity work is unglamorous and it is the thing that determines whether an agent deployment survives its first security review. When we run an audit, credential scope is one of the first things we map, because it usually reveals more about a system's real risk than the model choice or the prompt design does. From there the design phase sets the broker boundaries, the approval points where a human has to sign off before a token gets minted, and the failure handling for expiry and revocation. Build and deploy include the CI/CD integration and the documentation your security team needs to sign off, and the client owns all of it afterward.
Not every team needs custom work here. If your agents touch one SaaS product that already supports fine-grained OAuth scopes, configure it properly and move on. If you are early enough that you have one agent in staging, shorten the TTLs and revisit this in a quarter. Custom implementation earns its cost when agents span several systems of record, when regulated audit requirements apply, or when you need the delegation chain to hold across sub-agents. Book a call to map this to your workflow.
The question worth asking on Monday
Pull up your agent's configuration and find the credentials. For each one, answer three questions: when does it expire, what is the worst thing it can do, and who gets paged if it is used at 3am on a Sunday.
If you cannot answer all three for every credential, that is the work. The token exchange plumbing is a week or two of engineering against specifications that have existed for years. Deciding that agents should never hold keys is the part that requires a decision, and it is easier to make now, with three agents in production, than after the number is thirty.