Every AI action checked before it runs: by rules it can never break, a model trained on your team's decisions, and your team when it's unclear. With proof of every decision.
We're onboarding a small group of design partners. Or start on your own with the rules and the proof: Python 3.11+ on macOS or Linux, no dependencies, free for up to two agents.
Works with Claude Code, Codex and Cursor; any MCP client that starts a local server over stdio; Claude, GPT and Gemini model calls; and any Python agent.
CHECKPOINT
.paveo/audit.jsonlchain verified
0001allowclaude-code · Bash45d46e01cb
0002denyBash.command.not_matches3ea0ebec19
0003allowrefund-bot · lookup_orderfdb48a56af
0004allowrefund-bot · refundf75ff38a7d
0005denyrefund.requires.lookup_order6f1512b9b9
Calls reaching the checkpoint, judged by rules from Paveo's starter policies. Each log line's hash covers the line and the one before it, computed in your browser the way Paveo computes it.
The whole system
A good hospital runs on protocols and on judgment. So should your agents.
Protocols nobody may cross. A senior doctor's judgment for the cases no protocol covers. Someone to call when it's unclear. A chart that records every decision. Agents need the same four things, and most tools give them one: fixed rules, a model's judgment, or a dashboard after the fact. Paveo brings all four to one checkpoint, before the action happens; the second and third we build for each design partner when they join, on their own decisions.
1
Rules it can never cross
Which tools, which arguments, in what order, how often, at what cost. No guesswork: every answer comes from a rule you wrote, and you can point to the one that gave it.
"amount_usd": {"max": "500.00"}
2
Judgment for the grey zone
A refund inside the limit, to an account opened two hours ago. A model that learns your team's own past decisions, running on your machines, flags what the rules allow but shouldn't and sends it to someone on your own team. It can only make a decision stricter, never looser.
Built for each design partner
3
A human when it's unclear
A call flagged by a rule or by the model goes to someone on your own team, and the agent waits for the answer. What the rules allow and nothing flags runs on its own.
Built for each design partner
4
Proof of every decision
Replay your past Claude Code sessions through a policy before you switch it on. After that, every decision goes into a hash-chained record your auditor can verify.
paveo evidence --since 2026-09-01
Rules for what must be provable. Judgment inside them and a human for what gets flagged, built for each design partner. Proof for all of it.
We're onboarding a small group of design partners. Want in?
Under the hood
Your agent does the work. Paveo decides what it may do.
Every call passes the same six steps, in this order, before it leaves your process.
1
The call arrives
A tool call, a shell command or a model request, from your code or from a coding agent's hook.
2
Who is asking
The agent and the person it acts for. An agent the policy doesn't name is refused, and so is everything after paveo stop.
3
The rules
Which tools, which arguments, in what order, how often. An agent past its plan's limit is refused here too.
4
The ceiling
For a model call, its worst-case cost is held against the agent's budget before anything is sent.
5
The decision
Admitted, or refused with the rule and the reason. In shadow mode, a refusal is recorded and the call goes ahead.
6
The record
Your proof: written to the hash-chained log before the call leaves. When the model answers, its real cost settles the hold.
Every call gets a rule, a ceiling, a decision and a record, before it happens.
Who it's for
Engineering teams
One set of rules for every engineer's Claude Code, Codex and Cursor
No code to write. Before the agent runs a shell command or writes a file, the hook checks it, and a refusal goes back to the agent, which tries something else.
the agent calls Bash rm -rf ~/projects
it gets backRefused by policy: Bash.command.not_matches
(constraint_violated). An argument is outside
what this rule permits. Correct it only if it
was a mistake; do not split the action into
smaller calls to fit. If the task cannot be done
within the policy, stop and tell the user; do not
try to reach the same result another way.
Refuses rm -rf, git push --force, git reset --hard, DROP TABLE and edits to its own policy.
paveo stop refuses every call until paveo resume.
paveo replay claude-code shows what it would have refused in sessions you already had.
Teams shipping agents
A checkpoint around every call your agent makes, and the record for your customer's security review
Write what each agent may do in a policy file, then route its calls through check_tool and check_llm. Model calls are priced before they are sent, for Anthropic, OpenAI, Gemini and any model you price yourself.
with pf.session(agent_id="refund-bot", principal="user_123") as s:
s.check_tool("refund", {"order_id": "A-1", "amount_usd": 600})
PolicyDenied: refund.amount_usd.max (constraint_violated)
Agent platforms
Rules and proof for every agent built on your platform
Built into your platform and running in your customers' own infrastructure, so every agent they build arrives with limits and a record their security team can read. Talk to us.
Integration built with each platform partner
Any MCP client, any language
Put Paveo in front of any MCP server, with no code
Claude Desktop, Cursor, Windsurf: any client that starts a local MCP server over stdio. paveo mcp starts the server for it and checks every tool call against your policy first. A refused call never reaches the server; the client gets the refusal, naming the rule, and the model reads it.
the model calls write_file pwned.txt
it gets backRefused by policy: <undeclared> (tool_not_allowed).the server never sees it, and pwned.txt is never written
The server receives exactly what was judged: every message is passed on as Paveo re-read it, so no difference in how two programs split or parse a message can turn it into a call nobody judged. Tool calls only; resources, prompts and sampling pass through. Local servers over stdio, not remote ones.
Proof before you switch it on
Two months of our own Claude Code, put through the starter policy
We ran paveo replay over our own sessions while building Paveo: 106 sessions and 8,176 tool calls, from 31 July to 27 September 2026. This is what the starter policy would have refused.
117
rm -rf
3
git clean -f
2
git reset --hard
1
git push --force
Plus 547 attempts to edit the agent's own settings or the guard's files. Most of those came from building Paveo itself, whose files the starter policy protects. Not every rm -rf was a mistake: some were clean-ups the agent meant, and the guard would have made it find another way.
$ paveo replay claude-code ~/.claude/projects
paveo: read 106 session files.
Tool calls: 8,176
judged by the policy: 6,918, allowed 6,248, refused 670
...
Nothing was stored, and no prompt, command or argument is shown.
Run it on your own history before you trust the policy: it reads the sessions Claude Code already keeps, stores nothing, and prints only counts and rule names.
What a policy can say
Which tools, with which arguments
An argument that isn't named is refused, and a limit can't be dodged by leaving the argument out.
"amount_usd": {"max": "500.00"}
In what order
A refund only after the same order was looked up, earlier in the same session.
Twenty calls a minute, or the same call twice in thirty seconds: the loop that retries one failing request forever.
"rate": {"calls": 20, "seconds": 60}
Which models, and how much
A daily ceiling in dollars, held against the worst case of each call before it is sent.
"budget": {"period": "day", "limit_usd": "5.00"}
Try it first
Shadow mode records what a rule would refuse and lets the call through, so you can read a day of your agent's work before anything is enforced.
"mode": "shadow"
An agent with no rule for a tool may not call it. Allow-by-default is how agents end up acting outside their job.
Every refusal names its reason
These are the nineteen reasons Paveo can write into the log. Each refusal names one, with the rule that fired, so a year later you can still say why a call was stopped.
Tools and arguments
tool_not_allowed
The agent has no rule for this tool.
tool_denied
The tool is on the agent's deny list.
argument_not_permitted
An argument the rule doesn't name.
argument_missing
A constrained argument was left out.
constraint_violated
An argument is past its limit, or matches a forbidden pattern.
Order and pace
requires_unmet
The call that must come first didn't, with the same values.
rate_limited
More calls than the rule allows in its window.
repeated
The same call again, inside its window.
not_comparable
Arguments too complex to compare with earlier calls.
Models and money
model_not_allowed
A model this agent may not use.
model_denied
A model on the agent's deny list.
no_budget
A model call from an agent with no budget.
budget_exceeded
Its worst case would breach the ceiling.
pricing_unknown
A model or token type the price table can't price.
invalid_request
A request whose cost can't be bounded, such as one with no output cap.
The checkpoint itself
agent_unknown
An agent the policy doesn't name.
stopped
paveo stop is in force.
plan_limit
An agent past the number the plan covers.
memory_unavailable
The guard can't read what ran before, and a rule needs it.
What's inside
Five parts, all in your process
pip install paveo
policy.json
The policy. Agents, tools and their arguments, order, rates, models, budgets and shadow mode. Its hash goes into every record.
check_tool
The checkpoint.check_tool, check_llm and wrap_anthropic in your code, and the hook for Claude Code, Codex and Cursor.
reserve
The ledger. The worst case is reserved, the real cost settled. One lock serves threads and asyncio, so calls at the same moment can't overspend a ceiling.
prices
The price table. Dated prices for Anthropic, OpenAI and Gemini. A model it can't price is refused, never guessed.
audit.jsonl
The record. Hash-chained, with an anchor at its end. Exported as audit evidence on Team and up.
Proof after
A record you can hand to an auditor
Every decision goes into a hash-chained log on your disk: which agent, which tool or model, allowed or refused, by which rule, under which policy. Editing any record breaks every hash after it.
On Team and up, one command turns a period of it into evidence: a report to read or print, every record as a spreadsheet, the records themselves so the chain can be recomputed, and the policy that was in force. It refuses a log whose chain doesn't verify.
$ paveo evidence --since 2026-09-01 --until 2026-09-30
paveo: 420 records (seq 1-420) written to
paveo-evidence-2026-09. The chain verified from
record 1 to 420, and matches its anchor.
The report that command wrote, unedited. The log behind it is sample data: two agents, 420 decisions in September.
For the security review
You are being asked to put Paveo in the path of every call your agent makes. These are the answers a reviewer asks for, each one something you can check.
Network
Paveo opens no sockets. A test fails the build if one is created, and you can confirm it on your own machine with a firewall rule.
What is recorded
Agent, principal, tool or model name, decision, rule, policy hash, costs and token counts.
What is never recorded
Prompts, completions and tool arguments. A tool name the policy doesn't define is logged as <undeclared>, so a model can't write into the log through it.
Dependencies
None. Paid plans add one optional package, cryptography, used only to check a licence key's signature, offline.
Failure
A call Paveo can't judge is refused: a policy that won't load, a call it can't price, a log it can't write. Failing open is a setting that is off unless you switch it on, and it warns on every call while it is on.
The code
Source-available under the Elastic License 2.0. Read every line; releases are published only by CI, with a provenance attestation and an SBOM.
Paveo runs entirely on your machines, so there is no service of ours for your agents' data to reach: no status page to watch, no subprocessor handling that data, and no SOC 2 report to request, because there is nothing of ours to audit but the code.
It is a guard rail, not a sandbox. Code that calls your provider directly, without asking Paveo, is never seen.
The log is tamper-evident, not tamper-proof. Someone with write access can rewrite it; they can't do it invisibly.
The coding-agent guard matches patterns. It doesn't understand the shell, so rm -r -f or a script that does the deleting gets past it.
Budgets live in one process. A restart clears the spend record, and two processes don't share a ceiling yet.
It doesn't read model output, filter content or detect jailbreaks.
The MCP guard judges tool calls only. Resources, prompts and sampling pass through, a path in a call is judged as written (symbolic links are followed only for the coding agents), an argument spelled in another case is a different name unless the tool lists its constraints, it guards local servers over stdio, and a client set up to start a server without paveo mcp is not guarded.
Judgment and approvals are not in the library yet. We build them for each design partner when they join, trained on and shaped by that team's own decisions.
Pricing
Agents you build are priced per agent; coding agents across a company, per developer. No per-request fees: checks run on your machine, so there is no limit on them and nothing for us to count. Design partners get the Business plan at the Team price, $99 a month, for their first year.
Developer
For one person and one or two agents.
$0 forever
Up to 2 agents per policy
Unlimited checks, on your machine
Every rule: which tools, which arguments, in what order, how often
Shadow and enforce modes
Model-call budgets, held at each call's worst case
The coding-agent seatbelt for Claude Code, Codex and Cursor
Replay of your past Claude Code sessions through the policy
Developer is the free way to try Paveo: every rule, on your machine, for up to two agents. A paid plan is a licence key, checked offline, with no account. When a plan ends, the free plan applies: every rule keeps enforcing, the first two agents keep working, and any past two are refused until the plan is renewed.
Design partners
We're onboarding a small group of design partners.
For teams putting agents into production who have to show someone what those agents can and can't do: their own security team, a customer's security review, an auditor or an insurer.
Only for design partners:
The Business plan at the Team price for your first year: $99 a month, not $299. Up to 50 agents per policy, your policies written with us and a week in shadow mode before anything is enforced, your security questionnaire filled in, and replies within one working day.
Your own judgment model. We train it on your machines, on your team's own past decisions, and none of it leaves them. It flags what your rules allow but shouldn't, and it can only make a decision stricter, never looser.
Approvals by your own team. Anything a rule or the model flags waits for a yes from someone on your team, and everything else runs on its own.
The founder, every week. A weekly call, and what you run into gets fixed fast, usually within two days.