Skip to content

feat(tools): add serialize_multiagent_result#62

Merged
galuszkm merged 4 commits into
mainfrom
feat/mg/serialize-multiagent-result
Jun 22, 2026
Merged

feat(tools): add serialize_multiagent_result#62
galuszkm merged 4 commits into
mainfrom
feat/mg/serialize-multiagent-result

Conversation

@galuszkm

Copy link
Copy Markdown
Member

Description

MultiAgentResult.to_dict() drops node_history (SwarmResult) and execution_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 of results, 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_result to strands_compose.tools that captures the missing metadata before the object is discarded and embeds last_node_id and response (plain text from the correct final node) directly in the output.

extract_last_message and extract_text are kept package-internal — used by wrappers.py and the new serializer but not part of the public API.

Related Issues

N/A

Type of Change

  • New feature

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?

  • I ran uv run just check (lint + type check)
  • I ran uv run just test for overall testing
  • I added or updated tests that prove my fix is effective or my feature works
  • I verified existing examples in examples/ still work

Checklist

  • I have read the CONTRIBUTING document
  • I have updated the documentation accordingly
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

galuszkm added 2 commits June 22, 2026 22:40
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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 via strands_compose.tools and strands_compose) to embed last_node_id, response, and Swarm/Graph execution metadata alongside to_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 for AppConfig.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.

Comment thread src/strands_compose/tools/wrappers.py Outdated
Comment on lines +75 to +78
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 ""}]}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok good idea

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — removed the redundant or "" fallback in 8aacf1a.

Comment on lines 21 to 26
from strands_compose.tools.extractors import (
extract_last_message,
extract_text_from_message,
extract_text,
resolve_last_node_id,
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok import it at top

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Comment thread tests/unit/config/resolvers/orchestrations/test_tools.py Outdated
Comment on lines +643 to +646
@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 galuszkm left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implement according to my responses

Comment thread src/strands_compose/tools/wrappers.py Outdated
Comment on lines +75 to +78
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 ""}]}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok good idea

Comment on lines 21 to 26
from strands_compose.tools.extractors import (
extract_last_message,
extract_text_from_message,
extract_text,
resolve_last_node_id,
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok import it at top

Comment thread src/strands_compose/tools/wrappers.py Outdated
Comment on lines +75 to +78
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 ""}]}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea

@galuszkm

Copy link
Copy Markdown
Member Author

@copilot implement the changes i requested

@galuszkm galuszkm merged commit 9a6882b into main Jun 22, 2026
8 checks passed
@galuszkm galuszkm deleted the feat/mg/serialize-multiagent-result branch June 22, 2026 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants