Skip to main content
Metadata and attributes are key-value pairs that allow you to add custom contextual information to your traces and spans. This enrichment is invaluable for debugging, analysis, filtering, and gaining deeper insights into your LLM application’s behavior. LangWatch distinguishes between two main types of custom data:
  • Trace Metadata: Information that applies to the entire lifecycle of a request or a complete operation.
  • Span Attributes: Information specific to a particular unit of work or step within a trace.
This tutorial will guide you through capturing both types using the Python SDK.

Trace Metadata

Trace metadata provides context for the entire trace. It’s ideal for information that remains constant throughout the execution of a traced operation, such as:
  • User identifiers (user_id)
  • Session or conversation identifiers (thread_id) - see Tracking Conversations
  • Application version (app_version)
  • Environment (env: "production")
  • A/B testing flags or variant names
  • Labels for filtering and categorization

Setting Trace Metadata

Inside any function decorated with @langwatch.trace(), use langwatch.get_current_trace().update() to attach metadata:
import langwatch
from openai import OpenAI

client = OpenAI()

@langwatch.trace()
def handle_message(user_id: str, message: str):
    langwatch.get_current_trace().update(metadata={
        "user_id": user_id,
        "environment": "production",
    })

    # your LLM pipeline logic here...
You can call .update() multiple times throughout your function as more context becomes available:
@langwatch.trace()
def handle_message(user_id: str, message: str):
    trace = langwatch.get_current_trace()

    trace.update(metadata={"user_id": user_id})

    # After detecting the language
    detected_language = detect_language(message)
    trace.update(metadata={"language": detected_language})

    # After classifying intent
    intent = classify_intent(message)
    trace.update(metadata={"intent": intent})

    # process the message...

Adding Labels to Traces

Labels are a special type of trace metadata that allows you to organize, filter, and categorize your traces in the LangWatch dashboard:
@langwatch.trace()
def handle_message(user_id: str, request_type: str):
    trace = langwatch.get_current_trace()

    if request_type == "support":
        trace.update(metadata={"labels": ["customer_support", "high_priority"]})
    elif request_type == "sales":
        trace.update(metadata={"labels": ["sales_inquiry"]})

    # process the request...

Span Attributes

Span attributes provide context for a specific operation or unit of work within a trace. They are useful for details that are relevant only to that particular step. Examples include:
  • For an LLM call span: model_name, prompt_template_version, temperature
  • For a tool call span: tool_name, api_endpoint, specific input parameters
  • For a RAG span: retrieved_document_ids, chunk_count
  • Custom business logic flags or intermediate results specific to that span.

Setting Span Attributes

Use langwatch.get_current_span().update() or the span context manager to set attributes on a specific span:
import langwatch

@langwatch.trace(name="ArticleGenerator")
def generate_article(topic: str):
    with langwatch.span(name="FetchResearchData", type="tool") as research_span:
        research_data = fetch_data(topic)
        research_span.update(
            source="internal_db",
            query_complexity="medium",
            items_retrieved=10
        )

    with langwatch.span(name="GenerateText", type="llm") as llm_span:
        llm_span.update(model="gpt-5", prompt_length=len(topic))
        article_text = generate(topic, research_data)
        llm_span.update(output_length=len(article_text), tokens_used=150)

    return article_text

Key Differences: Trace Metadata vs. Span Attributes

FeatureTrace MetadataSpan Attributes
ScopeEntire trace (e.g., a whole user request)Specific span (e.g., one LLM call, one tool use)
GranularityCoarse-grained, applies to the overall operationFine-grained, applies to a specific part of the operation
PurposeGeneral context for the entire operationSpecific details about a particular step or action
Examplesuser_id, thread_id, app_versionmodel_name, tool_parameters, retrieved_chunk_id
SDK Accesslangwatch.get_current_trace().update(metadata={...})span.update(key=value, ...) or span.set_attributes({...})
When to use which:
  • Use Trace Metadata for information that you’d want to associate with every single span within that trace, or that defines the overarching context of the request (e.g., who initiated it, what version of the service is running).
  • Use Span Attributes for details specific to the execution of that particular span. This helps in understanding the parameters, behavior, and outcome of individual components within your trace.

Viewing in LangWatch

All captured trace metadata and span attributes will be visible in the LangWatch UI.
  • Trace Metadata is typically displayed in the trace details view, providing an overview of the entire operation.
  • Span Attributes are shown when you inspect individual spans within a trace.
This rich contextual data allows you to:
  • Filter and search for traces and spans based on specific metadata or attribute values.
  • Analyze performance by correlating metrics with different metadata/attributes (e.g., comparing latencies for different user_ids or model_names).
  • Debug issues by quickly understanding the context and parameters of a failed or slow operation.