revert: drop LITELLM_CAPTURE_VENDOR_SESSION_HEADERS flag

Generic x-<vendor>-session-id header capture is a new feature and only
runs *after* the explicit x-litellm-trace-id / x-litellm-session-id
checks, so it does not change behavior for any existing caller that was
already using the LiteLLM headers — no backwards-incompatibility to gate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Krrish Dholakia 2026-04-18 13:17:49 -07:00
parent f123e558ca
commit a1a7312d1d
2 changed files with 11 additions and 96 deletions

View file

@ -149,23 +149,6 @@ def _extract_generic_session_id_from_headers(
return None
def _is_generic_session_header_capture_enabled() -> bool:
"""
Check whether capturing generic ``x-<vendor>-session-id`` headers as the
LiteLLM trace/session id is opted-in via env var.
Defaults to False to preserve backwards compatibility existing deployments
that send vendor session-id headers for non-LiteLLM purposes must not have
those values silently re-used as the call's ``litellm_trace_id`` /
``litellm_session_id`` (which would regroup their spend logs and traces).
Set ``LITELLM_CAPTURE_VENDOR_SESSION_HEADERS=true`` to enable.
"""
from litellm.secret_managers.main import get_secret_bool
return bool(get_secret_bool("LITELLM_CAPTURE_VENDOR_SESSION_HEADERS", False))
def get_chain_id_from_headers(headers: Optional[Dict[str, str]]) -> Optional[str]:
"""
Extract chain id for call chaining from request headers.
@ -173,10 +156,8 @@ def get_chain_id_from_headers(headers: Optional[Dict[str, str]]) -> Optional[str
Priority order:
1. ``x-litellm-trace-id`` (explicit, highest priority)
2. ``x-litellm-session-id`` (explicit)
3. (OPT-IN) Any ``x-<vendor>-session-id`` header whose value looks like a
session id. E.g. ``x-claude-code-session-id``. Only consulted when the
``LITELLM_CAPTURE_VENDOR_SESSION_HEADERS`` env var is truthy keeping
the default behavior backwards-compatible.
3. Any ``x-<vendor>-session-id`` header whose value looks like a session id
(alphanumeric / UUID, at least 8 chars). E.g. ``x-claude-code-session-id``.
Header keys are matched case-insensitively so this works with raw header
dicts from any transport.
@ -187,14 +168,11 @@ def get_chain_id_from_headers(headers: Optional[Dict[str, str]]) -> Optional[str
if not headers:
return None
normalized = {k.lower(): v for k, v in headers.items() if isinstance(k, str)}
explicit = normalized.get("x-litellm-trace-id") or normalized.get(
"x-litellm-session-id"
return (
normalized.get("x-litellm-trace-id")
or normalized.get("x-litellm-session-id")
or _extract_generic_session_id_from_headers(normalized)
)
if explicit:
return explicit
if _is_generic_session_header_capture_enabled():
return _extract_generic_session_id_from_headers(normalized)
return None
def safe_add_api_version_from_query_params(data: dict, request: Request):

View file

@ -1213,15 +1213,8 @@ def test_add_litellm_metadata_from_request_headers_both_headers_trace_id_precede
assert data["litellm_trace_id"] == "trace-value"
def test_add_litellm_metadata_from_request_headers_generic_session_id_header(
monkeypatch,
):
"""
A generic x-<vendor>-session-id header is used when no explicit litellm
header is set only when the opt-in env var is enabled.
"""
monkeypatch.setenv("LITELLM_CAPTURE_VENDOR_SESSION_HEADERS", "true")
def test_add_litellm_metadata_from_request_headers_generic_session_id_header():
"""A generic x-<vendor>-session-id header is used when no explicit litellm header is set."""
headers = {"x-claude-code-session-id": "e96634a3-fa28-4083-b354-55542e2dca01"}
data = {"metadata": {}}
LiteLLMProxyRequestSetup.add_litellm_metadata_from_request_headers(
@ -1232,31 +1225,8 @@ def test_add_litellm_metadata_from_request_headers_generic_session_id_header(
assert data["litellm_trace_id"] == "e96634a3-fa28-4083-b354-55542e2dca01"
def test_add_litellm_metadata_from_request_headers_generic_session_id_header_ignored_by_default(
monkeypatch,
):
"""
Default (flag off): a generic x-<vendor>-session-id header must NOT be
treated as a litellm chain id prior users who sent such headers for
non-LiteLLM purposes continue to work unchanged.
"""
monkeypatch.delenv("LITELLM_CAPTURE_VENDOR_SESSION_HEADERS", raising=False)
headers = {"x-claude-code-session-id": "e96634a3-fa28-4083-b354-55542e2dca01"}
data = {"metadata": {}}
LiteLLMProxyRequestSetup.add_litellm_metadata_from_request_headers(
headers=headers, data=data, _metadata_variable_name="metadata"
)
assert "litellm_session_id" not in data
assert "litellm_trace_id" not in data
def test_add_litellm_metadata_from_request_headers_explicit_header_beats_generic(
monkeypatch,
):
def test_add_litellm_metadata_from_request_headers_explicit_header_beats_generic():
"""Explicit x-litellm-trace-id wins over a generic x-*-session-id header."""
monkeypatch.setenv("LITELLM_CAPTURE_VENDOR_SESSION_HEADERS", "true")
headers = {
"x-litellm-trace-id": "explicit-trace-id-value",
"x-claude-code-session-id": "e96634a3-fa28-4083-b354-55542e2dca01",
@ -1269,16 +1239,10 @@ def test_add_litellm_metadata_from_request_headers_explicit_header_beats_generic
assert data["litellm_trace_id"] == "explicit-trace-id-value"
def test_get_chain_id_from_headers_generic_vendor_session_id(monkeypatch):
"""
Generic ``x-<vendor>-session-id`` capture is opt-in via
``LITELLM_CAPTURE_VENDOR_SESSION_HEADERS``; when enabled, valid values are
picked up and explicit headers still take precedence.
"""
def test_get_chain_id_from_headers_generic_vendor_session_id():
"""get_chain_id_from_headers picks up any x-<vendor>-session-id with a valid value."""
from litellm.proxy.litellm_pre_call_utils import get_chain_id_from_headers
monkeypatch.setenv("LITELLM_CAPTURE_VENDOR_SESSION_HEADERS", "true")
assert (
get_chain_id_from_headers(
{"x-claude-code-session-id": "e96634a3-fa28-4083-b354-55542e2dca01"}
@ -1300,33 +1264,6 @@ def test_get_chain_id_from_headers_generic_vendor_session_id(monkeypatch):
)
def test_get_chain_id_from_headers_generic_vendor_session_id_disabled_by_default(
monkeypatch,
):
"""
Generic vendor session-id capture must stay OFF by default otherwise
existing deployments that send such headers for non-LiteLLM purposes would
have their spend logs / traces silently regrouped under those IDs.
"""
from litellm.proxy.litellm_pre_call_utils import get_chain_id_from_headers
monkeypatch.delenv("LITELLM_CAPTURE_VENDOR_SESSION_HEADERS", raising=False)
# Without the opt-in env var, generic vendor session headers are ignored.
assert (
get_chain_id_from_headers(
{"x-claude-code-session-id": "e96634a3-fa28-4083-b354-55542e2dca01"}
)
is None
)
# Explicit litellm headers still work (unchanged behavior).
assert (
get_chain_id_from_headers({"x-litellm-trace-id": "explicit-id-value"})
== "explicit-id-value"
)
def test_get_internal_user_header_from_mapping_returns_expected_header():
mappings = [
{"header_name": "X-OpenWebUI-User-Id", "litellm_user_role": "internal_user"},