Skip to content

Python: feat(core): add tool concurrency groups and sequential execution order - #8204

Closed
pratik wayase (PratikWayase) wants to merge 21 commits into
microsoft:mainfrom
PratikWayase:feat/serialize-same-message-function-calls
Closed

pratik wayase (PratikWayase) wants to merge 21 commits into
microsoft:mainfrom
PratikWayase:feat/serialize-same-message-function-calls

Conversation

@PratikWayase

@PratikWayase pratik wayase (PratikWayase) commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

PR Description

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, models routinely emit dependent calls in one batch (e.g., "write the file, then read it"). Because the framework lacked a batch-wide execution control, dependent reads could race still-running writes, leading to "not found" errors and contradictory agent states.

This PR closes that gap by providing a declarative, framework-level boolean to control batch-wide execution order, preventing stateful tool race conditions without relying on fragile, tool-side asyncio.Lock workarounds.

Note on PR History: This PR supersedes and closes #7523 and #7881. It incorporates all maintainer feedback from those previous iterations, specifically narrowing the scope to batch-wide execution control (removing concurrency_group per #7914), centralizing the configuration, and resolving all architectural and CI blockers raised by reviewers.

Description & Review Guide

  • What are the major changes?

    1. Batch-Wide Execution Control: Added allow_concurrent_invocation: bool to FunctionInvocationConfiguration (defaulting to True to preserve existing parallel behavior). When set to False, tools in the same batch execute one-by-one.
    2. Sequential Termination Handling: In _try_execute_function_call_groups, when allow_concurrent_invocation is False and a call requests termination, the loop now injects "Skipped: a prior tool call in this batch requested termination." results for all subsequent calls, ensuring provider continuation history remains fully resolved.
    3. Live Configuration Evaluation: Replaced the static config snapshot with a config_provider: Callable[[], FunctionInvocationConfiguration] in _execute_function_calls. This ensures dynamically registered tools (e.g., AG-UI server-managed placeholders) are respected during execution.
    4. Server-Tool Boundary Hardening: Added _is_server_managed_tool() filter to _get_tool_map() and a guard in _execute_single_function_call to guarantee hosted tools are never executed locally.
    5. Approval Replay Ordering: Tracked original_index in a parallel array for hidden already-approved requests. This ensures that resumed calls merge by their original batch position, restoring model order instead of reversing dependent operations.
    6. Pyright Strict Compliance: Fixed type inference issues in approval state serialization by explicitly typing serialized_requests and avoiding polluting the Content dictionaries with framework metadata.
    7. Tests & Formatting: Added test_try_execute_function_call_groups_sequential_config to verify execution order, and applied minor formatting fixes to _loop.py and _agent.py.
  • What is the impact of these changes?
    This is fully backward compatible. The default behavior remains parallel execution (True). It provides tool authors a safe, declarative way to handle stateful dependencies, fixes a critical server-tool execution bug, and ensures strict type safety.

  • What do you want reviewers to focus on?
    Please review the execution logic in _try_execute_function_call_groups (_tools.py). Specifically, verify that:

    • The config_provider in FunctionInvocationLayer.get_response cleanly evaluates live state without leaking options to the underlying chat client.
    • The _is_server_managed_tool filter cleanly prevents the get_time_zone local execution bug.
    • When allow_concurrent_invocation is False, the loop correctly breaks, stops dequeuing calls, and injects terminal "Skipped" results for the suffix.
    • The original_index tracking in _store_already_approved_approval_requests and _pop_already_approved_approval_responses correctly restores model order during sequential approval resumes.

Related Issue

Fixes #7386
Supersedes and closes #7523
Supersedes and closes #7881
Design for deferred per-tool controls: #7914

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.

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.

🟡 Changes recommended

Hosted-call isolation, context isolation, and approval replay ordering remain incorrect.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds configurable sequential tool execution while preserving concurrent execution by default.

Changes:

  • Adds batch-wide invocation ordering and termination handling.
  • Hardens hosted-tool and approval replay handling.
  • Adds sequential execution coverage and formatting updates.
File summaries
File Description
python/packages/core/agent_framework/_tools.py Implements execution policy, hosted-tool filtering, and approval replay ordering.
python/packages/core/tests/core/test_tools.py Tests sequential invocation order.
python/packages/core/agent_framework/_workflows/_agent.py Formatting-only update.
python/packages/core/agent_framework/_harness/_loop.py Formatting-only updates.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 4
  • Review effort level: Balanced

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread python/packages/core/agent_framework/_tools.py Outdated
Comment thread python/packages/core/agent_framework/_tools.py Outdated
Comment thread python/packages/core/agent_framework/_tools.py
Comment thread python/packages/core/agent_framework/_tools.py
Comment thread python/packages/core/agent_framework/_tools.py

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A few concerns to address before this is ready.

Comment thread python/packages/core/agent_framework/_tools.py
Comment thread python/packages/core/agent_framework/_tools.py
Comment thread python/packages/core/agent_framework/_tools.py Outdated
Comment thread python/packages/core/agent_framework/_tools.py Outdated
@eavanvalkenburg

Copy link
Copy Markdown
Member

Thanks for the update. Before this is ready, could you please:

Once those are addressed, please re-request review. Thanks!

@PratikWayase

Copy link
Copy Markdown
Contributor Author

Thanks for the follow-up, Eduard van Valkenburg (@eavanvalkenburg)
Both comments (2065 and 3407) have been fully addressed, and I've added regression tests for each. I also merged main to resolve the conflicts. Re-requesting your review!

@eavanvalkenburg

Copy link
Copy Markdown
Member

Thanks for the update. The earlier review discussions and merge conflicts are now resolved. The remaining blocker is that the PR body is missing the breaking-change checklist declaration from the current repository template. Could you please restore and complete that item? The approval-gated workflows can then be run and the PR reviewed.

@PratikWayase

Copy link
Copy Markdown
Contributor Author

Thanks for the update. The earlier review discussions and merge conflicts are now resolved. The remaining blocker is that the PR body is missing the breaking-change checklist declaration from the current repository template. Could you please restore and complete that item? The approval-gated workflows can then be run and the PR reviewed.

Thanks, Eduard!
The PR description checklist has been updated to match the template exactly.
All review discussions and merge conflicts are also resolved.
Re-requesting your review now.

Comment thread python/packages/core/agent_framework/_tools.py Outdated
@eavanvalkenburg

Copy link
Copy Markdown
Member

Thanks for the update. I verified that this head already contains the current main, so there is no branch update to apply. Public API Compatibility is still blocked before evaluating this PR because actions/checkout refuses a fork checkout in the repository’s pull_request_target workflow. No PR code change is indicated by that failure; a maintainer needs to correct or rerun the workflow before review can continue. Thanks!

@moonbox3

Copy link
Copy Markdown
Contributor

pratik wayase (@PratikWayase) please fix the file conflicts.

@eavanvalkenburg

Copy link
Copy Markdown
Member

Thank you, pratik wayase (@PratikWayase), for investigating this issue and for the work across #7523, #7881, and this PR. Your iterations established the batch-wide allow_concurrent_invocation direction and surfaced important ordering and context-isolation requirements. We've opened #8453 with a narrower implementation of that design, while leaving selective per-tool concurrency controls to #7914. Closing this PR in favor of #8453.

This branch was successfully deployed

1 active deployment
github-app-auth — e46467dd Deployed Sep 17, 2026 by PratikWayase via add_label #23098
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: [Feature]: No way to serialize (or order) same-message function calls — stateful tools with write→read dependencies race

4 participants