.agents/skills/llmobs-integration/references/plugin-architecture.md
Guide to implementing LLMObs plugins in dd-trace-js.
All LLMObs plugins extend LLMObsPlugin at packages/dd-trace/src/llmobs/plugins/base.js.
The base class handles span registration, context management, and lifecycle hooks. Plugins only need to implement two methods.
Defines span metadata for registration with LLMObs. Called at span start.
Returns an object with:
kind (string) — span type: 'llm', 'embedding', 'workflow', 'agent', 'tool', 'retrieval'name (string) — operation name (e.g. 'openai.chat.completions')modelProvider (string, optional) — provider name (e.g. 'openai', 'anthropic', 'google')modelName (string, optional) — model identifier (e.g. 'gpt-4', 'claude-3-sonnet')Return null to skip recording an LLMObs span for a given ctx entirely.
Extracts and tags LLM-specific data after the operation completes. Called in asyncEnd.
Responsibilities:
ctx.argumentsctx.resultthis._tagger methods (see below)Always tag inputs. On error, tag empty outputs. On success, tag outputs, metrics, and metadata.
start(ctx) — registers the LLMObs span, captures parent contextasyncEnd(ctx) — calls setLLMObsTags() to extract and tag dataend(ctx) — restores parent contextTag data using this._tagger, which provides:
tagLLMIO(span, inputMessages, outputMessages) — for llm spanstagEmbeddingIO(span, inputDocuments, outputDocuments) — for embedding spanstagRetrievalIO(span, inputDocuments, outputDocuments) — for retrieval spanstagTextIO(span, inputValue, outputValue) — for workflow, agent, tool spanstagMetadata(span, metadata) — model parameters (temperature, max_tokens, etc.)tagMetrics(span, metrics) — token usage (input_tokens, output_tokens, total_tokens)tagSpanTags(span, tags) — arbitrary key/value span tagstagPrompt(span, prompt) — prompt tracking metadataEach plugin class needs:
static integration — integration name (e.g. 'openai')static id — unique plugin ID (e.g. 'llmobs_openai')static prefix — diagnostic channel prefix (e.g. 'tracing:apm:openai:chat')Always tag empty outputs on error to ensure consistent span structure:
if (ctx.error) {
this._tagger.tagLLMIO(span, inputMessages, [{ content: '', role: '' }])
return
}
See existing plugins for complete working examples:
packages/dd-trace/src/llmobs/plugins/openai/index.js — simple messages array, standard token usagepackages/datadog-plugin-anthropic/src/llmobs.js — nested content arrays, different token field namespackages/datadog-plugin-google-genai/src/llmobs.js — contents/parts format, role normalizationpackages/dd-trace/src/llmobs/plugins/langgraph/index.js — orchestration, workflow span kind, no messages