Protection Levels: Monitor, Protect, Govern
Vesanor offers three levels of workflow governance. Start with Monitor, move to Protect when you're ready to block, and upgrade to Govern when you need durable server-backed state and stronger evidence.
The three levels
| Level | What it does | Blocks bad calls? | Server-backed state? | Best for |
|---|---|---|---|---|
| Monitor | Captures every tool call. Computes what enforcement would do, but doesn't apply it. | No | No | Learning what your agent does, shadow testing |
| Protect | Enforces contracts locally. Blocks illegal tool calls before they execute. | Yes | No | Most teams. Fast local governance, zero infrastructure. |
| Govern | Adds durable server-backed session state, pending-call tracking, and stronger evidence. | Yes | Yes | Shared sessions, durable review trails, stricter operational controls |
Monitor — watch without blocking
Monitor mode captures everything your agent does without changing its behavior. Use it to understand your agent before writing enforcement rules.
import OpenAI from "openai";
import { replay } from "@vesanor/replay";
const session = replay(client, {
contractsDir: "./contracts",
agent: "my-agent",
mode: "shadow", // Compute enforcement, don't apply it
apiKey: process.env.VESANOR_API_KEY,
});
// Agent runs normally — nothing blocked
const response = await session.client.chat.completions.create({
model: "gpt-4o-mini",
messages,
tools,
});
What you get:
- Every tool call captured with full context
shadow_delta— shows what would have been blocked by your contracts- Counterfactual analysis on the dashboard
- No risk — your agent behaves exactly as before
When to use Monitor:
- First deployment of
replay()— see what your contracts would catch - Testing new contracts before enabling enforcement
- Capture-first review without blocking
Protect — block locally, no server needed
Protect mode enforces contracts on every call. Illegal tool calls are blocked before they execute. No server connection needed — everything runs in-process.
const session = replay(client, {
contractsDir: "./contracts",
agent: "my-agent",
mode: "enforce", // Block illegal calls
gate: "reject_all", // Throw on any blocked call
});
// This call passes — lookup_customer is valid in triage phase
const response = await session.client.chat.completions.create({
model: "gpt-4o-mini",
messages,
tools,
});
// Check session state at any time
const state = session.getState();
console.log(state.currentPhase); // "customer_identified"
console.log(state.totalStepCount); // 1
console.log(state.forbiddenTools); // []
What you get:
- Contract enforcement on every call (phases, preconditions, limits, forbidden tools)
- Tool narrowing — illegal tools removed before the LLM sees them
- Session state tracking across calls
- Kill switch (
session.kill()) - Local captures for debugging
What you don't get:
- Server-backed durable state (if your process crashes, state is lost)
- Governed execution receipts or durable commit records
- Multi-worker coordination
When to use Protect:
- Most teams, most use cases
- Single-process agents
- Fast iteration on contracts
- When you don't need a durable server-backed trail
Govern — server-backed governed sessions
Govern mode connects to the Vesanor server. Session state is durable. Every governed call goes through a preflight/proposal/receipt pipeline that creates a durable server-backed record.
const session = replay(client, {
contractsDir: "./contracts",
agent: "my-agent",
mode: "enforce",
apiKey: process.env.VESANOR_API_KEY, // Connects to server
tools: { // Wrap tool executors
issue_refund: myRefundFunction,
delete_record: myDeleteFunction,
},
});
What you get (on top of Protect):
- Durable session state — survives process crashes
- Governed execution receipts — Replay records that a wrapped tool path ran with specific arguments
- Authoritative commit decisions for the governed session state
- Prepared request binding — each call is bound to a specific session state version
- Graceful degradation — falls back to Protect if server is unreachable
When to use Govern:
- Multi-worker agents that need shared state
- Durable review and recovery across crashes or retries
- High-risk workflows where server-backed session state and approvals matter
- Cases where local-only state is not enough
How to migrate between levels
The migration path is additive. Each level builds on the previous one.
Step 1: observe() to Monitor
If you're already using observe(), switch to replay() with shadow mode:
// Before: observe()
const { client, flush } = observe(openai, {
apiKey: process.env.VESANOR_API_KEY,
});
// After: replay() in shadow mode
const session = replay(openai, {
contractsDir: "./contracts",
agent: "my-agent",
mode: "shadow",
apiKey: process.env.VESANOR_API_KEY,
});
const guardedClient = session.client;
Note: observe() monkey-patches your client in place. replay() returns a wrapper — you must use session.client, not the original client.
Step 2: Monitor to Protect
Change mode from "shadow" to "enforce":
const session = replay(openai, {
contractsDir: "./contracts",
agent: "my-agent",
mode: "enforce", // Now blocking
gate: "reject_all",
});
Step 3: Protect to Govern
Add your API key and wrap your tool executors:
const session = replay(openai, {
contractsDir: "./contracts",
agent: "my-agent",
mode: "enforce",
apiKey: process.env.VESANOR_API_KEY, // Server connection
tools: { // Governed execution
issue_refund: myRefundFunction,
},
});
Choosing the right level
Do you need to block bad calls?
No → Monitor (shadow mode)
Yes ↓
Do you need server-backed state or durable governed records?
No → Protect (local enforcement)
Yes ↓
Do you need server-backed receipts and state coordination?
No → Protect with API key (server captures, local enforcement)
Yes → Govern (server-backed governed pipeline)
Most teams should start with Protect. It's fast, effective, and requires no infrastructure. Move to Govern when your workflow needs durable server-backed state, approvals, or coordination.
What stays the same across all levels
Regardless of protection level:
- Same contract format — YAML contracts work at all levels
- Same enforcement pipeline — narrow, pre-check, validate, gate
- Same session state model — phases, preconditions, forbidden tools, limits
- Same kill switch —
session.kill()works at every level - Same API —
session.client,session.getState(),session.getHealth()
The main difference is where state lives (local vs server) and how much of the execution path is durably recorded.
Next steps
- Quickstart — get running in 5 minutes with Protect mode
- Govern Mode — deep dive into server-backed governed sessions
- Shadow Mode — test contracts safely before enabling