Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Stopped setting `gen_ai.provider.name` on internal agent spans.
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,6 @@ def on_chain_start(
)
if suggested_agent_name_lower != agent_invocation_name_lower:
agent = self._telemetry_handler.invoke_local_agent(
provider=metadata.get("ls_provider", "unknown")
if metadata
else "unknown",
agent_name=suggested_agent_name,
)
agent.input_messages = make_input_message(inputs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ def test_new_agent_span_created(self):
)

telemetry.invoke_local_agent.assert_called_once_with(
provider="openai",
agent_name="math_agent",
)
assert agent_inv.agent_name == "math_agent"
Expand Down
42 changes: 28 additions & 14 deletions policies/genai_span_validation.rego
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# (name, type, presence) for spans matching its definitions; this file adds
# cross-cutting span-level invariants the registry can't easily express.
#
# Two classes of rules, both keyed on `gen_ai.operation.name`:
# Three classes of rules, all keyed on `gen_ai.operation.name`:
#
# 1. Span name format → `violation`
# (`{operation_name} {request_model}` for inference / embeddings,
Expand All @@ -17,6 +17,9 @@
# semantic-conventions/docs/gen-ai/gen-ai-spans.md and
# gen-ai-agent-spans.md (the MD flattens the YAML inheritance chain
# via `extends:`, so it's the right place to source from).
# `invoke_agent` is the one operation whose manifest also depends on
# span kind: semconv defines separate internal (same-process) and
# client (remote) spans, and only the client span carries server.*.
#
# The "set when known" Recommended subset (sampling parameters like
# `frequency_penalty`, `max_tokens`; provider-side caches; conditionally-
Expand Down Expand Up @@ -99,21 +102,26 @@ deny contains _span_finding(

# ─── Per-operation expected attributes (violation) ──────────────────────────

_expected_for_op["chat"] := _inference_expected
# `_expected_for_op(op, kind)` returns the expected-attribute manifest for a
# span given its `gen_ai.operation.name` and span kind. Most operations ignore
# kind (second arg is a wildcard); invoke_agent dispatches on it because
# semconv splits it into separate internal and client spans. Undefined (→ no
# violations) for an unmapped op or an unexpected agent span kind.
_expected_for_op("chat", _) := _inference_expected

_expected_for_op["generate_content"] := _inference_expected
_expected_for_op("generate_content", _) := _inference_expected

_expected_for_op["text_completion"] := _inference_expected
_expected_for_op("text_completion", _) := _inference_expected

_expected_for_op["embeddings"] := _embeddings_expected
_expected_for_op("embeddings", _) := _embeddings_expected

_expected_for_op["execute_tool"] := _execute_tool_expected
_expected_for_op("execute_tool", _) := _execute_tool_expected

_expected_for_op["invoke_agent"] := _invoke_agent_expected
_expected_for_op("invoke_agent", kind) := _invoke_agent_expected[kind]

_expected_for_op["create_agent"] := _create_agent_expected
_expected_for_op("create_agent", _) := _create_agent_expected

_expected_for_op["retrieval"] := _retrieval_expected
_expected_for_op("retrieval", _) := _retrieval_expected

# Inference (chat / generate_content / text_completion).
# Required: gen_ai.operation.name, gen_ai.provider.name.
Expand Down Expand Up @@ -156,11 +164,17 @@ _execute_tool_expected := {
"gen_ai.tool.type",
}

# Invoke agent.
# Required: gen_ai.operation.name, gen_ai.provider.name.
_invoke_agent_expected := {
# Invoke agent (internal)
# Required: gen_ai.operation.name
_invoke_agent_expected["internal"] := {
"gen_ai.operation.name",
"gen_ai.provider.name",
}

# Invoke agent (client)
# Required: gen_ai.operation.name, server.address
_invoke_agent_expected["client"] := {
"gen_ai.operation.name",
"server.address",
}

# Create agent. After creation completes the provider returns an agent.id;
Expand Down Expand Up @@ -193,7 +207,7 @@ deny contains _span_finding(
) if {
input.sample.span
op := _attr_value(input.sample.span, "gen_ai.operation.name")
expected := _expected_for_op[op]
expected := _expected_for_op(op, input.sample.span.kind)
some attr_name in expected
not _has_attr(input.sample.span, attr_name)
}
Expand Down
1 change: 1 addition & 0 deletions util/opentelemetry-util-genai/.changelog/132.removed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Removed the `provider` parameter from the internal agent invocation APIs and stopped emitting `gen_ai.provider.name` on internal agent spans and metrics.
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ def __init__(
metrics_recorder: InvocationMetricsRecorder,
logger: Logger,
completion_hook: CompletionHook,
provider: str,
*,
provider: str | None = None,
span_kind: SpanKind = SpanKind.INTERNAL,
request_model: str | None = None,
Comment thread
lmolkova marked this conversation as resolved.
server_address: str | None = None,
Expand All @@ -64,10 +64,10 @@ def __init__(
else _operation_name,
span_kind=span_kind,
)
self.provider = provider
self.request_model = request_model
self.server_address = server_address
self.server_port = server_port
self.provider = provider

self.agent_name: str | None = agent_name
self.agent_id: str | None = None
Expand Down Expand Up @@ -104,19 +104,20 @@ def __init__(
def _get_base_attributes(self) -> dict[str, Any]:
"""Return sampling-relevant attributes available at span creation time."""
optional_attrs = (
(GenAI.GEN_AI_PROVIDER_NAME, self.provider),
(GenAI.GEN_AI_REQUEST_MODEL, self.request_model),
(GenAI.GEN_AI_AGENT_NAME, self.agent_name),
(server_attributes.SERVER_ADDRESS, self.server_address),
(server_attributes.SERVER_PORT, self.server_port),
)
return {
GenAI.GEN_AI_OPERATION_NAME: self._operation_name,
GenAI.GEN_AI_PROVIDER_NAME: self.provider,
**{k: v for k, v in optional_attrs if v is not None},
}

def _get_common_attributes(self) -> dict[str, Any]:
optional_attrs = (
(GenAI.GEN_AI_PROVIDER_NAME, self.provider),
(GenAI.GEN_AI_REQUEST_MODEL, self.request_model),
(server_attributes.SERVER_ADDRESS, self.server_address),
(server_attributes.SERVER_PORT, self.server_port),
Expand All @@ -127,7 +128,6 @@ def _get_common_attributes(self) -> dict[str, Any]:
)
return {
GenAI.GEN_AI_OPERATION_NAME: self._operation_name,
GenAI.GEN_AI_PROVIDER_NAME: self.provider,
**{k: v for k, v in optional_attrs if v is not None},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,6 @@ def tool(

def start_invoke_local_agent(
self,
provider: str,
*,
request_model: str | None = None,
agent_name: str | None = None,
Comment thread
lmolkova marked this conversation as resolved.
Expand All @@ -409,7 +408,6 @@ def start_invoke_local_agent(
self._metrics_recorder,
self._logger,
self._completion_hook,
provider,
span_kind=SpanKind.INTERNAL,
request_model=request_model,
agent_name=agent_name,
Expand Down Expand Up @@ -439,7 +437,7 @@ def start_invoke_remote_agent(
self._metrics_recorder,
self._logger,
self._completion_hook,
provider,
provider=provider,
span_kind=SpanKind.CLIENT,
request_model=request_model,
agent_name=agent_name,
Expand All @@ -449,7 +447,6 @@ def start_invoke_remote_agent(

def invoke_local_agent(
self,
provider: str,
*,
request_model: str | None = None,
agent_name: str | None = None,
Comment thread
lmolkova marked this conversation as resolved.
Expand All @@ -469,7 +466,6 @@ def invoke_local_agent(
self._metrics_recorder,
self._logger,
self._completion_hook,
provider,
span_kind=SpanKind.INTERNAL,
request_model=request_model,
agent_name=agent_name,
Expand Down Expand Up @@ -499,7 +495,7 @@ def invoke_remote_agent(
self._metrics_recorder,
self._logger,
self._completion_hook,
provider,
provider=provider,
span_kind=SpanKind.CLIENT,
request_model=request_model,
agent_name=agent_name,
Expand Down
Loading