feat(frontend): stream/batch response channel switch for the agent playground#4861
Conversation
Adds a "Response" group (Stream / Batch) to the agent playground's kebab menu, next to the existing View group. It writes a transport-level `agentChannelModeAtom` (default "stream") on the @agenta/playground controller — not revision config — and `buildAgentRequest` reads it to set the `/messages` Accept header: `text/event-stream` for stream, `application/json` for batch (the backend already content-negotiates both). Batch rendering (replaying the WorkflowBatchResponse as a one-shot UIMessage stream so useChat can paint it) lands in the follow-up transport commit; until then batch is wired end-to-end on the request side only. Stream remains the default and is unchanged.
…m (AgentChatTransport)
useChat has no batch mode — its transport contract is always a UIMessageChunk stream. When the
channel mode is `batch`, the backend returns a single WorkflowBatchResponse (JSON, because
buildAgentRequest sent Accept: application/json). AgentChatTransport overrides processResponseStream
to parse that JSON and replay the assistant message as a one-shot v6 chunk sequence (start →
text/reasoning/tool parts → finish), so useChat paints it in a single frame. Stream mode delegates
to the default SSE parser unchanged, and the mode is read from the same agentChannelModeAtom that
set the Accept header so the request channel and response handling always agree.
The agent `/messages` batch path returns `data.outputs` as a neutral Message `{role, content}`
(content = string or content blocks), confirmed in QA — not a Vercel UIMessage. The extractor
normalizes that (and the other plausible shapes: list / {messages} / UIMessage-with-parts / string)
into UIMessage parts before emitting the chunks.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Pull #4850 (agent config panel) + the agent fix pass forward into the stream/batch channel branch. Conflicts were in the agent-lane barrels and AgentChatPanel.tsx, all where #4861 and the fix pass each added an adjacent agent export / changed the transport; resolved by keeping BOTH: - playground barrels export agentChannelModeAtom (this PR) AND agentShouldResumeAfterApproval (fix pass). - AgentChatPanel uses AgentChatTransport (this PR) with the fix pass's agentShouldResumeAfterApproval resume predicate and F-033 error handling. Backend/wire shape stays canonical (our side); the channel switch is purely the Accept header + a batch JSON->UIMessage replay. Claude-Session: https://claude.ai/code/session_01GYo3UEfvsZpncagqb28Mbc
Railway Preview Environment
|
Context
The agent playground always spoke to the agent
/messagesendpoint over SSE. This adds a per-playground switch to use batch mode instead (a single JSON response), surfaced in the playground kebab menu next to the existing View options. Stream stays the default.Changes
agentChannelModeAtomon the@agenta/playgroundcontroller (transport state, defaultstream). It is NOT revision config and is never persisted on the agent.buildAgentRequestreads it to set the requestAcceptheader:text/event-streamfor stream,application/jsonfor batch.AgentChatTransport(web/oss/src/components/AgentChatSlice/assets/AgentChatTransport.ts), a subclass ofDefaultChatTransport.useChathas no batch mode (its transport contract is always aUIMessageChunkstream), so in batch mode this parses theWorkflowBatchResponseand replays the assistant message as a one-shot chunk sequence (start → start-step → text/reasoning/tool → finish-step → finish), souseChatpaints it in one frame. Stream mode delegates to the default SSE parser unchanged.For the agent service (Mahmoud / agents)
sdk/agents/adapters/vercel/routing.py):Accept: text/event-stream→WorkflowStreamingResponse(SSE); anything else →WorkflowBatchResponse(JSON).data.outputsbeing a neutral Message{role, content}(content = a string or a list of content blocks), confirmed in QA. The chunk sequence is taken fromsdk/agents/adapters/vercel/stream.py. If the batchoutputsshape changes (a typed UIMessage, multiple messages, a wrapper), the single place to update isextractAssistantMessage/normalizeToPartsinAgentChatTransport.ts(it already accepts UIMessage-with-parts, a list,{messages}, and a string as fallbacks).tool_use/tool_resultcontent blocks →tool-input-available/tool-output-availablechunks); only confirmed against text so far, so a tool-calling agent in batch is the thing to validate.Tests / notes
agenta-playgroundpackage: tsc + eslint clean. oss: tsc + eslint clean on the changed files.{"role":"assistant","content":"Hi! How can I help you?"}→ one text part). Stream mode unchanged.What to QA