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

Конфигурация

Конфиг — секциями (yaml/toml/json), можно несколько --config — поздние сливаются поверх ранних; env-префикс EVA_ (см. Быстрый старт). Обязательны только server, db и llm, остальное — опционально с дефолтами. Полный аннотированный пример — config.example.yaml. Длительности — humantime (5s, 1m, 7days, 1h 30m).

server, db (обязательные)

поледефолтчто это
server.listenадрес API, напр. 127.0.0.1:8090
server.drain2mсколько ждать идущие туры при остановке. Передеплой посреди тура иначе рвёт его на полуслове; по истечении срока туры сворачиваются штатной отменой, дописывающей частичный ответ
db.pathпуть к SQLite-файлу; создастся сам, миграции — на старте

llm (обязательная)

поледефолтчто это
provideranthropic | openai (Chat Completions — llama-server/vLLM тоже он) | venice (Venice.ai, только картинки: generate и правка по source-картинке, открытые модели без вшитой цензуры; текстовых туров не обслуживает — ему место именованным апстримом при рисующей записи models, не основным) | mock (эхо, без ключа)
model.generalосновная модель
model.fastestне задана (general)мгновенная модель декоративных реплик (комментарии в меню настроек поверхности, inline-ответы); лучше вовсе без reasoning
model.smartestне задана (general)самая сильная модель — решения, где качество суждения важнее латентности и цены: консолидация памяти во сне
model.advisorне задана (советчика нет)вторая, дешёвая модель поверх рабочего тура — см. Советчик. Не задана — цикл не запускается ни разу
model.fallback[]кому передать тур, если модель отказала не по-транзиентному (упавший ключ на апстриме, снятая модель, кончившаяся квота); пробуются по порядку. Без цепочки такой отказ роняет тур вместе с уже сделанной работой
api_keygeneric-ключ активного провайдера; для openai необязателен (локальные серверы)
base_urlу провайдера свойoverride эндпоинта, напр. http://127.0.0.1:8080
proxyне заданпрокси до LLM-эндпоинта (socks5h://… | http://…) — когда WAF провайдера блочит прямой IP хоста
max_tokens8192потолок ответа
max_tokens_guest2048потолок для туров НЕ-разрешённых пользователей (чужие в открытых чатах)
max_tokens_uncappedне заданпотолок uncapped-туров доверенных клиентов; не задан — openai-провайдеру max_tokens не шлётся вовсе, anthropic подставляет 32000 (Messages API требует поле)
models[]дополнительные модели на выбор per-чат (GET /v1/models + PUT /v1/chats/{id}/model); применяются к турам Господина. Элемент — имя-строкой или { name, multimodal, image_output, jailbreak, description, effort, price_out, provider }: multimodal включает прямую передачу картинок, image_output — модель умеет отдавать картинки в ответе (тур просит их сам, image_generate спрятан), jailbreak — per-model стир против встроенной цензуры (часть кэшируемого промпта), description — для чего модель хороша (уезжает клиентам в descriptions и читается самой Евой при выборе исполнителя; по-английски), effort — уровень рассуждения по умолчанию для этой модели (off, low, mid, high), чтобы сильная и дорогая думала в полную силу, не поднимая уровень остальным, price_out — цена выходного токена в USD за миллион, из неё статистика считает деньги за рассуждения, context_window — жёсткий потолок контекста модели в токенах (счёт контекста меряет остаток и до него, ошибка «окно переполнено» пинит счёт в это число; уезжает клиентам в context_windows), provider — имя апстрима из providers, через который ходит эта модель
providers{}именованные дополнительные апстримы: имя: { provider, api_key, base_url, proxy, reasoning, temperature, prompt_cache, structured_output } — поля значат то же, что одноимённые в llm. Модель из models выбирает свой полем provider, остальные ходят через основной; роли и model.fallback свободно смешивают модели разных апстримов. Один апстрим — один HTTP-клиент, сколько бы моделей через него ни ходило. У venice правка картинки уходит парной *-edit модели (qwen-image-2qwen-image-2-edit); имя, уже несущее «edit» (qwen-edit-uncensored), едет как есть — но тогда генерация с нуля этой записью откажет словами Venice
reasoningoffуровень рассуждения: off | low | mid | high. Старое булево читается как раньше (truemid, falseoff). средняя ступень значит «думай как обычно» и едет без глубины — ровно то, что уходило на провод при старом true. openai: поле OpenRouter + вырезание inline <think>; anthropic: расширенное мышление (off говорится вслух — думающая по умолчанию модель иначе думает всегда). Уровень тура сильнее: поле effort записи модели, ключевое слово в реплике, настройка чата, поле запроса
structured_outputfalseапстрим понимает структурированный ответ: response_format с json_schema уходит на провод там, где вызов просит схему (план сна, schema в одноразовом дополнении). По умолчанию выключено: часть шлюзов ломается на незнакомом поле (как с reasoning), а вызывающие всё равно разбирают текст с ретраем — без флага всё работает как раньше, просто чаще ретраится. Касается openai-провайдера; anthropic эмулирует схему вынужденным вызовом инструмента и флага не требует, mock отвечает валидным по схеме образцом
magic_keywordstrueслово ultrathink целиком и вне кода в реплике Господина поднимает уровень рассуждения до верхнего на один ход; из текста оно не вырезается, инструкция доезжает до модели отдельной строкой состояния тура
temperatureдефолт провайдератемпература сэмплинга
prompt_cacheвыключенTTL кэша промпта: "5m" | "1h"; локальным серверам не включать
prompt_cache_telegramне задановеррайд для туров поверхности с якорём (телеграм): "off" | "5m" | "1h"; не задан — глобальный
code_modelне заданамодель посильнее для code_task; не задана — инструмента нет
image_modelпервая с image_outputрисующая модель для image_generate; не задана и рисующих в models нет — инструмента нет
summary_modelосновнаядешёвая модель служебных саммари (компакция, названия чатов)
max_turn_iterations16жёсткий потолок походов к провайдеру за один ход

Каждая модель, на которую конфиг ссылается по имени — model.general, model.fastest, model.smartest, model.advisor, model.fallback, code_model, image_model, summary_model — обязана быть в modelsimage_model — ещё и нести image_output). Иначе ядро не стартует и называет поле с опечаткой. Правило одно на весь конфиг, потому что список — это ещё и то, что видит Господин в меню, из чего Ева выбирает исполнителя и откуда модель получает свой jailbreak: не перечисленная модель работает тише и хуже, а опечатка вскрывается отказом провайдера посреди тура. Модели эмбеддингов (memory.embedding_model) сюда не относятся — у них свой каталог (и ходят они всегда через основной провайдер). Тем же стартовым правилом проверяются и ссылки provider у записей models: имя, которого нет в providers, роняет ядро сразу, а не туром не на том апстриме.

