Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.voight.xyz/llms.txt

Use this file to discover all available pages before exploring further.

For autonomous agents, trading bots, ElizaOS characters, Solana Agent Kit flows, or anything you build in TS/JS — import the library directly.

Install

npm install @voightxyz/sdk
Requirements:
  • Node.js 18+ (uses global fetch)
  • Bun, Deno, browsers, and Cloudflare Workers all supported

Quick start

import { Voight } from '@voightxyz/sdk'

const voight = new Voight({
  agentId: 'trading-bot.sol',     // SNS domain recommended for autonomous agents
  apiKey: process.env.VOIGHT_KEY, // from voight.xyz/dashboard
})

await voight.log({
  reasoning: 'SOL/USDC spread 8bps — arb window open',
  toolExecuted: 'jupiter.swap',
  transaction: '4zK…9Fp',
  amount: { token: 'SOL', value: 1.5 },
  outcome: 'success',
})
Returns { ok: true, eventId, agentId } on success, { ok: false, error: { code, message } } on failure.

Constructor options

interface VoightOptions {
  agentId: string                   // required
  apiKey: string                    // required
  endpoint?: string                 // default: production
  defaults?: Record<string, unknown>  // merged into every event's metadata
  swallowErrors?: boolean           // default: true
  fetch?: typeof fetch              // override (for tests / older runtimes)
  privacyLevel?: PrivacyLevel       // override the per-event privacy level
}
OptionTypeDefaultPurpose
agentIdstringYour agent’s stable identifier. Recommend a SNS domain for autonomous bots (trading-bot.sol), a stable label for services (market-watcher).
apiKeystringFrom the dashboard. Required for ingestion.
endpointstringhttps://voight-production.up.railway.appOverride for self-hosted deployments.
defaultsobject{}Metadata merged into every event (e.g. { env: 'prod', region: 'us-east' }).
swallowErrorsbooleantrueWhen true, voight.log() never throws — failures return { ok: false }. Recommended for production.
fetchfunctionglobalThis.fetchInject a custom fetch (for tests, older runtimes).
privacyLevel'minimal' | 'standard' | 'full''full'For library mode, defaults to Full. Pass 'standard' to get local PII scrubbing.

The log() method

interface LogInput {
  type?: 'reasoning' | 'tool' | 'tx' | 'decision' | 'action' | 'error'
  input?: { prompt?: string; context?: Record<string, unknown> }
  reasoning?: string
  toolsConsidered?: string[]
  toolExecuted?: string
  transaction?: string         // Solana tx signature
  amount?: { token: string; value: number }
  outcome?: 'pending' | 'success' | 'failed'
  durationMs?: number
  errorMessage?: string
  model?: string
  tokens?: { input?: number; output?: number; total?: number }
  metadata?: Record<string, unknown>  // anything custom
  timestamp?: string | number  // ISO string or unix ms
}
All fields optional. The server normalises and defaults type: 'decision' if you don’t pass one. Retry behaviour:
  • 3 attempts by default
  • Exponential backoff
  • Respects Retry-After header on 429s
  • Swallowed by default (swallowErrors: true) — recommended for production agents that shouldn’t crash on observability failures

Examples

Trading bot

const voight = new Voight({
  agentId: 'arbitrage.sol',
  apiKey: process.env.VOIGHT_KEY,
  defaults: { strategy: 'mean-reversion', env: 'prod' },
})

// 1. Reasoning step
await voight.log({
  type: 'reasoning',
  reasoning: `SOL/USDC spread at ${spreadBps}bps, threshold ${thresholdBps}bps — open arb`,
})

// 2. Tool / tx
await voight.log({
  type: 'tx',
  toolExecuted: 'jupiter.swap',
  transaction: txSignature,
  amount: { token: 'SOL', value: 1.5 },
  outcome: 'success',
})

// 3. Error
try {
  await maybeFlakyOperation()
} catch (err) {
  await voight.log({
    type: 'error',
    outcome: 'failed',
    errorMessage: (err as Error).message,
  })
}

ElizaOS character (skill plugin)

// Until @voightxyz/eliza-skill ships, you can wire it manually:
import { Voight } from '@voightxyz/sdk'

const voight = new Voight({
  agentId: 'eliza-research-bot',
  apiKey: process.env.VOIGHT_KEY,
})

agent.on('beforeAction', async (action) => {
  await voight.log({ type: 'action', toolsConsidered: [action.name] })
})

agent.on('afterAction', async (action, result) => {
  await voight.log({
    type: 'action',
    toolExecuted: action.name,
    outcome: result.ok ? 'success' : 'failed',
    durationMs: result.elapsed,
  })
})
A native ElizaOS plugin (@voightxyz/eliza-skill) is on the roadmap and will simplify this to one line.

LangChain / LangGraph agent

import { Voight } from '@voightxyz/sdk'

const voight = new Voight({ agentId: 'lc-agent', apiKey: process.env.VOIGHT_KEY })

const callbacks = [{
  handleToolStart: async (tool, input) => {
    await voight.log({ type: 'action', toolsConsidered: [tool.name] })
  },
  handleToolEnd: async (output) => {
    await voight.log({ type: 'action', outcome: 'success' })
  },
  handleLLMEnd: async ({ generations, llmOutput }) => {
    await voight.log({
      type: 'reasoning',
      reasoning: generations[0]?.[0]?.text,
      tokens: {
        input: llmOutput?.tokenUsage?.promptTokens,
        output: llmOutput?.tokenUsage?.completionTokens,
      },
    })
  },
}]

Error types

type VoightError =
  | { code: 'invalid_payload'; message: string }   // your payload failed Zod validation
  | { code: 'unauthorized'; message: string }      // bad API key
  | { code: 'rate_limited'; message: string }      // 429
  | { code: 'network'; message: string }           // fetch failed
  | { code: 'server'; message: string }            // 5xx
  | { code: 'unknown'; message: string }
When swallowErrors: false, these throw. Otherwise they return as { ok: false, error }.

Privacy in library mode

By default, library callers send events as Full (no scrubbing). To opt into Standard scrubbing per-event:
import { Voight, scrubPii } from '@voightxyz/sdk'

// Manual scrubbing
await voight.log({
  reasoning: scrubPii(`API call with token ${apiKey}`),
})

// Or set a privacy level at construction time and let the SDK handle it
const voight = new Voight({
  agentId: 'my-bot',
  apiKey: process.env.VOIGHT_KEY,
  privacyLevel: 'standard',  // applies scrubPii to every event automatically
})
The same 12 PII patterns + Luhn-validated card detection apply. See the PII patterns reference.

check() and enforce() — v1.0

const decision = await voight.check({ action: 'swap', context: { amount: 50 } })
if (!decision.allow) return // blocked by policy
Today these return { allow: true, reason: 'not-implemented' } so you can instrument call sites now and flip a flag later. Real implementation ships in v1.0.

Next

HTTP API

For runtimes that don’t use npm at all.

POST /v1/events

Full HTTP API schema for events ingestion.