“Both resolved” can still mean media was lost.
A successful promise is not an equivalence test. Keep the loss visible when a compatibility branch replaces media with text.
Reviewed October 15, 2026 · Pinned npm clients 0.0.59 and 1.0.2 · Original local fixtures
The original captured result
The fixture has one tool call, an empty argument object and a result containing a text part plus an image URL at example.invalid. The URL is data only: the tool never fetches it. No tool is executed, and the text “Demo receipt” is not evidence of an actual receipt or email.
| Pinned client | Original observation |
|---|---|
| 0.0.59 | Rejected: content array does not meet this client’s expected tool-result string shape. |
| 1.0.2 | Resolved: the materialized tool message retains text and image parts. |
Review the branch, not just the green result
The selectable fallback applies to the legacy request only. Text parts are joined, and non-text parts become explicit omission labels. The modern request receives the original content array. Source URLs, data sources and provider file handles are never dereferenced.
Demo receipt
[image omitted for pre-1.0 client: image/png]The run records include the exact branch wire input and a loss list. A warning-free legacy result after this change still lacks the image. Do not describe it as full feature compatibility.
Keep the producer’s declaration intact
This fixture declares the producer’s protocol as 1.0. The fallback does not rewrite that declaration to match the client. Our comparison supports the two tested request cases: no declaration and exact 1.0. It does not implement a general future-version negotiation policy.
The official migration documents describe the broader tool-content type change. Your application also needs to narrow content before passing it to a string-only renderer. CopilotKit migration guide.
Replay the exact bytes that matter
After reviewing and running the patch, export the package and compare legacy-reviewed.sse with modern-reviewed.sse. The offline harness regenerates the selected branches and checks the recorded SDK observations. It cannot show whether your frontend displays the media correctly; test that separately in your application.