Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6f6c400
opentelementry-instrumentation-google-genai: add gen_ai.tool.definiti…
wikaaaaa Jan 23, 2026
befc106
Add _to_tool_definition
wikaaaaa Jan 26, 2026
e724d13
Remove unused import
wikaaaaa Jan 26, 2026
238580a
Add GEN_AI_TOOL_DEFINITIONS to tests.
wikaaaaa Jan 26, 2026
c786752
Remove uneccesary space.
wikaaaaa Jan 26, 2026
35f0c68
Merge branch 'main' into tooldefinitions
wikaaaaa Jan 26, 2026
daec2f6
Merge branch 'main' into tooldefinitions
wikaaaaa Jan 26, 2026
f0b7ecc
Merge branch 'main' into tooldefinitions
wikaaaaa Jan 27, 2026
4fa7323
address comments: add exclude_none to model_dump and tool type to err…
wikaaaaa Jan 28, 2026
aea8374
address comment: add if/else statement on tool types and add tests fo…
wikaaaaa Jan 29, 2026
74b343e
Merge branch 'main' into tooldefinitions
wikaaaaa Jan 29, 2026
270ae8b
dont serilize mcp client sessions in case of synchronous methods
wikaaaaa Jan 30, 2026
9acaa71
Refactor _to_tool_definition_common to be more clear
wikaaaaa Feb 2, 2026
60f66ae
remove uncessary 'function' key
wikaaaaa Feb 2, 2026
c19cd9c
fix failing tests: make mcp import conditional
wikaaaaa Feb 3, 2026
364aed2
Update changelog
wikaaaaa Feb 3, 2026
bafdbe1
Merge branch 'main' into tooldefinitions
wikaaaaa Feb 3, 2026
d679473
Update uv.lock
wikaaaaa Feb 3, 2026
f14cfb9
address comment: remove undecessary typing.Type
wikaaaaa Feb 4, 2026
1b07dcf
address comment: make mcp import conditional
wikaaaaa Feb 4, 2026
9371484
Merge branch 'main' into tooldefinitions
wikaaaaa Feb 4, 2026
7588cc1
Merge branch 'main' into tooldefinitions
wikaaaaa Feb 4, 2026
2d86bd5
Merge branch 'main' into tooldefinitions
wikaaaaa Feb 4, 2026
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
Expand Up @@ -42,6 +42,8 @@
GenerateContentConfig,
GenerateContentConfigOrDict,
GenerateContentResponse,
ToolListUnionDict,
ToolUnionDict,
)

from opentelemetry import context as context_api
Expand Down Expand Up @@ -185,6 +187,35 @@ def _to_dict(value: object):
return json.loads(json.dumps(value))


def _to_tool_definition(tool: ToolUnionDict) -> MessagePart:
if isinstance(tool, dict):
Comment thread
DylanRussell marked this conversation as resolved.
Outdated
return tool
if hasattr(tool, "to_json_dict"):
try:
return tool.to_json_dict()
except TypeError:
pass
if hasattr(tool, "model_dump"):
try:
return tool.model_dump(exclude_none=True)
except TypeError:
pass
if callable(tool) and hasattr(tool, "__name__"):
doc = getattr(tool, "__doc__", "") or ""
return {
"function": {
"name": getattr(tool, "__name__", str(type(tool))),
"description": doc.strip(),
}
}
try:
return {"value": str(tool)}
except Exception:
return {
"error": f"failed to serialize tool definition, tool type={type(tool).__name__}"
}


