Uh oh!
There was an error while loading. Please reload this page.
feat(web): agent session detail page - #546
Conversation
Adds POST /internal/ai-sessions/spans: the two-stage aiSessionSpansQuery bounded by rows and bytes, mapped through the gen_ai integration layer server-side so the response carries the decoded span shape instead of the raw attribute maps. Truncation at the 2,000-span cap is reported rather than silent, and a byte-limit abort surfaces as a 413 AiSessionTooLargeError. The web adapter and atom follow the existing list/facets plumbing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Derives the shape of an agent session from its spans: turn boundaries, the occupancy of the wall clock, token and failure counts, the collapsed-idle time axis, and an estimate of model spend against a dated table of list prices. No framework records where one turn ends, so each rule is a named heuristic with its fallbacks — conversation id, then root agent invocations, then trace boundaries — and the tests cover the paths that pick each one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opens a session from the list into its own page: a header stating how long it ran, where the time went, what it spent and how it failed, then the same spans as either a turn-grouped waterfall or a lane-per-turn flow. The waterfall keeps three things adjustable because each is occasionally the thing you need — turns, collapsed idle, and hiding the app's own spans — and both views link every span back to its trace. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pan filter A trace rule was emitted before its turn's visibility was known, so filtering out a whole turn left the rule dangling above nothing; the rule now opens at the trace's first surviving turn. Collapsed turn headers likewise counted spans the active filter was hiding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lowers the response byte ceiling to 10MB — the bounded read accumulates parsed rows before the counter can trip, so 20MB of attribute-heavy rows risked the isolate instead of producing the designed 413. The 413 now carries fix_request recovery (a narrower window genuinely helps), the handler annotates session id, span count and truncation on its span, a span-level key-drift assert joins the genAi ones, and the truncation and limit-error paths get a handler test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review against production spans found the turn rules failing off the mockup's idealized shapes: six vendors derive the session id from gen_ai.conversation.id, so a single distinct id must not count as a turn partition; agent roots must be found by walking for an AI ancestor, since the app's own spans parent every agent span; and same-millisecond anchors produced phantom empty turns. Also: llm-call counting now agrees with span classification for unknown operation names, titles and turn labels reject injected pseudo-XML context blocks, failure/retry counts and token totals count only the deepest span carrying a signal (frameworks stamp parents and children alike), cache buckets no longer double the headline token count, model pricing refuses to price unknown models off a neighbouring row, and a session that errored recently reads failed, not active. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The stats band now steps through 2/3/5 columns instead of collapsing to a 560px stack that clipped the waterfall out of reach at 1280x800. Filtering is consistent end to end: fully filtered turns take their trace rules and idle rows with them, the count strip reads "N of M spans", and the flow view respects the same filter. Single-turn traces put their trace link in the turn header instead of a dedicated rule row, the model/target column no longer echoes the span name, SUBAGENT marks only real delegations, retried calls get their pill, view state survives tab switches, zero-value stats give way to empty states, and the axis uses nice-number ticks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
JeremyFunk
commented
Aug 20, 2026
Post-open review cycle (an effect-review-v4 multi-lane pass plus a live frontend design review) landed as the three Correctness against real vendor data — the turn rules were rebuilt after the review verified them against production spans: a single distinct Endpoint hardening — byte ceiling 20MB→10MB (parsed-row accumulation means the cap must sit well under the isolate heap), 413 with Design/UX — the stats band no longer collapses into a stack that pushed the waterfall off-screen at 1280×800; titles and turn labels reject injected pseudo-XML context blocks (real eve sessions titled themselves Known follow-ups deliberately not in this PR: TTFT is dark for orgs whose SDKs emit 🤖 Generated with Claude Code |
Adds the session detail page under Explore > Agent Sessions (still behind the
agent_tracingflag), consuming the read layer from #540. List rows now link to it.What's in it
API — one new internal endpoint,
POST /internal/ai-sessions/spans: the existingaiSessionSpansQuery(bounded by rows and bytes viacompiledQueryBounded), mapped throughmapAiSpansserver-side so the response carries the decoded span shape instead of the raw attribute maps. Truncation at the 2,000-span cap is reported astruncated: true; a byte-limit abort surfaces as a 413.Session anatomy header — title from the first captured user message (falls back to agent name + start time), derived status (active / completed / failed / abandoned), wall-clock vs active time, an occupancy bar (idle · TTFT · inference · tool · unaccounted, computed as wall-clock occupancy so parallel tool calls can't push it past 100%), five token buckets, work and failure counts, and a model-spend estimate.
Trace view — the turn-grouped waterfall: trace rules band the turns, idle gaps are collapsed out of the axis (expandable per gap), agent-spans-only and text filtering, virtualized rows, and navigation from any span into the trace detail page.
Flow view — one lane per turn, nodes per agent/inference/tool span with plain SVG edges (no graph library), optional merging of repeated tool calls.
All header/turn/axis computation is pure client-side code in
apps/web/src/lib/agent-sessions/with colocated tests (turn segmentation, occupancy sweep, status derivation, axis compression, pricing).Notes for review
model-pricing.ts. Unpriced models are counted and surfaced ("N models unpriced") rather than silently priced at zero.gen_ai.conversation.idwhen a vendor provides it (eve does), otherwise root agent-invocation spans, otherwise one turn per trace.t/endhints from the list row and pads by an hour; deep links without hints fall back to the last 7 days.<current_time>block) gets that as the session title verbatim.Browser-verified locally against replayed captures from six frameworks: multi-trace banding, subagent nesting, 796-span virtualized session, token buckets/spend, filtering, flow lanes, deep-link fallback.
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.