Veto TypeScript SDK
Native TypeScript SDK for AI agent authorization. Works with OpenAI, Anthropic, Vercel AI SDK, LangChain.js, and MCP. Type-safe, zero dependencies in local mode, two lines of code to add runtime guardrails.
TypeScript AI agent guardrails with veto-sdk
The Veto TypeScript SDK provides runtime authorization for AI agents built in JavaScript or TypeScript. It intercepts tool calls before execution, validates them against your policies, and enforces allow/deny/approval decisions. Works with OpenAI, Anthropic, Vercel AI SDK, LangChain.js, MCP, and custom agents. Runs in Node.js, Deno, Bun, Cloudflare Workers, and Vercel Edge.
Installation
npm install veto-sdk
Also available via pnpm add veto-sdk, yarn add veto-sdk, or bun add veto-sdk. Zero runtime dependencies in local mode. Cloud mode requires network access.
Quick start
The protect function wraps any tool definition and returns a guarded version with identical types. The wrapped tools are drop-in replacements.
import { protect } from 'veto-sdk';
const tools = [
{
name: 'transfer_funds',
description: 'Transfer money between accounts',
parameters: {
type: 'object',
properties: {
amount: { type: 'number' },
recipient: { type: 'string' },
},
required: ['amount', 'recipient'],
},
execute: async (args: { amount: number; recipient: string }) => {
// Your transfer logic
return { success: true, txId: 'tx_...' };
},
},
];
// Add guardrails in one line
const safeTools = await protect(tools);OpenAI integration
Wrap OpenAI function calling tools directly. The SDK understands OpenAI's tool format and returns compatible definitions.
import OpenAI from 'openai';
import { protect } from 'veto-sdk';
const client = new OpenAI();
const tools = await protect([
{
type: 'function',
function: {
name: 'search_database',
description: 'Query the customer database',
parameters: {
type: 'object',
properties: {
query: { type: 'string' },
include_pii: { type: 'boolean' },
},
required: ['query'],
},
},
},
{
type: 'function',
function: {
name: 'send_notification',
description: 'Send a push notification to a user',
parameters: {
type: 'object',
properties: {
user_id: { type: 'string' },
message: { type: 'string' },
},
required: ['user_id', 'message'],
},
},
},
]);
const response = await client.chat.completions.create({
model: 'gpt-5.4',
messages: [{ role: 'user', content: 'Look up order #4521 and notify the customer' }],
tools,
});Anthropic Claude integration
Works with Anthropic's tool use format. Wrap tool definitions before passing them to Claude. The SDK handles the format differences between providers.
import Anthropic from '@anthropic-ai/sdk';
import { protect } from 'veto-sdk';
const client = new Anthropic();
const tools = await protect([
{
name: 'execute_sql',
description: 'Run a SQL query against the database',
input_schema: {
type: 'object',
properties: {
query: { type: 'string', description: 'SQL query to execute' },
database: { type: 'string', enum: ['analytics', 'production'] },
},
required: ['query', 'database'],
},
},
]);
const response = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Get last month revenue from analytics' }],
tools,
});
// Handle tool use blocks
for (const block of response.content) {
if (block.type === 'tool_use') {
// Veto already validated this call. Execute safely.
const result = await executeQuery(block.input);
}
}Vercel AI SDK integration
Use veto.guard() inside Vercel AI tool execute functions for pre-flight validation. Works with streaming responses and all Vercel AI providers.
import { openai } from '@ai-sdk/openai';
import { generateText, tool } from 'ai';
import { Veto } from 'veto-sdk';
import { z } from 'zod';
const veto = await Veto.init();
const result = await generateText({
model: openai('gpt-5.4'),
tools: {
weather: tool({
description: 'Get weather for a location',
parameters: z.object({
location: z.string(),
}),
execute: async ({ location }) => {
// Pre-flight check before execution
const decision = await veto.guard('weather', { location });
if (decision.decision === 'deny') {
return { error: decision.reason };
}
return fetchWeather(location);
},
}),
sendEmail: tool({
description: 'Send an email',
parameters: z.object({
to: z.string().email(),
subject: z.string(),
body: z.string(),
}),
execute: async (args) => {
const decision = await veto.guard('sendEmail', args);
if (decision.decision === 'deny') {
return { error: decision.reason };
}
return sendEmail(args);
},
}),
},
prompt: 'Check weather in NYC and email the report to team@company.com',
});Initialization modes
The SDK supports multiple initialization patterns depending on your deployment needs.
Local mode (default)
No API key required. Policies loaded from your local ./veto config directory.
import { Veto } from 'veto-sdk';
// Local mode: no API key, policies from ./veto directory
const veto = await Veto.init();
const safeTools = veto.wrap(tools);Cloud mode
Policies managed in the Veto dashboard. Supports human-in-the-loop approvals, team collaboration, and real-time policy updates.
import { Veto } from 'veto-sdk';
// Cloud mode: dashboard-managed policies, approval workflows
const veto = await Veto.init({
apiKey: 'veto_...',
onApprovalRequired: (context, approvalId) => {
console.log(`Tool "${context.toolName}" needs approval (id: ${approvalId})`);
// Notify Slack, email, or in-app
},
});
const safeTools = veto.wrap(tools);Policy packs
Pre-built policy packs for common use cases. Start with sensible defaults, customize as needed.
import { protect } from 'veto-sdk';
// Financial transactions with built-in limits
const safeTools = await protect(tools, { pack: 'financial' });
// Browser automation guardrails
const safeBrowserTools = await protect(browserTools, { pack: 'browser' });
// File system operations
const safeFileTools = await protect(fileTools, { pack: 'filesystem' });Operating modes
Control how the SDK handles policy violations during development and rollout.
import { protect } from 'veto-sdk';
// strict (default) - Block violations, throw ToolCallDeniedError
const strict = await protect(tools, { mode: 'strict' });
// log - Allow execution but log violations for monitoring
const logging = await protect(tools, { mode: 'log' });
// shadow - Allow, log, and track what would have been blocked
const shadow = await protect(tools, { mode: 'shadow' });Standalone validation
Use guard to validate tool calls without wrapping. Returns a decision object for conditional logic, custom workflows, or pre-flight checks.
import { Veto } from 'veto-sdk';
const veto = await Veto.init();
// Pre-flight validation without wrapping
const result = await veto.guard('transfer_funds', {
amount: 25000,
recipient: 'vendor-123',
});
if (result.decision === 'deny') {
console.log('Blocked:', result.reason);
console.log('Rule:', result.ruleId);
console.log('Severity:', result.severity);
}
if (result.decision === 'require_approval') {
console.log('Needs approval:', result.approvalId);
// Poll or webhook for approval status
}Error handling
In strict mode, blocked tool calls throw typed errors you can catch and handle. Return the error to the LLM so it can retry with compliant parameters.
import { ToolCallDeniedError, BudgetExceededError } from 'veto-sdk';
try {
await safeTools[0].execute({ amount: 50000, recipient: '...' });
} catch (error) {
if (error instanceof ToolCallDeniedError) {
console.log('Tool:', error.toolName);
console.log('Reason:', error.reason);
console.log('Rule:', error.ruleId);
// Return error to the LLM so it can retry with different params
}
if (error instanceof BudgetExceededError) {
console.log('Budget:', error.spent, '/', error.limit);
// Agent should stop spending operations
}
}Edge runtime support
The SDK uses standard Web APIs and works in any JavaScript runtime. Deploy guarded agents to Cloudflare Workers, Vercel Edge Functions, Deno Deploy, or Bun.
// Works in Node.js, Deno, Bun, Cloudflare Workers, Vercel Edge
import { protect } from 'veto-sdk';
export default {
async fetch(request: Request): Promise<Response> {
const safeTools = await protect(myTools);
// Process the request with guarded tools
const result = await runAgent(safeTools, request);
return new Response(JSON.stringify(result));
},
};Framework integrations
First-class integrations with popular TypeScript agent frameworks.
Features
Full TypeScript types. Wrapped tools have identical signatures to originals.
Local mode has no runtime dependencies. Cloud mode adds a single HTTP client.
Policies evaluate locally with no network latency. Sub-millisecond overhead.
Node.js, Deno, Bun, Cloudflare Workers, Vercel Edge. Standard Web APIs.
Frequently asked questions
How do I add guardrails to existing TypeScript agents?
Can I use veto-sdk without an API key?
Does the SDK work with streaming responses?
How do I test guardrails in development?
What runtimes are supported?
Related
Add guardrails to your TypeScript agent in minutes.