Skip to main content

agentveto

Replay it. Prove it. Veto it.

Every other tool answers "what did my agent do?". Those tools already exist, and there are a lot of them. agentveto is being built for the harder question: what is my agent allowed to do, and can I prove it afterwards?

Today it does the first part properly. It records every step - prompts, tool calls, tokens, cost, timing, errors - into a local SQLite file and turns it into a single HTML file you can open, search, and attach to an incident report. Then it replays the whole run for free.

No account. No SaaS. No network call. Everything stays on your machine.

pip install agentveto

60 seconds

import agentveto

agentveto.init()  # wraps any installed openai / anthropic SDK


@agentveto.trace(kind="tool")
def lookup_order(order_id: str) -> dict:
    return db.orders.find(order_id)


@agentveto.trace
def handle_ticket(ticket: str):
    order = lookup_order(parse_id(ticket))
    return decide(order)


handle_ticket("two of three items never arrived")

agentveto.report()  # writes agentveto-handle-ticket.html

Open the HTML file. Every step is on a timeline, clickable, with its input, output, token count and cost.

No API key and no LLM? Run the built-in example:

python examples/demo.py

What the report looks like

Veto preview — three blocked calls

Three calls in this run were refused before they executed. The denied rows are red, the ones that went through a human prompt (and failed closed, since no human was attached) carry the same veto tag. Click any row for the exact prompt, response, model and cost.

The replay-only view is the same shape, minus the veto tags:

Replay demo — full timeline with cost attribution

Regenerate these from the bundled demos with:

python scripts/make_assets.py

What it does today

Zero setup init() and you are done. No project, no token, no dashboard to sign into.
Auto-instrumentation Installed openai or anthropic SDKs are wrapped automatically - tokens and cost captured without touching your call sites.
Explicit spans @trace or with start_span(...) for your own functions and tool calls. Nesting is automatic.
Cost attribution Per-step and per-run, using a pricing table you can override. Unknown models are reported as unknown rather than guessed.
Record and replay First run records LLM responses. init(replay=True) replays them, so a 40-step run is reproducible for free.
Policy gates @guard evaluates a call before it runs and can deny it or route it to a human. Blocked calls are on the record like everything else.
Tamper-evident evidence prove sign chains every run's digest and optionally signs it with Ed25519. verify detects a single changed byte and names the run it is in.
Self-contained reports One HTML file, no CDN, no build step. Renders offline, six months from now, on a plane.
Nothing leaves your machine Traces are written to ./agentveto.db. There is no server component.

Veto: stop a call before it runs

Replay tells you what happened. @guard decides, before a dangerous call goes out, whether it is allowed to happen at all:

from agentveto import guard, VetoError

POLICY = {
    "default": "allow",
    "rules": [
        {
            "name": "no-customer-email",
            "action": "send_email",
            "effect": "deny",
            "reason": "Outbound customer email requires a human in the loop.",
        },
        {
            "name": "refund-needs-approval",
            "action": "issue_refund",
            "effect": "ask",
            "when": {"amount_usd": {"gt": 250}},
            "reason": "Refunds over $250 need a human approver.",
        },
    ],
}


@guard(POLICY, action="send_email")
def send_email(to, subject, body): ...


@guard(POLICY, action="issue_refund")
def issue_refund(order_id, amount_usd): ...


issue_refund("A-1", 214.50)  # under the line: runs
issue_refund("A-1", 412.50)  # raises VetoError - no money moves
  • deny raises VetoError; the wrapped function never executes.
  • ask prompts on the terminal and fails closed (denies) where there is no human - CI, a cron job, a server.
  • Policies are plain dicts: ordered rules, first match wins, when clauses with eq/ne/gt/gte/lt/lte/in/exists on dot paths into the call payload.
  • Every decision is written onto the trace, so a blocked call appears in the same HTML report as the steps around it, marked veto.
python examples/veto_demo.py     # 3 blocked calls, no API key needed

Replay: the part that matters

agentveto.init()  # run once: records every LLM response
agentveto.init(replay=True)  # run again: serves recorded responses

The LLM calls come from disk; everything else - routing, tool calls, branching, your business logic - executes for real. That is what makes an old run reproducible instead of merely inspectable. It also makes iteration on step 37 free, because you stop paying for steps 1-36.

Streaming responses are traced but not replayable yet.

Prove: evidence you can hand to an auditor

A trace in a SQLite file is only as trustworthy as whoever controls the file. prove turns a run into evidence: a canonical digest chained across runs, optionally signed with Ed25519, exportable as one portable file that anyone can verify offline - without your database and without your secret key.

agentveto prove keygen -o ./keys                            # agentveto.key + agentveto.pub
agentveto prove sign --db agentveto.db --key ./keys/agentveto.key
agentveto prove export --db agentveto.db --run <run-id> -o incident.evd

agentveto verify incident.evd       # the auditor's path: offline, no db needed
agentveto verify agentveto.db       # or: is my own store still untouched?
OK      ok
  [ok] target_run_digest   data matches attested digest
  [ok] chain               ok
  [ok] head_anchor         ok
  [ok] signature           valid

