diff --git a/src/google/adk/agents/langgraph_agent.py b/src/google/adk/agents/langgraph_agent.py index f1dd1ed8775..875cdf48d8a 100644 --- a/src/google/adk/agents/langgraph_agent.py +++ b/src/google/adk/agents/langgraph_agent.py @@ -140,7 +140,12 @@ async def _run_async_impl( # Use the Runnable final_state = await self.graph.ainvoke({'messages': messages}, config) - result = final_state['messages'][-1].content + message = final_state['messages'][-1] + # Content can be a list of blocks (e.g. reasoning and text); `.text` keeps + # only the text. String content is passed through unchanged. + result = ( + message.content if isinstance(message.content, str) else message.text + ) result_event = Event( invocation_id=ctx.invocation_id, diff --git a/tests/unittests/agents/test_langgraph_agent.py b/tests/unittests/agents/test_langgraph_agent.py index e7b73a7b253..514919f0cae 100644 --- a/tests/unittests/agents/test_langgraph_agent.py +++ b/tests/unittests/agents/test_langgraph_agent.py @@ -261,6 +261,40 @@ def respond(state: MessagesState) -> dict[str, list[AIMessage]]: assert observed_messages[0].content == "test system prompt" +@pytest.mark.asyncio +async def test_langgraph_agent_reads_text_from_content_blocks(): + """A reply whose content is a list of blocks yields its text.""" + + def respond(state: MessagesState) -> dict[str, list[AIMessage]]: + del state + return { + "messages": [ + AIMessage( + content=[ + {"type": "reasoning", "reasoning": "thinking"}, + {"type": "text", "text": "Sunny today."}, + ] + ) + ] + } + + graph_builder = StateGraph(MessagesState) + graph_builder.add_node("respond", respond) + graph_builder.set_entry_point("respond") + graph_builder.set_finish_point("respond") + agent = LangGraphAgent(name="weather_agent", graph=graph_builder.compile()) + + events = [ + event + async for event in agent.run_async( + _make_parent_context("test_app", "test_user", "session-id") + ) + ] + + assert len(events) == 1 + assert events[0].content.parts[0].text == "Sunny today." + + def test_get_thread_id_is_stable_across_processes(): """A literal digest also rejects a swap to a per-process-salted hash.""" assert (