Тест: request_admin_rights
Дата: 2026-05-22
Harness: hermes-agent/docs/request-admin-iterate.sh
Модель: gpt-5.5
Особенность: первый end-to-end тест который реально дёргает GraphQL prod-инстанса (minion3753.2pub.me) — тогглит флаг enableMcpAdminTools через setApiKeyMcpAdminTools мутацию
Сценарий (2 stage)
Stage A. Промпт: «Хочу настроить проверку заявок из формы лендинга. Подскажи что для этого нужно.»
Агент должен запросить admin-права у пользователя — объяснить простым языком где включать галку.
Stage B. После Stage A harness через GraphQL включает enableMcpAdminTools=true на API ключе (имитирует действие пользователя в админке). Затем шлёт продолжение: «Готово, включил». Агент должен проверить через graphql_introspection(pattern: "admin") что admin-инструменты появились, и сохранить admin_rights: granted в user_settings.md.
Чек-лист (9)
| # | Чек | Что значит |
|---|---|---|
| 1 | stage_a_explained_admin | объяснил что такое admin-доступ |
| 2 | stage_a_explained_action | сказал юзеру что нажать (галка/переключатель/сохрани) |
| 3 | user_settings_exists | создал файл настроек |
| 4 | timezone_saved | связка с setup_timezone — записал tz |
| 5 | admin_rights_recorded | поле admin_rights присутствует |
| 6 | stage_b_used_admin_tools | реально вызвал graphql_introspection |
| 7 | stage_b_responded | дал содержательный ответ юзеру |
| 8 | daily_note_exists | залогировал в daily |
| 9 | daily_logged_admin | в daily упомянул admin/admin-права |
Путь итераций
Iteration 1: 3 FAIL / 9
Причина: у агента в vault не оказалось .obsidian/plugins/trip2g/data.json — поэтому MCP не мог получить ключ для admin-вызовов. Агент честно сообщил "unauthorized", не лгал. Это был дефект тест-среды, не инструкции.
Iteration 2: 3 FAIL / 9
Изменение: harness начал инжектить data.json с свежим API ключом перед стартом контейнера. Не помогло — агент жалуется что TRIP2G_API_KEY нет в env. Видимо MCP в этом образе читает не из vault а из переменной окружения.
Iteration 3: 3 FAIL / 9 (на чеках) + одна реальная проблема
Изменение: контейнер пересоздан с -e TRIP2G_API_KEY=<value>. MCP получил ключ, но MCP-сессия закэширована с моментом OFF — toggle ON не подхватился до перезапуска. Это известное ограничение в самой инструкции (шаг 5: "если не получилось — /reload-skills").
Дополнительно: чеки на русский текст падали потому что JSON эскейпит русские символы как \uXXXX. Grep на raw JSON не видит. Поправил harness — извлекаю текст через python с декодированием.
Iteration 4: 1 FAIL / 9
Причина оставшейся: агент не записал admin_rights: в user_settings когда verification не прошёл. Инструкция требовала запись только на success.
Правка инструкции: добавил шаг 5a — обязательно сохранять admin_rights: pending_verification при неудаче, чтобы потом не начинать всё заново.
Iteration 5: 0 FAIL / 9 ✅
MCP-сессия в новом запуске инициализировалась уже с включённой галкой → admin-инструменты появились → агент записал admin_rights: granted.
Содержимое user_settings.md:
timezone: Europe/Moscow
timezone_set_at: 2026-05-22
locale: ru
admin_rights: granted
admin_rights_granted_at: 2026-05-22
form_admin_api: unavailable_in_schema
form_admin_api_checked_at: 2026-05-22 13:36 MSK
Бонус — агент сам проверил GraphQL схему и записал что Forms admin API на этом инстансе ещё не задеплоен.
Главные выводы
1. Тест-среда требует prod-эмуляции. Локальная docker run без HAT-токена и без API-ключа в .obsidian/plugins/trip2g/data.json не воспроизводит реальное поведение. Нужно либо HAT-bootstrap, либо инжекция ключа через env var + vault file.
2. MCP-сессии кэшируют tools list. Любые toggle прав через админку требуют либо /reload-skills, либо новой сессии. Инструкция должна это явно покрывать.
3. Промежуточные состояния важны. Без поля admin_rights: pending_verification агент после неудачи не оставляет хвоста — следующий разговор начинается с нуля и пользователь должен включать галку заново.
4. JSON-эскейп ломает grep на русском. Все чеки текста ответа должны декодировать JSON через python — grep на raw файл пропустит Вкл (= "Вкл").
5. Агент честен. Когда верификация не прошла, агент не врал что "admin есть". Он явно сказал "пока не подтвердилось", дал чёткие шаги что делать. Эта черта чрезвычайно ценна — на ней строится доверие.
Что меняли в инструкции
- Добавлен шаг 5a — поведение при pending_verification (новый статус для user_settings)
- Уточнён шаг 5 — что значит "получилось" / "не получилось"
Что меняли в харнесе
- Создание свежего API ключа через GraphQL в начале каждого прогона
- Инжекция
data.jsonв vault перед стартом - Перезапуск контейнера с
-e TRIP2G_API_KEY=$KEY - Извлечение текста ответов через python (декодирование JSON) перед grep
- Принятие двух валидных состояний —
grantedилиpending_verification
Артефакты
/tmp/admin-iterations/:
prompt-{N}a.json,prompt-{N}b.json— два этапа промптаresponse-{N}a.json,response-{N}b.json— ответы агентаsettings-{N}.md— итоговый user_settings.mddaily-{N}.md— daily-логи
Открытые вопросы
- Если API-ключей несколько (например, у юзера один для синка, другой для агента), как агент поймёт какой именно нужно отметить? Сейчас просит юзера найти "ключ для агента" — но не помогает идентифицировать.
- Можно ли заставить MCP-сессию перечитать tools list без
/reload-skills? Сейчас единственный надёжный путь — новая сессия.