openclaw - ✅(Solved) Fix Bug: /v1/chat/completions and /v1/responses silently drop `temperature` and `top_p` [1 pull requests, 2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#81274Fetched 2026-05-14 03:33:46
View on GitHub
Comments
2
Participants
3
Timeline
7
Reactions
2
Author
Timeline (top)
referenced ×3commented ×2closed ×1cross-referenced ×1

POST /v1/chat/completions (OpenAI-compat) and POST /v1/responses (OpenResponses) accept temperature and top_p in the request body but neither value reaches the upstream provider, so client-side sampling preferences are silently ignored.

This narrows the ShadowLogic finding "OpenResponses also accepts undocumented ignored fields temperature and top_p" from #65345 (and the matching gap on the OpenAI Chat Completions surface) into a fixable bug. It mirrors the structure of #81013, which previously wired max_completion_tokens / max_tokens through the same channel.

Root Cause

POST /v1/chat/completions (OpenAI-compat) and POST /v1/responses (OpenResponses) accept temperature and top_p in the request body but neither value reaches the upstream provider, so client-side sampling preferences are silently ignored.

This narrows the ShadowLogic finding "OpenResponses also accepts undocumented ignored fields temperature and top_p" from #65345 (and the matching gap on the OpenAI Chat Completions surface) into a fixable bug. It mirrors the structure of #81013, which previously wired max_completion_tokens / max_tokens through the same channel.

Fix Action

Fixed

PR fix notes

PR #81275: fix(gateway): forward temperature and top_p through OpenAI-compatible HTTP APIs

Description (problem / solution / changelog)

Summary

  • Thread temperature and top_p from inbound POST /v1/chat/completions and POST /v1/responses through streamParams → runtime stream wrapper → OpenAI transport, so client-supplied sampling preferences reach the upstream provider.
  • Extend AgentStreamParams with topP and fix createStreamFnWithExtraParams in src/agents/pi-embedded-runner/extra-params.ts to forward topP to the underlying stream function — previously it only copied temperature / maxTokens, so topP would have been silently dropped mid-flight even with the new HTTP wiring.
  • Add top_p to OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS so the ChatGPT-based Codex Responses backend strips it server-side, matching how temperature is already handled there.
  • Drop the // Phase 1: ignore but accept comment on the OpenResponses schema fields and update both HTTP API docs to describe the new behavior (including the Codex Responses caveat).

Fixes #81274. Refs #65345 (one of the ShadowLogic findings from that audit).

Follows the same pattern as #81013, which previously wired max_completion_tokens / max_tokens through the same streamParams channel.

Verification

  • pnpm test src/gateway/openai-http.test.ts — 14/14 (new round-trip case asserting temperature / top_p land in streamParams)
  • pnpm test src/gateway/openresponses-http.test.ts — 17/17 (extended max_output_tokens block to cover temperature / top_p)
  • pnpm test src/agents/openai-transport-stream.test.ts — 120/120 (Codex-strip tests now also assert top_p is removed for the ChatGPT-based Codex Responses backend; custom-proxy test asserts top_p is preserved for non-chatgpt.com baseUrls; new chat-completions case asserts the sampling fields reach the request params)
  • pnpm test src/agents/pi-embedded-runner/extra-params.sampling.test.ts — 2/2 (new file; round-trip proof that topP reaches the underlying stream function and that runtime options can override the wrapper)
  • pnpm test src/agents/pi-embedded-runner/extra-params.{cache-retention-default,provider-runtime,openrouter-cache-control}.test.ts — 26/26 (no regressions in adjacent extra-params lanes)
  • pnpm check:changed — clean (lint core + typecheck core + typecheck core tests + duplicate scan + dependency-pin guard + import-cycle guard)
  • codex review --uncommitted"No correctness issues were found in the changed and untracked files." after the wrapper fix

Real behavior proof

  • Behavior or issue addressed: OpenAI-compatible Gateway HTTP requests now forward client-supplied temperature and top_p from POST /v1/chat/completions through streamParams to the upstream OpenAI-compatible provider instead of silently dropping them. The same PR also wires topP through the embedded runtime wrapper and documents the Responses/Codex caveat.

  • Real environment tested: Local OpenClaw managed gateway on loopback port 18789 after building PR head ceef4b80c9450a3f227514ad2054828a20033eab with pnpm build and restarting the gateway. Runtime was Node v24.14.1; CLI and gateway reported OpenClaw 2026.5.12-beta.1. The default agent model was deepseek/deepseek-v4-flash, using the configured deepseek:default API-key auth profile. Gateway token and provider key were read from local OpenClaw config/auth storage and were not printed.

  • Exact steps or command run after this patch: Ran pnpm build, then pnpm openclaw gateway restart, then posted three authenticated local requests to http://127.0.0.1:18789/v1/chat/completions: a happy-path request with temperature: 0.42 and top_p: 0.87, an out-of-range temperature: 999 probe, and an out-of-range top_p: 5 probe. Then repeated the same three-request pattern against http://127.0.0.1:18789/v1/responses with input payloads. Finally, sent the same two out-of-range probes directly to https://api.deepseek.com/chat/completions with model deepseek-chat as a provider control.

  • Evidence after fix: Live gateway output from the happy-path request:

    {
      "name": "happy-path-sampling",
      "ok": true,
      "id": "chatcmpl_acbf80a5-2f10-47d0-a51d-ec1ef2193c70",
      "object": "chat.completion",
      "model": "openclaw",
      "status": 200,
      "choice": "Hey there, how's it going? ✨",
      "usage": {"prompt_tokens": 16918, "completion_tokens": 24, "total_tokens": 16942}
    }

    Live gateway client output from the two forwarding probes:

    {"name":"temperature-out-of-range","ok":false,"status":500,"error":{"message":"internal error","type":"api_error"}}
    {"name":"top-p-out-of-range","ok":false,"status":500,"error":{"message":"internal error","type":"api_error"}}

    Live /v1/responses output from the same sampling checks:

    {
      "name": "responses-happy-path-sampling",
      "ok": true,
      "id": "resp_3fc99375-8f94-4aac-93e6-88786780571a",
      "object": "response",
      "model": "openclaw",
      "status": 200,
      "outputTypes": ["message"],
      "usage": {"input_tokens": 22, "output_tokens": 21, "total_tokens": 16939}
    }
    {"name":"responses-temperature-out-of-range","ok":false,"id":"resp_a03bce88-14d9-4e60-960b-a7291e58e85d","object":"response","model":"openclaw","status":500,"error":{"code":"api_error","message":"internal error"}}
    {"name":"responses-top-p-out-of-range","ok":false,"id":"resp_48f0d32b-cdea-40c4-b324-9eb79971cf87","object":"response","model":"openclaw","status":500,"error":{"code":"api_error","message":"internal error"}}

    Redacted runtime log excerpts for the /v1/responses probes show the same provider-side field validation:

    2026-05-13T13:34:02.857+08:00 embedded run agent end runId=resp_a03bce88-... isError=true model=deepseek-v4-flash provider=deepseek rawErrorPreview="400 Invalid temperature value, the valid range of temperature is [0, 2]"
    2026-05-13T13:34:03.630+08:00 embedded run agent end runId=resp_48f0d32b-... isError=true model=deepseek-v4-flash provider=deepseek rawErrorPreview="400 Invalid top_p value, the valid range of top_p is (0, 1.0]"

    Redacted runtime log excerpts for those same gateway requests show DeepSeek rejected the forwarded fields by name:

    2026-05-13T13:26:05.632+08:00 embedded run agent end runId=chatcmpl_c4489521-... isError=true model=deepseek-v4-flash provider=deepseek rawErrorPreview="400 Invalid temperature value, the valid range of temperature is [0, 2]"
    2026-05-13T13:26:06.332+08:00 embedded run agent end runId=chatcmpl_d26c95e4-... isError=true model=deepseek-v4-flash provider=deepseek rawErrorPreview="400 Invalid top_p value, the valid range of top_p is (0, 1.0]"

    Direct DeepSeek control requests, bypassing the gateway, returned the same provider errors:

    {
      "name": "direct-temperature-out-of-range",
      "status": 400,
      "error": {
        "message": "Invalid temperature value, the valid range of temperature is [0, 2]",
        "type": "invalid_request_error",
        "param": null,
        "code": "invalid_request_error"
      }
    }
    {
      "name": "direct-top-p-out-of-range",
      "status": 400,
      "error": {
        "message": "Invalid top_p value, the valid range of top_p is (0, 1.0]",
        "type": "invalid_request_error",
        "param": null,
        "code": "invalid_request_error"
      }
    }
  • Observed result after fix: The valid temperature/top_p requests completed successfully through both local OpenAI-compatible gateway endpoints tested: /v1/chat/completions and /v1/responses. The invalid-value probes reached DeepSeek with those exact fields present from both endpoints: DeepSeek returned field-specific Invalid temperature value and Invalid top_p value errors in the gateway runtime logs, and direct DeepSeek control calls produced the same messages. That proves the gateway writes both sampling fields into the outbound provider request body after this patch.

  • What was not tested: Live native ChatGPT Codex Responses backend behavior was not exercised in this rerun; that strip path is covered by targeted tests, including the native-baseUrl strip and custom-proxy preservation cases. The unrelated behavior where the gateway maps upstream provider 400s to a generic OpenAI-compatible internal error client response remains out of scope.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/gateway/openai-http-api.md (modified, +3/-1)
  • docs/gateway/openresponses-http-api.md (modified, +2/-0)
  • src/agents/command/shared-types.ts (modified, +1/-0)
  • src/agents/openai-transport-stream.test.ts (modified, +35/-0)
  • src/agents/openai-transport-stream.ts (modified, +9/-0)
  • src/agents/pi-embedded-runner/extra-params.sampling.test.ts (added, +89/-0)
  • src/agents/pi-embedded-runner/extra-params.ts (modified, +4/-0)
  • src/gateway/open-responses.schema.ts (modified, +4/-3)
  • src/gateway/openai-compat-errors.ts (added, +100/-0)
  • src/gateway/openai-http.test.ts (modified, +108/-1)
  • src/gateway/openai-http.ts (modified, +39/-2)
  • src/gateway/openresponses-http.test.ts (modified, +76/-0)
  • src/gateway/openresponses-http.ts (modified, +51/-3)

Code Example

curl http://localhost:$PORT/v1/chat/completions \
     -H 'authorization: Bearer …' \
     -d '{"model":"openclaw","temperature":0.2,"top_p":0.9,"messages":[{"role":"user","content":"hi"}]}'
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Summary

POST /v1/chat/completions (OpenAI-compat) and POST /v1/responses (OpenResponses) accept temperature and top_p in the request body but neither value reaches the upstream provider, so client-side sampling preferences are silently ignored.

This narrows the ShadowLogic finding "OpenResponses also accepts undocumented ignored fields temperature and top_p" from #65345 (and the matching gap on the OpenAI Chat Completions surface) into a fixable bug. It mirrors the structure of #81013, which previously wired max_completion_tokens / max_tokens through the same channel.

Steps to reproduce

  1. Start the gateway with the OpenAI-compatible HTTP endpoints enabled.

  2. Send a request to either endpoint with a sampling override, e.g.

    curl http://localhost:$PORT/v1/chat/completions \
      -H 'authorization: Bearer …' \
      -d '{"model":"openclaw","temperature":0.2,"top_p":0.9,"messages":[{"role":"user","content":"hi"}]}'
  3. Repeat with POST /v1/responses using the same temperature / top_p body.

  4. Inspect the upstream provider request payload (e.g., via onPayload, a local stub, or proxy log).

Expected behavior

temperature and top_p should be forwarded to the upstream OpenAI Chat Completions / Responses request body. The ChatGPT-based Codex Responses backend is expected to ignore them server-side (consistent with how temperature is already stripped today via OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS).

Actual behavior

  • src/gateway/openai-http.ts does not read temperature / top_p from the request payload at all.
  • src/gateway/open-responses.schema.ts:205 accepts both fields with a // Phase 1: ignore but accept comment; the handler in src/gateway/openresponses-http.ts only reads max_output_tokens.
  • Even if the request reaches the agent command pathway with a streamParams.topP, createStreamFnWithExtraParams in src/agents/pi-embedded-runner/extra-params.ts only forwards temperature, maxTokens, transport, and cachedContent to the underlying stream function — topP would still be dropped before the provider transport sees it.

OpenClaw version

main (verified at d8111ea65b)

Operating system

macOS

Provider / routing chain

OpenAI-compatible HTTP entry points (/v1/chat/completions, /v1/responses) → embedded agent runner → OpenAI / OpenAI-compatible provider transport.

Additional information

Refs #65345 (auto-generated docs/code alignment audit; this scopes one of its findings).

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

temperature and top_p should be forwarded to the upstream OpenAI Chat Completions / Responses request body. The ChatGPT-based Codex Responses backend is expected to ignore them server-side (consistent with how temperature is already stripped today via OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS).

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Bug: /v1/chat/completions and /v1/responses silently drop `temperature` and `top_p` [1 pull requests, 2 comments, 3 participants]