Skip to content

PlawIO/veto

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

303 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Veto

sudo for AI agents.

Stop agents from deleting files, leaking secrets, or pushing to prod — without slowing anyone down.

npm npm PyPI npm downloads License CI GitHub Stars

docs.veto.so · veto.so · npm · PyPI


AI agents can execute code, call APIs, and modify production systems. Veto is the permission layer that sits between every agent action and execution — validating, blocking, or routing to human approval before anything runs.

const veto = await Veto.init(); // loads ./veto/veto.config.yaml + rules
const guarded = veto.wrap(tools); // inject guardrails — types preserved
// pass guarded to your agent. done.

The agent is unaware it's being governed. Your tools are unchanged. No behavior change for the AI.

How it works

┌───────────┐         ┌────────────┐         ┌──────────────┐
│ AI Agent  │────────▶│    Veto    │────────▶│  Your Tools  │
│  (LLM)    │         │  (Guard)   │         │  (Handlers)  │
└───────────┘         └────────────┘         └──────────────┘
                            │
                      ┌─────┴──────┐
                      │ YAML Rules │  block · allow · ask
                      └────────────┘
  1. Agent calls a tool
  2. Veto intercepts and validates (deterministic conditions first, optional LLM for semantic rules)
  3. allow → executes normally · block → denied with reason · ask → human approval queue

Packages

Package Language Install Description
veto-sdk TypeScript npm install veto-sdk SDK for guarded agentic apps
veto Python pip install veto Same API, all major LLM providers
veto-cli TypeScript npm install -g veto-cli Interactive studio + headless automation
veto-bash Rust + Node npm install -g veto-bash Rust-first guarded bash runtime + MCP

Quick start

TypeScript

npm install veto-sdk
npx veto init       # creates ./veto/veto.config.yaml + default rules
import { Veto } from "veto-sdk";

const veto = await Veto.init();
const guarded = veto.wrap(myTools); // LangChain, Vercel AI SDK, or any custom tools

Python

pip install veto
veto init
from veto import Veto

veto = await Veto.init()
guarded = veto.wrap(my_tools)

Rules

Rules are YAML files in ./veto/rules/. Static conditions run locally with no API call. LLM validation is opt-in for semantic rules.

rules:
  - id: block-large-transfers
    name: Block transfers over $1,000
    action: block
    tools: [transfer_funds]
    conditions:
      - field: arguments.amount
        operator: greater_than
        value: 1000

  - id: require-approval-for-push
    name: Require human approval before pushing to main
    action: ask
    tools: [git_push]
    description: "Intercept any push targeting the main branch."

Actions: block · allow · warn · log · ask (human-in-the-loop)

Full TypeScript SDK docs · Python SDK docs

Economic authorization

For agents that spend money — trading bots, paid API calls, SaaS billing — Veto adds cost-aware policy enforcement.

# veto.config.yaml
extends: "@veto/economic-agent"
const result = await veto.guard(
  "purchase",
  { item: "GPU" },
  {
    economic: {
      cost: 42.5,
      currency: "USD",
      payer: "team-wallet",
      protocol: "custom",
    },
  }
);
// result.decision: 'allow' | 'deny' | 'require_approval'
// (YAML uses action: block/ask — guard() returns the resolved decision)

Built-in protocol connectors for x402 (HTTP 402), Stripe MPP, and Google AP2. Session budgets enforced locally; agent/user/global budgets via Veto Cloud.

Economic Authorization Guide →

CLI + Studio

npx veto-cli@latest                        # launch interactive Veto Studio (TUI)
npx veto-cli@latest policy generate \
  --tool transfer_funds \
  --prompt "block over $500 to unverified recipients"
npx veto-cli@latest guard check \
  --tool transfer_funds --args '{"amount": 600}' --json
npx veto-cli@latest scan --fail-uncovered  # CI gate: exit 1 on unguarded tools

Full CLI reference

Bash runtime + MCP

npm install -g veto-bash
mkdir -p "$HOME/.veto/bin"
VETO_BASH_NATIVE="$(veto-bash native-path)"
ln -sf "$VETO_BASH_NATIVE" "$HOME/.veto/bin/bash"
export PATH="$HOME/.veto/bin:$PATH"
export VETO_BASH_REAL_BASH=/bin/bash
VETO_API_KEY=veto_... bash -c 'echo hello'
veto-bash mcp init
veto-bash mcp serve --veto-api-key "$VETO_API_KEY"

veto-bash is now Rust-first: the native runtime handles bash interception, deterministic local evaluation, SWR cloud policy refresh, approval polling, audit spooling, and MCP stdio serving. Use veto-bash native-path once during setup, then shadow bash with that packaged native binary so warm executions stay fully native. Cold or unsupported cases fall back to cloud POST /v1/validate. Interactive shells still pass through to the real system bash.

