Skip to content

PlawIO/veto

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

352 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Veto

Veto is the policy runtime for AI agent tool calls — write deny rules in plain English, enforce them deterministically, in 5 lines of code.

npm veto-sdk PyPI License

Veto sits between an agent and the tools it can execute. It evaluates tool name + arguments against deterministic policy, then allows, denies, warns, logs, or routes to approval before your handler runs. It governs tool calls, not prompts.

Benchmarks

Checked-in PR-mode baselines are measured on GitHub Actions runner output, not local hardware or thresholds. CI gates Veto p99 regressions above 10% against benchmark/baselines/*.json; absolute thresholds remain separate.

Runtime Workload Iterations p50 p95 p99 p99 threshold Source
Veto single-rule local eval 50,000 0.000260ms 0.001092ms 0.002594ms 0.05ms measured on GitHub Actions PR-mode, PR #208 CI log
Veto 100-rule merged packs 50,000 0.027291ms 0.037470ms 0.057136ms 0.5ms measured on GitHub Actions PR-mode, PR #212 CI log
Veto localhost PDP server eval 250 0.402051ms 0.841651ms 2.092263ms 30ms local loopback fixture baseline; not run in PR mode
AGT policy eval latency per rule published 0.012ms/rule not published not published n/a source: published, not reproduced
AGT throughput at 50 concurrent agents published 35K ops/sec not published not published n/a source: published, not reproduced

Get started

import { protect } from "veto-sdk";
const safeTools = await protect(tools);
npm install veto-sdk

Pass safeTools to LangChain, LangGraph, Vercel AI SDK, OpenAI Agents, MCP adapters, Claude SDK, Google ADK, Mastra, AutoGen, CrewAI, or your own tool runner. If ./veto/veto.config.yaml and ./veto/rules/*.yaml exist, protect() loads them. Without local policy, Veto applies @veto/safe-defaults in observe mode so suspicious shell/file/db/money-movement patterns are logged without surprise blocking.

The unscoped veto npm name is not controlled by Plaw yet; use the owned veto-cli package form until transfer completes.

For a blocking local policy in under a minute:

npm install veto-sdk
npx --package veto-cli@latest veto init
npx --package veto-cli@latest veto policy generate --tool bash --prompt "block rm -rf" --save ./veto/rules/block-rm-rf.yaml
node examples/60-second-denied-call/denied-call.mjs

This path is local-only: no provider SDK or API key is required. For prose generation, Veto tries configured cloud/self-hosted/kernel endpoints first, then uses a local deterministic template fallback with review warnings; in fallback, no prompt or policy data leaves your machine.

Install Veto into developer tools and MCP clients:

npx --package veto-cli@latest veto install claude-code
npx --package veto-cli@latest veto install cursor
npx --package veto-cli@latest veto install codex
veto-mcp-proxy --config ./veto/mcp.config.yaml

Runtime adapter matrix

Runtime Artifact Status
Provider-agnostic tools protect(tools), Veto.wrap() Canonical path
Vercel AI SDK veto-sdk/integrations/vercel-ai middleware + guard helper Supported
OpenAI Agents veto-sdk/integrations/openai-agents guardrails + guard helper Supported
LangChain / LangGraph veto-sdk/integrations/langchain middleware, ToolNode, guard helper Supported
MCP provider adapters + Veto.wrapMCPTools() Supported
Browser Use veto-sdk/integrations/browser-use Supported
OpenClaw veto-sdk/integrations/openclaw hooks Supported
Claude SDK veto-sdk/integrations/claude-sdk Anthropic tool-use helpers Added P2
Google ADK veto-sdk/integrations/google-adk function declaration/call helpers Added P2
Mastra veto-sdk/integrations/mastra tool wrappers Added P2
AutoGen veto-sdk/integrations/autogen function/tool wrappers Added P2
CrewAI veto-sdk/integrations/crewai tool-function wrappers Added P2

TypeScript

npm install veto-sdk
import { protect } from "veto-sdk";

const safeTools = await protect(tools);
const agent = createAgent({ tools: safeTools });

Python

pip install veto
from veto import protect

safe = await protect(tools)
agent = create_agent(tools=safe)

Add local deny rules

npx --package veto-cli@latest veto init

npx --package veto-cli@latest veto init creates ./veto/veto.config.yaml and ./veto/rules/defaults.yaml. The default local rules are strict and include deterministic denials for sensitive paths and destructive shell commands.

Prefer prose for new rules, then review the generated YAML:

npx --package veto-cli@latest veto policy generate --tool bash --prompt "block rm -rf" --save ./veto/rules/block-rm-rf.yaml
rules:
  - id: block-large-transfers
    name: Block transfers over $1,000
    enabled: true
    severity: high
    action: block
    tools: [transfer_funds]
    conditions:
      - field: arguments.amount
        operator: greater_than
        value: 1000

Actions: block, allow, warn, log, require_approval.

Advanced API

Veto.init() and .wrap() remain supported for advanced/internal-facing integrations that need an explicit instance, guard() checks, cloud/self-host options, audit exports, or event hooks.

import { Veto } from "veto-sdk";

const veto = await Veto.init({ configDir: "./veto", mode: "strict" });
const safeTools = veto.wrap(tools);
const decision = await veto.guard("transfer_funds", { amount: 1500 });

Packages

Package Language Install Purpose
packages/veto TypeScript local workspace only Reserved/local wrapper pending npm-name transfer
veto-sdk TypeScript npm install veto-sdk Policy runtime for agent tool calls
veto (Python) Python pip install veto Python parity SDK with protect()
veto-cli TypeScript npx --package veto-cli@latest veto init Currently published CLI package exposing veto
veto-bash Rust + Node npm install --global veto-bash Native bash tool-call enforcement path
create-veto-app TypeScript npm create veto-app Starter TypeScript app

Self-host locally

docker compose up
curl -s http://localhost:3001/v1/validate \
  -H 'content-type: application/json' \
  -d '{"toolName":"bash","arguments":{"command":"echo hello"}}'

See docs/self-hosting.md for the public reviewer path, fixed localhost:3001 compose mapping, disabled-by-default outbound checks, and the local unauthenticated validation contract.

BYOC / customer-plane boundary

Veto BYOC runs in the customer plane. Public install artifacts are in helm/, terraform-modules/, cf-templates/, and cdk/. They are outbound-only and must not grant Plaw cross-account IAM or impersonation. Customer policy, decision rows, tool arguments, agent IDs, user IDs, Slack content, prompts, environment variables, and secrets do not cross to Plaw.

Allowed outbound control-plane checks are limited to license heartbeat and optional telemetry. The heartbeat schema is exactly six fields: instance_uuid, license_id, decision_count_30d, sdk_version, operator_version, timestamp.

Install docs:

Why Veto

  • Deterministic local evaluation for policy rules that can be checked from tool arguments.
  • Provider-agnostic wrapping for any agent framework or custom tool runner.
  • Human approval and cost-aware governance for sensitive tool calls.
  • Local-first operation with optional self-hosted or cloud policy distribution.
  • Apache-2.0 licensed packages and public supply-chain verification artifacts.

Contributing

See CONTRIBUTING.md. Report vulnerabilities to security@plaw.io.

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