part = 3 / 5
How everyone else models it
Every AI observability product answers the same three questions — what is the unit of record, is the request a real object, and who owns conversation identity — and the answers sort the whole field into two philosophies. Phoenix sits firmly in one of them.
Two philosophies
Telemetry-first products (Phoenix, Datadog LLM Observability, anything OTel-native) start from the wire: flat, immutable spans, emitted by anyone, assembled into structure at read time. The model is whatever survives transport. Application-first products (LangSmith, Langfuse, Braintrust, W&B Weave) start from the developer's program: this function ran with these inputs and returned these outputs. Their SDKs own the write path, so their objects can be richer — mutable while running, nested payloads intact, request and conversation as real records with fields.
Neither side is confused; they optimized for different first questions. Telemetry-first optimizes "will I be able to ingest whatever exists, from anywhere, forever?" Application-first optimizes "will the developer's second-favorite debugging question — what did this request take in and put out? — be answerable by a primary-key lookup?" Everything below is downstream of that fork.
The interesting details, per product
LangSmith: the run tree
LangSmith's primitive is the Run: a typed node (llm, chain, tool,
retriever…) with first-class inputs and outputs as structured
JSON, an error field, and timestamps. A trace is simply the tree under a root run — which
means the trace has inputs, outputs, and a status by construction, because the
root run is a real record, created at start and patched at end. That
create-then-patch protocol is the load-bearing difference from OTel: LangSmith sees runs
the moment they begin. Conversations ("threads") are, amusingly, a metadata convention —
a session_id/thread_id key on the root run — so their session
story is roughly as duct-taped as ours, one level up.
Langfuse: the trace as a real object
Langfuse is the cleanest expression of application-first modeling. The
trace is a first-class record with its own input,
output, metadata, tags, user_id, and
session_id — settable and updatable from application code at any point
during execution. Observations (spans, generations, events) hang off
it. Sessions are first-class and group traces. Scores
attach to traces, observations, or sessions symmetrically — the annotation model
Part 4 argues for, shipped. Langfuse also ingests OTLP by mapping it into this
model, which is an existence proof that the wire format and the mental model can differ.
Braintrust: spans, but mutable
Braintrust looks OTel-ish — everything is a span, the root span stands in for the trace — but spans are mergeable: log the same span id twice and the fields merge, so you can open a span, stream into it, and close it later, even from a different process. It's a quiet rejection of OTel's one core constraint (immutability) while keeping its shape. The product's center of gravity is evals — datasets, experiments, scorers — with production tracing as the feeder.
W&B Weave: the program is the model
Weave traces calls — decorated function invocations with captured inputs and outputs, linked to versioned code objects ("ops"). It's the most literal "your program, replayed" model, excellent for the single-process notebook-to-app workflow, and the least concerned with distributed transport of anything here.
Datadog LLM Observability: our philosophy, their scale
Datadog models LLM work as typed spans (workflow, agent, llm, tool) with
session_id tagging, riding the existing APM pipeline. Telemetry-first, like
us. Notable mostly as evidence that the big-infrastructure players landed on the same
side of the fork, for the same reasons: they don't control the write path either.
So who has the cleaner mental model?
For the core debugging loop — find the bad request, read its input and output, look inside, mark it — yes, the application-first products are cleaner, and it isn't close. In Langfuse the object the user is thinking about (this request, this conversation) is the object in the database. In Phoenix it's a projection that usually resolves correctly. Users don't see our schema, but they feel its edges: the trace table that can't be tagged, the session that can't be annotated from the UI, the turn whose "annotate" button aims one level down (Part 1).
But the cleanliness is purchased with the write path. LangSmith's live run tree requires create-then-patch through their SDK. Langfuse's updatable trace requires their client and their two-phase writes. Braintrust's merges require their ingestion semantics. Each of those products, when it decided to also accept OTLP, had to build the same read-time reconstruction machinery we run — they just treat it as a compatibility layer instead of the core. The moment you accept arbitrary OTel input (and at this point they all felt compelled to), you inherit the orphan roots, the late spans, the convention-based sessions. The difference is what happens next: they map the mess into a rich model; we present the mess with good typography.
Can we make the transitions?
Mostly yes, because the fix is at the read/ingest boundary, not the wire. Nothing about OTel compliance forbids Phoenix from materializing the objects users think in:
- Promote the trace from label to summary. At ingest (or first read), cache trace-level facts onto the trace row: input/output copied from the resolved root span, error status, token and cost totals. Phoenix already does exactly this trick one level down — cumulative token counts on spans — so the pattern is proven in-house. The root-span ambiguity doesn't disappear, but it gets resolved once, in one place, with one policy, instead of per-view.
- Unify the root-span predicate. One orphan-aware definition, everywhere. This is a bug fix wearing a data-model costume.
- Finish the session object. The table exists, the mutations exist (Part 1); what's missing is UI. Session-level annotation and inspection is a frontend project, not a schema project.
- What we can't have: in-flight visibility and authoritative conversation identity. Those genuinely require owning the write path (create-then-patch, or server-assigned sessions). The honest OTel-compatible approximations are partial-trace rendering (show the orphan forest live, labeled as in-progress) and session validation warnings (surface the conflicts we currently swallow) — worse than LangSmith's live tree, much better than our current nothing.
Competitor descriptions reflect their public data models as of mid-2026; all of these products move quickly, and the point is the philosophy fork, not any vendor's current feature list.