SpyBara
Go Premium

claude-apps-gateway-config.md 2026-11-12 23:02 UTC to 2026-11-13 23:02 UTC

This page contains 263 additions and 240 deletions.

2026
Mon 2 23:57 Wed 4 23:59 Fri 6 23:01 Mon 9 23:02 Wed 11 22:59 Fri 13 23:02

Конфигурация Claude apps gateway

Справочник по каждому параметру gateway.yaml: listener и TLS, OIDC, session, хранилище Postgres, upstreams Amazon Bedrock, Claude Platform на AWS, Agent Platform Google Cloud и Microsoft Foundry, маршрутизация моделей, управляемые политики и телеметрия.

Развёртывание Claude apps gateway настраивается одним файлом YAML, обычно gateway.yaml. Файл определяет всё, что делает gateway: где он слушает, как разработчики входят в систему, куда идёт вывод, и какие политики и телеметрия применяются. Эта страница — справочник по каждому параметру в этом файле.

Чтобы написать свой первый файл, начните с quickstart, который создаёт минимальную рабочую конфигурацию и запускает её. Когда у вас будет конфигурация, которой вы довольны, руководство по развёртыванию охватывает контейнеризацию и размещение на Kubernetes, Cloud Run или вашей собственной платформе.

Gateway читает файл один раз при запуске с помощью claude gateway --config /path/to/gateway.yaml. Каждый параметр проверяется по схеме при загрузке, поэтому неправильная конфигурация не запускается с ошибкой на уровне поля, а не при первом использовании.

Полный пример в конце этой страницы охватывает каждый раздел.

Структура файла

Пять разделов обязательны. Все остальные разделы опциональны, и пропущенный раздел принимает значения по умолчанию.

Обязательные разделы:

  • listen: адрес привязки, публичный URL, завершение TLS
  • oidc: ваш поставщик идентификации (IdP), включая издателя, клиента, сопоставление утверждений и кто может входить
  • session: токены-носители, которые выпускает gateway, с секретом и временем жизни
  • store: PostgreSQL для грантов устройств и счётчиков ограничения скорости
  • upstreams: куда идёт вывод, будь то Anthropic, Amazon Bedrock, Claude Platform на AWS, Agent Platform Google Cloud или Microsoft Foundry

Опциональные разделы:

  • login_notice: уведомление, которое разработчики видят при входе
  • admin: аутентификация Admin API и сохранение лимитов расходов
  • enforcement: поведение лимитов расходов при сбое — пропускать запросы (fail-open) или блокировать (fail-closed)
  • pricing: договорные ставки и множитель для счётчика расходов и для цифр стоимости, которые видят разработчики
  • models и auto_include_builtin_models: кураторский список моделей администратором и ID для каждого upstream
  • managed: управляемые политики параметров по группам IdP
  • telemetry: пересылка OTLP на ваш стек наблюдаемости
  • access_control, limits, timeouts, rate_limits: разрешение/запрет IP, ограничения размера запроса, время до первого байта upstream и лимиты входа по IP
  • load_test_mode: нагрузочное тестирование gateway без вызова поставщика модели

Расширение секретов

Не пишите секреты, такие как client_secret, jwt_secret или postgres_url, прямо в gateway.yaml. Ссылайтесь на них одной из форм ниже, и gateway разрешит значение при загрузке из переменной окружения или файла:

Форма Разрешается в Используется для
${VAR} Переменная окружения VAR. Загрузка не удаётся, если не определена. Переменные окружения контейнера, AWS Secrets Manager через внедрение env
${file:/path} Содержимое файла по этому абсолютному пути, обрезано. Ссылка должна быть полным значением поля: в отличие от ${VAR}, она не расширяется внутри более длинной строки, поэтому для пароля базы данных установите store.password вместо встраивания его в postgres_url. Монтирования томов Kubernetes Secret, Vault Agent, SOPS

Обязательные разделы

listen

Блок listen определяет, где работает шлюз: адрес и порт привязки, внешне видимый origin и необязательное завершение TLS.

Поле Обязательно Описание
host Нет Адрес привязки. По умолчанию 0.0.0.0.
port Нет Порт привязки. По умолчанию 8080.
public_url Если host не является loopback-адресом Внешне видимый origin https://, используемый для формирования redirect_uri IdP и метаданных обнаружения. Обязателен всякий раз, когда host не является loopback-адресом, независимо от того, завершается ли TLS на прокси, таком как ALB, Ingress или Cloud Run, или на самом шлюзе через tls, поскольку шлюз никогда не определяет собственный origin по заголовкам X-Forwarded-*: их может подделать клиент. Без него шлюз не запустится. Описанный ниже trusted_proxies управляет только определением IP-адреса клиента. Также обязателен для включения телеметрии, поскольку шлюз формирует из этого URL эндпоинт OTLP, который он передаёт клиентам.
tls.cert / tls.key Нет Пути к PEM-файлам, если шлюз сам завершает TLS
trusted_proxies Нет CIDR или IP-адреса фронтендов, которым следует доверять. Если поле задано, шлюз доверяет X-Forwarded-For только от этих узлов и записывает реальный IP-адрес клиента для ограничения частоты запросов по IP и аудита.

Указывайте фронтенд в trusted_proxies, только если последняя запись X-Forwarded-For, которую он передаёт дальше, не написана ни одним разработчиком. Не указывайте ни адресов, ни диапазонов, с которых подключаются разработчики. Фронтенд, который добавляет адрес каждого получаемого соединения, подходит. Фронтенд, который передаёт заголовок дальше в том виде, в каком его отправляют разработчики, не подходит.

Записи X-Forwarded-For в виде ipv4:port или [ipv6]:port, как их пишут некоторые балансировщики нагрузки, читаются с отброшенным портом. IPv6-адрес с добавленным портом без квадратных скобок может быть прочитан как другой адрес или не прочитан вовсе. Отключите опцию добавления порта на любом прокси, который пишет адреса в таком виде.

oidc

Блок oidc подключает шлюз к вашему поставщику удостоверений и определяет, кто может входить. В нём указываются издатель и OAuth-клиент, сопоставляются claims, содержащие email и группы, и ограничивается вход по домену электронной почты или группе.

OpenID Connect (OIDC) — это протокол SSO, который шлюз использует с вашим поставщиком удостоверений; о том, что нужно зарегистрировать на стороне IdP, см. в разделе Настройка поставщика удостоверений.

Поле Обязательно Описание
issuer Да Базовый адрес OIDC discovery. Должен отдавать документ обнаружения по пути /.well-known/openid-configuration. В продакшене используйте HTTPS; шлюз принимает издателя с http://. Loopback-издатель, например http://localhost:8081, отклоняется защитой от SSRF, если в окружении шлюза не задано CLAUDE_GATEWAY_ALLOW_LOOPBACK=1.
client_id Да Из регистрации вашего OAuth-клиента
client_secret Если token_endpoint_auth_method не равен private_key_jwt Из регистрации вашего OAuth-клиента. Не указывайте его, если используете аутентификацию клиента по сертификату.
allowed_email_domains Нет Отклонять id_token, у которых claim email не относится ни к одному из этих доменов, без учёта регистра. Эшелонированная защита от неправильной конфигурации мультитенантного IdP. Независимо от этой настройки id_token, у которого claim email_verified явно равен false, всегда отклоняется.
allowed_groups Нет Ограничить вход участниками этих групп IdP, сопоставляемых по groups_claim. Пользователь из разрешённого домена электронной почты, не состоящий ни в одной из этих групп, отклоняется. Требуется, чтобы IdP выдавал claim групп. Сопоставление — это точное сравнение строк с учётом регистра со значениями в этом claim, и шлюз не раскрывает вложенные группы: чтобы допустить участников подгруппы, укажите здесь подгруппу или настройте IdP на выдачу развёрнутого членства.
groups_claim Нет Какой claim id_token содержит членство в группах. По умолчанию groups. Microsoft Entra выдаёт роли приложения в roles. Принимает плоский ключ или JSON Pointer по RFC 6901, например /resource_access/gateway/roles, для вложенных claims.
google_groups Нет Получать группы вошедшего пользователя через Directory API из Google Workspace Admin SDK, поскольку id_token Google не содержит claim групп. Задайте в service_account_json_path файл ключа сервисного аккаунта с делегированием на уровне домена для scope https://www.googleapis.com/auth/admin.directory.group.readonly, а в admin_email — администратора Workspace, от имени которого действует сервисный аккаунт; Directory API требует реального субъекта-администратора. Адреса электронной почты групп каждого пользователя становятся его claim групп, поэтому allowed_groups и managed.policies.match.groups сопоставляются по адресам электронной почты групп.
email_claim Нет Какой claim id_token содержит email пользователя. По умолчанию email. Некоторые IdP, такие как ADFS и Entra B2C, вместо него выдают upn или preferred_username. Принимает плоский ключ, JSON Pointer или список резервных ключей, из которых используется первый присутствующий.
scopes Нет Полное переопределение OIDC scope, запрашиваемых шлюзом. По умолчанию [openid, profile, email, offline_access]. Задайте, если ваш IdP отклоняет неизвестные ему scope или требует пользовательский scope для выдачи групп или email. Должен включать openid. Удаление offline_access отключает refresh-токены, поэтому разработчики будут заново проходить вход через браузер каждые session.ttl_hours. Рецепты scope для отдельных IdP, например для потока refresh-токенов Google, см. в разделе Настройка поставщика удостоверений.
scope_on_refresh Нет Также отправлять scope с тем же списком, что и в запросе на вход, когда шлюз обменивает refresh-токен. По умолчанию false: запрос обновления не содержит scope. Большинство IdP возвращают id_token при каждом обновлении, и им это не нужно. Установите true, если ваш IdP возвращает id_token при обновлении, только когда снова запрошен openid, — именно так Okta документирует свой refresh grant. Без id_token каждое обновление зависит от того, примет ли эндпоинт userinfo IdP обновлённый access-токен. Если вы ограничиваете вход или сопоставляете политики по группам, а id_token вашего IdP при обновлении их не содержит, также задайте userinfo_fallback: true, чтобы шлюз заполнял их из эндпоинта userinfo. IdP, предоставивший меньше scope, чем было запрошено, может отклонить обновление с invalid_scope, в том числе для существующих сессий, если вы добавите записи в scopes, пока этот параметр включён. Удалите ключ, если после его установки обновления начнут завершаться ошибкой на token_endpoint. Требуется Claude Code v2.1.260 или новее на сервере шлюза.
extra_auth_params Нет Дополнительные параметры запроса, добавляемые к запросу авторизации IdP дословно. Это механизм переопределения поведения, специфичного для IdP, например access_type: offline для refresh-токенов Google, domain_hint для некоторых тенантов Entra или acr_values для потоков повышения уровня аутентификации. Не может переопределять протокольные параметры, которыми управляет шлюз: state, nonce, redirect_uri, PKCE, scope, response_type, response_mode и client_id.
userinfo_fallback Нет Если id_token не содержит email или группы, получать их из /userinfo. Нужно для облегчённых access-токенов Keycloak, сервера организации Okta и минимальных токенов ADFS. id_token остаётся авторитетным источником; userinfo лишь заполняет пробелы. По умолчанию false.
use_pkce Нет Отправлять challenge PKCE (S256) в запросе авторизации. По умолчанию true. Устанавливайте false, только если ваш IdP отклоняет PKCE для этого конфиденциального клиента.
clock_skew_seconds Нет Допустимое расхождение часов при проверке временных claims id_token. По умолчанию 0, то есть строгая проверка. Увеличьте, если сразу после входа видите ошибки «token expired / not yet valid» из-за расхождения часов хоста и IdP.
token_endpoint_auth_method Нет Как шлюз проходит аутентификацию на эндпоинте токенов IdP: client_secret_basic, client_secret_post или private_key_jwt для аутентификации клиента по сертификату. По умолчанию шлюз выбирает один из двух методов client_secret исходя из того, что объявляет IdP.
client_assertion При private_key_jwt Блок с private_key_pem и certificate_pem: закрытый ключ и сертификат для аутентификации клиента по сертификату. Требуется v2.1.284 или новее.
id_token_signed_response_alg Нет Ожидаемый алгоритм подписи id_token. По умолчанию RS256. Задайте для IdP, которые подписывают с помощью ES256, PS256 или EdDSA.
additional_authorized_parties Нет Дополнительные значения azp, принимаемые помимо client_id, для потоков брокера Keycloak и обмена токенов
discovery_url Нет Загружать документ обнаружения с этого URL, а не выводить его из issuer, — для IdP за прокси, который переписывает хост издателя. Путь должен содержать /.well-known/.
use_proxy Нет Отправлять собственные запросы шлюза к IdP через forward-прокси из HTTPS_PROXY или HTTP_PROXY с учётом NO_PROXY. false оставляет эти запросы прямыми. Требуется v2.1.227 или новее; см. ниже раздел Запросы к IdP через forward-прокси.
form_action_origins Нет Дополнительные origin для директивы Content-Security-Policy: form-action страницы /device. Шлюз уже разрешает 'self' и origin обнаруженного authorization_endpoint, но Chrome применяет form-action ко всей цепочке перенаправлений. Если ваш IdP перенаправляет через второй хост, например Azure AD с федерацией в ADFS, Okta с топологией hub-spoke или корпоративный перехватчик SSO, перечислите все origin, через которые может проходить запрос авторизации.
ca_cert_pem Нет Сам CA-сертификат в кодировке PEM, а не путь к файлу. Заменяет системное хранилище доверенных сертификатов только для запросов к IdP. Чтобы загрузить смонтированный файл, напишите ${file:/etc/gateway/idp-ca.pem}. Используйте для Keycloak или Dex за корпоративной PKI.

Аутентификация клиента по сертификату

Если ваш поставщик удостоверений аутентифицирует OAuth-клиентов по сертификату, а не по секрету клиента, как это делает Microsoft Entra с учётными данными-сертификатами, задайте token_endpoint_auth_method: private_key_jwt. Требуется Claude Code v2.1.284 или новее на сервере шлюза.

В такой конфигурации шлюз не отправляет секрет. Он проходит аутентификацию на эндпоинте токенов IdP с помощью короткоживущего JWT, подписанного закрытым ключом сертификата, когда разработчик входит в систему и каждый раз, когда шлюз обновляет его сессию. JWT подписывается с помощью RS256 и идентифицирует сертификат заголовками отпечатков x5t и x5t#S256, а не kid. Ваш IdP должен уметь находить зарегистрированный сертификат по отпечатку.

1. Создайте ключ и сертификат

Создайте незашифрованный закрытый ключ RSA длиной не менее 2048 бит в формате PEM PKCS#8 или PKCS#1 и сертификат для него. Шлюз отказывается запускаться с любым ключом, не удовлетворяющим этим условиям. Эта команда openssl создаёт такой ключ с самоподписанным сертификатом, действительным в течение одного года:

openssl req -x509 -newkey rsa:2048 -nodes -keyout idp-client.key -out idp-client.crt -days 365 -subj "/CN=claude-gateway"

Она записывает idp-client.key и idp-client.crt в текущий каталог. Скопируйте или смонтируйте оба файла туда, где шлюз сможет их прочитать. В примере на шаге 3 используется /etc/gateway/.

2. Загрузите сертификат в IdP

Загрузите сертификат, но не закрытый ключ, в регистрацию приложения шлюза в IdP.

3. Добавьте ключ и сертификат в gateway.yaml

Передайте шлюзу закрытый ключ и сертификат в блоке client_assertion. Не указывайте client_secret, поскольку шлюз отказывается запускаться, если он задан вместе с private_key_jwt. Этот блок oidc аутентифицирует шлюз в тенанте Microsoft Entra с помощью сертификата:

oidc:
  issuer: https://login.microsoftonline.com/<tenant-id>/v2.0
  client_id: <application-id>
  token_endpoint_auth_method: private_key_jwt
  client_assertion:
    private_key_pem: ${file:/etc/gateway/idp-client.key}
    certificate_pem: ${file:/etc/gateway/idp-client.crt}

Оба значения — это содержимое PEM, а не пути к файлам, поэтому загружайте смонтированные файлы с помощью ${file:/path}, как в примере. Шлюз отказывается запускаться, если certificate_pem не является одним PEM-сертификатом (без остальной части цепочки), открытый ключ которого совпадает с private_key_pem.

4. Перезапустите шлюз и проверьте лог загрузки

Перезапустите шлюз и найдите в логе загрузки такую строку:

[gateway] 2026-10-01T23:07:40.512Z info oidc: client authentication private_key_jwt; certificate CN=claude-gateway, SHA-1 thumbprint DE92821854EE8BAA1D98C758FAA04AABE80B9F57, expires Oct  1 23:07:31 2027 GMT

Сравните отпечаток SHA-1 с тем, который IdP показывает для загруженного вами сертификата. Если срок действия сертификата истёк или ещё не начался, шлюз всё равно запускается, но записывает в лог предупреждение о том, что вход и обновления будут завершаться ошибкой, пока вы не замените сертификат. Чтобы убедиться, что IdP принимает сертификат, попросите одного разработчика войти через шлюз.

Ротация сертификата клиента

Шлюз читает ключ и сертификат один раз при загрузке, поэтому изменённый файл вступает в силу только после перезапуска. Выполняйте ротацию в следующем порядке, чтобы ни один запрос токена не предъявлял сертификат, которого нет у IdP:

  1. Загрузите новый сертификат в IdP рядом со старым.
  2. Замените файлы ключа и сертификата, которые загружает gateway.yaml, затем перезапустите шлюз. Если вы запускаете несколько реплик, подойдёт поэтапный перезапуск, поскольку у IdP есть оба сертификата, пока вы не удалите старый.
  3. После перезапуска всех реплик удалите старый сертификат из IdP.

Запросы к IdP через forward-прокси

Upstream-серверы инференса учитывают HTTPS_PROXY и HTTP_PROXY во всех версиях. Собственные запросы шлюза к IdP — обнаружение, JWKS, токен и userinfo — идут напрямую, если вы не задали oidc.use_proxy: true, что требует v2.1.227 или новее. Если задана переменная прокси, use_proxy не задан, а издатель не охвачен NO_PROXY, шлюз оставляет эти запросы прямыми и при загрузке записывает в лог уведомление с просьбой сделать выбор; use_proxy: false оставляет их прямыми и отключает уведомление.

При use_proxy: true под сам разрешает имя хоста каждого эндпоинта IdP и просит прокси выполнить CONNECT к полученному IP-адресу, поэтому прокси должен принимать CONNECT к IP-адресу каждого хоста, указанного в документе обнаружения, а не только издателя. Используйте URL прокси с http://. ca_cert_pem и защита от SSRF действуют и на пути через прокси.

Исходящий трафик только через прокси меняет оба этих правила: пока он активен, запросы к IdP идут через прокси, если вы не задали use_proxy: false, а шлюз передаёт прокси имя хоста каждого IdP, не разрешая его предварительно.

Исходящий трафик только через прокси

Задайте CLAUDE_GATEWAY_PROXY_IS_EGRESS_BOUNDARY=1 в окружении шлюза рядом с HTTPS_PROXY, если под обращается к другим хостам только через этот forward-прокси и не может сам разрешать публичные DNS-имена или если прокси отказывает в CONNECT к IP-адресу. Требуется v2.1.277 или новее. Это переменная окружения, а не ключ gateway.yaml, чтобы ничто в файле конфигурации не могло ослабить проверку адресов шлюзом.

