From 44ac26939daec6a11a06fb0c07485c6a88d04532 Mon Sep 17 00:00:00 2001 From: asekka Date: Tue, 27 Jan 2026 12:49:47 +0100 Subject: [PATCH] feat: add __str__ support for MultiAgentResult Allow direct string conversion of MultiAgentResult, matching the existing behavior of AgentResult. This enables users to simply call str(result) to get the combined text output from all agent results. Closes #1561 --- src/strands/multiagent/base.py | 17 ++++++ tests/strands/multiagent/test_base.py | 76 +++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/src/strands/multiagent/base.py b/src/strands/multiagent/base.py index dc3258f68..9c99be54a 100644 --- a/src/strands/multiagent/base.py +++ b/src/strands/multiagent/base.py @@ -161,6 +161,23 @@ def from_dict(cls, data: dict[str, Any]) -> "MultiAgentResult": ) return multiagent_result + def __str__(self) -> str: + """Get the combined output from all agent results as a string. + + This method extracts and concatenates text content from all node results, + providing a convenient way to access the multi-agent output via str(). + + Returns: + The combined text output from all agent results. + """ + parts = [] + for node_result in self.results.values(): + for agent_result in node_result.get_agent_results(): + text = str(agent_result) + if text: + parts.append(text) + return "\n".join(parts) + def to_dict(self) -> dict[str, Any]: """Convert MultiAgentResult to JSON-serializable dict.""" return { diff --git a/tests/strands/multiagent/test_base.py b/tests/strands/multiagent/test_base.py index 4e8a5dd06..1a9592c7f 100644 --- a/tests/strands/multiagent/test_base.py +++ b/tests/strands/multiagent/test_base.py @@ -239,3 +239,79 @@ def test_serialize_node_result_for_persist(agent_result): assert "result" in serialized_exception assert serialized_exception["result"]["type"] == "exception" assert serialized_exception["result"]["message"] == "Test error" + + +def test_multi_agent_result_str_single_node(): + """Test MultiAgentResult __str__ with a single node result.""" + agent_result = AgentResult( + message={"role": "assistant", "content": [{"text": "Hello from agent"}]}, + stop_reason="end_turn", + state={}, + metrics={}, + ) + node_result = NodeResult(result=agent_result, status=Status.COMPLETED) + multi_result = MultiAgentResult(status=Status.COMPLETED, results={"node1": node_result}) + + assert str(multi_result) == "Hello from agent\n" + + +def test_multi_agent_result_str_multiple_nodes(): + """Test MultiAgentResult __str__ with multiple node results.""" + agent_result1 = AgentResult( + message={"role": "assistant", "content": [{"text": "Response 1"}]}, + stop_reason="end_turn", + state={}, + metrics={}, + ) + agent_result2 = AgentResult( + message={"role": "assistant", "content": [{"text": "Response 2"}]}, + stop_reason="end_turn", + state={}, + metrics={}, + ) + node1 = NodeResult(result=agent_result1, status=Status.COMPLETED) + node2 = NodeResult(result=agent_result2, status=Status.COMPLETED) + multi_result = MultiAgentResult(status=Status.COMPLETED, results={"node1": node1, "node2": node2}) + + result_str = str(multi_result) + assert "Response 1" in result_str + assert "Response 2" in result_str + + +def test_multi_agent_result_str_empty(): + """Test MultiAgentResult __str__ with no results.""" + multi_result = MultiAgentResult(status=Status.COMPLETED, results={}) + assert str(multi_result) == "" + + +def test_multi_agent_result_str_with_exception_node(): + """Test MultiAgentResult __str__ skips exception nodes.""" + agent_result = AgentResult( + message={"role": "assistant", "content": [{"text": "Good response"}]}, + stop_reason="end_turn", + state={}, + metrics={}, + ) + node_ok = NodeResult(result=agent_result, status=Status.COMPLETED) + node_fail = NodeResult(result=Exception("Something failed"), status=Status.FAILED) + multi_result = MultiAgentResult(status=Status.COMPLETED, results={"ok": node_ok, "fail": node_fail}) + + result_str = str(multi_result) + assert "Good response" in result_str + assert "Something failed" not in result_str + + +def test_multi_agent_result_str_nested(): + """Test MultiAgentResult __str__ with nested MultiAgentResult.""" + inner_agent = AgentResult( + message={"role": "assistant", "content": [{"text": "Nested response"}]}, + stop_reason="end_turn", + state={}, + metrics={}, + ) + inner_node = NodeResult(result=inner_agent, status=Status.COMPLETED) + inner_multi = MultiAgentResult(status=Status.COMPLETED, results={"inner": inner_node}) + outer_node = NodeResult(result=inner_multi, status=Status.COMPLETED) + outer_multi = MultiAgentResult(status=Status.COMPLETED, results={"outer": outer_node}) + + assert "Nested response" in str(outer_multi)