Every action, scored.
It takes agents to control agents. Guardrails stop what you can name in advance. The AI Analyzer reads the rest: an agent that scores every action for intent and syntax before it executes.
No deny list catches it all.
A deny list catches what you thought of: DROP TRUNCATE DELETE without a WHERE. The hard case breaks no rule.
Every query in this session is permitted. Read in sequence, they are an extraction. Nothing in a list of forbidden operations sees that.
SELECT name FROM customers LIMIT 100 OFFSET 03:01:12SELECT name FROM customers LIMIT 100 OFFSET 1003:01:14SELECT name FROM customers LIMIT 100 OFFSET 2003:01:15SELECT email FROM customers LIMIT 100 OFFSET 03:01:17SELECT ssn FROM customers LIMIT 100 OFFSET 03:01:18
Five passes. One extraction.
A score on every action.
The analyzer runs on the statement your agent just sent, in the same pass as the deterministic rules, while it is still in the sidecar. It returns a risk score, and the score decides what happens next.
Intent and syntax, together
Syntax says a statement is well formed. Intent asks what it is for. A SELECT with no WHERE on a table of ten rows and the same statement on ten million rows are different acts.
Before it executes
The score comes back while the statement is still in the sidecar. Nothing has reached your database, so the outcome is still a choice.
One of three outcomes
Pass, block, or route to a human: the same three outcomes every other control produces, so a scored action and a rule-matched one get the same handling downstream.
Your model, your key
Point the analyzer at the provider you already cleared. Your API key, your data policies, your region.
Low risk, so it passes.
Pick an action your agent sends and read the score it gets before it executes.
A standard read, scored in the same pass as the rules.
agent-07 → prod-db:5432
SELECT name, email FROM users LIMIT 50;- context
- First statement in this session.
- intent
- List 50 users for a report view.
- syntax
- Well formed. Bounded read with a LIMIT.
- risk
- Low
- outcome
- pass
● postgres(SELECT * FROM patients WHERE ssn = '900-12-3456')
⎿ session analyzer, before execution
Query targets patients table with SSN column.
Direct PII access without masking.
Previous sessions show 3x SSN queries in 24h.
Risk: HIGH. Escalating to compliance-on-call.
Not smarter. Just as fast.
The AI Analyzer does not understand your business, and it is not trying to. It has one job and a few hundred milliseconds to do it: read this statement, judge what it is for, return a score.
A static rule cannot judge intent.
It matches a pattern you wrote in advance. That is why it is reliable, and that is also its ceiling.
A human cannot review at machine speed.
Your agent issues the next statement in milliseconds. A person reading a queue is already behind.
So the control has to be an agent too.
One that moves at the speed of the thing it watches, with a single job: read every statement live and stop the dangerous one before it lands.
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.AI 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.
Point it at a model.
Name a provider and a model, give it a key, and the analyzer reads every action your agents send before it runs. Free and open source under MIT.
Ask an assistant how AI Analyzer 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: block
low: allow
message: refused by risk analysis
$ hoop start sidecar --config config.yaml
sidecar running