OpenAI runtime authorization
Wrap OpenAI tool calls with Veto. Each governed tool call is evaluated before dispatch: allow, review, or deny, with an exportable decision record per governed decision.
The problem with OpenAI tool calls
OpenAI's function calling lets GPT models trigger real actions in your system: send emails, process payments, modify databases, call external APIs. The model decides what to call, generates the arguments, and your code executes it. There is no guardrail step between the model's decision and your code's execution.
OpenAI's Agents SDK includes input and output guardrails, but these operate on the conversation level, not the tool level. They can check whether a user's message is appropriate, but they do not enforce "this specific function call with these specific arguments should be blocked." Enforcement is not a model problem. It is an infrastructure problem.
OpenAI's Agents SDK guardrails check input and output messages, not individual function calls. A blocked message stops the agent entirely, not a single tool call.
GPT models can hallucinate function arguments: wrong email addresses, inflated amounts, nonexistent table names. Pydantic validation catches type errors, not business logic violations.
Neither the Chat Completions API nor the Agents SDK log tool calls with decision context. For SOC 2, HIPAA, or financial compliance, you need to know what was attempted, what was allowed, and what was blocked.
Before and after Veto
The left tab shows standard OpenAI function calling. The model returns tool_calls, your code executes them unconditionally. The right tab adds Veto. Same agent, same tools, each governed call evaluated against policy first.
import OpenAI from 'openai'
const openai = new OpenAI()
const tools = [
{
type: 'function',
function: {
name: 'send_email',
description: 'Send an email',
parameters: {
type: 'object',
properties: {
to: { type: 'string' },
subject: { type: 'string' },
body: { type: 'string' },
},
required: ['to', 'subject', 'body'],
},
},
},
{
type: 'function',
function: {
name: 'process_payment',
description: 'Process a payment',
parameters: {
type: 'object',
properties: {
amount: { type: 'number' },
recipient: { type: 'string' },
},
required: ['amount', 'recipient'],
},
},
},
]
const response = await openai.chat.completions.create({
model: process.env.OPENAI_MODEL!,
messages: [{ role: 'user', content: userMessage }],
tools,
})
// GPT says "call process_payment with amount: 50000"
// Your code does it. No policy. No limit. No approval.
const toolCall = response.choices[0].message.tool_calls?.[0]
if (toolCall) {
const args = JSON.parse(toolCall.function.arguments)
await executeTool(toolCall.function.name, args)
}Policy configuration
Define guardrail rules in declarative YAML. Version control alongside your code. Prompt engineering is not the enforcement mechanism. Policies apply at the governed tool boundary, independent of the model response.
rules:
- name: block_competitor_emails
description: Block emails to competitor domains
tool: send_email
when: args.to.endsWith("@competitor.invalid")
action: deny
message: "Cannot send emails to competitor domains"
- name: approve_large_payments
description: Require approval for payments over $500
tool: process_payment
when: args.amount > 500
action: require_approval
approvers: [finance-team]
timeout: 30m
- name: block_after_hours_payments
description: No payments outside business hours
tool: process_payment
when: context.time.hour < 9 || context.time.hour > 17
action: deny
message: "Payments require business hours (9am-5pm)"
- name: daily_payment_cap
description: Cap total daily payments at $10,000
tool: process_payment
when: context.daily_total + args.amount > 10000
action: deny
message: "Daily payment cap of $10,000 reached"First governed call
Install the SDK
npm install veto-sdk openaiDefine policies
Create veto/policies.yaml with rules for each tool. Match on tool name, constrain arguments, set actions.
Validate before executing
Call veto.guard() in your tool handler. Check the decision. Execute only if allowed.
Supported models
Veto works with OpenAI models that emit tool calls through the API. Keep the model compatibility check in CI because provider catalogs change.
What Veto covers for OpenAI agents
Function allowlists
Allowlist which functions the agent can call. Block everything else by default. Different rules per environment, user role, or time of day.
Argument validation
Constrain function arguments by pattern, range, or business rule. Block emails to competitor domains. Cap payment amounts. Restrict SQL to read-only.
Approval workflows
Route sensitive function calls to human approval queues. Approvers get configured approval channel or email notifications with the function name, arguments, policy, and context.
Decision records
Each guarded function call can be recorded with name, arguments, decision, and timestamp. Queryable via API or workspace. Export for SOC 2 and evidence reporting.
Frequently asked questions
How is Veto different from OpenAI's built-in guardrails?
Does this work with the Responses API and Assistants API?
What happens when a function call is blocked?
Does Veto add latency?
Related integrations
Wrap one OpenAI tool path and inspect the decision record.