# Revoke AI Agent Access During a Live Task Safely

An active AI agent does not need malicious intent to create an incident. A bad instruction, an overbroad tool grant, a poisoned repository file, or a confused operator can send it into a destructive loop while it still has access. The response must stop new actions quickly without throwing away the record that explains what happened.

The usual bad response is to close the terminal, revoke every credential in sight, and reconstruct the event from memory the next morning. That creates a larger outage and often destroys the distinction between what the agent attempted, what a remote service accepted, and what actually changed. Treat an agent incident as a containment job with evidence handling, not an embarrassing interruption to hide.

## Revocation must stop future authority before it erases the scene

Revoking an agent means preventing it from making its next privileged action, while preserving enough state to determine whether earlier actions succeeded. Killing a visible chat or terminal window may satisfy neither requirement. The process can have children, the agent can have an open remote connection, and an HTTP request can be running after the local process has disappeared.

Separate these four things before touching controls:

- The agent process is the local program generating decisions and tool calls.
- The session is the authority granted to that particular process run.
- The credential is the secret or identity an external system accepts.
- The remote operation is work already accepted by an API, queue, host, or cloud control plane.

People regularly blur session revocation and credential rotation. The consequence is painful. If you rotate a shared deployment token to stop one agent, you may break production automation while the agent's already accepted request keeps running anyway. If you only kill the agent process after it copied a token into a workspace, you may leave a reusable secret behind.

Containment should therefore follow the closest reliable control to the agent. Deny the active run first. Then halt or cancel work that has crossed into remote systems. Escalate to credential disablement when the evidence says the secret may no longer be confined, or when you cannot rely on the session boundary.

Write down one plain incident rule before anyone needs it: the person who sees suspicious behavior can stop the agent immediately, without waiting for a meeting. Ask for a review afterward. A delayed approval process is appropriate for a deployment, not for withdrawing authority from a live process.

## Build an action map before the first incident

You cannot revoke what you cannot identify. Each agent run needs an identifier that appears in its local process record, its tool logs, and the requests that reach remote systems. A random run ID is enough if you pass it consistently. Do not use a human name or a vague label such as `coding-agent`; both collapse unrelated activity into the same bucket.

For each route through which an agent can act, record the answers to five operational questions:

1. Which local process owns the route, and how do we stop it?
2. Which session or token represents that process to the action gateway?
3. Which remote operations can remain active after local revocation?
4. Where do independent service logs record those operations?
5. Who can disable the route when the normal owner is unavailable?

This is not paperwork for its own sake. During an incident, an operator should not need to discover whether a database migration runs through a shell child, a CI job, an HTTP request, or a separate cloud workflow.

Use a run ID as a request header wherever an API permits it. For an agent with run ID `run_2025_04_18_7f3c`, a wrapper can add a correlation header without placing a secret in the agent's prompt or environment:

```sh
export AGENT_RUN_ID="run_2025_04_18_7f3c"
curl -sS -X POST "$ACTION_ENDPOINT" \
  -H "X-Agent-Run-ID: $AGENT_RUN_ID" \
  -H "Content-Type: application/json" \
  --data @request.json
```

The receiving service should log the run ID alongside its normal request ID, caller identity, endpoint, response status, and time. A useful record has a shape like this:

```text
time=2025-04-18T14:12:09Z request_id=req_91a run_id=run_2025_04_18_7f3c caller=agent-gateway method=POST path=/deployments status=202
```

A `202` matters. It says the service accepted work, not that work finished. This is where incident reviews often go wrong: teams call the agent's last tool output the outcome, although the remote system had only acknowledged a queue submission.

For SSH, map the remote account, target hosts, forced commands if any, and the place that records login and command activity. A local terminal transcript is useful, but it is not proof that a command did not run remotely. The host's own logs and the relevant service audit trail decide that question.

## Stop the active run in an order that preserves control

Start by recording the time and the immediate reason for revocation, then deny new actions and terminate the agent. The exact commands vary by operating system and runtime, but the sequence should not vary because it separates containment from cleanup.

1. Record the run ID, local process ID, operator, observed behavior, and current time in the incident record. Take a copy of the agent's current transcript and the last visible tool call before closing its interface.
2. Revoke or lock the active session at the gateway that authorizes actions. Confirm that a new test call from that same process receives a denial, if a safe read only operation exists.
3. Suspend the local process before killing it when your operating system permits it. Suspension gives you a stable process tree and open file list. Kill it only after you capture that state, unless continued execution would cause immediate harm.
4. Find and stop child processes, background jobs, containers, and remote sessions connected to that run.
5. Cancel accepted remote work using the service's own cancellation mechanism, then preserve the response and status.

On macOS or Linux, begin with an inspection rather than a blind `kill -9`. Replace the example process ID with the one you recorded:

```sh
ps -o pid,ppid,pgid,lstart,command -p 48192
pgrep -P 48192 -a
lsof -nP -p 48192
kill -STOP 48192
```

