feat(tools): add serialize_multiagent_result#62
Conversation
MultiAgentResult.to_dict() drops node_history and execution_order so consumers could not identify the last executing node. New func `serialize_multiagent_result` captures this metadata from the live object and adds last_node_id and response to the output directly.
There was a problem hiding this comment.
Pull request overview
Adds a new public helper to reliably serialize MultiAgentResult objects with execution-order metadata so downstream consumers can identify the true final node response (especially when nodes execute multiple times), instead of relying on results dict insertion order.
Changes:
- Introduces
serialize_multiagent_result()(exported viastrands_compose.toolsandstrands_compose) to embedlast_node_id,response, and Swarm/Graph execution metadata alongsideto_dict()output. - Renames/simplifies message text extraction helper to
extract_text()and updates wrappers/tests to use it. - Minor CLI output tweak to avoid redundant
str()conversion forAppConfig.entry.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
uv.lock |
Bumps editable package version metadata to 0.8.0. |
tests/unit/config/resolvers/orchestrations/test_tools.py |
Updates extractor tests and adds coverage for serialize_multiagent_result (Swarm/Graph/base behaviors). |
src/strands_compose/tools/wrappers.py |
Switches wrapper fallback text extraction to extract_text(). |
src/strands_compose/tools/extractors.py |
Adds serialize_multiagent_result() and replaces extract_text_from_message() with extract_text(). |
src/strands_compose/tools/__init__.py |
Exports serialize_multiagent_result from the tools package. |
src/strands_compose/cli.py |
Removes redundant str() cast for app_config.entry display. |
src/strands_compose/__init__.py |
Exports serialize_multiagent_result at the top-level package API. |
| if content: | ||
| return {"status": "success", "content": content} | ||
|
|
||
| return {"status": "success", "content": [{"text": extract_text_from_message(message) or ""}]} | ||
| return {"status": "success", "content": [{"text": extract_text(message) or ""}]} |
There was a problem hiding this comment.
Done — removed the redundant or "" fallback in 8aacf1a.
| from strands_compose.tools.extractors import ( | ||
| extract_last_message, | ||
| extract_text_from_message, | ||
| extract_text, | ||
| resolve_last_node_id, | ||
| ) | ||
|
|
There was a problem hiding this comment.
Done — serialize_multiagent_result is now imported in the top-level block alongside node_as_async_tool and node_as_tool, and the dead _FakeGraphEdgeTuple dataclass has been removed (8aacf1a).
| @dataclass | ||
| class _FakeGraphEdgeTuple: | ||
| """Edge represented as a plain tuple (from_node, to_node).""" | ||
|
|
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
galuszkm
left a comment
There was a problem hiding this comment.
Implement according to my responses
| if content: | ||
| return {"status": "success", "content": content} | ||
|
|
||
| return {"status": "success", "content": [{"text": extract_text_from_message(message) or ""}]} | ||
| return {"status": "success", "content": [{"text": extract_text(message) or ""}]} |
| from strands_compose.tools.extractors import ( | ||
| extract_last_message, | ||
| extract_text_from_message, | ||
| extract_text, | ||
| resolve_last_node_id, | ||
| ) | ||
|
|
| if content: | ||
| return {"status": "success", "content": content} | ||
|
|
||
| return {"status": "success", "content": [{"text": extract_text_from_message(message) or ""}]} | ||
| return {"status": "success", "content": [{"text": extract_text(message) or ""}]} |
|
@copilot implement the changes i requested |
Description
MultiAgentResult.to_dict()dropsnode_history(SwarmResult) andexecution_order/edges(GraphResult) — fields that only exist on the live in-memory object. Without them, consumers identifying the final response fell back to dict insertion order ofresults, which reflects first-seen order not execution order. In a swarm where an agent runs multiple times, this returns the wrong node's answer.Adds
serialize_multiagent_resulttostrands_compose.toolsthat captures the missing metadata before the object is discarded and embedslast_node_idandresponse(plain text from the correct final node) directly in the output.extract_last_messageandextract_textare kept package-internal — used bywrappers.pyand the new serializer but not part of the public API.Related Issues
N/A
Type of Change
YAML / API Impact
Adds new public name to
strands_compose:serialize_multiagent_result.No schema changes. Fully backwards-compatible.
Testing
How have you tested the change?
uv run just check(lint + type check)uv run just testfor overall testingexamples/still workChecklist