export HTTPS_PROXY=http://proxy.corp.example.com:3128
export NO_PROXY=
export no_proxy=
export CLAUDE_GATEWAY_PROXY_IS_EGRESS_BOUNDARY=1

Пока режим исходящего трафика только через прокси активен, шлюз при загрузке записывает в лог одну строку network:.

Каждая строка ниже — это один класс исходящих запросов шлюза с заданной HTTPS_PROXY: по умолчанию и при активном режиме исходящего трафика только через прокси.

Исходящий запрос По умолчанию Режим только через прокси активен
Upstream-серверы provider: anthropic, обмен токенов Workload Identity Federation, экспорт telemetry.forward_to Разрешается и проверяется локально, затем CONNECT к проверенному IP-адресу через прокси. К сборщику телеметрии, указанному в NO_PROXY, выполняется прямое подключение Имя хоста передаётся прокси
Обнаружение IdP, JWKS, токен и userinfo Напрямую, если не задано oidc.use_proxy: true; в этом случае CONNECT к проверенному IP-адресу Имя хоста передаётся прокси, за исключением случая, когда oidc.use_proxy: false оставляет прямое подключение к внутреннему IdP
Upstream-серверы Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform и Microsoft Foundry; получение групп Google Имя хоста передаётся прокси Без изменений

Режим исходящего трафика только через прокси остаётся выключенным, за исключением случая, когда окружение шлюза удовлетворяет всем трём следующим условиям:

  • Задана HTTPS_PROXY или HTTP_PROXY.
  • NO_PROXY и no_proxy пусты. Если ваша платформа внедряет любую из них в поды, задайте обеим пустое значение в контейнере шлюза. Указание сборщика телеметрии в NO_PROXY оставляет режим выключенным.
  • CLAUDE_GATEWAY_ALLOW_LOOPBACK не включена. Сборщик или IdP на собственном loopback-интерфейсе пода нельзя совмещать с режимом исходящего трафика только через прокси, поскольку loopback-адрес, переданный прокси, был бы loopback-адресом самого хоста прокси, поэтому дайте этим сервисам адрес, доступный прокси. По той же причине при активном режиме шлюз сразу отвергает имена вида localhost.

Если одно из этих условий не выполнено, шлюз при загрузке записывает в лог предупреждение с названием помешавшей переменной и сохраняет поведение по умолчанию.

Когда режим исходящего трафика только через прокси активен, разрешите в прокси все назначения, включая внутренний сборщик и любой хост, настроенный по IP-адресу. Внутренний IdP по-прежнему можно оставить на прямом подключении с помощью oidc.use_proxy: false.

[!WARNING]

Включайте этот режим, только если список разрешённых адресов прокси не менее строг, чем собственная проверка шлюза. Прокси должен отказывать в доступе к эндпоинтам облачных метаданных, таким как 169.254.169.254 и metadata.google.internal, к link-local-адресам и к собственному loopback-интерфейсу хоста прокси, причём отказывать по адресу, в который разрешается имя, а не только по имени, поскольку шлюз больше не перехватывает имя хоста, разрешающееся в один из них. Прокси, который подключается куда угодно по запросу, снимает защиту шлюза от SSRF для этих запросов.

session

Блок session определяет Bearer-токены, которые шлюз выпускает после входа: секрет, которым они подписываются, и срок их жизни.

Поле Обязательно Описание
jwt_secret Да Не менее 32 байт энтропии, например из openssl rand -base64 32. Подписывает Bearer-токены шлюза HS256. Принимает одну строку или массив для ротации: элемент с индексом 0 подписывает, а все элементы проверяют. Для ротации добавьте новый секрет в начало, подождите ttl_hours, затем удалите старый.
ttl_hours Нет Время жизни Bearer-токена шлюза. По умолчанию 1. CLI незаметно обновляет токен до истечения срока, если IdP выдаёт refresh-токены. Более короткий срок быстрее отзывает доступ; более длинный требует меньше обращений к IdP. Если ваш IdP не может выдавать refresh-токены, потому что offline_access недоступен, незаметного обновления не происходит, поэтому увеличьте значение до 8 или 12, чтобы разработчикам не приходилось каждый час заново входить через браузер.

store

Блок store указывает шлюзу его базу данных PostgreSQL, в которой хранятся выданные устройствам разрешения и счётчики ограничения частоты запросов.

Поле Обязательно Описание
postgres_url Да URL postgres:// или postgresql:// с одним хостом, а не списком через запятую. Шлюз сам выполняет миграции схемы при загрузке и при обновлении, поэтому роли нужны права на создание и изменение таблиц в целевой схеме. См. разделы Обновления и Postgres.
username Нет Переопределяет пользователя в postgres_url
password Нет Учётные данные базы данных. Задавайте их здесь, а не в postgres_url, чтобы учётные данные не попадали в URL. Принимает любые символы и имеет приоритет над учётными данными в URL.
max_connections Нет Размер пула соединений Postgres на реплику. По умолчанию 5 — консервативное значение, подходящее для общих баз данных. При включённых лимитах расходов шлюз выполняет несколько операций с базой данных на каждый запрос инференса, поэтому увеличьте его для выделенной базы данных под нагрузкой в пределах того, что допускает раздел Определение размера пула соединений.
connect_timeout_seconds Нет Сколько секунд шлюз ждёт при открытии соединения с Postgres. Целое число от 1 до 60, по умолчанию 5. Увеличьте, если попытки подключения завершаются по таймауту при запуске нового экземпляра шлюза. Требуется Claude Code v2.1.274 или новее на сервере шлюза. Более ранние версии отказываются запускаться, если ключ задан.
readiness_grace_seconds Нет Сколько секунд /readyz продолжает сообщать о готовности после того, как Postgres перестаёт отвечать. Целое число от 0 до 3600, по умолчанию 0. О выборе значения см. в разделе Поведение при сбоях. Требуется Claude Code v2.1.282 или новее на сервере шлюза. Более ранние версии отказываются запускаться, если ключ задан.

Для локальной разработки направьте postgres_url на одноразовый контейнер Postgres, например docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres.

upstreams

upstreams — упорядоченный список. Шлюз перенаправляет инференс на первый upstream, который разрешает запрошенную модель, пропуская любой upstream, чей список groups не включает разработчика.

При 5xx, 429, 401, 403, 404 или таймауте шлюз переключается на следующий upstream; при других 4xx — нет, поскольку эти ошибки связаны с запросом, а не с upstream. 401 или 403 означает, что upstream отклонил учётные данные, использованные шлюзом, или запретил ему доступ, например к запрошенной модели. 404 означает, что этот upstream не обслуживает запрошенную модель, поэтому её ещё может обслужить следующий upstream в списке.

Если вы задали forward_user_identity: true для upstream, то 429, возвращённый им на запрос, содержавший email разработчика, не приводит к переключению. См. раздел о том, как отказ по лимиту на пользователя доходит до разработчика.

Переключение при 404 требует шлюза v2.1.198 или новее. Более ранние выпуски возвращали клиенту первый 404, даже если модель обслуживал следующий upstream в списке.

Несколько upstream одного провайдера должны задавать разные name:.

Клиенты Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform и Microsoft Foundry создаются один раз при запуске, а их SDK обновляют учётные данные самостоятельно, поэтому ротация облачных учётных данных не требует перезапуска. Статические API-ключи и Bearer-токены Anthropic читаются при запуске; см. раздел Anthropic API.

Сообщения об ошибках upstream

В зависимости от того, как ответили upstream-серверы, шлюз возвращает ответ с ошибкой одного из upstream или собственный 502:

  • Upstream вернул статус, при котором шлюз не переключается: ответ этого upstream. Шлюз больше не пробует другие upstream.
  • Каждый опробованный шлюзом upstream завершился сбоем, при котором шлюз переключается: последний 429. Если ни один не вернул 429, шлюз предпочитает, в указанном порядке, последний 401 или 403, последний 404 и последний 501. Если ни один не вернул ничего из этого — собственный 502 шлюза, all upstreams failed (N attempted). N — это число записей в ваших upstreams, включая пропущенные, за вычетом тех, чей список groups не включает разработчика.

Когда шлюз возвращает ответ upstream, он сохраняет код статуса upstream. Сохранится ли сообщение upstream, зависит от провайдера. Тело ошибки upstream Anthropic API доходит до разработчика без изменений.

Upstream-серверы Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform и Microsoft Foundry могут указывать в тексте ошибки идентификаторы ваших аккаунтов, ARN ролей и идентификаторы проектов. Шлюз записывает этот полный текст в операционный лог. Что разработчик видит от этих upstream, зависит от вида отказа:

  • 400 или 413 в стандартной оболочке ошибки Anthropic: собственное сообщение upstream, например prompt is too long. Claude Platform on AWS, Agent Platform и Microsoft Foundry возвращают эту оболочку при отказах API модели.
  • 400 или 413 в собственном формате провайдера: токен capability_rejected:. Если шлюз не может классифицировать отказ — upstream rejected the request при 400 или request too large for this upstream при 413.
  • Любой другой статус: общий текст для данного статуса, например upstream rate limit exceeded при 429.

Например, шлюз заменяет сообщение Amazon Bedrock Input is too long for requested model. на capability_rejected: prompt_too_long. Claude Code автоматически выполняет сжатие при получении этого токена, так же как при prompt is too long.

Сохранение сообщения 400 или 413 облачного upstream или его замена токеном capability_rejected: требует шлюза v2.1.233 или новее.

Anthropic API

Минимальный upstream Anthropic — это API-ключ из Claude Console:

upstreams:
  - provider: anthropic
    auth:
      api_key: ${ANTHROPIC_API_KEY}
    # OR an OAuth bearer (e.g. a Workload-Identity-Federation-exchanged token):
    #   oauth_token: ${file:/var/run/secrets/anthropic-oauth-token}
    # base_url: https://api.anthropic.com   # default; override for a forward proxy

Две формы учётных данных различаются отправляемым заголовком:

  • api_key: отправляет x-api-key. Выполняйте ротацию в Claude Console и обновляйте переменную окружения.
  • oauth_token: отправляет Authorization: Bearer. Используйте Bearer-форму, если ваша организация выдаёт короткоживущие токены вместо долгоживущих API-ключей. Bearer-токен читается один раз при запуске, поэтому для обновления перемонтируйте секрет и перезапустите шлюз.

Вместо статического ключа или Bearer-токена можно использовать Workload Identity Federation. Создайте правило федерации по руководству Workload Identity Federation, затем смонтируйте OIDC JWT вашей рабочей нагрузки как файл, например projected-токен сервисного аккаунта Kubernetes или id-token CI-платформы. Шлюз обменивает JWT на короткоживущий Bearer-токен и автоматически обновляет его. Файл токена перечитывается при каждом обмене, поэтому обновлённые projected-токены подхватываются без перезапуска.

upstreams:
  - provider: anthropic
    auth:
      federation_rule_id: ${ANTHROPIC_FEDERATION_RULE_ID}
      organization_id: ${ANTHROPIC_ORGANIZATION_ID}
      identity_token_file: /var/run/secrets/anthropic/id-token
      # workspace_id: wrkspc_...       # required if the rule covers >1 workspace
      # service_account_id: svac_...   # optional expected-target check
Заголовки идентификации пользователя для вашего прокси

Вы можете направить base_url upstream с provider: anthropic на собственный прокси вместо Anthropic API. Чтобы сообщать этому прокси, какой разработчик отправил каждый запрос, задайте forward_user_identity: true для этого upstream. Тогда прокси сможет учитывать расходы по каждому разработчику. Требуется шлюз с Claude Code v2.1.233 или новее.

Например, для прокси по адресу upstream-gateway.internal.example.com:

upstreams:
  - provider: anthropic
    base_url: https://upstream-gateway.internal.example.com
    auth:
      api_key: ${PROXY_KEY}
    forward_user_identity: true        # default false

Шлюз добавляет эти заголовки к каждому запросу, который он перенаправляет этому upstream.

Заголовок Значение
x-litellm-end-user-id Email разработчика, если IdP его предоставил.
x-claude-gateway-user-id Субъект разработчика в IdP, из claim sub токена.
x-claude-gateway-user-email Email разработчика, если IdP его предоставил.

Если токен IdP не содержит email, шлюз отправляет только x-claude-gateway-user-id и опускает два заголовка с email. Если ваш IdP помещает email в другой claim, укажите этот claim в oidc.email_claim.

Ваш прокси не получает заголовки x-claude-code-*, которые отправляет Claude Code, например x-claude-code-session-id. Шлюз не передаёт их ни одному upstream, поэтому группируйте запросы по разработчикам с помощью заголовков из таблицы выше.

Когда ваш прокси отвечает 429 на запрос, содержавший email разработчика, шлюз возвращает этот ответ разработчику как есть, а не переключается на следующий upstream, поэтому бюджет или ограничение частоты запросов вашего прокси для каждого пользователя соблюдается. Остальные ответы прокси подчиняются обычным правилам переключения. Если токен IdP разработчика не содержит email, шлюз перенаправляет его запросы без заголовков с email, поэтому 429 на такой запрос считается нехваткой ёмкости upstream и приводит к переключению. До v2.1.267 на сервере шлюза каждый 429 приводил к переключению.

Задавайте forward_user_identity только для upstream, чей base_url — прокси, которым управляете вы. Шлюз отправляет email разработчиков на любой сервер, указанный в этом base_url. Если base_url — это Anthropic API, что является значением по умолчанию, шлюз отказывается запускаться.

[!NOTE]

Если вы зададите forward_user_identity для upstream Amazon Bedrock, шлюз при запуске завершится с ошибкой Unrecognized key(s) in object: 'forward_user_identity'. Если ваш прокси стоит перед Bedrock, укажите его как upstream с provider: anthropic. Шлюз отправляет такому upstream данные в формате Anthropic Messages, поэтому ваш прокси должен преобразовывать запросы для Bedrock. Чтобы вместо этого сообщать AWS имя каждого разработчика, см. раздел Учёт расходов AWS по разработчикам.

Amazon Bedrock

О клиентском развёртывании Amazon Bedrock, которое шлюз заменяет или перед которым стоит, см. раздел Claude Code на Amazon Bedrock. Upstream на стороне шлюза:

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}                           # preferred: AWS default credential chain
    # OR explicit credentials:
    # auth:
    #   aws_access_key_id: ${AWS_AKID}
    #   aws_secret_access_key: ${AWS_SK}
    #   aws_session_token: ${AWS_ST}
    # OR a Bedrock API bearer token:
    # auth:
    #   aws_bearer_token: ${AWS_BEARER_TOKEN}
    # Override the bedrock-runtime endpoint for FIPS or VPC-endpoint deployments:
    # base_url: https://bedrock-runtime-fips.us-east-1.amazonaws.com

Пустой блок auth использует цепочку учётных данных AWS SDK по умолчанию: переменные окружения, ~/.aws/credentials, роль задачи ECS, метаданные экземпляра EC2 или IRSA в EKS. В продакшене назначьте поду шлюза IAM-роль, а не встраивайте статические ключи в образ контейнера.

Явные учётные данные должны быть полными: шлюз завершается с ошибкой при загрузке, если aws_access_key_id и aws_secret_access_key не заданы вместе или если aws_session_token задан без них. До v2.1.207 частичный блок auth: проходил проверку.

Настройка Как
IAM-разрешения Предоставьте принципалу шлюза bedrock:InvokeModel и bedrock:InvokeModelWithResponseStream как на ARN профилей инференса, так и на ARN базовых foundation-моделей. Для встроенного каталога в регионах США: arn:aws:bedrock:<region>:<account>:inference-profile/us.anthropic.* и arn:aws:bedrock:*::foundation-model/anthropic.*. Также предоставьте bedrock:CountTokens на ARN foundation-моделей. Шлюз бесплатно использует его, чтобы подсчитать входные токены запроса, который клиент прервал, благодаря чему лимиты расходов остаются точными. Без него шлюз для этого подсчёта использует как резервный вариант запрос к Bedrock на один токен.
Доступ к моделям Amazon Bedrock по умолчанию включает доступ к моделям в коммерческих регионах. Оставшееся ограничение на уровне аккаунта — одноразовая форма описания сценария использования Anthropic: если никто в вашем аккаунте AWS её не отправлял, откройте консоль Amazon Bedrock, выберите модель Anthropic в каталоге моделей и заполните форму. О форме для AWS Organizations и разрешениях, необходимых отправителю, см. раздел Отправка описания сценария использования.
EKS (IRSA) Создайте IAM-роль с указанной выше политикой и политикой доверия для OIDC-провайдера вашего кластера, ограниченной сервисным аккаунтом шлюза. Добавьте к сервисному аккаунту аннотацию eks.amazonaws.com/role-arn: arn:aws:iam::<acct>:role/claude-gateway. auth: {} подхватывает её.
ECS / EC2 Привяжите IAM-роль к определению задачи или профилю экземпляра. auth: {} подхватывает её.
В любом другом месте Передайте учётные данные через переменные окружения AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY и AWS_SESSION_TOKEN или задайте их явно в auth: с подстановкой ${VAR}
Регион region: — регион эндпоинта API. Межрегиональные профили инференса маршрутизируют запросы в пределах геозоны (US, EU, APAC) независимо от выбранного региона. Для регионов за пределами США или ARN с выделенной пропускной способностью добавьте блок models: с нужными идентификаторами для каждого upstream.
Применение guardrail Amazon Bedrock

Чтобы применить guardrail Amazon Bedrock к каждому запросу инференса, который шлюз отправляет через upstream Bedrock, добавьте к этому upstream блок guardrail. Требуется Claude Code v2.1.281 или новее на сервере шлюза.

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}
    guardrail:
      id: gr-abc123                    # guardrail ID or full ARN
      version: "1"                     # a published version number, or DRAFT
 # keep the quotes: a bare 1 fails at boot

Также предоставьте bedrock:ApplyGuardrail на этот guardrail принципалу, который подписывает запросы этого upstream: AWS-принципалу шлюза или, при использовании assume_role, роли, указанной в role_arn.

Задайте guardrail либо для всех upstream bedrock, либо ни для одного. При смешанной конфигурации шлюз отказывается запускаться, поскольку иначе переключение могло бы отправить запрос на upstream Bedrock без guardrail.

Guardrail действует только для upstream Bedrock. Если в upstreams указан другой провайдер, шлюз отправляет запросы этому провайдеру без guardrail или отказывается запускаться, если этот провайдер — mantle.

Когда запрос /v1/messages, тело которого содержит поле amazon-bedrock-*, например amazon-bedrock-guardrailConfig, поступает на upstream Bedrock с заданным guardrail, шлюз отвечает 400, а не перенаправляет его.

[!WARNING]

По умолчанию шлюз не добавляет к промптам входные теги, поэтому фильтр guardrail, который Amazon Bedrock применяет только к помеченному входу, не срабатывает на трафике через шлюз. Чтобы добавлять теги, задайте input_tagging. О том, какие фильтры зависят от входных тегов, см. раздел input tags в документации Amazon Bedrock.

Добавление входных тегов guardrail