The first command records parentage and start time. `pgrep` exposes direct children, and `lsof` often shows open workspace files, sockets, and pipes worth preserving. `kill -STOP` freezes a cooperative process without giving it another chance to issue a cleanup command. It does not freeze an already detached child, a remote job, or an API request that has crossed the network boundary.

After copying the outputs into the incident folder, enumerate the process group. A process can launch a child that changes its process group, so do not stop at a single command. Inspect container runtimes and background job managers where your agent can use them. If the agent has SSH access, inspect active sessions on each target host as well.

When the task performs remote work, use the remote system's operation ID. For example, an API may return this when accepting a request:

```json
{
  "operation_id": "op_4e2b7c",
  "status": "queued"
}
```

Store that response, then call the documented cancellation endpoint or use the service console under human control. Record the cancellation result. A response of `cancel_requested` means you still need to poll the operation until it reports `cancelled`, `completed`, or another terminal state. Do not write "stopped" in the incident notes because the local process vanished.

## Preserve evidence before resetting the workspace

Capture evidence in a separate incident directory before deleting branches, restarting services, or running an automatic cleanup script. You need a time ordered record that another developer can inspect without depending on the operator's recollection.

Collect the following material and preserve original timestamps where possible:

- The agent transcript, tool inputs, tool outputs, and configuration used for the run.
- Process inspection output, parent and child process IDs, open connections, and shell history relevant to the run.
- Gateway session records and action logs, including denials after revocation.
- Remote service audit events, operation IDs, cancellation results, and changed resource identifiers.
- The repository state: current commit, diff, untracked files, and any generated artifacts.

Hash the files after collection. A simple manifest gives later reviewers a way to detect accidental modification while copies move between the on call engineer, security staff, and the developer who owns the affected system:

```sh
mkdir -p incident-run_2025_04_18/evidence
cp agent-transcript.txt incident-run_2025_04_18/evidence/
ps -o pid,ppid,pgid,lstart,command -p 48192 > incident-run_2025_04_18/evidence/process.txt
shasum -a 256 incident-run_2025_04_18/evidence/* > incident-run_2025_04_18/SHA256SUMS.txt
```

The output manifest should look like this:

```text
8f7c...  incident-run_2025_04_18/evidence/agent-transcript.txt
30b1...  incident-run_2025_04_18/evidence/process.txt
```

A hash does not make a file truthful. It proves that a reviewer received the same file you hashed. Cross check it against logs held by systems the agent could not edit, such as an API provider's audit trail or an append only central logging service.

NIST's Computer Security Incident Handling Guide, SP 800-61, treats containment, eradication, recovery, and post incident work as distinct activities. That separation fits agent incidents well. Teams often jump straight to eradication by deleting the working directory or rotating a token. They then discover that the deleted transcript contained the exact request body needed to find a remote resource.

Do not copy secrets into the incident folder merely because you are preserving context. Capture credential identifiers, ownership, scope, creation time, and last use records. Store actual secret values only if your existing incident process explicitly permits it and can protect them. An incident archive should reduce uncertainty, not create a second secret spill.

## A dead parent process does not prove the work stopped

Assume an active agent can leave work behind until you establish otherwise. The most troublesome cases are not dramatic shell commands. They are ordinary asynchronous actions that a developer would barely notice during normal work.

Consider a coding agent that posts a deployment request, starts an SSH command that launches a background migration, and then waits for tests. The operator sees an unexpected production target and stops the parent agent. The deployment service already accepted the request, while the remote shell has started a command under `nohup`. Both continue. The terminal's final line may say only that its connection closed.

The review needs three different checks:

### Inspect work accepted by APIs

Search the affected service with the run ID, request ID, account identity, and time window. Determine whether each request was rejected, queued, running, completed, or cancelled. For completed changes, list the concrete resource IDs and compare the resulting state with the requested state.

Do not rely on HTTP status alone. A `200` can describe a synchronous change, a status document, or a response from an intermediary. A `202` normally indicates accepted processing, but the service documentation defines the final meaning. Read that documentation before writing a cancellation playbook for the service.

### Inspect work detached from the agent

On target systems, check the remote account's sessions, process tree, scheduled jobs, temporary directories, and service logs. Search for the recorded command line, working directory, run ID, or a unique generated file. If a remote task uses a job scheduler, cancel it through that scheduler rather than killing a shell that may no longer own it.

Also check callbacks. A generated script may have configured a webhook, created a pull request workflow, or triggered CI. Those are separate actors with their own credentials and schedules. Revocation of the original agent does not revoke them.

This is why a narrow action gateway is safer than handing an agent a general shell with a broad environment. You can enumerate a bounded number of channels and require every privileged call to cross a control point. A shell full of inherited credentials turns every subprocess into a separate incident branch.

## Rotate credentials only when the exposure warrants it

