Как всё устроено¶
Адаптер — это платформа Hermes, а не отдельный сервер¶
hermes-mobile — плагин-адаптер, обычная платформа Hermes (такая же, как Telegram). Он
поднимает WebSocket-сервер внутри процесса шлюза (hermes gateway) и превращает кадры
протокола в MessageEvent, которые уходят в агента тем же путём, что и остальные каналы.
ваше приложение машина агента (hermes gateway)
┌────────────────────┐ ┌────────────────────────────────────────────┐
│ HermesClient / SDK │ │ плагин hermes-mobile (WS-сервер :8787/ws) │
│ text/audio/media │ ─────► │ │ │
│ prompt (кнопки) │ │ ▼ MessageEvent │
└────────────────────┘ │ ┌─────────────────────────────┐ │
▲ │ │ Hermes Agent │ │
│ message/media │ │ сессии · память · tools │ │
│ avatar/typing │ │ cron · биллинг · история │ │
└────────────────────│ └─────────────────────────────┘ │
└────────────────────────────────────────────┘
Ключевой вывод: у приложения нет своего бэкенда. Нет отдельного API-слоя, второй истории, второго набора инструментов и второго биллинга. Всё, что умеет агент в Telegram/CLI, он умеет и здесь — потому что это один и тот же агент.
Сессии и идентификатор устройства¶
Идентификатор сессии в Hermes — mobile:<device.id>. device.id выбирает приложение и
держит постоянным (например pilot-phone). От него зависят:
- идентификатор сессии и вся история диалога (история живёт на стороне Hermes, не в приложении);
- адрес доставки для cron и
hermes send(mobile:<device.id>); - записи в белых списках.
Один пользователь может иметь несколько устройств — это разные сессии. Одно устройство,
переподключившись, возвращается в свою же сессию: при обрыве сети достаточно снова отправить
hello, и диалог продолжится.
Если device.id не задан, адаптер сгенерирует его сам (dev-<hex>), но тогда адрес для доставки
меняется от подключения к подключению — задавайте device.id всегда.
Токены и белые списки — это разные вещи¶
Здесь легко запутаться: владельцы/пользователи и устройства — разные сущности и разные переменные.
| Переменная | Что перечисляет | Кто проверяет | Что будет, если не совпало |
|---|---|---|---|
MOBILE_TOKEN |
общий токен приложения (секрет) | адаптер, при рукопожатии | соединение закрывается кодом 1008, кадр error → auth_failed |
MOBILE_EXTRA_TOKENS |
дополнительные токены (на разные приложения/устройства); элемент device_id=token привязывает токен к устройству |
адаптер, при рукопожатии | при занятом чужом device.id → кадр error → forbidden + 1008 |
MOBILE_DELIVER_TOKENS |
токены, которым разрешён служебный кадр deliver вне loopback |
адаптер, при кадре deliver |
error → forbidden |
MOBILE_ALLOWED_DEVICES |
список device.id — устройства |
адаптер (дополнительный фильтр адаптера) | отказ auth_failed + 1008 |
MOBILE_ALLOWED_USERS |
список пользователей — штатная авторизация и pairing Hermes | сам Hermes | соединение принимается (ready), но агент не отвечает — нужен pairing/одобрение |
MOBILE_ALLOW_ALL_USERS |
1/true — принимать любое устройство с валидным токеном |
сам Hermes | — (снимает проверку пользователя) |
MOBILE_HOME_DEVICE |
устройство по умолчанию для cron | адаптер | device_offline, если оно не в сети |
Правила:
- Пустой
MOBILE_ALLOWED_DEVICES→ разрешено любое устройство с валидным токеном. - Пустой
MOBILE_TOKEN→ платформа не поднимается вообще (config_missing): адаптер не бывает «открытым». MOBILE_ALLOWED_USERS— это про пользователей (кто допущен к агенту), а фильтр устройств — этоMOBILE_ALLOWED_DEVICES. Не путайте: одно имя не должно значить две разные вещи.
Что происходит с памятью, инструментами и cron¶
- Память и история — на стороне Hermes, в профиле агента. Переустановка приложения их не теряет; несколько устройств видят свои сессии независимо.
- Инструменты — те же, что в других каналах. Опасные команды проходят через штатное
одобрение: адаптер присылает приложению карточку
promptс кнопками, а ответ резолвится родным механизмом Hermes (не как сообщение в чате). - Cron и
hermes send— умеют доставлять сообщения и файлы на устройство. Когда шлюз работает, отдельный процесс (standalone_sender_fn) подключается к нему как служебный клиент и просит отдать кадр устройству. Мобильная доставка требует живого подключения приложения: если устройство не в сети — вернётсяdevice_offline, а не «тихий» успех. - Стриминг — если включён на стороне агента, ответ сначала приходит целиком, а затем
правится по
id(кадрыmessageсedit: true).
Направления движения данных¶
- вверх (приложение → агент):
hello,text,audio,media,prompt,typing,ping,ack,deliver. - вниз (агент → приложение):
ready,message,media,prompt,prompt_done,avatar,typing,pong,error.
Полное описание каждого кадра — Протокол v1. Что реализовать в интерфейсе — Интерфейс приложения.