Problem
Per-target extra_body keys are merged into the outbound request body in
crates/libsy-llm-client/src/client.rs at a point that sits outside the retry loop, so the merge
happens once, before any attempt.
When an upstream rejects the request because of one of those keys — a 400/422 naming an unknown or
unexpected parameter — every retry re-sends the same rejected key. The retry cannot succeed, and
there is no way for a caller to say "drop this knob and try again".
The case we hit in practice: reasoning-control knobs (chat_template_kwargs, enable_thinking) that
some OpenAI-compatible servers accept and others reject outright. A call carrying the knob fails
permanently against a rejecting server, even though the identical call without it would succeed.
Proposal
Move the extra_body merge inside the retry loop and allow named keys to be dropped after a
parameter rejection. Roughly 20 lines.
Deliberately narrow:
- Only a 400/422 whose body names the parameter, or an unknown/extra-parameter condition,
qualifies. A 429 or 5xx must surface as-is — silently stripping a knob and re-firing on a
rate limit would double the load and mask the real failure.
- Retry exactly once without the knob. No escalation ladder, no second strip.
Scope
crates/libsy-llm-client/ only. Benefits every route that configures extra_body, which is why it
seems worth doing as its own change rather than inside a feature PR.
Notes
Happy to open the PR. Wanted to check the direction first, since it moves an existing statement
across the retry boundary rather than adding alongside it — if you'd prefer a different shape (e.g.
an explicit per-target "droppable keys" list instead of inferring from the reject), that's easy to
adjust.
Problem
Per-target
extra_bodykeys are merged into the outbound request body incrates/libsy-llm-client/src/client.rsat a point that sits outside the retry loop, so the mergehappens once, before any attempt.
When an upstream rejects the request because of one of those keys — a 400/422 naming an unknown or
unexpected parameter — every retry re-sends the same rejected key. The retry cannot succeed, and
there is no way for a caller to say "drop this knob and try again".
The case we hit in practice: reasoning-control knobs (
chat_template_kwargs,enable_thinking) thatsome OpenAI-compatible servers accept and others reject outright. A call carrying the knob fails
permanently against a rejecting server, even though the identical call without it would succeed.
Proposal
Move the
extra_bodymerge inside the retry loop and allow named keys to be dropped after aparameter rejection. Roughly 20 lines.
Deliberately narrow:
qualifies. A 429 or 5xx must surface as-is — silently stripping a knob and re-firing on a
rate limit would double the load and mask the real failure.
Scope
crates/libsy-llm-client/only. Benefits every route that configuresextra_body, which is why itseems worth doing as its own change rather than inside a feature PR.
Notes
Happy to open the PR. Wanted to check the direction first, since it moves an existing statement
across the retry boundary rather than adding alongside it — if you'd prefer a different shape (e.g.
an explicit per-target "droppable keys" list instead of inferring from the reject), that's easy to
adjust.