Examples
Four working programs in examples/ — a real downstream service, a provisioning script, an agent driver, and an annotated SDK walkthrough.
Everything in examples/ runs. No pseudo-code, no stubbed responses, no fake
state. The downstream service is a genuine HTTP service with mutable state and
its own API key, which is what makes the result inspectable.
#examples/real-tool-server.mjs
A real downstream service on loopback :4500.
bashnode examples/real-tool-server.mjs
| Route | Auth | Does |
|---|---|---|
POST /refunds |
x-api-key required |
Appends a refund to an in-memory ledger, returns a reference |
GET /ledger |
open | Returns everything that actually happened |
The API key is its own, configured as TOOL_SERVER_API_KEY and known to the
Veefore credential broker — not to the agent. An agent that tried to call
:4500 directly would get a 401.
Why the ledger matters
GET /ledger is the independent record of what reached the downstream. A
decision says what Veefore decided; the ledger says what happened. Comparing
the two is the only way to confirm enforcement actually enforced rather than
merely reported.
It is an in-memory ledger belonging to the example service, for observing enforcement. Veefore has no ledger of its own — see What Veefore is not.
#examples/setup-real.ts
Provisions a complete working setup entirely through the public API — no direct database access, no internal imports.
bashnpx tsx examples/setup-real.ts
It creates an organization, a workspace, a production environment, a capability,
a credential holding the downstream's API key, an HTTP tool pointing at
:4500 with a destination allowlist, an agent with a locally generated key
pair, and a policy. Then it writes .veefore-real.env at mode 0600.
Worth reading as a reference for provisioning from your own code. Every call is one you could make yourself, in the order the dependencies require.
`.veefore-real.env` holds a private key and an owner password
It is gitignored. Treat it as a secret, and delete it when you are done.
#examples/run-real-agent.ts
Drives the agent through three refund attempts, then reads the downstream ledger to show what actually happened.
bashnpx tsx examples/run-real-agent.ts --enforce
npx tsx examples/run-real-agent.ts --observe
The three attempts are chosen to produce three different outcomes: one that policy allows, one that requires approval, one that policy blocks.
In ENFORCE:
| Attempt | Decision | Reached the downstream |
|---|---|---|
| Small refund | ALLOW |
yes — appears in the ledger |
| Large refund | REQUIRE_APPROVAL |
no — waiting on a human |
| Blocked refund | BLOCK |
no — never left the gateway |
One ledger entry. Exactly what the decisions said.
In OBSERVE:
| Attempt | decision |
shadow.decision |
Reached the downstream |
|---|---|---|---|
| Small refund | ALLOW |
— | yes |
| Large refund | ALLOW |
REQUIRE_APPROVAL |
yes |
| Blocked refund | ALLOW |
BLOCK |
yes |
Three ledger entries.
Run both. This is the lesson.
In OBSERVE, all three refunds reach the downstream — including the one
ENFORCE refuses outright. The ledger proves it; you can count the rows.
This is the single most important thing to internalise about OBSERVE, and reading it in a table is less convincing than seeing the ledger. Run both modes.
#examples/protect-an-agent.ts
An annotated SDK walkthrough against the demo organization.
bashnpm run seed:demo
npx tsx examples/protect-an-agent.ts
Covers protect(), the handshake, an allowed action, a blocked action, an
approval-required action, and the error classes for each. The comments explain
why each step is shaped the way it is, which is the part a reference page
cannot carry.
Start here if you have not written Veefore code before.
#The full sequence
bash# 1. Database
docker run -d --name veefore-postgres \
-e POSTGRES_USER=veefore -e POSTGRES_PASSWORD=veefore -e POSTGRES_DB=veefore \
-p 55432:5432 postgres:16
# 2. Configure
cp .env.example .env
# then set:
# GATEWAY_ALLOW_REAL_EGRESS=true
# TOOL_SERVER_PORT=4500
# TOOL_SERVER_API_KEY=downstream-secret-key
# 3. Schema
npm run migrate
# 4. Three processes, three terminals
npm run dev
node examples/real-tool-server.mjs
# 5. Provision and run
npx tsx examples/setup-real.ts
npx tsx examples/run-real-agent.ts --enforce
# 6. Check what actually happened
curl -s http://localhost:4500/ledger
Then run it again with --observe and compare the ledger.
#Verifying the whole system
Not examples, but the same spirit — real processes, real HTTP, real decisions:
bashnpm run smoke # control plane: signup through enforcement
npm run smoke:gateway # agent auth, replay refusal, enforcement, revocation
npm run smoke:sdk # the published JS SDK surface, including fail-closed
npm run smoke:sdk-python # cross-language signing agrees with the server
npm run smoke:console # every console page through the browser origin
All five are stages of npm run verify.
Redirect smoke output to a file
These write with console.log while the services log through pino, and the two
interleave badly on a terminal. Redirect and filter:
bashnpm run smoke:gateway > /tmp/smoke.log 2>&1; grep -v '"level"' /tmp/smoke.log