images — блоб-стор сгенерированных картинок

поледефолтчто это
dir<каталог базы>/imagesкуда ложатся файлы картинок
base_urlhttp://<server.listen>из чего строится ссылка <base_url>/images/<id>; публичным клиентам сюда — адрес reverse-proxy, у которого /images/* открыт мимо токена (ключ доступа — неугадываемый uuid)
keep30dретенция: старше — файл и запись сносятся (чистка на старте и раз в сутки); картинка ~1 МБ, без потолка чат молча заполняет диск

context — гигиена промпта (база всегда полная)

поледефолтчто это
tool_result_keep6сколько последних сообщений держат тул-трафик целиком; старее — огрызок: и вывод, и длинные строки входа вызова (тело записанного файла, патч, скрипт), от которых остаётся пометка длины
tool_result_keep_chars24000второй бюджет того же окна, в символах — и он строже: выхлоп ОДНОЙ итерации ложится одним сообщением, поэтому шесть сообщений значат то шесть последовательных вызовов, то восемь параллельных на каждой из шести итераций. Последнее сообщение свежо всегда, даже если толще бюджета; 0 — мерить только сообщениями
reader_result_max_chars8000свой потолок ОКОННЫХ читателей (read_file, find_pattern, read_hex, history_search): их выхлоп нарезан по границам строк и сам говорит, как читать дальше, поэтому режется хвостом, а не серединой — и по более щедрой мерке
tool_result_max_chars4000кап на один tool_result даже среди свежих; инструменты, которых зовут ради полного текста (skill, agent_inbox, memory_list, chat_note_read…), внутри окна не режутся вовсе, оконные читатели режутся по reader_result_max_chars
past_tool_trafficstubчто делать с тул-трафиком ЗАКРЫТЫХ ходов: keep — оставить как есть, stub — оставить вызовы и огрызки, но схлопнуть полезную нагрузку входа за границей хода (даже если живое окно её ещё не тронуло), drop — выбросить вовсе, парами. Полный текст всегда достаёт history_search, база не трогается
turn_squeeze_percent50доля профильного порога компакции, после которой длинный тур поджимает СВОЙ трафик прямо на ходу: элизия гоняется один раз на входе, и сорокаитерационный ход иначе нёс весь свой выхлоп до переполнения окна провайдера. Тем же проходом вытесняются копии перечитанного внутри тура (тот же файл, та же выдача памяти) — у обоих одна цена, разрыв префикс-кэша, и платится она разом. Свежими остаются последние 4 сообщения, записи чтений внутри тура не отменяют; повторно — только на удвоенном весе, и проход, которому нечего схлопывать, молчит. Модель узнаёт строкой в [state], клиент — событием turn_squeezed, трасса — событием turn_squeeze. 0 выключает — вместе с вытеснением копий
compact_after_tokens37500порог компакции доверенного окружения (личка), в токенах честного счёта: контекст тяжелее — старая часть сворачивается в резюме. Устаревший ключ compact_after_chars читается как символы ÷ 4 (warning на старте)
compact_keep_tokens12500свежий хвост (в токенах), переживающий компакцию живьём; legacy-ключ compact_keep_chars — так же
compact_scopebody_after_prefixчто меряет порог: body_after_prefix — разговор без кэшируемого префикса (персона, правила, схемы тулов — стабилен и дёшев), total — весь промпт. Жёсткий потолок модели (context_window записи llm.models) всегда считает всё
compact_verbatim_percent15доля профильного порога на ДОСЛОВНЫЕ реплики Господина: при свёртке его самые свежие сообщения переживают её как есть, рядом с резюме, — формулировка задания дороже пересказа. Отбор от свежих к старым, первая не влезшая режется серединой; окно без его реплик сохранённое не стирает. 0 выключает
pressure.noticeангл. текствторая ступень давления в [state]: «осталось N»; плейсхолдеры {used}, {limit}, {left}
pressure.wrap_upангл. тексттретья ступень: приглашение свернуться ДО компакции — один раз на окно, только когда компакция не сработает сама прямо сейчас; "" выключает
pressure.just_foldedангл. текст«история только что свернулась — запиши, что резюме размыло»
pressure.wrap_up_reserve_tokens8000резерв третьей ступени: «сворачивайся» приходит, когда до ближайшей стены (порог компакции или потолок модели) меньше этого
summary_max_chars6000потолок саммари; merge пишет факт-лист без бюджета, переросшее ужимается отдельным проходом до ~80%
telegram.history_limit10нижняя граница окна живой истории телеграм-чатов В РЕПЛИКАХ ЛЮДЕЙ, не сообщениях (0 — без лимита); окно живёт в [limit, 2×limit) ходов ради кэша
telegram.past_tool_trafficdropто же поле для чатов поверхностей, со своим дефолтом: собственный выхлоп по закрытым задачам там не нужен ни модели, ни читателям чата
telegram.compact_after_tokens10000порог компакции чатов поверхностей (у чата задан surface: telegram, mtl) — ниже, компакция чаще
telegram.compact_keep_tokens3750свежий хвост поверхностной компакции
cron.compact_after_tokens3750порог компакции cron-туров — низкий: фоновой джобе не нужна вся история
cron.compact_keep_tokens1500свежий хвост cron-компакции
aggressive_folders[]папки, которые жмутся по cron-профилю (копят тяжёлый контент)
pin_first_message_folders[]папки с закреплённым первым сообщением (например транскрипт) — оно не компактится
project.root_markers[".git", ".jj", "flake.nix"]маркеры корня проекта для блока [project] (все AGENTS.md от корня до рабочего каталога): подъём от рабочего каталога останавливается на первом каталоге с любым из них; [] — подъём выключен, читается только сам каталог
project.max_bytes16384ОБЩИЙ бюджет на все AGENTS.md разом, в байтах: не влезшее усекается с подписью, какой файл пострадал; 0 выключает сбор целиком
project.memory_max_bytes8192свой бюджет памяти проекта (.eva/MEMORY.md, читается тем же проходом); 0 — файлы памяти не читаются
client_context_chars32000потолок клиентского context из send_message, в символах: чужие байты не смеют забить окно; перерост усекается серединой с явной пометкой, 0 — без потолка

