Skip to content

feat(proxy): optional SSE keepalive comments during streaming silence#32763

Closed
henricook wants to merge 2 commits into
BerriAI:litellm_internal_stagingfrom
henricook:feat/sse-keepalive-heartbeat
Closed

feat(proxy): optional SSE keepalive comments during streaming silence#32763
henricook wants to merge 2 commits into
BerriAI:litellm_internal_stagingfrom
henricook:feat/sse-keepalive-heartbeat

Conversation

@henricook

@henricook henricook commented Jul 10, 2026

Copy link
Copy Markdown

Relevant issues

Addresses #14953 (closed not-planned) — reopening the ask with a working implementation, tests, and e2e proof.

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Screenshots / Proof of Fix

Real call through the proxy running at commit e9f4177: Azure gpt-5.6-sol, reasoning.effort=high, LITELLM_SSE_KEEPALIVE_INTERVAL_SECONDS=3. The model reasons silently for ~30s and the keepalives land exactly in that gap:

$ curl -sS -N http://127.0.0.1:20488/v1/responses -H "Authorization: Bearer sk-..." \
    -d '{"model":"gpt-5.6-sol","input":"Think very carefully: how many primes below 500 have a digit sum of exactly 10?","reasoning":{"effort":"high"},"stream":true,"max_output_tokens":4000}'

data: {"type":"response.created", ...}
data: {"type":"response.in_progress", ...}
: keepalive
: keepalive
: keepalive        <- 10 keepalives over ~30s of reasoning silence
...
data: {"type":"response.output_item.added", ...}
data: {"type":"response.output_text.done", ... correct answer ...}
data: {"type":"response.completed", ...}

Without this, the same silence exceeds e.g. Envoy's 300s default stream_idle_timeout on longer thinks and the connection is killed mid-turn. We run this in production (LiteLLM gateway fronting Azure GPT-5.6 for Codex CLI users behind a Cilium/Envoy ingress) — the stream disconnected before completion retry loops disappear.

Tests: pytest tests/test_litellm/proxy/test_common_request_processing.py — 169 passed (5 new in TestSSEKeepalive).

Type

🆕 New Feature

Changes

Reasoning models (gpt-5.x and o-series on /v1/responses) stream nothing
while thinking, so connections sit wire-silent for minutes. Idle-timeout
middleboxes between the client and LiteLLM (nginx: 60s default,
Envoy/Cilium: 300s, cloud load balancers) then kill the stream mid-turn.
Clients like Codex CLI surface this as 'stream disconnected before
completion' retry loops.

Opt-in via LITELLM_SSE_KEEPALIVE_INTERVAL_SECONDS (default 0 = off).
When enabled, SSE streaming responses emit a spec-ignorable comment
line (': keepalive') whenever the upstream generator is silent past
the interval. Wraps after first-chunk error sniffing, so error-to-JSON
status mapping is unaffected; disabled path is byte-identical.
@CLAassistant

CLAassistant commented Jul 10, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.20690% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/proxy/common_request_processing.py 86.20% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

CI's ruff-format check covers whole files touched by the diff; this file
had pre-existing unformatted hunks that now fall under it.
@henricook

Copy link
Copy Markdown
Author

Companion docs PR: BerriAI/litellm-docs#531 (the documentation / code-quality checks validate env keys against that repo's config_settings.md, so they stay red here until it lands). lint fixed in 1651bbf.

@codspeed-hq

codspeed-hq Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing henricook:feat/sse-keepalive-heartbeat (1651bbf) with litellm_internal_staging (bf02a4a)

Open in CodSpeed

@henricook henricook closed this Jul 10, 2026
@henricook

Copy link
Copy Markdown
Author

Discovered that I could force codex to request summaries with model_reasoning_summary = "auto" - and that Azure supports it.

@henricook henricook deleted the feat/sse-keepalive-heartbeat branch July 10, 2026 12:08
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.

2 participants