Quickstart
Get started with Spect tracking in your AI application.
Installation
npm install @spect-tools/track
# or
pnpm add @spect-tools/trackPeer 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-sdkAPI 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
| Option | Type | Required | Description |
|---|---|---|---|
organizationId | string | Yes | Your organization identifier |
apiKey | string | Yes* | Spect API key (*not required if local: true) |
provider | string | No | Provider name override (e.g., 'openai', 'anthropic') |
operationName | string | No | Custom operation name for traces |
local | boolean | No | Local-only mode, skip sending to collector |