Skip to content

feat(frontend): negotiate agent stream→batch fallback on /invoke#4875

Merged
ardaerzin merged 5 commits into
big-agentsfrom
fe-feat/agent-invoke-endpoint
Jun 29, 2026
Merged

feat(frontend): negotiate agent stream→batch fallback on /invoke#4875
ardaerzin merged 5 commits into
big-agentsfrom
fe-feat/agent-invoke-endpoint

Conversation

@ardaerzin

Copy link
Copy Markdown
Contributor

Context

The agent playground's run lane talks to /invoke with content negotiation: Accept: text/event-stream asks for the v6 SSE UI-message stream, application/json for a single WorkflowBatchResponse. The SDK route answers a stream request it can't satisfy with 406 Not Acceptable, and surfaces handler errors as JSON with the real status code.

The first cut wired this as a fixed Accept driven by the kebab Stream/Batch toggle and trusted it — there was no negotiation. If the backend couldn't stream, the toggle's stream default had no fallback, and a stream request that came back as batch JSON would have been handed to the SSE parser.

Changes

Implements the negotiation the stream default implies — try stream → fall back to batch → error gracefully — aligned to the backend /invoke contract.

  • createNegotiatingFetch (new, @agenta/playground) — a fetch middleware that:
    1. requests the SSE stream;
    2. on a 406 (handler can only batch), re-issues the same request as application/json so the run isn't lost;
    3. passes any other non-OK response (or a failed batch fallback) through untouched, so the AI-SDK transport throws its body and useChat's onError renders the real error inline.
      It also trusts the response Content-Type over the request intent, and skips the stream attempt when batch is chosen explicitly.
  • AgentChatTransport now owns its fetch through the negotiator and parses the body by the channel that actually resolved (resolvedMode()), not the requested one — fixing the latent SSE-parser-fed-batch case.
  • channelMode doc + barrel exports updated; the Stream/Batch toggle is now a preference (Stream = negotiate with fallback, Batch = force batch).

Tests / notes

  • 5 new unit tests cover: stream honoured, 406 → batch re-request (Accept flips to application/json), real error pass-through (no second request), explicit batch skips the stream attempt, and Content-Type trust.
  • @agenta/playground build (tsc) clean; full package suite green (139 tests). OSS tsc clean for the touched files.
  • Branch is based on big-agents (after PR [feat] /invoke absorbs /messages + align agent env var names #4868/invoke absorbs /messages — merged into it).

What to QA

  • Run an agent that streams: replies stream token by token (SSE path).
  • Run an agent whose handler can't stream: the panel still returns a reply in one frame (batch fallback), not an empty/broken stream.
  • Trigger a run error (misconfigured model / missing key): the real error renders inline, not a generic failure.

The agent playground sent a fixed Accept from the kebab toggle and trusted it,
with no fallback if the backend could not stream. Add the negotiation the
'stream' default implies, aligned to the SDK /invoke contract:

- createNegotiatingFetch (new, @agenta/playground): a fetch middleware that
  requests the SSE stream, falls back to a batch re-request on a 406 (handler
  can't stream), and passes any other non-OK response through so useChat
  surfaces the real error inline.
- AgentChatTransport now owns its fetch via the negotiator and parses the body
  by the channel that actually resolved, not the requested one — fixing the
  latent case where a stream request that fell back to batch was fed to the SSE
  parser.
- channelMode doc + barrel exports updated; the Stream/Batch toggle is now a
  preference (Stream = negotiate with fallback, Batch = force batch).
- Adds 5 unit tests covering stream, 406 fallback, error pass-through, explicit
  batch, and Content-Type trust.
@vercel

vercel Bot commented Jun 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jun 28, 2026 4:02pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 93dcf486-f503-4c24-87d5-868e1ab2b5c5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fe-feat/agent-invoke-endpoint

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ardaerzin ardaerzin marked this pull request as ready for review June 26, 2026 13:48
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request feature Frontend labels Jun 26, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 213b6551-526e-4ec5-89c7-b81896c722bf

📥 Commits

Reviewing files that changed from the base of the PR and between b93e88f and 9ce1236.

📒 Files selected for processing (7)
  • web/oss/src/components/AgentChatSlice/assets/AgentChatTransport.ts
  • web/packages/agenta-playground/src/index.ts
  • web/packages/agenta-playground/src/state/execution/agentNegotiation.ts
  • web/packages/agenta-playground/src/state/execution/channelMode.ts
  • web/packages/agenta-playground/src/state/execution/index.ts
  • web/packages/agenta-playground/src/state/index.ts
  • web/packages/agenta-playground/tests/unit/agentNegotiation.test.ts

The negotiating fetch tracked the resolved channel (stream vs. batch) in a
shared mutable variable that AgentChatTransport read back later in
processResponseStream. That read-back across the fetch->parse boundary is only
safe while requests on a transport never overlap; it is a latent race if they
ever do (the parse could pick up a sibling request's mode).

Key the mode off the response body ReadableStream via a WeakMap instead, so the
parse decision is bound to the exact body being parsed. resolvedMode now takes
the stream (with a no-arg fallback to the last negotiation for callers without
it). Behaviour is unchanged for the existing single-request paths; the 5
negotiation unit tests stay green.
@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ardaerzin ardaerzin merged commit 6518090 into big-agents Jun 29, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request feature Frontend size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant