How to Instantly Revokean AI Agent's Access
AI agents are powerful because they act on their own: they call APIs, run tools, and touch data. That is also the risk. If an agent is steered by hidden instructions in the content it reads, it may use its access in ways you never intended. You cannot always stop the first bad action, but you can make sure you can cut the agent off in seconds. That kill switch is what this guide builds. It pairs with our guides on excessive agency and insecure output handling.
Why Does an AI Agent Need a Kill Switch?
A normal user acts slowly and predictably. An agent can make hundreds of calls a minute, and it can be manipulated through prompt injection. If an attacker hides an instruction in a web page or a document the agent reads, the agent may follow it and start calling tools with your permissions. When that happens, the only thing that limits the damage is how quickly you can revoke access. A long lived API key cannot be cancelled fast. A short lived, revocable token can.
Step 1: Give the Agent a Short-Lived Token
Instead of a static API key, issue the agent an access token that expires quickly and that you can revoke. Install the library first:
npm install @restingowlorg/owltokenguard
import { createTokenManager } from "@restingowlorg/owltokenguard";
const agentTokens = createTokenManager({
algorithm: "HS256",
hmacSecret: process.env.JWT_SECRET,
audience: "agent-tools",
expiresInSeconds: 300, // 5 minutes: a short life limits the damage
onSessionTerminate: async ({ jti }) => {
// the kill switch: drop the session so verify() rejects it next time
await revokedStore.add(jti);
},
});
// Issue a token the agent uses to call your tools
const issued = await agentTokens.generateAccessToken({
sub: "agent-42",
role: "tool-caller",
});
// issued.token -> hand this to the agent
// issued.claims.jti -> store this so you can revoke the session later
The short expiry matters. Even if you never press the kill switch, a stolen or misused token stops working within minutes. The onSessionTerminate hook is where you plug in your own store, such as a database or cache, that your app checks during verification.
Step 2: Verify the Token on Every Tool Call
The agent should present its token every time it asks to run a tool, and your code should verify it every time. Verification fails automatically once the token expires or is revoked.
import { TokenVerificationError } from "@restingowlorg/owltokenguard";
async function runTool(token, tool) {
try {
const auth = await agentTokens.verify(token, {
purpose: "access",
audience: "agent-tools",
});
return tool(auth.payload.sub);
} catch (error) {
if (error instanceof TokenVerificationError) {
throw new Error("agent access is revoked or invalid");
}
throw error;
}
}
If you run tools behind Express or Fastify, the library ships middleware (expressVerifyToken and fastifyVerifyToken) that does this check for you and puts the verified details on the request.
Step 3: Revoke Access the Moment Something Looks Wrong
This is the kill switch. When your monitoring, a human reviewer, or a guardrail spots trouble, you can cut the agent off in three ways.
| You want to | How | Use when |
|---|---|---|
| Stop one agent session | terminate({ jti }) | One agent is acting up and you know its session id |
| Cancel a refresh token | revokeToken(refreshToken, { purpose: "refresh" }) | You want to end an agent's ability to renew access |
| Stop everything at once | terminate(claims, { sub, invalidateBefore }) | A wider incident: kill every token issued before now |
// One session: cut off this agent right now
await agentTokens.terminate({ jti: agentJti });
// A refresh token: stop it renewing access
await agentTokens.revokeToken(agentRefreshToken, { purpose: "refresh" });
// Whole fleet: invalidate everything issued before this moment
await agentTokens.terminate(claims, {
sub: "agent-42",
invalidateBefore: Math.floor(Date.now() / 1000),
});
Because you verify on every call, the very next tool request the agent makes after you revoke will fail. Combined with the short expiry from step one, the window an attacker has is tiny.
How Does This Fit With Least Privilege?
Revoking access is the response side. The prevention side is giving the agent as little power as possible in the first place, so even a working token can do little harm. The two work together: scope the token tightly, then keep the ability to cancel it. For the prevention side, see least privilege for AI agents.
AI Agent Kill Switch Checklist
- 1Give agents short-lived tokens, not static API keys.
- 2Verify the token on every single tool call, and fail shut if it is invalid.
- 3Store each session id (jti) so you can revoke a single agent fast.
- 4Wire onSessionTerminate to your own revocation store.
- 5Have a one command way to invalidate every token before a cutoff for wider incidents.
- 6Log every tool call with the agent id and session id so you can spot abuse.
- 7Combine this with tight scoping so a live token can do little on its own.
This maps to OWASP LLM06, Excessive Agency, which recommends limiting an agent's permissions and keeping tight control over what it can do. A fast, reliable revocation path is a core part of that control.
npm install @restingowlorg/owltokenguard and wire the kill switch above. Then read least privilege for AI agents and excessive agency for the full picture.