Repository navigation
Conversation
Revert the finality wording from #7784 so automatic rejection of unanswered approvals does not prohibit a new call with fresh approval. Keep policy guidance in the optional Reason and document that usage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are reported for the neutral rejection-message and caller-guidance changes.
No open issues 🎉
What changed in this PR
Restores neutral tool-approval rejection wording in the AI function-invocation middleware, allowing callers to communicate finality or recovery guidance through Reason without a contradictory default message. Rejected calls remain unexecuted.
Changes:
- Restores
Tool call invocation rejected., reverting the wording introduced in #7784. - Documents how
Reasoncan clarify whether rejection is final or fresh approval may be requested. - Updates existing approval tests to expect the neutral message.
| File | Description |
|---|---|
| test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientApprovalsTests.cs | Updates rejection-message expectations across approval scenarios. |
| src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs | Restores the neutral default rejection message. |
| src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ToolApprovalResponseContent.cs | Adds documentation explaining caller-provided rejection guidance through Reason. |
Review effort: Balanced
|
@manjunathshiva, heads up: this reverts #7784 because the finality wording breaks MAF’s recovery from unanswered approvals. FICC shouldn’t prescribe retry policy for every rejection; callers can express finality through |
🎉 Good job! The coverage increased 🎉
Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=1662283&view=codecoverage-tab |
Fixes #7914.
Summary
Reverts the rejection-message change from #7784, restoring
Tool call invocation rejected.and the corresponding test expectations. Also clarifies that callers can useToolApprovalResponseContent.Reasonto express whether a rejection is final or a new call may be requested for approval.Why
A rejected approval does not always represent a final approver decision. Microsoft Agent Framework automatically rejects unanswered approval requests to recover from interrupted sessions. The unconditional "rejected by the approver and must not be retried" prefix incorrectly attributes those rejections and prevents the intended recovery through a new tool call with fresh approval. Appending a custom reason cannot reliably override that contradictory prefix.
Keep the default message neutral and leave finality/recovery guidance to the caller through the existing optional
Reason. Rejected calls remain unexecuted; this does not authorize retries without fresh approval.Reasonremains nullable and has no default, since it is used for both approvals and rejections.This restores pre-#7784 behavior: callers that need to discourage repeated approval requests should explicitly state that policy in
Reason.Related: microsoft/agent-framework#9656 and microsoft/agent-framework#8849.
Validation
FunctionInvokingChatClientApprovalsTestspassed on each framework (184 total), covering streaming and non-streaming approval handling, custom/default reasons, and mixed approvals.git diff --checkpassed.Command:
Microsoft Reviewers: Open in CodeFlow