Skip to main content

Veto CLI — agent-payment policy + on-chain hard-stop. Any agent. Any rail.

Project description


Veto



The safety layer for AI agents that spend money.

Any agent. Any payment rail. Safe transactions.
Real-time policy + signed decision receipts + optional on-chain hard-stop.

PyPI downloads stars license Python x402 Base Sepolia live signed receipts

Quick start · Engine · On-chain · Scaffold · Comparison · Architecture · Commands · Community


The pitch in one paragraph

Veto sits between AI agents and the money. Every spend an agent attempts is checked against a YAML policy you author — caps, allowlists, escalation thresholds, on-chain rules — and an 8-stage risk engine that catches typosquats, address-poisoning, sanctioned addresses, prompt injection, and behavioral anomalies. Every decision ships with a cryptographically-signed receipt anyone can verify offline. For agents that need adversarial-grade enforcement, an optional smart wallet contract refuses to release funds without a fresh, in-scope, Veto-signed mandate — the chain refuses, not just our SDK. Composes with x402, AP2, Stripe MPP, Verifiable Intent.

Built by Investech Global LLC. Elastic License v2. Python + TypeScript scaffolding for agents.

Layer 3 — Operational Policy

The agent-commerce stack has rails (x402, MPP, AP2) and consent (Verifiable Intent, AP2 mandates). The layer between agent and rail — operator-side governance, signed evidence, refusal at the moment of decision — has been empty. Veto is that layer.


Quick start

# 1. Install — agent-friendly (used by Claude Code skills, MCP plugins, scripts)
curl -fsSL https://veto-ai.com/install.sh | bash

# Or human-friendly (pip)
pip install veto-cli

# 2. Register a Veto account from the terminal — no website, no form
veto register --email me@example.com --preset inference

# 3. Ask Veto whether an action is allowed
veto authorize --amount 0.05 --merchant api.openai.com --action payment

Output:

✓ APPROVED — risk 0.18
  reason_codes:    REPUTATION_NEW
  policy:          AI Inference v1
  policy_hash:     53aa6184…
  transaction_id:  e9f1c2a4…
  receipt:         eyJhbGciOiJFZERTQSIs… (Ed25519, verifiable offline)

That's it. No SaaS account, no credit card, no MCP setup required. The API key lives in ~/.veto/config.json (mode 0600) — only your user can read it.


What Veto checks

Eight stages. Every signal that fires lands in the receipt's engine_trace — so "why was this denied?" always has a structured answer.

> veto authorize --amount 14500 --merchant api-anthropc.com --action payment

  ✗ DENIED — risk 1.00
    01 your_rules                  ✓ within caps
    02 prompt_injection            ✓ no patterns
    03 misspelled_merchants        ✗ TYPOSQUAT_CANONICAL
                                     api-anthropc.com ↔ api.anthropic.com (94%)
    04 crypto_safety               (n/a — fiat)
    05 intent                      ⚠ INTENT_PARTIAL — mission says "inference", merchant unverified
    06 anomaly                     ✗ AMOUNT_ANOMALY (47× 30-day avg)
    07 behavior_baseline           ✗ AMOUNT_ABOVE_BASELINE_P99
    08 final_decision              ✗ DENY — fraud floor + amount cap
# Stage What it catches
1 Your rules Caps, daily limits, allow- and blocklists for merchants, chains, tokens, addresses
2 Prompt-injection "Ignore previous instructions" patterns and friends
3 Misspelled merchants api-anthropc.com, аpple.com (Cyrillic homoglyph) — for every user, allowlist or not
4 Crypto safety OFAC sanctioned addresses (live feed), address-poisoning attacks, known-drainer contracts
5 Intent Does the spend match the agent's mission and recent context? Crypto-aware.
6 Anomaly Velocity bursts, merchant-diversity spikes, off-pattern amounts
7 Behavior baseline Per-agent rolling stats — distinguishes "trading bot at 20 tx/min (normal)" from "inference agent at 20 tx/min (suspicious)"
8 Final decision Weighted aggregation, fraud floor, human-required floor, signed receipt with full trace

Output: approve / deny / escalate plus a risk_score (0–1), structured reason_codes, and the full engine_trace. The receipt signs all of it.


On-chain hard-stop

A minimal smart wallet (VetoGuardedAccount) holds the agent's funds and only releases them on a fresh, in-scope, Veto-signed mandate. Single-use, time-bound, scope-locked. Deployed and proven:

Live contract 0xCBbbC4b924AF40D29f135c3a88b6F650d55d92c5 on Base Sepolia
First execution 0x2f9ec…d2af — 0.000001 ETH transferred
Replay rejected MandateAlreadySpent() selector 0xffa64355 — the chain refused a duplicate
Off-chain verifier @veto/mandate-verifier (TS, Node 18+)
Source veto-protocol/contracts

Verification: secp256k1 EIP-712 + ecrecover (~3k gas). Domain separator binds chainId + verifyingContract → no cross-chain or cross-contract replay either. Each mandate carries a single-use jti the contract tracks on-chain. Production audited contracts ship in v2.


