Skip to content

Python: Deduplicate fan-out selection results so each target runs once - #8739

Merged
Eduard van Valkenburg (eavanvalkenburg) merged 1 commit into
microsoft:mainfrom
RachelWanggg:fix/multi-selection-duplicate-targets
Sep 28, 2026
Merged

Eduard van Valkenburg (eavanvalkenburg) merged 1 commit into
microsoft:mainfrom
RachelWanggg:fix/multi-selection-duplicate-targets

Conversation

@RachelWanggg

Copy link
Copy Markdown
Contributor

Motivation & Context

A selection function that names a target more than once gets that target run once per entry. FanOutEdgeRunner.send_message validates that every selected ID is a target, then appends one deliverable edge per entry and gathers them, so ["billing_team", "billing_team"] runs billing_team twice on the same message. Routing by tags hits this whenever two tags map to the same executor. With an AgentExecutor target that is a second model call and a duplicated response.

Description & Review Guide

  • What are the major changes? FanOutEdgeRunner.send_message drops repeated IDs from the selection result after validation, keeping the order in which the selection function first names them. It uses list(dict.fromkeys(...)) rather than set(...) so delivery order stays deterministic.
  • What is the impact of these changes? Each selected target receives the message once. Selection results without repeats deliver exactly as before. Targeted messages already went to one edge, since that path only checks membership. No public API change.
  • What do you want reviewers to focus on? Whether repeated IDs should be deduplicated, as here, or rejected the way unknown IDs are. Rejecting them would turn workflows that run today into errors, so this PR deduplicates.

Verification

  • Two tests in test_edge.py, both failing on main: a target selected twice runs once (real executors, counting handler calls), and deduplicated targets are delivered in the order they are first named.
  • Mutation checks: removing the deduplication, or applying it only to targeted messages, fails both tests. Rebuilding the list in target_ids order fails the order test. set() fails the order test whenever the hash seed changes the order.
  • uv run poe test -P core: 7689 passed, 20 skipped, 2 xfailed.
  • uv run poe syntax -P core, uv run poe pyright -P core and uv run poe test-typing -P core (pyrefly, ty, zuban, pyright, mypy) pass.

Related Issue

Fixes #8738

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix). A workflow keeps the label and title prefix in sync automatically.

FanOutEdgeRunner validated that every ID returned by a selection function
is a target, then delivered once per entry, so a target named twice ran
twice on the same message. Drop repeats after validation, keeping the
order in which the selection function first names each target.

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@agent-framework-automation agent-framework-automation Bot added the python Usage: [Issues, PRs], Target: Python label Sep 24, 2026
Merged via the queue into microsoft:main with commit a384143 Sep 28, 2026
50 checks passed

This branch was previously deployed

1 inactive deployment
github-app-auth — 5fd94357 Deployed Sep 24, 2026 by RachelWanggg via team_check #5249
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: Multi-selection edge group runs a target twice when the selection function names it twice

3 participants