Чтобы шлюз добавлял входные теги, необходимые фильтру атак на промпт guardrail Amazon Bedrock, задайте input_tagging в блоке guardrail и перезапустите шлюз. Задайте одинаковое значение для всех upstream bedrock, иначе шлюз откажется запускаться. Требуется Claude Code v2.1.316 или новее на сервере шлюза. Шлюз версии, в которой этого ключа нет, при запуске завершается с ошибкой Unrecognized key(s) in object: 'input_tagging'.

[!WARNING]

Согласно документации Amazon Bedrock, как только запрос содержит входные теги, каждый фильтр guardrail перестаёт оценивать непомеченное содержимое. Опробуйте input_tagging на тестовом шлюзе, прежде чем задавать его на шлюзе, которым пользуются разработчики.

input_tagging принимает одно из следующих значений:

input_tagging Где шлюз помечает текст После того как guardrail заблокировал промпт
last_message Сообщения user после последнего ответа Claude В Claude Code следующий промпт может пройти, и тогда Claude получает заблокированный промпт как часть диалога
user_messages Сообщения user Последующие промпты в сессии тоже могут блокироваться, пока разработчик не удалит заблокированный промпт
all_messages Сообщения user и assistant Так же, как при user_messages
all_messages_and_system Системный промпт и каждое сообщение, включая системные сообщения в середине диалога Так же, как при user_messages

При last_message, если в сообщениях user после последнего ответа Claude нет текста для пометки, шлюз вместо этого помечает системные сообщения в середине диалога, появившиеся после этого ответа. Вызов инструмента считается ответом.

Рекомендация Amazon Bedrock для фильтра атак на промпт — помечать пользовательский ввод так, чтобы системный промпт был исключён. Если вы задаёте all_messages_and_system, фильтр, помечающий собственный системный промпт Claude Code, может блокировать запросы.

Пример ниже помечает текст в каждом сообщении user:

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}
    guardrail:
      id: gr-abc123
      version: "1"
      input_tagging: user_messages

Сообщения user также могут содержать текст, который добавляет Claude Code, например системные напоминания, поэтому проверьте на тестовом шлюзе, что обычные запросы не блокируются.

В тестах Anthropic помеченная сессия сохраняла чтение из кэша промптов от одного промпта к следующему, а теги не добавляли входных токенов.

Что не покрывают входные теги

Ни одно значение input_tagging не остановит разработчика, который намеренно помещает текст туда, где тегов нет. Не рассчитывайте, что guardrail будет оценивать следующие части запроса:

  • Содержимое, которое шлюз не помечает: сообщения, которые ваше значение input_tagging не охватывает, определения инструментов, входные данные вызовов инструментов, изображения и PDF, среди прочего. Если вы не задали all_messages_and_system, системный промпт тоже остаётся без тегов.
  • Результаты инструментов: они содержат то, что возвращают инструменты Claude, например содержимое файлов и веб-страницы. В тестах Anthropic фильтр слов не оценивал их ни с тегами, ни без.

Если ваш аккаунт или организация AWS принудительно применяет guardrail, о том, как такой guardrail обрабатывает входные теги, см. документацию Amazon Bedrock.

Запись в лог сработавшего фильтра guardrail

Чтобы узнать, какой фильтр guardrail Amazon Bedrock заблокировал запрос разработчика, задайте guardrail_trace: true для upstream Bedrock, перезапустите шлюз и попросите разработчика отправить запрос ещё раз. Затем найдите событие guardrail.trace этого запроса в журнале аудита. Требуется Claude Code v2.1.314 или новее на сервере шлюза. Более ранний шлюз отказывается запускаться, обнаружив guardrail_trace.

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}
    guardrail:
      id: gr-abc123
      version: "1"
    guardrail_trace: true              # default false; beside guardrail, not inside it

Шлюз записывает событие guardrail.trace без совпавшего текста, когда срабатывает фильтр или действие guardrail равно INTERVENED. Ищите события разработчика по email или sub. Один потоковый запрос может порождать несколько событий, и у одного из них список filters может быть пустым, поэтому читайте все события с одинаковым request_id:

Поле Что содержит
request_id ID запроса
sub, email ID пользователя и email разработчика
upstream Upstream, от которого пришёл ответ
action Действие guardrail, например INTERVENED
filters Сработавшие фильтры. Список пуст, если AWS не присылает сведений о фильтрах
filters[].side input или output
filters[].guardrail ID guardrail
filters[].policy Политика и список Bedrock, например contentPolicy.filters или sensitiveInformationPolicy.piiEntities
Другие поля filters[] Запись также может содержать такие поля, как action, name, type, confidence, filterStrength, score и threshold

Событие не содержит текста, совпавшего с фильтром, в том числе поля match трассировки Bedrock. Разработчики не получают данные трассировки Bedrock, поскольку шлюз удаляет их из каждого ответа, потокового или нет.

Если клиент отправляет поле amazon-bedrock-* в теле запроса /v1/messages, шлюз отвечает 400 на upstream, для которого задан guardrail_trace.

Bedrock в другом аккаунте AWS

Если задать assume_role для upstream Bedrock, шлюз использует собственное удостоверение AWS только для вызова sts:AssumeRole на указанной вами роли, которая может находиться в другом аккаунте AWS, чем шлюз. Каждый запрос к Bedrock от этого upstream подписывается часовыми учётными данными, которые возвращает STS, поэтому никакой долгоживущий ключ доступа не передаётся между аккаунтами.

Требуется шлюз с Claude Code v2.1.281 или новее. Более ранний шлюз отказывается запускаться, обнаружив этот ключ.

upstreams:
  - name: bedrock-isolated
    provider: bedrock
    region: us-east-1
    auth: {}                           # the gateway's own role: it only calls STS
    assume_role:
      role_arn: arn:aws:iam::222222222222:role/claude-gateway-bedrock
      # external_id: ${BEDROCK_ROLE_EXTERNAL_ID}   # when the role's trust policy requires one

Блок assume_role принимает три ключа:

Ключ Значение
role_arn IAM-роль, которую принимает шлюз, в виде ARN arn:aws:iam:: или arn:aws-us-gov:iam::. Предоставьте ей разрешения Bedrock, необходимые этому upstream, включая bedrock:CountTokens, а также bedrock:ApplyGuardrail, если для upstream задан guardrail.
external_id Необязательно. Отправляется как внешний ID при каждом вызове sts:AssumeRole. Задайте его, если политика доверия роли его требует, и заключите в кавычки, если он состоит только из цифр.
session_name Необязательно. email или sub даёт каждому разработчику собственную сессию: см. раздел Учёт расходов AWS по разработчикам. Если не задан, каждый запрос использует одну сессию с именем claude-apps-gateway.

Политика доверия роли указывает собственного принципала шлюза, например его роль IRSA или роль задачи ECS. Этому принципалу нужно sts:AssumeRole на роль и не нужно собственных разрешений Bedrock. Удалите Condition, если не задаёте external_id.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::111111111111:role/claude-gateway" },
    "Action": "sts:AssumeRole",
    "Condition": { "StringEquals": { "sts:ExternalId": "your-external-id" } }
  }]
}
  • Если STS отказывает или недоступен, шлюз не отправляет запрос с собственными учётными данными upstream. Он записывает в лог ошибку STS с указанием того, что проверить, и затем пробует следующий указанный вами upstream. Что получает клиент, когда ни один upstream не отвечает успешно, описано в разделе Сообщения об ошибках upstream. Следующий upstream без assume_role обслужил бы запрос со своими учётными данными, поэтому указывайте такой upstream, только если именно этого вы и хотите.
  • Шлюз обращается к региональному эндпоинту STS sts.<region>.amazonaws.com, который должен быть доступен из его сети. Для эндпоинта FIPS задайте AWS_USE_FIPS_ENDPOINT=true в окружении шлюза, а не use_fips_endpoint в файле конфигурации AWS.
  • assume_role требует исходных учётных данных SigV4: шлюз отказывается запускаться, если он задан рядом с aws_bearer_token.
  • Без списка groups этот upstream может использовать любой разработчик, которого допускает шлюз. Чтобы ограничить модели, доступные разработчику, задайте availableModels в политике managed.
  • Чтобы модель, обслуживаемая через роль, не обслуживалась также из другого аккаунта, дайте ей пользовательский id, карта upstream_model которого содержит только имя этого upstream. Для такого id шлюз пропускает все остальные upstream, поэтому ни сам запрос, ни подсчёт токенов для прерванного запроса не могут переключиться на другой аккаунт.
  • Запрос со встроенным именем модели всё равно может дойти до этого upstream, и шлюз подпишет его той же ролью. Размещайте этот upstream последним, если только его аккаунт не должен также обслуживать эти модели.

В этом примере одной модели назначается пользовательский id, который обслуживает только изолированный upstream:

models:
  - id: restricted-claude-opus-4-8      # a custom id, not a built-in model name
    upstream_model:
      bedrock-isolated: us.anthropic.claude-opus-4-8   # the only upstream that serves it
Учёт расходов AWS по разработчикам

По умолчанию шлюз подписывает каждый запрос к Bedrock одними учётными данными, поэтому AWS видит запросы всех разработчиков под одним IAM-принципалом. Добавьте session_name: email в assume_role, и шлюз будет вызывать sts:AssumeRole раз в час для каждого разработчика с именем сессии, равным email этого разработчика, и подписывать его запросы полученными учётными данными, так что запросы каждого разработчика будут поступать в AWS под его собственной сессией принятой роли. Роль может находиться в собственном аккаунте шлюза.

Требуется шлюз с Claude Code v2.1.281 или новее. Об IAM-роли и о том, где биллинг AWS показывает сессии, см. раздел Учёт расходов в AWS.

[!NOTE]

Для учёта по разработчикам задайте assume_role с session_name для каждого upstream bedrock и mantle, кроме тех, которые используют aws_bearer_token. Такие upstream не могут использовать assume_role, поэтому их запросы остаются под одним принципалом.

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}                           # the gateway's own role: it only calls STS
    assume_role:
      role_arn: arn:aws:iam::123456789012:role/claude-gateway-bedrock-user
      session_name: email              # or sub

session_name выбирает, какой проверенный claim становится RoleSessionName в AWS: email или sub. Шлюз записывает любой символ, кроме букв ASCII, цифр и _+,.@-, в виде =XX в шестнадцатеричной записи для каждого байта UTF-8 и сокращает результат длиннее 64 символов до префикса и хеша, поэтому имя сессии каждого разработчика остаётся допустимым и уникальным. Запрос от разработчика, в токене которого нет этого claim, не отправляется через этот upstream, а в операционном логе указывается, что нужно переключиться на sub или задать oidc.email_claim.

Каждый активный разработчик обходится в один вызов STS в час на реплику шлюза, а одновременные первые запросы используют один общий вызов.

Шлюз также выполняет с этой ролью один собственный вызов: подсчёт токенов для запроса, который клиент прервал, чтобы лимиты расходов оставались точными. Этот подсчёт и его резервный запрос на один токен подписываются общей сессией claude-apps-gateway, поэтому AWS относит резервный запрос к claude-apps-gateway, а не к разработчику.

Эндпоинт Amazon Bedrock Mantle

Провайдер mantle отправляет инференс на эндпоинт Mantle Amazon Bedrock. Он требует Claude Code v2.1.283 или новее на сервере шлюза. Более ранние выпуски шлюза отклоняют его при загрузке, поэтому обновите все реплики, прежде чем добавлять его.

В примере ниже Mantle стоит первым, а за ним следует upstream Amazon Bedrock, обслуживающий все модели, не указанные в поле models:

upstreams:
  - provider: mantle
    region: us-east-1
    models: [claude-opus-4-7, claude-haiku-4-5]   # required
    auth: {}                           # AWS default credential chain
  - provider: bedrock
    region: us-east-1
    auth: {}

В таблице ниже перечислены поля, специфичные для upstream mantle.

Поле Обязательно Описание
region Да Регион AWS. Шлюз выводит из него эндпоинт в виде https://bedrock-mantle.<region>.api.aws/anthropic.
models Да Модели, к которым вашему аккаунту AWS предоставлен доступ в Mantle, с именами в том виде, в каком их отправляют клиенты, например claude-haiku-4-5. Только они направляются на этот upstream, а все остальные модели переходят к следующему.
auth Нет Принимает те же ключи, что и блок auth upstream Amazon Bedrock, по тем же правилам.
assume_role Нет Роль, через которую проходят запросы этого upstream, с теми же ключами, что и для upstream bedrock, включая session_name для учёта по разработчикам. Предоставьте роли IAM-действия Mantle. Требуется шлюз с Claude Code v2.1.318 или новее. Более ранний шлюз при запуске завершается с ошибкой Unrecognized key(s) in object: 'assume_role'.
base_url Нет Переопределяет выведенный эндпоинт. Сохраните путь /anthropic в конце.

Предоставьте AWS-удостоверению upstream собственные IAM-действия Mantle для инференса и подсчёта токенов, перечисленные в разделе Использование эндпоинта Mantle.

Для ID модели Mantle, неизвестного шлюзу, добавьте запись в блок верхнего уровня models:, у которой upstream_model сопоставляет имя этого upstream с этим ID. Затем также укажите id этой записи в поле models этого upstream.

Настройки guardrail и assume_role upstream bedrock не распространяются на запросы, которые обслуживает Mantle:

  • guardrail: шлюз не применяет guardrail Bedrock к запросам, которые он отправляет в Mantle, поэтому отказывается запускаться, если указан upstream mantle, а какой-либо upstream bedrock задаёт guardrail.
  • assume_role: задайте его для самого upstream mantle. Без него запросы, которые обслуживает Mantle, отправляются с собственными учётными данными auth upstream mantle.

О значении собственных ответов Mantle с ошибками см. раздел Ошибки эндпоинта Mantle.

Claude Platform on AWS

Claude Platform on AWS предоставляет собственный API Anthropic на инфраструктуре AWS по адресу aws-external-anthropic.<region>.api.aws. Она использует собственные идентификаторы моделей Anthropic, учитывает заголовки anthropic-beta в том виде, в каком они отправлены, и обслуживает count_tokens, поэтому никакие преобразования, специфичные для Bedrock, не применяются. Провайдер anthropicAws требует Claude Code v2.1.198 или новее; более ранние выпуски шлюза отклоняют его при загрузке.

О клиентском развёртывании той же платформы см. раздел Claude Code на Claude Platform on AWS. Upstream на стороне шлюза:

upstreams:
  - provider: anthropicAws
    region: us-east-1
    workspace_id: wrkspc_...
    auth:
      api_key: ${ANTHROPIC_AWS_API_KEY}   # sent as x-api-key
    # OR SigV4 via the AWS default credential chain:
    # auth: {}
    # OR explicit SigV4 credentials:
    # auth:
    #   aws_access_key_id: ${AWS_ACCESS_KEY_ID}
    #   aws_secret_access_key: ${AWS_SECRET_ACCESS_KEY}
    # Override the derived endpoint:
    # base_url: https://aws-external-anthropic.us-east-1.api.aws

Платформа работает в отдельном от Amazon Bedrock аккаунте AWS и проверяет подписи SigV4 для собственного имени сервиса aws-external-anthropic, поэтому IAM-роль с областью действия Bedrock не даёт к ней доступа. API-ключ в auth.api_key имеет приоритет, если также заданы учётные данные SigV4. Пустой блок auth использует цепочку учётных данных AWS SDK по умолчанию — ту же, что и upstream Amazon Bedrock.

Поле Обязательно Описание
region Да Регион AWS: строчные буквы, цифры и дефисы. Шлюз выводит из него эндпоинт в виде https://aws-external-anthropic.<region>.api.aws.
workspace_id Да Отправляется как заголовок в каждом запросе; платформа его требует
auth.api_key Нет API-ключ платформы, отправляемый как x-api-key. Это не Bearer-токен: два режима аутентификации — API-ключ или SigV4.
auth.aws_access_key_id / auth.aws_secret_access_key Нет Явные учётные данные SigV4. Если задать одно без другого, загрузка завершится ошибкой. Вместе с ними принимается auth.aws_session_token.
base_url Нет Переопределяет выведенный эндпоинт

Поскольку платформа разрешает собственные идентификаторы моделей Anthropic, встроенный каталог маршрутизируется на неё без блока models:. Если вы составляете собственный список models:, используйте для записи ключ anthropicAws: с собственным идентификатором Anthropic.

Google Cloud Agent Platform

Об эквивалентной клиентской настройке см. раздел Claude Code в Google Cloud. Upstream на стороне шлюза:

upstreams:
  - provider: vertex
    region: us-east5
    project_id: example-prod
    auth: {}                           # preferred: Application Default Credentials
    # OR a service account key file:
    # auth: { service_account_json: /secrets/sa.json }
    # Override the aiplatform endpoint for Private Service Connect:
    # base_url: https://us-east5-aiplatform.p.googleapis.com

Пустой блок auth использует Application Default Credentials: GOOGLE_APPLICATION_CREDENTIALS, метаданные GCE или GKE Workload Identity. Файлы ключей сервисных аккаунтов в формате JSON поддерживаются, но не рекомендуются; используйте Workload Identity или привяжите сервисный аккаунт к экземпляру GCE или Cloud Run.

Задайте region: global, чтобы использовать глобальный эндпоинт Google Cloud's Agent Platform вместо регионального. Тогда Google направляет каждый запрос в доступный регион, и вам не нужно отслеживать доступность моделей по регионам. Указание конкретного региона закрепляет за ним каждый запрос.

Настройка Как
IAM-разрешения Предоставьте сервисному аккаунту шлюза roles/aiplatform.user на проект или пользовательскую роль с aiplatform.endpoints.predict. Включите API Google Cloud's Agent Platform (aiplatform.googleapis.com).
Доступ к моделям В Model Garden включите модели Claude для вашего проекта. Они публикуются в определённых регионах; поддерживаемые регионы смотрите в карточке модели.
GKE (Workload Identity) Привяжите сервисный аккаунт GCP к сервисному аккаунту Kubernetes шлюза и добавьте к KSA аннотацию iam.gke.io/gcp-service-account: claude-gateway@<proj>.iam.gserviceaccount.com. auth: {} подхватывает её.
Cloud Run / GCE Назначьте сервису сервисный аккаунт с roles/aiplatform.user. auth: {} подхватывает его.
В любом другом месте auth: { service_account_json: /secrets/sa.json } — путь к файлу ключа JSON, смонтированному как секрет. Поле принимает путь к файлу, а не содержимое ключа, поэтому подстановка ${file:…} не используется.

Microsoft Foundry

О клиентском развёртывании Microsoft Foundry см. раздел Claude Code на Microsoft Foundry. Upstream на стороне шлюза:

upstreams:
  - provider: foundry
    resource: example-foundry              # https://example-foundry.services.ai.azure.com
    auth: { use_azure_ad: true }        # preferred: DefaultAzureCredential / Managed Identity
    # OR an API key:
    # auth:
    #   api_key: ${FOUNDRY_API_KEY}

use_azure_ad: true разрешается через DefaultAzureCredential: Managed Identity в AKS, ACI или App Service; Azure CLI; или учётные данные из окружения. API-ключи работают, но действуют на весь проект и не ротируются автоматически. Эндпоинт Microsoft Foundry выводится из resource:; задайте необязательный base_url, чтобы переопределить его для суверенных облаков, таких как Azure Government.

