Skip to content

Python: fix(ag-ui): clean confirm_changes approval payloads in snapshot#7316

Closed
hsusul wants to merge 1 commit into
microsoft:mainfrom
hsusul:fix-python-agui-confirm-changes-snapshot
Closed

Python: fix(ag-ui): clean confirm_changes approval payloads in snapshot#7316
hsusul wants to merge 1 commit into
microsoft:mainfrom
hsusul:fix-python-agui-confirm-changes-snapshot

Conversation

@hsusul

@hsusul hsusul commented Jul 25, 2026

Copy link
Copy Markdown

Motivation & Context

In AG-UI, when human-in-the-loop tool execution is approved via the confirm_changes flow (e.g., CopilotKit useHumanInTheLoop), the approval response payload ({"accepted": true}) remains in snapshot_messages because _clean_resolved_approvals_from_snapshot looks up tool results in result_by_call_id using snap_msg.toolCallId. For confirm_changes synthetic tool calls, toolCallId is the confirm_id, which does not match the original tool call ID in result_by_call_id.

As a result, the raw approval JSON payload persists in snapshot_messages and the original tool call result is omitted. On subsequent turns, clients that reconcile UI state from MESSAGES_SNAPSHOT (such as CopilotKit) see an un-resulted tool call and revert the completed tool chip back to "Running" / "in progress".

Description & Review Guide

  • What are the major changes?
    • Updated _clean_resolved_approvals_from_snapshot in agent_framework_ag_ui/_agent_run.py so that when toolCallId does not directly match result_by_call_id (e.g. confirm_changes synthetic approval tool calls), it still cleans the {"accepted": ...} approval payload and replaces it with the executed tool result (or confirmation summary).
    • Added unit test suite in tests/ag_ui/test_confirm_changes_snapshot.py verifying that confirm_changes approval and rejection payloads are cleaned up and replaced with actual tool results in snapshot messages.
  • What is the impact of these changes?
    • Tool chips in AG-UI clients (e.g. CopilotKit) remain in the completed state after human approval rather than reverting to "Running" on subsequent turns.
  • What do you want reviewers to focus on?
    • The fallback logic in _clean_resolved_approvals_from_snapshot for matching synthetic approval tool calls when tool_call_id is not present directly in result_by_call_id.

Related Issue

Fixes #6828

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 is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change.

Copilot AI review requested due to automatic review settings July 25, 2026 04:23
@hsusul
hsusul temporarily deployed to github-app-auth July 25, 2026 04:23 — with GitHub Actions Inactive
@hsusul
hsusul temporarily deployed to github-app-auth July 25, 2026 04:23 — with GitHub Actions Inactive
@hsusul
hsusul temporarily deployed to github-app-auth July 25, 2026 04:23 — with GitHub Actions Inactive
@agent-framework-automation agent-framework-automation Bot added the python Usage: [Issues, PRs], Target: Python label Jul 25, 2026
@github-actions github-actions Bot changed the title fix(ag-ui): clean confirm_changes approval payloads in snapshot Python: fix(ag-ui): clean confirm_changes approval payloads in snapshot Jul 25, 2026
@hsusul
hsusul temporarily deployed to github-app-auth July 25, 2026 04:23 — with GitHub Actions Inactive

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 AG-UI’s confirm_changes human-in-the-loop flow so that end-of-turn MESSAGES_SNAPSHOT no longer retains the raw approval payload ({"accepted": ...}) and instead preserves the executed tool result, preventing clients (e.g., CopilotKit) from reverting completed tool chips back to “Running” on subsequent turns.

Changes:

  • Updated _clean_resolved_approvals_from_snapshot to handle confirm_changes synthetic tool call IDs when replacing approval payloads in snapshot tool messages.
  • Added new unit tests to validate snapshot cleaning behavior for confirm_changes approval and rejection cases.

Reviewed changes

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

File Description
python/packages/ag-ui/agent_framework_ag_ui/_agent_run.py Adjusts snapshot post-processing to replace approval JSON payloads with tool results, including a fallback path for confirm_changes.
python/packages/ag-ui/tests/ag_ui/test_confirm_changes_snapshot.py Adds tests ensuring confirm_changes approval/rejection payloads are cleaned and replaced appropriately in snapshot messages.

Comment on lines +1455 to +1465
if replacement is None:
# For confirm_changes synthetic tool calls, tool_call_id is the confirm_id
# while result_by_call_id is keyed by the original tool call id.
if parsed.get("accepted"):
replacement = (
"\n\n".join(result_by_call_id.values())
if result_by_call_id
else "Changes confirmed and applied successfully."
)
else:
replacement = "Changes declined."
Comment on lines +34 to +38
{
"id": confirm_call_id,
"type": "function",
"function": {"name": "confirm_changes", "arguments": "{}"},
},
@eavanvalkenburg

Copy link
Copy Markdown
Member

@hsusul, thank you for the confirm_changes snapshot cleanup work. The consolidated draft PR #7345 incorporates the fix while correlating the synthetic confirmation back to its original function_call_id so unrelated results are never joined. Closing this PR in favor of the consolidated work.

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]: AG-UI confirm_changes approval-gated tool reverts to "in progress" after completing

3 participants