SDK Reference
Unified API reference with TypeScript and Python implementations for each function.
This page is aligned with the current SDK source in veto-sdk/packages/sdk and veto-sdk/packages/sdk-python.
Use the language tabs on any section. Selection is shared across the page, so switching once updates all function examples.
Installation
npm install veto-sdkpip install veto
pip install veto[all]Wrapped execution enforces both:
- input
rulesbefore tool execution - output
output_rulesafter tool execution, before returning tool output
Veto.init(options?)
import { Veto } from 'veto-sdk';
const vetoLocal = await Veto.init();
const vetoCloud = await Veto.init({ apiKey: 'veto_...' });
const vetoSelfHosted = await Veto.init({ endpoint: 'https://veto.internal.example.com' });
const vetoWithIdentity = await Veto.init({
agentId: 'support-agent',
userId: 'user-123',
role: 'analyst',
});from veto import Veto, VetoOptions
veto_local = await Veto.init()
veto_cloud = await Veto.init(VetoOptions(api_key='veto_...'))
veto_self_hosted = await Veto.init(VetoOptions(base_url='https://veto.internal.example.com'))
veto_with_identity = await Veto.init(
VetoOptions(
agent_id='support-agent',
user_id='user-123',
role='analyst',
)
)Common identity options:
- TypeScript:
sessionId,agentId,userId,role - Python:
session_id,agent_id,user_id,role
These identity values are propagated through ValidationContext and guard/cloud validation context payloads.
veto.validateOutput(toolName, output) / veto.validate_output(tool_name, output)
Run standalone output validation/redaction without executing a wrapped tool.
const result = veto.validateOutput('fetch_account', {
contact: { email: 'alice@example.com' },
});
if (result.decision === 'block') {
throw new Error(result.reason);
}
console.log(result.output);OutputValidationResult fields:
decision:'allow' | 'block'output: transformed output (ornullwhen blocked)reason?: block reasonmatchedRuleIds:string[]redactions:number
result = veto.validate_output(
"fetch_account",
{"contact": {"email": "alice@example.com"}},
)
if result.decision == "block":
raise RuntimeError(result.reason)
print(result.output)OutputValidationResult fields:
decision:'allow' | 'block'output: transformed output (orNonewhen blocked)reason:str | Nonematched_rule_ids:list[str] | Noneredactions:int
veto.wrap(tools)
const wrappedTools = veto.wrap(tools);wrapped_tools = veto.wrap(tools)veto.wrapTool(tool) / veto.wrap_tool(tool)
const safeTool = veto.wrapTool(myTool);safe_tool = veto.wrap_tool(my_tool)veto.guard(...)
Run Veto validation as a standalone check without wrapping or executing a tool.
import { Veto, type GuardResult } from 'veto-sdk';
const result: GuardResult = await veto.guard(
'wire_transfer',
{ amount: 25000 },
{
sessionId: 'session-42',
agentId: 'agent-7',
userId: 'user-99',
role: 'admin',
}
);
if (result.decision === 'require_approval') {
console.log(result.approvalId);
}GuardResult fields:
decision:'allow' | 'deny' | 'require_approval'reason?: stringruleId?: stringseverity?:'critical' | 'high' | 'medium' | 'low' | 'info'approvalId?: string
from veto import GuardResult
result: GuardResult = await veto.guard(
"wire_transfer",
{"amount": 25000},
session_id="session-42",
agent_id="agent-7",
user_id="user-99",
role="admin",
)
if result.decision == "require_approval":
print(result.approval_id)GuardResult fields:
decision:'allow' | 'deny' | 'require_approval'reason:str | Nonerule_id:str | Noneseverity:'critical' | 'high' | 'medium' | 'low' | 'info' | Noneapproval_id:str | None
Guard semantics
- Uses the same internal validation engine as wrapped tool execution.
- Records guard checks in history.
- Returns deny/approval outcomes instead of throwing
ToolCallDeniedError. - In log mode,
guard()still returns real policy verdicts (it does not convert denies to allows). - Per-call identity overrides are supported (
sessionId/agentId/userId/rolein TypeScript,session_id/agent_id/user_id/rolein Python).
veto.getHistoryStats() / veto.get_history_stats()
const stats = veto.getHistoryStats();
// { totalCalls, allowedCalls, deniedCalls, ... }stats = veto.get_history_stats()
# {"total_calls": ..., "allowed_calls": ..., "denied_calls": ...}veto.clearHistory() / veto.clear_history()
veto.clearHistory();veto.clear_history()veto.setApprovalPreference(...) / veto.set_approval_preference(...)
veto.setApprovalPreference('read_file', 'approve_all');
veto.setApprovalPreference('delete_database', 'deny_all');veto.set_approval_preference('read_file', 'approve_all')
veto.set_approval_preference('delete_database', 'deny_all')veto.getApprovalPreference(...) / veto.get_approval_preference(...)
const pref = veto.getApprovalPreference('read_file');
// 'approve_all' | 'deny_all' | undefinedpref = veto.get_approval_preference('read_file')
# 'approve_all' | 'deny_all' | Noneveto.clearApprovalPreferences(...) / veto.clear_approval_preferences(...)
veto.clearApprovalPreferences('read_file');
veto.clearApprovalPreferences();veto.clear_approval_preferences('read_file')
veto.clear_approval_preferences()veto.wrapMCPTools(...) (TypeScript only)
const { tools, callTool } = veto.wrapMCPTools(mcpTools, mcpServer);
const result = await callTool({
name: 'read_file',
arguments: { path: '/tmp/example.txt' },
});# Not available in the Python SDK.
# Use veto.wrap(...) / veto.wrap_tool(...) with Python tool objects.veto.registerTools(...) (TypeScript only)
await veto.registerTools([
{
name: 'send_email',
description: 'Send an email',
parameters: [
{ name: 'to', type: 'string', required: true },
{ name: 'subject', type: 'string', required: true },
],
},
]);# Not exposed as a top-level Veto method in Python.
# Python auto-registers signatures when you call veto.wrap(...).veto.getBudgetStatus() / veto.resetBudget() (TypeScript only)
const budget = veto.getBudgetStatus();
// { spent, limit, remaining, currency } | null
veto.resetBudget();# Budget tracker APIs are not available in the Python SDK.ToolCallDeniedError
import { ToolCallDeniedError } from 'veto-sdk';
try {
await wrappedTool.invoke(args);
} catch (error) {
if (error instanceof ToolCallDeniedError) {
console.log(error.toolName);
console.log(error.reason);
console.log(error.callId);
}
}from veto.core.interceptor import ToolCallDeniedError
try:
await wrapped_tool.ainvoke(args)
except ToolCallDeniedError as error:
print(error.tool_name)
print(error.reason)
print(error.call_id)ApprovalTimeoutError
import { ApprovalTimeoutError } from 'veto-sdk';
try {
await client.pollApproval('apr_abc123', {
pollInterval: 2000,
timeout: 300000,
});
} catch (error) {
if (error instanceof ApprovalTimeoutError) {
console.log(error.approvalId);
console.log(error.timeoutMs);
}
}from veto.cloud.client import ApprovalTimeoutError
try:
await client.poll_approval('apr_abc123')
except ApprovalTimeoutError as error:
print(error.approval_id)
print(error.timeout)BudgetExceededError (TypeScript only)
import { BudgetExceededError } from 'veto-sdk';
try {
await wrappedTool.invoke(args);
} catch (error) {
if (error instanceof BudgetExceededError) {
console.log(error.spent);
console.log(error.limit);
console.log(error.remaining);
console.log(error.toolName);
console.log(error.toolCost);
}
}# BudgetExceededError is not currently exposed by the Python SDK.VetoCloudClient
import { VetoCloudClient } from 'veto-sdk';
const client = new VetoCloudClient({
config: {
apiKey: 'veto_abc123...',
baseUrl: 'https://api.runveto.com',
timeout: 30000,
retries: 2,
retryDelay: 1000,
},
logger,
});from veto.cloud.client import VetoCloudClient, VetoCloudConfig
client = VetoCloudClient(
VetoCloudConfig(
api_key='veto_abc123...',
base_url='https://api.runveto.com',
timeout=30000,
retries=2,
retry_delay=1000,
)
)client.registerTools(...) / client.register_tools(...)
await client.registerTools([
{
name: 'send_email',
description: 'Send an email',
parameters: [
{ name: 'to', type: 'string', required: true },
{ name: 'subject', type: 'string', required: true },
{ name: 'body', type: 'string', required: true },
],
},
]);from veto.cloud.types import ToolRegistration, ToolParameter
await client.register_tools([
ToolRegistration(
name='send_email',
description='Send an email',
parameters=[
ToolParameter(name='to', type='string', required=True),
ToolParameter(name='subject', type='string', required=True),
ToolParameter(name='body', type='string', required=True),
],
)
])client.validate(...)
const result = await client.validate('send_email', {
to: 'user@example.com',
subject: 'Hello',
});result = await client.validate('send_email', {
'to': 'user@example.com',
'subject': 'Hello',
})client.pollApproval(...) / client.poll_approval(...)
const approval = await client.pollApproval('apr_abc123', {
pollInterval: 2000,
timeout: 300000,
});from veto.cloud.types import ApprovalPollOptions
approval = await client.poll_approval(
'apr_abc123',
ApprovalPollOptions(poll_interval=2.0, timeout=300.0)
)client.fetchPolicy(...) / client.fetch_policy(...)
const policy = await client.fetchPolicy('send_email');policy = await client.fetch_policy('send_email')client.logDecision(...) / client.log_decision(...)
client.logDecision({
tool_name: 'send_email',
arguments: { to: 'user@example.com' },
decision: 'allow',
mode: 'deterministic',
latency_ms: 2,
source: 'client',
});client.log_decision({
'tool_name': 'send_email',
'arguments': {'to': 'user@example.com'},
'decision': 'allow',
'mode': 'deterministic',
'latency_ms': 2,
'source': 'client',
})client.isToolRegistered(...) / client.is_tool_registered(...)
const isRegistered = client.isToolRegistered('send_email');is_registered = client.is_tool_registered('send_email')client.clearRegistrationCache() / client.clear_registration_cache()
client.clearRegistrationCache();client.clear_registration_cache()client.close() (Python only)
// VetoCloudClient in TypeScript does not expose close().await client.close()For deeper language-specific guides, see TypeScript SDK and Python SDK.