Setup

setupLangWatch()

Initializes the LangWatch client for Node.js or browser environments, enabling data collection and tracing for your LLM application. This is typically the first function you’ll call when integrating LangWatch.
import { setupLangWatch } from "langwatch/node";

await setupLangWatch({
  apiKey: process.env.LANGWATCH_API_KEY, // Optional, defaults to process.env.LANGWATCH_API_KEY
  endpoint: process.env.LANGWATCH_ENDPOINT_URL // Optional, defaults to LangWatch Cloud
});
apiKey
Optional<string>
default:"process.env.LANGWATCH_API_KEY"
Your LangWatch API key. It’s recommended to set this via an environment variable (e.g., LANGWATCH_API_KEY) and retrieve it using process.env.LANGWATCH_API_KEY.
endpoint
Optional<string>
default:"https://app.langwatch.ai"
The URL of the LangWatch backend where traces will be sent. Defaults to the LangWatch Cloud service. For self-hosted instances, you’ll need to provide this.
otelSpanProcessors
Optional<SpanProcessor[]>
default:"[]"
Additional OpenTelemetry span processors to add to the SDK. These will be added after the LangWatch SDK has been initialized. Not supported in browser environments.
otelSpanProcessingExcludeRules
Optional<SpanProcessingExcludeRule[]>
default:"[]"
Rules to filter out specific spans from being exported to LangWatch, based on span name or attributes. See SpanProcessingExcludeRule for details.
skipOpenTelemetryAutomaticSetup
Optional<boolean>
default:"false"
If true, skips the automatic setup of the OpenTelemetry SDK. You will need to setup the OpenTelemetry SDK yourself, and ensure that a SpanProcessor is added that will send traces to the LangWatch API.
disableAutomaticInputCapture
Optional<boolean>
default:"false"
If true, disables the automatic capture of input data in spans.
disableAutomaticOutputCapture
Optional<boolean>
default:"false"
If true, disables the automatic capture of output data in spans.

Tracing

getLangWatchTracer()

Returns a LangWatch tracer instance that provides enhanced tracing capabilities for LLM applications.
import { getLangWatchTracer } from "langwatch";

const tracer = getLangWatchTracer("my-service", "1.0.0");
name
string
required
The name of the tracer/service.
version
Optional<string>
default:"undefined"
The version of the tracer/service.
Returns
tracer
LangWatchTracer
A LangWatchTracer instance with enhanced methods for LLM observability.

LangWatchTracer

The LangWatchTracer extends the standard OpenTelemetry Tracer with additional methods for LLM observability.

Methods

startSpan
(name: string, options?: SpanOptions, context?: Context) => LangWatchSpan
Starts a new LangWatchSpan without setting it on context. This method does NOT modify the current Context.
startActiveSpan
(name: string, fn: (span: LangWatchSpan) => T) => T
Starts a new LangWatchSpan and calls the given function passing it the created span as first argument. The new span gets set in context and this context is activated for the duration of the function call.
withActiveSpan
(name: string, fn: (span: LangWatchSpan) => Promise<T> | T) => Promise<T>
Starts a new LangWatchSpan, runs the provided async function, and automatically handles error recording, status setting, and span ending. This is a safer and more ergonomic alternative to manually using try/catch/finally blocks.

LangWatchSpan

The LangWatchSpan extends the standard OpenTelemetry Span with additional methods for LLM observability.

GenAI Event Methods

addGenAISystemMessageEvent
(body: LangWatchSpanGenAISystemMessageEventBody, system?: string, attributes?: Record<string, AttributeValue>) => this
Adds a GenAI system message event to the span. This logs a system/instruction message sent to the model.
addGenAIUserMessageEvent
(body: LangWatchSpanGenAIUserMessageEventBody, system?: string, attributes?: Record<string, AttributeValue>) => this
Adds a GenAI user message event to the span. This logs a user/customer message sent to the model.
addGenAIAssistantMessageEvent
(body: LangWatchSpanGenAIAssistantMessageEventBody, system?: string, attributes?: Record<string, AttributeValue>) => this
Adds a GenAI assistant message event to the span. This logs an assistant/bot response, including tool calls if present.
addGenAIToolMessageEvent
(body: LangWatchSpanGenAIToolMessageEventBody, system?: string, attributes?: Record<string, AttributeValue>) => this
Adds a GenAI tool message event to the span. This logs a message from a tool/function invoked by the assistant.
addGenAIChoiceEvent
(body: LangWatchSpanGenAIChoiceEventBody, system?: string, attributes?: Record<string, AttributeValue>) => this
Adds a GenAI choice event to the span. This logs a model output choice, including finish reason and message content.

