OAuth scopes and IAM roles tell you which services an agent can reach. They say nothing about what it does once it gets there — and that gap is where every agent incident actually lives.
Once agents act autonomously, you need answers to three questions: is this allowed, which agent did it, and can you prove what happened. Here's why access control alone can't answer any of them.
The three questions every autonomous AI agent must answer
send_email and query_database can still be one bad prompt away from drop_table.Keep reading for the full breakdown →
Your AI agents call tools, browse the web, query databases, and delegate to other agents. Once deployed, they make decisions autonomously — nobody is reviewing every tool call before it fires. An agent with access to send_email and query_database should never be able to reach drop_table. But in most production systems today, nothing actually stops it. The IAM role that got the agent into the database says nothing about what it's allowed to do once it's in.
That gap doesn't stay theoretical for long. It shows up the first time an agent does something nobody explicitly authorized, and the team discovers that "which agent did this?" has no good answer because five agents share one service account. It shows up again when an auditor asks for the record of what happened and gets a log line instead of proof. Neither is an acceptable answer once agents are making real decisions against real systems.
This piece breaks down each of the three questions, why the access-control layer you already have doesn't answer any of them, and what a real answer looks like — architecturally, not just as a policy document.
Reachability — what a credential lets you connect to (a database, an inbox, an API). Permission — what you're allowed to do once connected. OAuth scopes and IAM roles answer the first question. They were never designed to answer the second.
An IAM role that grants database access answers "can this identity open a connection to this database?" It does not answer "should this specific query run?" OAuth scopes answer "can this token call the Gmail API?" They don't answer "should this specific email go to this specific recipient with this specific attachment?" Every access-control system enterprises already run was built for human-scale decisions, where a person requests access once and then makes judgment calls thousands of times over the life of that access. Agents invert that: the access is requested once, and then an autonomous process makes the judgment call every single time, at machine speed, with no human in the loop to catch the bad one.
That's the structural reason "give the agent narrow scopes" isn't a complete answer. Narrow scopes shrink the blast radius of a compromised credential. They do nothing to stop an agent from misusing a capability it was legitimately granted — sending the right kind of email to the wrong person, running the right kind of query with the wrong parameters, or invoking a destructive operation because a prompt injection told it to.
OAuth and IAM draw a boundary around which services an agent can reach. The decisions that actually cause incidents happen entirely inside that boundary, where nothing is watching.
Every agent security incident you've read about didn't happen because a credential leaked out of its scope. It happened because the scope was legitimate and the action inside it wasn't.
Strip away the tooling and the vendor pitches, and every agent governance conversation reduces to three questions. Answer all three and you have a governed system. Answer one or two and you have a gap that will eventually become an incident.
An agent with access to send_email and query_database should not be able to call drop_table. That's not an access problem — the agent already has a valid database connection. It's a policy problem: does this specific action, with these specific parameters, in this specific context, match what the agent is actually supposed to do? OAuth scopes and IAM roles were never built to answer that; they answer whether the agent can reach the service, not what it does once it's there.
If your only defense against a destructive action is "the agent wasn't prompted to do that," you don't have a policy layer — you have an assumption about model behavior. Assumptions don't hold up under prompt injection or a bad tool description.
In a multi-agent system, five agents might share a single API key or service account because provisioning five separate credentials felt like unnecessary overhead. It works fine until something goes wrong — and then "an agent did it" is the entire incident report. Nobody can say which agent, under which task, with which upstream instruction, made the call that caused the problem. Without per-agent identity, attribution is a guess, not a fact.
Auditors and regulators don't want your word for it. They want tamper-evident records: what policy was active at the moment of the decision, exactly what the agent requested, and why it was allowed or denied. A log line that says "email sent" isn't that record. A signed, immutable entry that ties the action to a policy version, an agent identity, and a decision rationale is.
A governed agent request doesn't just check reachability once at connection time. It re-answers all three questions at the moment of execution — every time, not just the first time.
These aren't competing layers — they're stacked. Access control still matters. It just isn't sufficient on its own, and treating it as the whole answer is where the gap comes from.
| Question | OAuth / IAM | What actually answers it |
|---|---|---|
| Can the agent reach this service? | Yes — this is what it's designed for | Same — no change needed here |
| Is this specific action allowed? | No signal at all | Action-level policy engine evaluated per call |
| Which agent made this call? | Only if each agent has its own credential — most don't | Per-agent identity, independent of shared service keys |
| Was the decision rationale recorded? | No | Signed record of policy version, request, and outcome |
| Can the record be altered after the fact? | Standard logs usually can be | Tamper-evident, append-only audit trail |
| Recommendation | Keep OAuth/IAM for reachability. Add a policy + identity + audit layer above it for everything that happens after the connection opens. | |
The three questions map cleanly onto three layers of agent governance — pre-production certification, execution-time enforcement, and post-hoc audit. Solving one without the others leaves a real gap: certifying an agent's behavior without enforcing it at runtime just documents good intentions; enforcing policy without an audit trail leaves you unable to prove any of it happened.
AgentTrust OS builds all three layers so the same governance runs whether the agent is calling send_email, delegating to a sub-agent, or reaching for something it was never supposed to touch:
Before an agent reaches production, Trust Certify defines and tests its action contract — the explicit boundary of what it's allowed to do, not just which services it can reach. This is where "should this agent ever be able to call drop_table?" gets answered once, deliberately, instead of being left to whatever the model decides to do under a bad prompt.
At execution time, Trust Runtime validates every tool call against that contract and ties it to a specific agent identity — not a shared service key. Five agents behind one API key become five distinct, individually attributable identities the moment Trust Runtime is in the loop, and every call is checked against policy before it executes, not after.
Every decision — allowed or denied — is written to a tamper-evident record: which policy version was active, exactly what the agent requested, which identity made the request, and why it was allowed or denied. That's the record an auditor or regulator actually needs, generated automatically instead of reconstructed after an incident.
A system prompt is an instruction, not a boundary. It shapes behavior under normal conditions but doesn't survive prompt injection, adversarial tool outputs, or a model simply making the wrong call under ambiguity. Policy enforcement has to sit outside the model's reasoning, checking the actual action against actual rules — not hoping the model remembers what it was told.
Scoped IAM roles are necessary and should stay. But they only answer "can this agent reach this service" — they say nothing about which specific action, with which specific parameters, is appropriate once the connection is open. An agent scoped only to safe operations can still misuse them; the scope narrows the blast radius, it doesn't eliminate the need for action-level policy.
Verbose logs record that something happened. A tamper-evident audit trail proves it happened exactly that way and hasn't been altered since — typically through append-only storage and cryptographic signing. It also captures the governance context a log line usually doesn't: which policy version was active and why the decision went the way it did, not just the raw event.
The number of agents matters less than what they're allowed to touch. Two agents with write access to production data or the ability to send external communications need the same three answers as fifty. Start with per-agent identity and an action contract for your highest-risk tools — that's a small lift with immediate payoff, and it scales with you as the agent count grows.
There's a real cost — an execution-time check adds latency that a pure passthrough doesn't have. We won't pretend otherwise. In practice it's a small fraction of the round-trip time of the tool call itself, and it's the cost of being able to say, with evidence, that nothing executed without a policy check behind it.
Start by listing every destructive or irreversible action your agents can currently reach — deletes, sends, financial transactions, schema changes — regardless of how unlikely you think an agent is to trigger them. That list becomes your first action contract. Attribution and audit trail come next, once you know exactly what you're protecting against.