Risky ops wait for a person.
Risky operations escalate to a person for one-off approval. The agent holds on the wire with the exact statement attached, then continues the moment someone decides.
Pass and block are not enough.
The expensive cases sit in between: a cleanup that is right on Tuesday and a disaster on Friday.
Most operations are obviously fine or obviously not, and a rule handles those. The rest look like a migration that has to run or a backfill on a live table. Block them and the agent cannot do the work you gave it. Allow them and you trust a model with a decision nobody signed off on.
- Obviously fineA rule passes it
- In betweenA person decides
- Obviously notA rule blocks it
Most operations never reach a person.
The operation stops and waits.
Nothing reaches your resource while the agent waits for an answer. The statement sits in the sidecar, where it was intercepted, until a person approves it or turns it down.
One operation, one decision
An approval covers this statement, this time. It does not open a window, grant a role, or widen access for anything that comes after it.
The statement is attached
The approver reads the exact operation, not a ticket describing it. No paraphrase to check and nothing to reconstruct later.
The agent waits on the wire
The connection stays open. Nothing queues for a retry and no work is thrown away, so the agent resumes where it stopped.
The record writes itself
Who asked, what they asked for, who decided, and when. The evidence comes out of the decision, not out of a reconstruction for an auditor.
The agent waits.
Send one risky write through the sidecar. Hold it, then decide, and read what the agent sees at each step.
Nothing reaches the database. The connection stays open.
agent-07 → prod-db:5432 · task: close shipped orders
UPDATE orders SET status = 'delivered';NOTICE: held by hoop for approval
DETAIL: write against a production table, no WHERE clause
REQUEST: sent to the approver, statement attached
WAITING: · connection open
SCOPE: this statement, this time
agent-07 waits on the open connection
nothing has run, no retry is queuedApproval required
UPDATE orders SET status = 'delivered'Risk: high- Write against a production table
- No WHERE clause in the statement
- Session Analyzer scored this above your approval threshold
A hold is not a failure.
The agent is not told no. It is told to wait, and the connection stays open while it does. When the approval lands, the statement runs and the agent carries on with the work it was doing.
That is the difference between a control that governs an agent and one that just stops it.
Four controls, one sidecar.
Data Masking
Rewrites sensitive values in the response, in memory, before they reach the client. The request itself is never touched.Guardrails
An ordered deny list checked against every statement. Destructive ones never reach the database, and the client reads the reason you wrote.Session Analyzer
An agent scores every action’s intent and syntax for risk before it executes.Human in the Loop
Risky operations pause for a person’s one-off approval, then the agent carries on.
Decide what needs a person.
Everything else passes or gets refused on its own. Free and open source under MIT.
Ask an assistant how Human in the Loop works: Claude, ChatGPT, Grok, Gemini, Perplexity, Copilot.
# config.yaml
analyzer:
provider: anthropic
model: claude-sonnet-4-5
credentials_file: /run/secrets/anthropic-key
listeners:
- name: localdb
protocol: postgres
listen: 127.0.0.1:15432
upstream: 127.0.0.1:5432
analyzer:
trigger: {operations: [update, delete]}
high: require_review # the person at the terminal decides
$ hoop start sidecar --config config.yaml
sidecar running