
PRODUCTION
Why AI Agents Need Permissioning, Audit Logs, and Revocation
The three controls that separate AI agent demos from AI agent deployments: per-action permissioning, immutable audit logs, and immediate revocation. Why each is non-negotiable.
TL;DR
"Revocation" usually promises more than most systems actually deliver, and the gap is exactly where a disconnected integration keeps working anyway. Clicking disconnect clears whatever copy of a credential the platform itself is holding. It does not, by itself, reach into the provider and invalidate the token at the source.
The common assumption is that revocation is revocation: click the button, and every copy of the credential stops working immediately. That holds for a login session tied to SSO, which a provider like Okta can kill on request. It does not hold for an OAuth token handed to something outside the platform's own vault, because only the issuing provider can actually invalidate it.
This isn't an argument against building permissioning, audit logs, and revocation into an agent stack. It's an argument for building each one honestly, scoped to what it can actually reach, instead of describing it the way a slide describes a kill switch.
Before trusting any vendor's revocation claim, ask one specific question: does disconnecting clear the vendor's own copy of the credential, or does it also reach the provider and kill the token at the source? Those are different guarantees, and most teams have never been told which one they're getting.
Overview
Three controls tend to come up whenever an AI agent stack heads toward production: permissioning, audit logging, and revocation. Security review asks about all three, usually in that order, and a team with good answers clears the process faster than one that doesn't.
The trouble is what "good answers" tends to mean in practice. Permissioning gets described in terms of policy, which sounds more sophisticated than what's usually running underneath: a scope check against a role, evaluated per call. Audit gets described as a complete forensic record, true for the decisions a gate actually makes and not true for things nobody built the gate to record, like whether a human approved something that was never routed for approval in the first place. Revocation gets described as a kill switch, and that's the term that causes the most trouble, because a kill switch implies total control over something a lot of platforms only partially control.
We don't think any of the three is wrong to want. What's wrong is describing any of them with more authority than the system actually has. A security team that believes revocation is total makes different decisions than one that knows it's partial, and only one of those teams is deciding based on what's actually true.
The distinction worth holding onto: a control that's honest about its own boundary is safer to build a security posture around than one that oversells what it does. The gap between those two doesn't show up until an incident, which is exactly the wrong time to discover it.
Permissioning: per-action authorization
Most agents still run on standing access: a service-account token with broad OAuth scopes, usable for anything that token happens to allow, at any time, for any reason. That's the setup behind most of the headlines about an agent touching data or taking an action nobody sanctioned. Nobody had to attack anything. The credential was just wider than the task.
Real permissioning replaces standing access with a check made at the moment of the call: does this identity have this scope on this resource. Not a one-time grant evaluated at session start, and not a broad yes covering everything the underlying API happens to support, a lookup evaluated against the specific action being attempted, every time. The useful version of this is default-deny: nothing is reachable until a scope explicitly says otherwise, checked at the org, team, and individual level, so a broad grant at the top of an org doesn't silently become a broad grant for every member underneath it.
The check has exactly two honest outcomes: allow or deny. A system that also returns "hold for a human to approve" is describing a workflow it would need to build separately: routing, notification, an actual person who reviews and clicks something. That workflow doesn't exist just because the words are in a diagram. If a stack doesn't have that machinery, the check should say deny and stop implying a third option is available.
We think permissioning is not a policy question. It's a lookup. "Is this allowed" should resolve against a scope table, not against a paragraph of intent that gets interpreted at run time.
Audit logs: the forensic record
Audit logs get asked to answer a fixed set of questions after something goes wrong: which agent did this, on whose behalf, what did it touch, and when. A useful log answers all four for any action, not just the ones important enough that someone remembered to instrument by hand.
What a well-built audit trail actually captures is the gate's own decision: the scope that was checked, the action that was attempted, and the verdict, on every outcome, not just the ones that succeeded. A denied call belongs in the record exactly as much as an allowed one, and so does a call that never resolved because something timed out. That's a meaningfully different thing from a record of everything an agent might have wanted to do, and it's different again from a record of who approved what, because a gate that only ever returns allow or deny was never built to track approval in the first place. If a claimed audit trail includes an approval column, ask what process actually populates it.
A useful test: pick one action from yesterday and try to reconstruct it from the log alone. Which identity made the call, what scope was checked, what the gate decided, and what happened next. If that reconstruction takes longer than a minute, or depends on a system that isn't the audit log itself, the pipeline isn't doing its job yet.
Revocation: the actual boundary
Revocation is what a team reaches for once something has already gone wrong: an employee leaves, a credential leaks, an agent does something it shouldn't have. The instinct is to want one button that makes the problem stop being true everywhere, instantly. What that button actually does depends entirely on what kind of credential is being revoked, and conflating the two kinds is where most of the false confidence comes from.
A login session is the case where a hard revocation is real. Okta and other OIDC providers can kill an active SSO session the moment an administrator asks, and every system relying on that session loses access immediately, because the session's validity was always the provider's call to make.
A connected tool's OAuth token is a different animal. Disconnecting it inside a platform clears that platform's own stored copy: the vault entry is deleted, and any call routed through that platform's credential injection stops working right away, because there's nothing left to inject. What disconnecting does not do, on its own, is reach into the provider and invalidate the token at the source. A token issued earlier keeps whatever validity the provider gave it until it expires or someone revokes it directly with the provider — and in a setup where a raw token was ever handed out rather than injected server-side, a copy of it could keep working entirely outside the platform that believes it just revoked access.
Figure 1 — Disconnecting inside a platform clears that platform's own copy of a credential. It does not, by itself, reach the provider that actually issued the token.
This isn't a defect specific to one product. It's a property of OAuth: the party that issued a token is the only party with the authority to kill it outside its natural expiry, and most platforms sit downstream of that authority rather than inside it.
What "revoked" should mean, precisely: cleared from this platform's vault, immediately. Not: invalidated everywhere the token was ever used. Only the issuing provider can promise the second one, and most platforms cannot speak for the provider.
How They Work Together
Permissioning, audit, and revocation are one system looked at from three angles, not three separate features to check off. Permissioning decides what's allowed to happen. Audit records what the gate actually decided, call by call. Revocation removes an identity's ability to pass that gate going forward, within whatever boundary the revoking system actually controls.
Take any one away and the other two lose most of their value. A gate with no audit trail can't be checked against what it claims to enforce. An audit trail with no working revocation shows an incident after it's too late to stop it from continuing. And in our view, revocation without a real gate underneath it is a kill switch wired to a system nobody was actually controlling in the first place, since standing access was doing the real work the whole time.
Production Checklist
Before an agent stack goes to production, a team should be able to say yes to each of these, and mean the specific, narrower thing behind the words rather than the version that sounds better in a slide:
- Every agent is bound to a distinct identity, not a credential shared across every task it might run.
- Every tool call is checked against an explicit scope at the moment it's made, with a two-way outcome: allow or deny.
- Every check is logged with the identity, the scope evaluated, and the verdict, on success, failure, and timeout alike.
- Audit records are exportable to wherever the security team actually looks, not just visible inside the agent platform's own dashboard.
- Disconnecting a credential inside the platform stops new calls immediately, and the team knows whether that also reaches the provider or only clears the platform's own copy.
- A leaked credential's blast radius is known: how long it stays valid at the provider if disconnection doesn't reach that far, and what the actual path to killing it there looks like.
- The team can answer "what did this agent do last Tuesday" using the audit log alone, in under a minute.
Conclusion
None of these three controls needs to be exotic to be effective. What they need is a description that matches what they actually do: permissioning as a scope lookup with two honest outcomes, audit as a record of the gate's own decisions rather than a promise about approvals that were never built, and revocation scoped to exactly the boundary the revoking system controls, no further.
This is the model our own permission layer follows at Fabriq. Default-deny scopes get checked at call time across org, team, and individual grants, with the effective tool list set to whatever a user's and an agent's scopes actually intersect on. Credentials sit in a vault and get injected at the moment of the call rather than handed to the agent directly. Disconnecting a connection clears Fabriq's own stored copy of the credential immediately; it doesn't reach into the provider, which is the same honest boundary described above, not an exception to it. Audit records capture the scope check and the verdict for every call, filterable in the dashboard and exportable via API. SSO sessions through Okta or another OIDC provider revoke immediately, because that's the one part of this stack where the platform genuinely is the authority being revoked.
The question worth asking before any of this ships: if every claim were stripped out of the vendor pitch and only what the system provably does at the moment of the call was left, would permissioning, audit, and revocation still hold up? For most stacks the honest answer is mostly yes, with one boundary, usually revocation, that turns out narrower than the deck implied.