Настройка Как
RBAC Предоставьте удостоверению шлюза роль Foundry User или Cognitive Services User на ресурс Microsoft Foundry
Развёртывания Microsoft Foundry использует выбранные администратором имена развёртываний, а не канонические идентификаторы моделей. Добавьте блок models:, сопоставляющий каждый канонический ID с именем вашего развёртывания.
AKS (workload identity) Настройте федерацию User-Assigned Managed Identity с OIDC-издателем кластера и привяжите её к сервисному аккаунту шлюза. use_azure_ad: true подхватывает её через WorkloadIdentityCredential.
ACI / App Service Включите для ресурса управляемое удостоверение, назначаемое системой или пользователем. use_azure_ad: true подхватывает его.
В любом другом месте auth: { api_key: "${FOUNDRY_API_KEY}" }. Заключайте ${…} в кавычки внутри { }.

Статические заголовки в запросах к upstream

Чтобы добавить фиксированные заголовки к запросам, которые шлюз отправляет одному upstream, задайте для этого upstream headers:. Используйте это, если ваш прокси перед провайдером маршрутизирует или учитывает трафик по заголовку.

headers: требует Claude Code v2.1.277 или новее на сервере шлюза. Более ранний шлюз отказывается запускаться, обнаружив этот ключ. Обновите все реплики, прежде чем добавлять ключ, и удалите ключ, прежде чем откатываться на более раннюю версию.

Заголовки отправляются на сервер, указанный в base_url, или на собственный эндпоинт провайдера, если base_url не задан. Провайдер тоже их получает, если ваш прокси их не удаляет.

В этом примере upstream с provider: vertex доступен через прокси по адресу upstream-proxy.internal.example.com. Задаётся заголовок x-source, который читает прокси, и отправляется токен из переменной окружения PROXY_TOKEN в виде x-proxy-token:

upstreams:
  - provider: vertex
    region: us-east5
    project_id: example-prod
    base_url: https://upstream-proxy.internal.example.com
    auth: {}
    headers:
      x-source: claude-apps-gateway
      x-proxy-token: ${PROXY_TOKEN}

Значения — печатаемый текст ASCII без пробелов в начале и в конце. Заключайте число, true или false в кавычки, чтобы YAML читал их как текст.

Чтобы не хранить секрет в файле конфигурации, используйте подстановку секретов для загрузки значения из переменной окружения через ${VAR} или из файла через ${file:/path}. Если ${VAR} разрешается в пустое значение, шлюз не запустится.

headers: работает для любого провайдера, и каждый upstream отправляет только свои заголовки.

Не каждый запрос, который шлюз отправляет upstream, содержит их:

Запрос, который шлюз отправляет этому upstream Содержит headers:
/v1/messages, потоковый или нет, и /v1/messages/count_tokens Да
Запрос, переключившийся с другого upstream Да, только headers: этого upstream
Вызов CountTokens Amazon Bedrock для запроса, который клиент прервал Нет
Обмен токенов Workload Identity Federation Нет

На upstream Amazon Bedrock или Claude Platform on AWS, который подписывает запросы с помощью AWS SigV4, эти заголовки входят в подпись, поэтому ваш прокси должен передавать их без изменений.

Если вы используете имя, зарезервированное шлюзом, он отказывается запускаться, а ошибка запуска называет этот заголовок. К зарезервированным относятся:

  • authorization и x-api-key
  • host, content-type и user-agent
  • Любое имя, начинающееся с anthropic-, x-goog-, x-amz- или x-amzn-

Несколько вышестоящих провайдеров

Один и тот же провайдер может встречаться несколько раз с разными значениями name:. Это покрывает разные регионы, разные аккаунты через разные цепочки учётных данных, выделенную пропускную способность в сравнении с оплатой по запросу, а также переключение на другого провайдера в качестве резервного варианта.

Шлюз перебирает вышестоящих провайдеров по порядку. При 5xx, 429, 401, 403, 404, таймаутах и отсутствующем эндпоинте (501) происходит переключение на следующего; при остальных 4xx — нет.

429 относится к ёмкости конкретного вышестоящего провайдера, поэтому исчерпание выделенной пропускной способности (PT) приводит к переключению на оплату по запросу. Если для вышестоящего провайдера задан forward_user_identity: true, то 429 в ответ на запрос, содержащий email разработчика, означает отказ для конкретного пользователя и не приводит к переключению.

Запрос переходит к следующему вышестоящему провайдеру только в следующих случаях:

  • Вышестоящий провайдер вернул ошибку
  • Вышестоящий провайдер не обслуживает запрошенную модель
  • У вышестоящего провайдера есть список groups, в который разработчик не входит

Шлюз не хранит сведений о вышестоящих провайдерах, вернувших ошибку, поэтому, пока провайдер недоступен, каждый доходящий до него запрос всё равно обращается к нему и ждёт ошибки, прежде чем перейти дальше.

Шлюз ждёт начала ответа в течение следующего времени:

  • Вышестоящие провайдеры provider: anthropic: timeouts.upstream_ttfb_ms, по умолчанию 120 секунд
  • Другие провайдеры: до одного часа. Чтобы сократить это ожидание для потоковых запросов, задайте timeouts.upstream_ttfb_ms на шлюзе версии v2.1.295 или новее. Непотоковые запросы к модели в любом случае ждут до одного часа

404 относится к доступности модели у конкретного вышестоящего провайдера, поэтому провайдер, у которого модель не включена, не блокирует следующего провайдера, который её обслуживает. Вышестоящий провайдер, который не может сопоставить запрошенную модель, пропускается без сетевого обращения.

В этом примере запросы сначала направляются в выделенную пропускную способность Amazon Bedrock, излишек уходит на оплату по запросу и во второй аккаунт, а в качестве последнего резервного варианта используется Anthropic API:

upstreams:
  # Primary: provisioned throughput in your home region.
  - name: bedrock-pt
    provider: bedrock
    region: us-east-1
    auth: {}
  # Overflow: on-demand cross-region.
  - name: bedrock-od
    provider: bedrock
    region: us-west-2
    auth: {}
  # Different account: a separate Bedrock allotment via static keys.
  - name: bedrock-acct2
    provider: bedrock
    region: us-east-1
    auth:
      aws_access_key_id: ${ACCT2_AKID}
      aws_secret_access_key: ${ACCT2_SK}
  # Last resort: direct Anthropic API.
  - name: anthropic-fallback
    provider: anthropic
    auth:
      api_key: ${ANTHROPIC_API_KEY}

# Per-upstream model IDs are keyed on the upstream's `name:`.
models:
  - id: claude-opus-4-8
    label: Claude Opus 4.8
    upstream_model:
      bedrock-pt: arn:aws:bedrock:us-east-1:111111111111:provisioned-model/abcdef
      bedrock-od: us.anthropic.claude-opus-4-8
      bedrock-acct2: us.anthropic.claude-opus-4-8
      anthropic-fallback: claude-opus-4-8
Инструмент Как
Разные регионы Один вышестоящий провайдер Amazon Bedrock на регион, у каждого свой region:. С auto_include_builtin_models: true межрегиональные профили инференса маршрутизируются автоматически; для развёртываний, привязанных к региону, используйте блок models:.
Разные аккаунты Один вышестоящий провайдер Amazon Bedrock на аккаунт. Цепочка по умолчанию (auth: {}) использует идентичность пода; для второго аккаунта добавьте assume_role, чтобы обращаться к нему с краткосрочными учётными данными, или задайте явные учётные данные либо Bearer-токен в auth:.
Разные команды Задайте вышестоящему провайдеру каждой команды список groups, чтобы к нему обращались только разработчики из этих групп IdP. См. Направление каждой команды к её собственному вышестоящему провайдеру.
Выделенная пропускная способность Сопоставьте модель с ARN выделенной пропускной способности в models: для имени этого вышестоящего провайдера. Остальные провайдеры сохраняют ID для оплаты по запросу, поэтому ёмкость PT исчерпывается до переключения.
Эндпоинты VPC / FIPS Задайте для вышестоящего провайдера base_url: с URL вашего эндпоинта VPC или FIPS
Маршрутизация по модели Пользовательский id модели, то есть не встроенной модели Claude, пропускает вышестоящих провайдеров, отсутствующих в его карте upstream_model:. Вышестоящий провайдер со списком models, который обязателен для вышестоящего провайдера mantle, используется только для этих моделей.
Маршрутизация встроенных моделей Для вышестоящего провайдера без списков models и groups шлюз перебирает встроенные модели по порядку и использует ID провайдера по умолчанию, если в карте upstream_model: нет записи. Для встроенной модели, у которой есть ID по умолчанию у провайдера, карта меняет то, какой ID получает вышестоящий провайдер, а не то, будет ли он использован. Вышестоящий провайдер, отклоняющий ID, подчиняется тем же правилам переключения, что и при любой другой ошибке вышестоящего провайдера.

Переключение между облачными провайдерами или на прямой Anthropic API меняет то, какое соглашение, география и другие условия применяются к запросу.

CLI применяет одинаковое ограничение функций к шлюзам независимо от того, какой вышестоящий провайдер обслуживает конкретный запрос, поэтому по умолчанию при переключении не отправляется поле тела, которое вышестоящий провайдер отклонил бы. Если вы задали в политике одночасовой TTL кэша, он отправляется всем вышестоящим провайдерам в списке, поэтому задавайте его, только если все они его принимают.

Направление каждой команды к её собственному вышестоящему провайдеру

Чтобы направлять запросы каждой команды в её собственный аккаунт AWS или проект Google Cloud, укажите по одному вышестоящему провайдеру на команду и задайте каждому список groups. К такому провайдеру обращаются только разработчики из указанной группы IdP — как при первой попытке, так и при переключении. groups поддерживается всеми провайдерами. Требуется Claude Code v2.1.314 или новее на сервере шлюза.

В этом примере группы payments-eng и search-eng получают по аккаунту AWS, а также добавлен вышестоящий провайдер без списка groups, которым может пользоваться любой разработчик:

upstreams:
  - name: bedrock-payments
    provider: bedrock
    region: us-east-1
    auth: {}
    assume_role:
      role_arn: arn:aws:iam::111111111111:role/claude-gateway-bedrock
    groups: [payments-eng]
  - name: bedrock-search
    provider: bedrock
    region: us-east-1
    auth: {}
    assume_role:
      role_arn: arn:aws:iam::222222222222:role/claude-gateway-bedrock
    groups: [search-eng]
  - name: bedrock-shared               # no groups: open to everyone, so listed last
    provider: bedrock
    region: us-east-1
    auth: {}

С этой конфигурацией запросы каждого разработчика начинаются с первого вышестоящего провайдера в его строке и при переключении переходят к следующему:

Группы разработчика Вышестоящие провайдеры по порядку
payments-eng bedrock-payments, затем bedrock-shared
search-eng bedrock-search, затем bedrock-shared
payments-eng и search-eng bedrock-payments, затем bedrock-search, затем bedrock-shared
Ни одна из них bedrock-shared

Когда вышестоящий провайдер команды отклоняет запрошенную модель с кодом 403, шлюз пробует следующего провайдера в строке этой команды, который обслуживает модель. Чтобы удержать команду на одном вышестоящем провайдере, задайте каждому провайдеру список groups и убедитесь, что ни один другой провайдер не содержит группу, в которую входят разработчики команды. Тогда у этой команды нет переключения, а запросы от разработчиков, не входящих ни в одну указанную группу, завершаются ошибкой 400.

Чтобы каждый разработчик попадал к нужному вышестоящему провайдеру, указывайте записи, совпадающие в точности, и размещайте открытых провайдеров последними:

  • Записи: указывайте каждую группу в точности так, как ваш IdP отправляет её в claim групп, который также читает match.groups. Шлюз отказывается запускаться, если находит пустой список или пустую запись. Он не сверяет записи с вашим IdP, поэтому запись, которой никто не соответствует, не вызывает предупреждения.
  • Порядок: размещайте вышестоящего провайдера без списка groups последним. Он обслуживает всех, поэтому, если указать его раньше, он будет забирать запросы команды раньше её собственного провайдера.

[!WARNING]

Шлюз версии ниже v2.1.314 отказывается запускаться, если находит groups, поэтому обновите все реплики, прежде чем добавлять его.

Перед откатом версии удалите каждого вышестоящего провайдера со списком groups, а также все ключи upstream_model и переопределения цен, которые на него ссылаются, и оставьте хотя бы одного вышестоящего провайдера. Если удалить только ключ groups, этот провайдер становится открыт для всех разработчиков. Ключ или переопределение, всё ещё ссылающиеся на удалённого провайдера, не дают шлюзу запуститься с ошибкой references unknown upstream.

Что происходит, если разработчик не входит ни в одну указанную группу

Если у каждого вышестоящего провайдера есть список groups, разработчик, не входящий ни в одну из этих групп, видит следующую ошибку, и шлюз не обращается ни к одному провайдеру:

API Error: 400 you aren't in a group that can use this gateway. Ask your administrator to add you to one

Добавьте разработчика в одну из указанных групп в вашем IdP или добавьте вышестоящего провайдера без списка groups.

Шлюз заново считывает группы разработчика при каждом обновлении токена. Если ваш IdP не включает группы в обновление, у разработчика их не остаётся:

  • Задан oidc.allowed_groups: шлюз отклоняет обновление, и сессия завершается
  • Иначе, если есть вышестоящий провайдер без списка groups: запросы разработчика переходят к нему
  • Иначе, если у каждого вышестоящего провайдера есть список groups: запросы разработчика завершаются этой ошибкой

Если userinfo-эндпоинт вашего IdP возвращает claim групп, а oidc.google_groups не задан, установите oidc.userinfo_fallback в true, чтобы получать группы оттуда.

Необязательные разделы

login_notice

Чтобы показывать разработчикам уведомление при входе, задайте в ключе верхнего уровня login_notice текст уведомления длиной до 500 символов. В этом примере указано, для кого предназначен шлюз и куда обращаться за доступом:

login_notice: This gateway is for Example Corp staff. For access questions, email it-help@example.com.

Разработчики видят этот текст под заголовком Notice from <gateway hostname> на странице подтверждения шлюза в браузере и на интерактивном экране входа в терминале. Переносы строк в тексте заменяются пробелами. Уведомление отображается до входа, поэтому его может прочитать любой, кто может подключиться к шлюзу.

Требуется Claude Code v2.1.319 или новее на сервере шлюза, а для экрана в терминале — также на компьютере разработчика. Более ранняя версия шлюза отказывается запускаться, обнаружив этот ключ. Обновите все реплики, прежде чем добавлять ключ, и удалите ключ перед откатом.

admin

Необязательный. Включает /v1/organizations/spend_limits, который повторяет публичный Admin API Anthropic, и применение лимитов расходов для каждого разработчика на /v1/messages. О том, как задаются и применяются лимиты, см. Лимиты расходов; в этом разделе описаны ключи gateway.yaml, которые включают и настраивают эту функцию.

admin:
  # Named static API keys for the admin endpoints, sent as x-api-key.
  # The id appears in the audit log as admin-key:<id> so each key is
  # attributable. Array for rotation: add the new key, roll clients,
  # remove the old.
  write_keys:
    - { id: terraform, key: "${GATEWAY_ADMIN_WRITE_KEY_TF}" }
    - { id: ci,        key: "${GATEWAY_ADMIN_WRITE_KEY_CI}" }
  read_keys:
    - { id: reporting, key: "${GATEWAY_ADMIN_READ_KEY}" }
  # IdP groups granted full admin via the normal gateway JWT (no API key).
  admin_groups: [platform-finops]
  blocked_message: request an increase at https://go.example.com/claude-limits
  # Try eng-platform's pooled budget first, then eng-all's, then any other group's.
  pooled_conflict_rule: priority_list
  pooled_priority_order: [eng-platform, eng-all]
Поле Обязательное Описание
write_keys Нет Массив {id, key}. x-api-key, совпадающий с одним из них, может получать список лимитов расходов, задавать и удалять их. Значения ключей должны содержать не менее 32 символов; id должны быть уникальными среди read_keys и write_keys.
read_keys Нет Массив {id, key}. Только для чтения: все эндпоинты GET, включая получение списка лимитов, получение одного лимита по ID и чтение /effective и /audit.
admin_groups Нет Имена групп IdP. JWT шлюза, claim groups которого содержит одну из них, получает полный доступ администратора на чтение и запись и записывается в журнал аудита как oidc:<sub>. Используйте это для администраторов-людей, а API-ключи — для машин. Пустой элемент в этом списке останавливает шлюз при запуске. См. Значения matcher, которые останавливают шлюз при запуске.
blocked_message Нет Дословно добавляется к 429 billing_error, который видит заблокированный разработчик. Напишите полную инструкцию, например URL или канал Slack. Если поле не задано, шлюз отправляет только сообщение по умолчанию. См. Как работает применение лимитов.
audit_retention_days Нет По умолчанию 365. Более старые строки admin_audit удаляются.
spend_retention_months Нет По умолчанию 13. Строки счётчиков spend старше этого срока удаляются. Значение по умолчанию сохраняет полный год плюс текущий неполный месяц для сравнения год к году.
identity_retention_days Нет По умолчанию 90. TTL с момента последнего появления для строк principal_emails, которые хранят email, отображаемое имя и группы каждого разработчика (PII). Намеренно короче срока хранения расходов, чтобы удалённая учётная запись со временем исчезала, а её анонимные счётчики расходов сохранялись.
group_limit_mode Нет min (по умолчанию) или max. Когда разработчик состоит в нескольких группах с лимитами, min применяет самый строгий, а max — самый мягкий. Используется и при применении лимитов, и в /effective.
pooled_conflict_rule Нет default_order (по умолчанию) или priority_list. Порядок, в котором шлюз перебирает общие бюджеты разработчика. См. Порядок общих бюджетов. Требуется v2.1.319 или новее.
pooled_priority_order При priority_list До 50 имён групп, каждое указано один раз и написано так, как его отправляет ваш IdP. Группы, общие бюджеты которых шлюз перебирает первыми. См. Порядок общих бюджетов. Требуется v2.1.319 или новее.

Порядок общих бюджетов

Общий бюджет — это единый месячный лимит, из которого расходует вся группа. Чтобы задать его, добавьте pooled_budget в запрос, задающий месячный лимит группы, например "pooled_budget": {"amount": "500000"} для $5,000. Запрос также принимает scope группы, "period": "monthly" и amount, который остаётся личным лимитом каждого участника.

Для разработчика, состоящего в нескольких таких группах, каждый запрос засчитывается в первый бюджет, расходы по которому ниже его лимита, и отклоняется, когда исчерпаны все бюджеты. pooled_conflict_rule задаёт порядок, в котором шлюз перебирает бюджеты:

  • default_order: сначала самый большой лимит, а равные лимиты — по возрастанию имени группы
  • priority_list: бюджеты групп из pooled_priority_order в порядке списка, затем бюджеты остальных групп по имени группы

Если вы перечислите группы без pooled_conflict_rule: priority_list, шлюз проигнорирует список и запишет предупреждение в лог при запуске.

Сервер шлюза версии ниже v2.1.319 отказывается запускаться, обнаружив pooled_conflict_rule или pooled_priority_order. Обновите все реплики, прежде чем добавлять любой из этих ключей, и удалите оба ключа перед откатом.

enforcement

Блок enforcement управляет поведением проверок лимитов расходов, когда хранилище недоступно.