Two layers, on purpose:

  • Integrity (zero dependencies, always on): every run gets a SHA-256 digest of its stored rows, and runs are linked into a hash chain from a genesis value. Change one byte in one span and verification fails, naming the run.
  • Authenticity (optional, pip install 'agentveto[sign]'): an Ed25519 key signs the chain head, so a third party can verify the whole history without holding your key.

Signing is a deliberate act, not ambient tracing - you sign when you want to lock in the record. That keeps recording fast and dependency-free.

Honest limits: this proves the integrity of what was recorded, not that the recording is true. Anyone who edits the database before you sign edits the evidence too, so sign at the moment that matters. The chain is linear rather than a Merkle tree: the right size for one process's history.

How this compares

Recording is a crowded space. Here is the honest map:

agentveto agentblackbox agentledger (TS) LangSmith LangFuse
Python-native yes yes no yes yes
Works fully offline yes yes yes no no
Account required to view a trace no no no yes no
Single-file report you can email yes no no no no
Deterministic replay of LLM calls yes yes no no no
Runtime policy enforcement yes (V1 preview) no no no no
Tamper-evident evidence chain yes (v2 preview) no yes no no
Signed, portable evidence file yes (.evd) no no no no

Nobody in the Python ecosystem does enforcement yet. Recording tells you what went wrong; a veto point stops it from going wrong. The preview of that is in this repo now.

The other honest part: today this does less than the hosted platforms. No prompt management, no dataset curation, no hosted dashboards. It does one thing

  • tell you exactly what your agent did - with no setup and no data leaving your machine.

Roadmap

  1. Replay (done) - deterministic reproduction of any run, locally, for free.
  2. Veto (done, preview) - a policy gate that evaluates a step before it executes and can block it or route it to a human. The part nobody else has.
  3. Prove (done, preview) - hash-chained, optionally signed traces so a run can be handed to an auditor as evidence, not as a screenshot.
  4. Responsibility credentials (next) - bind an attested run to who authorised the agent, so "the agent did it" has a named human behind it.

CLI

agentveto demo                 # example run, no API key needed
agentveto demo --veto          # policy-gate demo: calls blocked before they run
agentveto list                 # recorded runs
agentveto report --run <id>    # write a report for a specific run
agentveto serve                # local viewer (pip install 'agentveto[serve]')

# policy tooling
agentveto policy show policy.json
agentveto policy validate policy.json --strict
agentveto policy explain policy.json --action send_email --payload '{"to":"x@y.com"}'

# evidence (pip install 'agentveto[sign]' to enable Ed25519 signing)
agentveto prove keygen -o ./keys
agentveto prove sign --db agentveto.db --key ./keys/agentveto.key
agentveto prove export --db agentveto.db --run <run-id> -o incident.evd
agentveto verify incident.evd
agentveto verify agentveto.db

MCP server (Claude Code, Cursor, ...)

pip install 'agentveto[mcp]'

Then add to your editor's MCP config:

{
  "mcpServers": {
    "agentveto": {
      "command": "agentveto-mcp",
      "args": ["--policy", "/abs/path/to/policy.json"]
    }
  }
}

The LLM in your editor can now ask evaluate_policy("send_email", {...}) and rewrite a call before it gets vetoed at runtime. Full docs: docs/mcp.md.

Configuration

agentveto.init(
    db="./traces.db",  # or set AGENTVETO_DB
    replay=False,  # serve recorded responses instead of calling the API
    record=True,  # store responses for later replay
    auto_patch=True,  # wrap installed LLM SDKs
)

agentveto.set_pricing({"my-internal-model": (1.0, 4.0)})  # USD per 1M tokens

Status

Early. The data model and the report are stable enough to rely on; the API may still change before 1.0. Issues and PRs welcome.

License

Apache 2.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agentveto-0.1.0.tar.gz (59.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agentveto-0.1.0-py3-none-any.whl (49.9 kB view details)

Uploaded Python 3

File details

Details for the file agentveto-0.1.0.tar.gz.

File metadata

  • Download URL: agentveto-0.1.0.tar.gz
  • Upload date:
  • Size: 59.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for agentveto-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b6631eb11262515678dc133502cc748de1bcc8566dc5a2d01b7575ef95d84eb2
MD5 d632b9147b1193b1a1ae23a9366c4859
BLAKE2b-256 3bf91a6ef1edb99f5e42717ffd85ea7f1484a107487d99316d9af7e2d4011dc5

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentveto-0.1.0.tar.gz:

Publisher: release.yml on jiawenyao401/agentveto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file agentveto-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: agentveto-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 49.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for agentveto-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ed3fe538328621a0790671f7bec74a426287394259ac6d675033750a499fc5d6
MD5 00b4810cf5e5ebeba94fb927f8f7a8a5
BLAKE2b-256 af658f872691bf48716c849de29d05bc78779b9312be47e29f3ec02703f63e25

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentveto-0.1.0-py3-none-any.whl:

Publisher: release.yml on jiawenyao401/agentveto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page