Stop Giving AI Agents Standing API Keys
Least Privilege, but for Non-Human Identities
We have decades of practice applying least privilege to people. Agents are different in three ways that make standing credentials especially risky:
- They act fast and unattended. A misused human credential might do damage for minutes before someone notices. An agent loop can make thousands of calls before anyone looks.
- Their instructions are attacker-reachable. Prompt injection means the thing deciding how to use a credential can be steered by untrusted input.
- They fan out. One agent calls another, which calls a tool, which calls an API. Scope has to travel with the request, not live in a shared secret.
So the unit of access for an agent should be a short-lived, narrowly scoped credential minted for a specific task - not a copy of your production key.
What "Scoped" Actually Means
A useful scoped credential pins down several dimensions at once:
- Audience - which upstream API or MCP server it is valid for.
- Operations - which methods or tools, e.g. read but not write.
- Resources - which endpoints, paths, or object IDs.
- Lifetime - minutes, not months. It expires on its own.
- Rate - a ceiling on calls per window, so a runaway loop is contained.
In practice a grant looks something like this:
{
"audience": "api.github.com",
"operations": ["GET"],
"resources": ["/repos/acme/billing/issues/*"],
"expires_in": "15m",
"rate_limit": "60/min"
}
When all five are tight, a leaked credential is worth very little: it stops working almost immediately and only ever opened a small door.
The Broker Pattern
The cleanest way to deliver this is a credential broker that sits between your agents and your secrets. The model never sees a real secret. Instead:
- The agent asks the broker to perform an operation (often via an MCP tool).
- The broker checks policy: is this principal allowed to do this, right now, within limits?
- If allowed, the broker injects the real credential at the edge, makes the call, and returns the result.
- Every step is recorded.
Because the secret is resolved at call time and never handed to the model, you can rotate or revoke it without touching a single agent. And because the broker is the one place every agent call flows through, it is also the natural place to enforce scope and capture an audit trail.
A Practical Migration Path
- Inventory the keys your agents hold today. Anything long-lived and broad is the priority.
- Move secrets behind the broker. Replace in-agent keys with a reference the broker resolves.
- Tighten scope per task. Start permissive, then ratchet down using what the audit log shows the agent actually needs.
- Shorten lifetimes. Once issuance is automatic, expiry becomes free.
The end state: agents carry no durable secrets, every credential is minted for a purpose and expires on its own, and you can answer "what could this agent do?" by reading a policy instead of guessing. Least privilege was always the goal - scoped, short-lived credentials are how agents get it by default.
Comments
No comments yet. Start the discussion.