Skip to content
/docs

LangGraph Integration

Use Veto with LangGraph JS ToolNode by wrapping executable tools before graph execution.

Veto works with LangGraph JS by wrapping executable LangChain-style tools before passing them to a ToolNode.

The current local TypeScript SDK supports objects that expose func, invoke, execute, or handler. It does not ship a dedicated createVetoToolNode helper or a Python LangGraph package in this repository.

Installation

npm install veto-sdk @langchain/core @langchain/langgraph

Quick start

import { ToolNode } from "@langchain/langgraph/prebuilt";
import { Veto, ToolCallDeniedError } from "veto-sdk";

const veto = await Veto.init();

const tools = [
  {
    name: "transfer_funds",
    description: "Transfer money between accounts",
    func: async (input: { amount: number; to_account: string }) => {
      return `Transferred $${input.amount} to ${input.to_account}`;
    },
    invoke: async function (input: { amount: number; to_account: string }) {
      return this.func(input);
    },
  },
];

const safeTools = veto.wrap(tools, {
  context: {
    agentId: "langgraph-agent",
    sessionId: "support-session",
  },
});

const toolNode = new ToolNode(safeTools);

When the graph calls invoke, Veto validates the tool name and arguments through /v1/validate before the original tool runs.

Denial handling

try {
  await safeTools[0].invoke({ amount: 5000, to_account: "external" });
} catch (error) {
  if (error instanceof ToolCallDeniedError) {
    console.log(`Blocked by Veto: ${error.reason ?? error.decision}`);
  } else {
    throw error;
  }
}

Register tools for Charter

Register the same tools so Charter can draft policy against the actual graph surface:

await veto.registerTools([
  {
    name: "transfer_funds",
    description: "Transfer money between accounts",
    parameters: [
      { name: "amount", type: "number", required: true },
      { name: "to_account", 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: "Transfers over $1,000 require finance 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.