OpenAI Agents Integration
Protect OpenAI Agents tools with Veto guard checks and wrapped execution.
The local TypeScript SDK does not ship a dedicated veto-sdk/integrations/openai-agents package.
Use the current SDK primitives:
veto.guard(toolName, args, context)for preflight checksveto.wrap(...)for executable TypeScript toolsToolCallDeniedErrorfor policy-denied executionVeto.charterto compile and review policies for registered tools
TypeScript tool guard
import { ToolCallDeniedError, Veto } from "veto-sdk";
const veto = await Veto.init();
const tools = veto.wrap([
{
name: "send_email",
description: "Send an email to a customer",
handler: async (args: { to: string; body: string }) => {
return { sent: true, to: args.to };
},
},
], {
context: {
agentId: "openai-agent",
sessionId: "support-session",
},
});
try {
const result = await tools[0].handler({
to: "customer@example.com",
body: "Account details...",
});
console.log(result);
} catch (error) {
if (error instanceof ToolCallDeniedError) {
console.log(`Blocked by Veto: ${error.reason ?? error.decision}`);
} else {
throw error;
}
}Preflight guard
Use preflight when your framework gives you the proposed tool call before execution:
const guard = await veto.guard("send_email", {
to: "customer@example.com",
body: "Account details...",
}, {
agentId: "openai-agent",
sessionId: "support-session",
});
if (guard.decision !== "allow") {
throw new Error(guard.reason ?? `Veto returned ${guard.decision}`);
}Python status
This repository currently publishes the TypeScript SDK. For Python OpenAI Agents, call the Veto API directly from a tool guardrail until a Python package is published:
import httpx
import os
async def veto_guard(tool_name: str, args: dict):
response = await httpx.AsyncClient().post(
"https://api.veto.so/v1/validate",
headers={"X-Veto-API-Key": os.environ["VETO_API_KEY"]},
json={"toolName": tool_name, "arguments": args},
timeout=10,
)
response.raise_for_status()
decision = response.json()
if decision["decision"] != "allow":
raise RuntimeError(decision.get("reason") or decision["decision"])Charter loop
Register the tools once, then let Charter draft policy for them:
await veto.registerTools([
{
name: "send_email",
description: "Send an email to a customer",
parameters: [
{ name: "to", type: "string", required: true },
{ name: "body", type: "string", required: true },
],
},
]);
const res = await fetch("https://api.veto.so/v1/charter/turn", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Veto-API-Key": process.env.VETO_API_KEY!,
},
body: JSON.stringify({
message: "Customer emails that include account details need support lead approval.",
mode: "compile",
surface: "api",
}),
});
const draft = await res.json();
console.log(draft.verification.linkUrl);Policy-changing Charter results require verification before anything goes live.

