Back to Articles

LangWatch: OpenTelemetry-Native LLM Observability That Actually Closes the Feedback Loop

[ View on GitHub ]

LangWatch: OpenTelemetry-Native LLM Observability That Actually Closes the Feedback Loop

Hook

Most LLM teams use three different tools: one for logging, another for evaluations, and a third for prompt management. LangWatch argues this fragmentation is the root cause of why most LLM apps never make it past the prototype stage.

Context

The LLM tooling landscape has exploded into a maze of point solutions. You instrument your app with Langfuse for observability, export traces to Braintrust for evaluations, manage prompts in Helicone, and stitch it all together with custom scripts. Each transition is a friction point where teams lose momentum—traces don't automatically become test cases, evaluation insights don't flow back into monitoring, and regression testing requires manual dataset curation.

LangWatch emerged from this fragmentation problem with a contrarian thesis: the observability-to-evaluation-to-testing loop should be a single continuous workflow, not three disconnected tools. Built on OpenTelemetry primitives, it positions itself as the only platform where a production trace can automatically become an evaluation dataset entry, feed into a DSPy prompt optimization run, and generate regression tests—without leaving the platform or writing ETL glue code. For teams building complex AI agents that need end-to-end simulation testing and production governance, this unified approach promises to collapse weeks of integration work into a single deployment.

Technical Insight

LangWatch's architecture revolves around OpenTelemetry traces as the universal primitive that flows through every subsystem. When you instrument your application using their TypeScript or Python SDK, you're emitting standard OTLP spans—not vendor-specific events. This matters because it means you can swap out tracing backends or dual-write to multiple systems without rewriting instrumentation code.

Here's what basic instrumentation looks like with automatic LLM call detection:

import * as langwatch from 'langwatch';
import OpenAI from 'openai';

langwatch.init({
  apiKey: process.env.LANGWATCH_API_KEY,
});

const openai = langwatch.openai(new OpenAI());

// This call is automatically traced with input/output/metadata
const response = await openai.chat.completions.create({
  model: 'gpt-4',
  messages: [{ role: 'user', content: 'Explain quantum entanglement' }],
});

// Traces appear in LangWatch with latency, tokens, cost

The magic happens when these traces hit LangWatch's ingestion pipeline. Unlike simple logging systems, each trace gets enriched with automatic evaluations—hallucination detection via RAG triad scoring, PII detection, toxicity checks, and custom evaluators you define. This enrichment happens server-side using ClickHouse for columnar analytics, which makes it blazing fast to query across millions of traces with complex filters like "show me all Claude responses with latency > 2s where hallucination score > 0.7."

The most distinctive architectural piece is the AI Gateway, a separate Go binary that sits between your application and LLM providers. Unlike Python-based proxies that add 50-200ms of overhead, LangWatch's gateway adds ~700 nanoseconds on the hot path. It handles OpenAI and Anthropic-compatible requests with hierarchical budget enforcement, automatic fallback routing when a provider fails, and—critically—Anthropic's cache_control passthrough for prompt caching. You point your OpenAI SDK at the gateway URL, and it transparently proxies while capturing telemetry:

from openai import OpenAI

client = OpenAI(
    base_url="https://gateway.langwatch.ai/v1",
    api_key="your_actual_openai_key",
    default_headers={"X-LangWatch-Project": "proj_abc123"}
)

# Gateway captures this, enforces budgets, handles fallbacks
response = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Hello"}]
)

The feedback loop closes with Evaluations and Experiments. Any trace filter becomes a dataset with one click—say you want to optimize prompts based on last week's production failures. Select the traces, create a dataset, and run a DSPy optimizer against it. LangWatch supports PromptOptimizer, SignatureOptimizer, and custom evaluators, storing results back as traces. These optimized prompts feed into A/B tests using the Experiments feature, where you define variants and LangWatch tracks performance metrics across cohorts.

For agent testing, LangWatch provides simulation frameworks that go beyond simple prompt evaluation. You define user simulators, tool implementations, and expected state transitions, then run Monte Carlo simulations where the system spawns hundreds of agent conversations with random but realistic inputs. Each simulation run generates granular traces showing which tool got called, what the LLM decided at each step, and where failures occurred. This is invaluable for testing multi-step agents where traditional unit tests fail to catch emergent behaviors.

The local development experience deserves mention: instead of wrestling with Docker Compose, you run npx langwatch dev, and it auto-provisions PostgreSQL, Redis, and ClickHouse into ~/.langwatch/, starts the Next.js dev server, and opens your browser. It's the smoothest local setup I've seen for a multi-database application, though it does mean you have persistent database state living in a hidden directory that's easy to forget about.

Gotcha

The all-in-one approach is both LangWatch's strength and its Achilles heel. If you already have Datadog for observability and just need LLM-specific evaluations, LangWatch requires you to either duplicate your infrastructure (running it alongside existing tools) or migrate entirely. There's no incremental adoption path—you're either in or out. Teams with established observability pipelines will chafe at this, especially when LangWatch's 3.2K GitHub stars pale compared to Langfuse's 14K+ or Arize Phoenix's maturity.

Self-hosting complexity is real despite the slick local dev experience. Production deployments need PostgreSQL (for metadata), Redis (for caching), ClickHouse (for analytics), and the Go gateway binary. That's four services to monitor, backup, and scale independently. The Helm chart helps, but compare this to Langfuse which only needs Postgres, or Helicone which is stateless. If you're a small team without a dedicated platform engineer, the cloud offering is your only realistic option, which reintroduces vendor lock-in concerns despite the OpenTelemetry foundation.

The DSPy integration, while powerful, assumes you want automatic prompt optimization via gradient-free methods. If your team prefers manual prompt engineering or uses frameworks like LMQL for structured generation, LangWatch's optimization workflows feel opinionated and potentially constraining. There's also limited support for streaming responses in the gateway—it works, but trace granularity suffers compared to non-streamed calls.

Verdict

Use if: You're building production LLM applications with complex multi-step agents that need end-to-end simulation testing, your team is tired of stitching together three different SaaS tools with custom scripts, or you need governance features like hierarchical budget controls and automatic provider fallback in a high-performance gateway. The unified workflow from trace to evaluation to optimization is genuinely compelling for teams that value iteration speed over best-of-breed tooling. Skip if: You're in early prototyping stages and just need basic prompt logging (LangSmith or Langfuse are simpler), you've already invested heavily in a mature observability stack and only need LLM-specific add-ons (Phoenix integrates better), or you're a small team without infrastructure resources to self-host four database systems. The operational overhead is non-trivial, and the platform's relative youth means you'll encounter rough edges that more established tools have smoothed out.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/data-knowledge/langwatch-langwatch.svg)](https://starlog.is/api/badge-click/data-knowledge/langwatch-langwatch)