Skip to content

Python: [Bug]: AG-UI: approving a restored card after a reconnect can fail with "Approval alias conflicts with an existing pending occurrence" #8758

Description

Description

Summary

With two approval-gated calls to the same tool in one assistant message, approving the first, reloading the page while the second card is pending, and then approving the restored card can kill the run:

ValueError: Approval alias conflicts with an existing pending occurrence.

The user sees the generic run-failure line and the approval card is re-offered; the turn is lost.

Stack (entirely upstream — no application frame raises)

agent_framework_ag_ui/_agent_run.py:_run_agent_stream
  → _agent_run.py:1002  _pop_collected_tool_approval_response_messages
    → _agent_run.py:928   _register_server_generated_approval_response
      → _approval_lifecycle.py:295  ApprovalLifecycle.register
        → _approval_lifecycle.py:366  _register_aliases
            raise ValueError("Approval alias conflicts with an existing pending occurrence.")

The application's frames are above _run_agent_stream only (our AG-UI wrapper and run buffer); everything from the collection of approval-response messages down is framework code.

Reproduction

Environment: agent-framework-core 1.19.0 / agent-framework-ag-ui 1.4.0 at 72325696, AG-UI host + the reference CopilotKit client, provider ollama, model glm-5.3-flash:cloud.

  1. Register one approval-gated tool. Ours is an MCP tool (microsoft_docs_search) with approval required.
  2. Prompt so the model emits two parallel calls to that same tool in one message ("look up BOTH X AND Y in the same step").
  3. Two tool chips appear "Running"; one approval card is offered.
  4. Approve it. The first call completes; the second card appears.
  5. Reload the page while the second card is pending. The transcript and the pending card are restored correctly — this part works.
  6. Approve the restored card.

Expected: the second call executes and the run completes, as it does without step 5.

Actual (1 of 3 attempts): the run ends with RUN_ERROR, the server logs the ValueError above, and the card is re-offered.

Code Sample

Error Messages / Stack Traces

Package Versions

agent-framework-core: 1.19.0, agent-framework-ag-ui: 1.4.0

Python Version

No response

Additional Context

What the same flow does without the reload

Identical prompt and approvals with no reload between them completed correctly on every attempt, both calls executing and the model producing its answer. So the batched-approval path itself is healthy — this is specific to re-registering a server-generated approval response on the resume path.

Note on what changed

_register_server_generated_approval_response and the ApprovalLifecycle alias registry are part of the 1.19.0 approval rework (PRs #8433, #8449, #8428). The same application code on agent-framework-core 1.18.0 did not produce this error in equivalent use. That is circumstantial rather than bisected, and the report should present it that way.

Suggested direction

On the resume path an alias that is already registered for a pending occurrence of the same call is more likely a replay of that occurrence than a genuine conflict. Treating a re-registration of an identical (call_id, alias) pair as idempotent — returning the existing occurrence instead of raising — would make the reconnect case safe without weakening the conflict check for genuinely distinct occurrences.

Activity

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

Metadata

Metadata

Labels

ag-uiUsage: [Issues, PRs], Target: AG-UI protocol integrationpythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions