Skip to content

Python: keep the approval response under service-side storage so a paused run resumes#7133

Open
he-yufeng wants to merge 1 commit into
microsoft:mainfrom
he-yufeng:fix/approval-response-service-side-storage
Open

Python: keep the approval response under service-side storage so a paused run resumes#7133
he-yufeng wants to merge 1 commit into
microsoft:mainfrom
he-yufeng:fix/approval-response-service-side-storage

Conversation

@he-yufeng

Copy link
Copy Markdown
Contributor

Summary

Fixes #7125.

When an approval-gated run pauses for tool approval and the follow-up request continues a stored response (service-side storage: previous_response_id / conversation_id), the user's function_approval_response was silently stripped from the outgoing request, so the approval decision never reached the model. The model then re-issued the same approval request and the run paused again — approval-gated tools could never execute under service-side storage.

Root cause

_prepare_message_for_openai handled function_approval_response and function_approval_request in one case and skipped both under service-side storage. That is correct for the request (a server-issued item the server already has via the prior response, so replaying it inline duplicates it — #3295), but wrong for the response: the response is the user's decision, references the prior request by approval_request_id, and is not itself a server-stored item, so it must reach the model.

Fix

Split the two into separate cases: the approval request keeps the storage skip (same treatment as function_call), the approval response is always sent (same treatment as function_result directly above it).

Test

test_prepare_message_for_openai_keeps_approval_response_under_service_side_storage asserts the response survives with request_uses_service_side_storage=True (before the fix the prepared result is empty). The existing test_prepare_message_for_openai_with_function_approval_response already pins the storage-off serialization.

I verified the change by reading: the existing storage-off test confirms the mcp_approval_response serialization, and the fix mirrors the function_result branch directly above. A local pytest run was blocked by a workspace-install issue in my environment (agent_framework core not resolving under uv run), so the added test is exercised by CI rather than a local run.

…used run resumes

_prepare_message_for_openai handled function_approval_response and
function_approval_request in one case and skipped both under service-side
storage. That is right for the request (a server-issued item the server already
has, so replaying it inline duplicates it -- microsoft#3295) but wrong for the response:
the response is the user's approval decision, references the prior request by
approval_request_id, and is not itself a server-stored item, so stripping it
means the decision never reaches the model and an approval-paused run never
resumes (approval-gated tools can never execute under service-side storage).

Split the two into separate cases: the approval request keeps the storage skip
(like function_call), the approval response is always sent (like
function_result).

Fixes microsoft#7125
Copilot AI review requested due to automatic review settings July 15, 2026 19:08
@giles17 giles17 added the python Usage: [Issues, PRs], Target: Python label Jul 15, 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.

Pull request overview

This PR fixes a Python OpenAI client serialization bug that prevented approval-gated runs from resuming when continuing via service-side storage (previous_response_id / conversation_id). It ensures the user’s function_approval_response is still sent to the model under continuation requests, while continuing to skip replaying the server-issued function_approval_request to avoid duplicate-item errors.

Changes:

  • Split _prepare_message_for_openai handling so function_approval_request is skipped under service-side storage but function_approval_response is always serialized.
  • Added a regression test asserting the approval response is preserved when request_uses_service_side_storage=True.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
python/packages/openai/agent_framework_openai/_chat_client.py Separates approval request vs response handling to prevent dropping the user’s approval decision under service-side storage.
python/packages/openai/tests/openai/test_openai_chat_client.py Adds a regression test to ensure approval responses survive continuation requests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: function_approval_response is dropped from the request under service-side storage, so an approval-paused run never resumes

3 participants