Span Configuration Methods

setType
(type: SpanType) => this
Set the type of the span (e.g., ‘llm’, ‘rag’, ‘tool’, etc). This is used for downstream filtering and analytics.
setRequestModel
(model: string) => this
Set the request model name for the span. This is typically the model name sent in the API request (e.g., ‘gpt-4’, ‘claude-3’).
setResponseModel
(model: string) => this
Set the response model name for the span. This is the model name returned in the API response, if different from the request.
setRAGContexts
(ragContexts: LangWatchSpanRAGContext[]) => this
Set multiple RAG contexts for the span. Use this to record all retrieved documents/chunks used as context for a generation.
setRAGContext
(ragContext: LangWatchSpanRAGContext) => this
Set a single RAG context for the span. Use this if only one context was retrieved.
setMetrics
(metrics: LangWatchSpanMetrics) => this
Set the metrics for the span.
setSelectedPrompt
(prompt: Prompt) => this
Set the selected prompt for the span. This will attach this prompt to the trace. If this is set on multiple spans, the last one will be used.
setInput
(input: unknown) => this
Record the input to the span as a JSON-serializable value. The input is stringified and stored as a span attribute for later analysis.
setInputString
(input: string) => this
Record the input to the span as a plain string. Use this for raw text prompts or queries.
setOutput
(output: unknown) => this
Record the output from the span as a JSON-serializable value. The output is stringified and stored as a span attribute for later analysis.
setOutputString
(output: string) => this
Record the output from the span as a plain string. Use this for raw text completions or responses.
setOutputEvaluation
(guardrail: boolean, output: EvaluationResultModel) => this
Set the evaluation output for the span.
recordEvaluation
(details: RecordedEvaluationDetails, attributes?: Attributes) => this
Record the evaluation result for the span.

Evaluation

runEvaluation()

Runs an evaluation using a saved evaluator or LangEvals evaluator.
import { runEvaluation } from "langwatch/evaluation";

// Using a saved evaluator
const result = await runEvaluation({
  slug: "sentiment-analyzer",
  data: {
    input: "I love this product!",
    output: "Positive sentiment detected."
  },
  asGuardrail: false
});

// Using a LangEvals evaluator
const result = await runEvaluation({
  evaluator: "sentiment",
  data: {
    input: "I love this product!",
    output: "Positive sentiment detected."
  },
  settings: {
    threshold: 0.5
  }
});
details
EvaluationDetails
required
The evaluation details. Can be either a SavedEvaluationDetails (using a saved evaluator) or LangEvalsEvaluationDetails (using a LangEvals evaluator).
Returns
result
SingleEvaluationResult
The evaluation result containing status, passed, score, and other details.

recordEvaluation()

Records an evaluation result manually.
import { recordEvaluation } from "langwatch/evaluation";

recordEvaluation({
  name: "Custom Evaluation",
  type: "custom",
  isGuardrail: false,
  status: "processed",
  passed: true,
  score: 0.95,
  label: "Excellent",
  details: "All checks passed.",
  cost: 0.001
});
details
RecordedEvaluationDetails
required
The evaluation details to record.
attributes
Optional<Attributes>
default:"undefined"
Additional OpenTelemetry attributes to add to the evaluation span.

Prompt Management

getPrompt()

Retrieves a prompt from the LangWatch platform.
import { getPrompt } from "langwatch/prompt";

// Get a prompt without variables
const prompt = await getPrompt("prompt-id");

// Get a prompt with variables (returns compiled prompt)
const compiledPrompt = await getPrompt("prompt-id", {
  user_name: "John",
  product_name: "LangWatch"
});
id
string
required
The ID of the prompt to retrieve.
variables
Optional<TemplateVariables>
default:"undefined"
Template variables to compile the prompt with. If provided, returns a compiled prompt.
Returns
prompt
Prompt | CompiledPrompt
The prompt or compiled prompt object.

getPromptVersion()

Retrieves a specific version of a prompt from the LangWatch platform.
import { getPromptVersion } from "langwatch";

// Get a prompt version without variables
const promptVersion = await getPromptVersion("prompt-id", "version-id");

