Skip to content

Python: fix(declarative): honor registered function approval requirements - #9606

Open
Yousuf alkhanjari (ghox789) wants to merge 2 commits into
microsoft:mainfrom
ghox789:python-declarative-honor-registered-approval
Open

Yousuf alkhanjari (ghox789) wants to merge 2 commits into
microsoft:mainfrom
ghox789:python-declarative-honor-registered-approval

Conversation

@ghox789

@ghox789 Yousuf alkhanjari (ghox789) commented Oct 22, 2026 •

Copy link
Copy Markdown

Motivation and Context

InvokeFunctionTool in agent-framework-declarative decides whether to request approval only from the action's requireApproval field. A function registered with @tool(approval_mode="always_require") therefore runs with no approval whenever the workflow omits requireApproval or sets it to false. The workflow definition silently overrides the function author's approval requirement.

The .NET implementation fixed the same behavior in #9393 and documented the rule:

Omitting requireApproval or setting it to false does not override the registered function's approval requirement.

This PR brings the Python declarative engine to parity.

Description

  • BaseToolExecutor._registered_tool_requires_approval() resolves the registered tool through the existing _get_tool() lookup (constructor registry, then State registry) and reports whether it has approval_mode == "always_require".
  • handle_action() requests approval when requireApproval is true or the registered tool requires it. The existing yield/resume flow (ToolApprovalRequest → handle_approval_response) is reused unchanged.
  • Tools without approval_mode="always_require" keep following requireApproval exactly as before.

Behavior change: a workflow that invokes an always_require tool without requireApproval: true now pauses for approval instead of running the tool directly. That's the point of the fix, but hosts that relied on the old behavior will see an approval request where there was none.

Tests

New tests in tests/test_function_tool_executor.py (TestApprovalFlow), mirroring the .NET tests from #9393:

  • test_registered_tool_approval_is_honored: requireApproval omitted / false / true × approved / rejected. An approval request is always emitted, the tool never runs before approval, it runs only when approved.
  • test_state_registered_tool_approval_is_honored: same guarantee for tools registered through the State registry.
  • test_unmarked_tool_uses_action_approval: a never_require tool still follows requireApproval.

Without the source change, the 6 bypass cases fail; with it, all 11 new tests pass. The rest of test_function_tool_executor.py passes, and the full declarative suite shows no new failures compared with main (the only failures in my local run came from the optional mcp package and the samples/ folder not being installed, and are identical on main). ruff check and ruff format --check pass on the changed files.

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? Behavior change for workflows that call always_require tools without requireApproval: true (see above).

…ents

InvokeFunctionTool decided whether to request approval only from the
action's requireApproval field. A function registered with
approval_mode="always_require" therefore ran without approval whenever
the workflow omitted requireApproval or set it to false.

Request approval when requireApproval is true or the resolved registered
tool has approval_mode="always_require", so the workflow definition can
no longer override the registered requirement. This matches the .NET fix
in microsoft#9393. Tools without that mode keep following requireApproval.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RuT3Gxp3nBFz1VLqf9FtMF

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.

🟢 Approval recommended

The localized change preserves tool lookup and approval-response behavior, with focused regression coverage and no identified blocking issues; tests were not executed during review.

No open issues 🎉

What changed in this PR

Aligns Python declarative function approval behavior with the .NET fix in #9393: workflows can no longer bypass a registered tool’s always_require approval setting.

Changes:

  • Checks registered approval metadata through the existing tool lookup.
  • Requests approval when either the action or the registered tool requires it, reusing the existing approval flow.
  • Adds regression coverage for approval and rejection, State-registered tools, and tools without mandatory approval.
File Description
python/​packages/​declarative/​tests/​test_function_tool_executor.py Adds tests for registered approval requirements and existing action-controlled behavior.
python/​packages/​declarative/​agent_framework_declarative/​_workflows/​_executors_tools.py Combines action and registered-tool approval requirements.

Review effort: Balanced

@ghox789

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Bring the PR branch up to date with upstream main so CI re-runs against
current base (clears the Public API Compatibility failure fixed upstream in
microsoft#9614 and the merge-gatekeeper BEHIND state). No changes to the fix itself.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BhP294P7bydCU9UZxwrohh

This branch was successfully deployed

1 active deployment
github-app-auth — cc4da2d4 Deployed Oct 23, 2026 by ghox789 via add_label #26057
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.

2 participants