useveto
Runtime authorization for AI agents — Python SDK.
What is Veto?
Veto intercepts every tool call your AI agent makes, evaluates it against your policies, and decides: allow, deny, or escalate. Sub-10ms. Default deny.
- Default deny — no matching policy = blocked
- Full audit trail — every decision logged
- Edge-first — powered by Cloudflare Workers
- Sync + async — both clients included
Install
pip install useveto
Quick Start
from veto import VetoClient
client = VetoClient(api_key="veto_...")
# Check if an agent can perform an action
result = client.authorize("agent-uuid", "file.write", {"path": "/etc/passwd"})
if not result.allowed:
print(f"Blocked: {result.reason}")
Async
from veto import AsyncVetoClient
async with AsyncVetoClient(api_key="veto_...") as client:
result = await client.authorize("agent-uuid", "send_email", {
"to": "user@example.com",
"subject": "Refund confirmation",
})
LangChain Integration
from veto import VetoClient, VetoError
veto = VetoClient(api_key="veto_...")
def veto_tool_wrapper(tool_func, tool_name: str, agent_id: str):
"""Wrap any LangChain tool with Veto authorization."""
def wrapper(*args, **kwargs):
result = veto.authorize(agent_id, tool_name, kwargs)
if not result.allowed:
return f"Authorization denied: {result.reason}"
return tool_func(*args, **kwargs)
wrapper.__name__ = tool_func.__name__
wrapper.__doc__ = tool_func.__doc__
return wrapper
CrewAI Integration
from veto import VetoClient
veto = VetoClient(api_key="veto_...")
def before_tool_callback(agent_id: str):
def callback(tool_name: str, tool_input: dict) -> bool:
result = veto.authorize(agent_id, tool_name, tool_input)
return result.allowed
return callback
API Reference
VetoClient / AsyncVetoClient
client = VetoClient(
api_key="veto_...", # required
endpoint="https://api.veto.tools", # optional
timeout=5.0, # optional, seconds
)
Authorization
client.authorize(agent_id, tool_name, parameters={}) -> AuthorizationResult
Agents
client.create_agent(CreateAgentInput(name="Bot", description="...")) -> Agent
client.list_agents() -> List[Agent]
client.get_agent(agent_id) -> Agent
client.delete_agent(agent_id) -> None
Policies
client.create_policy(CreatePolicyInput(
agent_id="...",
name="Allow reads",
rules=[PolicyRule(type="tool_allowlist", tools=["file.read"])],
priority=10,
)) -> Policy
client.list_policies(agent_id=None) -> List[Policy]
client.get_policy(policy_id) -> Policy
client.update_policy(policy_id, UpdatePolicyInput(name="New name")) -> Policy
client.delete_policy(policy_id) -> None
Audit Logs
client.query_audit_log(
agent_id=None,
tool_name=None,
result=None, # "allowed" | "denied" | "escalated"
limit=100,
offset=0,
) -> PaginatedAuditLogResponse
Error Handling
from veto import VetoError, UnauthorizedError, RateLimitError
try:
result = client.authorize("agent", "tool")
except RateLimitError as e:
print(f"Retry after {e.retry_after_ms}ms")
except UnauthorizedError:
print("Invalid API key")
except VetoError as e:
print(f"{e.code}: {e}")
Context Manager
# Sync
with VetoClient(api_key="veto_...") as client:
result = client.authorize("agent-1", "file.read")
# Async
async with AsyncVetoClient(api_key="veto_...") as client:
result = await client.authorize("agent-1", "file.read")
Links
- Website: veto.tools
- Dashboard: app.veto.tools
- API Docs: docs.veto.tools
- GitHub: github.com/useveto/python
License
MIT
Metadata
Release files for useveto 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| useveto-0.1.1.tar.gz | 9.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| useveto-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.6 kB
Release files / useveto-0.1.1.tar.gz
| Download URL | useveto-0.1.1.tar.gz |
|---|---|
| Size | 9.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
63cc3e3cc8430da96f35c490be57448dea069265164923196ee78ce12783e5cf
|
|
BLAKE2b-256 checksum How to use checksums |
ced46095012d3d9e18da96edb9f4845b41c69c3faa844ff573e312f713eb2125
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / useveto-0.1.1-py3-none-any.whl
| Download URL | useveto-0.1.1-py3-none-any.whl |
|---|---|
| Size | 9.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3206c8132bc8af78406b602684293c460623c633625bee614b791ddc8304fee3
|
|
BLAKE2b-256 checksum How to use checksums |
cab92758b8cdfe690acf6fb551883af9ea193911c469366e20804813e48501dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Security for useveto 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.