Skip to content

fix(openai_responses): centralize body-size enforcement - #700

Open
eoinfennessy wants to merge 577 commits into
praxis-proxy:mainfrom
eoinfennessy:fix/centralize-responses-body-size-enforcement
Open

fix(openai_responses): centralize body-size enforcement#700
eoinfennessy wants to merge 577 commits into
praxis-proxy:mainfrom
eoinfennessy:fix/centralize-responses-body-size-enforcement

Conversation

@eoinfennessy

Copy link
Copy Markdown
Member

Motivation

Several OpenAI Responses filters carried a max_body_bytes knob that only sized their StreamBuffer buffer. Because praxis core merges per-direction body modes across a chain (keeping the largest) before clamping to the listener's transport ceiling, that knob was silently widened whenever a sibling filter declared a larger buffer — so it never reliably capped the raw body it appeared to control.

Closes #562.

Approach

Raw transport size is now governed exclusively by the pipeline's body_limits (max_request_bytes / max_response_bytes), enforced once by core before any filter runs. Per-filter limits are reserved for the body a filter genuinely produces, which body_limits cannot see.

  • Shared helpers (apis/src/openai/responses/body_limits.rs): validate_size_limit (names the actual field in errors) and reject_rewritten_body_too_large (streaming-aware 413).
  • Producer filters (doc_extract, file_resolve, openai_mcp_tool_resolve, openai_responses_proxy) enforce max_rewritten_body_bytes / max_resolved_bytes on the rewritten body only; their buffers accept up to the 64 MiB absolute ceiling.
  • Pure-BodyMode filters (openai_responses_format, openai_responses_model_rewrite, agentic_loop, openai_mcp_dispatch, openai_tool_parse) drop the knob entirely and rely on body_limits.
  • responses_to_chat_completions renames max_body_bytesmax_rewritten_body_bytes to reflect that it bounds the translated body, not the raw input.

Breaking change

Removed fields are now rejected under #[serde(deny_unknown_fields)]. A config that still sets max_body_bytes on a migrated filter fails loudly at startup rather than silently ignoring the value. Example configs and filter docs are updated to the new form.

Testing

  • New body-size-limits example config plus a functional integration test asserting the transport cap rejects oversized raw bodies with 413 and forwards small ones.
  • Unit/integration coverage updated across all migrated filters (legacy-knob-rejected assertions added).
  • make test and make lint pass; filter docs, example README, and coverage manifests regenerated and in sync.

shaneutt and others added 30 commits June 24, 2026 19:23
sqlx 0.9 requires SqlSafeStr for query strings and grew internal future sizes.

Signed-off-by: Shane Utt <shaneutt@linux.com>
rand 0.10 moved random_range from Rng to RngExt.

