@vigil/sdk Documentation
Instrument your LLM applications in under 5 minutes. Capture traces, monitor costs, detect hallucinations, and gain full observability over every model call, tool invocation, and agent workflow.
Installation
Install the SDK with your preferred package manager.
| 1 | bun add @vigil/sdk |
| 1 | npm install @vigil/sdk |
Quick Start
Four lines to full observability. Initialize Vigil, instrument your LLM client, make calls as usual, and flush before exit.
| 1 | import { Vigil } from '@vigil/sdk'; |
| 2 | import Anthropic from '@anthropic-ai/sdk'; |
| 3 | |
| 4 | // 1. Initialize Vigil |
| 5 | const vigil = new Vigil({ |
| 6 | apiKey: process.env.VIGIL_API_KEY, |
| 7 | projectId: 'my-project', |
| 8 | }); |
| 9 | |
| 10 | // 2. Instrument the Anthropic client |
| 11 | const anthropic = new Anthropic(); |
| 12 | vigil.instrument('anthropic', anthropic); |
| 13 | |
| 14 | // 3. Make calls as usual -- Vigil captures everything |
| 15 | const message = await anthropic.messages.create({ |
| 16 | model: 'claude-sonnet-4-20250514', |
| 17 | max_tokens: 1024, |
| 18 | messages: [{ role: 'user', content: 'Explain quantum computing' }], |
| 19 | }); |
| 20 | |
| 21 | // 4. Flush before process exit (serverless / scripts) |
| 22 | await vigil.flush(); |
Auto-Instrumentation
Wrap your existing SDK clients with a single call. Vigil intercepts all API requests and captures traces automatically -- no code changes to your business logic.
Anthropic SDK
| 1 | import Anthropic from '@anthropic-ai/sdk'; |
| 2 | |
| 3 | const anthropic = new Anthropic(); |
| 4 | vigil.instrument('anthropic', anthropic); |
| 5 | |
| 6 | // All messages.create() and messages.stream() calls |
| 7 | // are automatically traced with: |
| 8 | // - Model name, provider |
| 9 | // - Token counts (prompt + completion) |
| 10 | // - Cost (USD), computed from built-in pricing table |
| 11 | // - Latency (ms) |
| 12 | // - Full prompt and completion text |
OpenAI SDK
| 1 | import OpenAI from 'openai'; |
| 2 | |
| 3 | const openai = new OpenAI(); |
| 4 | vigil.instrument('openai', openai); |
| 5 | |
| 6 | // Traces chat.completions.create(), responses.create(), |
| 7 | // and streaming variants automatically. |
MCP Client
DifferentiatorVigil is the first observability SDK to treat MCP tool calls as first-class citizens. Every tool invocation is captured with full input/output payloads, server identity, and parent span linkage -- so you can see exactly which LLM call triggered which tool, and how long each tool took.
| 1 | import { Client } from '@modelcontextprotocol/sdk/client/index.js'; |
| 2 | |
| 3 | const mcpClient = new Client({ |
| 4 | name: 'my-app', |
| 5 | version: '1.0.0', |
| 6 | }); |
| 7 | |
| 8 | vigil.instrument('mcp', mcpClient); |
| 9 | |
| 10 | // Every MCP tool call is now traced: |
| 11 | // - Tool name and server identity |
| 12 | // - Input arguments and output results |
| 13 | // - Latency per tool invocation |
| 14 | // - Parent span linkage (which LLM call triggered this tool?) |
| 15 | // |
| 16 | // This is the only observability SDK that treats |
| 17 | // MCP tool calls as first-class spans. |
Vercel AI SDK
| 1 | import { generateText, streamText } from 'ai'; |
| 2 | |
| 3 | vigil.instrument('vercel-ai', { generateText, streamText }); |
| 4 | |
| 5 | // Works with any Vercel AI SDK provider: |
| 6 | // anthropic, openai, google, mistral, etc. |
| 7 | // Traces model, tokens, cost, and latency. |
Manual Tracing
For full control over your trace hierarchy, use the manual tracing API. Create traces, then attach typed spans for LLM calls, tool invocations, agent workflows, or arbitrary operations.
| Method | Span Kind | Use Case |
|---|---|---|
| trace.span() | generic | Any custom operation |
| trace.llm() | llm | LLM API calls with token/cost tracking |
| trace.tool() | tool | Tool or MCP tool invocations |
| trace.agent() | agent | Agent workflows (wraps child spans) |
| 1 | // Create a trace for a multi-step workflow |
| 2 | const trace = vigil.trace('research-workflow'); |
| 3 | |
| 4 | // LLM span |
| 5 | const llmSpan = trace.llm('generate-outline', { |
| 6 | model: 'claude-sonnet-4-20250514', |
| 7 | provider: 'anthropic', |
| 8 | }); |
| 9 | llmSpan.setInput({ messages: [{ role: 'user', content: '...' }] }); |
| 10 | // ... make the actual LLM call ... |
| 11 | llmSpan.setOutput({ completion: '...' }); |
| 12 | llmSpan.setTokens({ prompt: 150, completion: 420 }); |
| 13 | llmSpan.end(); |
| 14 | |
| 15 | // Tool span |
| 16 | const toolSpan = trace.tool('web-search', { |
| 17 | toolName: 'brave_search', |
| 18 | toolServer: 'brave-mcp', |
| 19 | }); |
| 20 | toolSpan.setInput({ query: 'latest AI research' }); |
| 21 | // ... execute the tool call ... |
| 22 | toolSpan.setOutput({ results: ['...'] }); |
| 23 | toolSpan.end(); |
| 24 | |
| 25 | // Agent span (wraps other spans) |
| 26 | const agentSpan = trace.agent('research-agent', { |
| 27 | agentType: 'orchestrator', |
| 28 | }); |
| 29 | // ... agent logic with nested llm() and tool() spans ... |
| 30 | agentSpan.end(); |
| 31 | |
| 32 | // Generic span for custom operations |
| 33 | const span = trace.span('post-processing'); |
| 34 | // ... any custom logic ... |
| 35 | span.end(); |
| 36 | |
| 37 | trace.end(); |
Hallucination Detection
Vigil includes built-in hallucination detection that runs on every LLM span. Enable context grounding to score responses against your RAG source documents, or self-consistency to catch internal contradictions. Scores are attached to spans and surfaced in the dashboard.
Context Grounding
Compares LLM output against provided context chunks. Measures what percentage of response claims are supported by source documents.
Requires passing context via span.setContext()
Self-Consistency
Detects internal contradictions within a single response using rule-based NLI patterns. No external model required.
Always available, no configuration needed
| 1 | vigil.setHallucinationDetector({ |
| 2 | // Compare LLM output against provided RAG context. |
| 3 | // Scores how much of the response is grounded in source docs. |
| 4 | contextGrounding: true, |
| 5 | |
| 6 | // Detect internal contradictions within a single response. |
| 7 | // Uses rule-based NLI patterns (no external model needed). |
| 8 | selfConsistency: true, |
| 9 | |
| 10 | // Flag responses with a hallucination score above this value. |
| 11 | // Range: 0.0 (no hallucination) to 1.0 (fully hallucinated). |
| 12 | threshold: 0.7, |
| 13 | }); |
| 14 | |
| 15 | // When context grounding is enabled, pass context with your traces: |
| 16 | const span = trace.llm('rag-answer', { |
| 17 | model: 'claude-sonnet-4-20250514', |
| 18 | provider: 'anthropic', |
| 19 | }); |
| 20 | span.setContext([ |
| 21 | 'Source document chunk 1...', |
| 22 | 'Source document chunk 2...', |
| 23 | ]); |
| 24 | span.setInput({ messages: [{ role: 'user', content: '...' }] }); |
| 25 | // ... LLM call ... |
| 26 | span.setOutput({ completion: '...' }); |
| 27 | span.end(); |
| 28 | // Hallucination score is computed automatically and attached to the span. |
Configuration
All available options for the Vigil constructor. Only apiKey and projectId are required.
| 1 | import { Vigil, type VigilConfig } from '@vigil/sdk'; |
| 2 | |
| 3 | const vigil = new Vigil({ |
| 4 | // Required |
| 5 | apiKey: process.env.VIGIL_API_KEY, |
| 6 | projectId: 'my-project', |
| 7 | |
| 8 | // Endpoint (default: https://api.vigil.dev) |
| 9 | endpoint: 'https://api.vigil.dev', |
| 10 | |
| 11 | // Batching: flush traces in batches for efficiency |
| 12 | batchSize: 10, // Spans per batch (default: 10) |
| 13 | flushInterval: 5000, // Auto-flush interval in ms (default: 5000) |
| 14 | |
| 15 | // Sampling: control trace volume in production |
| 16 | sampleRate: 1.0, // 0.0 to 1.0 (default: 1.0 = capture all) |
| 17 | |
| 18 | // Payload limits |
| 19 | maxPayloadSize: 4096, // Bytes before offloading to R2 (default: 4096) |
| 20 | |
| 21 | // Debug mode: logs SDK activity to console |
| 22 | debug: false, // (default: false) |
| 23 | |
| 24 | // Hallucination detection (can also use setHallucinationDetector) |
| 25 | hallucination: { |
| 26 | contextGrounding: false, |
| 27 | selfConsistency: false, |
| 28 | threshold: 0.7, |
| 29 | }, |
| 30 | }); |
Self-Hosting
Run the full Vigil stack on your own infrastructure with Docker Compose. The self-hosted version uses SQLite for storage and MinIO as an S3-compatible blob store.
| 1 | # docker-compose.yml |
| 2 | version: '3.8' |
| 3 | |
| 4 | services: |
| 5 | vigil-api: |
| 6 | image: ghcr.io/vigil-dev/api:latest |
| 7 | ports: |
| 8 | - '8787:8787' |
| 9 | environment: |
| 10 | - DATABASE_URL=/data/vigil.db |
| 11 | - STORAGE_BACKEND=minio |
| 12 | - MINIO_ENDPOINT=minio:9000 |
| 13 | - MINIO_ACCESS_KEY=vigil |
| 14 | - MINIO_SECRET_KEY=vigilsecret |
| 15 | - MINIO_BUCKET=vigil-traces |
| 16 | volumes: |
| 17 | - vigil-data:/data |
| 18 | depends_on: |
| 19 | - minio |
| 20 | |
| 21 | vigil-dashboard: |
| 22 | image: ghcr.io/vigil-dev/dashboard:latest |
| 23 | ports: |
| 24 | - '3000:3000' |
| 25 | environment: |
| 26 | - VIGIL_API_URL=http://vigil-api:8787 |
| 27 | - NEXTAUTH_SECRET=your-secret-here |
| 28 | - NEXTAUTH_URL=http://localhost:3000 |
| 29 | |
| 30 | minio: |
| 31 | image: minio/minio:latest |
| 32 | command: server /data --console-address ":9001" |
| 33 | ports: |
| 34 | - '9000:9000' |
| 35 | - '9001:9001' |
| 36 | environment: |
| 37 | - MINIO_ROOT_USER=vigil |
| 38 | - MINIO_ROOT_PASSWORD=vigilsecret |
| 39 | volumes: |
| 40 | - minio-data:/data |
| 41 | |
| 42 | volumes: |
| 43 | vigil-data: |
| 44 | minio-data: |
| 1 | # Start the stack |
| 2 | docker compose up -d |
| 3 | |
| 4 | # Point your SDK to the self-hosted API |
| 5 | const vigil = new Vigil({ |
| 6 | apiKey: 'your-self-hosted-key', |
| 7 | projectId: 'my-project', |
| 8 | endpoint: 'http://localhost:8787', |
| 9 | }); |
API Reference
The Vigil REST API. All endpoints require a Bearer token in the Authorization header.
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/traces | Ingest a batch of traces and spans |
| GET | /v1/traces | List traces with filtering and pagination |
| GET | /v1/traces/:traceId | Get a single trace with all its spans |
| GET | /v1/traces/:traceId/spans | Get spans for a specific trace |
| GET | /v1/analytics/costs | Cost analytics grouped by model, agent, or tool |
| GET | /v1/analytics/hallucinations | Hallucination score trends and flagged spans |
| POST | /v1/prompts | Create a new prompt version |
| GET | /v1/prompts/:name/versions | List all versions of a named prompt |
| 1 | // All endpoints require Bearer token authentication |
| 2 | const response = await fetch('https://api.vigil.dev/v1/traces', { |
| 3 | method: 'GET', |
| 4 | headers: { |
| 5 | 'Authorization': 'Bearer YOUR_API_KEY', |
| 6 | 'Content-Type': 'application/json', |
| 7 | }, |
| 8 | }); |
| 9 | |
| 10 | const { traces, total } = await response.json(); |
| 11 | |
| 12 | // Query parameters for GET /v1/traces: |
| 13 | // project_id (required) Your project ID |
| 14 | // limit (optional) Results per page (default: 50) |
| 15 | // offset (optional) Pagination offset (default: 0) |
| 16 | // model (optional) Filter by model name |
| 17 | // status (optional) Filter by status: 'ok' | 'error' |
| 18 | // min_cost (optional) Minimum cost in USD |
| 19 | // max_cost (optional) Maximum cost in USD |
| 20 | // from (optional) Start datetime (ISO 8601) |
| 21 | // to (optional) End datetime (ISO 8601) |
Built by the Vigil team. Source on GitHub.