Skip to content

ADK Java OTel spans do not expose tool-call execution correctly in Langfuse/OpenInference #1235

Description

@akbarkanso

🔴 Required Information

Describe the Bug:
ADK Java traces exported to Langfuse via OTLP show call_llm spans, but tool-call execution is not represented correctly: tools appear as "not called", and execute_tool visibility/payload mapping is missing or inconsistent even when tools were actually invoked.

Steps to Reproduce:

  1. Create an ADK Java agent with MCP tools (for example, list_premerge_failed_tests_by_job and list_unhealthy_tests).
  2. Configure OpenTelemetry export to Langfuse using OtlpHttpSpanExporter.
  3. Run an agent prompt that should invoke those tools.
  4. Open the resulting trace in Langfuse UI and inspect the call_llm observation and tool section.
  5. Observe that tools are displayed as "not called" and no reliable execute_tool observation/payload is shown.

Expected Behavior:
When tools execute, Langfuse should show them as called, include execute_tool observation visibility, and render tool request/response payloads correctly.

Observed Behavior:

  • call_llm is visible in timeline.
  • Tools are shown as "not called" in the same trace.
  • Tool-call visibility/payload mapping is missing or inconsistent.
  • No crash, but observability is incorrect/incomplete for tool execution.

Environment Details:

  • ADK Library Version (see maven dependency): com.google.adk:google-adk:1.2.0 (google-adk-spring-ai:1.2.0)
  • OS: macOS
  • TS Version (tsc --version): N/A (Java integration)

Model Information:

  • Which model is being used: qwen-3.5-122b

🟡 Optional Information

Regression:
Unknown.

Logs:

Langfuse UI observation:
- call_llm span present
- Tools section shows entries as "not called"
- Agent output text indicates tools were expected/executed in flow

Screenshots / Video:

Image

Additional Context:

  • ADK Java appears to emit ADK-specific attributes (e.g. gcp.vertex.agent.tool_call_args, gcp.vertex.agent.tool_response, gcp.vertex.agent.llm_request, gcp.vertex.agent.llm_response).
  • Langfuse/OpenInference expects standard tool/IO mapping on spans (e.g. input.value, output.value) for reliable rendering.

Minimal Reproduction Code:

// Pseudocode reproduction shape:
// 1) Build LlmAgent with MCP tools
// 2) Enable OTLP export to Langfuse
// 3) Trigger prompt that should call tools
// 4) Inspect Langfuse trace: call_llm visible, tools shown as "not called"

How often has this issue occurred?:

  • 100%

Activity

  1. self-assigned this
    on May 29, 2026
  2. hemasekhar-p commented on May 29, 2026

    @hemasekhar-p
    Contributor

    Hi @akbarkanso, Thank you for reporting this issue. currently, Tracing.java is pulling the tool data properly, but as per current design, it is hardcoded to use gcp.vertex.agent.* attributes. which is why it shows up as not called in your UI. We are treating this as a feature request. it is currently under review by our team, and we will keep you posted if any updates. thank you.

  3. hemasekhar-p commented on May 29, 2026

    @hemasekhar-p
    Contributor

    @krwc, Please have a look into it.

  4. akbarkanso commented on Jul 7, 2026

    @akbarkanso
    Author

    Hi again. Sharing additional interesting findings, in case this helps scope the fix.

    We noticed different behavior depending on: spring.ai.openai.chat.options.internal-tool-execution-enabled

    • false: Langfuse shows clear per-step spans (execute_tool + call_llm).
      But the agent appears not to consume the tool response, as if it is not available to it. The tool actually executes and responds correctly (I can see the correct tool response in the Langfuse trace now after internal-tool-execution-enabled is disabled, as I mentioned), but the model does not seem to consume it, so it goes into a loop calling the same tool again, as if retrying the call. Because the model never gets to use the tool response, it eventually fails or hallucinates a final answer.
    • Default/true: tool execution behavior is correct (single call, correct final response), but tool execution spans are not exposed the same way in Langfuse, there is no observability on the tools called, or the interaction that happened behind the scenes.

    So in practice, reliable tool result delivery and detailed per tool span visibility in Langfuse/OpenInference don't currently seem to hold at the same time.

    We also tried a span-attribute bridge mapping approach (gcp.vertex.agent.* → OpenInference-style fields like input.value/output.value) but did not get reliable results in practice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions