Fix OTel invoke_agent span: prefix the operation name and omit empty agent name/description attributes#655
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request updates the OpenTelemetry invoke_agent span emitted by the OTel middleware to better align with GenAI semantic conventions (span naming and attribute emission), and extends the existing in-memory trace exporter tests to lock in the behavior.
Changes:
- Rename the
invoke_agentspan to"<operation> <target>"(e.g.,invoke_agent helper) with fallback from agent name to agent ID. - Stop emitting
gen_ai.agent.nameandgen_ai.agent.descriptionattributes when those values are empty. - Extend/update unit tests in
provider/otelproviderto validate the new span naming and attribute omission behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| provider/otelprovider/otel.go | Adjusts invoke_agent span naming and conditionally emits agent name/description attributes. |
| provider/otelprovider/otel_test.go | Updates existing assertions and adds new tests for span name and omitted empty attributes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| name := opInvoke | ||
| if n := cmp.Or(a.Name(), a.ID()); n != "" { | ||
| name += " " + n | ||
| } |
|
|
||
| func TestOtel_Run_OmitsEmptyAgentNameAndDescription(t *testing.T) { |
This comment has been minimized.
This comment has been minimized.
Name the agent span "<operation> <target>" (invoke_agent <name>) to match the GenAI semantic conventions and the sibling execute_tool span, instead of using the raw agent name. Fall back to the agent id when the name is empty so the span still carries a target. Only set gen_ai.agent.name and gen_ai.agent.description when non-empty, matching .NET and Python which omit these attributes for an unnamed/undescribed agent rather than emitting empty strings.
a95d1e3 to
09349fc
Compare
Cross-Repo Parity Review — ✅ AlignedThis PR fixes two OTel Change 1: Span name follows
|
What
Two GenAI-semantic-convention fixes in the
invoke_agentspan setup inprovider/otelprovider/otel.go:Span name. The span was started with the raw agent name (
tracer.Start(ctx, a.Name(), ...));invoke_agentwas only used for thegen_ai.operation.nameattribute, never the span name. It is now named<operation> <target>(e.g.invoke_agent helper), falling back to the agent id when the name is empty so the span still carries a target.Empty attributes.
gen_ai.agent.nameandgen_ai.agent.descriptionwere set unconditionally, so an agent with no name/description produced empty-string attributes. They are now appended only when non-empty. The provider name still keeps itsunknowndefault (parity with Python).Why
The GenAI semantic conventions require the span be named operation + target. The sibling tool span already does this —
startToolSpanintoolautocall/autocall.gobuildsexecute_tool <tool>— so the agent span was inconsistent within this repo and diverged from the .NET and Python SDKs. Both .NET and Python also omitgen_ai.agent.name/gen_ai.agent.descriptionwhen they are empty rather than emitting empty strings.Tests
Extended
provider/otelprovider/otel_test.gousing the existingtracetestin-memory exporter harness:TestOtel_Run_SpanNamePrefixedWithOperation— asserts the span Name isinvoke_agent helper.TestOtel_Run_OmitsEmptyAgentNameAndDescription— asserts nogen_ai.agent.name/gen_ai.agent.descriptionkeys for an unnamed/undescribed agent.TestOtel_Run_SpanHasCorrectAttributesto expect the prefixed span name.go build ./...,go vet ./provider/otelprovider/..., andgo test ./provider/otelprovider/...all pass.