MAQPNADocs

Runbook: kill switch

Stop an agent, session, user or token across the installation now with maqpna kill, make the revocation durable, confirm it is enforced on every replica and lift it afterwards.

Use this runbook to stop an agent, a session, a user's sessions or a token now: suspected misuse, a runaway loop, a leaked token, or a policy gap that is being exploited. A kill creates a revocation at the gateway. The next call from the revoked principal is denied with reason revoked (JSON-RPC error -32001), within about a second.

The task-by-task guide with example output is Kill switch and revocations. This page is the on-call version.

Symptoms#

  • An agent calls tools in a loop, or spends faster than expected (MaqpnaBudgetExceeded, cost spikes in maqpna top agents).
  • An agent does something harmful or unexpected, or you suspect a compromise.
  • A session token or a user's account is known to be leaked.

Impact#

While the incident runs, the agent can make every call its policy allows. After the kill, the matching principal can make no tool or model call. Other agents are not affected unless you widen the scope (--all).

Detection#

Signal Command or alert
Who is calling most right now maqpna top agents and maqpna top sessions
What one agent did maqpna audit tail --gateway "$GW" -n "$NS" --agent "$AGENT" --since 1h
A replica enforces an old revocation list MaqpnaRevocationLag
A replica cannot read the list and denies every call MaqpnaRevocationListUnavailable

GW is the gateway URL (with adminListen, the admin port). You need the killswitch or admin role: sign in with maqpna login, or pass --oidc-token-file (the break-glass --token also works where it is enabled).

export GW=https://gateway-admin.example.internal NS=team-a AGENT=coder INC=INC-123

Decide#

Pick the narrowest scope that stops the harm:

Situation Scope
One session misbehaves --session S
Every session of one agent --agent A (with -n NS)
A user's sessions (account takeover) --user U
A leaked token --jti J
Everything in a namespace -n NS --all

And the action:

Action Flag Effect
Block none (default) Every matching call is denied; sessions keep running.
Suspend --suspend Also suspends the matching sessions.
Terminate --terminate Also ends them (sandbox and token deleted) and, for users, revokes their connected accounts at the providers.
Quarantine --quarantine Suspends without deleting anything (snapshot kept for forensics), fences the network, revokes tokens and connected accounts, and records a signed incident.
flowchart TD
  A[Stop it now] --> B{"Gateway reachable?"}
  B -->|yes| C["maqpna kill --gateway<br/>(effective in about 1 s)"]
  B -->|no| D["maqpna kill --emit-yaml<br/>| kubectl apply"]
  C --> E{"More than one gateway replica,<br/>or need a durable record?"}
  E -->|yes| D
  E -->|no| F[Verify]
  D --> F
  F --> G{"Compromise suspected?"}
  G -->|yes| H["Compromised-agent runbook"]
  G -->|no| I["Fix cause, then lift"]

Respond#

Step 1: Revoke at the gateway#

maqpna kill --gateway "$GW" -n "$NS" --agent "$AGENT" --reason "$INC data exfiltration" --terminate --yes

The reason is required; it is written to the audit ledger and the session events. Add --ttl 2h for a revocation that expires by itself. The replica that answers enforces it on the next call.

Step 2: Make it durable and cluster-wide#

An AgentRevocation reaches every replica through configSync and survives restarts and database restores. It is required with several replicas on the file state backend, where each replica has its own break-glass list. With state.backend: postgres, step 1 already reaches every replica; apply it anyway as the record that survives a restore.

maqpna kill -n "$NS" --agent "$AGENT" --reason "$INC" --terminate --emit-yaml | kubectl apply -f -

--emit-yaml creates nothing at the gateway; it only prints the manifest. Use it alone when the gateway is unreachable (for example during a PostgreSQL outage): it goes through Kubernetes.

Step 3: Revoke delegated access (user incidents)#

--terminate with --user revokes the user's connected accounts. To revoke one account explicitly:

maqpna accounts list --gateway "$GW" --user <user>
maqpna accounts revoke <user> <provider> --gateway "$GW" --yes

Step 4: Hand over#

If the cause may be a compromise, continue with the compromised agent runbook before you lift anything. Pending approvals of the revoked agent are moot; approvers can deny them:

maqpna approvals list --gateway "$GW" -n "$NS"

Step 5: Lift the revocation#

When the cause is fixed, lift the revocation from both places:

maqpna revocations list --gateway "$GW"
maqpna revocations delete --gateway "$GW" breakglass/<id> --yes
kubectl -n maqpna-system delete agentrevocation <name>

maqpna kill --gateway "$GW" -n "$NS" --agent "$AGENT" --release --yes lifts the break-glass revocations an earlier kill of the same target created (and their mirrored AgentRevocations); for a quarantine add --quarantine. Suspended sessions stay suspended until you resume them with maqpna session resume.

Verify#

maqpna revocations list --gateway "$GW"                                  # the entry is listed, with its expiry
maqpna audit tail --gateway "$GW" -n "$NS" --agent "$AGENT" --decision deny --since 10m
  • New calls from the principal are denied with reason revoked.
  • The audit ledger has a revocation.create record with the reason and who made it, and a revocation.delete record when you lift it.
  • MaqpnaRevocationLag is not firing: every replica has the current list. With Prometheus, maqpna_gateway_revocation_propagation_max_seconds shows how long enforcement took per replica.

Troubleshooting#

Symptom Cause Fix
confirmation required, exit 2 No terminal and no --yes Add --yes.
HTTP 403 No killswitch or admin role maqpna whoami; map your group to killswitch in adminAuth.roles.
Calls still allowed on another replica file state backend: break-glass entries are per replica Apply the --emit-yaml manifest (step 2).
Every call denied with revocation_list_unavailable A replica cannot read the revocation list and fails closed Check the maqpna-revocations ConfigMap and the operator's agentrevocation controller.
MaqpnaRevocationLag fires configSync of that replica is behind Check maqpna_gateway_configsync_errors_total and the gateway's Role.

Follow-up#

  • Record the scope, the reason, the time of the kill and the time of the lift in the incident record; the audit ledger has the same facts with who made them.
  • If the cause was a policy gap, add a rule and a policy test.
  • Rehearse the kill switch regularly with a test session and --ttl 5m (Production checklist).

Next steps#