Skip to content

Split AgentInvocation into LocalAgentInvocation and RemoteAgentInvocation - #616

Draft
lmolkova wants to merge 4 commits into
lmolkova-metrics-refactorfrom
lmolkova-agent-split
Draft

Split AgentInvocation into LocalAgentInvocation and RemoteAgentInvocation#616
lmolkova wants to merge 4 commits into
lmolkova-metrics-refactorfrom
lmolkova-agent-split

Conversation

@lmolkova

@lmolkova lmolkova commented Sep 4, 2026

Copy link
Copy Markdown
Member

What does this change do?

Splits AgentInvocation into LocalAgentInvocation (SpanKind.INTERNAL) for in-process framework agents and RemoteAgentInvocation (SpanKind.CLIENT) for external agent services, and updates agent instrumentations and conformance scenarios to expect the new metrics.

Why?

Aligns agent spans and metrics with GenAI semantic conventions (agent spans spec):

  • Span kind distinction: In-process framework agents use INTERNAL spans, while remote agent calls use CLIENT spans.
  • Attributes on local agents:
    • gen_ai.agent.id is removed from local agent spans (only applies to remote agents with service-managed identifiers).
    • Provider and server attributes (gen_ai.provider.name, server.address, server.port) are excluded on local agent spans.
  • Attributes on remote agents: Supports gen_ai.agent.id, gen_ai.agent.version, gen_ai.request.previous_response.id, and cache token usage (gen_ai.usage.cache_write.input_tokens, gen_ai.usage.cache_read.input_tokens).
  • Duration metric: Records gen_ai.invoke_agent.duration (s) on local agent runs (replacing gen_ai.client.operation.duration), tagged with gen_ai.agent.name and optional gen_ai.request.model.

lmolkova added a commit that referenced this pull request Sep 4, 2026
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Sep 4, 2026

Copy link
Copy Markdown

Pull request dashboard status

Waiting on the author · refreshed 2026-09-04 06:38 UTC

Move out of draft to request review.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

Copilot AI 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.

🟡 Changes recommended

The split breaks direct construction of the public base class and omits known remote-agent identity from sampling attributes.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Splits local and remote agent invocation telemetry to align span kinds, attributes, and metrics with GenAI semantic conventions.

Changes:

  • Adds dedicated LocalAgentInvocation and RemoteAgentInvocation classes.
  • Records local-agent duration metrics while preserving remote client metrics.
  • Updates instrumentation tests, conformance expectations, and changelogs.
File summaries
File Description
util/opentelemetry-util-genai/tests/test_handler_agent.py Tests split invocation behavior and metrics.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/invocation.py Exports the new invocation types.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/handler.py Constructs local or remote invocation types.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py Implements split invocation telemetry.
util/opentelemetry-util-genai/.changelog/616.changed Documents local duration metrics.
util/opentelemetry-util-genai/.changelog/616.added Documents new public classes.
instrumentation/opentelemetry-instrumentation-genai-qwen-agent/tests/conformance/invoke_agent.py Updates expected agent/tool metrics.
instrumentation/opentelemetry-instrumentation-genai-qwen-agent/.changelog/616.changed Documents metric changes.
instrumentation/opentelemetry-instrumentation-genai-openai-agents/tests/conformance/orchestration.py Updates orchestration metrics.
instrumentation/opentelemetry-instrumentation-genai-openai-agents/.changelog/616.changed Documents metric changes.
instrumentation/opentelemetry-instrumentation-genai-llama-index/tests/conformance/agent.py Updates agent metrics.
instrumentation/opentelemetry-instrumentation-genai-llama-index/.changelog/616.changed Documents metric changes.
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_callback_handler.py Updates local-agent metadata assertions.
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/conformance/agent.py Adds agent/tool metric expectations.
instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py Stops assigning hosted IDs to local agents.
instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/616.changed Documents metric and attribute changes.
instrumentation/opentelemetry-instrumentation-genai-agno/tests/conformance/agent.py Updates agent/tool metrics.
instrumentation/opentelemetry-instrumentation-genai-agno/.changelog/616.changed Documents metric changes.
Review details

Suppressed comments (1)

util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py:262

  • This link targets the main semantic-conventions repository, where this GenAI document does not live. Point it at open-telemetry/semantic-conventions-genai so the new public class docstring has a working specification reference.
        https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-agent-spans.md#invoke-agent-client-span
  • Files reviewed: 18/18 changed files
  • Comments generated: 3
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 56 to +57
class AgentInvocation(GenAIInvocation):
"""Represents a single agent invocation (invoke_agent span).
"""Base class representing a GenAI agent invocation (invoke_agent span).
Comment on lines +277 to +278
agent_id: str | None = None,
agent_version: str | None = None,
Comment thread util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py Outdated
lmolkova added a commit to lmolkova/opentelemetry-python-genai that referenced this pull request Sep 4, 2026
lmolkova added a commit that referenced this pull request Sep 4, 2026
@lmolkova
lmolkova force-pushed the lmolkova-agent-split branch from 0e5ffcc to a69b40c Compare September 4, 2026 05:57
lmolkova added a commit that referenced this pull request Sep 4, 2026
@lmolkova
lmolkova force-pushed the lmolkova-agent-split branch from a69b40c to 5c62b47 Compare September 4, 2026 06:10
@lmolkova
lmolkova force-pushed the lmolkova-agent-split branch 2 times, most recently from 9aff3d6 to 2bfab08 Compare September 4, 2026 06:18

@DylanRussell DylanRussell 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.

Recommended Cleanups
google-genai/interactions.py: Change InferenceInvocation | AgentInvocation to InferenceInvocation | RemoteAgentInvocation.
qwen-agent / llama-index / langchain internal handler signatures: Update helper functions like _set_agent_output(invocation: AgentInvocation) to invocation: LocalAgentInvocation where they specifically handle LocalAgentInvocation.

)


class LocalAgentInvocation(AgentInvocation):

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.

Recommended Cleanups

google-genai/interactions.py: Change InferenceInvocation | AgentInvocation to InferenceInvocation | RemoteAgentInvocation.

qwen-agent / llama-index / langchain internal handler signatures: Update helper functions like _set_agent_output(invocation: AgentInvocation) to invocation: LocalAgentInvocation where they specifically handle LocalAgentInvocation.

tool_definitions=self.tool_definitions,
for_span=True,
)
attrs = dict(super()._get_usage_attributes())

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.

nit: we don't need to wrap this in dict() since get_usage_attributes is already creating a new dict

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.

same thing above (and maybe in other places didn't check everything)

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.

3 participants