Signed-off-by: Shane Utt <shaneutt@linux.com>
Signed-off-by: dependabot[bot] <support@github.com>
)

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: usize <mofoster@redhat.com>
Signed-off-by: usize <mofoster@redhat.com>
Signed-off-by: Sébastien Han <seb@redhat.com>
Signed-off-by: Teryl Taylor <terylt@ibm.com>
Signed-off-by: Frederico Araujo <frederico.araujo@ibm.com>
Co-authored-by: Teryl Taylor <terylt@ibm.com>
…essages (praxis-proxy#729)

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
…roxy#734)

Signed-off-by: Sébastien Han <seb@redhat.com>
Co-authored-by: Francisco Javier Arceo <farceo@redhat.com>
Signed-off-by: Sébastien Han <seb@redhat.com>
Signed-off-by: Shane Utt <shaneutt@linux.com>
Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
…SSE parser (praxis-proxy#739)

Signed-off-by: Sébastien Han <seb@redhat.com>
…d Content-Type (praxis-proxy#745)

Signed-off-by: Sébastien Han <seb@redhat.com>
To migrate to this repository we simply based on the core repository,
and this patch removes, modifies and updates everything to match the
new AI filters and capabilities crates we want here. This method allowed
us to keep all git history and attribution.

Signed-off-by: Shane Utt <shaneutt@linux.com>
shaneutt and others added 10 commits August 6, 2026 11:28
Signed-off-by: Shane Utt <shaneutt@linux.com>
* feat(anthropic): add Messages web search loop

Share web-search provider infrastructure across protocols and execute server-owned WebSearch calls through Praxis IRR. Add You.com configuration, vLLM-compatible Messages handling, bounded loop state, sanitized recordings, deterministic mocks, integration coverage, and generated documentation.

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

* fix(anthropic): preserve protocol headers across iterations

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

* fix(anthropic): address web search review feedback

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

* docs: remove web search planning artifacts

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

---------

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
…s-proxy#653)

* test(inference): add Rust-native recording and replay fixtures

Add versioned, provider-specific inference scenarios and sanitized
two-sided recordings for OpenAI, vLLM, and Anthropic. Replay fixtures
offline through the real Praxis pipeline with bounded recording,
credential safety, coverage validation, and generated documentation.

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

* fix(inference): tighten fixture recording safety

Contain the OpenAI credential to the exact first-party origin and normalize native Responses timestamps, padding, and item references. Keep provider identity separate from provenance origin and refresh the checked-in fixtures.

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

---------

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
)

* feat(openai): add Responses-to-Chat Completions filter

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

* fix(openai): address responses translation review

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

* fix(openai): preserve streaming pipeline errors

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

* fix(openai): cover Responses chat translation edge cases

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>

---------

Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
… input arrays (praxis-proxy#619)

* fix(openai_responses): make input_items pagination usable for ID-less input arrays

Ordinary array `input` items (plain content-part objects) carry no
`id` field, so `first_id`/`last_id` in the input_items list response
stayed `null` even when `has_more` was true, leaving clients with no
`after` value to resume pagination.

Assign a stable synthetic id (`msg_{response_id}_input_{index}`) to
any input item missing one, keyed to its original stored position so
it stays stable regardless of sort order. IDs become the primary
pagination cursor; the existing numeric offset fallback in
`build_input_items_ok` now also covers the residual case where an
array entry isn't a JSON object and can't carry a synthetic id.

Signed-off-by: mkoushni <mkoushni@redhat.com>

* test(openai_responses): cover mixed existing/synthetic id pagination

Add a regression test for input arrays that mix items already
carrying an id with id-less items, verifying ensure_stable_ids
preserves the existing id and assigns a synthetic one only to the
id-less item, and that cursor pagination (after=<existing>, then
after=<synthetic>) resolves correctly across the mix.

Addresses praxis-bot review feedback on praxis-proxy#612.

Signed-off-by: mkoushni <mkoushni@redhat.com>

---------

Signed-off-by: mkoushni <mkoushni@redhat.com>
…raxis-proxy#650)

Bumps [github/codeql-action/analyze](https://github.com/github/codeql-action) from 4.37.3 to 4.37.4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@e4fba86...f205ea1)

---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…axis-proxy#652)

Bumps [github/codeql-action/init](https://github.com/github/codeql-action) from 4.37.3 to 4.37.4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@e4fba86...f205ea1)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* implement and integrate is_promotable_value

Signed-off-by: Harrison Stropkay <hstropka@redhat.com>

* add oversized_model_not_promoted_to_header_or_results_or_metadata to
model_rewrite/tests.rs

Signed-off-by: Harrison Stropkay <hstropka@redhat.com>

---------

Signed-off-by: Harrison Stropkay <hstropka@redhat.com>
Co-authored-by: Francisco Javier Arceo <farceo@redhat.com>
…search (praxis-proxy#493)

* feat(openai): add file_search_callout filter for hosted vector store search

Add the `openai_file_search_callout` filter for executing OpenAI
Responses API `file_search_call` output items against any vector
store API compatible backend.

The filter runs inside `iterative_request_router` so a model
response can trigger vector store search and another inference
within the same client request. vLLM backends that emit
`function_call(name=file_search)` instead of native
`file_search_call` are automatically translated before execution.

Key capabilities:
- Bounded fan-out (64 specs, 8-way concurrency)
- Cross-store ranked aggregation with max_num_results
- Citation tracking via ResponsesState.citation_files
- SSRF-safe URL validation at startup
- Fail-open (ignore) and fail-closed (reject) error policies
- Partial failure tracking with incomplete status

Authentication is delegated to upstream header injection or
cluster-level request_headers_to_add rather than per-filter config.

Closes praxis-proxy#29.

Signed-off-by: Sébastien Han <seb@redhat.com>

* fix(openai): preserve completed searches at deadline

Record synthetic deadline failures only for specs at or after the scheduler cursor. Completed concurrency chunks have already produced and merged their results, so marking them failed could incorrectly reject the request or downgrade the call to incomplete.

Also mark top-of-loop deadline handling as recorded to avoid duplicating failures after result sorting, and cover the scheduler boundary with a focused regression test.

Signed-off-by: Sébastien Han <seb@redhat.com>

* fix(file_search): inject shared SubRequestClient instead of private connector

Replace the hardcoded SubRequestConnector::new(4, None) in
file_search_callout with the shared server-level SubRequestClient,
following the same pattern as file_resolve, compact, and web_search.

Add from_config_with_client to FileSearchCalloutFilter and wire
closure-based registration in register.rs so the filter inherits
runtime.subrequest_pool_size and subrequest_max_connections from
the server config.

Signed-off-by: Sébastien Han <seb@redhat.com>

* fix(file_search): add forward_headers and align failure vocabulary

- Add `forward_headers` config field to forward request headers
  (e.g. Authorization) from the incoming request to the vector
  store callout, using the shared `ApiClient` header-forwarding
  mechanism already used by file_resolve.

- Replace custom `on_error: ignore|reject` with
  `callout_failure_mode: open|closed` using the shared
  `FailureMode` enum from `config_validation`, matching the
  vocabulary used by `openai_responses_compact`.

- Clarify `max_state_bytes` documentation: the filter and the
  enclosing iterative router may use different values because
  the smaller limit wins at runtime.

- Update example config, integration test config, generated
  filter docs, and all unit tests.

Signed-off-by: Sébastien Han <seb@redhat.com>

---------

Signed-off-by: Sébastien Han <seb@redhat.com>
Several OpenAI Responses filters carried a `max_body_bytes` knob that only
sized their `StreamBuffer` buffer. Because praxis core merges per-direction
body modes across a chain (keeping the largest) before clamping to the
listener's transport ceiling, that knob was silently widened whenever a
sibling filter declared a larger buffer — so it never reliably capped the
raw body it appeared to control (issue praxis-proxy#562).

Raw transport size is now governed exclusively by the pipeline's
`body_limits` (`max_request_bytes` / `max_response_bytes`), enforced once by
core before any filter runs. Per-filter limits are reserved for the body a
filter genuinely *produces*, which `body_limits` cannot see.

- Add shared `body_limits` helpers: `validate_size_limit` (names the actual
  field) and `reject_rewritten_body_too_large` (streaming-aware 413).
- Producer filters (doc_extract, file_resolve, openai_mcp_tool_resolve,
  openai_responses_proxy) enforce `max_rewritten_body_bytes` /
  `max_resolved_bytes` on the rewritten body only; buffers accept up to the
  64 MiB absolute ceiling.
- Pure-BodyMode filters (openai_responses_format,
  openai_responses_model_rewrite, agentic_loop, openai_mcp_dispatch,
  openai_tool_parse) drop the knob entirely and rely on `body_limits`.
- responses_to_chat_completions renames `max_body_bytes` ->
  `max_rewritten_body_bytes` to reflect that it bounds the translated body.

Removed fields are now rejected under `deny_unknown_fields` (a breaking
config change surfaced loudly at startup rather than silently ignored).

Add the body-size-limits example config and its functional integration
test; update example configs, filter docs, and unit/integration coverage.

Signed-off-by: Eoin Fennessy <efenness@redhat.com>

rh-pre-commit.version: 2.4.0
rh-pre-commit.check-secrets: ENABLED
@eoinfennessy
eoinfennessy requested review from a team and jland-redhat August 10, 2026 22:03
eoinfennessy and others added 2 commits August 10, 2026 23:11
…raxis-proxy#688)

extract_arguments used Value::to_string() which re-serializes
JSON string values, wrapping them in an extra layer of quotes and
escapes. Extract a shared normalize_arguments helper for the
string-vs-non-string dispatch used by both the approval and
execution paths.

Closes praxis-proxy#558

Signed-off-by: Sébastien Han <seb@redhat.com>

@praxis-bot praxis-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed all 47 changed files across the centralized body-size enforcement migration.

Approach: Sound. Raw transport size enforcement moves to body_limits (pipeline-level), while producer filters retain a renamed max_rewritten_body_bytes / max_resolved_bytes for the body they produce. This correctly separates transport caps from semantic caps.

Checked:

  • body_limits.rs: validate_size_limit correctly rejects zero and above-ceiling values; reject_rewritten_body_too_large delegates to the streaming-aware responses_error_rejection envelope. Tests cover zero, above-ceiling, at-ceiling, non-streaming JSON, and streaming SSE.
  • All pure-BodyMode filters (responses_format, model_rewrite, agentic_loop, mcp_dispatch, tool_parse) correctly drop max_body_bytes and declare StreamBuffer { max_bytes: Some(MAX_JSON_BODY_BYTES) }. Legacy max_body_bytes is rejected at parse time via deny_unknown_fields (verified tests exist for each).
  • All producer filters (doc_extract, file_resolve, mcp_tool_resolve, responses_proxy, responses_to_chat_completions) correctly rename to max_rewritten_body_bytes / max_resolved_bytes, validate through the centralized helper, and enforce only on the produced body.
  • Pipeline test (resolve_pipelines_transport_limit_governs_openai_responses_raw_body) proves the transport cap clamps the merged 64 MiB StreamBuffer declarations.
  • Integration test verifies both under-cap forwarding (200) and over-cap rejection (413).
  • Streaming detection is consistent across all filters (metadata from openai_responses_format.stream).
  • Error types and status codes are consistent: 413 / invalid_request_error for oversized rewritten bodies.
  • Example config, docs, and README updates are in sync.

No issues found at critical, large, or medium severity.

leseb and others added 4 commits August 11, 2026 14:37
* chore(deps): update Praxis crates to v0.5.2

Bump praxis-core, praxis-filter, praxis-protocol, praxis-tls, and
praxis from v0.5.1 to v0.5.2. Since v0.5.2 is not yet published on
crates.io, a temporary [patch.crates-io] section pins the crates to
the v0.5.2 git tag.

The new HttpFilterContext.metrics_route field (added in v0.5.2) is
initialized in both test context constructors (apis, filters).

Closes praxis-proxy#681

Signed-off-by: Sébastien Han <seb@redhat.com>

* fix(ci): use inline git deps instead of patch section

Replace the [patch.crates-io] section with inline git tag references
in workspace dependencies. The patch approach conflicted with the
test-praxis-main CI job (which appends its own patch section) and was
rejected by cargo-deny (unknown-git = "deny").

Add https://github.com/praxis-proxy/praxis to deny.toml allow-git
until v0.5.2 is published on crates.io.

Signed-off-by: Sébastien Han <seb@redhat.com>

---------

Signed-off-by: Sébastien Han <seb@redhat.com>
…criminator bodies (praxis-proxy#594)

* fix(classifier): treat POST /v1/responses as authoritative for no-discriminator bodies

A valid Responses create body that omits the discriminator fields the
body heuristics key on (input, prompt object, previous_response_id,
conversation) — e.g. `{"model":"gpt-5"}` — classified as unknown_json,
which could be rejected or misrouted despite being a legitimate
Responses create request.

Treat the POST /v1/responses endpoint as authoritative: when body
classification yields UnknownJson, promote it to Responses while keeping
the extracted routing facts. Bodies with positive signals for another
format (ChatCompletions / AnthropicMessages) and genuine parse failures
(NonJson / InvalidJson) are left untouched so real errors still reject.

Fixes praxis-proxy#413

Signed-off-by: Charlie Doern <cdoern@redhat.com>

* test(classifier): update integration tests for authoritative create endpoint

The unknown_json routing/reject integration tests posted a no-discriminator
body to POST /v1/responses, which now classifies as Responses. Retarget them
to a non-create path so they still exercise unknown_json handling, and add a
test asserting a no-discriminator create body routes to the responses cluster.

Signed-off-by: Charlie Doern <cdoern@redhat.com>

* docs(classifier): document authoritative create endpoint and add reject-path test

Address PR review feedback:

- Convert inline comments in test bodies to assertion messages, per the
  project convention of putting explanations in the assertion's message
  argument so they print on failure.
- Add `post_v1_responses_create_without_discriminator_not_rejected`,
  covering a valid no-discriminator create body under `on_invalid: reject`
  and closing the gap between the `continue`-mode and invalid-JSON tests.
- Document the authoritative `POST /v1/responses` classification in the
  `ResponsesFormatFilter` doc comment, regenerate the filter doc, and
  describe the behavior in the format-routing example config.

Signed-off-by: Charlie Doern <cdoern@redhat.com>

* fix(responses): format merged classifier imports

Signed-off-by: Charlie Doern <cdoern@redhat.com>

---------

Signed-off-by: Charlie Doern <cdoern@redhat.com>
* fix(ci): stabilize flaky vLLM integration job

Lower CPU memory reservation from 70% to 50% — the runner's ~15.6 GiB
total minus other processes (cargo build, OGX, docker) often left less
than the 10.93 GiB that 0.7 demanded, causing WorkerProc to crash on
startup. The Qwen3-0.6B model needs ~1.2 GiB so 0.5 (~7.8 GiB) is
plenty.

Also add a container liveness check in the readiness loop so a crashed
vLLM fails immediately instead of curling a dead container for 15
minutes.

Signed-off-by: Sébastien Han <seb@redhat.com>

* fix(ci): print full vLLM logs on container crash

Signed-off-by: Sébastien Han <seb@redhat.com>

---------

Signed-off-by: Sébastien Han <seb@redhat.com>

@praxis-bot praxis-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the merge commit (c332136) that integrates nine main-branch changes into this PR.

Merge brought in two unrelated features from main:

  1. mcp_dispatch: normalize_arguments / extract_arguments refactor (argument parsing, double-encoding fix). No interaction with body-size enforcement.
  2. responses/mod.rs: authoritative POST /v1/responses classification (discriminator-less create bodies classify as openai_responses instead of unknown_json). New classify_request logic, tests, example config docs, integration tests.

Checked:

  • mcp_dispatch/mod.rs merge: normalize_arguments and the body-size changes (MAX_JSON_BODY_BYTES ceiling, max_body_bytes field removal) coexist cleanly. No conflict artifacts.
  • responses/mod.rs merge: body::MAX_JSON_BODY_BYTES import and request_body_mode ceiling change merged correctly alongside the new is_responses_create import and classify_request rewrite.
  • responses/tests.rs: run_filter_raw now delegates to run_filter_raw_with_method defaulting to POST /v1/responses. The PR's legacy_max_body_bytes_rejected and body_mode_is_stream_buffer tests are unaffected because they exercise config parsing and body mode, not classification.
  • format-routing.yaml, openai_responses_format.md, integration test updates from main are documentation/config changes with no body-size overlap.
  • Infrastructure changes (Cargo.lock, deny.toml, CI workflow) are orthogonal.

Note: mergeable_state: dirty -- main is 9 commits ahead since this merge. The branch will need another merge or rebase before it can land.

No new issues found in the merge commit.

@praxis-bot praxis-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed all 48 changed files across the centralized body-size enforcement migration.

Approach: Sound. Separating raw transport caps (body_limits) from per-filter produced-body caps (max_rewritten_body_bytes / max_resolved_bytes) is the correct architecture. The old max_body_bytes knob was misleading because core merged per-direction body modes across the chain before clamping to the transport ceiling, making per-filter raw caps unreliable.

Checked:

  • body_limits.rs helpers: validate_size_limit correctly rejects zero and above-ceiling values; reject_rewritten_body_too_large builds streaming-aware 413s via the shared responses_error_rejection envelope. Unit tests cover all branches.
  • All pure-BodyMode filters (responses_format, model_rewrite, agentic_loop, mcp_dispatch, tool_parse) correctly drop max_body_bytes and declare StreamBuffer { max_bytes: Some(MAX_JSON_BODY_BYTES) }. Legacy field rejected via deny_unknown_fields with test coverage for each.
  • All producer filters (doc_extract, file_resolve, mcp_tool_resolve, responses_proxy, responses_to_chat_completions) correctly rename to max_rewritten_body_bytes / max_resolved_bytes, validate through validate_size_limit, and enforce only on the produced body.
  • file_resolve: new max_resolved_bytes properly decouples the per-file content limit from the total rewritten body limit. Previously both were overloaded onto max_body_bytes. Tests verify independence (max_resolved_bytes_bounds_individual_content_independent_of_rewritten_limit).
  • mcp_tool_resolve: new ResolveError::RewrittenTooLarge variant added with 413 mapping in resolve_error_rejection. Previously this filter had no rewritten body size check at all -- this is a genuine improvement.
  • Raw body checks removed from doc_extract and file_resolve (reject_raw_body_too_large) -- correctly delegated to the pipeline transport cap.
  • Pipeline test (resolve_pipelines_transport_limit_governs_openai_responses_raw_body) proves the 64 MiB StreamBuffer declarations are clamped to body_limits.max_request_bytes.
  • Integration test covers both under-cap forwarding (200) and over-cap rejection (413).
  • Streaming detection is consistent across all producer filters (openai_responses_format.stream metadata).
  • Error types and status codes are consistent: 413 / invalid_request_error for oversized rewritten bodies.
  • Example config, filter docs, and README updates are in sync.

One medium observation noted inline.


serialized.commit(body, filter_name, "tools");
if serialized.len() > max_rewritten_body_bytes {
debug!(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium / consistency: This new oversized-body rejection path uses debug!, while doc_extract and file_resolve use warn! for the identical semantic event (rewritten body exceeds configured limit). At default log levels operators would see warnings for doc_extract/file_resolve rejections but miss mcp_tool_resolve rejections.

Note: responses_proxy and responses_to_chat_completions also use debug! for their equivalent paths, so the inconsistency is partially pre-existing. But since this PR centralizes body-size enforcement, it is an opportunity to align all producer filters on one level.

Suggestion:

warn!(
    actual = serialized.len(),
    limit = max_rewritten_body_bytes,
    "rewritten request body exceeds configured limit"
);

This would also align the tracing field names (actual/limit vs body_bytes/max_bytes) with the convention used in the other two producer filters.

@praxis-bot

Copy link
Copy Markdown
Collaborator

We haven't heard back from you on this in some time, so we're going to mark it closed for now. However, if you're still interested in pushing this forward please don't hesitate to re-open and update 🖖

@leseb

leseb commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

@eoinfennessy

@leseb leseb reopened this Aug 31, 2026
@leseb
leseb requested a review from shaneutt as a code owner August 31, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

Clarify and centralize body-size enforcement across OpenAI Responses filter chains