Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(ag-ui): keep empty confirm_changes resumes unseeded
Generic/predictive resumes with messages:[] must not prepend stored history into the turn input — confirm_changes synthesizes only the resume tool message and short-circuits without another model call. Seeding that history caused approval mismatch warnings and an extra stream invocation (test_agent_endpoint_confirm_changes_clears_persisted_interrupt).

Only non-empty client-replayed generic resumes go through reconcile_resume_messages + seeded_resume_from_snapshot. Approval and workflow/checkpoint paths still seed empty via reconcile.
  • Loading branch information
ktz03 committed Sep 9, 2026
commit e6820218139be57f3fefff0e3a533e1456e6d28b
9 changes: 6 additions & 3 deletions python/packages/ag-ui/agent_framework_ag_ui/_agent_run.py
Comment thread
ktz03 marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2493,9 +2493,12 @@ async def run_agent_stream(
)
raw_messages = provider_suffix
elif not config.use_service_session:
if resume_payload is not None:
# Predictive-state / generic resumes also merge history here; mark seeded
# so save-time resume_seeded_messages does not prepend again (#8140).
if resume_payload is not None and raw_messages:
Comment thread
ktz03 marked this conversation as resolved.
Resolved
# Client-replayed transcript on predictive/generic resume: overlap-merge
# and mark seeded so save-time resume_seeded_messages does not prepend
# again (#8140). Empty interrupt-only resumes (e.g. confirm_changes)
# must stay empty so synthesized resume tool messages are the only
# turn input; history is restored at save when this flag stays false.
seeded_resume_from_snapshot = True
raw_messages = snapshot_session.reconcile_resume_messages(raw_messages)
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,14 @@ def resume_seeded_messages(self, incoming: list[dict[str, Any]]) -> list[dict[st
def reconcile_resume_messages(self, incoming: list[dict[str, Any]]) -> list[dict[str, Any]]:
"""Merge stored history with resume messages without double-persisting.

Empty incoming (interrupt-only / checkpoint resume) prepends stored
history. Non-empty incoming is overlapped via the thread-snapshot
reconstructor so a client that replays its transcript is not duplicated.
Empty incoming prepends stored history (approval / checkpoint builders that
need history in the provider or snapshot input). Non-empty incoming is
overlapped via the thread-snapshot reconstructor so a client that replays
its transcript is not duplicated.

Agent confirm_changes resumes that synthesize the tool result separately
should keep empty incoming as empty and call this only for non-empty
client-replayed transcripts.
"""
if self._stored is None:
return incoming
Expand Down
Loading