Spect

Quickstart

Get started with Spect tracking in your AI application.

Installation

npm install @spect-tools/track
# or
pnpm add @spect-tools/track

Peer Dependencies

# For Vercel AI SDK
npm install ai @ai-sdk/provider

# For OpenTelemetry export
npm install @opentelemetry/core @opentelemetry/sdk-trace-base

# For Claude Agent SDK
npm install @anthropic-ai/claude-agent-sdk

API key

You can get your API key from the Spect settings page.

AI SDK integration

Wrap your language model to enable automatic trace collection:

import { wrap } from '@spect-tools/track';
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';

const wrappedModel = wrap(openai('gpt-4o'), {
  organizationId: 'your-org-id',
  apiKey: 'your-spect-api-key',
});

const result = await generateText({
  model: wrappedModel,
  prompt: 'Hello!',
});

Claude Agent SDK integration

Track Claude Agent sessions:

import { query } from '@anthropic-ai/claude-agent-sdk';
import { wrapQuery } from '@spect-tools/track';

const spectQuery = wrapQuery(query, {
  organizationId: 'your-org-id',
  apiKey: 'your-spect-api-key',
});

const session = spectQuery({
  prompt: 'Build a hello world app',
  options: {
    model: 'claude-sonnet-4-6',
  },
});

for await (const message of session) {
  console.log(message);
}

Customizing Spect

Operation names

Set the trace operation name with providerOptions.spect.name:

await generateText({
  model: wrappedModel,
  prompt: 'Hello!',
  providerOptions: {
    spect: {
      name: 'my-operation',
    },
  },
});

Spect generates trace IDs automatically so multi-step calls from the same wrapped model stay correlated.

Manual observer API

Use the generic observer when you are building your own SDK adapter. Record transcript items on spans with messages; use the tool overlay for tool-call/tool-result correlation.

import { createObserver } from '@spect-tools/track';

const observer = createObserver({
  organizationId: 'your-org-id',
  apiKey: 'your-spect-api-key',
  provider: 'custom',
});

const session = observer.startSession({
  name: 'custom.agent',
  model: { modelId: 'my-model', provider: 'custom' },
});

session.startSpan({
  name: 'user',
  kind: 'user',
  status: 'ok',
  messages: [{ id: crypto.randomUUID(), role: 'user', content: 'Find acute asthma protocols.' }],
});

session.startSpan({
  name: 'evidence_search',
  kind: 'tool-call',
  status: 'ok',
  tool: {
    toolCallId: 'call_1',
    toolName: 'evidence_search',
    parameters: { query: 'acute asthma protocols' },
  },
  messages: [
    {
      id: crypto.randomUUID(),
      role: 'assistant',
      content: [
        {
          type: 'tool-call',
          toolCallId: 'call_1',
          toolName: 'evidence_search',
          input: { query: 'acute asthma protocols' },
        },
      ],
    },
  ],
});

session.startSpan({
  name: 'evidence_search.result',
  kind: 'tool-result',
  status: 'ok',
  tool: {
    toolCallId: 'call_1',
    toolName: 'evidence_search',
    result: { matches: 3 },
  },
  messages: [
    {
      id: crypto.randomUUID(),
      role: 'tool',
      content: [
        {
          type: 'tool-result',
          toolCallId: 'call_1',
          toolName: 'evidence_search',
          output: { type: 'json', value: { matches: 3 } },
        },
      ],
    },
  ],
});

await session.send();

Configuration Options

OptionTypeRequiredDescription
organizationIdstringYesYour organization identifier
apiKeystringYes*Spect API key (*not required if local: true)
providerstringNoProvider name override (e.g., 'openai', 'anthropic')
operationNamestringNoCustom operation name for traces
localbooleanNoLocal-only mode, skip sending to collector

On this page