Skip to content
Open
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
15 changes: 14 additions & 1 deletion tools/gen-ai/runner/src/genai_conformance/_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@

from typing import Any, Callable, Mapping

# Which operation names belong to which span type.
# Which operation names belong to which span type. gen_ai.invocation.internal
# replaces gen_ai.invoke_agent.internal and gen_ai.invoke_workflow.internal
# (semantic-conventions-genai#571); both are listed so either registry
# classifies, and span kind keeps only the types the pinned model declares.
_OPERATION_NAMES = {
"gen_ai.create_agent.client": {"create_agent"},
"gen_ai.embeddings.client": {"embeddings"},
Expand All @@ -24,6 +27,11 @@
"gen_ai.invoke_agent.client": {"invoke_agent"},
"gen_ai.invoke_agent.internal": {"invoke_agent"},
"gen_ai.invoke_workflow.internal": {"invoke_workflow"},
"gen_ai.invocation.internal": {
"invoke_agent",
"invoke_workflow",
"invoke_runner",
},
"gen_ai.memory.client": {
"create_memory",
"create_memory_store",
Expand Down Expand Up @@ -52,6 +60,11 @@
"gen_ai.invoke_agent.client": {"gen_ai.agent.id", "gen_ai.agent.name"},
"gen_ai.invoke_agent.internal": {"gen_ai.agent.id", "gen_ai.agent.name"},
"gen_ai.invoke_workflow.internal": {"gen_ai.workflow.name"},
"gen_ai.invocation.internal": {
"gen_ai.agent.id",
"gen_ai.agent.name",
"gen_ai.workflow.name",
},
"gen_ai.retrieval.client": {"gen_ai.data_source.id"},
}

Expand Down
21 changes: 21 additions & 0 deletions tools/gen-ai/runner/tests/test_genai_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,27 @@ def test_span_kind_tells_the_two_invoke_agent_types_apart(
}


def test_invocation_internal_covers_agent_workflow_and_runner() -> None:
"""A registry with gen_ai.invocation.internal classifies in-process
invocations there, whatever the pinned registry declares."""
classify_span = DOMAIN.classifier(
{
"spans": {
"gen_ai.invoke_agent.client": {"kind": "client"},
"gen_ai.invocation.internal": {"kind": "internal"},
}
}
)

for operation in ("invoke_agent", "invoke_workflow", "invoke_runner"):
assert classify_span(
"", "internal", {"gen_ai.operation.name": operation}
) == {"gen_ai.invocation.internal"}
assert classify_span(
"", "client", {"gen_ai.operation.name": "invoke_agent"}
) == {"gen_ai.invoke_agent.client"}


def test_a_span_of_no_known_type_is_classified_as_nothing(
classify_span,
) -> None:
Expand Down