def _create_request_attributes(
config: Optional[GenerateContentConfigOrDict],
allow_list: AllowList,
Expand Down Expand Up @@ -285,10 +316,22 @@ def _config_to_system_instruction(
return config.system_instruction


def _config_to_tools(
config: Union[GenerateContentConfigOrDict, None],
) -> Union[ToolListUnionDict, None]:
if not config:
return None

if isinstance(config, dict):
return GenerateContentConfig.model_validate(config).tools
return config.tools


def _create_completion_details_attributes(
input_messages: list[InputMessage],
output_messages: list[OutputMessage],
system_instructions: list[MessagePart],
tool_definitions: list[MessagePart],
as_str: bool = False,
) -> dict[str, AttributeValue]:
attributes: dict[str, AttributeValue] = {
Expand All @@ -306,6 +349,11 @@ def _create_completion_details_attributes(
dataclasses.asdict(sys_instr) for sys_instr in system_instructions
]

if tool_definitions:
attributes[gen_ai_attributes.GEN_AI_TOOL_DEFINITIONS] = (
tool_definitions
)

return attributes


Expand Down Expand Up @@ -485,6 +533,10 @@ def _maybe_log_completion_details(
)
output_messages = to_output_messages(candidates=candidates)

tool_definitions = []
if tools := _config_to_tools(config):
tool_definitions = [_to_tool_definition(tool) for tool in tools]

span = trace.get_current_span()
event = LogRecord(
event_name="gen_ai.client.inference.operation.details",
Expand All @@ -503,6 +555,7 @@ def _maybe_log_completion_details(
input_messages,
output_messages,
system_instructions,
tool_definitions,
Comment thread
DylanRussell marked this conversation as resolved.
)
if self._content_recording_enabled in [
ContentCapturingMode.EVENT_ONLY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
# pylint: disable=too-many-public-methods


def _some_tool():
"""Description of some tool."""
return "result"


class ExampleResponseSchema(BaseModel):
name: str = Field(description="A Destination's Name")

Expand Down Expand Up @@ -359,6 +364,7 @@ def test_new_semconv_record_completion_as_log(self):
content = "Some input"
output = "Some response content"
sys_instr = "System instruction"
tools = [_some_tool]
with self.subTest(
f"mode: {mode}", patched_environ=patched_environ
):
Expand All @@ -371,6 +377,7 @@ def test_new_semconv_record_completion_as_log(self):
config=GenerateContentConfig(
system_instruction=sys_instr,
response_schema=ExampleResponseSchema,
tools=tools,
),
)
self.otel.assert_has_event_named(
Expand Down Expand Up @@ -401,6 +408,11 @@ def test_new_semconv_record_completion_as_log(self):
gen_ai_attributes.GEN_AI_SYSTEM_INSTRUCTIONS,
event.attributes,
)
self.assertNotIn(
gen_ai_attributes.GEN_AI_TOOL_DEFINITIONS,
event.attributes,
)

else:
expected_event_attributes = {
gen_ai_attributes.GEN_AI_INPUT_MESSAGES: (
Expand All @@ -423,6 +435,14 @@ def test_new_semconv_record_completion_as_log(self):
gen_ai_attributes.GEN_AI_SYSTEM_INSTRUCTIONS: (
{"content": sys_instr, "type": "text"},
),
gen_ai_attributes.GEN_AI_TOOL_DEFINITIONS: (
{
"function": {
Comment thread
wikaaaaa marked this conversation as resolved.
Outdated
"name": "_some_tool",
"description": "Description of some tool.",
}
},
),
}
self.assertEqual(
event.attributes[
Expand All @@ -448,6 +468,14 @@ def test_new_semconv_record_completion_as_log(self):
gen_ai_attributes.GEN_AI_SYSTEM_INSTRUCTIONS
],
)
self.assertEqual(
event.attributes[
gen_ai_attributes.GEN_AI_TOOL_DEFINITIONS
],
expected_event_attributes[
gen_ai_attributes.GEN_AI_TOOL_DEFINITIONS
],
)
self.tearDown()

def test_new_semconv_record_completion_in_span(self):
Expand Down Expand Up @@ -477,6 +505,7 @@ def test_new_semconv_record_completion_in_span(self):
config=GenerateContentConfig(
system_instruction="System instruction",
response_schema=ExampleResponseSchema,
tools=[_some_tool],
),
)
span = self.otel.get_span_named(
Expand Down Expand Up @@ -504,6 +533,12 @@ def test_new_semconv_record_completion_in_span(self):
],
'[{"content":"System instruction","type":"text"}]',
)
self.assertEqual(
span.attributes[
gen_ai_attributes.GEN_AI_TOOL_DEFINITIONS
],
'[{"function":{"name":"_some_tool","description":"Description of some tool."}}]',
)
else:
self.assertNotIn(
gen_ai_attributes.GEN_AI_INPUT_MESSAGES,
Expand All @@ -517,6 +552,10 @@ def test_new_semconv_record_completion_in_span(self):
gen_ai_attributes.GEN_AI_SYSTEM_INSTRUCTIONS,
span.attributes,
)
self.assertNotIn(
gen_ai_attributes.GEN_AI_TOOL_DEFINITIONS,
span.attributes,
)

self.tearDown()

Expand Down