chats, cron, memory

поледефолтчто это
chats.ephemeral_ttl1dayстолько молчания прощается временным чатам; молчащий уносится вместе со своими подагентами
chats.reap_interval1mкак часто ходит жнец
chats.problem_folderproblemsпапка, куда Ева заводит чат на каждую свою проблему
chats.max_agents4сколько подагентов чат держит живыми разом — предохранитель от веера
chats.quiet_folders["youtube", "cron", "code"]тихие полки: их плодит автоматика, и в GET /v1/chats без явного фильтра folder/project/surface их чаты не попадают; хвостовая * — префикс, без неё — точное имя (той же маской пользуется и сам фильтр folder: folder=mtl:* — все игровые полки разом). GET /v1/chats/folders отдаёт их как обычно
cron.tick5sразрешающая способность планировщика
memory.top_k8сколько отскоренных воспоминаний вплетается в промпт
memory.public_top_ktop_k / 2 (мин. 2)потолок релевантных в чужом публичном туре; core — всегда, личное — никогда
memory.recall_floor0.15нижняя граница выборки — ДОЛЯ от лучшего счёта в ней самой: top_k без порога добирает список до счёта, и запись, разделившая с запросом одно общее слово, занимает место наравне с попаданием. Порог относительный, потому что BM25 между запросами не нормирован; core идёт мимо скоринга и порогом не задевается. 0 выключает
memory.half_life7daysполураспад свежести
memory.prompt_budget8000потолок секции памяти в промпте, символов; core занимает не больше 60% его, остальное принадлежит выборке
memory.embedding_modelне заданамодель эмбеддингов у активного провайдера (напр. baai/bge-m3); не задана — чистый BM25

