feat: OTEL GenAI semantic conventions + Braintrust.Sdk.Extensions.AI package#42
Open
Brendan Gooden (brendangooden) wants to merge 2 commits into
Conversation
0b1f122 to
a074fa7
Compare
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Add gen_ai.* attributes where Braintrust fills gaps no framework covers:
- Function/tool spans: gen_ai.operation.name ("execute_tool"),
gen_ai.tool.name, gen_ai.tool.call.arguments, gen_ai.tool.call.result
(M.E.AI's UseOpenTelemetry() does not emit dedicated execute_tool spans)
- OpenAI raw SDK: gen_ai.operation.name, gen_ai.provider.name,
gen_ai.input/output.messages, gen_ai.usage.input/output_tokens
(no framework-level OTEL instrumentation for raw ChatClient)
- Anthropic raw SDK: same gen_ai.* attributes
(no framework-level OTEL instrumentation for raw IMessageService)
IChatClient chat/agent spans intentionally omit gen_ai.* — users should
stack UseOpenTelemetry() from M.E.AI for standard OTEL GenAI attributes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…mentation New package that instruments any IChatClient implementation via Microsoft.Extensions.AI middleware pattern. Works with OpenAI, Azure OpenAI, Ollama, and any other IChatClient provider. Emits only braintrust.* attributes on chat/LLM spans (users should stack UseOpenTelemetry() for standard gen_ai.* attributes). Emits gen_ai.tool.* on execute_tool spans — the gap M.E.AI doesn't cover. Includes: - BraintrustChatClient: delegating IChatClient with LLM tracing - BraintrustFunctionMiddleware: tool/function call tracing - Extension methods: UseBraintrustTracing, UseBraintrustFunctionTracing, UseAllBraintrustTracing - Full test suite (6 tests) - Example project (ExtensionsAIInstrumentation) - Updated README with package selection guidance Also adds SkipVersionVerification property to Directory.Build.targets. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
a074fa7 to
ce5538f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
gen_ai.tool.*OTEL attributes to execute_tool spans across AgentFramework and new Extensions.AI packagesgen_ai.*OTEL attributes to raw SDK packages (OpenAI, Anthropic) where no framework-level OTEL instrumentation existsBraintrust.Sdk.Extensions.AIpackage for instrumenting anyIChatClientimplementationArchitectural Rationale
Separation of concerns: Braintrust vs M.E.AI
gen_ai.*chat span attributesUseOpenTelemetry()braintrust.*dashboard attributesexecute_toolchild spans withgen_ai.tool.*main(post 10.4.0) but it's unreleased. Braintrust fills the gap for current 10.4.x usersChatClient/IMessageServiceWhy
braintrust.*attributes are neededThe Braintrust backend specifically parses
braintrust.*attributes to render the dashboard:braintrust.parent— routes spans to the correct project (without it, spans are dropped)braintrust.input_json/braintrust.output_json— renders Input/Output panels in span detailbraintrust.span_attributes— identifies span type for UI groupingbraintrust.metrics.*— renders token counts and timing metricsM.E.AI's
gen_ai.*spans arrive at Braintrust but render as empty/untyped without correspondingbraintrust.*attributes. See issue #43 for a proposal to have the backend consumegen_ai.*natively.M.E.AI
execute_toolspans — timeline notedotnet/extensionsmainbranch already hasexecute_toolspans inFunctionInvocationProcessor.cs(added March 11, 2026), but this is unreleased (post v10.4.0 tag). When the next M.E.AI release ships:UseBraintrustFunctionTracing()becomes redundant forIChatClientusers gettingexecute_toolspans nativelyRecommended pipeline for IChatClient users
Changes
1. OTEL GenAI tool span attributes (AgentFramework)
Added to
BraintrustFunctionMiddlewareexecute_tool spans:gen_ai.operation.name= "execute_tool"gen_ai.tool.namegen_ai.tool.call.arguments(alongsidebraintrust.input_json)gen_ai.tool.call.result(alongsidebraintrust.output_json)2. OTEL GenAI attributes on raw SDK packages
OpenAI (
InstrumentedChatClient):gen_ai.operation.name,gen_ai.provider.name,gen_ai.input/output.messages,gen_ai.usage.input/output_tokensAnthropic (
InstrumentedMessageService): same attributesThese raw SDKs have no framework-level OTEL instrumentation, so Braintrust emits both namespaces.
3. New
Braintrust.Sdk.Extensions.AIpackageInstruments any
IChatClient(OpenAI, Azure, Ollama) via M.E.AI middleware:BraintrustChatClient— delegating IChatClient (sync + streaming), emitsbraintrust.*onlyBraintrustFunctionMiddleware— execute_tool spans withgen_ai.tool.*+braintrust.*UseBraintrustTracing,UseBraintrustFunctionTracing,UseAllBraintrustTracingMicrosoft.Agents.AIPackage selection guide
Braintrust.Sdk.Extensions.AI(new)IChatClientprovider (OpenAI/Azure/Ollama via adapter)Braintrust.Sdk.AgentFrameworkChatClientAgentorchestrationBraintrust.Sdk.OpenAIChatClient(non-IChatClient)Braintrust.Sdk.AnthropicIMessageServiceTest plan
gen_ai.tool.*assertions on function spans)gen_ai.*assertions)gen_ai.*assertions)🤖 Generated with Claude Code