Repository navigation
[Rust Frontend][2/3] Add stateless non-streaming Responses API - #2
Open
franciscojavierarceo wants to merge 118 commits into
Open
franciscojavierarceo wants to merge 118 commits into
franciscojavierarceo wants to merge 118 commits into
Conversation
This was referenced Oct 7, 2026
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Valid controls are silently ignored and some response metadata misrepresents actual behavior.
Review effort: Balanced
Findings: 7
Open (7)
Error code format differs from Python vLLM contract · New Requested include outputs are silently ignored · New Response reports incorrect resolved sampling parameters · New Ignored reasoning summary and text verbosity controls · New Metadata accepts invalid shapes and exceeds documented limits · New Invalid service tiers are accepted and echoed · New Nullable stream value is rejected during deserialization · New
What changed in this PR
Adds a stateless, non-streaming OpenAI-compatible Responses API to the Rust frontend.
Changes:
- Adds request validation, chat lowering, response assembly, and tool/reasoning replay.
- Registers create, retrieve, and cancel routes with runtime offloading.
- Adds unit and HTTP regression coverage.
| File | Description |
|---|---|
rust/src/server/src/routes/tests/responses.rs |
Adds Responses HTTP tests. |
rust/src/server/src/routes/tests.rs |
Registers the test module. |
rust/src/server/src/routes/openai/responses/validate.rs |
Validates supported request features. |
rust/src/server/src/routes/openai/responses/types.rs |
Defines request and response wire types. |
rust/src/server/src/routes/openai/responses/convert.rs |
Converts Responses requests and outputs. |
rust/src/server/src/routes/openai/responses.rs |
Implements endpoint handlers. |
rust/src/server/src/routes/openai/mod.rs |
Exports Responses handlers. |
rust/src/server/src/routes.rs |
Registers HTTP routes. |
rust/src/server/src/middleware/offload.rs |
Offloads response generation work. |
rust/src/server/src/error.rs |
Adds unknown-response errors. |
rust/src/parser/src/tool/mod.rs |
Allows omitted function schemas. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+119
to
+123
| top_logprobs, | ||
| text, | ||
| truncation, | ||
| user, | ||
| include: _, |
Comment on lines
+113
to
+115
| /// Output presentation controls such as `include`, `reasoning.summary`, and | ||
| /// `text.verbosity` are accepted for compatibility. They do not add output | ||
| /// fields that this frontend cannot produce. |
| #[serde(default = "default_true")] | ||
| pub include_reasoning: bool, | ||
| #[serde(default)] | ||
| pub service_tier: Option<String>, |
6 tasks done
franciscojavierarceo
force-pushed
the
codex/responses-nonstreaming
branch
from
October 27, 2026 03:41
2049693 to
ee46722
Compare
franciscojavierarceo
marked this pull request as ready for review
October 27, 2026 11:39
franciscojavierarceo
force-pushed
the
codex/responses-nonstreaming
branch
2 times, most recently
from
October 28, 2026 10:32
5bc7b88 to
d5b7df3
Compare
…llm-project#64585) Signed-off-by: Erez Zarum <erezz@amazon.com> Co-authored-by: Artem Perevedentsev <aperevedents@nvidia.com>
…ncelled (vllm-project#64265) Signed-off-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…ithout the developer role (vllm-project#63901) Signed-off-by: Francisco Javier Arceo <4163062+franciscojavierarceo@users.noreply.github.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: Codex <noreply@openai.com> Co-authored-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…es (vllm-project#63974) Signed-off-by: Luyi Xiao <81631911+luyixiao95@users.noreply.github.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: OpenAI Codex <noreply@openai.com> Co-authored-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…tion prefix (vllm-project#58618) Signed-off-by: Yuting Wu (DLAlgo) <yutwu@nvidia.com> Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…untime (vllm-project#64294) Signed-off-by: reidliu41 <reid201711@gmail.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…llm-project#63137) Signed-off-by: world-executed <yolohalo@163.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: world-executed <yolohalo@163.com> Co-authored-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…#65140) Signed-off-by: Djordje Ramic <djoramic@amd.com>
…-project#65005) Signed-off-by: Alex-Wengg <hanweng9@gmail.com>
…0+ (vllm-project#65059) Signed-off-by: Seungryong Kim <137975233+srkim-business@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…dule's hook (vllm-project#57678) Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: nicole-lihui <44200120+nicole-lihui@users.noreply.github.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…64838) Signed-off-by: zjy0516 <riverclouds.zhu@qq.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…m-project#63870) Signed-off-by: Bugen Zhao <i@bugenzhao.com> Signed-off-by: Julien Darve <jdarve@NVIDIA.com> Co-authored-by: Bugen Zhao <i@bugenzhao.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ect#64920) Signed-off-by: Thomas Ortner <boh@zurich.ibm.com>
vllm-project#65166) Signed-off-by: davidteather <34144122+davidteather@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: xujixian <xjxian02@gmail.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…65153) Signed-off-by: akii96 <aakif.nawaz@amd.com> Co-authored-by: Simon Danielsson <70206058+simondanielsson@users.noreply.github.com>
…llm-project#64312) Signed-off-by: Stefano Castagnetta <scastagnetta@nvidia.com> Signed-off-by: lesj0610 <lesj0610@gmail.com> Signed-off-by: Isotr0py <Isotr0py@outlook.com> Co-authored-by: Stefano Castagnetta <scastagnetta@nvidia.com> Co-authored-by: Isotr0py <Isotr0py@outlook.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…project#63641) Signed-off-by: Chaojun Zhang <chaojun.zhang@intel.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…ase in v1/shutdown (vllm-project#65097) Signed-off-by: zengxian <xiangdong.zeng@intel.com>
…ce copies on integrated GPUs (vllm-project#58868) Signed-off-by: Willian <willian@willian.email> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: vllm-agent <claw@inferact.ai>
Signed-off-by: wang.yuqi <yuqi.wang@daocloud.io> Co-authored-by: vllm-agent <claw@inferact.ai>
…62802) Signed-off-by: Tianyu Guo <guoty@inferact.ai> Co-authored-by: vllm-agent <claw@inferact.ai>
Signed-off-by: Canlin <canlinguosdu@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Jee Jee Li <jeejeelee@inferact.ai> Co-authored-by: Codex <noreply@openai.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…t#56102) Signed-off-by: kbenkhaled <kbenkhaled@nvidia.com> Co-authored-by: Codex <noreply@openai.com>
…eshold (vllm-project#64558) Signed-off-by: Sohom Chakraborty <16609933+sohom-cs@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Or Ozeri <oro@il.ibm.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…llm-project#64993) Signed-off-by: waizuichougou <2082431897@qq.com> Co-authored-by: vllm-agent <claw@inferact.ai>
Add `POST /v1/responses` on top of `ChatLlm::chat`: requests lower into a chat request, and `OutputItemStreamer` turns the chat event stream into Responses output items and SSE lifecycle events. Store-dependent features are rejected or return 404. Non-streaming requests are rejected for now. This squashes the streaming-first part of the original stack: - 9e714a4 [Rust Frontend] Add stateless non-streaming Responses API - f785541 fix: validate Responses controls and report model sampling defaults - 881a178 fix: adapt Responses to current Rust frontend contracts - ef5a082 fix: mark truncated Responses output items incomplete - 5bc7b88 fix: adapt Responses decoding and cache usage to upstream - 6698c5b [Rust Frontend] Add Responses streaming lifecycle - 062c680 test: cover Responses partial output after stream decode failure - cf47141 fix: adapt Responses streaming to current chat events - a2adabf fix: preserve final output item status in Responses streams Its non-streaming path returns in a later commit. Route tests that do not depend on the response mode now run through streaming. Co-authored-by: Canlin Guo <canlinguosdu@gmail.com> Co-authored-by: Codex <noreply@openai.com> Signed-off-by: Francisco Javier Arceo <4163062+franciscojavierarceo@users.noreply.github.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Replace raw JSON probing in the Responses route with typed DTOs that reuse the chat-completions definitions: - Tools are `ResponsesTool::Function(Function)`, the chat-completions `Function` flattened next to `type`, lowered through a shared `Function -> ChatTool` conversion. - `tool_choice` reuses `ToolChoiceValue`, `FunctionChoice`, and `ToolReference`. - Input items deserialize into typed items; a message item may omit `type`, mirroring Python's `input_item_parsing`. Errors keep the item index. - `truncation`, `service_tier`, `reasoning.summary`, and `text.verbosity` are serde enums instead of string allow-lists. Stream events become a typed enum serialized directly into SSE data, with `type` and `sequence_number` added by a wrapper. Lifecycle events share the response through `Arc` instead of converting it to `Value`. `function_call_arguments` events no longer carry a `content_index`, matching the SDK event shape. Unknown tool, tool-choice, and input-item types now fail deserialization, so errors name the JSON path instead of a `param`. The unread `store` field is dropped; `store=true` still executes. Add an async-openai typed-client test for streaming Responses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Remove logic the Responses route duplicated from lower layers: - Echo `temperature`, `top_p`, `max_output_tokens`, and the presence/frequency penalties from the sampling values sent to the engine, as Python does. `ChatEventStream::sampling()` exposes them, read from the prepared generate request in `ChatLlm::chat`, instead of the handler pre-filling model defaults and repeating vllm-text's precedence. The echoed output limit is the context-clamped one, and an omitted limit or penalty no longer disappears from the response. The `TextRequestProcessor::sampling_hints()` accessor goes away. - Drop the `enable_thinking` template kwarg injection. The HF renderer already derives it from `reasoning_effort`, and native renderers resolve reasoning controls through `ReasoningControl`. - Revert `#[serde(default)]` on `vllm_parser::Tool.parameters`. Wire tools now deserialize into the server `Function` DTO, which owns that default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
The terminal streaming response rebuilt its output from the final chat message with fresh IDs and patched the streamed IDs back by item kind and order, while failed streams used the streamer's completed items instead. Make the streamer's completed items the only source of `output`, and drop the rebuild and the ID reconciliation. This also drops an empty reasoning block from the final output, which streaming never emitted as an item. Derive the next output index and the deferred `output_item.done` from the completed items instead of keeping copies of them, and drop a function-call field that was written but never read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Serve requests without `stream: true` by feeding chat events through the same `OutputItemStreamer` and discarding its SSE events, like `ChatEventStream::collect_message` does for Chat Completions. The streamer's completed items stay the only source of `output`, so both modes return the same items and IDs. Unlike streaming, engine errors map to typed HTTP errors (400 for validation, 503 for retryable failures) because no response has been sent yet. Both modes now share the terminal assembly: the handler builds the in-progress response once after submission, and the completed and failed responses derive from it. The terminal streaming event follows from the final response status. Restore the non-streaming route tests from the original stack and add an async-openai typed-client test for non-streaming Responses. Co-authored-by: Francisco Javier Arceo <4163062+franciscojavierarceo@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJckCDvqfKYQRRwCYtsCmk Signed-off-by: Bugen Zhao <i@bugenzhao.com>
Attach `metrics` to the final Responses object when `--enable-per-request-metrics` is set, as Python Responses does, for both the non-streaming body and the terminal streaming event. Python Responses reports timing only, so speculative-decoding statistics stay on Chat Completions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJckCDvqfKYQRRwCYtsCmk Signed-off-by: Bugen Zhao <i@bugenzhao.com>
When generation hits the output limit, the last output item is the truncated one. Message and function-call items were marked `incomplete`, but a reasoning item kept `completed`, so a request that ran out of tokens while reasoning returned an incomplete response whose only item claimed to be complete. Python passes the same `incomplete` status to reasoning items. Extend the length-limit test to two tool calls so it also checks that only the last one is marked, and cover reasoning-only truncation in both modes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJckCDvqfKYQRRwCYtsCmk Signed-off-by: Bugen Zhao <i@bugenzhao.com>
The Responses request type lacked several vLLM controls that Python declares, so serde dropped them and requests ran with the defaults: `min_p` was ignored, and `spaces_between_special_tokens: false`, `media_io_kwargs`, `mm_processor_kwargs`, and `enable_response_messages: true` were accepted without effect. Forward `min_p` to the shared sampling parameters, and reject the others with 400 as Chat Completions does. Prompt-cache hints and `safety_identifier` stay ignored, which Python documents as no-ops. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJckCDvqfKYQRRwCYtsCmk Signed-off-by: Bugen Zhao <i@bugenzhao.com>
The response object omitted every unset optional field, so the initial lifecycle objects had no `usage`, completed ones had no `incomplete_details`, and unset echoes such as `instructions` or `reasoning` disappeared. Python and the OpenAI schema keep these fields present with `null`. Serialize them as `null`, and keep omitting `metrics` when it is disabled, as Python does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJckCDvqfKYQRRwCYtsCmk Signed-off-by: Bugen Zhao <i@bugenzhao.com>
BugenZhao
force-pushed
the
codex/responses-nonstreaming
branch
2 times, most recently
from
November 3, 2026 08:42
7af1e25 to
a1d8bd8
Compare
…t chunks (vllm-project#64330) Signed-off-by: kliuae <kuanfu.liu@embeddedllm.com> Co-authored-by: Claude Opus <noreply@anthropic.com>
…connect (vllm-project#64299) Signed-off-by: jiuyueQ <631905507@qq.com> Co-authored-by: vllm-agent <claw@inferact.ai>
…e module's parameters (vllm-project#65296) Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…d weight now starts (vllm-project#65281) Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Add `usage.input_tokens_details.cache_write_tokens`, the prompt tokens newly written to the prefix cache, as the Python frontend has since vllm-project#60973. The OpenAI SDK `Response` type requires the field, so strict validation of Rust responses failed without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJckCDvqfKYQRRwCYtsCmk Signed-off-by: Bugen Zhao <i@bugenzhao.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Overview
add stateless, non-streaming
POST /v1/responsesthrough the existingvllm-chatpipeline, with input replay, function tools, reasoning, and usage.upstream review order: 1/3: renderer vllm-project/vllm#63901 → 2/3: non-streaming vllm-project/vllm#63902 → 3/3: streaming vllm-project/vllm#63903. all three upstream review PRs target
main; later diffs include earlier layers.this PR includes and depends on vllm-project#63901. the fork layer shows its isolated diff.
Claims
stream: truewith HTTP 400 onparam: streamuntil layer 3.Validation
Latest upstream synchronization — October 28
current head:
d5b7df30aa; rebased onto upstreamf4fd1ab68e. the fork keeps its native stacked bases; upstream PRs still targetmain.NotFoundandResponseNotFoundretain their existing wire envelopes; the LoRA/gRPC and Responses HTTP regressions pass.cargo test --locked -p vllm-server -p vllm-text --lib -- --test-threads=1: 579 server + 121 text passed, one existing text test ignored.git diff --check: passed.cargo nextestremains unavailable.f4fd1ab68e.the model-backed HTTP/Codex evidence below predates this synchronization (complete-stack head
3db4c9abf0); it was not repeated after this rebase. today's evidence covers compilation and deterministic wire/route/renderer regressions, not new model qualification. CI reruns on these new heads are separate from the earlier successful workflows. agentic-api was not changed or pushed.Earlier review and runtime evidence
reviewed and revised on October 27; non-streaming head:
91a782aa08.incompletestatus but a final message item markedcompleted.cargo test --locked -p vllm-server -p vllm-text --lib -- --test-threads=1: 552 server + 118 text passed, one existing text test ignored.git diff --check: passed.f8f7634cb4; the fork's isolated stack bases are preserved.commands ran from
rust/withOPENSSL_DIRpointing to the local OpenSSL build.cargo nextestwas unavailable. full-stack tests ran serially because of the previously reproduced shared chat audio-metrics collector collision.fresh model-backed HTTP and real Codex checks passed on the revised complete stack, as recorded in vllm-project#63903. this intermediate branch was tested separately with the in-process HTTP route harness; it does not contain streaming.
Details
Responses owns its wire envelopes and conversions while reusing the chat generation path and matching shared audio/tool primitives. the rebase preserves upstream's other route registrations and error serialization rather than restoring the older envelope.
streamselects non-streaming. omitted/null watermarking and explicit overrides follow current Chat Completions semantics.includeoutputs, and nonzerotop_logprobsare rejected.previous_response_iduses the current sharedNotFoundErrorenvelope: HTTP 404,param: response_id, numericcode: 404.the frontend remains stateless: clients replay history, and agentic-api owns persistence and tool execution. the shared native adapter tracked by vllm-project/agentic-api#359 and vllm-project/agentic-api#382 is still unfinished. accepted reasoning-summary, text-verbosity, and encrypted-reasoning inputs are documented compatibility no-ops; valid service tiers are echoed without scheduling guarantees. persistence, retrieval/cancellation, built-in/custom/namespace tool execution, Harmony rendering, output logprobs, and
allowed_toolsare out of scope. the rendered Responses documentation describes the supported subset.these are the existing vllm-project#58783 layers opened upstream at @BugenZhao's request, rather than competing implementations. the original authored history and discussion remain in vllm-project#58783. @gcanlin's vllm-project#53380 implementation is credited in the endpoint and streaming commits. vllm-project#56124 covers render endpoints and vllm-project#51535 covers chat
allowed_tools; neither duplicates this endpoint.this layer is 13 files, +2987 / -1 relative to vllm-project#63901. tests stay under the test-only route module. agentic-api compatibility follow-ups remain local and unpushed. Codex assistance was used; human review of every changed line and independent validation are required before merge.
Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.
BEFORE SUBMITTING, PLEASE READ https://docs.vllm.ai/en/latest/contributing (anything written below this line will be removed by GitHub Actions)