Repository navigation
Integrations Vercel AI
Experimental: this works and is tested, but may change and gets less hardening than the stable core.
tracekitAI (@cygnuxlabs/tracekit/v2/vercel-ai, in the TypeScript SDK) gates the
tool calls of a Vercel AI SDK v7 app: before each tool runs, the Tracekit signer decides it (an ask waits for a
person), and the call is recorded after it runs. Its middleware records each model response. It works with
generateText, streamText and ToolLoopAgent.
Node 18 or newer:
npm install @cygnuxlabs/tracekit ai@7npm also installs the signer package for your platform (@cygnuxlabs/tracekit-signer-<platform>: Apple Silicon
macOS, Linux x64 and arm64 with glibc, Windows x64), which bundles a Python, so a dev signer starts without one. On an
Intel Mac or Alpine there is none: pip install tracekit-ai.
Tested by the TypeScript adapter contract against the real signer, and in CI by
examples/v2_vercel_ai.mjs against ai 7 with a mock model (no API
key).
import { openai } from "@ai-sdk/openai"; // any provider
import { generateText, wrapLanguageModel } from "ai";
import { Client } from "@cygnuxlabs/tracekit";
import { tracekitAI } from "@cygnuxlabs/tracekit/v2/vercel-ai";
const client = new Client(); // the local signer; a dev signer is started if none answers
const run = await client.registerRun("assistant");
const tk = tracekitAI(run);
const model = wrapLanguageModel({ model: openai("gpt-5"), middleware: tk.middleware });
const r = await generateText({ model, tools: tk.tools({ pay }), toolApproval: tk.toolApproval, messages });
// asks end the step with tool-approval-request parts; once decided in the signer:
messages.push(...r.response.messages, { role: "tool", content: await tk.approvalResponses(r.content) });
await run.close();
await client.close();Or let instrument() register the run and close it when the process is about to exit: const tk = await instrument() (from @cygnuxlabs/tracekit), then tk.ai.middleware, tk.ai.tools(...) and tk.ai.toolApproval.
ES modules can't be patched from outside, so you pass the adapters to the SDK yourself. Then tracekit last exports
the run, pins the dev signer's key and verifies it.
A server registers a run per conversation and makes it current around each request with
withRun(run, () => generateText(...)); exit handling and the LLM gateway are in the
TypeScript SDK.
-
Decides the model's raw arguments.
tk.middlewarerecords each model response (V3 usage, the tool calls asked for) and keeps each call's raw arguments bytoolCallIdfor the decision. -
Maps the signer's decision onto the SDK's approvals.
tk.toolApprovalmapsdenytodeniedandasktouser-approval; without it anaskis refused. Adenyreaches the model as the tool's error result and the run goes on. -
Runs only what the signer approved.
tk.tools()wraps eachexecute: every call, allowed or approved, runs only after the signer'sapproval_consumeagrees, so a forged or replayedtool-approval-responseruns nothing.experimental_toolApprovalSecret(the SDK's HMAC over its own approval requests) may be set too; it does not replace the signer's check. -
Fails closed on a refusal. The run's fail mode applies only when the signer can't be reached at the decision; a
refusal, or a failure while waiting for an approval, never lets the call run. Recording a finished call never throws
and never changes its result (a failure is a
TracekitWarning).
MCP tools (@ai-sdk/mcp): tk.tools(await client.tools(), { mcp: "filesystem" }) decides each as
mcp:filesystem/<tool>. Your own toolApproval (a function, or one per tool name) composes with the signer's:
toolApproval: tk.toolApprovalWith(mine) asks the policy first, and your answer applies only to a call the policy
allows (a call you deny is recorded as refused; one you answer user-approval and then deny in your own UI stays
decided and not completed); tk.toolApproval alone replaces yours.
tk.middleware commits to each response's content, its reasoning parts included, but doesn't send the content: the
reasoning isn't readable from this record. Use the LLM gateway for readable reasoning. Which frameworks and providers return readable reasoning, and how to turn it on: reasoning.
- Tools without
executeand provider-executed tools are not gated; they appear in the recorded model responses. WithouttoolApproval, the adapter keeps the arguments of up to 4,096 such calls (limits). - Spans from
@ai-sdk/otelare telemetry, not evidence: the signed records are the middleware's and the adapter's. - An MCP tool's server isn't tied to the model's call by a bare tool name, so rules keyed on the server don't apply (limits).
- With a remote signer, the agent's identity needs grants for the RPCs the adapter calls,
approval_listincluded (limits).
Generated from docs/ at v1.4.1. Edit the docs in the repository, not here.
Get started
- Quickstart: the v2 signer
- Quickstarts
- Quickstart: Claude Agent SDK
- Quickstart: a custom agent
- Quickstart: LangChain and LangGraph
- Quickstart: MCP client
- Quickstart: OpenAI Agents SDK
- Coding agents other than Claude Code
- tracekit doctor
- Walkthrough: Tracekit end to end
How it works
- How Tracekit works
- Overview
- The life of a tool call
- The evidence format
- Verification and assurance
- Witnesses and monitoring
- Policy
- Approvals
- Detection and containment
- Capture and completeness
- Custody
- Provenance and tracekit why
- Deployment and isolation
- Storage, durability and performance
- Integrations
- Security model
- Architecture
- tracekit why: architecture
Integrations
- Integrations
- Adapters
- OpenTelemetry
- Remote clients
- Kubernetes agent-sandbox
- agentgateway
- agentsh and Tracekit
- Browser Use
- Claude Agent SDK
- Claude Code's sandbox
- Codex's sandbox
- CrewAI
- Docker MCP Gateway
- E2B
- Falco
- Gemini CLI's sandbox
- Google ADK
- Haystack
- LangChain v1
- LiteLLM
- LlamaIndex
- MCP client
- microsandbox
- Microsoft Agent Framework
- OpenAI Agents SDK
- NVIDIA OpenShell
- Pydantic AI
- sandbox-runtime's proxy on its own
- Strands Agents
- Tetragon
- Vercel AI SDK
- Wassette
Policy and approvals
- Policy reference
- Approvals
- Findings
- Reading the model's reasoning
- Incidents and containment
- Webhooks
Deploy and operate
- Deploying the signer
- The signer as a container
- The signer on Kubernetes
- The compose stack
- Identity
- Tool executor
- MCP gateway
- LLM gateway
- Egress observation
- Witnesses
- Log monitor
- Record-key issuer
- Signer observability
- Viewer
- tracekit why: causal investigation and replay
- Migrating
- Platforms
Verify the evidence
- Reading a v2 verify report
- Evidence format v2
- Auditor guide
- Sample evidence bundle
- Signing
- What Tracekit guarantees
Security and privacy
- Threat model: the v2 signer
- Threat model: the v1 laptop signer
- HTTP security checklist
- Threat-model review packet
- Privacy
- Known limits and trade-offs
- What's stable
Compliance
- Compliance mapping
- EU AI Act
- ISO/IEC 42001
- NIST AI RMF and the Generative AI Profile
- OWASP Top 10 lists for LLM and agentic applications
Evaluation
Demos
- Demos
- Agent approvers within bounds
- Completeness and tamper evidence
- Detection and containment
- Network coverage: an egress observer
- Guardrails: allow, deny, or ask a person
- MCP tools, gated and recorded
- Prompt injection held by provenance
- Why: which input caused the action
Help