Repository navigation
.NET: collect partial native approval decisions durably behind an opt-in - #9791
Closed
Ran Shemtov (ranst91) wants to merge 2 commits into
Closed
Ran Shemtov (ranst91) wants to merge 2 commits into
Ran Shemtov (ranst91) wants to merge 2 commits into
Conversation
Ran Shemtov (ranst91)
deployed
to
github-app-auth
October 28, 2026 11:11 — with
GitHub Actions
Active
Ran Shemtov (ranst91)
deployed
to
github-app-auth
October 28, 2026 11:11 — with
GitHub Actions
Active
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Collection-only runs can lose ordinary input or throw due to a missing ConversationId, while resumed model input can contain orphan tool results that providers reject.
3 open issues
What changed in this PR
Adds opt-in durable collection of partial tool-approval decisions to .NET ChatClientAgent, while preserving the default policy of rejecting unanswered requests on the next run.
Changes:
- Adds and wires
EnablePartialApprovalResponses, including cloning, configuration validation, and public API declarations. - Stores decisions and completed sibling results in session state, returning unanswered requests until the batch is ready.
- Adds serialization/reload regression coverage and documents persistence requirements and limitations.
| File | Description |
|---|---|
dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgent_PartialApprovalsTests.cs |
Tests partial decisions, reloads, replay, and option validation. |
dotnet/src/Microsoft.Agents.AI/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt |
Declares the option for .NET Standard 2.0. |
dotnet/src/Microsoft.Agents.AI/PublicAPI/net9.0/PublicAPI.Unshipped.txt |
Declares the option for .NET 9. |
dotnet/src/Microsoft.Agents.AI/PublicAPI/net8.0/PublicAPI.Unshipped.txt |
Declares the option for .NET 8. |
dotnet/src/Microsoft.Agents.AI/PublicAPI/net472/PublicAPI.Unshipped.txt |
Declares the option for .NET Framework 4.7.2. |
dotnet/src/Microsoft.Agents.AI/PublicAPI/net10.0/PublicAPI.Unshipped.txt |
Declares the option for .NET 10. |
dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientExtensions.cs |
Configures partial collection and rejects incompatible options. |
dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgentOptions.cs |
Defines, documents, and clones the opt-in setting. |
dotnet/src/Microsoft.Agents.AI/ChatClient/ApprovalResponseBindingChatClient.cs |
Collects durable decisions and prepares completed batches for resumption. |
docs/features/partial-tool-approvals.md |
Documents usage, durability constraints, and regression coverage. |
Review effort: Balanced
| var collected = this.CollectPartialResponses(messages, session); | ||
| if (collected.Waiting is not null) | ||
| { | ||
| return new ChatResponse([new ChatMessage(ChatRole.Assistant, collected.Waiting)]); |
| var copy = message.Clone(); | ||
| copy.Contents = message.Contents.Where(content => content switch | ||
| { | ||
| ToolApprovalRequestContent request => !settled.Contains(request.ToolCall.CallId), |
Comment on lines
+291
to
+293
| if (waiting.Count > 0) | ||
| { | ||
| return (input, waiting); |
Ran Shemtov (ranst91)
deployed
to
github-app-auth
October 28, 2026 12:27 — with
GitHub Actions
Active
Ran Shemtov (ranst91)
deployed
to
github-app-auth
October 28, 2026 12:29 — with
GitHub Actions
Active
Ran Shemtov (ranst91)
deleted the
fix/pni722-durable-partial-approvals
branch
October 29, 2026 16:49
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem and behavior
A native approval batch currently rejects every request omitted from the next run. That intentional default prevents applications from accepting decisions one at a time across session reloads.
Add
ChatClientAgentOptions.EnablePartialApprovalResponses(defaultfalse). With this option, the native approval-binding layer saves original-bound decisions and completed sibling results in session state and returns unanswered requests without executing tools or calling the model. Once the batch has answers, the existing binding/invocation path resumes it. The first recorded answer wins; duplicate or conflicting answers cannot replace it. This keeps the current default policy unchanged.Collection-only ordinary input is queued in native session state when the downstream service/history path has not received it. Synthetic waiting responses preserve the existing conversation identity.
The change includes serialized-state regression coverage and usage documentation, including the distinction between decided and executed, session serialization/concurrency requirements, and unchanged crash/side-effect transaction limitations. It does not change the AG-UI host or claim browser/Intelligence parity.
Validation
303 native approval tests pass, including 32 combinations of streaming/non-streaming, both history-persistence modes, partial approve/decline, late approve/decline, frontend/native batches, fresh-agent reloads, duplicate/conflicting answers, tampered caller call identities/arguments, canonical persisted results, and no re-execution of completed calls. Existing default-policy approval tests remain green. Four additional service-history cases verify that waiting responses retain ConversationId and that ordinary text accompanying a decision survives fresh-agent save/reload, reaches the resumed model once, and is not sent again after successful completion.
Local validation used SDK 10.0.201/runtime 10.0.5 and cache-only dependency overrides because this checkout requires unavailable SDK 10.0.401 and newer analyzer/test packages. MEAI stayed at 10.10.0 with Abstractions 10.10.1. Cached analyzers passed with incompatible existing-baseline PublicAPI diagnostics and an unrelated existing whitespace diagnostic suppressed. This is not a claim that the unmodified upstream toolchain passed; CI should run the repository-declared SDK/packages.
Portable deterministic reproduction:
dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgent_PartialApprovalsTests.cs. Run the native unit-test project with--filter-class '*Approval*'. Source behavior and usage are documented indocs/features/partial-tool-approvals.md.Review follow-up
Commit
aeadfd833addresses missing ConversationId and lost ordinary input on collection-only runs. The mixed frontend/native provider-history finding is tracked separately and is not resolved by this follow-up. The PR remains a draft pending that composition and real-host/provider validation.