Integrations
Whatever runs your agent, Vetro records each LLM call, tool call, cost and policy decision into a hash-chained, ed25519-signed ledger (.vetro/runs/*.vtl) that anyone can verify, and that we can countersign for your EU AI Act file. Every snippet below is taken from a working example we run in CI.
- Anthropic
- OpenAI
- Python
- Gemini
- Vercel AI SDK
- LangChain
- LlamaIndex
- Mastra
- OpenAI Agents SDK
- Claude Code
- n8n
- OpenTelemetry / OTLP
- MCP
- GitHub Action
Install steps for @vetro/core and the CLI are on the quickstart. Framework adapters marked adapter file are a single dependency-free file you drop into your project: download it from the link in each section.
Anthropic SDK (Claude)
import Anthropic from '@anthropic-ai/sdk';
import { Vetro } from '@vetro/core';
import { wrapAnthropic } from '@vetro/anthropic';
const run = new Vetro().startRun({ name: 'my-agent' });
const client = wrapAnthropic(new Anthropic(), run); // the only change
// ... use client exactly as before, streaming included ...
run.end();
Records and policy-guards every Claude call: model, params, token usage, cost, content.
OpenAI SDK
import OpenAI from 'openai';
import { Vetro } from '@vetro/core';
import { wrapOpenAI } from '@vetro/openai';
const run = new Vetro().startRun({ name: 'my-agent' });
const client = wrapOpenAI(new OpenAI(), run); // the only change
run.end();
Covers chat.completions and responses.
Python (Anthropic, OpenAI)
import anthropic from vetro import Vetro, wrap_anthropic # or wrap_openai run = Vetro().start_run(name="my-agent") claude = wrap_anthropic(anthropic.Anthropic(), run) run.end()
Sync and async clients, streaming included. Same ledger format as Node: vetro verify checks both.
Google Gemini (@google/genai) adapter file
import { GoogleGenAI } from '@google/genai';
import { Vetro, registerPrice } from '@vetro/core';
import { wrapGemini } from './gemini-adapter.mjs';
registerPrice('gemini-2.5-flash', { inputPerMTok: 0.3, outputPerMTok: 2.5 });
const run = new Vetro().startRun({ name: 'my-agent' });
const ai = wrapGemini(new GoogleGenAI({}), run);
await ai.models.generateContent({ model: 'gemini-2.5-flash', contents: 'hi' });
run.end();
Wraps models.generateContent (non-streaming); usage comes from usageMetadata. Download gemini-adapter.mjs
Vercel AI SDK
npm i https://attest.piratefly.com/dl/vetro-core-0.1.0.tgz https://attest.piratefly.com/dl/vetro-vercel-ai-0.1.0.tgz
import { wrapLanguageModel, generateText } from 'ai';
import { Vetro } from '@vetro/core';
import { createVetroMiddleware } from '@vetro/vercel-ai';
const run = new Vetro().startRun({ name: 'my-agent' });
const model = wrapLanguageModel({
model: yourModel, // any AI SDK LanguageModel
middleware: createVetroMiddleware(run),
});
await generateText({ model, prompt: '…' }); // guarded + recorded
run.end();
Records generateText and streamText (model, params, usage, finish reason, content); a blocking policy rule stops the call before it is sent. Single-file version: vercel-ai-sdk-middleware.mjs
LangChain.js
npm i https://attest.piratefly.com/dl/vetro-core-0.1.0.tgz https://attest.piratefly.com/dl/vetro-langchain-0.1.0.tgz
import { Vetro } from '@vetro/core';
import { createVetroCallbackHandler } from '@vetro/langchain';
const run = new Vetro().startRun({ name: 'support-agent' });
await agent.invoke({ input }, { callbacks: [createVetroCallbackHandler(run)] });
run.end('completed');
Records llm.request/llm.response with token usage and cost, tool.call/tool.result, chain start/end (recordChains: false to skip) and errors. A block stops the chain. { recordContent: false } keeps prompts out of the ledger.
LlamaIndex.TS adapter file
import { Settings } from 'llamaindex';
import { Vetro } from '@vetro/core';
import { attachVetroCallbacks, wrapVetroTool } from './llamaindex-callback.mjs';
const run = new Vetro().startRun({ name: 'rag-agent' });
attachVetroCallbacks(Settings.callbackManager, run, { model: 'gpt-5' });
const guardedTool = wrapVetroTool(myTool, run); // synchronous block on tool calls
run.end();
Records LLM start/end and tool call/result events. LlamaIndex callbacks are fire-and-forget, so wrap tools with wrapVetroTool when a policy must actually stop them. Download llamaindex-callback.mjs
Mastra adapter file
import { Agent } from '@mastra/core/agent';
import { Vetro } from '@vetro/core';
import { createVetroProcessor, wrapVetroTool } from './mastra-processor.mjs';
const run = new Vetro().startRun({ name: 'support-agent' });
const vetroProcessor = createVetroProcessor(run);
const agent = new Agent({
id: 'support-agent',
model: 'anthropic/claude-sonnet-4-5',
inputProcessors: [vetroProcessor], // processLLMRequest
outputProcessors: [vetroProcessor], // processOutputStep
tools: { refund: wrapVetroTool(refundTool, run) },
});
Records each LLM request and step output; a blocking rule trips Mastra's TripWire. Download mastra-processor.mjs
OpenAI Agents SDK
npm i https://attest.piratefly.com/dl/vetro-core-0.1.0.tgz https://attest.piratefly.com/dl/vetro-openai-agents-0.1.0.tgz
import { addTraceProcessor } from '@openai/agents';
import { Vetro } from '@vetro/core';
import { createVetroTracingProcessor } from '@vetro/openai-agents';
const run = new Vetro().startRun({ name: 'my-agent' });
addTraceProcessor(createVetroTracingProcessor(run));
// ... run your agents as usual ...
run.end();
Generation spans become LLM events (usage normalized by @vetro/openai), function spans become tool calls, handoffs and guardrails are recorded too. Single-file version: openai-agents-tracer.mjs
Claude Code (hook) adapter file
Record every tool a coding agent uses, and block the ones your policy denies. Run vetro init in the project (it writes vetro.policy.json), save claude-code-hook.mjs next to it, then add to .claude/settings.json:
{
"hooks": {
"PreToolUse": [{ "hooks": [{ "type": "command", "command": "node claude-code-hook.mjs" }] }],
"PostToolUse": [{ "hooks": [{ "type": "command", "command": "node claude-code-hook.mjs" }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "node claude-code-hook.mjs" }] }]
}
}
Tool calls and results are buffered per session and sealed into one signed ledger at Stop. tool.deny and content.regex rules block in real time (exit code 2); budget rules are evaluated at Stop. Try it without Claude Code: node claude-code-hook.mjs --demo.
n8n community node
A Vetro node for your AI agent workflows, with zero runtime dependencies. Record Ledger turns the input items into one hash-chained ledger (ed25519-signed if you add a PEM key to the credential), Verify Ledger catches any edited, dropped or reordered event, Attest Ledger returns a public verification link for your auditor. Self-hosted n8n:
mkdir -p ~/.n8n/nodes && cd ~/.n8n/nodes npm i https://attest.piratefly.com/dl/vetro-n8n-nodes-vetro-0.1.0.tgz # restart n8n, then search "Vetro" in the nodes panel
Docker: run the same npm i inside the volume mounted at /home/node/.n8n/nodes. Typical flow: AI Agent → Vetro: Record Ledger → Vetro: Attest Ledger → Slack / Email with the link. Record and Verify are free and run offline; Attest needs a vk_ key from the Continuous plan.
OpenTelemetry / OTLP
Already tracing with OpenTelemetry GenAI conventions (Langfuse, LangSmith, Arize Phoenix, Helicone, a Collector)? No SDK change: export the trace as OTLP/JSON and drop it on the verify box, or convert locally:
vetro otel import trace.json --out-dir .vetro/imported # OTel GenAI trace -> ledger vetro otel export .vetro/runs/run.vtl -o trace.json # ledger -> OTLP/JSON spans
Programmatic: importOtlpToLedgers(payload) and exportLedgerToOtlp(events) from @vetro/otel. Step-by-step exports: Langfuse · LangSmith · Arize Phoenix · Helicone.
MCP server: EU AI Act tools
A local stdio MCP server (no API key, no network) with classify_high_risk, penalty_estimate, gpai_obligations, log_retention and verify_ledger, for Claude Desktop, Claude Code, Cursor and any MCP client:
{ "mcpServers": { "eu-ai-act": { "command": "npx", "args": ["-y", "@vetro/mcp-ai-act"] } } }
claude mcp add eu-ai-act -- npx -y @vetro/mcp-ai-act
GitHub Action
Fail the build when any committed agent ledger has a broken hash chain or signature; optionally get each one countersigned:
# .github/workflows/agent-ledger.yml
name: agent-ledger
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: vetro/verify-action@v1
with:
ledger-glob: '.vetro/runs/*.vtl'
# anchor-file: '.vetro/anchors.jsonl'
# attest-api-key: ${{ secrets.VETRO_ATTEST_KEY }}
Then: verify free, countersign for your auditor
Any ledger from any of these integrations verifies with vetro verify .vetro/runs/*.vtl or on the home page. When it verifies, you can get the EU AI Act record-keeping report: a third-party countersignature, a PDF mapping the log to Art. 12, 14, 26 and 86, and a public link anyone can check.