The Veto TypeScript SDK provides guardrails for AI agent tool calls. It intercepts and validates tool calls before execution, blocking, allowing, or routing to human approval based on your policies.
Installation
Quick Start
import { Veto } from 'veto-sdk' ;
// Initialize Veto
const veto = await Veto . init ();
// Wrap your tools
const wrappedTools = veto . wrap ( myTools );
// Use with your agent framework
const agent = createAgent ({ tools: wrappedTools });
Core API
Veto.init()
Initialize a Veto instance by loading configuration and rules.
static async init ( options ?: VetoOptions ): Promise < Veto >
Optional configuration options Path to the veto directory containing config and rules
mode
'strict' | 'log' | 'shadow'
default: "strict"
Operating mode:
strict: Block denied tool calls
log: Only log denials, allow execution
shadow: Compute decisions but never block
logLevel
'debug' | 'info' | 'warn' | 'error' | 'silent'
default: "info"
Log verbosity level
Session ID for tracking (can also use VETO_SESSION_ID env var)
Agent ID for tracking (can also use VETO_AGENT_ID env var)
User ID for tracking (can also use VETO_USER_ID env var)
Role for tracking (can also use VETO_ROLE env var)
validators
Array<Validator | NamedValidator>
Additional custom validators to run
API key for cloud mode (can also use VETO_API_KEY env var)
Cloud endpoint override for self-hosted deployments
onApprovalRequired
(context, approvalId) => void | Promise<void>
Hook called when a tool call requires human approval
Examples
Default (local rules)
Custom directory
Cloud mode
Self-hosted
With tracking
const veto = await Veto . init ();
veto.wrap()
Wrap an array of tools with Veto validation. Types are preserved for framework compatibility.
Array of tools to wrap. Works with any tool format (LangChain, Vercel AI SDK, custom).
Wrapped tools with validation injected. Same type as input.
Examples
LangChain
Vercel AI SDK
Custom tools
import { tool } from '@langchain/core/tools' ;
import { Veto } from 'veto-sdk' ;
const tools = [
tool ( async ({ query }) => {
return searchDatabase ( query );
}, {
name: 'search_database' ,
description: 'Search the database' ,
schema: z . object ({ query: z . string () })
})
];
const veto = await Veto . init ();
const wrappedTools = veto . wrap ( tools );
// Use with LangChain agent
const agent = createReactAgent ({ llm , tools: wrappedTools });
Wrap a single tool with Veto validation.
Wrapped tool with validation injected
const safeTool = veto . wrapTool ( myTool );
Alternative API that returns both definitions and implementations.
wrapTools ( tools : ToolDefinition []): WrappedTools
Array of tool definitions with schemas
Object containing definitions and implementations Tool schemas to pass to AI provider
implementations
Record<string, WrappedHandler>
Handler functions keyed by tool name
const { definitions , implementations } = veto . wrapTools ( myTools );
// Pass definitions to AI provider
const response = await openai . chat . completions . create ({
tools: toOpenAITools ( definitions ),
messages: [ ... ]
});
// Execute with implementations
for ( const call of response . choices [ 0 ]. message . tool_calls ) {
const result = await implementations [ call . function . name ](
JSON . parse ( call . function . arguments )
);
}
veto.guard()
Standalone validation without execution. Useful for checking if a call would be allowed.
async guard (
toolName : string ,
args : Record < string , unknown > ,
context ?: GuardContext
): Promise < GuardResult >
Name of the tool to validate
args
Record<string, unknown>
required
Arguments to validate
Optional context for validation Session ID for this check
decision
'allow' | 'deny' | 'require_approval'
required
Validation decision
Human-readable reason for the decision
severity
'critical' | 'high' | 'medium' | 'low' | 'info'
Severity level from the matched rule
Approval ID if decision is require_approval
Whether this was evaluated in shadow mode
const result = await veto . guard ( 'transfer_funds' , {
amount: 5000 ,
recipient: 'vendor-123'
});
if ( result . decision === 'deny' ) {
console . log ( `Would be blocked: ${ result . reason } ` );
}
History & Export
veto.getHistoryStats()
Get statistics about tool call history.
getHistoryStats (): HistoryStats
Total number of tool calls validated
const stats = veto . getHistoryStats ();
console . log ( `Blocked ${ stats . deniedCalls } out of ${ stats . totalCalls } calls` );
veto.clearHistory()
Clear the call history.
veto.exportDecisions()
Export decision history in JSON or CSV format.
exportDecisions ( format : 'json' | 'csv' ): string
Serialized decision history
const json = veto . exportDecisions ( 'json' );
const csv = veto . exportDecisions ( 'csv' );
fs . writeFileSync ( 'decisions.json' , json );
fs . writeFileSync ( 'decisions.csv' , csv );
protect() Function
One-step wrapper for simple use cases. Automatically detects configuration source and applies appropriate policies.
import { protect } from 'veto-sdk' ;
async function protect < T extends { name : string }>(
tools : T | T [],
options ?: ProtectOptions
) : Promise < T | T []>
Tool or array of tools to protect
Built-in policy pack to apply (e.g., ‘financial’, ‘browser-automation’)
mode
'strict' | 'log' | 'shadow'
Operating mode
Examples
Auto-detect (heuristic packs)
Explicit pack
Inline rules
Cloud mode
import { protect } from 'veto-sdk' ;
const tools = [
{ name: 'transfer_funds' , handler : async ( args ) => { ... } },
{ name: 'navigate' , handler : async ( args ) => { ... } }
];
// Automatically applies @veto/financial and @veto/browser-automation packs
const protected = await protect ( tools );
Framework Integrations
LangChain
Middleware
Tool Node
Callback
import { createVetoLangChainMiddleware } from 'veto-sdk/integrations/langchain' ;
import { Veto } from 'veto-sdk' ;
const veto = await Veto . init ();
const middleware = createVetoLangChainMiddleware ( veto , {
throwOnDeny: true ,
onAllow : ( toolName , args ) => console . log ( `Allowed: ${ toolName } ` ),
onDeny : ( toolName , args , reason ) => console . log ( `Denied: ${ toolName } ` )
});
// Use with LangChain tool nodes
const agent = createReactAgent ({ llm , tools: [ middleware ] });
import { createVetoToolNode } from 'veto-sdk/integrations/langchain' ;
import { ToolNode } from '@langchain/langgraph/prebuilt' ;
const veto = await Veto . init ();
const toolNode = new ToolNode ( tools );
const vetoNode = createVetoToolNode ( veto , toolNode );
// Use in LangGraph
const graph = new StateGraph ()
. addNode ( 'tools' , vetoNode )
. addEdge ( 'agent' , 'tools' );
import { createVetoCallbackHandler } from 'veto-sdk/integrations/langchain' ;
const handler = createVetoCallbackHandler ({
onToolStart : ( toolName , input ) => console . log ( `Starting: ${ toolName } ` ),
onToolEnd : ( toolName , output ) => console . log ( `Completed: ${ toolName } ` ),
onToolError : ( toolName , error ) => console . error ( `Error: ${ toolName } ` )
});
await agent . invoke ({ input: 'Transfer funds' }, { callbacks: [ handler ] });
Vercel AI SDK
import { createVetoMiddleware } from 'veto-sdk/integrations/vercel-ai' ;
import { Veto } from 'veto-sdk' ;
const veto = await Veto . init ();
const middleware = createVetoMiddleware ( veto , {
throwOnDeny: true ,
onAllow : ( toolName , args ) => console . log ( `Allowed: ${ toolName } ` ),
onDeny : ( toolName , args , reason ) => console . log ( `Denied: ${ toolName } ` )
});
const result = await generateText ({
model ,
tools ,
prompt: 'Send an email' ,
experimental_providerMetadata: {
veto: middleware
}
});
Provider Adapters
Convert between Veto’s tool format and provider-specific formats.
OpenAI
import { toOpenAI , fromOpenAI , toOpenAITools } from 'veto-sdk' ;
// Convert to OpenAI format
const openaiTools = toOpenAITools ( vetoDefinitions );
// Convert from OpenAI tool call
const vetoCall = fromOpenAI ( openaiToolCall );
Anthropic
import { toAnthropic , fromAnthropic , toAnthropicTools } from 'veto-sdk' ;
const anthropicTools = toAnthropicTools ( vetoDefinitions );
const vetoCall = fromAnthropic ( anthropicToolUse );
Google
import { toGoogleTool , fromGoogleFunctionCall } from 'veto-sdk' ;
const googleTool = toGoogleTool ( vetoDefinition );
const vetoCall = fromGoogleFunctionCall ( googleCall );
MCP (Model Context Protocol)
import { toMCP , fromMCP , toMCPTools } from 'veto-sdk' ;
const mcpTools = toMCPTools ( vetoDefinitions );
const vetoCall = fromMCP ( mcpToolCall );
Error Handling
Thrown when a tool call is blocked in strict mode.
import { ToolCallDeniedError } from 'veto-sdk' ;
try {
await wrappedTool . handler ({ amount: 10000 });
} catch ( error ) {
if ( error instanceof ToolCallDeniedError ) {
console . error ( `Tool call denied: ${ error . message } ` );
console . error ( `Reason: ${ error . reason } ` );
console . error ( `Tool: ${ error . toolName } ` );
}
}
ApprovalTimeoutError
Thrown when approval flow times out.
import { ApprovalTimeoutError } from 'veto-sdk' ;
try {
await wrappedTool . handler ( args );
} catch ( error ) {
if ( error instanceof ApprovalTimeoutError ) {
console . error ( 'Approval timed out' );
}
}
Configuration Types
VetoOptions
interface VetoOptions {
configDir ?: string ;
mode ?: 'strict' | 'log' | 'shadow' ;
logLevel ?: 'debug' | 'info' | 'warn' | 'error' | 'silent' ;
sessionId ?: string ;
agentId ?: string ;
userId ?: string ;
role ?: string ;
validators ?: Array < Validator | NamedValidator >;
apiKey ?: string ;
endpoint ?: string ;
kernelClient ?: KernelClient ;
cloudClient ?: VetoCloudClient ;
onApprovalRequired ?: ( context : ValidationContext , approvalId : string ) => void | Promise < void >;
}
Validator
Custom validation function.
type Validator = (
context : ValidationContext
) => ValidationResult | Promise < ValidationResult >;
interface NamedValidator {
name : string ;
description ?: string ;
validate : Validator ;
priority ?: number ;
toolFilter ?: string [];
}
Example
const noDeleteValidator : NamedValidator = {
name: 'no-delete' ,
description: 'Block all delete operations' ,
priority: 10 ,
validate : async ( context ) => {
if ( context . toolName . includes ( 'delete' )) {
return {
decision: 'deny' ,
reason: 'Delete operations are not allowed'
};
}
return { decision: 'allow' };
}
};
const veto = await Veto . init ({
validators: [ noDeleteValidator ]
});
Advanced Features
Budget Tracking
const veto = await Veto . init ({
configDir: './veto'
});
// In veto.config.yaml:
// budget:
// max: 100.00
// currency: USD
// window: session
// costs:
// transfer_funds: 10.00
// send_email: 0.50
const status = veto . getBudgetStatus ();
console . log ( `Used: ${ status . used } / ${ status . max } ` );
Event Webhooks
// In veto.config.yaml:
// events:
// webhook:
// url: https://example.com/veto-events
// on:
// - decision
// - approval_required
// min_severity: high
// format: slack
const veto = await Veto . init ();
// Events automatically sent to webhook
Output Validation
Validate tool outputs against patterns.
# In veto/rules/output.yaml
output_rules :
- id : redact-ssn
name : Redact SSNs from output
action : redact
tools :
- fetch_user_data
patterns :
- '\d{3}-\d{2}-\d{4}'
TypeScript Types
The SDK is fully typed with TypeScript. Import types as needed:
import type {
VetoOptions ,
VetoMode ,
ValidationMode ,
WrappedTools ,
WrappedHandler ,
GuardContext ,
GuardResult ,
ToolDefinition ,
ToolCall ,
ToolResult ,
ValidationContext ,
ValidationResult ,
ValidationDecision ,
LogLevel
} from 'veto-sdk' ;