Scaffold an agent

veto agent init --name my-agent --dir ./my-agent

Generates a runnable TypeScript project with a local viem wallet (you own the key — no third-party vendor), an LLM brain you choose during setup (Anthropic Claude, OpenAI, or xAI Grok), tool wrappers for send_eth / send_usdc / get_balance, and every governed call routed through Veto's authorize first. Denies halt the agent before broadcast.

The full 4-step interactive lifecycle:

veto agent init      # scaffold the project + generate keys + write .env
veto agent fund      # auto-open faucet, poll for funds, confirm
veto agent deploy    # deploy a VetoGuardedAccount smart wallet (testnet)
veto agent status    # snapshot of agent + wallet + contract + policy

When WALLET_CONTRACT is set in .env, send_* calls go through executeWithMandate(...) on the deployed smart wallet. The chain refuses spends without a fresh, in-scope, Veto-signed mandate. Cooperative on the SDK side, hard-stop on the chain side, simultaneously.


Why Veto

🔒  Signed by default

Every approve, deny, escalate ships with an Ed25519-signed receipt over the canonical decision payload — engine version, policy fingerprint, signal scores, decision. Anyone verifies offline against /.well-known/jwks.json. The audit trail can't be rewritten.

⛓️  Optional on-chain hard-stop

For adversarial threat models, a smart wallet contract refuses to settle without a fresh Veto mandate. Live on Base Sepolia today; audited mainnet ships next. Same SDK, same policy, additional chain-level guarantee.

🛤️  Rail-agnostic

x402 (USDC over HTTP 402), Stripe MPP, AP2, direct EVM/Solana, Verifiable Intent. Veto sits one layer above the rail — pick whatever the rest of your stack picked. The policy travels with the agent.


The comparison

Wallet stacks Risk engines Schema specs Veto
Holds the agent's wallet (non-custodial by design)
Per-tx & daily caps ⚠️ wallet limit (spec only) enforced + versioned
Merchant + address allowlists ⚠️ flat list YAML + rollback
Typosquat + address-poisoning checks ⚠️ basic canonical + homoglyph-aware
OFAC sanctioned-address live feed ⚠️ static OFAC SDN, refreshed
Per-agent behavioral baselines ⚠️ per-account percentile-aware, per-agent
Signed decision receipts Ed25519 + JWKS, offline-verifiable
On-chain hard-stop VetoGuardedAccount + EIP-712 mandate
Composable across rails ❌ rail-bound ⚠️ vendor-bound x402 / MPP / AP2 / on-chain
Open source where it matters CLI + schema + contract + verifier

Veto is the operator-policy layer for autonomous-spending agents. The thing that makes "agent has a wallet" go from scary demo to production default.


All commands

Command What it does
veto register CLI-native signup. Creates account + default agent + preset policy.
veto authorize Ask Veto whether an action is allowed. Headline command.
veto verify Verify a Veto receipt offline against the issuer's JWKS endpoint.
veto policy export/push/show/list/check/activate Author and manage versioned YAML policies.
veto agent init Scaffold a runnable Veto-governed agent project (TypeScript).
veto agent fund Open a faucet for the agent's wallet, poll for funds.
veto agent deploy Deploy a VetoGuardedAccount smart wallet (testnet).
veto agent status Snapshot of agent + wallet + contract + policy state.
veto agent configure Re-run onboarding to fill in skipped keys.
veto init Auto-detect MCP clients (Claude Desktop, Cursor, Zed, Continue) and configure them.
veto status [agent_id] Show agent reputation tier + recent decision history.
veto mcp Run the Veto MCP server in stdio mode (used by MCP clients).

Five policy presets to start from

veto register applies a policy preset so your agent has sensible limits from the first authorize call. Pick one with --preset:

Preset For Defaults
personal (default) General-purpose agent $500/tx, $2k/day, blocks gambling/mixers/adult
inference AI API calls $5/tx, allowlists Anthropic/OpenAI/Replicate/etc.
x402-micropay x402 testing $1/tx, Base chain only, auto-approve <$0.10
ad-spend Meta/Google ads $1k/tx, escalate >$1k
dev Dogfooding/testing $500/tx, no merchant restrictions

When the preset isn't enough:

veto policy export inference > my-policy.yaml
$EDITOR my-policy.yaml
veto policy push my-policy.yaml      # auto-versioned, auto-active
veto policy check '{"action":"payment","amount":50,"merchant":"amazon.com"}'
veto policy activate <prior-policy-id>   # instant rollback

Every push creates a new versioned row. Receipts cite the exact policy_id, version_number, and policy_hash active at decision time — so an auditor in 12 months can prove which exact policy contents governed any past decision.


How it works

┌──────────────────────────────────────────────────────────────────┐
│  AGENT — your code, your stack, your runtime                     │
│  Calls veto.authorize() before each spend                        │
└────────────────────────┬─────────────────────────────────────────┘
                         │ HTTPS
                         ▼
