Skip to content

Python: Integrate tool approval into the harness - #6522

Merged
westey (westey-m) merged 5 commits into
microsoft:mainfrom
westey-m:python-harness-add-tool-approval
Jun 16, 2026
Merged

Python: Integrate tool approval into the harness#6522
westey (westey-m) merged 5 commits into
microsoft:mainfrom
westey-m:python-harness-add-tool-approval

Conversation

@westey-m

Copy link
Copy Markdown
Contributor

Motivation and Context

The Python harness (create_harness_agent) did not include tool approval out of the box, unlike the .NET harness. Agents could invoke approval-required tools without any standing "don't ask again" mechanism, and the console sample's approval prompt only offered approve-once / deny.

This change brings the Python harness to parity by integrating the existing ToolApprovalMiddleware as a default, batteries-included feature, and surfaces the framework's standing-approval helpers in the console sample. It also fixes a small defensive bug in the sample's tool-call formatter that surfaced while exercising the approval flow.

Description

  • Harness integration (_harness/_agent.py): create_harness_agent now wires ToolApprovalMiddleware by default, placed outermost so it intercepts inbound "always approve" responses and outbound approval requests at the caller boundary and its re-invocation loop re-runs user-supplied middleware. Two new keyword arguments:
    • disable_tool_approval (default False) to opt out.
    • auto_approval_rules to pass heuristic callbacks that can auto-approve a function_call, evaluated after standing rules but before prompting the user.
    • Note: the middleware requires an AgentSession at run time.
  • Console sample (console/observers/tool_approval.py): the approval prompt now offers "Always approve this tool (any arguments)" and "Always approve this tool with these arguments", backed by create_always_approve_tool_response and create_always_approve_tool_with_arguments_response.
  • Bug fix (console/formatters.py): FallbackToolFormatter.format_detail now guards that json.loads-parsed arguments are a dict before iterating, matching the existing get_argument_value helper. Previously, function-call arguments that parsed to a non-dict raised AttributeError: 'str' object has no attribute 'items' during streaming.
  • Tests / docs: added unit tests in tests/core/test_harness_agent.py and documented the feature in the harness sample README.

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 15, 2026 13:48
@moonbox3 Evan Mattson (moonbox3) added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python labels Jun 15, 2026
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework/_harness
   _agent.py104496%159, 463–464, 466
TOTAL39958450888% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
7982 34 💤 0 ❌ 0 🔥 2m 4s ⏱️

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 brings the Python harness agent (create_harness_agent) closer to .NET parity by enabling tool-approval handling by default, and updates the harness console sample to let users create standing “don’t ask again” approvals. It also hardens the console tool-call formatter against non-dict JSON argument payloads and adds unit coverage for the new harness wiring behavior.

Changes:

  • Wire ToolApprovalMiddleware by default in create_harness_agent, with disable_tool_approval opt-out and auto_approval_rules forwarding.
  • Extend the harness console approval prompt to support “always approve” (tool-wide and tool+arguments) responses.
  • Add tests validating middleware installation/ordering and update harness README to list the feature.

Reviewed changes

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

Show a summary per file
File Description
python/samples/02-agents/harness/README.md Documents tool approval as a default harness feature.
python/samples/02-agents/harness/console/observers/tool_approval.py Adds “always approve” options using standing-approval helper responses.
python/samples/02-agents/harness/console/formatters.py Prevents AttributeError by requiring JSON-decoded arguments to be a dict.
python/packages/core/tests/core/test_harness_agent.py Adds unit tests ensuring tool approval middleware is added/omitted and ordered correctly.
python/packages/core/agent_framework/_harness/_agent.py Installs tool approval middleware by default and exposes new configuration kwargs.

Comment thread python/packages/core/agent_framework/_harness/_agent.py Outdated
Comment thread python/packages/core/agent_framework/_harness/_agent.py Outdated

@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: 5 | Confidence: 88% | Result: All clear

Reviewed: Correctness, Security Reliability, Test Coverage, Failure Modes, Design Approach


Automated review by westey-m's agents

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Addresses PR review feedback that the parameter name was unclear. The flag
toggles the auto/standing tool-approval middleware.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@westey-m
westey (westey-m) added this pull request to the merge queue Jun 15, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 15, 2026
@westey-m
westey (westey-m) added this pull request to the merge queue Jun 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 16, 2026
@westey-m
westey (westey-m) added this pull request to the merge queue Jun 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 16, 2026
@westey-m
westey (westey-m) added this pull request to the merge queue Jun 16, 2026
@westey-m
westey (westey-m) removed this pull request from the merge queue due to a manual request Jun 16, 2026
@westey-m
westey (westey-m) added this pull request to the merge queue Jun 16, 2026
Merged via the queue into microsoft:main with commit 0db9305 Jun 16, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants