Skip to content

fix(mastra): emit tags as first-class Braintrust tags, not metadata#2212

Open
Cedric / ViaDézo1er (viadezo1er) wants to merge 2 commits into
mainfrom
cedric/tags-export
Open

fix(mastra): emit tags as first-class Braintrust tags, not metadata#2212
Cedric / ViaDézo1er (viadezo1er) wants to merge 2 commits into
mainfrom
cedric/tags-export

Conversation

@viadezo1er

@viadezo1er Cedric / ViaDézo1er (viadezo1er) commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

buildMetadata placed exported.tags under metadata.tags, where Braintrust
does not surface them as tags. Move root-span tags to the top-level
tags row field (via ExperimentLogPartialArgs.tags) so they appear as
first-class, filterable tags. Matching @mastra/braintrust, tags are only
attached to the Mastra root span (Braintrust tags are trace-level).

Verified empirically that span.log({ tags }) writes the top-level tags
field while metadata.tags stays inert. Adds js/src/wrappers/mastra.test.ts.

Filtering caveat (trace-level scope)

Braintrust's trace-list tag filter is scoped to the trace root span
(is_root); the summary / BTQL view instead aggregates tags across all spans
in a trace. This affects where the top-level tags are filterable:

  • Zero-config auto-instrumentation and manual integration: the Mastra root
    span is the Braintrust trace root, so tags are is_root and filterable
    everywhere (trace list + summary).
  • Mastra nested inside an existing Braintrust span (the exporter parents its
    subtree under the user's current span): tags land on a non-root span. They
    stay filterable via summary / BTQL, but not via the root-scoped trace-list
    form filter. Lifting them to the user's trace root isn't feasible from the
    exporter — rows merge by row id, and the exporter only has the root's
    span_id, not its row id. The metadata.tags mirror is retained
    regardless for backward compatibility.

Ports mastra-ai/mastra#12057 (re-fixes #9849).

buildMetadata placed exported.tags under metadata.tags, where Braintrust
does not surface them as tags. Move root-span tags to the top-level
`tags` row field (via ExperimentLogPartialArgs.tags) so they appear as
first-class, filterable tags. Matching @mastra/braintrust, tags are only
attached to the Mastra root span (Braintrust tags are trace-level).

Verified empirically that span.log({ tags }) writes the top-level tags
field while metadata.tags stays inert. Adds js/src/wrappers/mastra.test.ts.

Ports mastra-ai/mastra#12057 (re-fixes #9849).
Make the tags fix purely additive: keep writing exported tags to
metadata.tags (prior behavior, on any span) while also emitting them to
the top-level `tags` row field on the root span, which Braintrust
surfaces as first-class, filterable tags.

Add wire-level e2e coverage that drives real @mastra/core through
tracingOptions.tags and asserts both the top-level `tags` field and the
metadata.tags mirror on the root span (and no top-level tags on children).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 81856c39b3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "Codex (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".

Comment thread js/src/wrappers/mastra.ts
exported.tags &&
exported.tags.length > 0
) {
event.tags = exported.tags;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Deduplicate Mastra tags before logging

When Mastra passes duplicate tracingOptions.tags values, forwarding the array directly to the top-level Braintrust tags field makes Span.log run validateTags(), which throws on duplicates. Because exportTracingEvent catches that exception, a duplicate-tagged root span_started fails before this.spans.set(...), so the Mastra root span is not tracked and later child/end events can be dropped or detached; this was previously only metadata and did not hit tag validation. Deduplicate or otherwise sanitize the top-level tags while preserving the metadata mirror.

Useful? React with 👍 / 👎.

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