┌──────────────────────────────────────────────────────────────────┐
│  VETO ENGINE — 8-stage pipeline                                  │
│  Policy · Prompt-inj · Typosquat · Crypto safety                 │
│  Intent · Anomaly · Baseline · Aggregator                        │
└────────────────────────┬─────────────────────────────────────────┘
                         │
       ┌─────────────────┴─────────────────┐
       ▼                                   ▼
┌──────────────┐                 ┌──────────────────────┐
│  Receipt     │                 │  Mandate (optional)  │
│  Ed25519 JWS │                 │  Ed25519 JWT (off-   │
│  for audit   │                 │  chain)              │
│              │                 │  + secp256k1 EIP-712 │
│              │                 │  (on-chain)          │
└──────────────┘                 └──────────┬───────────┘
                                            │
                                            ▼
                                 ┌──────────────────────┐
                                 │  VetoGuardedAccount  │
                                 │  smart wallet        │
                                 │  ecrecover · verify  │
                                 │  scope · settle      │
                                 │  or revert           │
                                 └──────────────────────┘

The cooperative path (left, just the receipt) is enough for most threat models — bugs, hallucinations, runaway loops. The hard-stop path (right, with the smart wallet) closes the adversarial case where the agent code itself is compromised. Same engine, same policy, two enforcement surfaces.


Composes with

Spec One-line How Veto composes
x402 HTTP 402 micropayments (USDC on Base) veto authorize runs before the agent signs the x402 payload
AP2 (Google) User → Agent intent mandates Receipts carry mandate_ref to cite an upstream AP2 mandate
Stripe MPP Agent-to-merchant card-rail payments Veto sits above; rail handles settlement
Verifiable Intent (Mastercard + Google) Sibling of AP2 Same pattern as AP2
ACP (OpenAI + Stripe) Catalog/cart/checkout API Different layer (Layer 5); orthogonal

Different layer, different problem, complementary primitive. When all four exist on a transaction, the agent carries: AP2/VI mandate (legal consent), Veto receipt (operational compliance), ACP merchant flow (commerce), MPP/x402 settlement (money). All four produce signed credentials.


Documentation

  • 📐 Architecture — the 5-layer stack, engine pipeline, on-chain hard-stop
  • 🚀 Quickstart — first 60 seconds (install → authorize → verify → agent init)
  • 📜 Receipts — receipt format spec, signing, verification, audit guarantees
  • 🛡️ Policies — YAML format, presets, customization, lifecycle
  • 🗺️ Roadmap — what's shipped (v0.6) → what's next (audit + mainnet)

Public artifacts

Artifact Repository
CLI source (this repo) veto-protocol/veto-cli
APPS — open policy schema veto-protocol/x402-policy-schema
Mandate verifier (TS) veto-protocol/mandate-verifier
Smart wallet contract veto-protocol/contracts
Veto's own published policies veto-protocol/veto-policies
Documentation veto-protocol/docs
Public JWKS (Ed25519 signing key) https://veto-ai.com/.well-known/jwks.json
Live contract on Base Sepolia https://sepolia.basescan.org/address/0xCBbbC4b924AF40D29f135c3a88b6F650d55d92c5

Community

  • 🐦 @veto_ai — release notes, demos, ecosystem updates
  • 🐛 Issues — bugs and feature requests
  • ✉️ tomer@veto-ai.com — direct line to the founder

Development

git clone https://github.com/veto-protocol/veto-cli.git
cd veto-cli
pip install -e ".[dev]"
pytest                                # unit tests
veto --help                           # local CLI

Contributing: open an issue first to discuss meaningful changes. PRs welcome on bugs, docs, new policy presets, and engine signal additions.


License

Elastic License v2 (ELv2). See LICENSE for the full text and copyright. You may use, modify, and embed Veto freely. You may not host Veto as a managed service to third parties or strip the licensing notices.


The safety layer for AI agents that spend money.
Any agent. Any payment rail. Safe transactions.



Built by Investech Global LLC · ELv2-licensed.

Project details


Download files

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

Source Distribution

veto_cli-0.7.0.tar.gz (111.9 kB view details)

Uploaded Source

Built Distribution

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

veto_cli-0.7.0-py3-none-any.whl (104.8 kB view details)

Uploaded Python 3

File details

Details for the file veto_cli-0.7.0.tar.gz.

File metadata

  • Download URL: veto_cli-0.7.0.tar.gz
  • Upload date:
  • Size: 111.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for veto_cli-0.7.0.tar.gz
Algorithm Hash digest
SHA256 1a63cefe24e1ae8a70214b312b1df90b83238aca8c5588856be2b824af4d9aee
MD5 c9490d249d6880101fa15f070c5a445a
BLAKE2b-256 35746ea37a35ce58b012a9e88a3cd9b78fe8ba7844a3251f680a36e26db0f2c1

See more details on using hashes here.

File details

Details for the file veto_cli-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: veto_cli-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 104.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for veto_cli-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 431c7afb79271e61fe3cfa53de0606eeef43844a787ecb03e337a5593be9244b
MD5 71ac314750653e1344a9eb314e064654
BLAKE2b-256 f5a20b3f06ca00cb4f680324aa393c3feaeb357dbe869021ef33089fb1215d7f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page