Watchtower Commands
ASYNC · WEBHOOK · ACK · AUTO-RESPOND
Watchtower Commands are the async response layer for deployed agents. Guard handles inline request decisions; Commands handle actions that happen after a ShieldPi verdict: kill a compromised session, quarantine poisoned memory, switch to a hardened system prompt, or disable a risky tool.
Commands are delivered as signed command.issued webhooks. Your handler executes the action, then ACKs the command with executed, rejected, or failed. Pending commands expire after their TTL and emit command.expired.
Command actions
| Action | Payload | Use |
|---|---|---|
kill_session | Optional: reason | Terminate an active agent session after a critical verdict. |
quarantine_memory | Optional: reason, snapshot_to | Snapshot and clear poisoned memory for a session. |
switch_system_prompt | Required: prompt. Optional: reason | Move the agent to a hardened system prompt for the rest of the session. |
disable_tool | Required: tool_name. Optional: reason | Remove a risky tool from the agent registry until a human reviews it. |
Issue a command
ShieldPi SOC automation can issue commands when auto-respond is enabled. Customers can also issue commands from their own automation through the same API.
HTTPPOST /api/agent/commands/issue X-API-Key: shpi_live_... Content-Type: application/json { "action": "kill_session", "session_id": "user-abc-session-42", "payload": { "reason": "watchtower_critical:tool_abuse" }, "ttl_seconds": 600 }
application/json{ "id": "11111111-2222-3333-4444-555555555555", "session_id": "user-abc-session-42", "action": "kill_session", "payload": { "reason": "watchtower_critical:tool_abuse" }, "status": "dispatched", "expires_at": "2026-05-08T12:10:00+00:00" }
Handle the webhook
json{ "event_type": "command.issued", "data": { "command_id": "11111111-2222-3333-4444-555555555555", "session_id": "user-abc-session-42", "action": "kill_session", "payload": { "reason": "watchtower_critical:tool_abuse" }, "expires_at": "2026-05-08T12:10:00+00:00", "severity": "critical" } }
Webhooks use the same ShieldPi delivery pipeline as scan events: HMAC signing, retry, dead-letter tracking, and JSON/OCSF/CEF/Syslog/SIEM format adapters.
ACK after execution
HTTPPOST /api/agent/commands/11111111-2222-3333-4444-555555555555/ack X-API-Key: shpi_live_... Content-Type: application/json { "status": "executed", "reason": "session terminated by customer handler", "payload": { "terminated_at": "2026-05-08T12:02:11+00:00" } }
ACK status must be executed, rejected, or failed. ShieldPi stores the ACK next to the original command so the forensic timeline can show verdict, command, dispatch, and customer action together.
Python SDK
pythonfrom shieldpi import ShieldPiCommands commands = ShieldPiCommands(api_key="shpi_live_...") def handle_shieldpi_webhook(event: dict) -> None: if event["event_type"] != "command.issued": return data = event["data"] command_id = data["command_id"] try: if data["action"] == "kill_session": my_agent_runtime.terminate(data["session_id"]) elif data["action"] == "quarantine_memory": my_agent_runtime.snapshot_and_clear_memory(data["session_id"]) elif data["action"] == "switch_system_prompt": my_agent_runtime.set_system_prompt(data["session_id"], data["payload"]["prompt"]) elif data["action"] == "disable_tool": my_agent_runtime.disable_tool(data["payload"]["tool_name"]) commands.ack(command_id, status="executed", reason="completed") except Exception as exc: commands.ack(command_id, status="failed", reason=str(exc))
Operational controls
- Commands are action-whitelisted; unknown actions and unknown payload keys are rejected.
- Default TTL is 10 minutes, with API bounds from 30 seconds to 1 hour.
- Auto-respond defaults to off. Suggest mode queues commands for approval; auto mode only fires explicitly enabled actions.
- Use
GET /api/agent/commands?status=pendingto list pending commands. - Use
GET /api/agent/commands/_meta/actionsto fetch the live action schema.