- Core tracing (
github.com/langwatch/langwatch/sdks/go): the exporter, theTracer, theLangWatchSpanhelpers, span filtering and data capture. No provider dependencies. - Provider instrumentations (
github.com/langwatch/langwatch/sdks/go/instrumentation/<provider>): one module per provider, so importing one never pulls in the others’ SDKs. - REST client (
github.com/langwatch/langwatch/sdks/go/client): a typed client for the LangWatch API.
Installation
github.com/openai/openai-go/v3.
Core SDK (langwatch)
Setup
Create a LangWatch exporter and configure it as your tracer provider.NewExporter reads LANGWATCH_API_KEY from your environment automatically:
NewExporter:
There are two exporter constructors:
langwatch.NewFilteringExporter(wrapped, filters...) wraps any existing OTel exporter with LangWatch’s span filtering.
Tracer
Tracer() retrieves a LangWatchTracer instance, which is a thin wrapper around an OpenTelemetry Tracer.
Example:
LangWatchTracer
Tracer() returns a *langwatch.LangWatchTracer, which provides a Start method that mirrors OpenTelemetry’s but returns a *langwatch.Span, plus WithActiveSpan for scoped spans.
WithActiveSpan runs fn with a span that auto-ends and records error status, so you don’t manage defer span.End() or error recording yourself:
Span
The*langwatch.Span returned by tracer.Start embeds the standard trace.Span (so all OpenTelemetry span methods are available) and adds the LangWatch helper methods below. Every helper returns the span for chaining.
Input / Output
SetInput / SetOutput infer the value type (text, json, chat_messages, list, …) from the Go value; the typed variants force a specific type.
function
Records a value as the span’s input/output, inferring the type (
text for a string, json for a struct/map, …). Recorded as langwatch.input / langwatch.output.Example:function
Force the
text value type.function
Force the
json value type. Use for complex request/response objects.Example:function
Force the
chat_messages value type ([]langwatch.ChatMessage).Example:function
Force the
raw type, a list of nested typed values, or an explicit langwatch.TypedValue respectively.function
Record an
EvaluationResult as the span input/output.Multimodal / binary content
Build chat messages with text and binary attachments (audio / image / video / file). Inline bytes are externalised to a stored object by the ingest pipeline.TextMessage, MultiContentMessage (build ChatMessage values); TextPart, ImageURLPart, BinaryPart, BinaryURLPart, BinaryRefPart (build content parts).
Metrics, metadata & identity
function
Records token counts via the OTel-native
gen_ai.usage.* attributes (input / output / total / cached / reasoning).Example:function
Records cost and the
tokens_estimated flag (langwatch.metrics). Token counts go via SetGenAIUsage, not here.Example:function
Metadata blob hoisted to the trace (
langwatch.metadata). Reserved keys (thread_id, user_id, customer_id, labels) become trace identity; every other key is hoisted as a metadata.<key> trace attribute.Example:function
Reserved trace identity. All spans within the same trace share the same thread ID, grouping related interactions into a conversation.Example:
function
LLM invocation parameters (
langwatch.params).function
Attach a saved LangWatch prompt to the trace.
Model, provider & GenAI semconv
Handy when instrumenting manually. These map directly to OpenTelemetry GenAI semantic conventions.function
Sets
gen_ai.request.model (the model you requested) and gen_ai.response.model (the model that actually answered). Providers answer with the dated build they served, so the response model is normally a longer identifier than the one you requested. Setting both is what lets you see, later, which build produced a given output.Example:function
Sets
gen_ai.provider.name and gen_ai.operation.name.function
Sets
gen_ai.request.*: temperature, top_p, max_tokens, stop, reasoning_effort, and so on.function
Sets
gen_ai.response.finish_reasons.Categorization & context
function
Sets the span type for categorization in LangWatch, enabling specialized UI treatment and analytics. See LangWatch Span Types.Example:
function
Attach retrieved context chunks for RAG analysis (
langwatch.rag.contexts).Example:function
Fine-grained timing, including first-token time for streaming.Example:
Evaluations & events
function
Records an evaluation result against the span’s trace (e.g. an LLM judge or guardrail score). The same
langwatch.Evaluation value can be submitted later by trace id via the API client.function
Records a tracked event on the span’s trace.
RecordThumbsUp / RecordThumbsDown are conveniences for capturing thumbs feedback live; the optional string is freeform feedback.function
Sets metadata directly on the trace from any span within it.
SetTraceMetadata takes OTel key-values; SetTraceMetadataMap is the bulk map convenience.Automatic Instrumentation
Each provider instrumentation is a separate Go module so importing one never pulls in the others’ SDKs. Add only the one(s) you use. Every instrumentation captures request + response model, all token types (input / output / total / cached / reasoning / cache-creation), cost where the provider returns it, finish reasons, request params, system instructions, tool definitions and (capture-gated) input/output.OpenAI middleware
The…/instrumentation/openai package provides middleware for the official openai-go/v3 client. It dispatches by request/response shape, so Chat Completions, the Responses API and Embeddings are all captured (with a generic fallback for any other OpenAI-compatible endpoint), with full streaming reconstruction.
...Option):
function
Controls whether request (input) and response (output) content is recorded at the source. Defaults to
langwatch.DataCaptureAll, so input and output are captured by default.Example:function
Sets the
gen_ai.provider.name attribute on spans. Defaults to "openai". Use this when pointing the middleware at an OpenAI-compatible provider.Example:gen_ai.provider.name is the GenAI semantic-convention attribute for the provider. WithGenAISystem is a thin alias for this option.function
Specifies the
trace.TracerProvider to use. Defaults to the global provider.function
Specifies OTel propagators. Defaults to the global propagators.
WithDataCapture, WithGenAIProvider, WithTracerProvider); the HTTP-transport instrumentations (Gemini, Ollama, gopenai) and the Bedrock smithy middleware expose WithDataCapture, WithGenAIProvider and WithTracerProvider too. See each provider’s guide for its exact constructor.
Collected Attributes
The instrumentations add attributes to the client span, following the OpenTelemetry GenAI Semantic Conventions where applicable. The OpenAI middleware records: Request Attributes:gen_ai.provider.name(e.g.openai)gen_ai.request.modelgen_ai.request.temperature,gen_ai.request.top_pgen_ai.request.max_tokens(frommax_completion_tokens/max_tokens/max_output_tokens)gen_ai.request.frequency_penalty,gen_ai.request.presence_penaltygen_ai.request.stop_sequences,gen_ai.request.seed,gen_ai.request.choice_countgen_ai.request.reasoning_effortgen_ai.request.encoding_formats,gen_ai.embeddings.dimension.count(embeddings)langwatch.instructions(Responses API)gen_ai.request.stream(boolean)gen_ai.operation.name(e.g.chat,embeddings,responses)langwatch.input(when input capture is enabled)
gen_ai.response.idgen_ai.response.modelgen_ai.response.finish_reasonsgen_ai.response.status(Responses API)gen_ai.usage.input_tokens,gen_ai.usage.output_tokens,gen_ai.usage.total_tokensgen_ai.usage.cached_input_tokens,gen_ai.usage.reasoning.output_tokens(when returned)gen_ai.openai.response.system_fingerprintlangwatch.output(when output capture is enabled; for streaming this is the reconstructed textual content)
http.request.method, url.path, server.address, http.response.status_code) are also included. Other providers map their native token kinds onto the same gen_ai.usage.* attributes; for example Anthropic and Bedrock add gen_ai.usage.cache_creation.input_tokens for cache-creation tokens. See each provider’s guide for the exact list.
Data Capture
Data capture controls whether span input/output content leaves the process. It is enforced at export time, so one setting governs every instrumentation (the provider middlewares and your manual spans alike). Span structure, metrics, metadata, models and identity are always kept; only the content attributes (langwatch.input / langwatch.output and the gen_ai.* message/prompt/completion equivalents) are stripped. The default, unconfigured, captures everything.
Each instrumentation also accepts
WithDataCapture(mode) to gate content at the source for a single client. The two compose: the middleware gates content at the source, and the exporter strips content at export time. The exporter option is the recommended place for a uniform policy; the per-instrumentation option is handy when you only want to change behaviour for one client.
Filtering
Control which spans are exported to reduce noise and focus on what matters.Preset Filters
Custom Filters
UseInclude() to keep matching spans or Exclude() to remove them:
Criteria matches on ScopeName (the InstrumentationScope.Name) and/or SpanName (the Span.Name).
Matchers
Multiple filters use AND semantics (a span must pass all). Within a
Criteria, matchers use OR semantics (a span matches if any matcher matches); multiple fields in a Criteria use AND.LangWatch Span Types
SpanType is a string constant used with span.SetType() to categorize spans in LangWatch for specialized UI treatment and analytics.
Using these span types is optional but highly recommended, as it enables LangWatch to provide more tailored insights and visualizations for your traces.
API Client
Thegithub.com/langwatch/langwatch/sdks/go/client module is a typed REST client for the LangWatch API. It is separate from tracing and lives in its own module so its generated code stays out of the core graph.
Installation
Quick start
Services
Reach resources through the service fields on*client.Client. Every method takes a context.Context first and returns a typed error on failure.
Prompts, the flagship service:
langwatch.Event / langwatch.Evaluation types as the live span.RecordEvent / span.RecordEvaluation, so a value can be recorded live or submitted later interchangeably:
Error handling
Every method returns a typed*client.APIError for any non-2xx response, carrying the HTTP status, decoded message, the operation that failed and the raw body. Convenience helpers cover the common cases:
Pagination & iterators
The API uses offset (page / limit) and cursor pagination. The single-page List / Search / ListRuns methods return the page plus its metadata for manual paging. For large result sets, each heavy service exposes a range-over-func iterator (iter.Seq2[T, error]) that fetches one page at a time, so memory stays flat:
Manual OpenTelemetry Setup
If you prefer manual setup or need more control, point a standard OTLP exporter at LangWatch’s collector endpoint:Environment Variables
Version Compatibility
- Go Version: 1.25 or later
- OpenAI Go SDK:
github.com/openai/openai-go/v3 - OpenTelemetry: the SDK tracks current OTel Go releases