Skip to content

Python: Add tool approval middleware#6414

Merged
TaoChenOSU merged 8 commits into
microsoft:mainfrom
eavanvalkenburg:tool_approval_update
Jun 11, 2026
Merged

Python: Add tool approval middleware#6414
TaoChenOSU merged 8 commits into
microsoft:mainfrom
eavanvalkenburg:tool_approval_update

Conversation

@eavanvalkenburg

@eavanvalkenburg eavanvalkenburg commented Jun 9, 2026

Copy link
Copy Markdown
Member

Motivation and Context

Python currently surfaces approval prompts for every tool call in a mixed tool-call batch when any one tool requires approval. This can block safe read-only tools behind unnecessary approval prompts and makes host approval UX noisy.

Fixes #6385

Description

  • Adds a session-backed mixed-batch bypass in the Python function-invocation loop so known non-approval-required tool calls are hidden, stored, and reinjected as approved responses when the visible approval flow resumes.
  • Adds experimental ToolApprovalMiddleware with standing approval rules, tool+arguments rules, heuristic auto_approval_rules, queued approval prompts, and streaming/non-streaming support.
  • Adds public helper APIs for "always approve this tool" and "always approve this exact tool+arguments" responses.
  • Adds focused core tests and a regular-client sample showing host/user policy decisions for approval, rejection, standing approvals, and heuristic auto-approval.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

Copilot AI review requested due to automatic review settings June 9, 2026 14:05
@moonbox3 moonbox3 added documentation Improvements or additions to documentation python labels Jun 9, 2026
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _tools.py11389092%222–223, 400, 402, 415, 440–442, 450, 468, 482, 489, 496, 519, 521, 528, 536, 665, 699–701, 704–706, 708, 714, 765–767, 792, 818, 822, 860–862, 866, 888, 1031–1032, 1036, 1072, 1084, 1091–1094, 1115, 1119, 1123, 1137–1139, 1489, 1581, 1609, 1631, 1639, 1730, 1737–1738, 1797, 1801, 1847, 1908–1909, 1956, 1970, 1973, 1986, 1989, 2014, 2021, 2031, 2035, 2114, 2167, 2187, 2189, 2245, 2324, 2521, 2587–2588, 2740, 2745, 2747–2748, 2817, 2822, 2829
packages/core/agent_framework/_harness
   _tool_approval.py3584487%69, 72, 77, 115, 132, 135, 138, 196–197, 216, 245, 253, 264, 282–287, 299, 313, 316, 336, 374, 397, 399–400, 432, 442, 457, 459–460, 462–463, 488–489, 510–512, 550–551, 601, 605, 610
TOTAL39086447488% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
7762 34 💤 0 ❌ 0 🔥 2m 7s ⏱️

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

This PR improves Python tool-approval UX and correctness by fixing mixed tool-call batches (so only tools that truly require approval surface prompts) and by introducing an experimental, session-backed ToolApprovalMiddleware to coordinate queued approvals, standing approval rules, and heuristic auto-approval.

Changes:

  • Adjusts the core function-invocation loop to hide and session-store approval requests for known non-approval-required tools when a mixed batch contains at least one approval-required tool, then reinjects them as approved responses when the approval flow continues.
  • Adds experimental ToolApprovalMiddleware + state/rule models and helper APIs for “always approve this tool” / “always approve this tool with these arguments”.
  • Adds focused core tests plus a new sample demonstrating host/user policy decisions with the middleware.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
python/samples/02-agents/tools/tool_approval_middleware.py Adds an end-to-end sample showing queued approvals, standing rules, and heuristic auto-approval.
python/samples/02-agents/tools/README.md Documents the new sample.
python/packages/core/tests/core/test_harness_tool_approval.py Adds tests for mixed-batch hiding/replay, queued approvals (streaming + non-streaming), auto-approval callbacks, and standing rules.
python/packages/core/AGENTS.md Documents the new tool-approval harness concepts and APIs.
python/packages/core/agent_framework/_tools.py Implements mixed-batch bypass storage/replay via session-backed state.
python/packages/core/agent_framework/_harness/_tool_approval.py Introduces experimental ToolApprovalMiddleware, state/rule models, and “always approve” response helpers.
python/packages/core/agent_framework/init.py Exposes the new middleware/types/helpers at the package top-level.

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

@github-actions github-actions Bot 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.

Automated Code Review

Reviewers: 4 | Confidence: 90%

✓ Security Reliability

The tool approval middleware implementation is well-designed from a security and reliability perspective. The mixed-batch bypass correctly classifies tools: only tools explicitly NOT in the approval_tools set (i.e., not always_require) and known to the tool_map are auto-approved. Unknown tools, declaration-only tools, and additional tools all require visible approval. Standing rules are added only via explicit user/host action. Session state merging correctly preserves the core's hidden auto-approvable requests across middleware saves. No injection risks, no unsafe deserialization, no secrets in code. The one notable concern is the unbounded while True loop in the middleware when all approval requests are auto-approved, though this is mitigated by the inner MAX_ITERATIONS cap and the experimental nature of the feature.

✓ Test Coverage

The test coverage for the new ToolApprovalMiddleware is solid for the core flows (queuing, mixed batches, streaming, auto-approval callbacks, and tool-level standing rules). However, the public helper create_always_approve_tool_with_arguments_response has zero test coverage. This leaves the argument-scoped standing rule path—including _arguments_match, argument serialization, and the critical behavior that different arguments for the same tool should NOT be auto-approved—entirely unexercised.

✓ Failure Modes

The tool approval middleware and mixed-batch bypass are well-constructed with sound state management. The _save_state merge logic correctly preserves the core loop's auto_approvable_approval_requests across middleware serialization cycles. The streaming and non-streaming paths both handle queuing, auto-approval, and rejection correctly. Object identity tracking in _remove_approval_requests is safe because the Content references are drawn directly from the message lists. No silent failures, lost errors, or stale-state paths were found.

✗ Design Approach

The session-backed mixed-batch bypass mostly fits the stated goal, but it has one design hole: hidden never-require tool calls are replayed on the next session turn unconditionally, so abandoning the approval prompt and sending an unrelated follow-up can still execute stale hidden tool calls. That contradicts the new documented contract that replay happens only when the visible approval flow resumes.

Flagged Issues

  • python/packages/core/agent_framework/_tools.py:250 replays hidden auto-approved requests on any later turn in the session, not specifically when the visible approval flow resumes, so stale hidden tool calls can execute during an unrelated follow-up message.

Automated review by eavanvalkenburg's agents

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/_harness/_tool_approval.py Outdated
Comment thread python/packages/core/agent_framework/_tools.py Outdated
Comment thread python/packages/core/agent_framework/_harness/_tool_approval.py
Comment thread python/packages/core/agent_framework/_harness/_tool_approval.py
@moonbox3 moonbox3 added the .NET label Jun 10, 2026
@github-actions github-actions Bot changed the title Python: Add tool approval middleware .NET: Python: Add tool approval middleware Jun 10, 2026
@eavanvalkenburg eavanvalkenburg changed the title .NET: Python: Add tool approval middleware Python: Add tool approval middleware Jun 10, 2026
eavanvalkenburg and others added 8 commits June 10, 2026 14:32
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@TaoChenOSU TaoChenOSU added this pull request to the merge queue Jun 11, 2026
Merged via the queue into microsoft:main with commit df29af6 Jun 11, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: Mixed Tool Batch Applies Approval Wrapper To All Tool Calls

5 participants