feat(agent-sessions): page a session's spans and summarise it in the warehouse - #740
Open
JeremyFunk wants to merge 2 commits into
Open
Conversation
…warehouse The detail page read a session in one response capped at 2,000 spans and called anything past that truncated. The largest session in the warehouse has ~209k spans in one trace, a tenth of them the agent's own; one page showed its first minute. The `spans` read now pages by a keyset cursor on its own (timestamp, spanId) order — `nextCursor` replaces `truncated` — and takes a `scope` (all, the agent's spans, or the app's), `traceIds` for a turn's traces without session detection, and a `limit`. A new `summary` read returns the whole session's totals from an ungrouped aggregate, with per-turn rows grouped by conversation id (falling back to the trace) beside it; usage is summed over all spans and over model calls alone so the handler can apply the page's deepest-reporter rule. The page loads the opening whole — a session that fits is complete after one read, as before — and continues with the agent's spans alone, fetching a turn's app spans from the Trace view's header on demand. The Overview leads with the warehouse totals when the session is only partly loaded, the transcript ends on a load-more divider, and a deep link's bounds are stamped from the totals so a cut-short window is never written into the URL.
…nt-sessions-paged-spans # Conflicts: # apps/web/src/api/warehouse/ai-sessions.ts # apps/web/src/components/agent-sessions/session-detail/session-transcript.tsx # apps/web/src/components/agent-sessions/session-detail/session-views.tsx # apps/web/src/lib/agent-sessions/session-transcript.ts # packages/query-engine-integrations/src/ai/ai-sessions.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #739 (the projection change); merge that first.
Why
The Agent Sessions detail page read a session in one response capped at 2,000 spans, and reported anything past that as truncated. The largest session in the warehouse has ~209k spans in a single trace, of which ~19.5k are the agent's own and the rest the app's SQL/HTTP work. One page showed its first minute. No page size fixes that — the page has to load what the reader needs first and the rest on demand, and the totals it prints have to come from the warehouse rather than from the spans in hand.
What
API (
/internal/ai-sessions)spanspages by a keyset cursor:after: {timestamp, spanId}on the read's own(timestamp, spanId)order, withnextCursorin the response replacingtruncated. The timestamp is the warehouse literal at nanosecond precision, so the resume point is exact.scope: all | ai | app— every span, the vendor-stamped agent spans alone, or the app's own spans alone.traceIdsreads named traces without session detection — a turn's worth, capped at 100, validated as 32-hex.summary: whole-session totals (spans, agent spans, traces, bounds, model/tool calls, errors, tokens, cost, models, agents) plus per-turn rows aggregated in ClickHouse; the totals come from a separate ungrouped read so a session with more turns than one response carries still reports exact totals. The turn key is the conversation id under every vendor spelling the mapper reads, falling back to the trace. Usage is summed over all spans and over model-call spans; the handler keeps the model-call figures when any exist (per-call) and the plain sum otherwise (roll-up), which is the page's deepest-reporter rule at turn granularity. A child span that does not carry the id lands in its trace's row — the rows partition the session exactly, but a turn row may hold fewer spans than the page's turn; documented on the schema.AI_INFERENCE_OPERATIONSetc.) moves to@maple/domain/gen-aiso the summary's "llm call" is the page's.Web
useSessionSpans: the first page is the session's opening, every span of it — a session that fits is complete after one read, exactly as before. When a cursor comes back the session is partial: further pages fetch the agent's spans alone (a tenth of a large session's rows), and each turn's app spans are fetched from the Trace view's turn header by the turn's traces and bounds. Pages are merged and deduplicated; state is keyed by the first-page input so a window change drops them and a late response is discarded.t/endstamp waits for the summary's bounds so a deep link never gets a cut-short window written into it.Verification
CLICKHOUSE_E2E=1catalog sweep passes 259 shapes; scoped typecheck green.appread by its traces returns exactly its 1,930 app spans; the projected attribute map on an SQL span keeps onlyserver.address.DateTime64(9)vs string literal: strict, exact at the boundary).🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.