Skip to content

fix(weave_ts): link an evaluation to the agent spans it produced - #7708

Merged
ro31337 merged 4 commits into
masterfrom
roman/WB-38444-ts-eval-span-linking
Aug 11, 2026
Merged

fix(weave_ts): link an evaluation to the agent spans it produced#7708
ro31337 merged 4 commits into
masterfrom
roman/WB-38444-ts-eval-span-linking

Conversation

@ro31337

@ro31337 ro31337 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Three PRs, in review order:

  1. TypeScript evals: this PR, a prerequisite, separate from this work: it fixes existing eval linking
  2. Python + server: #7704
  3. TypeScript ops: #7711

JIRA Issue(s)

https://coreweave.atlassian.net/browse/WB-38444

Description

In TypeScript an evaluation never links to the agent spans its predictions produce. No "View spans" button, and the eval columns on spans stay empty. Python has had this link since May.

The code for it was here all along, just never connected. The processor registered on the OTel global provider, but weave emits through its own provider, which is kept out of that registry. The call never even ran: with no user-installed provider, trace.getTracerProvider() has no addSpanProcessor, so the helper returned false and nobody checked. Nothing regressed; the wire was never there.

The fix registers the processor where the provider is built, because that happens lazily on the first span and again when init() switches projects.

One attribute was missing too. The server counts a span as linked only with both weave.eval.run_id and weave.eval.predict_and_score_call_id, and TypeScript wrote only the second. It now writes both, run id first, since a full span drops whatever arrives next.

That is enough for the "View spans" drill-in. Full parity is a separate ticket, and so is EvaluationLogger, which cannot be linked this way at all.

Why this approach

Turning the processor on also turns on its onEnd hook, which appended a span ref to the prediction call's childSummary. That hook has never run, and once it does the result is wrong: childSummary propagates to the parent, and merging two rows' arrays gives an object with numeric keys, so every multi-row eval would ship a malformed weave.genai_span_ref on its root call. So it is gone. An existing test already says an SDK must not write that field; the promoted columns carry the link.

The linker goes after the exporting processor, the same order Python uses. That is neutral for the default pipeline. A custom settings.genai.spanProcessor now runs before it and will not see weave.eval.*, but no processor has ever seen those attributes, so nothing is lost today.

Testing

The new tests go through the public path: run an Evaluation, emit a real GenAI span, read the exported span. That is the only kind of test that catches this, since the old ones drove the processor directly and passed for months against a processor nobody had attached; the full sdks/node suite (503 tests), eslint, prettier and both typechecks are green.

…ts through

The eval span linker was registered on the OpenTelemetry global provider, but
Weave emits every GenAI span through a provider it owns, so the linker never saw
a span. Register it where the provider is built instead — lazily, and again after
a project switch rebuilds it.

Also write `weave.eval.run_id`: eval results only accept a span that carries it
alongside the predict-and-score call ID, and the TypeScript SDK never wrote it.
@codecov

codecov Bot commented Aug 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Its onEnd hook appended a span ref to the prediction call's childSummary, which
propagates to the parent, and merging two rows' arrays turns the list into an
object with numeric keys — garbage on the eval root of every multi-row run. The
hook has never executed, so nothing depended on it, and Python's linker is
onStart-only for the same reason: the promoted eval columns carry the link and
the server derives one representative ref per trace from them.

Also puts the linker after the exporting processor, matching how Python
registers the two, and notes both provider invariants in AGENTS.md.
@ro31337 ro31337 changed the title fix(weave_ts): install the eval span linker on the provider Weave emits through fix(weave_ts): install the eval span linker on the GenAI tracer provider Aug 9, 2026
Match the op names through the constants the sibling eval tests use, let the
eval helper hand back the two calls both tests look up, and drop the comment in
getOrBuildProvider — the rebuild test states the same thing executably.
@ro31337
ro31337 force-pushed the roman/WB-38444-ts-eval-span-linking branch from c477ca9 to 46835c8 Compare August 9, 2026 07:21
@ro31337 ro31337 changed the title fix(weave_ts): install the eval span linker on the GenAI tracer provider fix(weave_ts): link an evaluation to the agent spans it produced Aug 9, 2026
The genai suite already snapshots the whole attribute bag on spans emitted with
no eval on the stack, across five files, so a stray weave.eval.* breaks those
more strictly than the assertion added here did — it goes.

Names: the direct-call test is only there for the write order now that the
public-path test covers injection, and the provider test builds one provider,
not every one. Also drop the prescription from the attribute-limit note, since
Python's own eval linker does not follow the rule it implied.

@rgao-coreweave rgao-coreweave left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work, learned a lot!

LGTM

@ro31337
ro31337 merged commit f2c212d into master Aug 11, 2026
116 checks passed
@ro31337
ro31337 deleted the roman/WB-38444-ts-eval-span-linking branch August 11, 2026 18:16
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants