Observed since 20 Oct, 22:31 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Operational safety controls for autonomous AI agents - kill switch, heartbeat, circuit breaker
Your AI agents need an emergency stop button.
Operational safety controls for autonomous AI agents. Kill switch, heartbeat monitor, circuit breaker, and budget controls -- with zero required dependencies.
Autonomous AI agents are powerful, but they can go wrong. They can:
agent-killswitch gives you an infrastructure-level emergency stop that operates outside the agent's reasoning path. The agent cannot talk its way out of being killed.
| Scenario | Without | With agent-killswitch |
|---|---|---|
| Runaway agent burning $50/hr | Notice hours later in billing | Budget kill triggers at $50 limit |
| Agent making harmful API calls | Hope the LLM stops itself | KILL activates in <500ms |
| Agent crew member dies | Other agents wait forever | Heartbeat detects death, cascading kill cleans up |
| API provider goes down | Agents retry forever | Circuit breaker fails fast after 3 failures |
| Need to stop everything NOW | SSH into servers, kill processes | ks.activate(KillLevel.KILL, KillScope.GLOBAL) |
pip install agent-killswitch
Kill an agent in 3 lines:
from agent_killswitch import KillSwitch, KillLevel, KillScope
ks = KillSwitch()
ks.activate(KillLevel.KILL, KillScope.GLOBAL, reason="emergency shutdown")
Check before every agent action:
status = ks.check(scope_target="my-agent")
if status.is_killed:
print(f"KILLED: {status.level} - {status.reason}")
return # Stop immediately
+--------------------------------------------------+
| Your Application |
| |
| +----------+ +----------+ +----------+ |
| | Agent A | | Agent B | | Agent C | |
| +----+-----+ +----+-----+ +----+-----+ |
| | | | |
| +----v--------------v--------------v---------+ |
| | agent-killswitch | |
| | | |
| | +------------+ +----------+ +--------+ | |
| | | KillSwitch | | Heartbeat| | Circuit| | |
| | | PAUSE/STOP | | Monitor | | Breaker| | |
| | | /KILL | +----------+ +--------+ | |
| | +------------+ | |
| | +------------+ +----------+ | |
| | | Budget | | Cascading| | |
| | | Kill | | Terminate| | |
| | +------------+ +----------+ | |
| | | |
| | +---------+ (InMemory or Redis) | |
| | | Backend | | |
| | +---------+ | |
| +--------------------------------------------+ |
+--------------------------------------------------+
| Level | Behavior | Latency Guarantee |
|---|---|---|
| PAUSE | Stop new tasks, in-flight complete normally | <200ms |
| STOP | Checkpoint in-flight tasks, pause all activity | <300ms |
| KILL | Terminate everything immediately | <500ms |
from agent_killswitch import KillSwitch, KillLevel, KillScope
ks = KillSwitch()
# Scoped kills
ks.activate(KillLevel.PAUSE, KillScope.AGENT, scope_target="agent-1")
ks.activate(KillLevel.STOP, KillScope.CREW, scope_target="research-crew")
ks.activate(KillLevel.KILL, KillScope.GLOBAL, reason="everything must stop")
# Priority: GLOBAL > CREW > AGENT > TASK
status = ks.check(scope_target="agent-1", crew_id="research-crew")
from agent_killswitch import HeartbeatMonitor
monitor = HeartbeatMonitor(
interval_seconds=5.0,
miss_threshold=3,
on_dead=lambda agent_id: print(f"DEAD: {agent_id}"),
)
monitor.start("agent-1")
monitor.heartbeat("agent-1") # Call periodically
dead_agents = monitor.get_dead_agents()
from agent_killswitch import CircuitBreaker, CircuitBreakerOpen
breaker = CircuitBreaker(
name="openai-api",
failure_threshold=5,
recovery_timeout=30.0,
)
try:
result = breaker.call(call_openai_api, prompt)
except CircuitBreakerOpen:
result = use_fallback(prompt)
from agent_killswitch import BudgetKillTrigger, KillSwitch
ks = KillSwitch()
budget = BudgetKillTrigger(killswitch=ks, kill_on_exceed=True)
budget.set_budget("agent-1", limit=50.0) # $50 max
budget.track_cost("agent-1", 10.0) # Track each API call cost
# Auto-kills when budget exceeded
from agent_killswitch import KillSwitch, KillLevel
from agent_killswitch.core.cascading import CascadingTerminator
ks = KillSwitch()
cascade = CascadingTerminator(killswitch=ks)
ks.register_agent("supervisor")
ks.register_agent("worker-1", parent_id="supervisor")
ks.register_agent("worker-2", parent_id="supervisor")
# Kill supervisor -> workers cascade
cascade.cascade_kill("supervisor", KillLevel.KILL, reason="parent failed")
from agent_killswitch import killswitch_protected, with_heartbeat
from agent_killswitch.decorators import circuit_breaker
ks = KillSwitch()
monitor = HeartbeatMonitor()
@killswitch_protected(killswitch=ks, agent_id="my-agent")
async def my_agent_task(): ...
@with_heartbeat(monitor=monitor, agent_id="my-agent", interval=5.0)
async def long_running_agent(): ...
@circuit_breaker(name="openai", failure_threshold=5, recovery_timeout=30)
async def call_openai(prompt: str) -> str: ...
from agent_killswitch.integrations.langchain import KillSwitchCallbackHandler
handler = KillSwitchCallbackHandler(killswitch=ks, agent_id="my-agent")
llm = ChatOpenAI(callbacks=[handler])
from agent_killswitch.integrations.langgraph import KillSwitchNode
ks_node = KillSwitchNode(killswitch=ks, agent_id="graph-agent")
graph.add_node("check_kill", ks_node)
graph.add_conditional_edges(
"check_kill",
ks_node.should_continue,
{
"continue": "agent_work",
"killed": "terminated",
},
)
from agent_killswitch.integrations.crewai import KillSwitchHook
hook = KillSwitchHook(killswitch=ks, crew_id="my-crew")
if hook.before_action(agent_id="researcher"):
# Action is allowed
...
from agent_killswitch.integrations.openai_agents import KillSwitchGuardrail
guardrail = KillSwitchGuardrail(killswitch=ks, agent_id="openai-agent")
result = guardrail.check_input("user message")
from agent_killswitch.integrations.asyncio_tasks import KillSwitchTaskGroup
group = KillSwitchTaskGroup(killswitch=ks, agent_id="async-agent")
group.add_task(worker_coro())
results = await group.run() # Cancelled if kill switch activates
| Backend | Dependencies | Use Case |
|---|---|---|
InMemoryBackend | None (default) | Single process, testing |
RedisBackend | redis[hiredis] | Distributed, production |
# Default: in-memory (zero dependencies)
ks = KillSwitch()
# Redis: distributed
import redis
from agent_killswitch.backends.redis import RedisBackend
client = redis.Redis(host="localhost")
ks = KillSwitch(backend=RedisBackend(client, prefix="myapp:ks:"))
Custom backends implement the KillSwitchBackend protocol.
| Operation | Latency (p99) | Throughput |
|---|---|---|
activate() | <1ms | >100k ops/sec |
check() | <0.1ms | >1M ops/sec |
heartbeat() | <0.1ms | >1M ops/sec |
All with InMemoryBackend. Redis backend adds network RTT (~0.5ms).
# Core (zero dependencies)
pip install agent-killswitch
# With Redis support
pip install agent-killswitch[redis]
# With framework integrations
pip install agent-killswitch[langchain]
pip install agent-killswitch[langgraph]
pip install agent-killswitch[crewai]
pip install agent-killswitch[openai]
# Everything
pip install agent-killswitch[all]
# Development
pip install agent-killswitch[dev]
Apache 2.0 -- see LICENSE.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.0 | 7 Sept 2026 | 13 |
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 20 Oct, 22:31 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:e0f6de5c3f973e8dd12595c361e2ac6bd4fed76ce2d7aca5f2f821b976a1eb69