Kill Switch
The kill switch lets you disable any registered agent instantly. Once an agent is blocked, the proxy rejects every subsequent request from that agent with HTTP 403 — without forwarding anything to the LLM upstream. No redeployment, no config change, no restart required.
How it works
Every inbound request to the proxy carries an X-Agent-ID header (or the agent ID is inferred from the API key). Before forwarding the request, interceptor.rs queries the agent registry:
inbound request
|
v
interceptor.rs: SELECT status FROM agents WHERE agent_id = $1
|
+-- status = "active" --> forward to upstream
|
+-- status = "blocked" --> return HTTP 403 immediately
|
+-- DB error --> forward (fail-open)The check happens before any LLM call is made. A blocked agent consumes zero LLM tokens.
The current implementation performs one database query per request to fetch agent status. A TTL in-process cache is planned to reduce this to zero DB queries for the common case. Until then, each request adds one PostgreSQL round-trip (~0.5ms on a local network).
Blocking an agent
curl -X PUT http://localhost:4001/api/v1/agents/billing-agent \
-H "Authorization: Bearer $GOVRIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "blocked"}'Response:
{
"agent_id": "billing-agent",
"status": "blocked",
"updated_at": "2026-03-05T10:30:00.000Z"
}The change takes effect on the next request from that agent. There is no propagation delay beyond the time it takes the next request to hit the proxy.
Re-enabling an agent
curl -X PUT http://localhost:4001/api/v1/agents/billing-agent \
-H "Authorization: Bearer $GOVRIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "active"}'HTTP 403 response format
When a blocked agent makes a request, the proxy returns:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": "agent_blocked",
"message": "Agent 'billing-agent' is currently blocked. Contact your administrator.",
"agent_id": "billing-agent"
}Your agent code should treat a 403 with error: "agent_blocked" as a signal to stop retrying. Standard 403 retry logic will loop indefinitely — add a check for this error code.
Fail-open behavior
If the agent registry database is unreachable (connection pool exhausted, PostgreSQL down), the kill switch fails open: the request is forwarded to the upstream as if the agent were active.
Fail-open is a deliberate choice. Failing closed (rejecting all traffic when the DB is down) would cause a complete proxy outage whenever PostgreSQL has a hiccup. For most deployments, the risk of an occasional unblocked request during a DB outage is lower than the risk of dropping all traffic. If you need fail-closed behavior, this can be patched in interceptor.rs.
A tracing::warn log line is emitted whenever the kill switch falls back to fail-open:
WARN govrix_scout_proxy::interceptor: agent status check failed, failing open agent_id="billing-agent" error="connection pool timed out"Implementation
| File | Role |
|---|---|
crates/govrix-scout-proxy/src/interceptor.rs | Kill switch check — queries agent status before forwarding |
crates/govrix-scout-store/src/agents.rs | get_agent() — database read for agent status |