sleepсон: этапы memory и tools

Секция целиком необязательная: сон включён из коробки и безвреден на мелком корпусе (min_memories не даст этапу памяти стартовать). Наверху — общее ядро сна, работа ночи — в подсекциях этапов.

поледефолтчто это
enabledtrueвыключить целиком: компонент не поднимается, тул и ручки отвечают отказом
at00:00время суток (зона хоста), в которое пора спать, раз в сутки; пропущенную границу досыпает первым подходящим тиком
tick5mкак часто компонент сверяет, не пора ли
idle_for30mне будить, пока идёт разговор: последнее сообщение должно быть старше, живых генераций — ноль; срок не сгорает, недождавшийся тик пробует на следующем
dry_runfalseпланы обоих этапов считаются и пишутся в журнал, но не применяются — режим первых недель

sleep.memory — этап консолидации памяти

поледефолтчто это
enabledtrueвыключить только этап памяти; сон остальными этапами живёт
modelне заданаоверрайд роли smartest только для этапа; цепочка: sleep.memory.modelllm.model.smartestllm.model.general
min_memories20корпус мельче — этап памяти пропускается (сон целиком не блокируется, если этапу tools есть что делать)
max_ops40потолок правок памяти за один сон; лишние отбрасываются с отметкой в журнале
max_forget8из них забываний — отдельным, более узким потолком
keep_recent48hмоложе — не забываем и не переписываем: свежее ещё не устоялось
archive_ttl30dсколько забытое лежит в архиве до окончательного выноса
cluster_jaccard0.35ребро графа кластеризации по лексике (Jaccard основ)
cluster_cosine0.6ребро по семантике (косинус векторов одного пространства)
max_cluster8кластер крупнее — режется на подкластеры по слабейшим рёбрам

sleep.tools — этап курирования наборов инструментов

поледефолтчто это
enabledtrueвыключить только этап tools; сон остальными этапами живёт
modelне заданаоверрайд роли smartest только для этапа
max_ops10потолок правок наборов за одну ночь

Старых плоских ключей (sleep.model, sleep.max_ops, …) больше нет — serde их молча проигнорирует, и этап памяти уедет на дефолты: при обновлении секцию нужно переписать под подсекции (ломающее).

chat_sleepсон чата: набор инструментов по умолчанию

Отдельный от sleep компонент: свой у каждого чата, ленивый и фоновый, туров не держит. Секция необязательная целиком.

