Description
Microsoft Agent Framework / GPT-5.6 stateless approval-resume failure
Status: final submission report — sanitized HTTP 400 evidence captured on the exact 10.5.2 package set
Suggested title
Intermittent HTTP 400 during GPT-5.6 approval resume through the documented stateless Microsoft Agent Framework Responses path after the approved tool executes
Product area
- Microsoft Agent Framework for .NET
Microsoft.Agents.AI.Foundry
Microsoft.Extensions.AI.OpenAI
- Azure AI Foundry / Azure OpenAI Responses API
- Human-in-the-loop
ApprovalRequiredAIFunction
Summary
We are evaluating GPT-5.6 for two chat tiers in a production Microsoft Agent Framework application. The existing production route remains unchanged and healthy on Azure OpenAI Chat Completions. GPT-5.6 requires a Responses-based route for our combination of explicit reasoning and function tools.
Using the documented MAF composition over the Foundry project Responses client, a protected tool correctly pauses and emits ToolApprovalRequestContent without executing. Resuming the session with the correlated approval is intermittent. On the exact 10.5.2 candidate, iteration 1 passed both model tiers; iteration 2 failed on Terra/low during approval_resume with System.ClientModel.ClientResultException, HTTP 400, and Azure apim-request-id e03444a9-8d3c-41c2-ba9d-b3309d929790. The approved synthetic tool had executed exactly once before the provider rejected the continuation. We stopped immediately without another provider call.
No customer data or side-effecting tool is involved. The reproduction tool only increments an in-memory counter and returns a constant string.
Supported structure under test
The candidate migration uses Microsoft Agent Framework APIs only:
AIProjectClient
GetProjectOpenAIClient().GetProjectResponsesClient()
AsIChatClientWithStoredOutputDisabled(modelId, includeReasoningEncryptedContent: true)
UseFunctionInvocation(...)
AsAIAgent(new ChatClientAgentOptions { ... })
ApprovalRequiredAIFunction
CreateSessionAsync() / RunStreamingAsync(...)
ToolApprovalRequestContent.CreateResponse(...)
- Resume with
RunStreamingAsync(new ChatMessage(ChatRole.User, [approval]), session)
We are not asking Microsoft to validate a raw ResponsesClient, hand-written protocol adapter, mixed API route, or previous_response_id workaround.
Package combinations validated
Live confirmed failing candidate
- Target framework:
net9.0
Microsoft.Agents.AI: 1.6.2
Microsoft.Agents.AI.Foundry: 1.6.2-preview.260521.1
Microsoft.Extensions.AI.OpenAI: 10.5.2
Azure.AI.Projects: 2.1.0-beta.2
OpenAI: 2.10.0
Newer-package offline reconnaissance
Microsoft.Agents.AI: 1.13.0
Microsoft.Agents.AI.Foundry: 1.13.0-preview.260703.1
Microsoft.Extensions.AI.OpenAI: 10.6.0
Azure.AI.Projects: 2.1.0-beta.4
OpenAI: 2.10.0
Both combinations restore and build with zero warnings/errors and pass the same eight offline MAF contracts. The newer combination was not treated as a fix and was not deployed.
Azure deployments exercised
gpt-5.6-terra, reasoning effort low
gpt-5.6-sol, reasoning effort medium
Resource endpoint, subscription, tenant, resource group, Container App configuration, tokens, and customer identifiers are intentionally omitted from this public-safe report. They can be supplied through an authenticated Microsoft support channel if required.
Minimal reproduction behavior
- Construct the stateless project Responses
IChatClient with encrypted reasoning included.
- Wrap a no-side-effect
AIFunction in ApprovalRequiredAIFunction.
- Create a MAF session.
- Prompt the model to call the protected tool exactly once.
- Consume the first stream.
- Assert that exactly one
ToolApprovalRequestContent is present and the tool execution count remains zero.
- Create an approved response correlated to the emitted call.
- Resume the same MAF session with the approval response.
- Assert exactly one tool execution and one correlated
FunctionResultContent.
- Repeat the exact two-tier test in a bounded loop.
Expected behavior
- Every first stream pauses before tool execution.
- Every approved resume executes the tool exactly once.
- The resume stream exposes the correlated function result and completes normally.
- Stateless requests use
store=false, send neither previous_response_id nor conversation, and include reasoning.encrypted_content.
Actual behavior
- Offline request and MAF contracts pass consistently.
- In the latest 10.5.2 bounded live run, iteration 1 passed both Terra/low and Sol/medium.
- Iteration 2 failed on Terra/low at
2026-07-11T12:39:18.3248089+00:00 during approval_resume with System.ClientModel.ClientResultException and HTTP 400.
- Azure correlation header:
apim-request-id: e03444a9-8d3c-41c2-ba9d-b3309d929790.
- The response did not provide an allowlisted
x-ms-error-code header, so the captured error code is null. No response body or exception message was retained.
- The approved synthetic tool execution count was exactly one when the provider rejected the continuation.
- An earlier 10.5.1 spike recorded in the frozen plan reported
invalid_payload with protected-only reasoning. Because that earlier raw artifact was not retained, it remains historical context and a root-cause hypothesis; the new 10.5.2 evidence independently establishes HTTP 400 without claiming a body error code.
- Source inspection found the MEAI OpenAI conversion shape constructs
ReasoningResponseItem(reasoningContent.Text) and assigns EncryptedContent = ProtectedData. That shape remained textually unchanged across the inspected 10.5.1, 10.5.2, 10.6.0, and 10.7.0 source revisions.
The protected-only reasoning conversion is our leading localized hypothesis, not a claim about Azure parser internals. The end-to-end intermittent failure is the blocker regardless of mechanism.
Controls used to validate the report
- Eight exact offline contracts passed on the default package set, Matrix A, and Matrix B.
- Contracts cover stateless wire shape, denial, serialized cross-agent resume, dual approval correlation, replay idempotency, cancellation, skills/tool-loop caps, and streaming terminal order.
- Default and both matrix builds completed with zero warnings/errors.
- Fable independently reviewed the probe across multiple rounds, required corrections to package defaults, test discrimination, failure coverage, and redaction controls, and approved after every accepted finding was corrected and re-proven.
- Claude Code Opus 4.8 independently returned
PASS in read/check mode.
- The repository diff-scoped Semgrep/gitleaks gate returned zero findings and zero vulnerable-package signals. Because the untracked probe sources were outside that diff scan, they also received dedicated line-level source and redaction reviews: Fable approved and Claude Code returned
PASS before live capture and external packaging.
- Product
backend/ and frontend/ trees have zero drift against the frozen production-evidence SHA.
- No product implementation, feature flag, QA deployment, upload, Avatar, SAP, database, or secret mutation occurred.
Questions for Microsoft
- Is this exact stateless MAF approval-resume structure supported for GPT-5.6 deployments when encrypted reasoning is included?
- Is a protected-only reasoning item with empty text/summary and non-empty encrypted content valid input on approval resume?
- Is there a released or planned version of
Microsoft.Extensions.AI.OpenAI, Microsoft.Agents.AI.Foundry, or the Azure Responses service that changes this replay shape or fixes the rejection?
- Is there a different officially documented MAF-only construction for stateless GPT-5.6 Responses with human tool approval, streaming, tools, and skills?
- Can Microsoft provide a documented mitigation that preserves
store=false, disables provider-side response/conversation chaining, preserves encrypted reasoning, and does not bypass approval semantics?
Evidence included in the support package
02-diagnostic-evidence.public.json — sanitized HTTP 400 metadata, request ID, exact package versions, final probe hashes, and pass/failure sequence.
03-offline-matrix-proof.json — final-source Matrix A build and 9/9 offline contract proof.
04-independent-review-summary.json — public-safe Fable and Claude Code review summary.
repro/ — the complete four-file instrumented approval-resume reproduction.
SHA256SUMS.txt — integrity manifest for every other package file.
Captured diagnostic safety boundary
The submission evidence includes the exact UTC timestamp, Azure apim-request-id, exception type, HTTP status, model/tier, phase, package versions, method-only stack frames, execution count, and probe hashes. It contains no bearer token, endpoint, request or response body, exception message, encrypted reasoning, customer/tenant data, file path, or unrelated Container App configuration. The capture projection and all assertion/exception paths were reviewed by Fable and independently passed Claude Code read/check review before the live call.
Current disposition
Migration and QA deployment remain blocked. The existing production model route is unchanged. We will reconsider only after Microsoft supplies a documented MAF-compatible fix or mitigation and it passes the complete parity suite, including uploads and Avatar.
microsoft-maf-gpt56-20260711.zip
Code Sample
var responsesClient = projectClient
.GetProjectOpenAIClient()
.GetProjectResponsesClient();
var statelessClient =
responsesClient.AsIChatClientWithStoredOutputDisabled(
modelId,
includeReasoningEncryptedContent: true);
var tool = new ApprovalRequiredAIFunction(
AIFunctionFactory.Create(
() => "APPROVAL_EXECUTED",
"approval_probe"));
var agent = (ChatClientAgent)statelessClient
.AsBuilder()
.UseFunctionInvocation()
.Build()
.AsAIAgent(new ChatClientAgentOptions
{
ChatOptions = new ChatOptions
{
ModelId = modelId,
Tools = [tool],
},
UseProvidedChatClientAsIs = true,
});
var session = await agent.CreateSessionAsync();
var first = await agent.RunAsync(
"Call approval_probe now.",
session);
var request = first.Messages
.SelectMany(m => m.Contents)
.OfType<ToolApprovalRequestContent>()
.Single();
var approval = request.CreateResponse(
approved: true,
reason: request.ToolCall.CallId);
// Intermittently fails with HTTP 400:
var resumed = await agent.RunAsync(
new ChatMessage(ChatRole.User, [approval]),
session);
Error Messages / Stack Traces
Exception: System.ClientModel.ClientResultException
HTTP status: 400
Phase: approval_resume
Model: gpt-5.6-terra
Reasoning effort: low
UTC: 2026-07-11T12:39:18.3248089Z
Azure apim-request-id: e03444a9-8d3c-41c2-ba9d-b3309d929790
Synthetic tool execution count: 1
Sanitized stack:
OpenAI.ClientPipelineExtensions__ProcessMessageAsync_d__0.MoveNext
OpenAI.Responses.ResponsesClient__CreateResponseAsync_d__48.MoveNext
OpenAI.Responses.ResponsesClient___c__DisplayClass18_0___CreateResponseStreamingAsync_b__0_d.MoveNext
No response body or exception message was retained.
Package Versions
Microsoft.Agents.AI: 1.6.2 Microsoft.Agents.AI.Foundry: 1.6.2-preview.260521.1 Microsoft.Extensions.AI.OpenAI: 10.5.2 Azure.AI.Projects: 2.1.0-beta.2 OpenAI: 2.10.0 Target framework: .NET 9.0
.NET Version
Microsoft.Agents.AI: 1.6.2 Microsoft.Agents.AI.Foundry: 1.6.2-preview.260521.1 Microsoft.Extensions.AI.OpenAI: 10.5.2 Azure.AI.Projects: 2.1.0-beta.2 OpenAI: 2.10.0 Target framework: .NET 9.0
Additional Context
microsoft-maf-gpt56-20260711.zip
Description
Microsoft Agent Framework / GPT-5.6 stateless approval-resume failure
Status: final submission report — sanitized HTTP 400 evidence captured on the exact 10.5.2 package set
Suggested title
Intermittent HTTP 400 during GPT-5.6 approval resume through the documented stateless Microsoft Agent Framework Responses path after the approved tool executes
Product area
Microsoft.Agents.AI.FoundryMicrosoft.Extensions.AI.OpenAIApprovalRequiredAIFunctionSummary
We are evaluating GPT-5.6 for two chat tiers in a production Microsoft Agent Framework application. The existing production route remains unchanged and healthy on Azure OpenAI Chat Completions. GPT-5.6 requires a Responses-based route for our combination of explicit reasoning and function tools.
Using the documented MAF composition over the Foundry project Responses client, a protected tool correctly pauses and emits
ToolApprovalRequestContentwithout executing. Resuming the session with the correlated approval is intermittent. On the exact 10.5.2 candidate, iteration 1 passed both model tiers; iteration 2 failed on Terra/low duringapproval_resumewithSystem.ClientModel.ClientResultException, HTTP 400, and Azureapim-request-ide03444a9-8d3c-41c2-ba9d-b3309d929790. The approved synthetic tool had executed exactly once before the provider rejected the continuation. We stopped immediately without another provider call.No customer data or side-effecting tool is involved. The reproduction tool only increments an in-memory counter and returns a constant string.
Supported structure under test
The candidate migration uses Microsoft Agent Framework APIs only:
AIProjectClientGetProjectOpenAIClient().GetProjectResponsesClient()AsIChatClientWithStoredOutputDisabled(modelId, includeReasoningEncryptedContent: true)UseFunctionInvocation(...)AsAIAgent(new ChatClientAgentOptions { ... })ApprovalRequiredAIFunctionCreateSessionAsync()/RunStreamingAsync(...)ToolApprovalRequestContent.CreateResponse(...)RunStreamingAsync(new ChatMessage(ChatRole.User, [approval]), session)We are not asking Microsoft to validate a raw
ResponsesClient, hand-written protocol adapter, mixed API route, orprevious_response_idworkaround.Package combinations validated
Live confirmed failing candidate
net9.0Microsoft.Agents.AI:1.6.2Microsoft.Agents.AI.Foundry:1.6.2-preview.260521.1Microsoft.Extensions.AI.OpenAI:10.5.2Azure.AI.Projects:2.1.0-beta.2OpenAI:2.10.0Newer-package offline reconnaissance
Microsoft.Agents.AI:1.13.0Microsoft.Agents.AI.Foundry:1.13.0-preview.260703.1Microsoft.Extensions.AI.OpenAI:10.6.0Azure.AI.Projects:2.1.0-beta.4OpenAI:2.10.0Both combinations restore and build with zero warnings/errors and pass the same eight offline MAF contracts. The newer combination was not treated as a fix and was not deployed.
Azure deployments exercised
gpt-5.6-terra, reasoning effortlowgpt-5.6-sol, reasoning effortmediumResource endpoint, subscription, tenant, resource group, Container App configuration, tokens, and customer identifiers are intentionally omitted from this public-safe report. They can be supplied through an authenticated Microsoft support channel if required.
Minimal reproduction behavior
IChatClientwith encrypted reasoning included.AIFunctioninApprovalRequiredAIFunction.ToolApprovalRequestContentis present and the tool execution count remains zero.FunctionResultContent.Expected behavior
store=false, send neitherprevious_response_idnorconversation, and includereasoning.encrypted_content.Actual behavior
2026-07-11T12:39:18.3248089+00:00duringapproval_resumewithSystem.ClientModel.ClientResultExceptionand HTTP 400.apim-request-id: e03444a9-8d3c-41c2-ba9d-b3309d929790.x-ms-error-codeheader, so the captured error code isnull. No response body or exception message was retained.invalid_payloadwith protected-only reasoning. Because that earlier raw artifact was not retained, it remains historical context and a root-cause hypothesis; the new 10.5.2 evidence independently establishes HTTP 400 without claiming a body error code.ReasoningResponseItem(reasoningContent.Text)and assignsEncryptedContent = ProtectedData. That shape remained textually unchanged across the inspected 10.5.1, 10.5.2, 10.6.0, and 10.7.0 source revisions.The protected-only reasoning conversion is our leading localized hypothesis, not a claim about Azure parser internals. The end-to-end intermittent failure is the blocker regardless of mechanism.
Controls used to validate the report
PASSin read/check mode.PASSbefore live capture and external packaging.backend/andfrontend/trees have zero drift against the frozen production-evidence SHA.Questions for Microsoft
Microsoft.Extensions.AI.OpenAI,Microsoft.Agents.AI.Foundry, or the Azure Responses service that changes this replay shape or fixes the rejection?store=false, disables provider-side response/conversation chaining, preserves encrypted reasoning, and does not bypass approval semantics?Evidence included in the support package
02-diagnostic-evidence.public.json— sanitized HTTP 400 metadata, request ID, exact package versions, final probe hashes, and pass/failure sequence.03-offline-matrix-proof.json— final-source Matrix A build and 9/9 offline contract proof.04-independent-review-summary.json— public-safe Fable and Claude Code review summary.repro/— the complete four-file instrumented approval-resume reproduction.SHA256SUMS.txt— integrity manifest for every other package file.Captured diagnostic safety boundary
The submission evidence includes the exact UTC timestamp, Azure
apim-request-id, exception type, HTTP status, model/tier, phase, package versions, method-only stack frames, execution count, and probe hashes. It contains no bearer token, endpoint, request or response body, exception message, encrypted reasoning, customer/tenant data, file path, or unrelated Container App configuration. The capture projection and all assertion/exception paths were reviewed by Fable and independently passed Claude Code read/check review before the live call.Current disposition
Migration and QA deployment remain blocked. The existing production model route is unchanged. We will reconsider only after Microsoft supplies a documented MAF-compatible fix or mitigation and it passes the complete parity suite, including uploads and Avatar.
microsoft-maf-gpt56-20260711.zip
Code Sample
var responsesClient = projectClient .GetProjectOpenAIClient() .GetProjectResponsesClient(); var statelessClient = responsesClient.AsIChatClientWithStoredOutputDisabled( modelId, includeReasoningEncryptedContent: true); var tool = new ApprovalRequiredAIFunction( AIFunctionFactory.Create( () => "APPROVAL_EXECUTED", "approval_probe")); var agent = (ChatClientAgent)statelessClient .AsBuilder() .UseFunctionInvocation() .Build() .AsAIAgent(new ChatClientAgentOptions { ChatOptions = new ChatOptions { ModelId = modelId, Tools = [tool], }, UseProvidedChatClientAsIs = true, }); var session = await agent.CreateSessionAsync(); var first = await agent.RunAsync( "Call approval_probe now.", session); var request = first.Messages .SelectMany(m => m.Contents) .OfType<ToolApprovalRequestContent>() .Single(); var approval = request.CreateResponse( approved: true, reason: request.ToolCall.CallId); // Intermittently fails with HTTP 400: var resumed = await agent.RunAsync( new ChatMessage(ChatRole.User, [approval]), session);Error Messages / Stack Traces
Package Versions
Microsoft.Agents.AI: 1.6.2 Microsoft.Agents.AI.Foundry: 1.6.2-preview.260521.1 Microsoft.Extensions.AI.OpenAI: 10.5.2 Azure.AI.Projects: 2.1.0-beta.2 OpenAI: 2.10.0 Target framework: .NET 9.0
.NET Version
Microsoft.Agents.AI: 1.6.2 Microsoft.Agents.AI.Foundry: 1.6.2-preview.260521.1 Microsoft.Extensions.AI.OpenAI: 10.5.2 Azure.AI.Projects: 2.1.0-beta.2 OpenAI: 2.10.0 Target framework: .NET 9.0
Additional Context
microsoft-maf-gpt56-20260711.zip