Drop local approval controls from the Responses API input - #12
Merged
Conversation
A local tool's approval is resolved in-process, so the provider never issued a matching MCP approval item. Serializing one produced an orphaned mcp_approval_request (server_label: null) or an mcp_approval_response referencing an id the API never saw. The function-calling loop already strips these before the provider sees them, so the hole was the raw OpenAIChatClient path (and FoundryChatClient, which wraps it). Both cases in toResponsesInput now gate on isHostedApproval, the same server_label test the loop layer uses. Mirrors the upstream Python fix (microsoft/agent-framework#7462). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a wire-format edge case in the OpenAI Responses API adapter where local (in-process) tool approvals could be serialized as MCP approval items, producing orphaned mcp_approval_request / mcp_approval_response entries that the provider never issued or recognized. The change aligns toResponsesInput with the framework’s existing hosted-vs-local approval boundary (isHostedApproval) and updates tests to reflect the real hosted approval shape.
Changes:
- Gate
function_approval_requestandfunction_approval_responseserialization intoResponsesInputonisHostedApproval, preventing local approvals from being emitted as MCP wire items. - Add regression tests ensuring local approvals serialize to zero input items in both stateless and service-storage modes, while hosted approvals still round-trip on the wire.
- Update the hosted approval round-trip test to include
server_labelon the approval response’sfunctionCall, matching the behavior ofapprovalResponse().
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/openai/src/to-openai.ts | Filters approval request/response items so only hosted approvals are serialized into Responses API input. |
| packages/openai/src/to-openai.wire-fallbacks.test.ts | Adds coverage for local vs hosted approval serialization boundaries across stateless and service-storage modes. |
| packages/openai/src/hosted-tools.test.ts | Fixes the hosted approval round-trip test fixture to include server_label on the response call. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Merged
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.
A local tool's approval is resolved in-process, so the provider never issued a matching MCP approval item. Serializing one produced an orphaned
mcp_approval_request(server_label: null) or anmcp_approval_responsereferencing an id the API never saw. The function-calling loop already strips these before the provider sees them, so the hole was the rawOpenAIChatClientpath — andFoundryChatClient, which wraps it.Both cases in
toResponsesInputnow gate onisHostedApproval, the sameserver_labeltest the loop layer uses. Mirrors the upstream Python fix (microsoft/agent-framework#7462), which also documented the hosted/local boundary in the function-calling-loop spec.The existing hosted round-trip test built its approval response without
server_labelon the wrapped call;approvalResponse()copies the request's call verbatim, so a real hosted decision always carries it. The test now uses that shape — the same update the upstream fix applied to its own existing test.Test plan
mcp_approval_request/mcp_approval_response.pnpm checkpasses.🤖 Generated with Claude Code