Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Советчик

Работающий агент видит свой тур изнутри — и оттуда не видно, что он час чинит не тот файл. Советчик — вторая, дешёвая модель со своей историей: раз в несколько итераций ей показывают дельту транскрипта (что Ева сказала, что позвала, что вернулось), она при желании читает своими инструментами и, если увидела промах, кладёт в тур одну заметку:

<advisory severity="concern" guidance="weigh, don't blindly obey">…</advisory>

Блок клеится спереди к результату инструмента только в промпт-копии — тем же каналом, что и правила. В базу и в стрим клиента уходит чистый выхлоп: это служебная вставка, а не речь.

Ева про советчика в промпте не знает вовсе. Тег со своим guidance — её единственная подсказка, как к этому относиться: взвесь, не подчиняйся слепо. Советчик не начальник, и заметка, в которой он неправ, обязана проиграть тому, что Ева видит своими глазами.

Где он включается

условиезачем так
задана llm.model.advisorбез роли советчика нет вовсе: он удваивает разговор с моделью, и это решение Господина, а не дефолт
advisor.enabledзаткнуть, не убирая роль
рабочий турклиентские операции, рабочий режим набора (он же кодовый) или подагент — там легче всего увязнуть, и там ошибка дороже
тур Господинав чужом туре он комментировал бы чужую переписку

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

Цена

Цикл идёт каждой every_iterations-й итерации рабочего тура и стоит от одного до max_steps вызовов дешёвой модели плюс его чтения. Платим ещё и латентностью: цикл идёт внутри тура, между итерациями, и не уложившийся в timeout просто выбрасывается — тур продолжается без него. Кулдаун после заметки цикл не запускает вовсе, так что говорящий советчик обходится дешевле молчаливого.

Инструменты

Только читающие: read_file, find_pattern, history_search. Мутирующих у советчика не будет никогда, даже под флагом: за файловыми инструментами стоит настоящая машина Господина. Список — детерминированный белый, а не просьба в промпте: любое другое имя отбивается кодом.

Голос у советчика один — инструмент advisory_note (severity, text). В реестре ядра его нет: Еве он не виден и не доступен.

Щит вокруг заметки

Без щита вторая модель превращает тур в поток «продолжай, ты молодец». Щит живёт в коде (src/advisor.rs), а не в промпте советчика:

правилочто делает
нормализацияNFKC, нижний регистр, всё неалфавитное — в пробел: перефразировка пунктуацией не становится новой мыслью
чёрный список«lgtm», «продолжай», «замечаний нет», «готово», «стоп» и родня. Молчание — правильная форма «всё хорошо»
дедуп кольцомта же заметка второй раз не проходит (32 последних на чат)
одна за циклвторая — подавляется; подавленные потолок max_notes не расходуют
кулдаунпосле вклеенной заметки советчик молчит cooldown_cycles циклов: иначе он комментирует собственное вмешательство, не дав ему сработать
сбросперезапись истории (компакция, пересборка резюме, chat_clear) стирает всю его память о чате — иначе он рецензирует то, чего уже нет

Подавление невидимо советчику: на любую заметку инструмент отвечает «записано». Скажешь ему «подавлено» — он перефразирует ту же бесполезную мысль в обход дедупа, и заплатит за это Господин.

Ступени

severitynit | concern | blocker. Ступень доезжает до Евы атрибутом тега, но обрабатываются все три одинаково мягко: идущий тур советчик не прерывает. Жёсткая половина (обрыв и ретрай) сядет вместе с жёсткой половиной правил — до тех пор blocker отличается от nit только тем, как Ева его прочтёт.

Телеметрия

Каждая заметка — вклеенная и подавленная — пишется в advisor_notes, а вклеенная ещё и в лог. Свод — в GET /v1/stats, поле advisor:

"advisor": [{ "verdict": "spliced", "notes": 2 }, { "verdict": "hollow", "notes": 7 }]

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

Настройка

llm:
  model:
    advisor: "qwen/qwen3.7-flash"   # без этого советчика нет

advisor:                # вся секция опциональна
  enabled: true
  every_iterations: 3   # цикл каждой третьей итерации рабочего тура
  max_steps: 3          # его собственных шагов за цикл
  max_notes: 2          # вклеенных заметок за тур
  cooldown_cycles: 3    # молчания после заметки
  delta_max_chars: 6000 # потолок дельты транскрипта
  timeout: 60s          # не уложился — тур идёт дальше без него