Python: feat(core): add tool concurrency groups and sequential execution order - #7881
Conversation
|
/review |
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: Findings reported
Scope: full PR (5 commit(s)): e3efb1e57d81, b8b1f034fbdc, 7783ec2d9c37, fb4cb4f75eb1, e55413014eb4
Model: gpt-5.6-sol
Overview
The PR adds per-tool concurrency groups and a run-level sequential mode while preserving result order, per-call context propagation, and cancellation of in-flight group tasks. The new grouping loop has gaps around fail-closed middleware, middleware-requested termination, and approval replay ordering, and its configuration/key handling can silently violate the requested execution policy. These issues can start side-effecting calls after a policy stop, reverse dependent operations, or unexpectedly serialize or parallelize a batch.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
5 verified findings remained after source verification (1 high, 4 medium) across 1 file. Details are attached to the affected lines below.
Affected areas: python/packages/core/agent_framework/_tools.py
|
pratik wayase (@PratikWayase) Thanks for working on this. I think we should narrow the scope of this PR to the batch-wide execution control and make two changes to that API:
I am not yet convinced that we have resolved enough of the design for per-tool I opened #7914 to design the selective tool-level controls separately and tagged Roger Barreto (@rogerbarreto) there for input on whether we should address this in .NET and Python together. I suggest removing |
|
Hi Eduard van Valkenburg (@eavanvalkenburg), thanks for the guidance! I've updated the PR based on your feedback Renamed |
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. 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.Lockworkarounds.Fixes #7386
Description & Review Guide
What are the major changes?
tool_execution_orderstring option withallow_concurrent_invocation: boolto mirror the .NETFunctionInvokingChatClient.AllowConcurrentInvocationAPI.allow_concurrent_invocationstrictly withinFunctionInvocationConfiguration(defaulting toTrueto preserve existing Python parallel behavior), rather than routing it through provider chat options._try_execute_function_call_groupsin_tools.py. When set toFalse, tools run one-by-one. If a call requests termination or fails, the loop immediately stops dequeuing subsequent calls and safely cancels any in-flight parallel siblings.allow_concurrent_invocationis safely popped frommutable_optionsandcustom_argsbefore being forwarded, preventing it from leaking as a tool runtime argument or provider request option.What do you want reviewers to focus on?
Please review the execution logic in
_try_execute_function_call_groups(_tools.py). Specifically, verify that:allow_concurrent_invocationisFalse, the loop correctly breaks and stops dequeuing calls immediately ifshould_terminateisTrue.except BaseExceptionblock correctly cancels in-flight sibling tasks and discards their results to preserve fail-closed middleware behavior.FunctionInvocationLayer.get_responsecleanly removes the key frommutable_optionswithout leaking it to the underlying chat client.Related Issue
Fixes #7386
Design for deferred per-tool controls: #7914
Contribution Checklist
allow_concurrent_invocation = True.