This PR does not add a full cross-platform prebuilt binary pipeline yet. The current package/build flow is honest about that: build on the target platform or install an artifact produced for the same platform/arch.

Full veto-bash reference

Why Veto

  • Deterministic-first — Static conditions run locally, zero latency, no API call. LLM validation only when you need semantic reasoning.
  • Provider agnostic — Works with OpenAI, Anthropic, Google, LangChain, Vercel AI SDK, and any custom tool-calling setup.
  • Human-in-the-loopask action routes sensitive decisions to an approval queue instead of auto-blocking.
  • Audit trail — Every decision logged with tool name, arguments, rule matched, and outcome. Exportable as JSON or CSV.
  • Local-first — No cloud required. Fully offline. Optional Veto Cloud for team sync and dashboard.
  • Rate limiting — Per-rule sliding window rate limits. In-memory or Redis-backed for distributed deployments.
  • Zero-config defaultsveto init generates sensible baseline rules. Production-hardened in under 10 minutes.

Advanced features

Rate limiting

Attach sliding window rate limits to any rule. Scopes: global, agent, user, session.

rules:
  - id: rate-limit-api
    name: Limit API calls
    action: block
    tools: [call_api]
    rate_limits:
      - scope: user
        max_calls: 10
        window_seconds: 60

The default store is in-memory. For distributed deployments, plug in RedisRateLimitStore:

import { RedisRateLimitStore } from "veto-sdk";
const store = new RedisRateLimitStore(redisClient, "veto:rl:");

Audit chain

Every decision is appended to a tamper-evident hash chain. Each record's SHA-256 hash covers the previous hash plus the record's deterministic JSON serialization. Mutating any historical record invalidates all subsequent hashes.

import { computeChainHash, GENESIS_HASH } from "veto-sdk";

let prevHash = GENESIS_HASH;
const hash = computeChainHash(prevHash, {
  tool: "transfer_funds",
  decision: "allow",
});

Verify integrity from the CLI:

npx veto-cli audit verify

Policy testing

YAML fixture files validated against your policy with deterministic replay -- no LLM, no network.

# ./veto/tests/transfers.yaml
suite: Transfer rules
tests:
  - id: block-large-transfer
    tool: transfer_funds
    arguments: { amount: 5000 }
    expect:
      decision: block
      rule_id: block-large-transfers
npx veto-cli test              # run all fixtures
npx veto-cli test --coverage   # show untested rule IDs

SSE proxy

Intercept OpenAI and Anthropic streaming responses, validate tool calls against policies before forwarding to the client.

npx veto-cli intercept --port 8080 --target https://api.openai.com

Point your application at http://localhost:8080 instead of the provider URL. Supports auto-detection of OpenAI and Anthropic SSE formats.

OpenTelemetry

Optional @opentelemetry/api peer dependency. When installed, Veto instruments guard checks with spans. When not installed, all tracing functions are no-ops -- zero overhead.

Webhooks

Send decision events to external systems. Built-in formatters for Slack, PagerDuty, generic JSON, and CEF (ArcSight). Configure webhook endpoints per event type: tool_call_blocked, approval_requested, rate_limit_exceeded, and others.

skills.sh skill (coding agents)

npx skills add PlawIO/veto

Installs veto-policy-runtime — gives Claude Code, Cursor, and Windsurf safe, non-destructive policy operations without any SDK integration. Ideal for teams that want guardrails at the coding-agent level.

Real-world example: guarded MCP trading agent

Veto also fits agent runtimes outside coding workflows. One practical pattern is a Polymarket MCP server where market reads stay open, mutating tools are policy-gated, and larger actions route to approval before execution.

See the Guarded Polymarket MCP guide for the architecture and YAML rules, or the full reference implementation in PlawIO/polymarket-cli-veto.

Veto Cloud

The OSS SDK runs entirely local. Veto Cloud adds:

  • Natural language → policy YAML (no manual YAML writing)
  • Central policy sync across all team repos
  • Dashboard: decisions, blocked calls, pending approvals
  • Approval workflows for human-in-the-loop at scale
  • Rate limiting (in-memory + Redis)
  • Tamper-evident audit chain
  • OpenTelemetry tracing integration
  • SSO, audit export, compliance reporting

Contributing

See CONTRIBUTING.md. On your first PR, a bot will ask you to sign the CLA — takes 30 seconds, one comment.

Security

Report vulnerabilities to security@plaw.io. See SECURITY.md for the full disclosure policy.

License

Apache-2.0 © Plaw, Inc.

About

The authorization kernel for AI agents. Block, allow, or escalate agent tool calls with YAML rules — deterministic-first, LLM fallback.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors