Python: Add tool concurrency groups and sequential execution order for same-message calls - #7523
Open
PratikWayase wants to merge 2 commits into
Open
Conversation
PratikWayase
temporarily deployed
to
github-app-auth
August 5, 2026 10:27 — with
GitHub Actions
Inactive
PratikWayase
temporarily deployed
to
github-app-auth
August 5, 2026 10:27 — with
GitHub Actions
Inactive
PratikWayase
temporarily deployed
to
github-app-auth
August 5, 2026 10:27 — with
GitHub Actions
Inactive
PratikWayase
temporarily deployed
to
github-app-auth
August 5, 2026 10:27 — with
GitHub Actions
Inactive
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds framework-level controls to prevent same-message tool-call race conditions in the Python core by allowing (a) per-tool serialization via concurrency groups and (b) run-level sequential execution of all tool calls in a batch.
Changes:
- Added
concurrency_group: str | NonetoFunctionTooland the@tooldecorator, enabling sequential execution for tools sharing a group within a single message batch. - Added
tool_execution_order: Literal["parallel","sequential"]to chat options and function invocation configuration, and wired it through to the function-call execution layer. - Added unit tests covering concurrency-group serialization and sequential execution behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| python/packages/core/agent_framework/_tools.py | Adds concurrency-group metadata, serializes it, and implements grouped/sequential function-call execution and option wiring. |
| python/packages/core/agent_framework/_types.py | Extends chat options with tool_execution_order to expose the configuration at the API surface. |
| python/packages/core/tests/core/test_tools.py | Adds tests validating concurrency-group handling and sequential tool execution order. |
PratikWayase
temporarily deployed
to
github-app-auth
August 5, 2026 10:56 — with
GitHub Actions
Inactive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation & Context
Currently, the framework executes all tool calls requested in a single assistant message concurrently. While this is a great default for independent calls (like parallel document lookups), models routinely emit dependent calls in one batch (e.g., "write the file, then read it"). Because the tool author has no way to serialize these calls, dependent reads race the still-running writes, leading to "not found" errors and contradictory agent states.
This PR closes that gap by providing declarative, framework-level control over tool execution order, preventing stateful tool race conditions without relying on fragile, tool-side
asyncio.Lockworkarounds.Fixes #7386
Description & Review Guide
What are the major changes?
concurrency_group: strparameter toFunctionTooland the@tooldecorator. Tools sharing the sameconcurrency_groupexecute sequentially in call order within a message batch, while ungrouped tools remain fully concurrent.tool_execution_order: Literal["parallel", "sequential"]to_ChatOptionsBaseandFunctionInvocationConfiguration. Setting this to"sequential"forces all tool calls in a batch to execute one-by-one.tool_execution_orderchat option through theFunctionInvocationLayerdown to the execution engine so the setting actually takes effect at runtime.FunctionTool.to_dict()to ensureconcurrency_groupsurvives serialization, and added docstrings documenting the ordering guarantee (specifically requested in the issue).What is the impact of these changes?
This is fully backward compatible. The default behavior remains
"parallel"with noconcurrency_groupset, ensuring existing agents behave exactly as before. It provides tool authors a safe, declarative way to handle stateful dependencies.What do you want reviewers to focus on?
Please review the grouping algorithm in
_try_execute_function_call_groups(_tools.py). Specifically, verify that theordered_resultsarray correctly maps indices to ensure results are returned in the exact order the model requested them, and thatcontextvars.copy_context()is still applied correctly per-call to preserve agent span observability.Related Issue
Fixes #7386
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.