feature: three archive fields for offline session analysis — distinct tool-result counts, interleaved-completion marker, stream mismatch

Aperta
#1,740 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
48/100
Tipo di issue
Funzionalità
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
go
Ambito
observability

Direzione di ricerca

Start with core/pipeline/extensions.go to inspect InferenceExtension, then trace the inference parser to find where the previous turn and tool manifest are available. Read core/sessionapi/summary.go and its summarizeEvent function to see how existing counts reach the archive. The issue describes three separate additions; done means the requested counts, utility completion marker, and stream mismatch are recorded and surfaced in the relevant archive or usage view.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

enhancement

Summary

Three small fields the inference parser could record that would make the session archive
answer questions it currently cannot. All three came out of an offline analysis of a
30-day local archive (66 sessions, 29,606 events, 41 MB compressed) read through
archive.Open + Earlier. Each is independently useful; they are filed together because
they share one motivation — the archive already holds the data, the event just does not
carry the count or the flag that makes it readable without a full-session pass.

Scope of the measurements below

One developer's laptop archive, heavily Claude Code (18,785 of 29,606 events carry
claude-code/2.1.270). The ratios here describe one working style and should not be read
as a population — #1494 measured 59% of replies batching tool calls under explicit
prompting, against 7.3% here unprompted, so these numbers clearly move. What is not
style-dependent is the structural point in each item: the archive holds the fact and the
event does not state it.


1. A distinct tool-result count, so ToolResults metrics are not inflated ~272x

Every inference request re-sends the whole conversation, so each tool_result block is
recorded again on every subsequent turn. Counting ToolResults rows across a session
therefore overcounts by the conversation's length.

Measured on this archive:

Raw ToolResult rows across all events 2,765,534
Distinct results (deduped by ToolUseID) 10,183
Replay amplification 271.6x
Distinct results with IsError 362 (3.6%)

Taking the raw rows at face value gives "~8 tool errors per LLM call" (75,207 error rows).
The true rate is 3.6%. The two differ by more than two orders of magnitude, and nothing on
the event signals which one you are computing — a consumer has to know to dedup, and has to
hold the whole session to do it.

InferenceExtension already carries MessageCount and ToolCount for exactly this
"counts for a reader of a projected copy" reason. Two more in the same spirit:

  • NewToolResults int — results whose ToolUseID was not in the previous turn
  • ToolResultErrors int — of those, how many had IsError

Then a correct failure rate is a sum over events rather than a dedup pass over a session.
Cheap at parse time, where the previous turn is already in hand.

Related but distinct: #1541 fixed in-memory heap from interner misses on interleaved
conversations. This is about analysis-time row counting — a different layer, and
unaffected by that fix.


2. Mark the agent's own interleaved utility completions

Claude Code issues completions that are not conversation turns: the permission security
monitor and the auto-mode state classifier. As AgentRole's own documentation notes, these
come from the same CLI, declare no subagent marker, and are therefore main. What separates
them is that they carry no tool manifest.

This matters for any attempt to measure how long a human took to respond. Classifying
"response with 0 tool calls -> next request" as user wait time gives 1,442 gaps — but 33.6%
of them are under 5 seconds, impossible for a person. Splitting by FinishReason:

FinishReason n p50 <5s
end_turn 1,072 82.5s 23.7%
(empty) 270 2.1s 64.1%
stop_sequence 97 0.4s 100%

Requiring end_turn and a non-empty tool manifest gets this to 939 gaps, p50 111s, and
drops sub-5s to 16.7%. That is a workable heuristic, but it is a consumer-side guess at
something the parser knows directly.

  • A sibling flag (Interleaved bool, or similar) set when a completion is one of these
    utility calls — derivable at parse time from a zero/short tool manifest

Deliberately not a third AgentRole value: that field is parsed from a billing header
and its doc argues against widening it. The precedent is Tunnel, whose doc makes the same
argument for an explicit producer signal rather than letting consumers infer shape.


3. Surface responses that were asked to stream and did not

InferenceExtension already distinguishes Stream (what the request asked for) from
StreamedResponse (what arrived). Nothing reads the disagreement:

asked / got n
true / true 8,776
true / false 295
false / false 121

295 requests asked to stream and did not. That is a real upstream or proxy behaviour worth
knowing about, and today it is invisible unless someone compares the two fields by hand.

  • Count or surface the mismatch (usage pane, /v1/usage, or an agentop column)

While in the area, TunnelReason records failures nothing aggregates either: dial-failed
168, program-refused 66, os-trust-only 53 — 287 tunnels where, per that field's own
doc, "every plugin is blind to that traffic and someone has to restart something." The
visibility half of this is #1022; the counting half is cheap and separate.


Why these are worth the bytes

The archive is already the right place to answer "where did my agent's time go" — with
these three, one more question becomes answerable from Cortex alone, with no agent-harness
access: how much of a session's wall-clock was tool execution versus waiting on a human.

Classifying each response -> next request gap by whether proxied traffic landed inside it:

n p50 total share of gap time
Proxied tool (measured from Duration) 1,910 1,045 ms 11.6 h 18.8%
Local tool (inferred — no proxied traffic) 5,653 158 ms 5.3 h 8.6%
User wait (0 tool calls) 1,442 32,358 ms 44.8 h 72.6%

On single-tool-call turns the gap is that tool's latency, which recovers per-tool timings
with no harness data at all: Bash p50 201 ms (n=3,754), Edit 89 ms (n=814), Read 82 ms
(n=338), and AskUserQuestion 62,602 ms (n=68). That last one is useful validation —
the classifier never saw the tool's name, yet separated the one human-blocking tool from
the machine ones by three orders of magnitude.

Two honest limits on that table: the user-wait total is very sensitive to the gap ceiling
(24.8 h at 300s, 44.8 h at 1800s, 56.8 h at 3600s, 539 h uncapped), so the cap has to be
published with the figure; and the ~85 ms floor on Edit/Read is proxy round-trip plus agent
overhead, not tool time, so fast-tool numbers are upper bounds. Items 1 and 2 above remove
the two largest sources of error in it.

Where it lives

  • core/pipeline/extensions.go — InferenceExtension, beside MessageCount / ToolCount
  • the inference parser, where the previous turn and the full manifest are both in hand
  • core/sessionapi/summary.go — summarizeEvent, which already copies the counts

Not part of this

  • Time-to-first-token and response-time percentiles: #951 (and #1026, #1466)
  • Lossless request capture and replay: #1494
  • URL-level egress visibility: #1022

Assisted-By: Claude (Anthropic AI) [email protected]

Lingua principale
Go
Stelle
23
Fork
44
Merge medio
13h 49m
PR unite (30g)
244

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di rossoctl/cortex

Tutte le issue di rossoctl/cortex

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.