Surface AG-UI MESSAGES_SNAPSHOT events as metadata instead of dropping them - #725
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the AG-UI provider’s event handling so MESSAGES_SNAPSHOT frames are no longer silently dropped, and instead are surfaced to consumers as provider-specific metadata on a streamed agent.ResponseUpdate.
Changes:
- Handle
*aguiEvents.MessagesSnapshotEventintoolCallAccumulator.onEventand emit an assistantResponseUpdatecontainingAdditionalProperties["agui_messages_snapshot"]. - Add a regression test that streams a
NewMessagesSnapshotEventand asserts the snapshot is present in collected message metadata.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| provider/aguiprovider/agui.go | Adds a MessagesSnapshotEvent case that returns a metadata-only ResponseUpdate instead of falling through to the default drop path. |
| provider/aguiprovider/agui_test.go | Adds a test ensuring agui_messages_snapshot metadata is preserved in the collected response when the event is streamed. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This comment has been minimized.
This comment has been minimized.
The AG-UI SSE decoder produces a typed *MessagesSnapshotEvent for MESSAGES_SNAPSHOT frames, but onEvent had no case for it, so these frames fell through to the default branch and were silently dropped. Add a case that emits an assistant ResponseUpdate carrying the message list under AdditionalProperties[agui_messages_snapshot], mirroring the surface-instead-of-drop pattern already used for RunStarted metadata and state snapshot/delta events.
62a8f61 to
cb26f02
Compare
Parity Review: ✅ ApprovedThis PR fixes a silent event-discard bug in the AG-UI provider by handling Scope check: Both changed files are in Cross-repo parity: The upstream Python AG-UI package ( No public API change: The fix is confined to the unexported Verdict: The change preserves cross-repo semantic alignment and does not introduce divergence from .NET or Python behavior. Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
What
onEventinprovider/aguiprovider/agui.goswitched overStateSnapshotEventandStateDeltaEventand then hitdefault: return nil, nil. There was nocase *aguiEvents.MessagesSnapshotEvent. The vendored AG-UI SDK decodesMESSAGES_SNAPSHOTinto a distinct typed*MessagesSnapshotEvent{ *BaseEvent; Messages []Message }and feeds it toonEvent, so every MESSAGES_SNAPSHOT frame reached the default branch and was silently discarded.This adds a
case *aguiEvents.MessagesSnapshotEventthat emits a single assistant*agent.ResponseUpdatewithCreatedAt: eventTime(evt)and the snapshot exposed underAdditionalProperties["agui_messages_snapshot"].Why
MESSAGES_SNAPSHOT is a first-class AG-UI event that lets a server re-sync the full conversation history to the client. Dropping it means consumers lose that history-continuity signal entirely. The metadata-surfacing form is the lowest-risk mapping and matches how RunStarted metadata and the state snapshot/delta events are already surfaced instead of dropped, keeping consistent behavior across the provider's event handling. Surfacing the snapshot as provider-specific metadata (rather than fabricating message content) aligns with the .NET/Python AG-UI clients, which expose the snapshot to callers rather than discarding it.
Testing
Added
TestAGUIAgentRun_SurfacesMessagesSnapshotEventtoagui_test.go(parallel to the existing state-snapshot test): it streams aNewMessagesSnapshotEventwith one message during a run and asserts a collected message carriesAdditionalProperties["agui_messages_snapshot"]holding that message list. The test fails before the change (the frame yields no such update) and passes after.go build ./...,go vet ./provider/aguiprovider/..., andgo test ./provider/aguiprovider/...all pass.