Skip to content

refactor(trace): record output messages through record() - #171

Draft
rgao-coreweave wants to merge 1 commit into
mainfrom
turn-record-output-messages
Draft

refactor(trace): record output messages through record()#171
rgao-coreweave wants to merge 1 commit into
mainfrom
turn-record-output-messages

Conversation

@rgao-coreweave

@rgao-coreweave rgao-coreweave commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

0.16.5 added outputMessages to Turn.record(); 0.16.6 added it to SubAgent.record() too. That closes the parity gap, so all five gen_ai.output.messages writers migrate together instead of leaving a split.

// every call site is now one line
recordOutput(call.span, [text]);                       // subagent
recordOutput(span, turns.flatMap(t => t.text), model); // teammate turn
recordOutput(turn.span, text, latestModel);            // turn

A single recordOutput() helper holds the shape conversion and the
already-ended guard, so no call site repeats them. Net effect across the repo is
+2 lines. assistantOutputMessages() has no callers left and is deleted;
assistantMessages() is now module-private. Afterwards ATTR.OUTPUT_MESSAGES
survives only as a constant used by tests, and no src/ code hand-serializes
the attribute.

Wire format is unchanged

Verified against a live in-memory exporter before writing the change:

manual    : [{"role":"assistant","content":"first reply"},{"role":"assistant","content":"second reply with \"quotes\" and \n newline"}]
via record: [{"role":"assistant","content":"first reply"},{"role":"assistant","content":"second reply with \"quotes\" and \n newline"}]
IDENTICAL

Message.content is an optional field the SDK stringifies verbatim, so {role, content} survives as-is, and SubAgent.end() serializes _outputMessages exactly as Turn.end() does. Two independent pins confirm it: the turn-side assertions added in #170, and the pre-existing subagent assertions (25 of them fail if the subagent writes are removed).

Two deliberate details

The Turn calls stay guarded. record() writes at end() and warns when the span has already ended. Making it unconditional would emit weave.Turn.record() called after end() noise into the daemon log on recovery paths that write nothing today. Passing undefined for either field is a no-op inside the SDK, so a previously recorded model is never clobbered.

gen_ai.response.model is left alone. record({ model }) writes gen_ai.request.model, a different attribute. The setAttributes({ [ATTR.RESPONSE_MODEL]: … }) calls in hookHandler.ts are therefore not folded in, since that would silently move the value to a different key.

Verification

npm run check

tsc clean, 203/203 pass.

🤖 Generated with Claude Code

rgao-coreweave commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@w-b-hivemind

w-b-hivemind Bot commented Aug 14, 2026

Copy link
Copy Markdown

HiveMind Sessions

4 sessions · 40m · $13

Session Agent Duration Tokens Cost Lines
Multi-Agent Code Review of TypeScript Files
4e2b4f5e-e561-4d9e-94c4-3bc98b53f8ba
claude 58s 2.1K $0.30 +0 -0
Multi-Agent Code Review of Parser and Lifecycle
ce6d3866-6899-471e-ba0b-457a190257ea
claude 1m 2.7K $0.35 +0 -0
Multi-Agent Code Review of TypeScript Files
ab11b764-d095-4007-8aeb-bbd935665e35
claude 1m 2.0K $0.35 +0 -0
Build and Instrument Agent Team with Weave Tracing
4a3aa5b0-d015-4d3a-8048-426e02002931
claude 36m 83.8K $12 +521 -52
Total 40m 90.6K $13 +521 -52

View all sessions in HiveMind →

Run claude --resume 4e2b4f5e-e561-4d9e-94c4-3bc98b53f8ba to pickup where you left off.

@rgao-coreweave
rgao-coreweave force-pushed the turn-record-output-messages branch from c49a807 to 8fdc2a9 Compare August 14, 2026 18:57
@rgao-coreweave rgao-coreweave changed the title refactor(trace): record turn output through Turn.record() refactor(trace): record output messages through record() Aug 14, 2026
@rgao-coreweave
rgao-coreweave force-pushed the turn-record-output-messages branch from 8fdc2a9 to f1936b9 Compare August 14, 2026 19:26
@rgao-coreweave
rgao-coreweave force-pushed the turn-record-output-messages branch from f1936b9 to 2110d47 Compare August 17, 2026 16:47
Base automatically changed from cover-turn-output-messages to main August 17, 2026 16:47
weave 0.16.6 adds outputMessages to both Turn.record() and
SubAgent.record(), so all five gen_ai.output.messages writers stop
hand-serializing the attribute.

One recordOutput() helper replaces the per-site guard and shape code, so
each call site is a single line and the already-ended guard lives in one
place. assistantOutputMessages() has no callers left and is deleted.

Wire format is unchanged, pinned by the assertions in the parent PR plus
the existing subagent assertions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rgao-coreweave
rgao-coreweave force-pushed the turn-record-output-messages branch from 2110d47 to 6c0c6d4 Compare August 17, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant