Build1 distinct publisher3 min readUpdated
A write-up on assembling execution trees from span events argues the hard part is not collecting logs but handling out-of-order, concurrent, incomplete and retried spans without lying.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
A dev.to write-up by Raju Dandigam takes apart a problem most agent observability stacks paper over: the trace format that is cheapest to emit is the one that hides causality. His argument is that agent traces get written as flat event sequences because append-only data is simple to produce [1], while the artefact an engineer actually needs is a causal tree showing an agent run branching into web search, a database query, a finance API call that timed out on the first attempt and succeeded on the second, and a summarisation step [2].
The framing is worth stealing: the event stream is optimised for writing, the execution tree is optimised for understanding [3]. The gap between them is not a rendering problem. According to the post, building a reliable tree requires more than sorting by timestamp, because events may arrive out of order, siblings may run concurrently, spans may be incomplete, and retries may fail while the parent operation still succeeds [4].
That last case is the one that quietly poisons dashboards. A tool call with a failed attempt_1 and a successful attempt_2 is a success at the parent and a failure at the leaf [2], and any pipeline that flattens status upward or downward will report the wrong thing.
The mechanics come down to identity. Every event needs stable trace and span identity, with start events establishing parentage and end events establishing outcome and duration [5]. Timestamps alone cannot do it: two adjacent events may be siblings, unrelated concurrent work, or operations from entirely different traces [6]. Nor can you assume the two halves of a span arrive together, since a buffered exporter can deliver the end before the start and a crashed process may never deliver an end at all [7].
Dandigam's assembler handles this by buffering an end event until its start arrives, keeping a separate map of pending ends [8]. Duplicate starts are dropped with a diagnostic rather than overwriting the existing span [9]. End timestamps are clamped with a max against the start time, so a skewed clock cannot produce a negative duration [10]. At finalisation, unmatched ends and spans still open are surfaced as diagnostics, and the assembler does not invent timestamps or mark incomplete work successful [11]. The diagnostic vocabulary is four codes: duplicate_start, duplicate_end, end_without_start, span_left_open [12] - two for redelivery, two for a missing half [13]. Six span kinds are declared: run, model, tool, retrieval, decision and fallback [14][15].
The post is honest about what this design does not solve. On an unbounded live stream, the pending-event map needs a size limit and an expiration policy, or malformed or hostile input can grow it without bound [16]. And a renderer should tolerate multiple roots and orphans without crashing, even though a valid trace normally has exactly one root [17].
Two things to watch in your own stack. First, whether your tracing UI can tell you that a span was left open, or whether it draws a tidy tree and omits the branch it could not resolve [11][12]. Second, whether the ingest path in front of it has a bounded buffer for orphaned ends [16]. A trace assembler that silently guesses is worse than flat logs, because it produces something that looks authoritative.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
An agent trace is usually written as a sequence of events (span_started, span_ended) because append-only data is simple to produce.
Developers do not want to debug the raw event sequence; they want the causal structure, illustrated as a research_agent tree containing search_web, query_database, call_finance_api with attempt_1 timeout and attempt_2 ok, and summarize_results.
The event stream is optimized for writing; the execution tree is optimized for understanding.
Building a reliable tree requires more than sorting by timestamp: events may arrive out of order, siblings may run concurrently, spans may be incomplete, and retries may fail while the parent operation still succeeds.
Timestamps alone cannot establish parentage. Two events that occur next to each other may be siblings, unrelated concurrent work, or operations from different traces.
Start and end events may not arrive together: a buffered exporter can deliver the end first, and a crashed process may never deliver an end at all.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Verifiable in-source code, no external corroboration
Unusually for a single-source cluster, most claims can be checked directly against the supplied artifact: the SpanKind and AssemblyDiagnostic unions, the SpanAssembler.accept branches, applyEnd's Math.max clamp, finish()'s diagnostic emission, and buildForest's root/orphan/duplicate handling are all present in the body text. That raises evidence above a bare assertion. It is capped well below high because there is one publisher, no tests, no benchmark, no independent implementation, and the two hardening measures the author recommends (bounded pending buffer, cycle detection) are described but not shown.
No adoption signal in supplied sources
The cluster contains no release, deployment, benchmark, usage disclosure, pricing or license event. The artifact is an illustrative code pattern in a blog post with no named users, no repository, no download or install figures, and no production account. Adoption cannot be scored without inventing facts.
Claims roughly matched to evidence, mild framing stretch
The substantive claims are narrow and mostly self-proving in the supplied code, so there is little room for overstatement. The small positive gap comes from three things: the headline framing that append-only traces 'hide the bug', the unevidenced generalization about what developers want, and prose that presents hardening (bounded pending map, cycle detection) as part of the approach while the shown implementation lacks both. No production or scale claim is made, so the article does not overreach on adoption either.
Low commercial pull, engagement-driven platform
Observable from the source itself: the post names no product, vendor, service, pricing tier or repository to adopt, and sells no tool — the pattern is given as inline code the reader can copy, which limits commercial distortion. Residual incentive comes from the developer-content platform context, where a provocative framing about hidden bugs rewards engagement, and from the absence of any author affiliation or interest disclosure that would let a reader rule out tooling interest.
Confident on code specifics, thin on generalization
Confidence is moderate: the mechanical claims about types, diagnostics and assembly behaviour can be read off the supplied artifact with little interpretive risk, so those are firm. Everything beyond the artifact — whether this design holds under real trace volume, whether it aligns with prevailing span conventions, whether anyone runs it — is unverifiable from one publisher with zero adoption evidence, which prevents a higher score.
build
Flat logs cannot explain an agent run, and adding more of them makes it worse1 distinct publisher
build
An empty array is a claim about your query: verify identifiers before you trust the metric1 distinct publisher
build
Allow-list the closed set, block-list the open one: 193 thin geo pages, one gate1 distinct publisher
build
A GAN beauty filter is a device budget allocation, not a feature toggle1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 19, 2026