The Agent Did It. But the Logs Say You Did.
Why AI agents need their own identities, scoped permissions, audit trails, owners, and kill switches before they touch production.
The agent opened the pull request. The audit log says you did.
That’s not a bug. The permissions worked exactly as designed. The agent used the OAuth token someone handed it, took an action every system in the chain accepted as legitimate, and moved on. No exploit, no escalation, no alert. Just a credential that doesn’t tell you who’s actually behind it.
This is already causing real damage. Not because agents broke through firewalls. Because they used borrowed credentials, did something wrong, and nobody could cleanly trace it back.
Borrowed credentials, invisible agents
Most agent setups start the same way. You connect the agent to Slack, Jira, GitHub, your cloud account, a few internal APIs. The easiest path is already there: reuse the user’s session, reuse a shared service account, drop a long-lived API key into the workflow engine.
It works immediately. Which is exactly why it spreads.
Nobody’s trying to build a security mess. They’re trying to get the agent to do something useful. Read this ticket. Summarize this incident. Open a pull request. Triage these alerts. Then the agent becomes useful enough that people give it more access. Still using borrowed permissions. Still showing up in logs as someone else.
The access isn’t the problem. Access is the whole point. The problem is that the access doesn’t belong to the agent, so the accountability doesn’t either.
Most enterprises still use shared credentials for agent-to-agent authentication. No individual accountability. No way to revoke one agent without disrupting five other workflows. No way to answer “which agent did this?” during an incident.
Agents aren’t scripts
A script runs a known path. Calls the same API. Transforms the same input. If it has a bug, the bug is in the code. You fix the code.
Agents are different. They read context, make decisions, choose tools, and adapt based on what comes back. A Jira ticket, Slack message, README, or support request can become part of the decision loop. That’s not a flaw. That’s the feature. But it means our old access patterns don’t fit.
A service account assumes the software behind it behaves predictably. A human token assumes there’s a human making the judgment call. An agent sits between those two models. It’s software, but it makes choices. It can act for a human, but it isn’t the human. It can call APIs, but the sequence of calls isn’t known ahead of time.
When something goes wrong, most systems answer one question well: which credential was used? That was enough when credentials mapped cleanly to a person or a workload. It’s not enough when an agent is borrowing that credential.
You need to know: which agent acted? Who owns it? Was it acting on its own or on behalf of a user? Which tools was it allowed to use? What triggered the action? Can you turn it off without breaking ten other things?
If your audit trail can’t answer those, it’s a credential usage log with a nice UI.
The access contract
Every production agent needs a clear boundary that says what it is, who’s responsible for it, and what it can do.
# agent-access-contract.yaml
agent:
name: pr-review-agent
owner: platform-team@company.com
purpose: Review pull requests for security and code quality
permissions:
github:
- repo:read
- pull_request:comment
jira:
- issue:read
- issue:transition
execution_mode: autonomous
expiry: 2026-07-01
kill_switch: /agents/pr-review-agent/disable
That’s the shape. Not a 40-page policy document. A configuration that captures six things:
Name. Not automation, not bot, not svc-prod-admin. A real name that shows up in logs and alerts. When you see pr-review-agent in a trace, you know what you’re looking at.
Owner. A human or team that gets paged when it does something weird. No owner means nobody’s accountable when things go sideways.
Scoped tools. The systems it can touch, and the exact operations. A review agent needs read access and comment permissions. It doesn’t need push access, terminal access, or deploy permissions. Same principle as right-sized agents, applied to identity.
Execution mode. Whether it acts autonomously, needs approval, or only runs on behalf of a user. This isn’t a prompt instruction. It’s an application-level gate the model can’t bypass.
Expiry. When the identity or permission grant must be reviewed. Permanent agent credentials are just service account sprawl with a different name.
Kill switch. A way to revoke the agent without taking down unrelated automation. If a shared service account powers five agents, three scripts, and a nightly job, nobody wants to rotate it during an incident. It becomes too risky to touch. So the bad identity survives because the blast radius of fixing it is bigger than the blast radius of leaving it alone. That’s backwards. An agent should be easy to kill because its identity is specific.
Acting as itself vs. acting for a user
Two very different modes. They shouldn’t look identical in the logs.
Sometimes the agent acts as itself. A security triage agent reads alerts, enriches them, opens low-priority tickets. Nobody asked it to do a specific thing. It’s operating inside its own assigned job. The audit trail should show the agent identity, its owner, and its assigned scope.
Sometimes the agent acts on behalf of a user. You ask a coding agent to open a pull request. You ask a support agent to refund a customer. The audit trail should preserve both sides: the user requested it, pr-review-agent performed it.
{
"actor": "pr-review-agent",
"on_behalf_of": "amit@company.com",
"action": "pull_request.comment",
"scope": "repo:read, pull_request:comment",
"trigger": "webhook/pr-opened/4521"
}
Lose either side and incident response gets weird. If you only log the human, you can’t tell what the agent actually did. If you only log the agent, you can’t tell who initiated the work. The user explains intent. The agent explains execution. You need both.
Don’t let the model draw the boundary
One easy mistake is turning all of this into prompt text.
“Only use approved tools.” “Always ask before taking destructive action.” “Do not access sensitive data.”
That’s not access control. That’s a suggestion written inside the part of the system most exposed to bad input. Researchers already found over 30 vulnerabilities in AI coding tools including prompt injection flaws leading to arbitrary code execution. If the boundary lives in the prompt, the boundary moves when the prompt gets manipulated.
Your application decides which tools the agent can see. Your authorization layer decides which scopes it gets. Your approval gate decides whether a destructive action proceeds. Your logging layer records the agent, the user, the tool, the input, and the result.
The model reasons inside the boundary. It doesn’t get to draw it.
Where the ecosystem is heading
The industry is starting to treat this seriously.
Microsoft Entra Agent ID (public preview, May 2025) gives agents their own identity type with separate sign-in logs, audit trails, and role-based access control. It’s one vendor’s implementation, but it proves the pattern works at scale.
NIST launched an AI Agent Standards Initiative in February 2026 focused specifically on agent authentication, authorization, and identity infrastructure. The MCP authorization spec bakes OAuth flows and scope challenges directly into agent-tool connections. The A2A protocol brings identity into agent-to-agent communication through Agent Cards with capabilities, security requirements, and signatures.
Different pieces, same direction. Agents are becoming real actors in software systems. Real actors need identity.
Honest trade-offs
Agent identity adds friction to a workflow that currently has none. Copy-pasting a service account key into an agent config takes 30 seconds. Building proper identity infrastructure takes real engineering time.
Most teams don’t need all of this on day one. If you have one agent doing one thing, a dedicated service account with tight scopes is probably fine. The patterns here matter when agents multiply, when they share credentials, when they act autonomously, or when you can’t answer “what happened?” after an incident.
The tooling is young. Entra Agent ID is in preview. NIST standards are in progress. MCP authorization just shipped. You’ll be building some of this yourself for a while, and the patterns will change as the ecosystem matures.
But the gap between “agents have production access” and “agents have accountable identities” is where incidents live. That’s not a tooling problem. That’s a “we haven’t decided agents need real identities” problem.
The uncomfortable question
Everyone’s racing to give agents more tools. More tools, more access, more autonomy. That’s the fun part.
But tools without identity turn every agent into a shadow operator. It can act, but it can’t be cleanly named. It can fail, but it can’t be cleanly isolated. It can cause damage, but the logs blame whatever credential it borrowed.
Before an agent gets another tool, make sure you can name it, scope it, trace it, and kill it.
Common questions
What is an agent identity?
A unique identity for an AI agent so its actions, permissions, owner, and lifecycle can be managed separately from humans and service accounts.
Why shouldn't AI agents use human tokens?
Human tokens make agent actions look like user actions. That breaks attribution, least privilege, revocation, and incident response.
What should every production agent have?
A name, an owner, a purpose, scoped tools, allowed actions, expiry rules, clear audit logs, and a kill switch.
What is an agent access contract?
A structured boundary that defines who the agent is, what it can do, who owns it, and how to shut it down. Not a policy document. Enforceable configuration.