
Попросите агента «поставь нам LLM-шлюз», и он уверенно придумает переменные окружения, которых не существует. Поэтому у Keystone есть плагин для Claude Code: восемь скиллов, которые знают настоящие команды, флаги и поля конфига, и MCP-сервер, через который агент видит, что запущено. Ключи при этом в чат не попадают.
Keystone. The Model Switchboard. (KTMS) — self-hosted LLM-шлюз на Go: сервисы ходят в одну точку, а он хранит ключи вендоров, выбирает модель по правилам, переключается при отказах и держит лимиты расходов. Про сам шлюз была релизная статья, здесь — как его поставить за один разговор с агентом.
Установка
claude plugin marketplace add ai-process/ktms && claude plugin install ktms@ai-process
✔ Successfully added marketplace: ai-process (declared in user settings)
Installing plugin "ktms@ai-process"...✔ Successfully installed plugin: ktms@ai-process (scope: user)
Скиллы вызывают CLI ktms, его нужно положить в PATH из архива релиза или через go install. Версия плагина совпадает с версией Keystone.
|
Скилл |
Что делает |
|---|---|
|
|
Смотрит на систему и говорит, куда встаёт Keystone и с чего начать |
|
|
Compose или Helm, секреты, порядок первого запуска |
|
|
Переводит вызовы LLM одного сервиса на шлюз |
|
|
Маршрутизация, ключи и лимиты в |
|
|
Переезд с другого шлюза или с прямых вызовов SDK |
|
|
Локальная GPU-нода с фолбэком в облако |
|
|
Вопросы о расходах, отчёты и алерты |
|
|
Проверка перед запуском и после |
Помнить названия не нужно: агент сам берёт подходящий скилл, а слеш-команда запускает его явно.
Шаг 1. Куда встаёт шлюз
Демо-проект — три сервиса. Бот поддержки на OpenAI SDK с model="gpt-4o" в двух местах, поиск на Anthropic SDK с эмбеддингами OpenAI, ночной воркер, который зовёт Gemini около 40 000 раз за ночь. В Compose уже есть Postgres, Redis и Prometheus.
/ktms:assess ничего не меняет. Он читает код и деплой, перечисляет все вызовы LLM с файлом и строкой и отвечает: где запустить Keystone, что поменяется в каждом сервисе, что это даст и чего будет стоить, какой скилл запускать дальше. И честно говорит, если шлюз здесь не нужен: например, один сервис, одна модель, лимитов нет.
Ответ — отчёт строк на сто. Скилл нашёл все пять вызовов с файлом и строкой и заметил то, о чём его не спрашивали:
Every service loads it through
env_file, so each one gets all three vendor keys.
То есть каждый сервис получает все три ключа вендоров. И про temperature:
temperature=0.3indraft_reply:/v1ignores it, so check reply quality after the switch.
Ещё он заметил, что rerank.ts ничего не переранжирует, а только объясняет результаты, и что основные деньги и риск — в ночном воркере. Шлюз он ставит так:
Compose project "demo-shop" (one network, nothing exposed to the host)
┌─────────────────────────────────────────────────────────────────┐
│ support-bot ─┐ │
│ search-api ──┼── HTTP :8080 /v1 ──▶ ktms ──▶ OpenAI │
│ digest-worker┘ (gRPC :9090 later ├─▶ Anthropic │
│ for batch) └─▶ Gemini │
│ │ │ │ │
│ postgres:16 ◀── db "ktms" ──┘ │ └── :9091 ◀── prometheus │
│ redis:7 ◀──── limits ──────────┘ │
│ light-tokenmeter ◀── usage events (spend per action_id) │
│ ktms-admin (internal only; reach it via SSH tunnel/VPN) │
└─────────────────────────────────────────────────────────────────┘
Вердикт с условием:
Verdict: worth it. If the system were only support-bot on
gpt-4o, it wouldn’t be.
Если бы был только бот поддержки на gpt-4o, шлюз был бы не нужен. План начинается с ночного воркера: один вызов, пользователи его не видят, неудачную ночь можно просто перезапустить.
Шаг 2. Деплой и конфиг без ключей в чате
/ktms:deploy сначала спрашивает: Compose на одном хосте или Kubernetes с Helm, свои или управляемые Postgres и Redis, где хранятся секреты, имена хостов, мониторинг. Потом пишет файлы, где каждый секрет — ссылка на хранилище, пробы на /readyz и порядок первого запуска.
Один шаг агент нарочно оставляет человеку: ktms init в собственном терминале. Команда спрашивает админский ключ и ключи вендоров без эха, поэтому в чат они не попадают, пишет ktms.yaml с моделями и правилами по умолчанию, показывает план и применяет.

Дальше /ktms:configure работает с этим файлом как с Terraform: правка, ktms config plan, план показан человеку, применение только после согласия. Ограничения зашиты в инструменты, а не в промпт:
-
MCP-сервер
ktmsпо умолчанию только читает. Инструменты записи появляются, только если
добавить --allow-write.
-
config_planвозвращаетplan_id, аconfig_applyприменяет ровно этот план один раз и
откажется, если конфигурация успела измениться.
-
Ключ вендора в плане берётся из окружения MCP-сервера и только из переменных
KTMS_VENDOR_KEY_*,
так что агент не может подсунуть в конфиг админский ключ или другой секрет.
-
Имена и значения, пришедшие из Keystone, помечены как данные, а не инструкции.
Шаг 3. Перевести один сервис
/ktms:integrate тоже начинает со списка вызовов и ничего не меняет. Потом собирает адрес, ключ, таймауты, ретраи и атрибуцию в один маленький клиентский модуль и меняет каждую зашитую модель на уровень сложности с обоснованием в одну строку: low для классификации и коротких ответов, medium для обычной генерации, high для рассуждений и длинных документов.
Он же выключает ретраи SDK и один раз реализует контракт ошибок (ждать Retry-After на 429, отступать на 503, не повторять ошибки конфигурации) и помечает то, что не переносится: эмбеддингам нужен точный id модели, а temperature, top_p, stop и seed OpenAI-совместимый API Keystone игнорирует.
Проверка в конце — по настоящей маршрутизации:
$ ktms route explain billing --effort low
rule: default effort: low route mode: direct
# MODEL VENDOR STATE
1 gpt-4o-mini openai kept
2 gemini-2.5-flash google dropped: no_vendor_key
3 gpt-4o openai dropped: effort
tries: gpt-4o-mini
Это вывод Keystone 1.3.6. Цепочка, которая заканчивается моделью в статусе kept, в порядке; если в конце no_vendor_key, ключа не хватает, и это видно до выкатки сервиса.
Почему скиллы не устаревают
Скилл, который называет флаг, удалённый два релиза назад, отправит агента в ошибку, а дальше агент начнёт импровизировать. Поэтому CI Keystone читает каждый SKILL.md и падает, если в нём есть команда ktms, флаг, инструмент MCP или раздел README, которых в этой версии нет.
Не только Claude Code
Скиллы — обычные Agent Skills, папка с SKILL.md. Их можно скопировать в Codex, Cursor или другой агент, который их читает, и подключить два MCP-сервера. Для ассистентов без скиллов и MCP те же инструкции лежат промптами.
-
Keystone: https://github.com/ai-process/ktms
-
Подробнее, на английском: https://blog.ai-process.dev/2026/11/04/set-up-keystone-from-claude-code/
Автор: coylOne


