fix(mastra): emit tags as first-class Braintrust tags, not metadata#2212
fix(mastra): emit tags as first-class Braintrust tags, not metadata#2212Cedric / ViaDézo1er (viadezo1er) wants to merge 2 commits into
Conversation
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).
5b13f4a to
a86388f
Compare
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>
81856c3 to
ca077c6
Compare
There was a problem hiding this comment.
💡 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".
| exported.tags && | ||
| exported.tags.length > 0 | ||
| ) { | ||
| event.tags = exported.tags; |
There was a problem hiding this comment.
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 👍 / 👎.
buildMetadata placed exported.tags under metadata.tags, where Braintrust
does not surface them as tags. Move root-span tags to the top-level
tagsrow field (via ExperimentLogPartialArgs.tags) so they appear asfirst-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 spansin a trace. This affects where the top-level tags are filterable:
span is the Braintrust trace root, so tags are
is_rootand filterableeverywhere (trace list + summary).
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'sspan_id, not its rowid. Themetadata.tagsmirror is retainedregardless for backward compatibility.
Ports mastra-ai/mastra#12057 (re-fixes #9849).