Rotate a credential when you have reason to believe the agent, its subprocesses, its logs, or its workspace could have retained the secret. Do not rotate merely to create the appearance of a response. Wide rotation breaks legitimate users and can make a review harder if it changes the records you still need to inspect.

These conditions justify immediate disablement or rotation:

- The agent received a plaintext secret in a prompt, environment variable, config file, command line, or tool output.
- A credential appeared in a transcript, repository diff, temporary file, or CI log with access beyond the incident team.
- You cannot account for a child process, remote session, or outbound connection that could have read the secret.
- The credential carries broad privileges and lacks reliable per use logs.
- The affected provider tells you the credential was used from an unexplained identity or location.

If a gateway injected the credential and returned only the action result to the agent, the situation differs sharply. The agent might have performed an unauthorized action, but it did not necessarily possess a reusable secret. Disable the active session and the affected action route, examine the audit record, and rotate the underlying credential if the review finds a route around that boundary or a provider level concern.

Avoid the recommendation to rotate every secret after every agent mistake. It is popular because it feels decisive and because leaked credentials have serious consequences. It is wrong as a default because it confuses unauthorized use with credential disclosure, creates avoidable production failures, and teaches teams to skip careful scoping. Rotate aggressively when disclosure is plausible. Otherwise, preserve the ability to distinguish the compromised run from everyone else.

When rotation is required, document the old credential identifier, the disable time, downstream systems that use it, the replacement owner, and a test that proves the old credential no longer works. Do not place either value in a ticket or transcript. A secret manager or the provider's protected rotation mechanism should handle the replacement.

## The incident record must support a skeptical review

An incident review should allow a developer who was not on call to rebuild the sequence without trusting a single mutable log. Start with the agent's intent and local process record, then compare that story with gateway records and remote service evidence.

Make a timeline with explicit confidence labels. For example, "agent proposed request" comes from a transcript. "gateway executed request" comes from the gateway action record. "provider accepted operation" comes from the provider audit entry. "resource changed" comes from the resource's final state and change history. Those are different claims, and they deserve different evidence.

A write blind, hash chained audit log has a useful property here: the component that executes actions cannot silently rewrite its own history after the fact. Verification over ciphertext also lets a reviewer check continuity without gaining access to every secret or action payload. That does not make the log complete. It still records only activity that crossed the gateway, which is why remote service logs remain part of the review.

Sallyport records agent sessions and individual actions from one encrypted, hash chained audit log, and `sp audit verify` checks the chain offline without a vault key. That gives an incident reviewer a clean test to run on an exported log copy:

```sh
sp audit verify /path/to/exported-audit-log
```

A successful verification establishes continuity of the encrypted record you received. A failed verification should halt casual cleanup and trigger evidence handling, because you must determine whether export damage, storage corruption, or deliberate alteration caused the break.

The review should produce answers, not a vague list of observations. Identify the triggering instruction or input, the authority granted to the run, every confirmed external action, every action still uncertain, credentials that may have escaped, and the control change that would have stopped the event earlier. If the team cannot name the first control that failed, it will likely add a noisy approval prompt instead of fixing the exposed route.

## Resume development with a fresh boundary, not a reopened session

Developers can continue work after containment, but they should not resume through the same process, workspace state, or authority grant. The interrupted run may hold unreviewed instructions in memory, stale task context, generated scripts, or a child process that the first response missed.

Create a new run with a new session identity. Review the repository diff and generated files before exposing the new run to credentials or production targets. If the earlier task needs to continue, give the new run a short written handoff that states which remote actions completed, which remain cancelled, and which resources require inspection.

Use a narrower permission set for the resumed task. A code review task rarely needs deployment authority. A task that must query production usually does not need write access. This is not about forcing every developer into a complex policy language. It is about refusing to carry yesterday's broad grant into a run that starts after an incident.

Per session authorization is especially useful when a new local process starts after a stop event, because it forces a human to recognize that this is a different run. Per call approval fits actions where the cost of a mistaken write is high enough to justify interruption. If an approval card fails to identify the calling process and the specific action, fix that before trusting it during an incident.

The first drill should take fifteen minutes: start a harmless agent task, revoke its session during an API call, preserve the local and remote records, and confirm the task cannot resume under its old authority. Run the drill against a disposable target. You will find missing request IDs, detached children, and log access problems there, when the cost is low, rather than during a real production mistake.

## Make revocation a normal operator action

A team that treats revocation as a rare emergency will hesitate when an agent behaves oddly. The controls should make the safe decision quick: lock the action boundary, revoke the session, inspect what has already crossed it, and leave a record that survives the cleanup.

The strongest design choice is simple separation. Agents can plan and request actions. A local control point holds credentials, identifies the process that asks, records the request, and can deny that process without handing it the secret. When the operator presses stop, the next privileged call must fail, and the earlier calls must remain reviewable.

Test that claim with the actual tools your agents use. If the team cannot stop one live run without rotating a shared credential, cannot correlate a remote operation to that run, or cannot verify its action history after the fact, the incident workflow is unfinished.
