27 KiB
date, type, tags
| date | type | tags | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| 2026-06-20 | decision |
|
German (Hermes LXC 141) — 400 out of extra usage на cc/* через OmniRoute
Handoff-документ. Проблема НЕ закрыта полностью на 2026-06-20. Сделаны два смягчающих фикса (привязка аккаунта + retry-патч), но остаточные пики
out of usageостаются. Окончательное решение — за Олегом (Extra usage / разгрузка нагрузки). Ниже — всё, чтобы продолжить без повторного прохода по тупикам.
Симптом
German-бот (@german_dttb_bot, Hermes Agent v0.16.0, LXC 141) периодически отвечает ошибкой вместо ответа:
400 - You're out of extra usage. Add more at claude.ai/settings/usage and keep going.
Интермиттентно: ~7-12% запросов cc/* падают, остальные 200. Бот «то работает, то нет».
Что НЕ является причиной (проверено — НЕ тратить время заново)
- НЕ баг версии OmniRoute. Обновил 3.8.29 → 3.8.30 (
npm install omniroute@latestв/root/.npm/_npx/cb5891f90ae65d14, ExecStart ужеdist/server.js). Ошибка осталась. (В 2026-06-09 похожая ошибка реально была багом 3.8.7 — но не в этот раз.) - НЕ реальный лимит подписки Олега. Скриншоты Claude Code Plan usage: 5h-limit 43→53%, Weekly 5-6%, Sonnet 0% — свободно. Олег прав: «лимитов нет».
- НЕ размер запроса. Тест: контекст 357K симв (~90K токенов) → 200 на opus-4-7/opus-4-8/sonnet. Размер ни при чём.
Архитектура (как cc/* доходит до Anthropic)
German (LXC 141) → OmniRoute (LXC 132, 10.0.0.179:20128) → cliproxy (/root/.cli-proxy-api:8319) → Anthropic Max OAuth
- В OmniRoute
provider_connections(БД/root/.omniroute/storage.sqlite) — два Claude-аккаунта:e8a70f39-564d-4529-a911-4b5d0a47e512— priority 1, перегружен: SwarmClaw (8 агентов) + code-server жгут через него ~13Кopus-4-8/час → сыпет 400/429/502/529.883152e1-7160-4d5c-90eb-88822d50db31=batlaew@gmail.com— рабочий аккаунт Олега (тот, что в скриншоте 53%), свободнее, почти всё 200.
- Ключи German/openclaw в OmniRoute
api_keys:clawиtest-key(обаsk-225e902dc95ff…— это и естьOPENAI_API_KEYв/root/.hermes/.envGerman). SwarmClaw-нагрузка (13К) идёт БЕЗapi_key_name(мастер-путь), отдельно от этих ключей.
Главная диагностическая команда (с неё начинать в будущем)
# на LXC 132 (через pct exec 132 с Proxmox 10.0.0.250 root/1qaz!QAZ):
sqlite3 -column /root/.omniroute/storage.sqlite \
"SELECT model, account, status, COUNT(*) n FROM call_logs WHERE model LIKE '%opus%' GROUP BY model,account,status ORDER BY n DESC LIMIT 20"
Поля account + status сразу показывают, какой аккаунт сыпет 400 и какой 200. Не гадать про версию/лимит — смотреть сюда.
Что СДЕЛАНО (два смягчающих фикса)
1. Привязка ключей German/openclaw к рабочему аккаунту
Ключи claw/test-key имели пустой allowed_connections → ротация кидала German на перегруженный e8a70f39. Привязал к batlaew:
# на LXC 132. Формат allowed_connections = JSON-массив id (JSON.parse, length>0 ограничивает)
sqlite3 /root/.omniroute/storage.sqlite \
"UPDATE api_keys SET allowed_connections='[\"883152e1-7160-4d5c-90eb-88822d50db31\"]' WHERE name IN ('claw','test-key')"
systemctl restart omniroute # сбросить кэш ключей
- Бэкап БД:
/root/.omniroute/storage.sqlite.bak-keybind. - Проверено: 10/10 запросов German-ключом → account=batlaew. SwarmClaw не затронут (другой путь).
- Откат:
UPDATE api_keys SET allowed_connections=NULL WHERE name IN ('claw','test-key').
2. Retry-патч Hermes (out-of-usage → retryable)
До патча Hermes считал 400 out of extra usage фатальной (Aborting). Сделал retryable:
- Файл:
/usr/local/lib/hermes-agent/agent/error_classifier.py— добавлен паттернstatus_code==400 and "out of extra usage" in error_msg → FailoverReason.rate_limit, retryable=True(перед «── 2. HTTP status code classification»). config.yaml:agent.api_max_retries3 → 5.- Проверено вызовом
classify_api_error: на этот текст RETRYABLE=True, обычные 400 остаются non-retryable. - Бэкап:
error_classifier.py.bak-outofusage. Переналожатель:/root/hermes-patch-outofusage.py— запустить ПОСЛЕ обновления Hermes (патч в коде слетает).
Текущий статус (на 2026-06-20 ~16:00)
- German отвечает, когда нет пика (проверено в логах: 14:16 inbound
?→ ответ; и прямыми тестами все модели 200). - В длинные пики (>~50с, ретраи 5×40с не хватает) German всё ещё возвращает ошибку «model provider failed after retries».
- Пульсация
out of usageостаётся на ОБОИХ аккаунтах (e8a70f39 и batlaew) периодически — ДАЖЕ при свободном 5h (53%). Это похоже на burst/моментную механику Anthropic Max, из логов OmniRoute до конца НЕ объяснено.
Что осталось — варианты окончательного решения (ВЫБОР ОЛЕГА)
- Extra usage on —
claude.ai/settings/usage, секция Extra usage (не Plan usage). Поднять spend limit → overflow в пик оплачивается,out of usageисчезает для ВСЕХ ботов. Самое прямое, платно, в биллинге Олега. - Разгрузить главного пожирателя — SwarmClaw (8 агентов) + code-server с
cc/claude-opus-4-8(~13К/час) на Sonnet/меньше агентов → давление на Max-пул/burst падает. - Восстановить не-Max тракт для German (вывести из Max-пула). На 2026-06-20 ВСЕ мертвы: Kiro (
402/нет кредов), Codex (not supported/таймаут), gemini-cli (403нет лицензии), GLM (429баланс 0). - Поднять retry-окно German ещё (api_max_retries + backoff) — пережидать и длинные пики, ценой задержки ответа на 1-2 мин (плохой UX).
Связанные факты
- German модель:
config.yamlmodel.default: cc/claude-opus-4-7, fallbackcc/claude-haiku → claude/claude-haiku(всё Max-tract; при пике все падают — fallback бесполезен, ретрай важнее). Рекомендация: рассмотретьcc/claude-opus-4-8как primary (Олег его юзает в Claude Code; в тестах не хуже). - Доступ: Proxmox
10.0.0.250root/1qaz!QAZ→pct exec 141(German) /pct exec 132(OmniRoute+cliproxy). - Память: ../../.claude/projects/-Users-ai-knowledge-base/memory/feedback_omniroute_update, ../../.claude/projects/-Users-ai-knowledge-base/memory/project_german_hermes.
- Деплой German: 2026-06-18-german-hermes-agent-deploy.
Продолжение 2026-06-20 (вечер) — e8a70f39 МЁРТВ, изоляция невозможна
Олег выбрал «реанимировать e8a70f39» → не сработало по жёсткой причине:
- Флипнул
is_active=1(priority 1). При первом master-вызове OmniRoute попытался обновить протухший токен (expired 06-16) и получилRefresh token consumed (unrecoverable_refresh)→ авто-выключил аккаунт обратно (is_active=0), вызов свалился на batlaew (200). Это и есть причина, почему e8a70f39 был выключен 06-16: его OAuth refresh-токен сожжён безвозвратно. Поднять без свежего OAuth-логина нельзя. БД вернулась в исходное сама (бэкапstorage.sqlite.bak-reactivate-e8a70f39). - Вывод: рабочий Claude-аккаунт в OmniRoute РОВНО ОДИН — batlaew. Двух-пуловая изоляция (фикс #1) больше неактуальна — изолировать не на что. Привязка ключей к batlaew стала бессмысленной (он и так единственный), но не вредит.
Профиль «почему то работает, то нет» (опровергает «весь день без ошибок»)
German-ключи (claw/test-key) сегодня по часам: 09 18×200/3×400/14×429, 13 2×200/**18×400**, 14 8×200/6×400, 15 24×200 (чисто), 16 1×200/6×400. То есть весь день интермиттирующие burst-провалы, худший в 13:00; в 15:00 — идеально. Олег тестировал в 16:xx → попал в burst. Спайки 1-в-1 со спайками out of extra usage у batlaew (09:5, 12:9, 13:21, 14:7, 16:7).
«Лимитов нет» объясняется так: дашборд Plan usage (5h 53%) — сглаженное среднее и burst не показывает. Блок out of extra usage — это потолок Extra usage (pay-as-you-go overflow), который стоит на $0. В момент пика суммарный спрос на batlaew (German + SwarmClaw + code-server, все сошлись на нём после смерти e8a70f39 06-16) превышает включённый в план объём, а раз overflow $0 — Anthropic жёстко режет вместо очереди.
Сделано в этом проходе
- German default-модель
cc/claude-opus-4-7→cc/claude-opus-4-8(запрос Олега). Бэкапconfig.yaml.bak-opus48. Проверено: German-ключ → opus-4-8 → 200. Внимание: opus-4-8 НЕ снижает out-of-usage — тот же аккаунт/пул.
Реальные варианты (e8a70f39 вычеркнут) — ВЫБОР ОЛЕГА
- Extra usage ON на batlaew (
claude.ai/settings/usage→ Extra usage, не Plan) — единственное, что убирает out-of-usage насовсем при одном аккаунте. Платно, биллинг Олега. Рекомендация #1. - Разгрузить burst-пожирателей — SwarmClaw (8 агентов) + code-server с
cc/opus-4-8на Sonnet/меньше агентов → суммарный пик влезает в план batlaew. - Свежий OAuth второго Max-аккаунта в OmniRoute (заново залогинить — хоть тот же, что был e8a70f39, хоть новый) → восстановить двух-пуловую изоляцию. Требует интерактивного OAuth (Олег).
- Реальный backoff ретраев German (сейчас 5 ретраев летят за <1с — бесполезно против burst в секунды-минуту). Пережидать пик ценой задержки ответа.
Продолжение 2026-06-20 (вечер-2) — СМЕНА СТРАТЕГИИ: почему Антошка работает, а German нет
Олег ткнул верно: openclaw (Антошка) на том же OmniRoute/Opus 4.8 работает стабильно → теория «account-level cap» неполна. Сравнил два бота эмпирически (call_logs) — 3 реальные разницы:
- Объём. Антошка (ключ
claw) сегодня = 2 вызова; German (test-key) = 114 (+ master/SwarmClaw+codeserver 130). German — половина нагрузки batlaew и worst fail-rate (39/114=34%). Антошка «работает» во многом потому что лёгкий → редко попадает в burst. - Фоллбэк-цепочка. У German была
cc/claude-haiku → claude/claude-haiku(ОБА Max → бьются в тот жеout of extra usage, что и opus — проверено: sonnet-4-6 тоже ловит этот 400). У Антошки последний фоллбэк =kr/claude-sonnet-4.5(Kiro, FREE, не-Max) → когда Max в пике, Антошка уезжает на не-Max и продолжает отвечать. - Пин ключа (КОРЕНЬ). Фикс #1 (
allowed_connections=['883152e1'/batlaew]) делался против перегруженного e8a70f39 — но тот мёртв. Пин же запер German на единственном перегруженном batlaew: эскейп-маршрутыkr//cx/ключом German отдавали 400 (connection-not-allowed). Пин из «защиты» превратился в «ловушку». ../../.claude/projects/-Users-ai-knowledge-base/memory/feedback_root_cause_recurring: лечил симптом, корень — в своём же конфиге.
Сделано (привёл German к схеме Антошки, всё в рамках моих прав, без биллинга)
- Снят пин с
test-keyиclaw:UPDATE api_keys SET allowed_connections=NULL WHERE name IN ('test-key','claw'). Теперь opus-4-8 всё равно → batlaew (других Max-аккаунтов нет), а kr//cx/ доходят до своих провайдеров. Проверено: до — kr/cx=400, после — opus-4-8=200, kr/cx доходят (402/timeout = флап free-пулов, но маршрут открыт). - Фоллбэк-цепочка German переписана как у Антошки:
cc/claude-sonnet-4-6 → kr/claude-sonnet-4.5 → cx/gpt-5.5(выкинул мёртвый haiku→haiku). Бэкапconfig.yaml.bak-fallback-*. - Primary =
cc/claude-opus-4-8. German стабилен (NRestarts=0), opus-4-8 → 200.
Честный остаток (Олегу знать)
Это не делает German неуязвимым — free-эскейпы (Kiro/Codex/GLM) сейчас сами полудохлые (Kiro: «reached the limit» 402 / «fetch failed» 502 / 429; Codex throttled; GLM баланс 0). В ГЛУБОКИЙ burst, когда и batlaew capped, и free-пулы лежат — German всё ещё может блипнуть (как блипнул бы и Антошка под такой нагрузкой). German теперь архитектурно равен рабочему боту, а не сломан. Для полной неуязвимости при тяжёлой нагрузке всё равно нужно одно из: Extra usage ON на batlaew / разгрузка master-пути (SwarmClaw 8 агентов + code-server = вторая половина нагрузки batlaew) / свежий 2-й Max-аккаунт (OAuth). Возможный твик при рецидиве: снизить api_max_retries 5→3 (сейчас burst → шторм 5×4 тира вызовов, сам прогревает cap).
Продолжение 2026-06-20 (вечер-3) — ДОКАЗАНО: это всё-таки account-level cap, протокол ни при чём
Олег давил: «дело не в лимитах, почему Антошка работает». Проверил гипотезу «формат запроса»:
- Эндпоинт-разница реальна: Антошка (
claw) шлёт нативный Anthropic/v1/messages(source_format=claude), German (test-key) — OpenAI-формат/v1/chat/completions+/v1/responses. История: claw 448×200 / 0×400;/v1/messagesсуммарно 355×200 / 0 out-of-usage, а ВСЕ 396out of extra usage— на/v1/chat/completions. Выглядело как корень. - Перевёл German primary на
provider: anthropic+/v1/messages(+ANTHROPIC_API_KEYв .env). Подтвердил: трафик пошёлpath=/v1/messages source_format=claude. И всё равно поймалout of extra usage400 (17:11/17:12 на opus-4-8 через /v1/messages; в 17:04 был 200 — т.е. интермиттентно). - РЕШАЮЩИЙ ТЕСТ: бил
/v1/messagesopus-4-8 обоими ключами (claw Антошки + test-key German) залпами. В пик — оба 400, вне пика — оба 200×5. Ключ Антошки ловит ту же ошибку. Значит «0×400 у claw» в истории = следствие МАЛОГО ОБЪЁМА (claw сегодня 2 вызова против 114 у German), а не иммунитета протокола. - Вывод:
out of extra usage— account-level cap на batlaew, интермиттентный (burst), бьёт по ЛЮБОМУ пути (/v1/messages и /chat/completions) и ЛЮБОЙ модели (opus/sonnet/haiku — всё проверено). Антошка «работает» только потому что лёгкий. Дашборд Олега = Plan usage (5h-среднее, 53%), а режет потолок Extra usage (overflow) = $0. Это и есть лимит, просто не тот, что на дашборде. - Откат: протокол-правку вернул к проверенному
provider: custom+/v1(anthropic-режим не помог и не проверен на tool-нагрузке German — спекулятивная правка).ANTHROPIC_API_KEYубран. Бэкап откатаconfig.yaml.bak-anthropic-170948.
Итоговое состояние German (что осталось включённым)
- primary
cc/claude-opus-4-8(custom/openai-compat, проверенный путь), фоллбэкcc/sonnet-4-6 → kr/sonnet-4.5 → cx/gpt-5.5, ключ распинён (NULL). active, opus-4-8→200.
Финал (без иллюзий): убрать out of extra usage можно только так
- Extra usage ON на batlaew —
claude.ai/settings/usage→ секция Extra usage (не Plan). Это буквально то, что просит текст ошибки. Снимает cap для всех. - Срезать конкурентную burst-нагрузку на batlaew: SwarmClaw (8 агентов) + code-server (cc/opus-4-8) = вторая половина трафика, льют параллельно → создают пики. Throttle/Sonnet/меньше агентов.
- German усиливает пики своим retry-штормом (5 ретраев × 4 тира мгновенно). Снизить
api_max_retries5→3 — меньше шторм, меньше вклад в cap. - Свежий 2-й Max-аккаунт (OAuth) — изоляция German на отдельный пул.
Продолжение 2026-06-20 (вечер-4) — SwarmClaw НЕ ест лимит + фикс «работает» через overloaded-backoff
Олег: «SwarmClaw 3 дня не юзаю, как он ест лимит?» — прав, проверил:
- Master-путь на batlaew (opus) по дням: 06-17=268, 06-18=591, 06-19=82, 06-20=74. Тяжёлый поток был 3 дня назад, сошёл на нет. SwarmClaw сейчас лимит НЕ ест — прежняя атрибуция неверна для текущего момента.
- Крупнейший потребитель СЕЙЧАС — сам German: opus-токены batlaew сегодня — test-key(German) 916K fresh in / 877K cache; (master) 394K; claw(Антошка) 83K. German грузит большой KB-контекст в каждый ход × tool-loop → ест в 2.3× больше master и 11× больше Антошки. Антошка лёгкий → не упирается.
Почему backoff раньше «не работал» (казалось мгновенным)
В логе 16:17 5 ретраев были на timestamp 16:17:10 — иллюзия от буферизации (_buffer_vprint флашится разом). Реально backoff ЕСТЬ: conversation_loop.py:3439 jittered_backoff(base_delay=2.0, max_delay=60.0) + respects Retry-After. НО для rate_limit есть eager-failover (2764): при наличии фоллбэк-цепочки Hermes сразу прыгает на следующую модель, минуя ожидание opus — и каскадит через дохлые free-пулы (kr 400/cx 429) → быстро сдаётся.
Фикс «чтобы работал» (выбор Олега делегирован мне)
- out-of-usage классифицирован как
FailoverReason.overloaded(былоrate_limit) вerror_classifier.py:674. overloaded НЕ триггерит eager-failover (2764 ловит только rate_limit/billing) → German пережидает burst на самом opus-4-8 с backoff (2с→60с jittered), а не каскадит на мёртвые фоллбэки. Провереноclassify_api_error: out-of-usage→overloaded/retryable=True; обычная 400→model_not_found/non-retryable (узкий паттерн). Бэкапerror_classifier.py.bak-overloaded-*, переналожатель/root/hermes-patch-outofusage.pyобновлён (rate_limit→overloaded). api_max_retries5→6 — окно пережидания ~1-2 мин (jittered 2с..60с × 6).- Сохранены: opus-4-8 primary, распин ключа, цепочка фоллбэков (теперь — последний резерв ПОСЛЕ ожидания opus).
Механика: batlaew кратко капается → German ждёт (2с,4с,8с…до 60с) и повторяет opus, ловя восстановление за ~1-2 мин, вместо мгновенной ошибки. Цена — в пик ответ на десятки секунд позже (но ОТВЕЧАЕТ). Это не победит длинный (>2 мин) аккаунт-аутаж, но такие редки; обычный burst — секунды. Полностью убирает out-of-usage всё равно только Extra usage ON / урезание контекста German (RAG вместо полного KB).
Продолжение 2026-06-20 (вечер-5) — НАСТОЯЩЕЕ различие German vs Антошка: агентный burst
Олег: «какие ещё идеи, почему German не работает, а Антошка да». Проверил оставшиеся гипотезы на уровне запроса:
-
Per-key лимиты (test-key vs claw): у обоих пусто — исключено.
-
Холодный кэш (идея: German простаивает → cache_ttl 5m протухает → дорогой re-create): ОПРОВЕРГНУТО. German кэшируется нормально (3 дня: cache_read 1.5M vs cache_creation 450K). Антошка кэш вообще не читает (read=0), но ему и не надо.
-
Тела запросов (max_tokens/thinking): артефакты OmniRoute хранятся усечённо (~572 симв) → ненадёжно.
-
★ НАЙДЕНО — агентный burst вызовов:
Антошка (claw) German (test-key) макс. opus-вызовов/мин 1 8 (стабильно 6-7) вызовов за 3 дня 13 158 German — агентный (tool-loop): 1 сообщение Олега → каскад 6-8 Opus-вызовов/мин, каждый тащит ~45K-контекст → ~360K Opus-токенов залпом в минуту. Антошка — разговорный, 1 вызов на обращение. 5h-лимит Max взвешенный (Opus ~5× Sonnet), и минутный burst German пробивает мгновенную взвешенную планку Opus →
out of extra usage. Дашборд (53%) = 5h-среднее, не минутный пик. Это и есть «почему German, а не Антошка» — частота Opus-вызовов на сообщение (агентность vs разговорность), не формат/ключ/кэш/KB.
Сделано
agent.max_turns80 → 25 (goals.max_turns20 не трогал) — ограничивает размер burst: одна сложная задача больше не выстрелит до 80 Opus-вызовов подряд. Бэкапconfig.yaml.bak-maxturns-*. German active, opus-4-8→200.
Полный набор активных мер для German (итог всей цепочки)
- primary
cc/claude-opus-4-8; ключ распинён (NULL); фоллбэкcc/sonnet-4-6 → kr/sonnet-4.5 → cx/gpt-5.5(резерв). - out-of-usage →
overloaded(backoff-пережидание burst на opus, не каскад на дохлые фоллбэки) +api_max_retries6. max_turns25 (меньше burst). Остаточный полный фикс (если рецидив): Sonnet 4.6 как primary (в ~5× легче по весу Max, «Sonnet 0%» — почти без лимита) ИЛИ Extra usage ON.
Урок (мне на будущее)
Я трижды выдал неверный диагноз (баг версии → реальный лимит → перегрузка пула), прежде чем дошёл до call_logs по account. При out of usage на cc/ — СНАЧАЛА call_logs GROUP BY account,status, потом гипотезы.* См. ../../.claude/projects/-Users-ai-knowledge-base/memory/feedback_root_cause_recurring.