Направлення трафіку Claude Code за допомогою заголовків замість читання запиту
Дізнайтеся, як заголовки підказок гейтвею з опційною участю Claude Code дозволяють гейтвею ШІ пріоритизувати, контролювати бюджет та керувати кешами на основі метаданих запиту, не аналізуючи тіло запиту.
Коли компанія надсилає трафік Claude Code через шлюз LLM, цей шлюз мусить приймати рішення щодо кожного запиту перед його пересиланням: який використовувати канал передачі даних, до якої черги додати запит, за яким лімітом швидкості його обробити та який пріоритет призначити. До недавнього часу єдиним джерелом інформації для цих рішень було тіло запиту, тобто ваші запити, вміст файлів, результати роботи інструментів та CLAUDE.md. Набір заголовків запиту з можливістю їх використання, доданий у нещодавньому оновленні Claude Code, переміщує цю інформацію у заголовки запиту. Нижче ви побачите, що можна визначити за допомогою кожного заголовка, як змінюється робота проксі при їх використанні та де все одно не варто їм довіряти.
Чому шлюзи змушені читати ваші запити
Перевірка тіла повідомлення — це не теоретичне питання; саме так працює багато маршрутизаторів сьогодні. Семантичні маршрутизатори, такі як vLLM Semantic Router, витягують запит користувача, інтегрують його за допомогою моделі у стилі BERT та порівнюють вектор із векторами контрольних завдань для класифікації запиту. Маршрутизатори, оптимізовані для зменшення затримки передачі даних, можуть визначити назву моделі приблизно з першого кілобайта та передавати решту даних у потоці, але будь-який маршрутизатор, якому потрібна класифікація, змушений буферизувати та перевіряти весь об’єм даних.
Саме ця перевірка є ключовою функцією продукту, і вона також робить шлюз набагато більш чутливим межею довіри, ніж може видатися з його скромної назви. Він бачить та потенційно зберігає все, що надсилає агент розробника.
У версії Claude Code 2.1.273, датованій 15 вересня 2026 року у чат-логу, було додано п’ять заголовків, призначених для операторів шлюзів. Разом вони скоріше є мінімальними метаданими, необхідними шлюзу для функціонування як планувальника, ніж функцією для забезпечення прозорості.
Обмеження початкових заголовків ідентифікаторів
До версії 2.1.273 посібник з сумісності для шлюзів описував три заголовки Claude Code, усі з яких були ідентифікаторами:
+--------------------------------+---------------------------------+
| HEADER | WHAT IT IS |
+--------------------------------+---------------------------------+
| x-claude-code-session-id | which session |
| x-claude-code-agent-id | which subagent (if any) |
| x-claude-code-parent-agent-id | which agent spawned it |
+--------------------------------+---------------------------------+
|
v
good for GROUPING after the fact
useless for DECIDING before forwarding
Документація передбачає їх використання для агрегації: ідентифікатор сеансу дозволяє групувати все, що надіслано під час сеансу, без необхідності парсингу тіла запиту, а ідентифікатор агента у поєднанні з ідентифікатором сеансу дозволяє присвоювати витрати агентам, які працюють паралельно. Це є частиною бухгалтерського обліку. Цього достатньо для панелі керування витратами, але недостатньо для планування. Знання про те, що запит надійшов з сеансу abc та агента def, нічого не говорить про те, наскільки він буде дорогим, скільки часу займе або чи може система дозволити собі чекати. Тож будь-який шлюз, який хотів би бути розумнішим за простий лічильник, змушений був би відкривати тіло запиту.
П’ять нових заголовків-підказок
Згідно з чартом змін, у версії 2.1.273 було додано п’ять заголовків, усі вони активуються разом із параметром CLAUDE_CODE_GATEWAY_HINT_HEADERS=1. Два з них описують викликаючий клієнт (x-claude-code-agent-type та x-claude-code-request-class), один — нещодавні таймінги (x-claude-code-prev-tool-durations), а ще одна пара — переписування контексту (x-claude-code-context-compacted разом із x-claude-code-compaction).
Важлива застереження: на момент написання таблиця заголовків запиту в посібнику з сумісності гейтвеїв все ще містить лише три ідентифікаційні заголовки, а змінна відсутня у довідці щодо змінних середовища. Назви заголовків взяті з журналу змін, але формати їхніх значень поки не задокументовані. Усе, що наведено нижче, описує, як кожен заголовок дозволяє гейтвею приймати рішення, а не гарантований формат передачі даних. Перевіряйте власний трафік перед тим, як покладатися на конкретні значення, та ознайомтесь з актуальною документацією — вона може вже бути оновлена.
Груповано за рішеннями, які кожен з них дозволяє приймати:
+---------------------------+------------------------------------------+
| HEADER | DECISION IT UNBLOCKS AT THE EDGE |
+---------------------------+------------------------------------------+
| request-class | is this a real turn, or a small |
| | internal call? -> priority, cheap pool |
+---------------------------+------------------------------------------+
| agent-type | which kind of subagent is asking |
| | -> per-agent-type budgets and quotas |
+---------------------------+------------------------------------------+
| prev-tool-durations | how long the last tools took |
| | -> timeout and retry window sizing |
+---------------------------+------------------------------------------+
| compaction | this turn IS the summarization call |
| | -> never count it as user latency |
+---------------------------+------------------------------------------+
| context-compacted | the prefix just changed under you |
| | -> do not expect a cache hit this turn |
+---------------------------+------------------------------------------+
Коротко кажучи:
- request-class відокремлює справжні етапи розмови від невеликих внутрішніх запитів, що дозволяє надати пріоритет першим та надсилати другі до дешевшого пулу.
- agent-type визначає, який тип підагента здійснює запит, що уможливлює встановлення бюджетів та квот за типом агента.
- prev-tool-durations повідомляє про тривалість нещодавньої роботи інструментів, що допомагає визначити таймаути та інтервали повторних спроб.
- compaction позначає запит, який сам виконує узагальнення, тож він ніколи не має враховуватися у показниках затримки для користувача.
- context-compacted сигналізує про те, що префікс розмови щойно було переписано, тому очікувати доступу з кешу не варто.
Усе це не є новою інформацією. Гейтвей може вже визначити клас запиту, порівнявши повний системний промпт Claude Code зі скороченим промптом класифікатора, визначити тип агента з розділу системного промпта, присвяченого агенту, та виявити ступінь компактності за структурою масиву повідомлень. Заголовки не розкривають жодної додаткової інформації про вас. Змінюється лише ціна знань: замість обробки до мегабайта вихідного коду гейтвей читає короткий рядок з заголовків.
Та сама правило маршрутизації, до та після
Візьмемо конкретну мету: направити підсумовування фонової інформації до дешевшого пулу. Без підказок проксі повинен зберігати в буфері та обробляти розмову, а потім вгадувати її зміст:
// BEFORE: the router has to read the conversation to classify it
const body = await readEntireBody(req); // buffers the whole prompt
const parsed = JSON.parse(body); // your files are now in gateway memory
const sys = flattenSystemBlocks(parsed.system);
const isBackground =
sys.includes("summarize the conversation") ||
parsed.messages.length > COMPACT_THRESHOLD;
і лише тоді передавати збережений в буфері текст:
route(isBackground ? "cheap-pool" : "interactive-pool", body);
У цього підходу є три проблеми, від найменш серйозної до найсерйознішої. Буферування всього тексту знищує затримку стрімінгу. Пошук за формулюванням запиту є крихким, оскільки це формулювання змінюється між версіями Claude Code. Найгірше те, що весь текст вашого репозиторію тепер знаходиться у пам’яті процесу шару маршрутизації, у його дампах пам’яті та, ймовірно, у журналах подій — у місці, яке не показано на жодній архітектурній діаграмі та яке ніхто не подумав захистити.
За допомогою заголовків-підказок маршрутизатор читає два значення з конверта:
// AFTER: the router decides on the envelope and never touches the body
const cls = req.headers["x-claude-code-request-class"];
const comp = req.headers["x-claude-code-compaction"];
і маршрутизує незмінений потік запитів. Як зазначено у примітці до фрагмента коду, літеральні рядки значень є ілюстративними, оскільки формат ще не задокументований:
// value strings below are illustrative: confirm them against your own
// traffic, since the wire format is not documented yet
const isBackground = Boolean(comp) || cls === "background";route(isBackground ? "cheap-pool" : "interactive-pool", req); // streams through
Немає буферизації, немає обробки JSON та жодних запитів не зберігаються в пам’яті. Керівництво з сумісності вже дозволяє таку модель: окрім anthropic-workspace-id, anthropic-beta та anthropic-version, заголовки описуються як дані, які гейтвей може використовувати для відстеження, атрибуції чи маршрутизації, і не є обов’язковими до передачі. Ці підказки розроблені так, щоб залишатися на рівні гейтвею; оскільки модель їх ніколи не бачить, вони можуть залишатися примітивними та дешевими у реалізації.
Пара значень для стиснення є сигналом кешування
Два з цих заголовків здаються зайвими, але відповідають на різні запитання. Перший, x-claude-code-compaction, встановлюється під час самого запиту, який генерує резюме. Другий, x-claude-code-context-compacted, з’являється під час наступних запитів, після того, як вже відбулося стиснення.
Ця різниця має значення, коли ви працюєте з кешем. Ключі кешу для запитів — це префікси, утворені з інструментів, потім системного запиту та повідомлень, тож будь-яка зміна у частині, що знаходиться спереду, робить недійсним усе, що йде після неї. Записи в кеш також коштують дорожче, ніж його читання, тому зайві записи є суцільними витратами. Компактування є найбільшим фактором, який робить дані недійсними під час звичайної сесії: воно замінює накопичену історію на короткий огляд, що за визначенням створює абсолютно новий префікс.
turn N turn N+1 (compaction) turn N+2
+---------+ +------------------+ +------------------+
| prefix | | compaction: 1 | | context- |
| stable | --> | rewrites history | --> | compacted: 1 |
| cache | | EXPECT A MISS | | new prefix is |
| hits | | bill it as | | now the stable |
+---------+ | background | | one, re-warm it |
+------------------+ +------------------+
Шлюз, який підтримує власну кеш-пам’ять, але нічого не знає про процедуру компактування, поводиться якомога гірше під час неї: він виконує повне пошукове запитання, не знаходить потрібної інформації, зберігає запис для префіксу, який стане застарілим вже через один крок, а потім повідомляє про зниження частки успішних пошуків, що потім розглядається як дефект. Завдяки заголовкам він може пропустити пошук під час запиту на компактування, віднести цей запит до фонових операцій та навмисно «розігріти» новий префікс у наступному кроці, коли він стане стабільним.
Підказки — це твердження клієнта, а не облікові дані
І журнал змін, і назви змінних використовують ці заголовки підказок, і тут важлива саме назва. Підказка — це неперевірене твердження, зроблене клієнтом. Значення x-claude-code-request-class — це те, що Claude Code вирішує надіслати; жоден верхній компонент його не перевіряє.
Припустимо, що ваш шлюз надає преференції запитам, позначеним як фонові — зі зниженими тарифами, більшими квотами чи послабленими обмеженнями на кількість запитів. Тоді рядок даних, наданий клієнтом, тихо приймає рішення щодо авторизації. Розробник, який змінює своє середовище роботи, або будь-хто, хто запускає невеликий локальний проксі перед шлюзом, може обрати ту позначку, яка забезпечує найбільш лояльне ставлення. Підказки є гарними даними для формування черг, прийняття рішень щодо кешу та вимірювання затримки, але ніколи не для визначення того, які привілеї має користувач.
Друга практична проблема — це впровадження. Заголовки вимкнені, якщо їх не увімкнути явно, що є правильним вибором для метаданих, які розкривають структуру сеансу середньому пристрою. У поєднанні з їх відсутністю у посиланні на змінну середовища на момент написання, ймовірно, лише деякі інсталяції матимуть їх увімкненими. У організації їх зазвичай доведеться впроваджувати через керовані налаштування адміністратором, який помітив окрему рядок у журналі змін.
План впровадження для операторів шлюзів
Якщо ваша команда керує шлюзом для трафіку Claude Code, обережний підхід до впровадження виглядає так:
- Увімкніть
CLAUDE_CODE_GATEWAY_HINT_HEADERS=1для невеликої групи учасників пілотування. - Записуйте всі п’ять заголовків протягом приблизно тижня, не вживаючи щодо них жодних дій.
- Порівняйте їхні значення з рішеннями, які приймає ваш поточний класифікатор для аналізу тексту.
Перевагою є значно менший радіус впливу: код джерела ваших розробників більше не мусить проходити через пам’ять шару маршрутизації, і це коштує лише однієї змінної середовища.
Підсумок
Самі заголовки є специфічними для Claude Code, але урок дизайну застосовується до будь-якої платформи агентів. Будь-який шар, розташований перед агентом, має класифікувати запити перед їх передачею, і для цього існує лише два способи: вивести відповідь з контенту запиту або отримати її у вигляді явних метаданих. Виведення завжди працює, але завжди залишає копію конфіденційного контенту в компоненті, який не мав підстав його зберігати. Канал явних метаданих вимагає більше початкових зусиль у дизайні, але це єдиний варіант, коли проміжник може правильно направляти запити, не отримуючи при цьому самих даних. Щоб дізнатися більше про те, що надає гейтвей, перегляньте огляд LLM-гейтвею у документації Claude Code.