Quick Start
Protect executable agent tools with Veto Cloud and make them visible to Charter.
This guide uses the current TypeScript SDK. You need a Veto API key for Guard, Charter, approvals, and dashboard visibility.
1. Install
npm install veto-sdk
export VETO_API_KEY=veto_...2. Wrap Executable Tools
import { protect } from "veto-sdk";
const tools = await protect([
{
name: "issue_refund",
description: "Issue a customer refund",
execute: async ({ amount_usd }: { amount_usd: number }) => {
return { refunded: amount_usd };
},
},
]);When Veto denies a call or requires approval, the original tool does not run.
import { ToolCallDeniedError } from "veto-sdk";
try {
await tools[0].execute({ amount_usd: 900 });
} catch (error) {
if (error instanceof ToolCallDeniedError) {
console.error(error.toolName, error.decision, error.message);
}
}Every stored decision includes a compact receipt summary. Export and verify canonical receipt payloads when you need an audit archive:
npx veto-cli@latest receipts export --base-url https://api.veto.so --api-key "$VETO_API_KEY" --output receipts.ndjson
npx veto-cli@latest receipts verify receipts.ndjson3. Register Tools For Charter
Register the same runtime surface so Charter can compile policies against the tools your agent actually has.
import { Veto } from "veto-sdk";
const veto = await Veto.init();
await veto.registerTools([
{
name: "issue_refund",
description: "Issue a customer refund",
parameters: [{ name: "amount_usd", type: "number", required: true }],
},
]);4. Compile A Policy With Charter
Charter is a REST API. Send a turn to POST /v1/charter/turn:
const response = 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: "Refunds over $200 require support lead approval.",
mode: "compile",
surface: "api",
}),
});
const turn = await response.json();
if (turn.verification.required) {
console.log("Review before it goes live:", turn.verification.linkUrl);
}Production policy changes require a verification link. Charter does not silently publish compiled policy.
5. Stream A Charter Turn
Use POST /v1/charter/stream for Server-Sent Events with progress updates:
curl -N https://api.veto.so/v1/charter/stream \
-H "X-Veto-API-Key: $VETO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"message":"Block prod DB writes","mode":"compile","surface":"api"}'6. Vercel AI SDK
For AI SDK tools, use the Veto middleware so model tool calls are intercepted before execution.
import { generateText, tool, wrapLanguageModel } from "ai";
import { openai } from "@ai-sdk/openai";
import { Veto } from "veto-sdk";
import { createVetoMiddleware } from "veto-sdk/integrations/vercel-ai";
import { z } from "zod";
const veto = await Veto.init();
const model = wrapLanguageModel({
model: openai("gpt-4.1"),
middleware: createVetoMiddleware(veto),
});
await generateText({
model,
tools: {
issue_refund: tool({
inputSchema: z.object({ amount_usd: z.number() }),
execute: async ({ amount_usd }) => ({ refunded: amount_usd }),
}),
},
prompt: "Refund $250",
});7. AI Agent Integration Prompt
Paste this into a coding agent working inside your repository:
Install `veto-sdk`. Wrap executable tool objects with `protect()` or `Veto.wrap()`.
Register the same tools with `veto.registerTools()` so Charter can compile policies
against the real runtime surface. Use `createVetoMiddleware` for Vercel AI SDK tools.
Do not silently allow tool execution when Veto returns deny or require_approval.
