fix(agent): route MoA streaming through virtual client - #57328
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes MoA (“moa://local”) streaming on gateway platforms by routing streaming chat-completions through the existing in-process MoA client facade (agent.client) rather than constructing a request-scoped OpenAI client that attempts to connect to the virtual moa://local URL.
Changes:
- Update the streaming chat-completions path to call
agent.client.chat.completions.create(...)whenprovider == "moa", preserving existing stream assembly/diagnostics behavior for other providers. - Add regression tests ensuring MoA streaming does not create a request OpenAI client and still forwards
stream=Trueandstream_options.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
agent/chat_completion_helpers.py |
Adds a MoA-specific dispatch in the streaming chat-completions path to use the in-process MoA client facade. |
tests/run_agent/test_streaming.py |
Adds/updates tests to assert MoA streaming bypasses request OpenAI client creation and preserves streaming kwargs forwarding. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Thanks for the clean writeup and tests, @deaneeth — this is a well-constructed PR. Closing it because the bug it targets is already fixed on current Since ~June 27 ( def _create_request_openai_client(self, *, reason, api_kwargs=None):
primary_client = self._ensure_primary_openai_client(reason=reason)
if self.provider == "moa":
return primary_client # <- the MoA facade itself
...So the streaming path's Verified end-to-end on current The reproduction in #57251 is from a build predating June 27 — The one adjacent observation worth keeping: on interrupt of a hung MoA stream, the abort path targets the facade (which has no sockets), so stream-handle teardown there is a genuine but separate gap from what this PR/issue reported. If you want to pursue that as its own focused PR against current Appreciate the contribution and the regression tests — sorry this one collided with an already-landed fix. |
|
@teknium1 Confirmed after checking latest main: the routing bug this PR targeted was already fixed via #53826, so closing this PR was the right call. I split out only the separate MoA stream-handle teardown gap you mentioned into a focused PR: #57354 . It keeps current main’s MoA facade routing intact and only adds interrupt/stale cleanup for the active per-request MoA stream handle. Thank you so much for pointing that out, when you have a time please take a look... |
What does this PR do?
Routes MoA streaming requests through the existing in-process MoA client facade instead of constructing a request-local OpenAI client for the virtual
moa://localendpoint.Root cause:
interruptible_streaming_api_call()always used_create_request_openai_client()for chat-completions streaming. That is correct for real OpenAI-compatible endpoints, but MoA is a virtual provider backed byagent.client.chat.completions.create(...). Gateway platforms using streaming therefore tried to connect tomoa://localand failed withAPIConnectionError.Related Issue
Fixes #57251
Type of Change
Changes Made
agent/chat_completion_helpers.py: useagent.client.chat.completions.createforprovider == "moa"in the streaming path while preserving existing streaming assembly, timeout, diagnostics, fallback behavior, and interrupt/stale stream teardown.tests/run_agent/test_streaming.py: add regression coverage proving MoA streaming does not create a request OpenAI client, still forwardsstream=True/stream_optionsto the MoA facade, and closes a hung MoA stream handle on interrupt.How to Test
python -m pytest tests/run_agent/test_streaming.py -qpython -m pytest tests/run_agent/test_moa_streaming.py tests/agent/test_moa_trace_streamed_capture.py -qpython scripts/run_tests_parallel.py tests/run_agent/test_streaming.py tests/run_agent/test_moa_streaming.py tests/agent/test_moa_trace_streamed_capture.py -qpython -m ruff check agent/chat_completion_helpers.py tests/run_agent/test_streaming.pyLocal result:
tests/run_agent/test_streaming.py: 44 passed, 2 skippedtests/run_agent/test_moa_streaming.py+tests/agent/test_moa_trace_streamed_capture.py: 12 passedscripts/run_tests_parallel.py ...: 55 passed, 0 failedruff check ...: all checks passedChecklist
Code
Documentation & Housekeeping
cli-config.yaml.exampleupdate N/ACONTRIBUTING.md/AGENTS.mdupdate N/A