Veefore docs

Local development

A fast loop with real decisions — simulated execution by default, a real downstream when you want one.

The goal locally is real decisions with harmless execution. Veefore gives you that by default: the pipeline runs for real and the tool runtime is simulated until you deliberately turn egress on.

#Start the stack

bash
npm run dev
Control plane http://localhost:4000
Gateway http://localhost:4010
Console http://localhost:5173

Full setup in Self-host Veefore.

#Seed something to look at

bash
npm run seed:demo

Creates an organization with agents, tools, policies, delegations, credentials, approvals, incidents and audit history — enough that every console page renders something real. The accounts are printed at the end; the owner is owner@acme.test.

npm run seed gives you an empty organization instead.

Reseeding destroys what you created

seed:demo resets the dataset. Anything you set up by hand goes with it. If you have a working configuration you care about, script it — see examples/setup-real.ts for the pattern, which provisions everything through the public API.

#Execution is simulated by default

GATEWAY_ALLOW_REAL_EGRESS=false is the default, and with it the tool runtime produces deterministic simulated responses. The full pipeline still runs: real authentication, real policy, real risk, real approvals, real audit. Only the outbound call is simulated.

Every simulated response carries simulated: true. Nothing is presented as output from a real system when it is not.

That default means you cannot accidentally refund a real customer while testing a policy. It also means you cannot catch a credential or destination problem, because nothing is actually called.

#Then make it real, safely

The repository ships a genuine downstream service for exactly this.

bash
node examples/real-tool-server.mjs

A real HTTP service on loopback :4500 with real mutable state and its own API key:

POST /refunds Requires x-api-key. Appends to a ledger
GET /ledger Open. Shows what actually happened

Turn egress on:

ini
GATEWAY_ALLOW_REAL_EGRESS=true
TOOL_SERVER_PORT=4500
TOOL_SERVER_API_KEY=downstream-secret-key

Then:

bash
npx tsx examples/setup-real.ts      # provisions everything through the public API
npx tsx examples/run-real-agent.ts --enforce
curl -s http://localhost:4500/ledger

The ledger is the point. It shows you what actually reached the downstream, which is the only way to confirm enforcement did what the decision said it did. See Examples.

Plaintext HTTP is allowed to loopback only

The egress guards require HTTPS unless the host is a loopback address. That is why the example service runs on 127.0.0.1 — a plaintext endpoint on any other host is refused with DESTINATION_BLOCKED.

#Watch decisions live

bash
veefore dev

Streams every decision for this agent with the policy and rule behind it, and the next concrete step for each outcome. --all for every agent in the environment.

bash
veefore logs --follow --decision BLOCK
veefore status

#Use SIMULATE, not OBSERVE

For a development environment, SIMULATE is the better mode:

bash
veefore deploy --mode SIMULATE --reason "Local development"

SIMULATE gives you real refusals with no execution, so your error handling is exercised. OBSERVE lets everything through, which means your code never sees a refusal locally and then sees its first one in production.

#Iterating on policy

bash
veefore policies test
veefore policies diff pol_01ABC --from 3 --to 4

Simulation is the fastest loop, because it has no side effects at all:

bash
curl -X POST http://localhost:4000/v1/policies/simulate \
  -H "Authorization: Bearer $VEEFORE_API_KEY" \
  -H 'content-type: application/json' \
  -d '{ "agentId": "agt_01JAV…", "tool": "refund_customer", "amount": 150000 }'

#Ports

4000 and 5173 are commonly taken, so expect to change at least one. Change it in .env — everything reads from there, including the console's Vite config.

Variable Default
CONTROL_PLANE_PORT 4000
GATEWAY_PORT 4010
VEEFORE_CONSOLE_PORT 5173
VEEFORE_CONSOLE_PREVIEW_PORT 4173
VEEFORE_DOCS_PORT 4800
TOOL_SERVER_PORT 4500

Changing the console port means changing CORS_ALLOWED_ORIGINS to match, or the browser refuses every request.

#Avoid two traps

Ambient VEEFORE_* variables. A shell with VEEFORE_AGENT_ID exported from an earlier session will quietly make a test authenticate as the wrong agent. Shell environments persist. If something is behaving as though it is a different agent, check env | grep Veefore.

The embedded database. PGlite is per-process. Pointing the stack at it gives the control plane, the gateway and the seed script each a private copy of the database, and the symptom is that an agent you just created does not exist. Use a real PostgreSQL for anything multi-process.

Identity, authority, policy and enforcement for autonomous AI agents.