// Get a prompt version with variables (returns compiled prompt)
const compiledPromptVersion = await getPromptVersion("prompt-id", "version-id", {
  user_name: "John",
  product_name: "LangWatch"
});
id
string
required
The ID of the prompt to retrieve.
versionId
string
required
The ID of the specific version to retrieve.
variables
Optional<TemplateVariables>
default:"undefined"
Template variables to compile the prompt with. If provided, returns a compiled prompt.
Returns
prompt
Prompt | CompiledPrompt
The prompt version or compiled prompt object.
Throws
error
Error
Throws an error if the specified prompt version is not found.

Processors

FilterableBatchSpanProcessor

A span processor that filters spans before processing them.
import { FilterableBatchSpanProcessor } from "langwatch/observability";
import { LangWatchExporter } from "langwatch/observability";

const processor = new FilterableBatchSpanProcessor(
  new LangWatchExporter(), // Uses environment variables
  [
    {
      fieldName: "span_name",
      matchValue: "health-check",
      matchOperation: "exact_match"
    }
  ]
);
exporter
SpanExporter
required
The span exporter to use.
excludeRules
SpanProcessingExcludeRule[]
required
Rules to exclude spans from processing.

LangChain Integration

LangWatchCallbackHandler

A LangChain callback handler that automatically traces LangChain operations and integrates them with LangWatch.
import { LangWatchCallbackHandler } from "langwatch/observability/instrumentation/langchain";
import { ChatOpenAI } from "@langchain/openai";

const handler = new LangWatchCallbackHandler();
const llm = new ChatOpenAI({
  callbacks: [handler]
});

// All operations will now be automatically traced
const response = await llm.invoke("Hello, world!");
The LangWatchCallbackHandler automatically:
  • Creates spans for LLM calls, chains, tools, and retrievers
  • Captures input/output data
  • Sets appropriate span types and metadata
  • Handles errors and status codes
  • Integrates with the LangWatch tracing system

convertFromLangChainMessages

Utility function to convert LangChain messages to a format compatible with LangWatch GenAI events.
import { convertFromLangChainMessages } from "langwatch/observability/instrumentation/langchain";
import { HumanMessage, SystemMessage } from "@langchain/core/messages";

const messages = [
  new SystemMessage("You are a helpful assistant."),
  new HumanMessage("Hello!")
];

const convertedMessages = convertFromLangChainMessages(messages);
// Use with span.addGenAIUserMessageEvent(), etc.

Exporters

LangWatchExporter

A LangWatch exporter for sending traces to the LangWatch platform. Extends the OpenTelemetry OTLP HTTP trace exporter with proper authentication and metadata headers.
import { LangWatchExporter } from "langwatch/observability";

// Using environment variables/fallback configuration
const exporter = new LangWatchExporter();

// Using custom API key and endpoint
const exporter = new LangWatchExporter('api-key', 'https://custom.langwatch.com');
apiKey
Optional<string>
default:"getApiKey()"
Optional API key for LangWatch authentication. If not provided, will use environment variables or fallback configuration.
endpointURL
Optional<string>
default:"getEndpoint()"
Optional custom endpoint URL for LangWatch ingestion. If not provided, will use environment variables or fallback configuration.
The exporter automatically configures:
  • Authorization headers using the provided API key or environment variables/fallback
  • SDK version and language identification headers
  • Proper endpoint configuration for LangWatch ingestion using provided URL or environment variables/fallback

Semantic Conventions

The langwatch/observability module provides semantic convention constants for consistent attribute naming and event types across the LangWatch ecosystem.

Attributes

import { semconv } from "langwatch/observability";

// LangWatch-specific attributes
semconv.ATTR_LANGWATCH_INPUT           // "langwatch.input"
semconv.ATTR_LANGWATCH_OUTPUT          // "langwatch.output"
semconv.ATTR_LANGWATCH_SPAN_TYPE       // "langwatch.span.type"
semconv.ATTR_LANGWATCH_RAG_CONTEXTS    // "langwatch.contexts"
semconv.ATTR_LANGWATCH_METRICS         // "langwatch.metrics"
semconv.ATTR_LANGWATCH_SDK_VERSION     // "langwatch.sdk.version"
semconv.ATTR_LANGWATCH_SDK_NAME        // "langwatch.sdk.name"
semconv.ATTR_LANGWATCH_SDK_LANGUAGE    // "langwatch.sdk.language"
semconv.ATTR_LANGWATCH_TIMESTAMPS      // "langwatch.timestamps"
semconv.ATTR_LANGWATCH_EVALUATION_CUSTOM // "langwatch.evaluation.custom"
semconv.ATTR_LANGWATCH_PARAMS          // "langwatch.params"
semconv.ATTR_LANGWATCH_CUSTOMER_ID     // "langwatch.customer.id"
semconv.ATTR_LANGWATCH_THREAD_ID       // "langwatch.thread.id"
semconv.ATTR_LANGWATCH_STREAMING       // "langwatch.gen_ai.streaming"
semconv.ATTR_LANGWATCH_PROMPT_ID       // "langwatch.prompt.id"
semconv.ATTR_LANGWATCH_PROMPT_VERSION_ID // "langwatch.prompt.version.id"
semconv.ATTR_LANGWATCH_PROMPT_VARIABLES // "langwatch.prompt.variables"
semconv.ATTR_LANGWATCH_PROMPT_SELECTED_ID // "langwatch.prompt.selected.id"
semconv.ATTR_LANGWATCH_PROMPT_VERSION_NUMBER // "langwatch.prompt.version.number"

