Skip to content
/docs

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.ndjson

3. 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.

Next Steps