Context
We're evaluating AG-UI as the production wire for a music-production agent app (Mastra backend, assistant-ui frontend), with a bounded proof: our server emits AG-UI events over SSE, validated against @ag-ui/core's own EventSchemas, consumed by @ag-ui/client's HttpAgent (only fetch stubbed). Versions: @ag-ui/core@0.0.57, @ag-ui/client@0.0.57, @assistant-ui/react-ag-ui@0.0.50.
Four findings from that proof, receipts below — the first is the one that blocks us.
1. RUN_CANCELLED is rejected by EventSchemas, but adapter unions declare it
@ag-ui/core@0.0.57's EventSchemas rejects a RUN_CANCELLED event with invalid_union_discriminator, while @assistant-ui/react-ag-ui@0.0.50's own AgUiEvent union declares one — the two halves of the ecosystem disagree about whether the event exists.
Consequence: a server that cancels a run has no standard event to say so. The only conforming option is a coded RUN_ERROR.
2. runAgent resolves on RUN_ERROR, so cancellation is indistinguishable from provider failure
With cancel degraded to RUN_ERROR, HttpAgent.runAgent does not reject — it resolves. A caller cannot tell "the user stopped this" from "the model/provider blew up" unless it subscribes to the event stream and reads a non-standard code field. A first-class RUN_CANCELLED (or a typed reason on RUN_FINISHED) would fix both this and #1.
3. HttpAgentConfig has no credentials option
requestInit() emits only {method, headers, body}. Cookie-session auth (our case: same-site session cookie) requires replacing fetch wholesale. A credentials?: RequestCredentials passthrough would remove the workaround.
4. THINKING_TEXT_MESSAGE_* carries no messageId
Reasoning content that must stay id-addressable has to ride the id-keyed REASONING_MESSAGE_* channel instead, which materializes reasoning as a separate role: "reasoning" message rather than a part of the assistant turn (client-side consequence filed against assistant-ui separately).
Happy to provide the validation harness details or test cases for any of these.
Context
We're evaluating AG-UI as the production wire for a music-production agent app (Mastra backend, assistant-ui frontend), with a bounded proof: our server emits AG-UI events over SSE, validated against
@ag-ui/core's ownEventSchemas, consumed by@ag-ui/client'sHttpAgent(onlyfetchstubbed). Versions:@ag-ui/core@0.0.57,@ag-ui/client@0.0.57,@assistant-ui/react-ag-ui@0.0.50.Four findings from that proof, receipts below — the first is the one that blocks us.
1.
RUN_CANCELLEDis rejected byEventSchemas, but adapter unions declare it@ag-ui/core@0.0.57'sEventSchemasrejects aRUN_CANCELLEDevent withinvalid_union_discriminator, while@assistant-ui/react-ag-ui@0.0.50's ownAgUiEventunion declares one — the two halves of the ecosystem disagree about whether the event exists.Consequence: a server that cancels a run has no standard event to say so. The only conforming option is a coded
RUN_ERROR.2.
runAgentresolves onRUN_ERROR, so cancellation is indistinguishable from provider failureWith cancel degraded to
RUN_ERROR,HttpAgent.runAgentdoes not reject — it resolves. A caller cannot tell "the user stopped this" from "the model/provider blew up" unless it subscribes to the event stream and reads a non-standardcodefield. A first-classRUN_CANCELLED(or a typed reason onRUN_FINISHED) would fix both this and #1.3.
HttpAgentConfighas nocredentialsoptionrequestInit()emits only{method, headers, body}. Cookie-session auth (our case: same-site session cookie) requires replacingfetchwholesale. Acredentials?: RequestCredentialspassthrough would remove the workaround.4.
THINKING_TEXT_MESSAGE_*carries nomessageIdReasoning content that must stay id-addressable has to ride the id-keyed
REASONING_MESSAGE_*channel instead, which materializes reasoning as a separaterole: "reasoning"message rather than a part of the assistant turn (client-side consequence filed against assistant-ui separately).Happy to provide the validation harness details or test cases for any of these.