Поле Обязательное Описание
fail_closed_on_error Нет По умолчанию false. При сбое Postgres применение лимитов расходов отключается (fail open), поэтому инференс продолжает работать. Установите true, чтобы блокировать при сбое (fail closed): разработчики, превысившие лимит, блокируются, но если хранилище недоступно, блокируются и все остальные. Требует блока admin:: применение лимитов расходов работает, только когда настроен admin, и шлюз отказывается запускаться, если вы установили здесь true без него.

pricing

Блок pricing сообщает счётчику расходов, какие цены использовать вместо прейскурантных в USD, чтобы лимиты и /effective отражали ваши договорные тарифы. Суммы остаются в USD и являются оценкой, а не счётом. Два предварительных требования:

  • Claude Code v2.1.227 или новее на сервере шлюза. Более ранние версии отклоняют неизвестный ключ при запуске.
  • Блок admin: или, в v2.1.268 и новее, блок managed: хотя бы с одной политикой. Шлюз отказывается запускаться, если задан pricing и нет ни одного из этих блоков, поскольку его никто не будет читать.
pricing:
  multiplier: 0.85
  overrides:
    - upstream: bedrock-eu
      model: claude-sonnet-4-6
      input: 3.30
      output: 16.50
      cache_read: 0.33
      cache_write: 4.125
Поле Обязательное Описание
multiplier Нет По умолчанию 1. Счётчик умножает на это значение каждую учитываемую сумму, будь она по прейскуранту или переопределённой, поэтому 0.85 начисляет 85% цены. Должно быть больше 0 и не больше 10, а значение выше 1 является наценкой.
overrides Нет Строки {upstream, model, input, output, cache_read, cache_write} в USD за миллион токенов. Все четыре тарифа обязательны. Каждый должен быть больше 0 и не больше 10000.

Как счётчик сопоставляет строку переопределения:

  • Строка заменяет прейскурантную цену для запросов, которые upstream, то есть upstreams[].name, обслуживает для model. Это включает повышенный тариф быстрого режима, поэтому быстрые и стандартные запросы учитываются по одним и тем же четырём тарифам.
  • Встроенный ID, например claude-sonnet-4-6, сопоставляемый так же, как models[].id, охватывает все датированные формы, региональные формы Amazon Bedrock или формы Google Cloud Agent Platform, которые счётчик тарифицирует как эту модель. Любая другая строка, например псевдоним или ARN профиля инференса, сопоставляется без учёта регистра с ID, отправленным клиентом, или со строкой, отправленной в upstream.
  • Если строки пересекаются, счётчик выбирает самую конкретную строку, а не первую: строку, чей model точно совпадает со строкой модели, отправленной в upstream, затем строку, совпадающую с точным ID, отправленным клиентом, затем строку, называющую встроенную модель.
  • Неизвестное имя upstream приводит к ошибке при запуске, как и две строки для одного upstream с одной и той же моделью, включая два написания одной встроенной модели. Шлюз выдаёт предупреждение при запуске о строке, которую не может использовать ни одна запрашиваемая модель.
  • Запросы веб-поиска остаются по прейскурантной цене $0.01; множитель к ним всё равно применяется.

Для тарифов по регионам задайте каждому региону собственный именованный upstream и по одной строке на каждый upstream.

Наценка на цены

С v2.1.271 или новее на сервере шлюза вы можете установить multiplier выше 1, вплоть до 10, чтобы учитывать больше, чем взимает провайдер, например по внутреннему тарифу перевыставления затрат. В этом примере каждый запрос учитывается по 120% цены:

pricing:
  multiplier: 1.2

При наличии блока admin: наценка применяется и к лимитам расходов. Счётчик учитывает 120% цены, поэтому разработчики достигают своих лимитов раньше. Шлюз записывает в лог предупреждение об этом при запуске.

Множитель не меняет того, что upstream-провайдер взимает за запросы.

Если шлюз также отправляет тарифы клиентам, вошедшим в систему, разработчикам нужен Claude Code v2.1.271 или новее, чтобы видеть наценку. Более ранние клиенты игнорируют multiplier выше 1 и показывают затраты без него.

Сервер шлюза версии ниже v2.1.271 отказывается запускаться, если вы установили multiplier выше 1.

Отправка тарифов клиентам, вошедшим в систему

С v2.1.268 или новее на сервере шлюза шлюз также помещает ставки из pricing в обслуживаемые им политики managed в виде управляемой настройки modelPricing.

Разработчики, подпадающие под политику, затем видят ставки pricing в /usage, строке состояния и OpenTelemetry. Разработчик, не подпадающий ни под одну политику, не получает управляемых настроек, поэтому его показатели остаются по прейскурантной цене. Клиенты применяют эту настройку в Claude Code v2.1.242 или новее.

  • Что добавляет шлюз: если блок cli политики ещё не задаёт modelPricing, шлюз добавляет multiplier и, для каждого ID модели, который может запросить клиент, строку переопределения первого upstream, обслуживающего этот ID. Тариф, который взимает только резервный upstream, остаётся на шлюзе.
  • Upstream со списком groups: если такой upstream — первый, обслуживающий ID модели, шлюз не добавляет строку для этого ID. Тогда разработчики видят собственную ставку Claude Code для этого ID — стандартную ставку модели, если Claude Code распознаёт ID, — умноженную на multiplier.
  • Исключение отдельной политики: установите modelPricing в {} в блоке cli этой политики, и её разработчики останутся на прейскурантных ценах.
  • Сохранение собственных тарифов политики: политика, блок cli которой задаёт modelPricing с собственными multiplier или overrides, сохраняет этот modelPricing целиком, и шлюз не добавляет в него свои тарифы.

models

Блок models — необязательный список моделей, курируемый администратором; он отдаётся на /v1/models и используется для преобразования ID моделей для каждого upstream. Он обязателен для регионов Amazon Bedrock за пределами США, ARN provisioned throughput в Amazon Bedrock и имён развёртываний Microsoft Foundry.

auto_include_builtin_models: true   # false: expose only the list below
models:
  - id: claude-opus-4-8
    label: Claude Opus 4.8
    # description: optional text shown in clients that surface it
    upstream_model:
      anthropic: claude-opus-4-8
      bedrock: us.anthropic.claude-opus-4-8   # or an inference-profile ARN
      foundry: your-opus-deployment-name

Каждый ключ в upstream_model должен совпадать с name настроенного upstream, которое по умолчанию равно имени провайдера. Ключ, не совпадающий ни с одним upstream, приводит к ошибке при запуске, поэтому опустите строки для провайдеров, которые вы не используете.

Чтобы разработчики могли использовать псевдоним fable при auto_include_builtin_models: false, добавьте запись claude-fable-5 в models. Это ID, в который псевдоним fable разрешается для разработчиков, вошедших через шлюз. Без неё их сообщения завершаются ошибкой, начинающейся с API Error: 400 model claude-fable-5 is not in the operator's model allowlist.

managed

Блок managed определяет политики доступа на основе ролей, привязанные к группам IdP или домену email. Политики оцениваются по порядку; по умолчанию выбирается первое совпадение, которое затем объединяется с базовой политикой match: {}, охватывающей всех. Пользователь, подпадающий под две ролевые политики, получает только первую, поэтому правила запрета второй политики не применяются, если вы не примените все подходящие политики. Политики обслуживаются для каждого пользователя по адресу GET /managed/settings с кэшированием ETag/304.

managed:
  policies:
    # Specific groups first.
    - match: { groups: [eng-contractors] }
      cli:
        availableModels: [claude-sonnet-4-6]
        permissions: { deny: ["WebFetch", "WebSearch"] }
    # Default catch-all last: matches everyone who authenticated.
    - match: {}
      cli:
        availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
        # Make the Default option in /model resolve inside each policy's
        # list. The eng-contractors policy inherits enforceAvailableModels.
        enforceAvailableModels: true

Универсальная политика match: {}, которую по соглашению указывают последней, рассматривается как базовый слой. Любая другая политика наследует от неё каждый ключ, который сама не задаёт, поэтому в ролевых записях нужно перечислять только то, что отличается от значений по умолчанию для организации. Правила объединения зависят от типа ключа:

  • Списки разрешённых: availableModels и permissions.allow. Список конкретной политики полностью заменяет базовый.
  • Списки запрещённых и массивы хуков: берётся объединение базовой и конкретной политики:
    • permissions.deny и permissions.ask
    • disabledMcpjsonServers и deniedMcpServers
    • blockedMarketplaces и deniedModels
    • Массивы типов событий hooks
  • Ключи типа record: env, modelOverrides и skillOverrides. Они объединяются поверхностно, поэтому ролевой блок env переопределяет заданные в нём ключи, а остальные наследует от базы.

availableModels также применяется на стороне сервера на /v1/messages, поэтому запрещённая модель возвращает 400 независимо от того, что отправляет клиент. Пустой список запрещает все модели. Проверка также охватывает модель, с которой сессия начинается до того, как разработчик выберет модель, поэтому запускайте сессии на модели, разрешённой политикой.

Шлюз сам проверяет значение model, прежде чем передать запрос, поэтому некорректное значение никогда не достигает upstream. Он отклоняет запрос с 400 в двух случаях:

  • Когда значение отсутствует или пустое, шлюз отклоняет запрос с сообщением model is required. Для этой проверки нужен шлюз с Claude Code v2.1.228 или новее.
  • Когда значение присутствует, но не является строкой, шлюз отклоняет запрос с сообщением model must be a string. Требуется шлюз с Claude Code v2.1.221 или новее.
Matcher Поведение
match: {} Совпадает с любым аутентифицированным пользователем. Начните с такой политики и позже добавьте над ней политики для групп.
match: { groups: [a, b] } Совпадает, если claim groups в JWT содержит любую из перечисленных групп. С учётом регистра: группы должны совпадать с точным написанием в IdP.
match: { email_domain: example.com } Сопоставляется с частью после последнего @ в claim email из JWT, без учёта регистра. Принимает один домен на политику.
match: { groups: [a], email_domain: example.com } Должны выполняться оба условия

Аутентифицированный пользователь, не подпадающий ни под одну политику, получает значения шлюза по умолчанию, то есть все модели из каталога и никаких управляемых настроек. Добавьте последней универсальную политику match: {}, если вам нужна гарантированная политика по умолчанию.

Размещайте правила запрета на уровне организации в политике match: {}, потому что правила групповой политики применяются только пока токен пользователя содержит эту группу.

[!NOTE]

Шлюз не хранит собственного каталога пользователей. Он авторизует каждый запрос по токену IdP пользователя, считывая членство в группах из claim groups токена и вычисляя политики по нему. Нет списка пользователей для перечисления и нет учётных записей для предварительного создания, а значит, нет и эндпоинта SCIM, потому что SCIM нечего синхронизировать.

Управляйте жизненным циклом пользователей и групп в источнике истины — через встроенную подготовку SCIM вашего IdP или специализированную платформу управления учётными данными. Членство и отзыв доступа, управляемые там, автоматически попадают в шлюз через токен. Если вам нужна подготовка учётных записей Claude через SCIM, это возможность Claude for Enterprise.

Действуют два срока распространения изменений:

  • Содержимое политики: изменение политики и повторное развёртывание доходят до подключённых клиентов Claude Code при их следующем опросе управляемых настроек, в течение часа, за исключением изменений, которые применяются только при следующем запуске
  • Членство в группах: изменение членства пользователя в группах меняет то, какая политика с ним совпадает. Это вступает в силу при следующем перевыпуске сессии, то есть при следующем фоновом обновлении, не позднее session.ttl_hours.

Claude Desktop следует собственному расписанию.

Применение всех подходящих политик

Пользователь, подпадающий под несколько ролевых политик, получает только первую, если вы не зададите policy_mode: layered рядом с policies. С layered применяется каждая политика, под которую подпадает пользователь, вплоть до первой политики match: {}.

policy_mode требует Claude Code v2.1.316 или новее на сервере шлюза. Шлюз версии без поддержки этого ключа отказывается запускаться, обнаружив его. Обновите все реплики, прежде чем добавлять ключ, и удалите ключ перед откатом на более раннюю версию. В этом примере одна группа теряет WebFetch, а другая получает Opus:

managed:
  policy_mode: layered
  policies:
    - match: { groups: [no-web] }
      cli:
        permissions: { deny: ["WebFetch"] }
    - match: { groups: [opus-users] }
      cli:
        availableModels: [opus, sonnet]
    - match: {}
      cli:
        availableModels: [sonnet]
        enforceAvailableModels: true

В таблице показано, что получает пользователь, состоящий и в no-web, и в opus-users, при режиме по умолчанию, first_match, и при layered.

Настройка first_match layered
availableModels sonnet opus, sonnet
enforceAvailableModels true true
permissions.deny WebFetch WebFetch

Шлюз объединяет каждую подходящую политику с политиками, указанными ниже неё, по тем же правилам объединения, что и для базового слоя:

  • Списки разрешённых, одиночные значения и блоки, такие как sandbox: каждый берётся целиком из первой по порядку подходящей политики, которая его задаёт, поэтому списки availableModels двух групп не суммируются.
  • Списки запрещённых и массивы хуков: суммируются по всем подходящим политикам, поэтому пользователь в двух группах получает правила запрета обеих групп.
  • env, modelOverrides и skillOverrides: записи объединяются по имени, и значение для имени берётся из первой по порядку подходящей политики, которая его задаёт.
  • Ключи desktop: объединяются по правилам для базового блока desktop.

[!WARNING]

В сумме политики могут дать более мягкие правила, чем любая из них по отдельности. Например, политика match: {} задаёт sandbox.enabled: true, политика одной группы задаёт permissions.allow: ["Bash"], а политика другой — sandbox.enabled: false. Пользователь в обеих группах получает разрешённый Bash с выключенной песочницей. В таком случае укажите первой политику, разрешающую Bash, и скопируйте в неё весь блок sandbox политики match: {}.

С layered шлюз отказывается запускаться при некоторых настройках, в том числе таких:

  • Шаблон с !: отрицание ! в правиле Read или Edit в списке permissions.deny или permissions.ask любой политики, включая политику match: {}
  • Ограничение хуков вне политики, охватывающей всех: disableAllHooks, allowedHttpHookUrls или httpHookAllowedEnvVars в любой политике, кроме match: {}

Запуск сессий на модели, разрешённой политикой

Если availableModels не включает модель Claude Code по умолчанию, сессии получают ответы 400, пока разработчик не выберет модель из списка, например с помощью /model. В сессиях через шлюз моделью по умолчанию является модель Opus, на которую указывает псевдоним opus, и availableModels сам по себе её не меняет.

Чтобы это исправить, установите enforceAvailableModels: true в том же блоке cli, а затем проверьте, какого рода записи содержит список:

  • Псевдоним, например sonnet, или встроенный ID, например claude-sonnet-4-6: сессии запускаются на одной из этих моделей, и вариант Default в /model указывает на неё
  • В списке нет ни псевдонима, ни встроенного ID: сессии могут продолжать запускаться на встроенной модели по умолчанию, поэтому также установите model в один из перечисленных ID в блоке cli этой политики

Эта политика перечисляет один пользовательский ID, определённый в models, и запускает сессии на этом ID:

managed:
  policies:
    - match: { groups: [restricted-projects] }
      cli:
        availableModels: [restricted-claude-opus-4-8]
        enforceAvailableModels: true
        model: restricted-claude-opus-4-8
        env:
          ANTHROPIC_DEFAULT_OPUS_MODEL: restricted-claude-opus-4-8   # opus and Default resolve to the ID too

Значения matcher, которые останавливают шлюз при запуске

При запуске шлюз проверяет блок match каждой политики и список admin_groups. Любое из этих значений останавливает шлюз с ошибкой, в которой названо поле:

  • Пустой список groups
  • Пустой элемент в groups или в admin_groups
  • Пустой email_domain
  • email_domain, содержащий @, пробельный символ или запятую. Перед этой проверкой шлюз обрезает значение и удаляет один начальный @. Укажите один домен без лишних символов, например example.com.

До v2.1.232 шлюз запускался с этими значениями. Каждое из них имело следующий эффект:

  • Пустой email_domain: шлюз пропускал проверку домена, поэтому политика с пустым email_domain и без списка groups совпадала с любым аутентифицированным пользователем
  • Пустой список groups: политика не совпадала ни с кем
  • email_domain, содержащий @, пробельный символ или запятую: политика не совпадала ни с кем
  • Пустой элемент в groups или в admin_groups: элемент совпадал с пользователем, только если claim groups этого пользователя в IdP тоже содержал пустой элемент. В admin_groups такое совпадение давало доступ администратора. Если ваш список admin_groups никогда не содержал пустого элемента, никто не получил доступ администратора таким образом.

Выбор между cli и code

[!WARNING]

Когда политика использует ключ code, каждое из следующих условий не даёт шлюзу запуститься:

  • Версия шлюза: code требует Claude Code v2.1.296 или новее на сервере шлюза. Более ранний шлюз отказывается запускаться, обнаружив этот ключ. Обновите все реплики, прежде чем добавлять ключ, и замените code обратно на cli, прежде чем откатываться на более раннюю версию.
  • Смешанные ключи: файл, в котором есть и code, и cli или его прежнее написание settings, останавливает шлюз при запуске. Поместите все блоки под один ключ за одну правку.

Настройки Claude Code для политики, например правило, запрещающее чтение файлов .env, помещаются в блок под ключом cli или code. code — рекомендуемый ключ, а cli — устаревший. Оба ключа принимают одинаковое содержимое. Ключ определяет, где применяются настройки:

  • cli: терминал, расширения VS Code и JetBrains, а также Agent SDK. При cli вкладка Code в Claude Desktop получает производные настройки, поэтому ограниченное правило, например Read(./.env), не останавливает там пользователя.
  • code: те же места, и при этом может быть охвачена вкладка Code в Claude Desktop.

Файл, использующий cli, работает как раньше, а шлюз, обнаруживший cli в политике с ключом desktop, выдаёт предупреждение при запуске и всё равно запускается. Перейдите на code, чтобы настройки могли охватывать и вкладку Code.

Прежде чем переходить, прочитайте раздел Применение настроек code во вкладке Code. Политике нужен ключ desktop, а машины пользователей требуют настройки, прежде чем настройки начнут там действовать, и в Claude Desktop отключается веб-поиск.

Эта политика помещает правило запрета под code с пустым ключом desktop:

managed:
  policies:
    - match: {}
      code:
        permissions: { deny: ["Read(./.env)"] }
      desktop: {}

При переходе удалите все строки serve_to_desktop в той же правке, в которой переименовываете блоки. Там, где в инструкции упоминается блок cli, используйте ваш блок code.

serve_to_desktop: true — устаревший способ предложить настройки cli политики вкладке Code. Он не действует, когда Claude Desktop подключается через bootstrapUrl. Пока ваши политики используют cli, предупреждение при запуске, упоминающее этот ключ, означает, что эти настройки не доходят до вкладки Code:

  • Чтобы охватить вкладку Code: перейдите на code, как только машины пользователей будут соответствовать условиям из раздела Применение настроек code во вкладке Code
  • Чтобы остаться на cli: установите serve_to_desktop: false рядом с cli в политике, чтобы убрать предупреждение

Что помещать в cli

Каждое значение code или cli — это полный документ managed-settings.json Claude Code, с той же схемой, которую вы развёртывали бы через MDM или /etc/claude-code/managed-settings.json, но записанный здесь в формате YAML. CLI применяет доставленный документ на управляемом уровне, выше пользовательских и проектных настроек, вместо управляемых настроек сервера. Поэтому он игнорирует настройки, доступные только из источников политик уровня ОС, такие как policyHelper и wslInheritsWindowsSettings.

