Documentation
VasperaMesh sits between your agents and their model provider. Every generation becomes one immutable row in a hash-chained audit ledger you — or a regulator — can verify offline, without trusting us.
Quickstart
- Sign up with your invite code (or join the waitlist).
- Mint a mesh key on the onboarding page — it walks you to your first ledger row in under five minutes.
- Point your SDK at the shadow proxy (snippets below). No other code changes.
- Draft a policy in the Policy Studio, get it approved by a second member, and activate it — that first activation is your chain's genesis.
Fastest path: set up with Claude
Don't want to hunt for where your base URL lives? Mint your key on the onboarding page (the Set up with Claude tab pre-fills it), then paste this into Claude Code, Cursor, or any AI coding agent inside your project — it finds your model client and wires up Mesh for you.
Set up VasperaMesh audit logging in this project.
VasperaMesh is a drop-in proxy: it records every AI model call to a tamper-evident
audit ledger. My provider API key is unchanged and passes straight through — this only
changes the client's base URL and adds two headers. It is observe-only and fail-open.
Do this:
1. Find where this repo creates its LLM client. Search for: "new Anthropic(",
"new OpenAI(", "createAnthropic(", "createOpenAI(".
2. Add these to that client, WITHOUT removing the existing provider API key:
• Anthropic SDK: baseURL: "https://www.vasperamesh.com/api/proxy"
• OpenAI / AI SDK: baseURL: "https://www.vasperamesh.com/api/proxy/v1"
• headers: { "x-mesh-key": process.env.MESH_KEY, "x-mesh-agent": "my-agent" }
3. Add MESH_KEY to my .env / secrets: MESH_KEY=<your-mesh-key>
4. Change nothing else — no model names, prompts, or other logic.
5. Make one small test model call, then check https://www.vasperamesh.com/dashboard.Or mint a key from your terminal
The CLI authenticates via your browser and writes MESH_KEY to your .env. The key is issued only after you approve the request in a signed-in session, so it always belongs to your account.
npx vasperamesh login # approve in the browser, MESH_KEY written to .env npx vasperamesh init # login, then print the "set up with Claude" prompt
The shadow proxy
Change the baseURL, add two headers, done. Your provider API key passes through untouched; Mesh stores only content digests, never your prompts or completions. The proxy fails open: if Mesh is ever unreachable, your calls still go through — you lose rows, not uptime.
Anthropic SDK
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://www.vasperamesh.com/api/proxy", // SDK appends /v1/messages
defaultHeaders: {
"x-mesh-key": "<your-mesh-key>",
"x-mesh-agent": "my-agent", // how rows are attributed
},
});
// Keep your own ANTHROPIC_API_KEY — Mesh passes it through untouched.OpenAI SDK
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://www.vasperamesh.com/api/proxy/v1", // SDK appends /chat/completions
defaultHeaders: {
"x-mesh-key": "<your-mesh-key>",
"x-mesh-agent": "my-agent",
},
});
// Keep your own OPENAI_API_KEY — Mesh passes it through untouched.Vercel AI SDK
import { createAnthropic } from "@ai-sdk/anthropic";
const anthropic = createAnthropic({
baseURL: "https://www.vasperamesh.com/api/proxy/v1", // AI SDK appends /messages
headers: {
"x-mesh-key": "<your-mesh-key>",
"x-mesh-agent": "my-agent",
},
});curl
curl https://www.vasperamesh.com/api/proxy/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "x-mesh-key: <your-mesh-key>" \
-H "x-mesh-agent: my-agent" \
-d '{"model":"claude-haiku-4-5-20251001","max_tokens":50,
"messages":[{"role":"user","content":"Hello from Mesh"}]}'Each response includes an X-Mesh-Ledger header with the row that recorded it.
Policies & the gate
A policy is a plain-English constitution plus a compiled, deterministic gate. Describe what your agent may and may not do; the AI assistant drafts both, and the worked examples you see are computed by running the compiled gate — not model-claimed.
The lifecycle enforces separation of duties: the author can never approve their own policy, approval freezes the content, and activation stamps the ledger. Every transition is itself a ledger row.
Every check passed and confidence cleared the floor. The action proceeds.
A check failed or confidence fell short. The action waits for review.
A bound you marked as escalating was crossed. A human must decide.
Gate checks are declarative — required sources, grounding, numeric bounds, required disclosures, freshness — and they fail closed: a check that cannot run counts against the action, never for it.
Verify the ledger yourself
Each row commits to the previous row's hash, and your chain's identity is inside every hash — an operator cannot serve one customer's chain as another's. Chain heads are anchored to Bitcoin via OpenTimestamps, so even we cannot rewrite history after the fact.
The verifier is a single dependency-free script. Download verify-mesh-ledger.mjs and run it against the live API or an exported JSON file from /api/ledger/export:
node verify-mesh-ledger.mjs \ --base https://www.vasperamesh.com \ --chain <your-chain-id>
Your chain ID and this exact command are on your dashboard. Anyone holding an export can re-derive every hash offline — no VasperaMesh account, no trust in us required.
Questions
Open an issue on GitHub or use the contact page.