// LangChain-specific attributes
semconv.ATTR_LANGWATCH_LANGCHAIN_TAGS  // "langwatch.langchain.tags"
semconv.ATTR_LANGWATCH_LANGCHAIN_EVENT_NAME // "langwatch.langchain.event_name"
semconv.ATTR_LANGWATCH_LANGCHAIN_RUN_ID // "langwatch.langchain.run.id"
semconv.ATTR_LANGWATCH_LANGCHAIN_RUN_TAGS // "langwatch.langchain.run.tags"
semconv.ATTR_LANGWATCH_LANGCHAIN_RUN_TYPE // "langwatch.langchain.run.type"
semconv.ATTR_LANGWATCH_LANGCHAIN_RUN_METADATA // "langwatch.langchain.run.metadata"
semconv.ATTR_LANGWATCH_LANGCHAIN_RUN_EXTRA_PARAMS // "langwatch.langchain.run.extra_params"
semconv.ATTR_LANGWATCH_LANGCHAIN_RUN_PARENT_ID // "langwatch.langchain.run.parent.id"

Events

import { semconv } from "langwatch/observability";

// GenAI event names
semconv.LOG_EVNT_GEN_AI_SYSTEM_MESSAGE    // "gen.ai.system_message"
semconv.LOG_EVNT_GEN_AI_USER_MESSAGE      // "gen.ai.user_message"
semconv.LOG_EVNT_GEN_AI_ASSISTANT_MESSAGE // "gen.ai.assistant_message"
semconv.LOG_EVNT_GEN_AI_TOOL_MESSAGE      // "gen.ai.tool_message"
semconv.LOG_EVNT_GEN_AI_CHOICE            // "gen.ai.choice"

// LangChain event names
semconv.EVNT_LANGWATCH_LANGCHAIN_CALLBACK // "langwatch.langchain.callback"

Values

import { semconv } from "langwatch/observability";

// GenAI system identifiers
semconv.VAL_GEN_AI_SYSTEM_OPENAI         // "openai"
semconv.VAL_GEN_AI_SYSTEM_ANTHROPIC      // "anthropic"
semconv.VAL_GEN_AI_SYSTEM_AWS_BEDROCK   // "aws.bedrock"
semconv.VAL_GEN_AI_SYSTEM_AZURE_AI_OPENAI // "azure.ai.openai"
semconv.VAL_GEN_AI_SYSTEM_GCP_GEMINI    // "gcp.gemini"
semconv.VAL_GEN_AI_SYSTEM_COHERE        // "cohere"
semconv.VAL_GEN_AI_SYSTEM_GROQ          // "groq"
semconv.VAL_GEN_AI_SYSTEM_MISTRAL_AI    // "mistral_ai"
semconv.VAL_GEN_AI_SYSTEM_PERPLEXITY    // "perplexity"
semconv.VAL_GEN_AI_SYSTEM_XAI           // "xai"

// GenAI finish reasons
semconv.VAL_GEN_AI_FINISH_REASON_STOP           // "stop"
semconv.VAL_GEN_AI_FINISH_REASON_LENGTH         // "length"
semconv.VAL_GEN_AI_FINISH_REASON_CONTENT_FILTER // "content_filter"
semconv.VAL_GEN_AI_FINISH_REASON_ERROR          // "error"
semconv.VAL_GEN_AI_FINISH_REASON_TOOL_CALLS    // "tool_calls"

Core Data Types

SpanType

Supported types of spans for LangWatch observability:
type SpanType = 
  | "span"
  | "llm"
  | "chain"
  | "tool"
  | "agent"
  | "guardrail"
  | "evaluation"
  | "rag"
  | "prompt"
  | "workflow"
  | "component"
  | "module"
  | "server"
  | "client"
  | "producer"
  | "consumer"
  | "task"
  | "unknown";

