---
name: cebers-pulse-llm-rules
description: "Правило выбора LLM — запрещён только СВОЙ Claude/прямой Anthropic API, через стороннего провайдера можно; кросс-проектное (cebers-pulse, investpilot), каждый слот с fallback"
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 6620ea3d-79ed-46e4-b5ea-65828f0cc0b8
  modified: 2026-07-23T05:30:41.460Z
---

Два устойчивых правила владельца для бота cebers-pulse (2026-06-11):

1. **Запрещён только «свой» Claude** — Anthropic-официальный (прямой Anthropic API / та модель, на которой работает сам ассистент / тот же вендор-канал). **Claude через СТОРОННИЙ провайдер/шлюз — РАЗРЕШЁН** (уточнение юзера 2026-06-14: «Claude нельзя в смысле твой, если какой-то другой провайдер — то можно»). Это СМЯГЧАЕТ прежний тотальный запрет (раньше резали и agy/*, и kiro/*). Теперь Claude-модель, отдаваемая третьим провайдером (logfare, сторонний gateway), допустима в прод. При выборе слота можно брать лучшую модель, включая Claude-через-чужой-провайдер; нельзя — прямой Anthropic.
   **Концретно (2026-06-17): aerolink (`capi.aerolink.lat`) = сторонний серый Claude-Code-прокси** (`ANTHROPIC_BASE_URL`, каталог только Claude: opus-4-7/8, sonnet-4-6, haiku-4-5, fable-5; не-Claude имена → 400; ошибки на китайском; квоты 5h/weekly). Маркетинг-сайт `aerolink.lat` за Cloudflare-Turnstile (недостижим), но **API-хост `capi.aerolink.lat` открыт даже с RU-IP мини**. Подключён в Делор как спорт-**voter#8** `claude-sonnet-4-6` (commit c355c53). ⚠️ Условие владельца для таких серых 3rd-party шлюзов: **использовать аккуратно — чтобы провайдер НЕ мог читать/менять ПК и не видел chat/1С/личное.** → обязательна изоляция как у atessa: off-bus + `AtessaClient(provider_label="aerolink")` + `assert_sport_only` (fail-closed вне `sport_analysis_scope`), ответ только голос консенсуса (не исполняется). Ключ только в plist `DELOR_AEROLINK_API_KEY` (обе: com.cebers.delor + delor-sport), не в git. См. [[risky-llm-provider-isolation]].
2. **Каждый модельный слот обязан иметь fallback.** Новый LLM-слот в конфиге = сразу пара (primary + fallback) и механика переключения (готовый `ChainAdvisorLLM` в advisor/llm_client.py поддерживает вложение: модельный отказ → та же семья, канальный отказ → другой провайдер).

**Why:** юзер явно запретил Claude для этого бота (12-я итерация v0.16.2, откат agy/claude-opus с onec_llm) и потребовал отказоустойчивость на уровне модели.

**ОБНОВЛЕНО 2026-07-18:** повторно подтверждено юзером в контексте notion-web2api (:1722, Enterprise-сиденье с каталогом fable-5/opus-4.8/sonnet-5/haiku-4.5 наравне с gpt/gemini/grok/kimi/deepseek/glm) как 4-й уровень фолбэка для Делор-спорта: «Claude можно выбирать, правило должно работать, что не использовать мою подписку на тебя, а claude модели от других провайдеров можно использовать». Я по ошибке в той сессии написал в коде «НЕ Claude-модели» (сослался на укороченную строку MEMORY.md-индекса, не на этот файл целиком) и выбрал deepseek-v4-pro вместо, например, sonnet-5 через notion. Урок: **строка индекса MEMORY.md — не источник истины сама по себе, при спорных решениях («можно ли Х») открывать полный файл памяти, не полагаться на однострочный кэш.** Индекс поправлен на точную формулировку.

**ПОДТВЕРЖДЕНО КРОСС-ПРОЕКТНО 2026-07-23 (investpilot, [[investpilot_recalibration_overext]]).** Аудит-агент безопасности принял правило investpilot буквально («no Claude models in the bot's runtime LLM chains») и пометил `research/notion-opus` (Claude Opus 4.8 через Notion Enterprise-прокси, стоит хвостом в `llm_primary_fallbacks`/`llm_challenger_fallbacks`/`kb_distill_fallback`) как нарушение границы. Владелец уточнил: «Claude цепочки можно ставить, просто чтобы провайдер был не ты и не anthropic» — то есть то же правило, что и для cebers-pulse, просто раньше нигде явно не зафиксировано ДЛЯ investpilot конкретно. Не нарушение, код не менялся. **Урок:** формулировка security-constraint в контексте конкретного проекта («no Claude models») может быть КОРОТКОЙ версией этого общего правила, а не отдельным более строгим запретом — при находке «Claude-модель в проде» сверяться с этим файлом ПЕРЕД тем, как квалифицировать как нарушение, а не доверять дословной формулировке локального constraint-списка.

**How to apply:** при любых изменениях моделей в cebers-pulse сверяться с этим правилом; в бенчи Claude можно включать только для справки, в прод — нет. codex/* как fallback не годится — квота пула выжигается неделями. После смены моделей — прогнать `scripts/llm_slots_health.py` (живой пинг всех слотов); новый слот добавить в `SLOT_FIELDS` (src/cebers_pulse/llm_health.py) — иначе мониторинг (тик 6ч, DM при отказе) его не увидит. Связано: [[cebers_pulse_v080_state]].

**L2 текст/vision РАЗДЕЛЕНЫ + пустой ответ = сбой (2026-06-17, commit a85fe74).** Регрессия: vision-правка отдала `cloud_l2_chat_model` под флапающую nvidia-vision, а через него шёл и общий ТЕКСТ-чат (`_select_l2_model` case `_`) → каждый чат: nvidia-11b-vision (404/таймаут)→nvidia-90b(медленно)→groq = «чат не работает». Фикс: `cloud_l2_chat_model="cerebras/gpt-oss-120b"` (надёжный текст при любом бюджете; reasoning-модели типа `cerebras/zai-glm-4.7` ПУСТЕЮТ на малом max_tokens — thinking съедает бюджет!), fallback `mistral/mistral-small-latest`; vision вынесен в отдельные `cloud_l2_vision_model/_fallback` (nvidia VLM), роутятся ТОЛЬКО `has_media`/VISION (router `_select_l2_model`+`_get_l2_fallback`, onec `_vision_form`, SLOT_FIELDS l2chat=text + новый l2vision=vision). `_try_cloud`: пустой контент → `None` (роутер падает на след. слот, не отдаёт юзеру пустоту; `route_stream` это умел, `route()` — которым ходит чат-агент через agent_loop — нет). Проверено реальным TG-e2e: бот отвечает полным текстом быстро. ⚠️ Чат-агент (`run_agent_stream`) использует `pulse_router.route()` (НЕ route_stream).

**siliconflow снят со всех слотов + анти-спам монитора (2026-06-17, commit e5219f9).** siliconflow массово флапает целым провайдером (все модели → 60с-таймаут/503) — ломал бот и спамил пушами на каждый heal. Убран из ВСЕХ активных слотов (sport primary-FB/last-resort/FB2/deep-review + L2 reasoning/code) и из heal-пулов (text/code/l2code/sport/sportdeep). Замены: chat → trusted `cerebras/zai-glm-4.7` + `nvidia/meta/llama-3.3-70b-instruct`; sport → cerebras + nvidia + fmd. Из heal-пулов также вычищены умирающий gemini-cli и IP-banned groq. **Sport voter#4 (FB3) удалён** (не осталось надёжного нес-siliconflow bus-голоса без дублирования; build_sport_voters пропускает пустой `sport_llm_fallback3`, слот снят из SLOT_FIELDS/SPORT_VOTERS) — спорт-голосов теперь 3 на шине (#1 cerebras-glm, #2 cerebras-oss, #3 nvidia-70b→research) + off-bus #5 z.ai/#6 atessa/#7 fmd/#8 aerolink. **Анти-спам:** health-монитор шлёт DM ТОЛЬКО на критику (слоту нет живой замены `⚠️` / спорт-кворум `🚨` голодает или восстановился); рутинные самозалеченные флапы (любой free-провайдер, вкл. nvidia-vision, который тоже 404-троттлит) — только в лог. Иначе любой нестабильный провайдер снова делал из монитора пуш-рассылку. ⚠️ Перед опорой на старые комментарии в config.py: там ещё остались stale-упоминания siliconflow как «primary/voter#3» — это комментарии, активные значения уже cerebras/nvidia.

**Три уровня отказоустойчивости (v0.16.2→v0.17, на проде):** (1) per-запрос failover — `ChainAdvisorLLM` (вложение: модель→семья→другой провайдер) + перебор fallback'ов в router/judge; (2) мониторинг `llm_health.py` (тик 6ч, пинг primary И fallback, DM при отказе/восстановлении); (3) **самолечение `llm_auto_heal=True`**: мёртвый слот на лету (runtime-setattr settings, БЕЗ записи в git — D27) переключается на живую модель из `HEAL_CANDIDATES` своего типа (text/code/vision; vision-слотам только vision; не дублирует живые модели той же подсистемы), оживший оригинал возвращается, каждая замена/возврат — DM. Канон в git = источник истины, после рестарта расхождение переобнаруживается. `SLOT_FIELDS` = кортеж `(label, field, group, tier)` — при добавлении слота указывать group (подсистема) и tier (text/code/vision).
