From 423ed0f07f706b0555547a0f3512ea0402221207 Mon Sep 17 00:00:00 2001 From: rltakashige Date: Thu, 19 Feb 2026 18:29:34 +0000 Subject: [PATCH] Strip Claude headers to improve prefix cache hit rates (#1552) ## Motivation Our hits are really bad at the moment (0.2%). This PR makes it 98.5% on average. ## Changes Also adds an example for how to run Claude using Exo. ## Why It Works Claude sends some billing and session headers that change with each message. ## Test Plan ### Manual Testing Works in manual testing. --- src/exo/master/adapters/claude.py | 19 +++++++++++++++++++ tmp/config_examples/claude_code.sh | 8 ++++++++ 2 files changed, 27 insertions(+) create mode 100755 tmp/config_examples/claude_code.sh diff --git a/src/exo/master/adapters/claude.py b/src/exo/master/adapters/claude.py index d9d52496..d5246bbc 100644 --- a/src/exo/master/adapters/claude.py +++ b/src/exo/master/adapters/claude.py @@ -1,6 +1,7 @@ """Claude Messages API adapter for converting requests/responses.""" import json +import re from collections.abc import AsyncGenerator from typing import Any @@ -61,6 +62,22 @@ def _extract_tool_result_text(block: ClaudeToolResultBlock) -> str: return "".join(sub_block.text for sub_block in block.content) +# Matches "x-anthropic-billing-header: ...;" (with optional trailing newline) +# or similar telemetry headers that change every request and break KV prefix caching. +_VOLATILE_HEADER_RE = re.compile(r"^x-anthropic-[^\n]*;\n?", re.MULTILINE) + + +def _strip_volatile_headers(text: str) -> str: + """Remove Anthropic billing/telemetry headers from system prompt text. + + Claude Code prepends headers like 'x-anthropic-billing-header: cc_version=...; + cc_entrypoint=...; cch=...;' that contain per-request content hashes. These + change every request and break KV prefix caching (the prefix diverges at ~20 + tokens instead of matching thousands of conversation tokens). + """ + return _VOLATILE_HEADER_RE.sub("", text) + + def claude_request_to_text_generation( request: ClaudeMessagesRequest, ) -> TextGenerationTaskParams: @@ -73,6 +90,8 @@ def claude_request_to_text_generation( instructions = request.system else: instructions = "".join(block.text for block in request.system) + + instructions = _strip_volatile_headers(instructions) chat_template_messages.append({"role": "system", "content": instructions}) # Convert messages to input diff --git a/tmp/config_examples/claude_code.sh b/tmp/config_examples/claude_code.sh new file mode 100755 index 00000000..685d0a27 --- /dev/null +++ b/tmp/config_examples/claude_code.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# Run Claude Code against a local exo cluster! (Here, GPT OSS 120B) +ANTHROPIC_BASE_URL="http://localhost:52415/" \ + ANTHROPIC_AUTH_TOKEN="dummy" \ + ANTHROPIC_MODEL="mlx-community/gpt-oss-120b-MXFP4-Q8" \ + ANTHROPIC_SMALL_FAST_MODEL="mlx-community/gpt-oss-120b-MXFP4-Q8" \ + CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \ + claude