Шлюз проверяет каждый документ по схеме настроек CLI при запуске, поэтому нераспознанный ключ верхнего уровня приводит к ошибке запуска с перечислением всех некорректных ключей. Намеренно открытые части схемы по-прежнему принимают произвольные значения, поскольку более новые клиенты могут распознавать записи, которых нет в схеме шлюза. К таким открытым ключам относятся env, pluginConfigs и ключи, вложенные в permissions.

Поскольку проверка использует схему, поставляемую с установленной версией шлюза, чтобы поместить в управляемую конфигурацию ключ настроек верхнего уровня, появившийся в более новом выпуске Claude Code, сначала нужно обновить шлюз. Проверьте новую политику на одном клиенте, прежде чем развёртывать её.

Полный справочник ключей находится в разделе Настройки Claude Code. Ключи, к которым операторы обращаются в первую очередь:

managed:
  policies:
    - match: {}
      cli:
        # Model access (also enforced server-side at /v1/messages)
        availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
        enforceAvailableModels: true              # Default resolves inside the list

        # Permission policy
        permissions:
          deny:
            - "WebFetch"
            - "Read(./.env)"
            - "Read(./secrets/**)"
          disableBypassPermissionsMode: disable   # blocks --dangerously-skip-permissions
        allowManagedPermissionRulesOnly: true     # ignore user/project permission rules

        # Environment pushed into the CLI process. DISABLE_UPDATES blocks
        # background and manual updates; DISABLE_AUTOUPDATER stops only
        # background updates.
        env:
          DISABLE_UPDATES: "1"                    # pin versions via your own distribution

        # Org-wide hooks. Hook commands run on developer machines, not the
        # gateway, so the path must exist on every client OS in the policy.
        hooks:
          PostToolUse:
            - matcher: "Edit|Write"
              hooks:
                - { type: command, command: /usr/local/bin/audit-edit.sh }
Ключ Кем применяется Эффект
availableModels Шлюз + CLI Список разрешённых моделей. Также проверяется на /v1/messages, поэтому модифицированный клиент не может его обойти.
deniedModels, availableModelsMatch Шлюз + CLI Блокирует отдельные модели или версии, которые иначе разрешил бы availableModels. Заблокированная модель отклоняется с 400 на /v1/messages и не включается в /v1/models. Собственная проверка шлюза требует Claude Code v2.1.299 или новее на сервере шлюза. Проверка CLI требует v2.1.283 или новее на клиентах, а более ранние клиенты игнорируют оба ключа.
permissions.allow / .deny CLI Правила для инструментов и команд. См. Разрешения и что не сопоставляется правилом Bash.
permissions.disableBypassPermissionsMode CLI Установите disable, чтобы заблокировать bypassPermissions — режим, пропускающий запросы разрешений, — и флаг --dangerously-skip-permissions
allowManagedPermissionRulesOnly CLI Если true, управляемые настройки становятся единственным источником правил разрешений. В описании allowManagedPermissionRulesOnly перечислены все источники, которые Claude Code в этом случае игнорирует.
env CLI Переменные окружения, объединяемые в процесс CLI. Используйте для телеметрии, автообновления и переопределения имён моделей.
hooks CLI Хуки на уровне организации
managedMcpServers CLI Удалённые MCP-серверы, предоставляемые каждому подпадающему разработчику наряду с серверами, которые он добавляет сам; только http и sse. См. MCP-серверы в политике. Требует Claude Code v2.1.259 или новее на сервере шлюза и на клиентах. Более ранние клиенты игнорируют ключ.

Поскольку эти настройки приходят по сети, CLI показывает каждому разработчику диалоговое окно подтверждения безопасности, прежде чем применить перечисленные ниже настройки:

  • hooks
  • переменные env, требующие подтверждения разработчика, например переменные прокси и базового URL
  • настройки выполнения команд оболочки, такие как apiKeyHelper и statusLine
  • настройки бинарных файлов песочницы sandbox.bwrapPath, sandbox.socatPath и sandbox.ripgrep
  • Настройки песочницы, которые перехватывают трафик, внедряют учётные данные или ослабляют изоляцию, например sandbox.network.tlsTerminate и настройки портов прокси. Полный список приведён в разделе Диалоговые окна подтверждения безопасности.

В разделе Запоминание подтверждений описано, как долго действует подтверждение и когда диалоговое окно появляется снова.

Некоторые доставленные переменные env, например настройки выбора модели и числовые ограничения, Claude Code применяет, не показывая разработчику диалоговое окно подтверждения. Другие доставленные переменные могут требовать подтверждения разработчика; непустое значение прокси, базового URL или OTEL_EXPORTER_OTLP_ENDPOINT требует его всегда. Когда доставленная переменная требует подтверждения, она указывается в диалоговом окне. Подробности, включая четыре переключателя конфиденциальности, для которых необходимость подтверждения зависит от доставленного значения, приведены в разделе Переменные окружения и диалоговое окно подтверждения.

Конфигурация телеметрии шлюза передаёт OTEL_EXPORTER_OTLP_ENDPOINT, поэтому установка telemetry.forward_to вызывает диалоговое окно на каждом интерактивном клиенте. Диалоговое окно защищает машину разработчика от скомпрометированного или враждебного шлюза, а не организацию от разработчика.

Неинтерактивный запуск, например claude -p, сессия Agent SDK или сессия во вкладке Code в Claude Desktop, не может показать диалоговое окно. Он применяет переданные настройки только для этого запуска и не записывает их как подтверждённые, поэтому следующая интерактивная сессия разработчика всё равно покажет диалоговое окно.

Если разработчик отказывается, Claude Code завершает эту сессию, а не применяет политику. Поэтому, когда вы передаёте новый хук или любую переменную окружения, вызывающую диалоговое окно, в широкую политику, каждый подпадающий разработчик увидит диалоговое окно в своих интерактивных сессиях. Работающая интерактивная сессия показывает его при следующем ежечасном опросе, а в остальных случаях оно появляется при следующем интерактивном запуске у разработчика.

В более ранних выпусках ключ cli назывался settings, и шлюз по-прежнему принимает это написание как псевдоним. Для новых развёртываний используйте code.

Проверка политики перед развёртыванием

Чтобы проверить изменение политики, запустите шлюз с временной базой данных Postgres. Шлюз подключается к Postgres и применяет миграции схемы, прежде чем проверять содержимое блоков cli, code и desktop. Если база данных недоступна, запуск останавливается на could not connect to Postgres и ничего не сообщает об их содержимом.

Контекстное окно в сессиях терминала

Сессии терминала, выполненные со входом через /login, используют контекстное окно 1M для Opus 4.7 и новее, Sonnet 5 и новее, а также моделей Fable. ID модели не требует суффикса [1m], и сессии сжимаются при достижении примерно 967K токенов. До Claude Code v2.1.287 на машине разработчика Claude Code считал, что у моделей Opus и Fable окно 200K, если ID модели не заканчивался на [1m].

Чтобы сессии терминала вместо этого сжимались на границе 200K, задайте окно автосжатия в env политики:

managed:
  policies:
    - match: {}
      cli:
        env:
          CLAUDE_CODE_AUTO_COMPACT_WINDOW: "200000"

Claude Code применяет эту переменную без показа разработчику диалогового окна подтверждения. Переменная применяется ко всем моделям, включая ID моделей, заканчивающиеся на [1m].

Чтобы вместо этого отключить контекст 1M, установите CLAUDE_CODE_DISABLE_1M_CONTEXT: "1" в том же блоке env. Тогда Claude Code считает, что у каждой модели окно 200K. В интерактивных сессиях каждый разработчик подтверждает эту переменную в диалоговом окне подтверждения, прежде чем она вступит в силу.

[!NOTE]

Claude Code не читает upstream_model псевдонима, чтобы определить размер его контекстного окна. Чтобы передать окно модели псевдониму в models, который Claude Code не распознаёт, см. Исправление окна для ID модели шлюза или пользовательской модели.

Часовой кэш промптов

Чтобы запрашивать часовой TTL кэша промптов вместо пятиминутного по умолчанию, добавьте эти ключи в существующий блок code, cli или settings политики и перезапустите шлюз. Ключам нужен Claude Code v2.1.242 или новее на сервере шлюза и на клиентах.

promptCacheTtl охватывает основной диалог. subagentPromptCacheTtl необязателен и охватывает субагентов, workflows и фоновые запросы. В этом примере оба ключа добавляются в политику match: {} с ключом cli:

managed:
  policies:
    - match: {}
      cli:
        promptCacheTtl: 1h
        subagentPromptCacheTtl: 1h

[!WARNING]

Задавайте эти ключи, только если ваши upstream предлагают часовой TTL для каждой модели, которую обслуживает шлюз. Если upstream отклоняет TTL, запрос завершается ошибкой, и ни шлюз, ни Claude Code не повторяют попытку с пятиминутным TTL. Для Amazon Bedrock проверьте поддерживаемые модели, регионы и ограничения.

Чтобы проверить promptCacheTtl, войдите в шлюз как пользователь, подпадающий под политику, и проверьте, какой TTL использовали ваши записи в кэш. Передайте --model, чтобы повторить проверку для каждой модели, которую обслуживает шлюз.

Часовые записи в кэш стоят дороже, чем пятиминутные. Чтобы лимиты расходов учитывали этот повышенный тариф, нужна v2.1.286 или новее на сервере шлюза.

MCP-серверы в политике

Чтобы предоставить MCP-серверы клиентам Claude Code, подпадающим под политику, задайте managedMcpServers в блоке cli этой политики. Нужен Claude Code v2.1.259 или новее на сервере шлюза и на клиентах.

Шлюз проверяет каждую запись при запуске по тем же правилам, которые Claude Code применяет на клиенте, и если запись не проходит проверку, шлюз отказывается запускаться и называет эту запись.

Если вы пишете ссылку ${VAR} в gateway.yaml, шлюз разрешает её из своего окружения при запуске через подстановку секретов до проверки записей, поэтому каждый подпадающий клиент получает буквальное значение и может его прочитать. Рекомендации по заголовкам для предоставляемых серверов относятся к подставленному значению.

Шлюз отклоняет написание mcpServers из .mcp.json в блоке cli, и в его ошибке запуска в качестве нужного ключа указан managedMcpServers. До v2.1.259 шлюз отклонял любое определение MCP-сервера в блоке cli.

Наложение для Claude Desktop

Если ваша организация также развёртывает Claude Desktop, один и тот же шлюз обслуживает оба клиента. Направьте bootstrapUrl в управляемой конфигурации Claude Desktop на <listen.public_url>/user/bootstrap. Claude Desktop выводит издателя OAuth из этого URL, выполняет тот же вход по коду устройства через этот шлюз и получает свою конфигурацию из ответа.

[!NOTE]

Требует Claude Code v2.1.203 или новее на сервере шлюза и явного включения: /user/bootstrap возвращает 404, если политика, под которую подпадает пользователь, не содержит ключа desktop. Пустой desktop: {} включает политику, а ключ desktop в базовом слое match: {} включает каждую политику, которая его наследует. Журнал аудита записывает каждый запрос как desktop_bootstrap.serve или desktop_bootstrap.denied.

Если вы не развёртываете Claude Desktop, вообще не указывайте desktop в своих политиках; тогда шлюз возвращает 404 на /user/bootstrap для каждого пользователя.

Настройки, которые шлюз выводит для Claude Desktop

Шлюз выводит бо́льшую часть ответа bootstrap из блока cli или code совпавшей политики и из конфигурации шлюза верхнего уровня:

  • Список моделей — из availableModels. В список не входят модели, которые политика блокирует с помощью deniedModels или availableModelsMatch: exact. Этот фильтр требует Claude Code v2.1.299 или новее на сервере шлюза. Вариант контекста 1M для каждой модели описан в разделе Расширенный контекст в Claude Desktop

  • Отключённые инструменты — из записей permissions.deny, содержащих только имя инструмента. Если вы задаёте disabledBuiltinTools в блоке desktop политики, шлюз отдаёт объединение вашего значения и выведенного списка, поэтому так можно отключить больше инструментов, но нельзя снова включить инструмент, отключённый через permissions.deny

  • Список разрешённых адресов для исходящего трафика — из sandbox.network.allowedDomains. Если вы задаёте coworkEgressAllowedHosts в блоке desktop политики, шлюз использует это значение вместо выведенного списка. Если список разрешённых, который отдаёт шлюз, включает * и шлюз при этом не отдаёт allowedWorkspaceFolders для Claude Desktop, Claude Desktop не включает песочницу Bash во вкладке Code

  • Эндпоинт OTLP, указывающий на сам шлюз, и атрибуты идентичности вошедшего пользователя. Шлюз пересылает экспорты, полученные на этом эндпоинте, в ваши назначения forward_to. Он включает эндпоинт и атрибуты, когда вы задаёте и telemetry.forward_to, и listen.public_url.

    Claude Desktop экспортирует все сигналы в одной кодировке: http/protobuf или http/json, если вы установили OTEL_EXPORTER_OTLP_PROTOCOL или один из его вариантов для отдельных сигналов в http/json в env политики. До Claude Code v2.1.261 на сервере шлюза ответ в любом случае задавал http/json, поэтому коллектор, принимающий только protobuf, отклонял экспорты Claude Desktop

Чтобы задать disabledBuiltinTools, coworkEgressAllowedHosts или собственную настройку managedMcpServers Claude Desktop в блоке desktop политики, нужен Claude Code v2.1.232 или новее на сервере шлюза. managedMcpServers в Claude Desktop принимает значение-массив, а не объект.

Шлюз не включает в ответ bootstrap ключи, не имеющие эквивалента в Claude Desktop, например hooks и ограниченные правила разрешений вроде Bash(npm *).

Применение настроек code во вкладке Code

Настройки Claude Code, которые политика содержит под ключом code, применяются во вкладке Code в Claude Desktop, когда выполняются все следующие условия:

  • У политики также есть ключ desktop, причём пустой desktop: {} тоже считается
  • Claude Desktop версии 2.9939.2 или новее
  • Управляемые настройки Claude Code на машине указывают этот шлюз
  • Эта машина обращается к шлюзу по HTTPS в частной сети

Последние два условия относятся к той машине, на которой Claude Code выполняет сессию. Для локальной сессии это собственный компьютер пользователя. Для сессии вкладки Code через SSH — удалённый хост.

Разверните управляемые настройки на стороне клиента на этих машинах, прежде чем переименовывать cli в code. Когда первые два условия выполняются, а одно из последних двух — нет, пользователь, подпадающий под политику, получает один из следующих результатов:

  • По HTTPS, если Claude Desktop поставляется с Claude Code v2.1.296 или новее: вкладка Code не запускается, а ответ на промпт пользователя объясняет причину
  • По HTTPS, если Claude Desktop поставляется с более ранней версией: вкладка Code запускается без ваших настроек code, и ничто в сессии об этом не сообщает
  • По обычному HTTP: вкладка Code запускается без ваших настроек code, независимо от версии, с которой поставляется Claude Desktop

Когда прокси перед шлюзом отвечает на /managed/settings собственным 404, вкладка Code также запускается без ваших настроек code, в том числе на машине, соответствующей всем четырём условиям.

В политике с ключом desktop блок code, содержащий настройки, отключает инструмент WebSearch в Cowork, Chat и вкладке Code. О MCP-серверах см. Где применяется managedMcpServers.

Прямое задание настроек Claude Desktop

Добавьте необязательный блок desktop рядом с cli, чтобы задавать настройки Claude Desktop напрямую. Указывайте настройки из справочника управляемой конфигурации Claude Desktop в виде плоских имён ключей. Не указывайте ключи, которые Claude Desktop читает только из MDM или локальных файлов, например bootstrapUrl; шлюз отклоняет их при запуске.

В этом примере для группы eng-contractors задаются три ключа Claude Desktop наряду с её настройками cli:

managed:
  policies:
    - match: { groups: [eng-contractors] }
      cli:
        availableModels: [claude-sonnet-4-6]
        enforceAvailableModels: true
      desktop:
        isLocalDevMcpEnabled: false
        disableAutoUpdates: true
        banner: { text: "Contractor build: internal use only" }

Каждый ключ необязателен; для любого опущенного ключа Claude Desktop применяет собственное значение по умолчанию.

Что шлюз отклоняет при запуске

Шлюз завершается сбоем при загрузке, если блок desktop содержит:

  • Распознанный ключ со значением, которое Claude Desktop отклонил бы или молча отбросил, например пустым значением.
  • Ключ, который шлюз вычисляет сам: подключение для инференса, список моделей и ретрансляция OTLP. Настраивайте их через upstreams, models и forward_to в разделе telemetry.
  • Устаревший псевдоним текущего ключа. В ошибке запуска шлюз называет канонический ключ, который нужно указать.
  • Начиная с v2.1.300 — любой ключ, имя которого начинается с selfHosted, например ключи для самостоятельно размещённого хоста сессий. Удалите эти ключи, прежде чем обновлять шлюз до v2.1.300 или более поздней версии.

Если вы используете устаревшее значение или форму записи, например запись managedMcpServers без transport, шлюз запускается и записывает в лог предупреждение с названием замены.

До v2.1.232 шлюз принимал фиксированный список из 11 ключей-флагов функций, например chatTabEnabled и disableAutoUpdates, и отклонял все остальные ключи при запуске. До v2.1.227 шлюз также отклонял при запуске chatTabEnabled и chatAdvancedFileAnalysisEnabled.

Ключи, неизвестные шлюзу

На шлюзе под управлением Claude Code v2.1.295 или более поздней версии большинство ключей из более нового выпуска Claude Desktop не требуют обновления шлюза. В v2.1.321 или более поздней версии его не требует и большинство новых подключей внутри известного ключа.

Некоторые ключи и значения по-прежнему приводят к сбою при загрузке, например:

  • Новый вариант в фиксированном списке значений известного ключа.
  • Вероятная опечатка в ключе, который можно задать в блоке desktop, например disable_auto_updates вместо disableAutoUpdates. Ошибка предлагает правильное имя.

В каждом случае, если такое имя или значение действительно существует в более новом выпуске Claude Desktop, обновите шлюз до последнего выпуска. В противном случае исправьте или удалите его. Чтобы узнать это до развёртывания, проверьте политику.

Ключи, требующие более новой версии шлюза или Claude Desktop

userPluginMarketplacesEnabled и userPluginUploadsEnabled требуют Claude Code v2.1.260 или более поздней версии на сервере шлюза и Claude Desktop 1.37937.0 или более поздней версии на машинах участников.

blockReadsOutsideWorkingDirectories, disableBypassPermissionsMode, configRecheckIntervalMinutes и sshClientPath требуют Claude Code v2.1.281 или новее на сервере шлюза. То же относится к значению required для microsoftAuthBroker и полю continuousAccessEvaluation записи managedMcpServers для Microsoft 365. Выпуски Claude Desktop, вышедшие до появления значения required, читают его как disabled, поэтому задавайте required только после того, как Claude Desktop у каждого участника будет его поддерживать. В справочнике управляемой конфигурации Claude Desktop указан выпуск, который первым читает каждый ключ.

[!NOTE]

sshTransport требует Claude Code v2.1.293 или новее на сервере шлюза.

Если вы задаёте orgPluginSettings в блоке desktop политики, шлюз отдаёт его в форме массива, которую читает Claude Desktop 1.15200.0 и новее. Более старые десктопы игнорируют массив и не применяют никакой политики инструментов плагинов, поэтому обновите участников до 1.15200.0 или новее, прежде чем на это полагаться.

Как ролевая политика наследует базовый блок desktop

Шлюз заполняет ключи, которые блок desktop политики не задаёт, из блока desktop универсальной политики match: {}, так же как он заполняет блок cli политики из базы. Если вы задаёте disabledBuiltinTools или builtinToolPolicy и в базе, и в ролевой политике, шлюз сохраняет ограничение базы:

  • disabledBuiltinTools: шлюз использует объединение списка базы и списка политики
  • builtinToolPolicy: если в базе вы задали для инструмента значение, отличное от allow, шлюз сохраняет это значение, даже если в ролевой политике для того же инструмента задано allow

Для любого другого ключа, если вы задали его в ролевой политике, шлюз использует значение ролевой политики. Массив или вложенный объект, например banner, шлюз заменяет целиком, поэтому если вы задали banner.text в ролевой политике, шлюз отбрасывает banner.backgroundColor из базы.

Когда изменение политики доходит до Claude Desktop

После повторного развёртывания шлюза с изменённой политикой Claude Desktop применяет большинство настроек только при следующем запуске:

  • Закрыт: Claude Desktop получает ответ bootstrap при запуске, поэтому изменение применяется со следующего запуска
  • Открыт: Claude Desktop по умолчанию каждые 10 минут проверяет, изменился ли ответ, и применяет некоторые настройки без перезапуска. Для остальных, например skillCreationEnabled, пользователь видит карточку Relaunch Claude Desktop на боковой панели и сохраняет прежнюю конфигурацию, пока не перезапустит приложение. По умолчанию через 24 часа Claude Desktop показывает диалоговое окно перезапуска и перезапускается сам после 2 минут бездействия

Чтобы сократить эти 24 часа, задайте relaunchEnforcementHours в блоке desktop политики. Нужен Claude Code v2.1.260 или новее на сервере шлюза и Claude Desktop 1.40609.0 или новее на машинах участников. При значении 0 диалоговое окно появляется сразу, как только Claude Desktop обнаруживает изменение.

Расширенный контекст в Claude Desktop

Если вы обслуживаете Claude Desktop через шлюз, его окно выбора модели предлагает вариант с контекстом 1M для каждой указанной модели, которая может работать с контекстным окном 1M. К ним относятся Claude Opus 4.6 и новее, Claude Sonnet 4.6 и новее, а также модели Fable. Этот вариант — это вариант модели [1m], описанный в разделе Расширенный контекст. Нужен Claude Code v2.1.284 или новее на сервере шлюза.

Запись models не получает варианта 1M, когда:

  • Upstream, способный обслуживать запись, сопоставляет её с моделью без поддержки 1M, включая upstream, к которому шлюз обращается только при отказе основного
  • Ни её id, ни одно из значений upstream_model не называет модель Claude, например пользовательский псевдоним, направленный на ARN профиля инференса приложения

Чтобы изменить то, что предлагает окно выбора, используйте один из следующих способов:

  • Запуск пользователей на варианте 1M: установите modelPrefer1mContext: true в блоке desktop политики. Пользователи, ещё не выбравшие модель, начинают с варианта 1M, если он есть у первой указанной модели. Пользователи, уже выбравшие модель, сохраняют свой выбор.
  • Ручное предложение варианта: сделайте это, если сервер шлюза работает на версии старше v2.1.284 или запись не называет модель Claude. Укажите модель в models дважды: один раз с простым ID и один раз с добавленным [1m], оба раза с одной и той же картой upstream_model. Claude Desktop показывает пару как одну модель с вариантом 1M. Шлюз отдаёт запись [1m] без проверки, поэтому добавляйте её только для модели, которую ваши upstream обслуживают с 1M.

В этом примере вариант вручную предлагается для пользовательского псевдонима, направленного на профиль инференса приложения, и новые пользователи запускаются на нём:

models:
  - id: corp-sonnet
    upstream_model:
      bedrock: arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/sonnet-5-prod
  - id: corp-sonnet[1m]
    upstream_model:
      bedrock: arn:aws:bedrock:us-east-2:123456789012:application-inference-profile/sonnet-5-prod

managed:
  policies:
    - match: {}
      desktop:
        modelPrefer1mContext: true
Удаление варианта 1M

Чтобы убрать этот вариант из окна выбора, установите CLAUDE_CODE_DISABLE_1M_CONTEXT: "1" в блоке env под ключом cli политики. Если вы также указали запись, id которой заканчивается на [1m], шлюз по-прежнему её отдаёт, поэтому удалите и эту запись.

Переменная также доходит до сессий терминала разработчиков, подпадающих под политику. О том, что она там меняет, см. Расширенный контекст.

Приоритет относительно других управляемых источников

Если на устройстве также есть политика, доставленная через MDM, или локальный managed-settings.json, настройки, доставленные шлюзом, имеют наивысший приоритет. Раздел Приоритет внутри управляемого уровня на странице управляемых настроек объясняет, когда применяются локальные источники, и содержит ключи, которые Claude Code читает из каждого административного источника независимо от того, какой источник он выбрал, например ключи блокировки песочницы, forceRemoteSettingsRefresh и объединение env по отдельным переменным. policyHelper, настроенный в профиле MDM или файле управляемых настроек, выполняется, только когда шлюз не доставляет никаких настроек; в его описании указано, что заменяет его вывод.

Встраивающие хосты, такие как Claude Desktop, могут передавать политику через параметр SDK managedSettings. Раздел Родительские настройки от встраивающих хостов объясняет, когда Claude Code её применяет, а в разделе Ограничение родительских настроек перечислено, какие разрешающие настройки по-прежнему применяются без блокировок allowManaged*Only.

Политики шлюза применяются к каждому вызову Claude Code на машине, включая неинтерактивные запуски claude -p и сессии, порождённые Agent SDK. Если шлюз недоступен при запуске, сессии с выполненным входом завершаются с ошибкой, а не работают без своей политики.

telemetry

CLI отправляет метрики, логи и, если включено, трассировки на шлюз, который дословно пересылает их в каждое настроенное назначение. Экспорт использует OpenTelemetry Protocol (OTLP) поверх HTTP. Чтобы обойти ретрансляцию и экспортировать данные сессий напрямую в ваш коллектор, укажите коллектор в политике. Метрики и события, которые генерирует CLI, описаны в разделе Мониторинг использования.

В сессиях с выполненным входом через /login CLI помечает каждый экспорт идентичностью аутентифицированного пользователя, считанной из JWT, выданного шлюзом: атрибутами user.id, user.email и user.groups. Поэтому учёт затрат и использования по разработчикам работает без какой-либо настройки на стороне разработчика. События, которые Claude Code записывает в лог до входа разработчика, не содержат этой идентичности. О том, какой атрибут отражает изменение групп разработчика, см. Изменение групп во время открытой сессии.

Сессии Claude Desktop и Cowork с выполненным входом через шлюз помечают свою телеметрию атрибутами user.email и user.groups наряду с enduser.id, поэтому вы можете охватить использование терминала, Desktop и Cowork одним запросом по user.email или user.groups. user.groups — список групп IdP, разделённый запятыми.

Телеметрия Desktop и Cowork также содержит enduser.sub — claim sub, который ваш провайдер идентификации выдаёт пользователю и который не меняется при смене email пользователя. Сессии терминала помечают то же значение как user.id, поэтому запрос, сопоставляющий enduser.sub с user.id терминала, охватывает использование терминала, Desktop и Cowork одним пользователем вместе. В экспортах Desktop и Cowork user.id — анонимный идентификатор, а не субъект.

Как и все данные OpenTelemetry из Claude Code, эти атрибуты отправляются только в назначения, настроенные вашей организацией, и никогда не отправляются в Anthropic.

Если список групп пользователя длиннее 255 символов после процентного кодирования или имя группы содержит запятую или знак равенства, шлюз не включает user.groups в телеметрию Desktop и Cowork этого пользователя, а не обрезает список. Сессии терминала этого пользователя по-прежнему содержат полный список.

Шлюз не включает enduser.sub, если субъект длиннее 255 символов после процентного кодирования или содержит пробел, символ вне печатаемого ASCII или один из символов , ; = \ " %. Телеметрия Desktop и Cowork этого пользователя сохраняет остальные атрибуты.

Для user.email и user.groups в телеметрии Desktop и Cowork нужен Claude Code v2.1.265 или новее на сервере шлюза, а для user.groups — Claude Desktop 1.24012 или новее на машине каждого разработчика.

Для enduser.sub нужен Claude Code v2.1.274 или новее на сервере шлюза.

telemetry:
  forward_to:
    - url: https://otel-collector.internal.example.com
      headers:
        Authorization: ${OTLP_TOKEN}
      # Per-signal opt-in. Default: metrics only.
      metrics: true
      logs: false
      traces: false
    - url: https://api.datadoghq.com/api/v2/otlp
      headers:
        DD-API-KEY: ${DD_API_KEY}

[!WARNING]

Каждое назначение независимо включает metrics, logs и traces, а по умолчанию — только метрики. Сигналы различаются по чувствительности:

  • Метрики: агрегированные счётчики, такие как количество токенов, количество запросов и задержка
  • Логи и трассировки: могут содержать полные команды Bash, входные данные инструментов и пути к файлам, охватывая всё, что Claude Code делает на машине разработчика

Включайте логи и трассировки только для назначений с теми средствами контроля доступа и политикой хранения, которых требуют эти данные.

Каждый URL forward_to должен использовать https://, за одним исключением — для коллектора на собственном loopback-интерфейсе шлюза:

  • http://localhost:<port> проходит проверку конфигурации, но защита от SSRF блокирует каждый экспорт с ECONNREFUSED_SSRF, если вы не установите CLAUDE_GATEWAY_ALLOW_LOOPBACK=1 в окружении шлюза
  • http://127.0.0.1:<port> или http://[::1]:<port> приводят к ошибке запуска, если эта переменная не установлена

Для коллектора внутри кластера откройте к нему доступ по HTTPS по его собственному внутреннему адресу или запустите его как sidecar с установленной переменной.

Когда задан HTTPS_PROXY, шлюз отправляет экспорты через этот прокси.

Чтобы обращаться к внутреннему коллектору напрямую, добавьте его в NO_PROXY по имени хоста или по домену с начальной точкой, например .internal.example.com, что требует Claude Code v2.1.277 или новее на сервере шлюза. Убедитесь, что шлюз может достучаться до коллектора без прокси. Запись без начальной точки совпадает только с этим точным именем, а не с именами под ним. Диапазоны CIDR не сопоставляются.

При включённом исходящем трафике только через прокси вместо этого разрешите коллектор в прокси, поскольку любая запись NO_PROXY отключает режим исходящего трафика только через прокси.

По умолчанию телеметрия в CLI отключена. Когда вы задаёте и telemetry.forward_to, и listen.public_url, шлюз включает её для подключённых клиентов, передавая шесть переменных окружения через /managed/settings:

  • CLAUDE_CODE_ENABLE_TELEMETRY=1
  • OTEL_METRICS_EXPORTER, OTEL_LOGS_EXPORTER и OTEL_TRACES_EXPORTER, каждая из которых имеет значение otlp, если хотя бы одно назначение forward_to включает этот сигнал, и none в противном случае
  • OTEL_EXPORTER_OTLP_ENDPOINT=<public_url>
  • OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

Когда вы добавляете собственные метки, шлюз также передаёт OTEL_RESOURCE_ATTRIBUTES.

До Claude Code v2.1.265 на сервере шлюза шлюз передавал все три селектора экспортёров со значением otlp, в том числе для сигналов, которые не включало ни одно назначение.

Передаваемый эндпоинт строится из публичного URL, поэтому метрики и логи не требуют настройки OTEL ни от разработчиков, ни в политиках.

Разработчики, выполнившие вход через /login, не могут перенаправить экспорт с помощью собственной конфигурации OTEL:

  • Локально заданные переменные: Claude Code применяет переданные переменные на управляемом уровне, поэтому каждая из них переопределяет значение, которое разработчик задаёт для неё локально.
  • Локально настроенные эндпоинты: при включённом экспорте OTLP/HTTP CLI игнорирует любой локально настроенный эндпоинт, независимо от того, передал ли шлюз переменные телеметрии. Его экспорт идёт на шлюз, если политика не указывает ваш коллектор в качестве эндпоинта.

Если для сигнала нет назначения forward_to, шлюз принимает и отбрасывает его. Если разработчики уже экспортируют телеметрию Claude Code в один из ваших коллекторов, добавьте его как назначение forward_to, включив логи или трассировки, если они их экспортируют, чтобы он продолжал получать их данные после входа. Чтобы вместо этого обойти ретрансляцию, укажите коллектор в политике.

Трассировки также требуют CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1 на каждом клиенте. Задайте её в блоке env управляемой политики, поскольку шлюз её не передаёт. Разработчики подтверждают её в том же диалоговом окне подтверждения безопасности, которое уже вызывает переданный эндпоинт.

Устанавливайте её в 1 только в тех политиках, группы которых вы хотите трассировать. Политика, которая её не задаёт, наследует значение от вашей универсальной политики match: {}, если та его задаёт, согласно правилам объединения. Чтобы клиенты группы не отправляли трассировки, даже если разработчик задаёт переменную локально, установите её в 0 в политике этой группы.

Пересылаются обе кодировки OTLP — protobuf и JSON, и в качестве назначения подходит любой бэкенд, совместимый с OpenTelemetry.

Отправка кумулятивных метрик

Если ваш коллектор принимает только кумулятивные метрики, установите OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE в cumulative. По умолчанию Claude Code отправляет дельта-метрики, а шлюз пересылает их без преобразования. Задайте переменную там, где её читает каждый вид сессий:

Если вы добавляете переменную в управляемые настройки машины, также установите parentSettingsBehavior: "merge" в источнике с наивысшим приоритетом на этой машине. Без этого сессии Cowork и сессии вкладки Code под политикой cli работают без списка разрешённых адресов для исходящего трафика и других политик, которые Claude Desktop передаёт им как родительские настройки.

Добавление собственных меток

Чтобы добавить фиксированные метки, например service.namespace или deployment.environment.name, к телеметрии сессий с выполненным входом через шлюз, задайте telemetry.resource_attributes. Каждая метка — это атрибут ресурса OpenTelemetry, и каждое назначение получает одни и те же метки.

Сессии получают метки, только если вы также задали telemetry.forward_to и listen.public_url. В этом примере добавляются две метки:

telemetry:
  forward_to:
    - url: https://otel-collector.internal.example.com
  resource_attributes:
    service.namespace: claude
    deployment.environment.name: prod

Шлюз отказывается запускаться, если метка нарушает одно из следующих правил, и ошибка запуска называет эту метку:

  • Имена содержат только буквы, цифры, ., _ и -
  • Имена не являются зарезервированными. Без учёта регистра зарезервированы все имена, начинающиеся с user., enduser. или identity., а также service.name, service.version, claude.deployment_mode, host.arch, os.type, os.version и wsl.version
  • Значения — непустой печатаемый ASCII без пробелов и без символов , ; = \ " %
  • Значения содержат не более 255 символов в подсчёте шлюза после процентного кодирования, поэтому /, : и @ считаются за три символа каждый
  • Значения являются текстом, поэтому заключайте в кавычки числа, true или false

Чтобы задать telemetry.resource_attributes, нужен Claude Code v2.1.281 или новее на сервере шлюза. Более ранний шлюз отказывается запускаться, обнаружив этот ключ. Обновите все реплики, прежде чем добавлять ключ, и удалите ключ, прежде чем откатываться на более раннюю версию.

Сессии терминала с выполненным входом через /login получают метки в виде OTEL_RESOURCE_ATTRIBUTES, передаваемой вместе с другими переменными телеметрии. Если вы задаёте OTEL_RESOURCE_ATTRIBUTES в блоке env политики, сессии терминала, подпадающие под эту политику, получают это значение вместо меток. Claude Desktop получает метки от шлюза вместе с user.email и другими атрибутами идентичности.

Claude Code также копирует каждую метку в каждую точку данных метрики, чтобы вы могли фильтровать по ней метрики в бэкенде, который не индексирует атрибуты ресурса. Чтобы отключить это копирование, см. Управление кардинальностью метрик.

Изменение групп во время открытой сессии

Сессии терминала помещают user.groups в ресурс OTLP и повторно в каждую точку данных метрики и каждое событие. Если группы разработчика меняются, пока сессия открыта, точки данных и события для использования после следующего фонового обновления содержат новые группы. Ресурс сохраняет старые группы, пока разработчик не перезапустит Claude Code, поэтому группируйте по атрибуту в точке данных или событии.

Если вы включаете resource_to_telemetry_conversion в экспортёре Prometheus remote write в OpenTelemetry Collector, экспортёр заменяет user.groups каждой точки данных значением из ресурса, поэтому каждая точка данных показывает старые группы. Чтобы сохранить значение точки данных, удалите user.groups из ресурса до этого экспортёра.

Этот процессор resource OpenTelemetry Collector удаляет атрибут в конвейерах, где он указан:

processors:
  resource/drop-user-groups:
    attributes:
      - key: user.groups
        action: delete

После добавления resource/drop-user-groups в processors конвейера метрик каждый ряд содержит метку user_groups из собственной точки данных.

Экспорт напрямую в ваш коллектор

Чтобы сессии, в которые выполнен вход через /login, отправляли телеметрию напрямую в ваш коллектор, а не через ретранслятор, задайте OTEL_EXPORTER_OTLP_ENDPOINT как базовый URL коллектора с https:// в блоке env управляемой политики. Claude Code добавляет /v1/metrics, /v1/logs или /v1/traces к заданному вами URL, например https://otel-collector.example.com:4318, и экспортирует туда каждый сигнал по OTLP/HTTP. Требуется Claude Code v2.1.265 или новее на машине каждого разработчика. Более ранние клиенты экспортируют через ретранслятор.

Для аутентификации в коллекторе задайте OTEL_EXPORTER_OTLP_HEADERS в том же блоке env. Сессии никогда не отправляют токен сессии шлюза разработчика в коллектор, указанный таким образом.

Когда вы добавляете или изменяете этот эндпоинт в политике, Claude Code просит каждого разработчика подтвердить его в диалоге подтверждения безопасности, прежде чем применить его в интерактивной сессии.

Claude Code проверяет эндпоинт перед тем, как экспортировать сигнал напрямую, и оставляет этот сигнал на ретрансляторе, если проверка не пройдена. Проверки включают:

  • Эндпоинт поступает от самого шлюза. Если вы задаёте ту же переменную в профиле MDM или в локальном managed-settings.json, экспорт остаётся на ретрансляторе.
  • URL использует https:// либо, для loopback-адреса, http://
  • URL разрешается в путь, заканчивающийся на /v1/<signal>, без строки запроса и фрагмента. Claude Code сам строит этот путь из общей переменной. Переменную для отдельного сигнала, такую как OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, он использует как есть, поэтому указывайте в ней полный путь.
  • URL не является собственным хостом шлюза. Эндпоинт, адресованный шлюзу, сохраняет путь через ретранслятор и его токен сессии.
  • Ни вы, ни разработчик не настроили otelHeadersHelper ни в одном источнике настроек. Если helper настроен, все сигналы остаются на ретрансляторе.

