Describe the bug
In openinference-instrumentation-google-adk (observed in v0.1.15), the _RunnerRunAsync and _BaseAgentRunAsync wrappers intercept events and set the span's OUTPUT_VALUE when event.is_final_response() is True.
However, the Google ADK can yield multiple events where is_final_response() is True during a single invocation (for instance, the actual model response containing content, followed by a state synchronization event like actions.state_delta which has no content).
Because the wrapper unconditionally overwrites OUTPUT_VALUE on every final response event, the last event (which lacks content) wins. This effectively erases the LLM/Agent's actual text response from the trace output in downstream visualization tools like Langfuse or Arize Phoenix.
To Reproduce
Steps to reproduce the behavior:
- Run a Google ADK agent that emits state updates or navigation deltas after generating its text response.
- Observe the invocation span in Phoenix/Langfuse.
- See error: The output field is empty or only contains the state delta JSON, missing the core
content object.
Expected behavior
The instrumentation should preserve the actual generated content. It should only overwrite the OUTPUT_VALUE if the new final event actually contains content, or alternatively, retain the last final response that possessed a non-empty content payload.
Screenshots
N/A
Desktop:
- OS: Linux
- Version:
openinference-instrumentation-google-adk==0.1.15
Additional context
Proposed Fix
In openinference/instrumentation/google_adk/_wrappers.py, track whether an event with content has already been captured during the stream evaluation.
Inside _RunnerRunAsync and _BaseAgentRunAsync:
has_set_content = False
async for event in self.__wrapped__:
if event.is_final_response():
event_has_content = getattr(event, "content", None) is not None
if event_has_content or not has_set_content:
if event_has_content:
has_set_content = True
try:
span.set_attribute(
SpanAttributes.OUTPUT_VALUE,
event.model_dump_json(exclude_none=True),
)
# ... rest of the span tracking logic
Describe the bug
In
openinference-instrumentation-google-adk(observed inv0.1.15), the_RunnerRunAsyncand_BaseAgentRunAsyncwrappers intercept events and set the span'sOUTPUT_VALUEwhenevent.is_final_response()isTrue.However, the Google ADK can yield multiple events where
is_final_response()isTrueduring a single invocation (for instance, the actual model response containing content, followed by a state synchronization event likeactions.state_deltawhich has no content).Because the wrapper unconditionally overwrites
OUTPUT_VALUEon every final response event, the last event (which lacks content) wins. This effectively erases the LLM/Agent's actual text response from the trace output in downstream visualization tools like Langfuse or Arize Phoenix.To Reproduce
Steps to reproduce the behavior:
contentobject.Expected behavior
The instrumentation should preserve the actual generated content. It should only overwrite the
OUTPUT_VALUEif the new final event actually contains content, or alternatively, retain the last final response that possessed a non-empty content payload.Screenshots
N/A
Desktop:
openinference-instrumentation-google-adk==0.1.15Additional context
Proposed Fix
In
openinference/instrumentation/google_adk/_wrappers.py, track whether an event with content has already been captured during the stream evaluation.Inside
_RunnerRunAsyncand_BaseAgentRunAsync: