Documentation Index Fetch the complete documentation index at: https://mintlify.com/plawio/veto/llms.txt
Use this file to discover all available pages before exploring further.
Veto rules are YAML files that define guardrails for AI agent tool calls. Rules can be deterministic (static conditions evaluated locally) or semantic (LLM-based validation for natural language policies).
Rule Structure
Every rule has these core fields:
rules :
- id : unique-rule-id # required: unique identifier
name : Human readable name # required: display name
enabled : true # optional: default true
severity : high # critical | high | medium | low | info
action : block # block | warn | log | allow | require_approval
tools : # optional: empty = applies to all tools
- tool_name
conditions : # optional: deterministic checks (AND logic)
- field : arguments.amount
operator : greater_than
value : 1000
description : "Optional semantic guidance for LLM validation"
Actions
Veto supports five action types:
Deny execution immediately. Tool call fails with a ToolCallDeniedError.Use for hard security boundaries (e.g., block production deployments, prevent rm -rf).
Route to human approval queue . Execution pauses until approved/denied via callback URL.Configure approval webhook in veto.config.yaml: approval :
callbackUrl : "http://localhost:8787/approvals"
timeout : 30000
timeoutBehavior : "block"
See Approval Workflows for full guide.
Log warning but allow execution . Useful for soft policy enforcement during testing.
Log decision only . No blocking, no warning. Ideal for audit trails and monitoring.
Explicitly permit . Useful for allowlists in combination with global block rules.
Rules apply to specific tools or all tools:
# Apply to specific tools
tools : [ transfer_funds , make_payment ]
# Apply to all tools (global rule)
tools : []
Example: Global rule with tool-specific override
rules :
# Global: require approval for everything
- id : global-approval
name : Default approval gate
action : require_approval
tools : [] # applies to all tools
# Override: allow read-only tools
- id : allow-reads
name : Allow safe reads
action : allow
tools : [ get_balance , read_file , list_directory ]
Conditions (Deterministic Rules)
Conditions run locally with zero latency . No LLM call. Use dot notation for nested fields.
Field Paths
field : arguments.amount # tool arguments
field : arguments.user.role # nested objects
field : context.time # built-in context (time, day_of_week)
All Operators
Equality
Strings
Numeric
Lists
Time Windows
# Exact match
- field : arguments.status
operator : equals
value : "approved"
# Not equal
- field : arguments.env
operator : not_equals
value : "production"
# Contains substring
- field : arguments.command
operator : contains
value : "rm -rf"
# Does not contain
- field : arguments.email
operator : not_contains
value : "@competitor.com"
# Starts with
- field : arguments.path
operator : starts_with
value : "/etc/"
# Ends with
- field : arguments.filename
operator : ends_with
value : ".env"
# Regex match
- field : arguments.url
operator : matches
value : "^https://[a-z]+ \\ .example \\ .com$"
# Greater than
- field : arguments.amount
operator : greater_than
value : 10000
# Less than
- field : arguments.retries
operator : less_than
value : 3
# Length greater than (arrays, strings, objects)
- field : arguments.recipients
operator : length_greater_than
value : 10
# Value in list
- field : arguments.region
operator : in
value : [ "us-east-1" , "us-west-2" ]
# Value not in list
- field : arguments.branch
operator : not_in
value : [ "main" , "master" , "production" ]
# Within business hours
- field : context.time
operator : within_hours
value :
start : "09:00"
end : "17:00"
timezone : "America/New_York"
days : [ "mon" , "tue" , "wed" , "thu" , "fri" ]
# Outside business hours
- field : context.time
operator : outside_hours
value :
start : "09:00"
end : "17:00"
timezone : "UTC"
Condition Logic
AND logic (all conditions must match):
conditions :
- field : arguments.amount
operator : greater_than
value : 1000
- field : arguments.to_account
operator : starts_with
value : "EXT-"
OR logic (any group matches):
condition_groups :
- # Group 1: high amount
- field : arguments.amount
operator : greater_than
value : 10000
- # Group 2: external recipient
- field : arguments.to_account
operator : starts_with
value : "EXT-"
Semantic Rules (LLM Validation)
For policies that can’t be expressed with static conditions, use semantic guidance :
- id : verify-recipient
name : Verify payment recipient
action : block
tools : [ transfer_funds ]
description : |
Block transfers to recipients that are not verified vendors in the system.
Check if the recipient is on the approved vendor list.
When conditions are absent or don’t match , Veto sends the rule’s name and description to the LLM for semantic validation.
Hybrid Rules
Combine deterministic + semantic:
- id : high-value-verification
name : High-value transfer verification
action : require_approval
tools : [ transfer_funds ]
conditions :
- field : arguments.amount
operator : greater_than
value : 10000
description : |
Require approval for large transfers. Ensure the recipient
is a known business partner and the reason is documented.
Execution flow :
Deterministic conditions checked first (fast, local)
If conditions match , rule triggers immediately
If conditions don’t match , LLM evaluates semantic description
Best Practices
Deterministic First Use static conditions whenever possible. Zero latency, no LLM cost. # Good: deterministic
- field : arguments.amount
operator : greater_than
value : 1000
# Avoid if deterministic works
description : "Block amounts over $1,000"
Specific Tool Scoping Narrow rule scope to relevant tools. Reduces false positives. # Specific
tools : [ git_push , deploy ]
# Too broad
tools : [] # applies to all tools
Explicit Severity Tag rules with severity for dashboards and alerting. severity : critical # production impact
severity : high # data/security risk
severity : medium # policy violation
severity : low # audit flag
Descriptive IDs Use kebab-case IDs that describe intent. # Good
id : block-external-transfers
id : require-approval-for-prod-deploy
# Avoid
id : rule1
id : temp-rule
Expression Syntax (Advanced)
Veto supports compiled policy expressions for complex logic:
conditions :
- expression : "arguments.amount > 10000 and arguments.to_account starts_with 'EXT-'"
Expressions support:
Boolean operators: and, or, not
Comparisons: >, <, >=, <=, ==, !=
String operators: starts_with, ends_with, contains
Grouping: (...)
Note: Expressions take precedence over field/operator/value when both are present.
Real-World Examples
Financial Transfers
Coding Agent
Browser Automation
After-Hours Restrictions
version : "1.0"
name : financial-policies
rules :
- id : block-large-transfers
name : Block Large Transfers
description : Transfers over $10,000 require manual approval
enabled : true
severity : high
action : block
tools : [ transfer_funds ]
conditions :
- field : arguments.amount
operator : greater_than
value : 10000
- id : block-external-transfers
name : Block External Transfers
description : Block transfers to external banks
enabled : true
severity : critical
action : block
tools : [ transfer_funds ]
conditions :
- field : arguments.to_account
operator : starts_with
value : "EXT-"
Testing Rules
Before deploying, test rules with veto guard check:
veto guard check --tool transfer_funds --args '{"amount": 15000}' --json
# {"decision":"block","rule":"block-large-transfers","reason":"amount exceeds $10,000"}
See Testing Policies for comprehensive testing workflows.
Next Steps
Approval Workflows Set up human-in-the-loop with approval callbacks
Audit Trail Export decisions as JSON/CSV for compliance
Testing Policies Write tests and validate rules before deployment
CI/CD Integration Enforce policy coverage in your build pipeline