LangWatchSpanRAGContext

Context for a RAG (Retrieval-Augmented Generation) span.
document_id
string
required
Unique identifier for the source document.
chunk_id
string
required
Unique identifier for the chunk within the document.
content
string
required
The actual content of the chunk provided to the model.

LangWatchSpanMetrics

Metrics for a LangWatch span.
promptTokens
Optional<number>
The number of prompt tokens used.
completionTokens
Optional<number>
The number of completion tokens used.
cost
Optional<number>
The cost of the span.

SpanProcessingExcludeRule

Defines a rule to filter out spans before they are exported to LangWatch.
fieldName
'span_name'
required
The field of the span to match against. Currently, only "span_name" is supported.
matchValue
string
required
The value to match for the specified fieldName.
matchOperation
'includes' | 'exact_match' | 'starts_with' | 'ends_with'
required
The operation to use for matching.

LangWatchSpanGenAISystemMessageEventBody

Body for a system message event in a GenAI span.
content
Optional<string>
Content of the system message.
role
Optional<'system' | 'instruction'>
Role of the message (system or instruction).

LangWatchSpanGenAIUserMessageEventBody

Body for a user message event in a GenAI span.
content
Optional<string>
Content of the user message.
role
Optional<'user' | 'customer'>
Role of the message (user or customer).

LangWatchSpanGenAIAssistantMessageEventBody

Body for an assistant message event in a GenAI span.
content
Optional<string>
Content of the assistant message.
role
Optional<'assistant' | 'bot'>
Role of the message (assistant or bot).
tool_calls
Optional<ToolCall[]>
Tool calls made by the assistant.

LangWatchSpanGenAIToolMessageEventBody

Body for a tool message event in a GenAI span.
content
Optional<string>
Content of the tool message.
id
string
required
Tool call identifier.
role
Optional<'tool' | 'function'>
Role of the message (tool or function).

LangWatchSpanGenAIChoiceEventBody

Body for a choice event in a GenAI span.
finish_reason
string
required
Reason the generation finished.
index
number
required
Index of the choice.
message
Optional<Message>
Message content for the choice.

RecordedEvaluationDetails

Details for recording an evaluation.
evaluationId
Optional<string>
Unique identifier for the evaluation.
name
string
required
Name of the evaluation.
type
Optional<string>
Type of the evaluation.
isGuardrail
Optional<boolean>
Whether this is a guardrail evaluation.
status
Optional<'processed' | 'skipped' | 'error'>
Status of the evaluation.
passed
Optional<boolean>
Whether the evaluation passed.
score
Optional<number>
Score of the evaluation.
label
Optional<string>
Label for the evaluation result.
details
Optional<string>
Additional details about the evaluation.
cost
Optional<number | { currency: string; amount: number }>
Cost of the evaluation.
error
Optional<Error>
Error that occurred during evaluation.
timestamps
Optional<{ startedAtUnixMs: number; finishedAtUnixMs: number }>
Timestamps for the evaluation.

EvaluationResultModel

Result model for evaluation output.
status
'processed' | 'skipped' | 'error'
Status of the evaluation.
passed
Optional<boolean>
Whether the evaluation passed.
score
Optional<number>
Score of the evaluation.
details
Optional<string>
Additional details about the evaluation.
label
Optional<string>
Label for the evaluation result.
cost
Optional<{ currency: string; amount: number }>
Cost of the evaluation.
raw_response
Optional<any>
Raw response from the evaluation.

EvaluationDetails

Union type for evaluation details.
type EvaluationDetails = SavedEvaluationDetails | LangEvalsEvaluationDetails<EvaluatorTypes>;

SavedEvaluationDetails

Details for using a saved evaluator.
slug
string
required
The slug of the saved evaluator.
data
BasicEvaluationData | Record<string, unknown>
required
The evaluation data.
name
Optional<string>
Name for the evaluation.
contexts
Optional<RAGChunk[] | string[]>
Context data for the evaluation.
conversation
Optional<Conversation>
Conversation data for the evaluation.
asGuardrail
Optional<boolean>
Whether to run as a guardrail.
settings
Optional<Record<string, unknown>>
Settings for the evaluator.

LangEvalsEvaluationDetails

