Pi Coding Agent instrumentation double-counts tokens and estimated cost in trace rollups (AgentSession.prompt carries summed LLM usage)
Maintainer antworten meist innerhalb von 1 Tag
@AbhiPrasad arbeitet bereits daran.
Seit 26.10.2026.
Bewertung
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Anfängerfreundlichkeit
- 72/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- typescript
- Bereich
- observability
Rechercherichtung
Lies zuerst js/src/instrumentation/plugins/pi-coding-agent-plugin.ts, insbesondere finishPiLlmSpan und finishPiPromptRun, um nachzuvollziehen, wie die Nutzung der untergeordneten Spans zum Prompt-Span hinzugefügt und protokolliert wird. Verfolge einen Prompt mit einem LLM-Aufruf und vergleiche dessen Rollup mit den Metriken des Leaf-LLM. Fertig ist die Aufgabe, wenn das Trace-Rollup die Nutzung und die geschätzten Kosten einmal zählt.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Summary
With wrapPiCodingAgentSDK (braintrust 3.39.0, @earendil-works/pi-coding-agent 1.4.0), each AgentSession.prompt task span gets the summed token usage of its child llm spans, and it also carries metadata.model. Braintrust's trace rollups add the parent's metrics to the children's. As a result, the trace summary, the logs table and the trace header report exactly 2× the prompt, completion and cached tokens and 2× estimated_cost for every Pi run.
The instrumentation spec says parent task spans "MAY include aggregate token metrics for display, but SDKs SHOULD avoid making parent rollups look like independent billable LLM calls" (braintrust-spec/skills/instrumentation-spec/references/features/token-and-cost-metrics.md). Here the parent is priced and summed like an LLM call.
Where
js/src/instrumentation/plugins/pi-coding-agent-plugin.ts at [email protected]:
finishPiLlmSpanlogs the usage on the LLM span and also callsaddMetrics(promptState.metrics, usageMetrics)(L703-L707).finishPiPromptRunlogscleanMetrics(state.metrics)on theAgentSession.promptspan, together withextractModelMetadata(...)(L655-L667).
Minimal reproduction
- Call
braintrust.wrapPiCodingAgentSDK(pi), create anAgentSessionwith any model, and run onesession.prompt(...)that takes at least one LLM turn underinitLogger(...). - Run these two project-log queries on that trace:
-- trace rollup
SELECT id, metrics.prompt_tokens, metrics.estimated_cost
FROM project_logs('<project_id>', shape => 'summary') WHERE root_span_id = '<root>'
-- per span, grouped
SELECT span_attributes.name, span_attributes.type, sum(metrics.prompt_tokens) AS pt, sum(metrics.estimated_cost) AS cost
FROM project_logs('<project_id>') WHERE root_span_id = '<root>' AND metrics.prompt_tokens IS NOT NULL
GROUP BY 1, 2
Observed on one trace (gpt-6.1-sol via openai.responses.create, 11 LLM calls):
| span | type | prompt_tokens | estimated_cost |
|---|---|---|---|
openai.responses.create (×11) |
llm | 443,901 | 0.1708972 |
AgentSession.prompt |
task | 443,901 | 0.1708972 |
| summary rollup | 887,802 | 0.3417944 |
Across 19 consecutive traces, the ratio of summary to leaf-llm sums was 2.000 for both tokens and cost in every trace.
Expected
A trace's rollup equals the sum of its leaf llm spans. Either the prompt span should not carry summed usage (or should carry it under a non-rolled-up name), or it should not be priced or summed as a billable call.
Workaround we use
We sum span_attributes.type = 'llm' AND span_attributes.purpose IS NULL spans and ignore the summary's token and cost metrics.
- Vorherrschende Sprache
- TypeScript
- Sterne
- 29
- Forks
- 22
- Ø Merge
- 1 T. 7 Std.
- Gemergte PRs (30 T.)
- 65
Entwicklungsumgebung
- Enthält ein Dockerfile oder eine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Kein Beitragsleitfaden
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus braintrustdata/braintrust-sdk-javascript
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 28/100
braintrustdata/braintrust-sdk-javascript#2709 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 45/100
braintrustdata/braintrust-sdk-javascript#2708 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 35/100
braintrustdata/braintrust-sdk-javascript#2707 ·
Maintainer antworten meist innerhalb von 1 Tag
-
typescript
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 45/100
braintrustdata/braintrust-sdk-javascript#2686 ·
Maintainer antworten meist innerhalb von 1 Tag
-
typescript
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 45/100
braintrustdata/braintrust-sdk-javascript#2685 ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in braintrustdata/braintrust-sdk-javascript
Ähnliche Issues
-
Remove unused dependenciesEvtl. vergeben @alastair-smith hat das heute übernommen. Offenchore other
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
alastair-smith/card-games#384 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 62/100
code-yeongyu/senpi#5571 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
nexu-io/open-design#9262 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
friction
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
kentcdodds/kody#4753 ·
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 62/100
lingdojo/kana-dojo#33508 · 1 Kommentar · 5 Reaktionen ·
Maintainer antworten meist innerhalb von 1 Tag