Skip to content

.NET: fix: avoid final rejection wording for unanswered approvals - #9678

Closed
ssccinng wants to merge 2 commits into
microsoft:mainfrom
ssccinng:openfix/4c5a7a6c-5901-46ab-9605-88e474fea50f
Closed

ssccinng wants to merge 2 commits into
microsoft:mainfrom
ssccinng:openfix/4c5a7a6c-5901-46ab-9605-88e474fea50f

Conversation

@ssccinng

@ssccinng ssccinng commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Motivation & Context

Unanswered tool approvals should explain that approval was missing without presenting the decision as a final human rejection. Empty or whitespace conversation IDs must also preserve matching assistant tool calls so providers do not receive orphan tool results.

Description & Review Guide

  • What are the major changes? Generate missing-approval results directly while preserving explicit human rejection, approval binding, and history ordering. Match the existing history policy with string.IsNullOrWhiteSpace. Cover null, empty, whitespace, and non-empty conversation IDs through streaming and non-streaming approval tests. Correct cancellation forwarding, an unnecessary import, and the static test field's required s_ prefix.
  • What is the impact of these changes? Client-managed history receives matching call/result pairs; non-empty conversation IDs retain result-only downstream behavior. Callers still receive complete pairs, and persisted history avoids duplicates. Existing coverage for mixed decisions, late approvals, restored sessions, and cancellation/retry is retained.
  • What do you want reviewers to focus on? Call IDs, message roles, ordering, counts, history deduplication, and preservation of approval behavior. Validation scope includes approval tests, warning-free builds, formatting, packaging, and applicable API compatibility checks with the current SDK and dependencies.

Validation: The regression fails on the original commit and passes after the update (8 original failures; 20/20 focused tests now pass). The affected project unit suite passed 3471/3471 tests. Builds with warnings as errors, formatting, package creation passed.

Related Issue

Fixes #9656

AI Assistance

  • No material AI assistance was used.
  • This is an AI-assisted contribution. I reviewed, understood, and verified all submitted content and accept responsibility for it.

AI assistance details: Implementation, regression tests, analyzer corrections, and this description received AI assistance.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR links to an agreed issue with no competing open PR, or the Related Issue section documents a trivial-change or repository-automation exception.
  • This is not a breaking change.

@agent-framework-automation agent-framework-automation Bot added the .NET Usage: [Issues, PRs], Target: .Net label Oct 25, 2026
@github-actions github-actions Bot changed the title fix: avoid final rejection wording for unanswered approvals .NET: fix: avoid final rejection wording for unanswered approvals Oct 25, 2026
@ssccinng
ssccinng marked this pull request as ready for review October 25, 2026 07:40
@baywet
Vincent Biret (baywet) requested a balanced review from Copilot October 26, 2026 11:00

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.

🟡 Changes recommended

Blank conversation IDs can omit the matching tool-call message and leave an orphan tool result in the model request.

1 open issue
What changed in this PR

This PR addresses #9656 by generating unanswered-approval results directly, avoiding dependency-provided wording that presents missing approval as a final human rejection.

Changes:

  • Return generated approval decisions and call/result messages while preserving explicit human rejection behavior.
  • Insert generated messages alongside approval decisions to maintain history ordering.
  • Expand coverage for streaming, restored sessions, mixed decisions, history deduplication, and cancellation/retry behavior.
File Description
dotnet/​tests/​Microsoft.Agents.AI.UnitTests/​ChatClient/​OpenFixApprovalResultTests.cs Adds default-stack checks for result wording, persistence, and fresh approvals.
dotnet/​tests/​Microsoft.Agents.AI.UnitTests/​ChatClient/​ChatClientAgent_ApprovalRetryTests.cs Covers canceled automatic rejections and retry after session restoration.
dotnet/​tests/​Microsoft.Agents.AI.UnitTests/​ChatClient/​ApprovalResponseBindingChatClientTests.cs Verifies generated call/result messages and interrupted streaming.
dotnet/​src/​Microsoft.Agents.AI/​ChatClient/​ToolApprovalHelpers.cs Supports inserting generated messages with approval decisions.
dotnet/​src/​Microsoft.Agents.AI/​ChatClient/​ApprovalResponseBindingChatClient.cs Generates missing-approval results directly and returns them to callers.

Review effort: Balanced

@westey-m westey (westey-m) self-assigned this Oct 30, 2026

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

No active review issues were identified in the changes distinguishing missing tool approvals from explicit rejections.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@westey-m

Copy link
Copy Markdown
Collaborator

Thanks for the contribution ssccinng, however we reverted the change that caused this issue lower down the stack, so this workaround will not be required anymore. Closing this PR. Feel free to reopen if I missed anything.

This branch was previously deployed

1 inactive deployment
github-app-auth — 60c810de Deployed Nov 1, 2026 by ssccinng via add_label #26801
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

.NET Usage: [Issues, PRs], Target: .Net

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET: automatic rejection of unanswered approvals tells the model the call "must not be retried"

3 participants