Details for using a LangEvals evaluator.
evaluator
EvaluatorTypes
required
The LangEvals evaluator type.
data
BasicEvaluationData | Record<string, unknown>
required
The evaluation data.
name
Optional<string>
Name for the evaluation.
contexts
Optional<RAGChunk[] | string[]>
Context data for the evaluation.
conversation
Optional<Conversation>
Conversation data for the evaluation.
asGuardrail
Optional<boolean>
Whether to run as a guardrail.
settings
Optional<Evaluators[T]['settings']>
Settings for the evaluator.

BasicEvaluationData

Basic evaluation data structure.
input
Optional<string>
Input text for evaluation.
output
Optional<string>
Output text for evaluation.
expected_output
Optional<unknown>
Expected output for evaluation.
contexts
Optional<RAGChunk[] | string[]>
Context data for evaluation.
expected_contexts
Optional<RAGChunk[] | string[]>
Expected context data for evaluation.
conversation
Optional<Conversation>
Conversation data for evaluation.

SingleEvaluationResult

Result of an evaluation.
status
'processed' | 'skipped' | 'error'
Status of the evaluation.
passed
Optional<boolean>
Whether the evaluation passed.
score
Optional<number>
Score of the evaluation.
label
Optional<string>
Label for the evaluation result.
details
Optional<string>
Additional details about the evaluation.
error
Optional<string>
Error message if the evaluation failed.
cost
Optional<{ currency: string; amount: number }>
Cost of the evaluation.

Prompt

A prompt object retrieved from the LangWatch platform.
id
string
Unique identifier for the prompt.
name
string
Name of the prompt.
updatedAt
string
Last update timestamp.
version
number
Version number.
versionId
string
Version identifier.
versionCreatedAt
string
Version creation timestamp.
model
string
Model used for the prompt.
prompt
string
The prompt template.
messages
Array
Array of message objects.
response_format
Optional<object>
Response format configuration.

CompiledPrompt

A compiled prompt with variables substituted.
content
string
The compiled prompt content with variables substituted.
original
Prompt
The original prompt object.

TemplateVariables

Template variables for prompt compilation.
type TemplateVariables = Record<string, string | number | boolean | object | null>;

PromptCompilationError

Error thrown when prompt compilation fails.
template
string
The template that failed to compile.
originalError
Optional<any>
The original compilation error.

Usage Examples

Basic Tracing

import { setup } from "langwatch/node";
import { getLangWatchTracer } from "langwatch";

await setup({ apiKey: process.env.LANGWATCH_API_KEY });

const tracer = getLangWatchTracer("my-service");

await tracer.withActiveSpan("process-request", async (span) => {
  span.setType("llm");
  span.setRequestModel("gpt-4");
  
  // Your LLM call here
  const response = await openai.chat.completions.create({
    model: "gpt-4",
    messages: [{ role: "user", content: "Hello!" }]
  });
  
  span.setOutput(response.choices[0].message.content);
  span.setMetrics({
    promptTokens: response.usage?.prompt_tokens,
    completionTokens: response.usage?.completion_tokens
  });
});

RAG Operations

await tracer.withActiveSpan("rag-query", async (span) => {
  span.setType("rag");
  
  // Retrieve documents
  const documents = await vectorStore.similaritySearch("query", 5);
  
  // Set RAG contexts
  span.setRAGContexts(documents.map(doc => ({
    document_id: doc.metadata.id,
    chunk_id: doc.metadata.chunk_id,
    content: doc.pageContent
  })));
  
  // Generate response
  const response = await llm.generate([documents, "query"]);
  span.setOutput(response);
});

Using Semantic Conventions

import { semconv } from "langwatch/observability";
import { getLangWatchTracer } from "langwatch";

const tracer = getLangWatchTracer("my-service");

await tracer.withActiveSpan("llm-call", async (span) => {
  // Use semantic convention attributes for consistency
  span.setAttribute(semconv.ATTR_LANGWATCH_SPAN_TYPE, "llm");
  span.setAttribute(semconv.ATTR_LANGWATCH_STREAMING, false);
  
  // Add GenAI events with proper system identifiers
  span.addGenAISystemMessageEvent(
    { content: "You are a helpful assistant." },
    semconv.VAL_GEN_AI_SYSTEM_OPENAI
  );
  
  span.addGenAIUserMessageEvent(
    { content: "Hello!" },
    semconv.VAL_GEN_AI_SYSTEM_OPENAI
  );
  
  // Record events with proper event names
  span.addEvent(semconv.LOG_EVNT_GEN_AI_ASSISTANT_MESSAGE, {
    content: "Hello! How can I help you today?"
  });
});