@@ -38,7 +38,6 @@ import ai.koog.agents.features.opentelemetry.span.endInvokeAgentSpan
3838import ai.koog.agents.features.opentelemetry.span.endNodeExecuteSpan
3939import ai.koog.agents.features.opentelemetry.span.endStrategySpan
4040import ai.koog.agents.features.opentelemetry.span.endSubgraphExecuteSpan
41- import ai.koog.agents.features.opentelemetry.span.enrichExecuteToolSpanWithMcpAttrs
4241import ai.koog.agents.features.opentelemetry.span.startCreateAgentSpan
4342import ai.koog.agents.features.opentelemetry.span.startExecuteToolSpan
4443import ai.koog.agents.features.opentelemetry.span.startInferenceSpan
@@ -114,10 +113,10 @@ public class OpenTelemetry {
114113 id = eventContext.eventId,
115114 runId = eventContext.context.runId,
116115 nodeId = eventContext.node.id,
117- nodeInput = nodeInput
116+ nodeInput = nodeInput,
117+ spanAdapter = spanAdapter,
118118 )
119119
120- spanAdapter?.onBeforeSpanStarted(nodeExecuteSpan)
121120 spanCollector.collectSpan(
122121 span = nodeExecuteSpan,
123122 path = patchedExecutionInfo
@@ -137,11 +136,11 @@ public class OpenTelemetry {
137136
138137 val nodeOutput = nodeDataToString(eventContext.output, eventContext.outputType, pipeline.config.serializer)
139138
140- spanAdapter?.onBeforeSpanFinished(nodeExecuteSpan)
141139 endNodeExecuteSpan(
142140 span = nodeExecuteSpan,
143141 nodeOutput = nodeOutput,
144- verbose = config.isVerbose
142+ verbose = config.isVerbose,
143+ spanAdapter = spanAdapter,
145144 )
146145 spanCollector.removeSpan(
147146 span = nodeExecuteSpan,
@@ -160,12 +159,12 @@ public class OpenTelemetry {
160159 spanType = SpanType .NODE
161160 ) ? : return @intercept
162161
163- spanAdapter?.onBeforeSpanFinished(nodeExecuteSpan)
164162 endNodeExecuteSpan(
165163 span = nodeExecuteSpan,
166164 nodeOutput = null ,
167165 error = eventContext.error,
168- verbose = config.isVerbose
166+ verbose = config.isVerbose,
167+ spanAdapter = spanAdapter,
169168 )
170169 spanCollector.removeSpan(
171170 span = nodeExecuteSpan,
@@ -194,10 +193,10 @@ public class OpenTelemetry {
194193 id = eventContext.eventId,
195194 runId = eventContext.context.runId,
196195 subgraphId = eventContext.subgraph.id,
197- subgraphInput = subgraphInput
196+ subgraphInput = subgraphInput,
197+ spanAdapter = spanAdapter,
198198 )
199199
200- spanAdapter?.onBeforeSpanStarted(subgraphExecuteSpan)
201200 spanCollector.collectSpan(
202201 span = subgraphExecuteSpan,
203202 path = patchedExecutionInfo
@@ -217,11 +216,11 @@ public class OpenTelemetry {
217216
218217 val subgraphOutput = nodeDataToString(eventContext.output, eventContext.outputType, pipeline.config.serializer)
219218
220- spanAdapter?.onBeforeSpanFinished(subgraphExecuteSpan)
221219 endSubgraphExecuteSpan(
222220 span = subgraphExecuteSpan,
223221 subgraphOutput = subgraphOutput,
224- verbose = config.isVerbose
222+ verbose = config.isVerbose,
223+ spanAdapter = spanAdapter,
225224 )
226225 spanCollector.removeSpan(
227226 span = subgraphExecuteSpan,
@@ -240,12 +239,12 @@ public class OpenTelemetry {
240239 spanType = SpanType .SUBGRAPH
241240 ) ? : return @intercept
242241
243- spanAdapter?.onBeforeSpanFinished(subgraphExecuteSpan)
244242 endSubgraphExecuteSpan(
245243 span = subgraphExecuteSpan,
246244 subgraphOutput = null ,
247245 error = eventContext.error,
248- verbose = config.isVerbose
246+ verbose = config.isVerbose,
247+ spanAdapter = spanAdapter,
249248 )
250249 spanCollector.removeSpan(
251250 span = subgraphExecuteSpan,
@@ -311,10 +310,10 @@ public class OpenTelemetry {
311310 id = eventContext.eventId,
312311 model = eventContext.agent.agentConfig.model,
313312 agentId = eventContext.context.agentId,
314- messages = messages
313+ messages = messages,
314+ spanAdapter = spanAdapter,
315315 )
316316
317- spanAdapter?.onBeforeSpanStarted(createAgentSpan)
318317 spanCollector.collectSpan(
319318 span = createAgentSpan,
320319 path = eventContext.executionInfo
@@ -331,10 +330,10 @@ public class OpenTelemetry {
331330 runId = eventContext.runId,
332331 llmParams = eventContext.agent.agentConfig.prompt.params,
333332 messages = messages,
334- tools = tools
333+ tools = tools,
334+ spanAdapter = spanAdapter,
335335 )
336336
337- spanAdapter?.onBeforeSpanStarted(invokeAgentSpan)
338337 // Patch the agent execution info to include runId in the path.
339338 // This is required to create a path structure that matches the span structure in the OTel feature.
340339 spanCollector.collectSpan(
@@ -360,12 +359,12 @@ public class OpenTelemetry {
360359 )
361360 }
362361
363- spanAdapter?.onBeforeSpanFinished(invokeAgentSpan)
364362 endInvokeAgentSpan(
365363 span = invokeAgentSpan,
366364 messages = eventContext.context.config.prompt.messages.toList(),
367365 model = eventContext.context.config.model,
368- verbose = config.isVerbose
366+ verbose = config.isVerbose,
367+ spanAdapter = spanAdapter,
369368 )
370369 spanCollector.removeSpan(
371370 span = invokeAgentSpan,
@@ -395,13 +394,13 @@ public class OpenTelemetry {
395394 spanType = SpanType .INVOKE_AGENT
396395 ) ? : return @intercept
397396
398- spanAdapter?.onBeforeSpanFinished(invokeAgentSpan)
399397 endInvokeAgentSpan(
400398 span = invokeAgentSpan,
401399 messages = eventContext.context.config.prompt.messages.toList(),
402400 model = eventContext.context.config.model,
403401 error = eventContext.error,
404- verbose = config.isVerbose
402+ verbose = config.isVerbose,
403+ spanAdapter = spanAdapter,
405404 )
406405 spanCollector.removeSpan(
407406 span = invokeAgentSpan,
@@ -428,10 +427,10 @@ public class OpenTelemetry {
428427 spanType = SpanType .CREATE_AGENT
429428 ) ? : return @intercept
430429
431- spanAdapter?.onBeforeSpanFinished(agentSpan)
432430 endCreateAgentSpan(
433431 span = agentSpan,
434- verbose = config.isVerbose
432+ verbose = config.isVerbose,
433+ spanAdapter = spanAdapter,
435434 )
436435
437436 spanCollector.removeSpan(
@@ -468,10 +467,10 @@ public class OpenTelemetry {
468467 parentSpan = parentSpan,
469468 id = eventContext.eventId,
470469 runId = eventContext.context.runId,
471- strategyName = eventContext.strategy.name
470+ strategyName = eventContext.strategy.name,
471+ spanAdapter = spanAdapter,
472472 )
473473
474- spanAdapter?.onBeforeSpanStarted(strategySpan)
475474 spanCollector.collectSpan(
476475 span = strategySpan,
477476 path = patchedExecutionInfo
@@ -487,8 +486,11 @@ public class OpenTelemetry {
487486 spanType = SpanType .STRATEGY
488487 ) ? : return @intercept
489488
490- spanAdapter?.onBeforeSpanFinished(strategySpan)
491- endStrategySpan(span = strategySpan, verbose = config.isVerbose)
489+ endStrategySpan(
490+ span = strategySpan,
491+ verbose = config.isVerbose,
492+ spanAdapter = spanAdapter,
493+ )
492494 spanCollector.removeSpan(
493495 span = strategySpan,
494496 path = patchedExecutionInfo
@@ -522,11 +524,10 @@ public class OpenTelemetry {
522524 model = eventContext.model,
523525 messages = messages,
524526 llmParams = eventContext.prompt.params,
525- tools = eventContext.tools
527+ tools = eventContext.tools,
528+ spanAdapter = spanAdapter,
526529 )
527530
528- // Start span
529- spanAdapter?.onBeforeSpanStarted(inferenceSpan)
530531 spanCollector.collectSpan(
531532 span = inferenceSpan,
532533 path = patchedExecutionInfo
@@ -563,20 +564,13 @@ public class OpenTelemetry {
563564 )
564565 }
565566
566- // Pre-populate gen_ai.output.messages so SpanAdapter implementations (Langfuse, Weave)
567- // can reshape the response messages before the span ends.
568- // endInferenceSpan re-adds the same attribute idempotently.
569- if (eventContext.responses.isNotEmpty()) {
570- inferenceSpan.addAttribute(GenAIAttributes .Output .Messages (eventContext.responses))
571- }
572-
573567 // Stop InferenceSpan
574- spanAdapter?.onBeforeSpanFinished(inferenceSpan)
575568 endInferenceSpan(
576569 span = inferenceSpan,
577570 messages = eventContext.responses,
578571 model = eventContext.model,
579- verbose = config.isVerbose
572+ verbose = config.isVerbose,
573+ spanAdapter = spanAdapter,
580574 )
581575 spanCollector.removeSpan(
582576 span = inferenceSpan,
@@ -629,13 +623,13 @@ public class OpenTelemetry {
629623 spanType = SpanType .INFERENCE
630624 ) ? : return @intercept
631625
632- spanAdapter?.onBeforeSpanFinished(inferenceSpan)
633626 endInferenceSpan(
634627 span = inferenceSpan,
635628 messages = emptyList(),
636629 model = eventContext.model,
630+ error = eventContext.error,
637631 verbose = config.isVerbose,
638- error = eventContext.error
632+ spanAdapter = spanAdapter,
639633 )
640634 spanCollector.removeSpan(
641635 span = inferenceSpan,
@@ -664,32 +658,11 @@ public class OpenTelemetry {
664658 toolName = eventContext.toolName,
665659 toolArgs = eventContext.toolArgs.toKotlinxJsonObject(),
666660 toolDescription = eventContext.toolDescription,
667- toolCallId = eventContext.toolCallId
668- )
669- val mcpToolMetadata = eventContext.context.llm.toolRegistry.getMcpToolMeta(eventContext.toolName)
670- if (mcpToolMetadata != null ) {
671- val mcpVersion = mcpToolMetadata[McpMetadataKeys .McpProtocolVersion ]
672- val mcpTransportType = mcpToolMetadata[McpMetadataKeys .McpTransportType ]
673- if (mcpVersion != null && mcpTransportType != null ) {
674- executeToolSpan.enrichExecuteToolSpanWithMcpAttrs(
675- toolName = eventContext.toolName,
676- sessionId = mcpToolMetadata[McpMetadataKeys .McpSessionId ],
677- methodName = " tools/call" ,
678- serverPort = mcpToolMetadata[McpMetadataKeys .ServerPort ]?.toIntOrNull(),
679- serverAddress = mcpToolMetadata[McpMetadataKeys .ServerUrl ],
680- mcpProtocolVersion = mcpVersion,
681- mcpTransportType = mcpTransportType,
682- )
683- } else {
684- logger.error {
685- " MCP protocol version ($mcpVersion ) and transport type ($mcpTransportType ) are required " +
686- " for mcp tool call spans: tool=${eventContext.toolName} , " +
687- " serverUrl=${mcpToolMetadata[McpMetadataKeys .ServerUrl ]} "
688- }
689- }
690- }
661+ toolCallId = eventContext.toolCallId,
662+ mcpToolMetadata = eventContext.context.llm.toolRegistry.getMcpToolMeta(eventContext.toolName),
663+ spanAdapter = spanAdapter,
664+ )
691665
692- spanAdapter?.onBeforeSpanStarted(executeToolSpan)
693666 spanCollector.collectSpan(executeToolSpan, path)
694667
695668 // Metrics
@@ -918,12 +891,12 @@ public class OpenTelemetry {
918891 spanType = SpanType .EXECUTE_TOOL
919892 ) ? : return
920893
921- spanAdapter?.onBeforeSpanFinished(span = span)
922894 endExecuteToolSpan(
923895 span = span,
924896 toolResult = toolResult?.toKotlinxJsonElement(),
925897 error = error,
926- verbose = config.isVerbose
898+ verbose = config.isVerbose,
899+ spanAdapter = spanAdapter,
927900 )
928901 spanCollector.removeSpan(
929902 span = span,
0 commit comments