поледефолтчто это
enabledtrueвыключить целиком: компонент не поднимается, нуджи уходят в никуда, ручки отвечают отказом. Уже посчитанное курирование продолжает действовать — снять его можно только явно
at00:00граница суток (зона хоста), после которой сну чата пора
min_gap20hзащита от двойного сна за сутки: срок ставится не раньше, чем через это после пробуждения
retry_after1hна столько уезжает срок в момент захвата; им же закрываются дубли нуджей и падение посреди ночи
max_parallel2сколько чатов спит одновременно
dry_runfalseплан в журнал без применения — первые недели держать true
keep_days400ретеншн дневной статистики чатов; жнёт её гигиена глобального сна
min_turns10меньше туров в статистике — данных нет, этап молча пропускается
thin_turns10ниже — окно помечается thin, и на нём модели разрешено только расширять набор
skip_folders[agents, cron]полки, чьи чаты не курируются: у подагентов и крон-джоб свой узкий whitelist и однообразные туры

chat_sleep.tools — этап набора по умолчанию

поледефолтчто это
enabledtrueвыключить только этап; статистика копится и срок двигается по-прежнему
modelне заданаоверрайд на все чаты; не задана — модель самого чата
budget_percent10доля окна модели чата на схемы инструментов. Досягаемый набор влезает — этап не запускается вовсе: ни вызова модели, ни расхода. Отсюда же и то, что инструмент никогда не прячется «за молчание»
max_hide_per_night8сколько видимых инструментов одна ночь вправе спрятать
core[memory, ask_questions, think_harder, notify_master, telegram]обязательное ядро набора: курирование его не прячет. Имена тулов и групп регистрации, сверяются с реестром на старте

notesблокнот модели по чату

Секция целиком необязательная: дефолты рассчитаны на то, чтобы её не писать.

поледефолтчто это
enabledtrueвыключенный блокнот не регистрирует тулов, не идёт в промпт и не трогает базу
inline_chars2000тела тяжелее — блокнот показывается индексом
inline_back_chars1400возврат к дословному показу; ниже входного порога ради гистерезиса
inline_max8то же по числу заметок
inline_back_max6возврат по числу заметок
index_max_chars4000потолок индекса: перерос — пора пересобирать, даже если тела лёгкие
compact_after_chars20000порог пересборки по размеру тел
compact_target_chars6000во столько символов просим уложить блокнот при пересборке
max_note_chars2000потолок тела одной заметки; перебор — отказ «разбей на две»
max_notes40порог пересборки по числу заметок
pinned_max3сколько заметок можно закрепить
pinned_chars2500суммарный бюджет закреплённых тел в промпте; ниже max_note_chars ставить нельзя — законная по размеру заметка перестанет закрепляться
modelне заданамодель пересборки; не задана — модель самого чата

advisorсоветчик поверх рабочего тура

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

поледефолтчто это
enabledtrueзаткнуть советчика, не убирая роль модели
every_iterations3цикл каждой N-й итерации рабочего тура
max_steps3его собственных шагов за цикл (чтения инструментами — внутри счёта)
max_notes2вклеенных заметок за тур; подавленные щитом не в счёт
cooldown_cycles3сколько циклов молчать после вклеенной заметки
delta_max_chars6000потолок дельты транскрипта на цикл; жертвуется середина
timeout60sне уложился — тур идёт дальше без него

tools, mcp, shell

поледефолтчто это
tools.dirне заданкаталог *.toml-деклараций внешних инструментов
tools.on_demand[]имена тулов и групп, которых нет в списке по умолчанию: они видны только именем и назначением, а схему получают по tool_load. Для редкой работы, чьи схемы не должны ехать провайдеру в каждом запросе
mcp.servers.<имя>.commandstdio: argv запуска (ядро держит процесс); env — окружение
mcp.servers.<имя>.urlstreamable HTTP: URL эндпоинта; headers — заголовки (авторизация). Ровно одно из command/url
mcp.servers.<имя>.timeout60sтаймаут одного запроса (handshake, список, вызов)
mcp.servers.<имя>.accessmasterкому доступны инструменты: master | allowed | everyone
mcp.servers.<имя>.trusted_onlyfalseтолько из доверенного окружения (TUI/Android; телеграм — нет)
mcp.servers.<имя>.lazyfalseленивый старт: на старте ядра к серверу не ходить, тулы поднять из кэша прошлого запуска, первый живой вызов запустит сервер сам. Первый запуск (кэша нет) подключается как обычно
shell.remoteне задан (локально)удалённый хост: name (для логов и подсказки модели), destination ([user@]host или алиас ssh_config), args (identity, порт…)
shell.output_capне задан (без обрезки)потолок вывода shell в символах; задан — обрезка с пометкой