Указанный вами эндпоинт меняет только то, куда направляется экспорт. Какие сигналы вообще экспортируются, вы по-прежнему выбираете с помощью селекторов OTEL_*_EXPORTER.

Сам по себе эндпоинт не включает экспорт, поэтому также задайте переменные, которые это делают, если шлюз ещё не передаёт их:

  • Если шлюз уже передаёт переменные телеметрии, они покрывают включение, селекторы и протокол, а ваш явно заданный эндпоинт переопределяет переданное значение <public_url>. Устанавливайте селектор OTEL_*_EXPORTER в otlp самостоятельно только для сигнала, который не включает ни одно назначение forward_to.
  • Если нет, также задайте CLAUDE_CODE_ENABLE_TELEMETRY=1, селекторы OTEL_*_EXPORTER и OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf.

Когда разработчик выходит из системы или входит в другой шлюз, экспорт в коллектор прекращается, и Claude Code отбрасывает каждый оставшийся пакет вместо его отправки.

Когда назначение недоступно

Шлюз не буферизует, не выполняет повторных попыток и не хранит телеметрию, поэтому он отбрасывает экспорт, который не достиг назначения, а не доставляет его с опозданием. Каждое назначение завершается успехом или неудачей независимо, и экспортирующий клиент в любом случае получает успешный ответ, поэтому неудачная доставка видна только в логе шлюза.

После пяти последовательных неудачных доставок в назначение шлюз приостанавливает пересылку в него периодами по 30 секунд, записывая каждую паузу в лог, пока доставка не завершится успешно. Неудачной доставкой считается любой ответ с ошибкой, таймаут или ошибка соединения, кроме 400, 413, 415, 422 и 431, которые означают, что коллектор отклонил данные этого экспорта как некорректные или слишком большие.

Отклонённые данные не увеличивают и не сбрасывают счётчик неудач: шлюз продолжает пересылку в назначение и записывает в лог предупреждение с указанием назначения и статуса при первом отклонении этим назначением и при каждом сотом после него.

Настройка HTTP

Четыре необязательных блока верхнего уровня, access_control, limits, timeouts и rate_limits, настраивают HTTP-интерфейс. Значения по умолчанию подходят для большинства развёртываний.

Блок Ключ По умолчанию Описание
access_control allow_cidrs / deny_cidrs пусто Разрешение/запрет входящих IP по адресу клиента после разрешения trusted_proxies. deny_cidrs проверяется первым; клиент, совпавший с ним, отклоняется, даже если совпадает и с allow_cidrs. Если allow_cidrs не пуст, шлюз по умолчанию запрещает доступ. /healthz и /readyz освобождены от allow_cidrs. Когда доверенный прокси отправляет в X-Forwarded-For запись, не являющуюся IP-адресом, реальный клиент неизвестен, и шлюз один раз записывает в лог предупреждение с указанием того, что нужно проверить. Если к запросу применяется любой из списков, шлюз отклоняет его с 403 и причиной аудита xff_unparseable. Если не применяется ни один, шлюз обслуживает запрос и использует собственный адрес прокси как IP клиента для ограничений частоты запросов по IP и аудита.
limits max_request_bytes 32 MiB Максимальный размер тела входящего запроса; слишком большие запросы получают 413 до буферизации тела. Увеличьте для запросов с большими файлами или изображениями.
limits max_request_header_bytes не задано Снижает установленный в шлюзе лимит 256 KiB на общий размер заголовков запроса. Запрос сверх лимита возвращает 431, а значение выше 256 KiB не действует. Если разработчики получают 431 после входа, см. Слишком большие заголовки запроса после входа.
limits max_url_length не задано Если задано, слишком длинный URL возвращает 414
timeouts upstream_ttfb_ms 120000 Максимальное время ожидания заголовков ответа вышестоящего сервера (время до первого байта). Затем тело ответа передаётся потоком без ограничения по реальному времени. Если ключ не задан, значение по умолчанию применяется к вышестоящим серверам provider: anthropic, а для всех остальных провайдеров шлюз ждёт начала ответа до одного часа. Чтобы сократить это ожидание, см. Несколько вышестоящих серверов.
rate_limits device_authorization.max / .window_seconds 30 / 600 Ограничение частоты запросов по IP для неаутентифицированного эндпоинта авторизации устройства. Увеличьте для крупной организации за общим исходящим IP или NAT. В разделе Крупные развёртывания показано, как подобрать значение. Эти лимиты применяются только к процессу входа с device grant, а не к инференсу /v1/messages. См. Устойчивость пользовательского кода к перебору.
rate_limits device_verify.max / .window_seconds 10 / 600 Ограничение частоты запросов по IP для отправки user_code на /device. Именно оно не даёт кому-либо подобрать код другого разработчика. В разделе Крупные развёртывания показано, насколько его увеличить.

Если оставить оба списка access_control пустыми, как по умолчанию, шлюз обслуживает любой адрес клиента, поэтому ограничивать круг тех, кто может к нему обратиться, будет только ваша сеть. Это важно, поскольку шлюз может передавать управляемые настройки, которые выполняют команды на машинах разработчиков.

Пока allow_cidrs пуст, шлюз выдаёт предупреждения в двух местах, не меняя того, как он отвечает на запросы:

  • При запуске: предупреждение в операционном логе рекомендует разрешить только частные диапазоны 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 100.64.0.0/10, 127.0.0.0/8, ::1/128 и fc00::/7, а также любые другие внутренние диапазоны, из которых подключаются ваши разработчики. Если вы привязываете шлюз к loopback-адресу и не задаёте ни trusted_proxies, ни public_url, как при локальной разработке, предупреждение не появляется.
  • Во время работы: когда впервые поступает запрос с адреса вне этих частных диапазонов, шлюз записывает в лог предупреждение и генерирует событие аудита access.public_client с IP клиента. Оба срабатывают один раз за процесс. Link-local адреса, 169.254.0.0/16 и fe80::/10, не считаются публичными. Шлюз отвечает на /healthz и /readyz до выполнения этой проверки, поэтому проверки работоспособности из публичных диапазонов её не вызывают.

Оба сигнала используют адрес клиента в том виде, в каком его определяет шлюз. Если балансировщик нагрузки, проброс портов или туннель ретранслирует трафик и не указан в listen.trusted_proxies, шлюз видит адрес ретранслятора, который обычно является частным, поэтому ни предупреждение во время работы, ни список разрешённых частных адресов не отлавливают трафик, ретранслируемый через него.

Если ретранслятору место в listen.trusted_proxies, укажите его там. В любом случае обеспечьте недоступность шлюза и всего, что находится перед ним, из публичного интернета.

load_test_mode

Блок load_test_mode позволяет провести нагрузочное тестирование шлюза без обращения к провайдеру модели. Пока режим включён, шлюз, как обычно, формирует и подписывает каждый запрос к провайдеру, но отбрасывает его вместо отправки и передаёт потоком заготовленный ответ по своему обычному пути ответа. Ответ представляет собой текст-заполнитель, начинающийся с предложения о том, что он заготовлен.

Требуется Claude Code v2.1.282 или новее на сервере шлюза. Более ранний шлюз отказывается запускаться, обнаружив этот ключ. Обновите все реплики перед добавлением блока и удалите блок перед откатом.

Пример ниже включает режим со значениями по умолчанию — ответом примерно из 750 токенов текста, передаваемым потоком около 10 секунд:

load_test_mode:
  enabled: true
  reply_tokens: 750     # roughly how many tokens of text each canned reply carries
  reply_seconds: 9.5    # how long a streamed reply takes
Поле Обязательное Описание
enabled Да true включает режим. false сохраняет ваши значения в файле при выключенном режиме. Шлюз отказывается запускаться, если блок присутствует без этого поля.
reply_tokens Нет По умолчанию 750. Примерное количество токенов текста в каждом заготовленном ответе, целое число от 1 до 100000.
reply_seconds Нет По умолчанию 9.5. Сколько времени занимает потоковый ответ, от 0 до 600. 0 отправляет весь ответ сразу. Ответ на непотоковый запрос всегда возвращается сразу.

Нагрузочный тест в этом режиме охватывает шлюз, ваш Postgres и всё, что стоит перед шлюзом. Он не охватывает ограничения, скорость и сетевой путь провайдера, а также ожидание на ограничении числа одновременных запросов к вышестоящему серверу каждой реплики. Реплика по-прежнему записывает в лог предупреждение client requests are open, когда открытых запросов больше этого ограничения — порога, при котором запросы в рабочей среде начинают ждать.

Запросы к модели не отправляются провайдеру, поэтому загрузка CPU реплики на запрос является оценочной и оказывается ниже, чем в продакшене, где трафик к провайдеру ещё и шифруется. Подтвердите количество реплик небольшим пилотом с реальным провайдером. До v2.1.283 оценка оказывается значительно ниже.

Пока режим включён, запрос может содержать заголовок x-load-test-user с целым числом длиной до семи цифр. Шлюз считает каждое число отдельным разработчиком с адресом электронной почты и группами того разработчика, чей токен пришёл с запросом.

Выделите развёртыванию для нагрузочного тестирования собственную пустую базу данных, поскольку шлюз отказывается запускаться с включённым режимом на базе данных, в которой какой-либо разработчик уже что-то потратил.

[!WARNING]

Никогда не включайте этот режим для шлюза, которым пользуются разработчики. Каждый запрос получает заготовленный ответ, и модель не вызывается. Пока режим включён, шлюз записывает в лог предупреждение load_test_mode is on при запуске и помечает каждое событие аудита inference значением load_test: true.

Полный пример

Этот полный справочный конфиг использует каждый основной раздел; блоки настройки HTTP сохраняют свои значения по умолчанию. Скопируйте его, удалите то, что вам не нужно, и заполните свои значения. Конфиг в Quickstart — это минимальная версия этого.

# Запуск с помощью:
#   claude gateway --config gateway.yaml
#
# Подробность операционного журнала контролируется переменной окружения
# CLAUDE_GATEWAY_LOG_LEVEL (debug | info | warn | error; по умолчанию info). debug
# также логирует имена утверждений в каждом id_token для диагностики groups_claim.
# Это не влияет на события аудита, которые всегда генерируются.
# Установите CLAUDE_GATEWAY_LOG_FORMAT=json, чтобы записывать строки операционного
# журнала как объекты JSON с полями severity, time и message.

listen:
  host: 0.0.0.0
  port: 8080
  public_url: https://claude-gateway.internal.example.com
  # Опустите блок tls при запуске за TLS-завершающим ingress.
  # tls:
  #   cert: /certs/gateway.crt
  #   key: /certs/gateway.key
  # trusted_proxies:
  #   - 10.0.0.0/8

oidc:
  issuer: https://example.okta.com
  client_id: 0oa1example2
  client_secret: ${OIDC_CLIENT_SECRET}
  allowed_email_domains:
    - example.com
  # Требуется, когда издатель является сервером организации Okta, чьи id_tokens
  # могут опускать email и groups; шлюз заполняет их из /userinfo.
  userinfo_fallback: true
  # allowed_groups: [claude-code-users]
  # Okta выдает groups только когда запрашивается scope `groups` и
  # фильтр утверждения groups приложения их разрешает. Политика contractors ниже
  # соответствует groups, поэтому scope запрашивается здесь.
  scopes: [openid, profile, email, offline_access, groups]
  # extra_auth_params: { access_type: offline, prompt: consent }  # Google
  # groups_claim: groups          # Роли приложения Entra: используйте `roles`
  # email_claim: email

session:
  jwt_secret: ${GATEWAY_JWT_SECRET}   # openssl rand -base64 32
  # ttl_hours: 1

store:
  postgres_url: ${GATEWAY_POSTGRES_URL}
  # max_connections: 5
  # connect_timeout_seconds: 5
  # readiness_grace_seconds: 300   # продолжайте проходить проверку готовности через отказ базы данных

# Уведомление, показываемое при входе. Его может прочитать любой, у кого есть доступ к шлюзу.
# login_notice: This gateway is for Example Corp staff. For access questions, email it-help@example.com.

# Включает /v1/organizations/spend_limits (зеркалирует Admin API Anthropic)
# и принудительное соблюдение лимитов расходов на разработчика на /v1/messages. Опустите для отключения.
# Сами лимиты устанавливаются через admin API, а не здесь.
# admin:
#   write_keys:
#     - { id: terraform, key: "${GATEWAY_ADMIN_WRITE_KEY_TF}" }
#   read_keys:
#     - { id: reporting, key: "${GATEWAY_ADMIN_READ_KEY}" }
#   admin_groups: [platform-finops]
#   blocked_message: request an increase at https://go.example.com/claude-limits
#   # audit_retention_days: 365
#   # spend_retention_months: 13
#   # identity_retention_days: 90
#   # group_limit_mode: min
#   # pooled_conflict_rule: priority_list
#   # pooled_priority_order: [eng-platform, eng-all]

# enforcement:
#   fail_closed_on_error: false

# Нагрузочное тестирование этого развёртывания без вызова поставщика модели. Никогда на
# шлюзе, который используют разработчики: каждый запрос получает заготовленный ответ.
# load_test_mode:
#   enabled: true
#   # reply_tokens: 750
#   # reply_seconds: 9.5

# Измеряйте по договорным ставкам вместо цены USD по прайс-листу. Требует admin: или
# managed: политику. С managed:, те же ставки также идут подписанным клиентам.
# Ставки ниже — это заполнители, а не реальные договорные цены.
# pricing:
#   multiplier: 0.85
#   overrides:
#     - { upstream: anthropic, model: claude-sonnet-4-6, input: 3.30, output: 16.50, cache_read: 0.33, cache_write: 4.125 }

upstreams:
  - provider: anthropic
    auth:
      api_key: ${ANTHROPIC_API_KEY}

  # - provider: bedrock
  #   region: us-east-1
  #   auth: {}

  # - provider: mantle
  #   region: us-east-1
  #   models: [claude-opus-4-8, claude-opus-4-7, claude-haiku-4-5]
  #   auth: {}

  # - provider: anthropicAws
  #   region: us-east-1
  #   workspace_id: wrkspc_...
  #   auth:
  #     api_key: ${ANTHROPIC_AWS_API_KEY}

  # - provider: vertex
  #   region: us-east5
  #   project_id: example-prod
  #   auth: {}

  # - provider: foundry
  #   resource: example-foundry
  #   auth: { use_azure_ad: true }

auto_include_builtin_models: true
models:
  - id: claude-opus-4-8
    label: Claude Opus 4.8
    upstream_model:
      anthropic: claude-opus-4-8
      # bedrock: us.anthropic.claude-opus-4-8
      # mantle: anthropic.claude-opus-4-8
      # anthropicAws: claude-opus-4-8
      # vertex: claude-opus-4-8
      # foundry: <your-opus-deployment-name>
  - id: claude-sonnet-4-6
    label: Claude Sonnet 4.6
    upstream_model:
      anthropic: claude-sonnet-4-6
  - id: claude-haiku-4-5
    label: Claude Haiku 4.5
    upstream_model:
      anthropic: claude-haiku-4-5

managed:
  policies:
    - match: { groups: [contractors] }
      cli:
        availableModels: [claude-haiku-4-5]
        # allow автоматически одобряет эти инструменты; это не блокирует остальное.
        # Добавьте правила deny для ограничения инструментов.
        permissions: { allow: [Read, Grep] }
    - match: {}
      cli:
        availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
        # Ограничьте опцию Default в выборе модели значением availableModels каждой политики
        # вместо встроенного значения по умолчанию, чтобы ни одна роль не получила 400 на Default.
        # Политика contractors наследует этот ключ.
        enforceAvailableModels: true
        permissions:
          allow: [Read, Grep, Edit]
          deny: ["WebFetch"]
        env: { HTTP_PROXY: http://proxy.example.com:8080 }

telemetry:
  forward_to:
    - url: https://otel.internal.example.com:4318
      headers:
        Authorization: Bearer ${OTEL_TOKEN}

Управляемые параметры на стороне клиента

Всё выше настраивает сервер gateway. Указание машин разработчиков на него настраивается отдельно, на каждом устройстве, через управляемые параметры Claude Code. Gateway не может отправлять эти ключи сам, потому что они говорят клиенту, где находится gateway.

Для CLI установите эти ключи в managed-settings.json для каждой ОС. Два ключа входа маршрутизируют /login каждого разработчика на ваш gateway:

{
  "forceLoginMethod": "gateway",
  "forceLoginGatewayUrl": "https://claude-gateway.internal.example.com",
  "parentSettingsBehavior": "merge"
}

parentSettingsBehavior: "merge" сохраняет доставку Claude Desktop списка разрешённых исходящих соединений в его встроенные сеансы Claude Code; Доставка политики в сеансы Claude Desktop объясняет механизм и где должно находиться согласие.

Чтобы помешать разработчикам обойти gateway с помощью переменной облачного провайдера или собственного ANTHROPIC_BASE_URL, добавьте "allowedProviders": ["gateway"] в тот же файл. Claude Code затем отказывает в каждом сеансе на машине, который не настроен для Cloud gateway, и допускает gateway только когда это тот, который называет forceLoginGatewayUrl, или тот, чей URL файл устанавливает в блоке env как ANTHROPIC_BASE_URL. claude gateway отказывается запускаться на машине, которая устанавливает список, поэтому держите ключ отключённым на хосте gateway. См. запись allowedProviders в справочнике параметров. Требуется Claude Code v2.1.285 или позже.

Развёртывайте файл managed-settings.json на каждое устройство, обычно через вашу платформу MDM. Путь файла отличается по платформе. См. где каждый механизм хранит политику.

По умолчанию политика реестра в Windows или управляемые предпочтения plist в macOS заменяют файл managed-settings.json вместо слияния с ним, за исключением ключей исключения и проверок между источниками выше. Все три ключа в этом фрагменте следуют правилу источника с наивысшим приоритетом, поэтому парки, которые доставляют политику через Group Policy или профили конфигурации, должны поместить все три в этот механизм вместо этого.

Для Claude Desktop установите ключ bootstrapUrl в собственной управляемой конфигурации Claude Desktop на <listen.public_url>/user/bootstrap. Поток входа и политика для каждой группы затем совпадают с CLI после того, как политика на стороне сервера даёт согласие ключом desktop; без этого согласия /user/bootstrap возвращает 404. См. Наложение Claude Desktop для серверной части.

Claude Code учитывает forceLoginGatewayUrl, gatewayInternalNetworks и значение "gateway" ключа forceLoginMethod из управляемого источника на машине: managed-settings.json, plist macOS или реестра HKLM Windows либо помощника политики. Установка их в данных, передаваемых шлюзом, не настраивает вход через шлюз. Для собственного ~/.claude/settings.json разработчика см. Установка URL шлюза в пользовательских настройках.

Оставьте forceLoginMethod и forceLoginOrgUUID вне полезной нагрузки. Claude Code по-прежнему читает оба ключа из полезной нагрузки для проверки учётных данных при запуске, поэтому разработчик, который хранит выданные Anthropic учётные данные на машине, получает выход при запуске, описанный в разделе Политика администратора требует вход в Cloud gateway даже после того, как они вошли.

Связанное