Python AI Agent Guardrails with Veto SDK
Native Python SDK for AI agent authorization. Works with LangChain, CrewAI, PydanticAI, or any custom agent framework. Two lines of code.
Quick start
Install the SDK via pip, initialize with your API key, and wrap your tools. Authorization happens automatically before each tool execution.
pip install vetoBasic usage
Wrap your tools with Veto. Every tool call is validated against your policies before execution. Blocked calls raise ToolCallDeniedError.
import asyncio
from veto import Veto, ToolCallDeniedError
# Your existing tools
async def transfer_money(amount: float, to_account: str) -> str:
return f"Transferred $" + str(amount) + " to " + to_account
async def delete_file(path: str) -> str:
return "Deleted " + path
async def main():
# Initialize Veto with API key from VETO_API_KEY env var
veto = await Veto.init()
# Wrap your tools - authorization is now enforced
tools = [transfer_money, delete_file]
wrapped = veto.wrap(tools)
# Use wrapped tools in your agent
try:
result = await wrapped[0].handler({"amount": 500, "to_account": "ACC123"})
print("Allowed: " + result)
except ToolCallDeniedError as e:
print("Blocked: " + e.reason)
asyncio.run(main())Tool wrapping patterns
Veto adapts to your tool structure. Works with dataclasses, LangChain tools, or any callable with a handler method.
from dataclasses import dataclass
from typing import Any
@dataclass
class MyTool:
name: str = "my_tool"
description: str = "Does something useful"
async def handler(self, args: dict[str, Any]) -> str:
return "Executed with " + str(args)
# Veto automatically detects and wraps
tool = MyTool()
wrapped = veto.wrap([tool])[0]from langchain_core.tools import tool
from pydantic import BaseModel, Field
class TransferInput(BaseModel):
amount: float = Field(description="Amount to transfer")
to_account: str = Field(description="Destination account")
@tool("transfer_money", args_schema=TransferInput)
def transfer_money(amount: float, to_account: str) -> str:
"""Transfer money to an account."""
return "Transferred $" + str(amount) + " to " + to_account
# Wrap LangChain tools directly
wrapped_tools = veto.wrap([transfer_money])
# Use with your LangChain agent
agent = create_react_agent(llm, wrapped_tools)Provider adapters
Built-in adapters convert between tool formats. Works with OpenAI, Anthropic, and Google function calling conventions.
from veto import (
to_openai, to_openai_tools,
to_anthropic, to_anthropic_tools,
to_google_tool,
)
# Convert tool definitions to provider formats
openai_tools = to_openai_tools(my_tools)
anthropic_tools = to_anthropic_tools(my_tools)
google_tool = to_google_tool(my_tool)
# Convert tool calls back to Veto format
from veto import from_openai_tool_call, from_anthropic_tool_use
tool_call = from_openai_tool_call(openai_message)Features
Runtime authorization
Every tool call is validated against your policies before execution. The agent cannot bypass guardrails regardless of its reasoning.
Framework agnostic
Works with LangChain, CrewAI, PydanticAI, or any custom agent framework. No framework-specific code required.
Deterministic policies
Define constraints as code. Argument limits, required fields, pattern matching. Evaluate locally without network latency.
Cloud sync
Policies managed in Veto Cloud. Real-time updates, team collaboration, approval workflows, and audit logging.
Build vs buy
| Capability | DIY | Veto Python SDK |
|---|---|---|
| Initial setup | 2-4 weeks | 5 minutes |
| Policy engine | ||
| Approval workflows | ||
| Audit logging | ||
| Framework integrations | ||
| Maintenance burden | Ongoing | None |
Frequently asked questions
How do I install the Python SDK?
Does it work with async tools?
Can I use Veto without a network connection?
How do I handle blocked tool calls?
Related integrations
LangChain agent guardrails and tool authorization
CrewAICrewAI multi-agent authorization and role-based access
Ship Python agents with confidence.