Сломанный MCP-сервер выключается целиком, ядро живёт дальше. На старте серверы разрешаются параллельно (старт платит за самый медленный, не за сумму), а регистрируются по отсортированным именам — порядок инструментов в промпте детерминирован. Инструмент, объявивший _meta.ui.visibility без "model" в списке (UI-виджеты MCP apps), модели не отдаётся.

modules — процессные модули

поледефолтчто это
servers.<имя>.socketUDS-сокет модуля (line-JSON-RPC, как stdio)
servers.<имя>.tcphost:port модуля на другой машине; ровно одно из socket/tcp
servers.<имя>.accesseveryoneкому доступны тулы: модуль ставит оператор, а администрирование внутри себя он запирает сам (_meta["dev.eva/master"])
servers.<имя>.trusted_onlyfalseтолько из доверенного окружения
servers.<имя>.timeoutкак у MCPтаймаут запроса
socket_dirне заданадиректория *.sock-кандидатов: видны в module_list, подключаются module_approve

Динамические модули регистрируются не конфигом, а тулами (module_register и др.) — живут в базе, тулы появляются и исчезают без рестарта ядра.

web

поледефолтчто это
proxyне заданпрокси веб-запросов (socks5h://… или http://…)
fetch_chars8000потолок отдаваемого моделью текста страницы
searxngне заданабаза своего SearXNG — источник web_search; не задана — поиска нет (на SearXNG прокси не действует — он свой и локальный)
search_results6сколько результатов поиска отдавать
booru.<доска>{}учётки danbooru/e621/gelbooru: login/user_id + api_key (секрет) — снимают анонимные лимиты
allow_private_hosts[]исключения из SSRF-щита: хосты (имена или IP-литералы), в которые web_fetch и скачивание source картинок могут ходить, даже если адрес приватный; см. безопасность

secrets — затирание секретов в выхлопе инструментов

поледефолтчто это
rulesвстроенный наборполный список правил {pattern, replace} (синтаксис Regex::replace_all, группы — ${1}); свой список замещает встроенный целиком, порядок несущий, пустой — выключает затирание

Встроенный набор: Bearer …, sk-…, AKIA…, AGE-SECRET-KEY-…, glpat-…, ghp_…/gho_…, PEM-блок приватного ключа целиком и присвоения вида token=…/API_KEY: …. Плейсхолдер называет вид секрета: [redacted: bearer token]. Подробнее — в безопасности.

tools

поледефолтчто это
dirне заданкаталог с *.toml-декларациями внешних инструментов
ask_ttl5mсколько ждут ответа кнопочные вопросы ask_questions
on_demand[]что держать вне списка по умолчанию до tool_load

Секции telegram в ядре нет: поверхность — отдельный модуль со своим конфигом.

notify — куда стучаться, когда Ева просит внимания

Путей четыре, включать можно сколько угодно — уведомление уйдёт по каждому включённому (тул может сузить набор на один вызов: имена путей — chat, push, tool, turn). Путь, который не смог, пишет в лог и не мешает остальным.

поледефолтчто это
chat_idне заданчат ядра, куда падает сообщение-уведомление — видно в любом клиенте
push.urlне заданпуш на телефон: POST текста на URL (ntfy-совместимый)
push.headers{}заголовки пуша: авторизация, приоритет, теги
toolне заданинструмент реестра, которым уходит уведомление: текст ядро кладёт полем text его входа
tool_args{}постоянная часть входа этого инструмента (объект): адрес, приоритет — всё, чего ядру знать не нужно
turn.promptне задантур Евы по инструкции: master+trusted, но всё, что требует разрешения, идёт через очередь одобрений
turn.chat_idне заданчат тура; не задан — чат повода, иначе свежий в папке проблем

Путь tool — то, чем ядро дотягивается до мессенджера, ничего о нём не зная: имя инструмента и его аргументы даёт оператор, куда это приедет — забота самого инструмента. Личка Господина в телеграме выглядит так:

notify:
  tool: "telegram_send_to_other_chat"   # инструмент модуля-поверхности
  tool_args: { chat_id: 123456789 }     # его личка

Вызов идёт мастерским и доверенным (личности за ним нет), поэтому инструменту доступны и master-only аргументы вроде адреса чата.

persona, master

поледефолтчто это
persona.fileвстроенная яфайл персоны для системного промпта
master.nameне заданимя Господина для маркера; сообщения без sender считаются его
master.aliases[]алиасы его личностей (tg:<id> и т.п.) — по ним считается master-тур