OpenClaw Integration
Use Veto with OpenClaw agents — plugin install, approval flows, and deterministic guardrails for real-world actions.
Veto integrates with OpenClaw at two levels. The plugin is the fast path: install it, run veto init, and your agent has hard guardrails, approval gates, and rule enforcement without touching a line of agent code. The SDK hooks are available for advanced use cases where you need direct control inside a custom plugin.
| Path | Best for | Code changes? |
|---|---|---|
| Plugin (recommended) | Any OpenClaw project — local or cloud | None in agent code |
| SDK hooks | Custom plugins, non-standard tool routing, embedded control flows | Requires a plugin scaffold |
If you are starting fresh, use the plugin. If you are building a custom OpenClaw plugin that needs to embed Veto policy logic directly, use the SDK hooks.
Installation and setup
Plugin install
openclaw plugins install openclaw-vetoThen initialize Veto configuration in your project:
cd your-project && veto initGenerated directory structure:
veto/
├── veto.config.yaml
└── rules/
└── defaults.yamlveto.config.yaml defaults to local mode. All validation runs in-process using your YAML rules — no API key, no network calls, no account required to start.
Upgrade to cloud mode
Add your API key to activate the Veto Cloud approval UI, dashboard, and LLM-backed policies:
export VETO_API_KEY=veto_xxxOr set it directly in veto.config.yaml:
version: "1.0"
mode: "strict"
cloud:
apiKey: veto_xxxApproval modes
The plugin supports two approval modes. Set approvalMode in your Veto config or pass it explicitly at init time.
| Mode | How approval requests are resolved | Requires cloud? |
|---|---|---|
openclaw-native | OpenClaw's built-in approval UI, local rule engine | No |
veto-cloud | Veto Cloud approval dashboard and audit log | Yes (VETO_API_KEY) |
openclaw-native
Approval requests are resolved inside OpenClaw's own interface. Veto evaluates rules locally and signals OpenClaw to surface the approval prompt.
veto-cloud
Approval requests are polled against the Veto Cloud queue. The agent waits for a human decision in the Veto dashboard before the tool call proceeds.
What Veto guarantees
This is the most important section to understand before deploying to production.
| Capability | Deterministic? | What it means |
|---|---|---|
| Block leverage above threshold | Yes | Hard permission check — no model judgment, no bypass |
| Require approval before large trade | Yes | Approval gate is structural. The tool call cannot proceed until a human acts |
| Enforce session budget / open-position count | Yes | Stateful server/client checks evaluated before every tool call |
| Block calls to non-allowlisted exchanges or APIs | Yes | Rule fires on argument value, independent of model behavior |
| Judge whether agent reasoning is "sound" | No — LLM-backed | Useful signal, but not a substitute for structural rules |
| Evaluate whether a multi-step plan is safe | No — LLM-backed | Additive layer; don't treat it as a hard constraint |
Veto is strongest when enforcing structured permissions on structured tool arguments. A rule like "block any trade with leverage above 5x" fires reliably because leverage is a discrete argument value — the rule is evaluated deterministically, every time, without model involvement.
LLM-backed policies are a real feature and they add meaningful coverage for cases that can't be expressed as static rules. But they are additive, not the foundation of financial safety. Build your critical guardrails on YAML rules first.
What is plug-and-play vs what needs tuning
Works immediately after install
- Hard blocks — argument-value checks (
greater_than,not_in,matches) fire without any configuration - Approval gates —
require_approvalworks in both modes out of the box - Default pack thresholds —
veto init --pack financialloads a pre-built rule set with sensible defaults for trading, transfers, and data access - Local YAML rules — any rule in
veto/rules/*.yamlis evaluated in-process with zero setup
Requires configuration for your environment
- Exchange-specific tool names — rules target tools by name; you need to map your agent's actual tool identifiers
- Custom argument schemas — if your tools pass amounts in non-standard fields (e.g.,
qtyinstead ofamount), update the conditionfieldpaths accordingly - Cloud-mode approvals —
veto-cloudrequires aVETO_API_KEY; approval routing and notification setup happens in the Veto dashboard - Semantic LLM policies — natural-language policy descriptions require an LLM provider API key and a
veto compilerun to generate their YAML equivalents
Example rules
All examples below use valid Veto YAML rule syntax. Place files in veto/rules/.
File access control
rules:
- id: block-sensitive-paths
name: Block access to sensitive file paths
action: block
severity: critical
tools:
- read_file
- write_file
- delete_file
conditions:
- field: arguments.path
operator: matches
value: "(\\.env|credentials|secrets|\\.ssh|/etc/passwd)"Shell command approval
rules:
- id: require-approval-shell
name: Require approval for shell command execution
action: require_approval
severity: high
tools:
- execute_command
- run_shell
conditions:
- field: arguments.command
operator: matches
value: ".*"
- id: block-destructive-commands
name: Block destructive shell commands unconditionally
action: block
severity: critical
tools:
- execute_command
- run_shell
conditions:
- field: arguments.command
operator: matches
value: "^(rm -rf|mkfs|dd if=|:(){ :|:& };:)"External API allowlist
rules:
- id: allowlist-external-apis
name: Block calls to non-allowlisted external APIs
action: block
severity: high
tools:
- http_request
- fetch_url
- api_call
conditions:
- field: arguments.url
operator: not_in
value:
- "https://api.exchange-a.com"
- "https://api.exchange-b.com"
- "https://data.market-feed.io"Trading guardrails
rules:
- id: block-high-leverage
name: Block trades with leverage above 5x
action: block
severity: critical
tools:
- place_order
- open_position
conditions:
- field: arguments.leverage
operator: greater_than
value: 5
- id: require-approval-large-trade
name: Require approval for trades above $10,000 notional
action: require_approval
severity: high
tools:
- place_order
- open_position
conditions:
- field: arguments.notional_usd
operator: greater_than
value: 10000
- id: block-short-selling-disabled
name: Block short positions when short-selling is disabled
action: block
severity: critical
tools:
- place_order
conditions:
- field: arguments.side
operator: not_in
value:
- "buy"
- "close"SDK hooks (advanced)
Use the SDK integration directly inside a custom OpenClaw plugin when you need programmatic control over the hook lifecycle.
npm install veto-sdkimport { Veto } from 'veto-sdk';
import {
createVetoBeforeToolCallHook,
createVetoAfterToolCallHook,
} from 'veto-sdk/integrations/openclaw';
const veto = await Veto.init();
const beforeHook = createVetoBeforeToolCallHook(veto, {
onAllow: (toolName, args) => {
console.log(`[veto] allow: ${toolName}`);
},
onDeny: (toolName, args, reason) => {
console.warn(`[veto] deny: ${toolName} — ${reason}`);
},
throwOnDeny: false,
});
const afterHook = createVetoAfterToolCallHook(veto, {
onComplete: (toolName, args, result) => {
// post-execution audit hook — no blocking
},
});
// Register with your OpenClaw plugin
plugin.hooks.beforeToolCall(beforeHook);
plugin.hooks.afterToolCall(afterHook);Hook options
| Option | Type | Default | Description |
|---|---|---|---|
onAllow | (toolName, args) => void | — | Called when a tool call passes validation |
onDeny | (toolName, args, reason) => void | — | Called when a tool call is denied |
throwOnDeny | boolean | false | Throw ToolCallDeniedError instead of returning a denial result |
approvalMode | "openclaw-native" | "veto-cloud" | From config | Override the approval mode for this hook instance |
sessionId | string | Auto-generated | Tie this hook to a specific session for budget and state tracking |
How it works
Every tool call is intercepted before execution and evaluated against your loaded YAML rules. The outcome maps directly to an OpenClaw result:
| Veto decision | OpenClaw behavior |
|---|---|
allow | Tool call executes normally |
deny | { block: true, reason: "..." } returned to agent |
require_approval | Approval flow triggered (openclaw-native or veto-cloud depending on mode) |
The agent receives denial and approval-pending results as structured responses. It does not see Veto's presence — the guardrail is transparent to agent logic.
A note on what Veto promises
Veto does not promise profitable trading. It does not guarantee that an agent will make good decisions.
What Veto does promise: every tool call that touches money, files, or external systems passes through an explicit, auditable policy check before it executes. Approvals are structural, not advisory. Hard blocks are deterministic. If you define a rule that blocks leverage above 5x, that rule fires every time — not most of the time.
This is the trust model: accountable actions, explicit approvals, and deterministic guardrails around agent behavior. Financial safety is built on rules you write and own, not on model judgment.
Exports
import {
createVetoBeforeToolCallHook,
createVetoAfterToolCallHook,
} from 'veto-sdk/integrations/openclaw';
import type {
VetoOpenClawBeforeHookOptions,
VetoOpenClawAfterHookOptions,
VetoOpenClawDenyResult,
} from 'veto-sdk/integrations/openclaw';Related
- YAML Rule Format — complete rule syntax, operators, severity levels, and extends
- SDK Modes — local, cloud, and self-hosted mode differences
- MCP Integration — Veto with Model Context Protocol tool definitions