Budget Overflow Streaming
Demonstrates the terminal-failure contract when an upstream Responses SSE stream overflows the request-wide retained-payload budget AFTER the client stream is already committed
Versions marked “overview” do not contain this page. Selecting one opens that version’s documentation overview.
Category: Setup-dependent integration
Task: Demonstrates the terminal-failure contract when an upstream Responses SSE stream overflows the request-wide retained-payload budget AFTER the client stream is already committed
Prerequisites: The external service, credentials, or certificates referenced by this configuration.
This configuration comes from the selected release. The example has not been run here; external services are not bundled.
Download the source file.
# Committed-stream retained-payload overflow (Responses streaming)
# Requires `--features openai-agentic-loop` (experimental, off by default; it
# transitively enables openai-responses) because this chain uses openai_agentic_loop.
#
# Demonstrates the terminal-failure contract when an upstream Responses SSE
# stream overflows the request-wide retained-payload budget AFTER the client
# stream is already committed.
#
# `openai_agentic_loop.max_retained_bytes` publishes the request-wide budget
# policy (`AgenticBudgetPolicy`). `openai_responses_request` installs a
# per-request `SimpleBudget` from that policy, sized here small enough to admit
# the create body and the first `response.created` frame (which commits the
# `text/event-stream` response to the client) but to reject a later oversized
# output frame.
#
# When `openai_stream_events` charges that oversized post-commit chunk and the
# budget rejects it, the logical stream is poisoned: the loop owner emits one
# terminal SSE `error` frame and suppresses `response.completed` and the
# `[DONE]` sentinel, stops processing later frames, and skips successful
# persistence. There is no second commitment authority on the wire.
#
# This is the streaming counterpart to the buffered 413/502 retained-payload
# rejection: once the stream is committed the terminal can only be an SSE
# `error` event, never a buffered JSON error.
#
# Example:
#
# curl -N http://localhost:8080/v1/responses \
# -H "Content-Type: application/json" \
# -d '{"model":"gpt-4.1","input":"Say hello","stream":true}'
listeners:
- name: ai-gateway
address: "127.0.0.1:8080"
filter_chains: [responses-budget-overflow-stream]
filter_chains:
- name: responses-budget-overflow-stream
filters:
# Publishes the typed operation consumed by openai_responses_request.
- filter: ai_operation
# Parses the create body and installs the per-request retained-payload
# SimpleBudget from the AgenticBudgetPolicy published by
# openai_agentic_loop. A create body larger than the budget is rejected
# here with a buffered 413 before any backend request.
- filter: openai_responses_request
on_invalid: reject
- filter: iterative_request_router
initial_step: inference
max_iterations: 2
# The IRR's 30s default is too short for production model streams.
timeout_ms: 360000
steps:
- name: inference
filters:
# Composes the inference SSE stream into one logical Responses
# lifecycle and owns the terminal frame. Charges each raw chunk
# against the retained-payload budget; a rejected post-commit chunk
# poisons the stream so the terminal becomes an SSE error.
- filter: openai_stream_events
# Publishes the AgenticBudgetPolicy and owns the single terminal
# decision. A tiny retained budget admits the create body and the
# committing response.created frame but rejects a later output
# frame after its weighted wire and parsing charges exceed the
# remaining budget.
- filter: openai_agentic_loop
max_infer_iters: 1
# Tiny retained budget. It admits the small create body and the
# committing response.created frame but rejects the post-commit
# output frame after its weighted wire and parsing charges exceed
# the remaining budget.
max_retained_bytes: 131072
# Selects typed streaming automatically when the effective outbound
# body carries `"stream": true`.
- filter: openai_responses_proxy
- filter: headers
request_set:
- name: Content-Type
value: application/json
- filter: router
routes:
- path: "/v1/responses"
cluster: "inference-backend"
- filter: load_balancer
clusters:
- name: "inference-backend"
read_timeout_ms: 300000
endpoints:
- "127.0.0.1:3001"
on_result:
- filter: openai_agentic_loop
key: action
value: loop
next: inference
- default: true
done: true
insecure_options:
allow_private_endpoints: true # example proxies to local backends