If you’re building with AI agents today, there’s a good chance at least one of them has more access than it should.
Maybe it’s a coding agent with a long-lived GitHub token. Maybe it’s an MCP-connected assistant that can read internal docs, open PRs, and hit production-adjacent APIs. Maybe it’s “just” a bot running in CI with a secrets bundle you copied from another service account because it was faster than designing proper access controls.
That works right up until you need to answer basic questions like:
- Which agent actually performed this action?
- Was it allowed to do that?
- Who delegated that permission?
- Can I revoke access without breaking everything else?
- If the agent is compromised, what’s the blast radius?
This is where a lot of agent systems start to look like the early cloud era: too many shared secrets, too little identity, and almost no principled authorization.
The fix is not “more API keys.” It’s giving agents real identities and binding permissions to those identities with RBAC, delegation, and auditability.
The core problem: API keys don’t describe who an agent is
Most agent integrations still rely on bearer credentials:
- API keys in environment variables
- Shared service accounts
- OAuth tokens with broad scopes
- Static secrets copied across tools and workflows
The problem with bearer credentials is simple: possession is identity.
If an agent, plugin, prompt injection, or compromised tool gets the token, it gets the authority. There’s no strong distinction between:
- the human who initiated the task,
- the agent executing it,
- the tool being called,
- and the environment where it runs.
That makes least-privilege hard and incident response worse.
A better model is:
- Every agent gets a cryptographic identity
- Permissions are granted to roles, not hardcoded into secrets
- Delegation is explicit, scoped, and auditable
- Every action can be tied back to an identity chain
This is the same direction infrastructure security went years ago. AI agents need the same treatment.
Why cryptographic identity matters
A cryptographic identity gives an agent a verifiable, non-shared way to prove who it is.
For example, with an Ed25519 keypair, an agent can sign requests or attestations. A verifier can check:
- this request came from the holder of the private key,
- the identity is the one we expect,
- and the message wasn’t tampered with in transit.
That’s fundamentally different from “here’s a token string, trust me.”
In practice, crypto identity helps with a few important things:
1. Strong attribution
You can distinguish:
agent:code-review-botagent:release-assistanthuman:alicetool:mcp/github
instead of seeing everything as “somebody had the token.”
2. Safer machine-to-machine auth
Agents increasingly call other agents, MCP servers, internal APIs, and task runners. Signed identity lets you verify the caller directly rather than relying only on network location or copied credentials.
3. Better delegation
If Alice authorizes an agent to open a PR on her behalf, that should be represented as a scoped delegation, not “give the bot Alice’s token.”
Standards like RFC 8693 token exchange are useful here because they model delegated access explicitly.
Why RBAC still matters for agents
There’s a temptation to think agent authorization needs something entirely new. In reality, plain old RBAC is still a strong baseline.
Roles answer a simple question: what category of actions should this agent be able to perform?
For example:
repo.readrepo.write.prdocs.searchbilling.noneprod.deploy.approver
That’s already much better than one “agent token” with unlimited access.
A minimal role model might look like this:
{
"roles": {
"code_reviewer": [
"repo.read",
"pr.comment",
"ci.read"
],
"pr_creator": [
"repo.read",
"branch.write",
"pr.create"
],
"deploy_agent": [
"artifact.read",
"deploy.request"
]
}
}
Then bind identities to roles:
{
"bindings": [
{
"subject": "agent:review-bot",
"roles": ["code_reviewer"]
},
{
"subject": "agent:release-bot",
"roles": ["deploy_agent"]
}
]
}
This gives you a clean separation between identity and permission.
And if RBAC isn’t expressive enough? Use policy on top. OPA is a perfectly good answer for many teams.
For example, you might allow PR creation only on non-protected branches and only during a delegated session:
package agent.authz
default allow = false
allow {
input.subject.type == "agent"
input.action == "pr.create"
input.resource.repo == "acme/app"
not input.resource.branch_protected
input.delegation.active == true
}
RBAC gives you the broad shape. Policy gives you the edge-case control.
The missing piece: delegation chains
A lot of agent actions are not autonomous in the pure sense. They’re delegated.
Examples:
- A developer asks an agent to patch a dependency
- A support agent updates a ticket on behalf of a human operator
- A coding agent opens a PR using a temporary permission granted from a CI workflow
- A planner agent delegates execution to a worker agent
If you flatten all of that into one credential, you lose context.
Delegation chains preserve it:
- Human requests task
- Coordinator agent receives delegated scope
- Worker agent executes a narrower subtask
- Tool/API verifies the chain before allowing the action
That means your logs can say more than “token used successfully.” They can say:
agent:worker-17created PR#4821, delegated byagent:planner-2, originating fromhuman:alice, scoperepo.write.pr, expires in 10 minutes.
That is a much better security and operations story.
A practical starting point
You don’t need to rebuild your whole stack tomorrow. Here’s a reasonable path.
1. Stop sharing agent credentials
If multiple agents use the same API key, split them now.
Bad:
GITHUB_TOKEN=shared-super-token
Better:
AGENT_REVIEWER_TOKEN=...
AGENT_PR_CREATOR_TOKEN=...
AGENT_DOCS_TOKEN=...
Even before full crypto identity, unique credentials improve attribution and revocation.
2. Define roles before adding more tools
List the actual actions each agent needs.
Example:
agents:
review-bot:
roles:
- repo.read
- pr.comment
fix-bot:
roles:
- repo.read
- branch.write
- pr.create
deploy-bot:
roles:
- artifact.read
- deploy.request
If an agent “needs admin,” that’s usually a design smell.
3. Add short-lived delegated credentials
When a human or upstream system authorizes an action, mint a short-lived delegated token instead of handing over a broad long-lived secret.
Pseudocode:
const delegatedToken = await issueDelegatedToken({
subject: "agent:fix-bot",
actor: "human:alice",
scope: ["repo.read", "branch.write", "pr.create"],
ttl: "10m"
});
The exact implementation can be OAuth token exchange, signed JWTs, or your existing identity provider if it supports this well.
4. Verify identity at the edge
If you expose internal tools or MCP servers, verify the calling agent before processing requests.
For example, require:
- a signed request,
- an attached identity document or token,
- and an authorization check against role/policy.
Conceptually:
def authorize(request):
identity = verify_signature(request)
claims = parse_delegation(request.token)
if not identity:
return deny("invalid identity")
if "pr.create" not in claims.scopes:
return deny("missing scope")
return allow()
5. Log the full chain
For every sensitive action, log:
- subject identity
- delegated actor
- scopes
- target resource
- approval status
- timestamp
- request/session ID
Without this, security reviews turn into archaeology.
Where Authora fits
If you’re building this yourself, the main ideas still apply: crypto identity, RBAC, delegation, policy, and audit trails.
Authora’s identity stack is built around those primitives for AI agents: cryptographic agent identities, RBAC, delegation chains, MCP authorization, policy enforcement, approvals, and audit logging. But the broader point is more important than any single platform: agents should be treated like first-class principals in your security model.
And if your team already has good IAM, OPA, or internal auth infrastructure, use it. The goal is not to replace solid security patterns. It’s to extend them to agents before the sprawl gets worse.
Try it yourself
If you want to start hardening agent identity and access today, here are a few useful free tools:
- Want to check your MCP server? Try https://tools.authora.dev
-
Scan your codebase for agent security issues:
npx @authora/agent-audit - Add a verified badge to your agent: https://passport.authora.dev
- More resources and papers: https://github.com/authora-dev/awesome-agent-security
A good first step is to audit where your agents are using shared credentials, then map those agents to explicit roles and short-lived delegated access.
The biggest security improvement usually isn’t fancy. It’s replacing “one secret that does everything” with “an identifiable agent that can only do its job.”
-- Authora team
This post was created with AI assistance.
Top comments (0)