Skip to content

fix: Responses effort rides extra_body; envelope reports metadata; "" is unset on every lane - #469

Merged
rejojer merged 3 commits into
mainfrom
fix/chat-protocol-followups
Sep 3, 2026
Merged

fix: Responses effort rides extra_body; envelope reports metadata; "" is unset on every lane#469
rejojer merged 3 commits into
mainfrom
fix/chat-protocol-followups

Conversation

@rejojer

@rejojer rejojer commented Sep 3, 2026

Copy link
Copy Markdown
Member

Three follow-ups to #460 (chat(protocol=)), from the review rounds on #461. Same commits as feat/chat-protocol df16c18 / fbd6b4d / b15858b, cherry-picked onto main.

Responses effort rides extra_body; chat() docs say what the wire does (8ca938c)
reasoning_effort on the Responses lane joins the caller's extra_body["reasoning"] object (their keys win) instead of a separate reasoning= that a caller's object replaced whole on the wire. Mirrors the Messages lane's output_config. reasoning_effort="" is unset on both protocol lanes. Docstrings name the wire fields per lane, drop the invitation to override the SDK's system/input, say every system row joins the managed prompt on the answer lane, and document the max_turns raise-vs-truncate divergence. The migration message points at keywords + extra_body.

Responses envelope reports the metadata sent (51909cd)
metadata is a request field the caller sets through extra_body; the envelope hard-coded None. Now given.get(), like the other caller-set fields.

"" is unset on the answer lane; managed-cloud gate reads falsy as unset (e3cd7d4)
reasoning_effort="" reached LiteLLM as a literal empty effort on the answer lane while the protocol lanes treated it as unset. And chat_completions' managed-cloud own-model gate, which chat() routes through, refused model="" / reasoning_effort="" / {} as knobs the caller never set. Non-numeric knobs now read falsy as unset, as the local lane always has; numeric ones keep is not None.

Each fix carries a red-verified test. 470 passed on this base; the same commits are CI-green on feat/chat-protocol (#461).

https://claude.ai/code/session_01BAmVWYKoSnFEydbMjuZjHc

… does

The rule chat() follows, written down: chat() names PageIndex's own
parameters plus a subset of LiteLLM's unified vocabulary; anything
vendor-specific rides extra_body under the lane's wire names. Three
layers meet on the wire — the skeleton (managed prompt, conversation,
tools) is the SDK's, the named knobs are translated per lane, and
extra_body is the caller's, merged last so it wins. A key the SDK writes
into a nested object must go in through extra_body too, so the caller's
other keys in that object survive — the SDK merge is shallow.

- Responses lane: reasoning_effort joins the caller's extra_body
  "reasoning" object (their keys win) instead of riding a separate
  reasoning= that extra_body's object replaced whole on the wire.
  Mirrors the Messages lane's output_config. The envelope's
  given.get("reasoning") now reports the merged object for free.
- reasoning_effort="" is unset on both protocol lanes, like model=""
  and instructions="".
- extra_body docstring: drop the invitation to override the SDK's
  system/input — that is the skeleton, and a fixed input breaks the
  tool loop; name the wire fields per lane instead of one mixed list.
- messages docstring: every system row joins the managed prompt on the
  answer lane, not only a leading one (_split_chat_messages hoists all).
- max_turns docstring: the OpenAI lanes raise at the cap, the Messages
  lane returns the truncated run — the divergence was documented only on
  the private door.
- Migration message: parameters go by keyword; the doors' sampling and
  thinking fields ride extra_body.
- chat_model docstring: responses is no longer a chat surface.
- _split_chat_messages refusals no longer name chat_completions, a
  method the chat() caller never typed.
- Tests: the Responses door equivalence takes the extra_body shape;
  effort/extra_body collision, key survival and "" pinned on both
  protocol lanes; the ModelSettings spy asserts the values reached the
  wire, not only the envelope.

Claude-Session: https://claude.ai/code/session_01Hj6t26s7thUjkcho6sn4zE
metadata is a Responses request field the caller sets through
extra_body; the envelope hard-coded None. Same source as the other
caller-set fields: given.get().

Claude-Session: https://claude.ai/code/session_01Hj6t26s7thUjkcho6sn4zE
…s unset

reasoning_effort="" reached LiteLLM as a literal empty effort on the
answer lane while the protocol lanes already treated it as unset. And
chat_completions' managed-cloud own-model gate, which chat() routes
through, refused model="" / reasoning_effort="" / {} as knobs the caller
never set. Non-numeric knobs now read falsy as unset, as the local lane
always has (model or chat_model, if extra_body, backend or {}); numeric
ones keep `is not None`.

Claude-Session: https://claude.ai/code/session_01BAmVWYKoSnFEydbMjuZjHc
(cherry picked from commit b15858b)
@rejojer
rejojer merged commit 1ccb31b into main Sep 3, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant