@dobbyai/collector
Capture telemetry from any Node.js / TypeScript AI agent and stream it to Dobby for governance, compliance, and observability.
What this gives you
Every agent run captured
Run lifecycle, LLM calls, tool invocations, agent steps — all stream to Dobby in 10-second batches. Visible in /dashboard/workloads/runs within ~5s of completion.
Policy Scanner auto-fires
Each captured run triggers a compliance scan against your org's Policy Templates (SOC 2 / GDPR / HIPAA / EU AI Act / ISO 42001). Verdicts surface in /dashboard/compliance.
tracing_enabled flips to configured
SDK auto-emits W3C traceparent per batch. The Surrounding-mode governance control "tracing_enabled" automatically marks your org as configured after the first run.
Zero runtime dependencies
Base @dobbyai/collector pulls no production deps — uses Node 18+ built-ins (fetch + crypto.randomUUID + node:async_hooks). Framework peer deps are optional, install only what you use.
Install
npm install @dobbyai/collectorManual API (any framework, recommended starting point)
Works with any agent code — no framework dependency. Verified end-to-end on prod 2026-05-17 with 6/6 telemetry fields green.
import { init, startRun, endRun, span, shutdown } from '@dobbyai/collector';
init({
apiKey: process.env.DOBBY_API_KEY!, // dsdk_* token from the wizard
connectorId: process.env.DOBBY_CONNECTOR_ID!, // wc_* connector id
agentAnchor: { agentKey: 'kyc-decisioner' }, // or DOBBY_AGENT_KEY — see below
});
const run = startRun({
name: 'weekly_report',
inputs: { week: '2026-W19' },
});
const docs = await span('retrieval', { kind: 'tool', inputs: { q: 'sales' } }, async () => {
return await retriever.invoke('sales');
});
const summary = await span('summarize', { kind: 'llm' }, async () => {
return await llm.invoke(docs);
});
endRun(run, { outputs: { summary }, status: 'success' });
await shutdown(); // forces final flushAgent identity (attestation)
Declare a stable agentKey — in code via agentAnchor, or with the DOBBY_AGENT_KEY environment variable. It is a name you choose and keep the same across deploys, not a secret and not an ID Dobby issues you. It is what lets Dobby resolve every run of this agent — across replicas and restarts — to one canonical entry in your org-wide Agent Register.
# Equivalent to passing agentAnchor: {...} to init()
export DOBBY_AGENT_KEY=kyc-decisioner # stable name for THIS agent
export DOBBY_AGENT_VERSION=2.3.1 # optional — recorded, never a merge key
export DOBBY_ENV=prod # optional
export DOBBY_AGENT_OWNER=risk-team # optionalWithout a declared key, runs are still fully collected, governed and scanned — but their identity is recorded as unverifiable, the agent gets no Agent Register entry, and it is reported as unattributed in the Agent Identity & Coverage section of an evidence pack. Dobby never infers a key for you: an inferred identity is an unprovable claim in an audit, so Dobby reports unverifiable rather than a false attestation.
Framework auto-instrumentation
Each handler is a subpath export — install only the peer dep for the framework you use. Base @dobbyai/collector pulls NO framework deps.
LangChain.js
Pass DobbyLangChainCallbackHandler to your AgentExecutor.invoke() — every chain.start/end, llm.start/end, tool.start/end, agent.step automatically emits a Dobby event. One workload_run per .invoke() call.
npm install @langchain/coreimport { init } from '@dobbyai/collector';
import { DobbyLangChainCallbackHandler } from '@dobbyai/collector/langchain';
init({ framework: 'langchain' });
const handler = new DobbyLangChainCallbackHandler();
// Pass to .invoke() / .stream() — every LangChain callback emits a Dobby event
const result = await agent.invoke(
{ input: 'What is the population of Reykjavik?' },
{ callbacks: [handler] },
);Mastra
wrapMastraAgent returns a Proxy that intercepts .generate() and .stream() calls. Same shape as the original Agent — no other code changes. Tool calls land as nested spans.
npm install @mastra/coreimport { init } from '@dobbyai/collector';
import { wrapMastraAgent } from '@dobbyai/collector/mastra';
import { Agent } from '@mastra/core';
init({ framework: 'mastra' });
const agent = wrapMastraAgent(
new Agent({ /* ... */ }),
{ agentName: 'research-bot' },
);
// Same shape as the original Agent — Proxy intercepts .generate() / .stream()
const result = await agent.generate('What is the weather?');Vercel AI SDK
trackVercelAiCall wraps generateText / generateObject Promises. vercelAiCallbacks returns { onStepFinish, onFinish } to spread into streamText. Tool calls + step events captured per call.
npm install ai @ai-sdk/openaiimport { trackVercelAiCall, vercelAiCallbacks } from '@dobbyai/collector/vercel-ai';
import { generateText, streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
init({ framework: 'vercel-ai' });
// Non-streaming
const result = await trackVercelAiCall(
'weekly_summary',
{ inputs: { topic: 'AI safety' } },
() => generateText({ model: openai('gpt-4o-mini'), prompt: '...', tools: {/*...*/} }),
);
// Streaming
const cbs = vercelAiCallbacks({ agentName: 'live_chat' });
const stream = streamText({
model: openai('gpt-4o-mini'),
prompt: '...',
...cbs,
});Ready to onboard a customer?
Use the step-by-step walkthrough — covers credential generation, framework-specific snippets, troubleshooting, and known gotchas. ~10–15 minutes end-to-end.
Walkthrough docContent capture (on by default)
Unlike Dobby’s OTLP connectors (Claude Code, OpenClaw), the Collector SDK captures content by default: run inputs and outputs, per-call LLM prompt and completion text, and tool arguments / outputs travel inside the events your instrumentation emits, and Dobby stores them with the run — so compliance scans can inspect real evidence out of the box. What lands is what your code sends; you control it client-side:
track('search_db', { kind: 'tool', captureArgs: false, captureReturn: false }, searchDb)— skip a tool’s arguments or return value (both default to true).span/startRun/endRunstore exactly theinputs/outputsyou pass — omit a field and it never leaves your process.
If a compliance scan reports unverifiable and its evidence gap names a missing prompt, tool arguments, or final output, the run reached Dobby without that content — pass inputs / outputs on your runs, keep captureArgs / captureReturn on, or use a framework handler (they capture LLM and tool content automatically). The connector-level capture_content toggle gates Dobby’s OTLP connectors only — it does not change what this SDK’s ingest stores.
capture* flags and trim your inputs / outputs for fields that must never leave.Related
- SDK overview — all 4 Dobby SDKs (Client + Collector × Python + Node)
- Python sister SDK — CrewAI integration — wire-protocol identical, server-side normalizer shared
- How traceparent unlocks the tracing_enabled governance control — applies equally to Node SDK (auto-emitted per batch)
- Source on GitHub