Document that `@ag-ui/client` leaves activity messages out of requests, and how to keep the records `AGUIAdapter` carries in them
AGUIAdapter carries some history records to the frontend as reserved pydantic_ai_* activity messages: tool-availability deltas, compaction items, enqueued messages, and (under preserve_file_data) files. The docs said a frontend that holds the history sends them back and load_messages restores them. @ag-ui/client doesn't: AbstractAgent.prepareRunAgentInput filters role === "activity" out of every RunAgentInput it sends (and 1.0.x filters again after an onRunInitialized mutation). Its own reducer comment says activities "never travel back to the backend". This is true of every release that has activity messages, 0.0.42 through 1.0.3 (latest) and the current 1.0.4 canary.
The real-client round-trip harness in #10560 found it: its tool_reveal, enqueued_messages, compaction and enqueued_system_prompt_client AG-UI scenarios are strict xfails for this gap.
This PR corrects the docs:
- A new "Records carried as activity messages" section in
docs/ui/ag-ui.mdlists the record types and whether each is streamed or dumped. It says what@ag-ui/clientdoes with them, what the next run loses (revealed tools hidden again, compaction undone, enqueued messages and preserved files gone, so the prefix and the cache move), and the two ways to keep them:- keep the history on the server (recommended)
- a client middleware registered with
agent.use()that puts thepydantic_ai_*activities fromagent.messagesback in their original positions
- The Compaction, Enqueued messages and Preserving files sections,
docs/capabilities/compaction.md,docs/capabilities/caching.md, thepreserve_file_datadocstring and a comment in_event_stream.pyno longer claim the records come back.
I checked all of this against the real client:
- A Node probe with
@ag-ui/client@1.0.3shows activity messages, from bothinitialMessagesand the stream, missing from the sent input. - An end-to-end run (Python
dump_messages, then the realHttpAgentrequest body, then Pythonload_messages) loses theToolAvailabilityDeltaPartandCompactionPartwithout the middleware and restores both with it. The middleware's output passes the client'senforceOutgoingInputschema check.
Not in this PR: a server-side carrier that doesn't depend on the client (for example riding the existing encrypted_value namespace, which @ag-ui/client does send back on user/assistant/system messages). That is a design decision for the UI record carrier layer, not a docs fix.
Checklist
- No breaking changes in accordance with the version policy.
- Any permitted compatibility impact has a label, warning, migration, release note, and exact API-check waiver.
- PR title is fit for the release changelog.
š¤ Generated with Claude Code