Skip to content

Commit d08f1fd

Browse files
committed
KG-175. Add input.value and output.value attributes for ExecuteToolSpan
1 parent c27ed28 commit d08f1fd

File tree

4 files changed

+39
-4
lines changed

4 files changed

+39
-4
lines changed

agents/agents-features/agents-features-opentelemetry/src/jvmMain/kotlin/ai/koog/agents/features/opentelemetry/attribute/SpanAttributes.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,5 +283,17 @@ internal object SpanAttributes {
283283
override val key: String = super.key.concatKey("name")
284284
override val value: String = name
285285
}
286+
287+
// Custom tool attribute with tool arguments used for tool calls
288+
data class InputValue(private val input: String) : Attribute {
289+
override val key: String = "input.value"
290+
override val value: Any = input
291+
}
292+
293+
// Custom tool attribute with tool execution results used for tool calls
294+
data class OutputValue(private val output: String) : Attribute {
295+
override val key: String = "output.value"
296+
override val value: Any = output
297+
}
286298
}
287299
}

agents/agents-features/agents-features-opentelemetry/src/jvmMain/kotlin/ai/koog/agents/features/opentelemetry/feature/OpenTelemetry.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,8 @@ public class OpenTelemetry {
345345

346346
val executeToolSpan = ExecuteToolSpan(
347347
parent = nodeExecuteSpan,
348-
tool = eventContext.tool
348+
tool = eventContext.tool,
349+
toolArgs = eventContext.toolArgs,
349350
)
350351

351352
spanProcessor.startSpan(executeToolSpan)
@@ -368,7 +369,16 @@ public class OpenTelemetry {
368369
)
369370

370371
// End the ExecuteToolSpan span
371-
spanProcessor.endSpan(executeToolSpanId)
372+
val finishAttributes = buildList {
373+
eventContext.result?.toStringDefault()?.let { result ->
374+
add(SpanAttributes.Tool.OutputValue(result))
375+
}
376+
}
377+
378+
spanProcessor.endSpan(
379+
spanId = executeToolSpanId,
380+
attributes = finishAttributes
381+
)
372382
}
373383

374384
pipeline.interceptToolCallFailure(interceptContext) { eventContext ->

agents/agents-features/agents-features-opentelemetry/src/jvmMain/kotlin/ai/koog/agents/features/opentelemetry/span/ExecuteToolSpan.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package ai.koog.agents.features.opentelemetry.span
22

33
import ai.koog.agents.core.tools.Tool
4+
import ai.koog.agents.core.tools.ToolArgs
5+
import ai.koog.agents.core.tools.ToolResult
46
import ai.koog.agents.features.opentelemetry.attribute.Attribute
57
import ai.koog.agents.features.opentelemetry.attribute.SpanAttributes
68
import io.opentelemetry.api.trace.SpanKind
@@ -11,6 +13,7 @@ import io.opentelemetry.api.trace.SpanKind
1113
internal class ExecuteToolSpan(
1214
parent: NodeExecuteSpan,
1315
private val tool: Tool<*, *>,
16+
private val toolArgs: ToolArgs
1417
) : GenAIAgentSpan(parent) {
1518

1619
companion object {
@@ -26,7 +29,7 @@ internal class ExecuteToolSpan(
2629
override val kind: SpanKind = SpanKind.INTERNAL
2730

2831
/**
29-
* Add the necessary attributes for the Execute Tool Span according to the Open Telemetry Semantic Convention:
32+
* Add the necessary attributes for the Execute Tool Span, according to the Open Telemetry Semantic Convention:
3033
* https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/#execute-tool-span
3134
*
3235
* Attribute description:
@@ -41,5 +44,11 @@ internal class ExecuteToolSpan(
4144

4245
// gen_ai.tool.name
4346
add(SpanAttributes.Tool.Name(name = tool.name))
47+
48+
// Tool arguments
49+
@Suppress("UNCHECKED_CAST")
50+
(tool as? Tool<ToolArgs, ToolResult>)?.let { tool ->
51+
add(SpanAttributes.Tool.InputValue(tool.encodeArgsToString(toolArgs)))
52+
}
4453
}
4554
}

agents/agents-features/agents-features-opentelemetry/src/jvmTest/kotlin/ai/koog/agents/features/opentelemetry/feature/OpenTelemetryTest.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ class OpenTelemetryTest {
478478

479479
val mockExecutor = getMockExecutor(clock = testClock) {
480480
mockLLMToolCall(TestGetWeatherTool, TestGetWeatherTool.Args("Paris")) onRequestEquals userPrompt
481-
mockLLMAnswer(mockResponse) onRequestContains "rainy, 57°F"
481+
mockLLMAnswer(mockResponse) onRequestContains TestGetWeatherTool.RESULT
482482
}
483483

484484
val agent = createAgent(
@@ -581,6 +581,8 @@ class OpenTelemetryTest {
581581
mapOf(
582582
"tool.Get whether" to mapOf(
583583
"attributes" to mapOf(
584+
"output.value" to TestGetWeatherTool.RESULT,
585+
"input.value" to "{\"location\":\"Paris\"}",
584586
"gen_ai.tool.description" to "The test tool to get a whether based on provided location.",
585587
"gen_ai.tool.name" to "Get whether",
586588
),
@@ -764,6 +766,8 @@ class OpenTelemetryTest {
764766
mapOf(
765767
"tool.Get whether" to mapOf(
766768
"attributes" to mapOf(
769+
"output.value" to TestGetWeatherTool.RESULT,
770+
"input.value" to "{\"location\":\"Paris\"}",
767771
"gen_ai.tool.description" to "The test tool to get a whether based on provided location.",
768772
"gen_ai.tool.name" to "Get whether",
769773
),

0 commit comments

Comments
 (0)