19. Виджет и каналы ввода/вывода
🔵 Как пользователи и внешние системы общаются с агентами. Это не «API» в программном смысле, а каналы — готовые точки входа/выхода, которые агент получает из конфигурации.
| Канал | Где настраивается | Характер |
|---|---|---|
| Виджет (веб) | server.yaml → widget + встраивание widget.js |
встраиваемый чат на сайте |
| Telegram-бот | agent.yaml → telegram (на агента) |
long-polling, личные чаты |
| VK-бот сообщества | agent.yaml → vk (на агента) |
Long Poll, сообщения сообщества |
| Email (IMAP→SMTP) | agent.yaml → email (на агента) |
входящие письма + ответ |
| HTTP API (SSE) | без конфига | POST /v1/chat/completions (§8) |
| Входящий webhook | server.yaml → inbound |
POST /v1/inbound/:template (§8.8) |
| Sink'и (выход) | notify в cron/email/workflow |
log/webhook/telegram/messages_db/agent/email/workflow (§11) |
19.1 Виджет (веб)
Встраиваемый чат-интерфейс, который общается с агентом через
/v1/chat/completions (SSE) и закрывает сессию через POST /v1/sessions/:id.
Встраивание
На любую страницу сайта:
<script src="http://127.0.0.1:3000/widget.js"></script>
Сервируемые маршруты: /widget (страница), /widget.js (лоадер), /dist/*
(ассеты).
Какой агент открывается
Виджет разрешает модель в таком порядке (последний выигрывает):
widget.default_model(изserver.yaml);window.AGENTOS_MODEL— переменная родительского фрейма;?model=в URL (/widget?model=felix).
Конфигурация в server.yaml:
widget:
default_model: "drom-agent" # агент по умолчанию
Базовый URL виджет берёт из window.AGENTOS_BASE_URL (пусто = тот же origin) —
нужно при хостинге виджета на другом домене.
Готовые демо-страницы
| URL | Что |
|---|---|
/widget?model=felix |
виджет с конкретным агентом |
/demo/overlay |
виджет поверх живых сайтов (вкладки из config/demo.yaml) |
/demo |
демо виджета |
Вкладки /demo/overlay задаются в config/demo.yaml
(tabs: [{label, url, model}], hot-reload'ится на лету).
Визуальные блоки в виджете
Инструменты могут вернуть визуальный слой (графики chart, таблицы table,
текст) — виджет рендерит их inline (Chart.js + таблицы). Формат блоков и
пагинация — общие поля.
19.2 Telegram
Один long-polling бот на шаблон; запускается при старте сервера, если задан
token_env. Токен читается из env (никогда не в YAML).
telegram:
token_env: MY_TG_BOT_TOKEN # имя env с токеном бота
allowed_user_ids: [] # пусто = любой; список = только эти Telegram user id
show_typing: true # индикатор «печатает…» во время работы
show_tool_calls: true # компактные строки статуса tool-вызовов
| Поле | По умолч. | Описание |
|---|---|---|
token_env |
пусто | имя env с токеном; пусто = бот выключен |
allowed_user_ids |
[] |
ограничение отправителей по Telegram user id |
show_typing |
true |
показывать typing-индикатор |
show_tool_calls |
true |
эхо tool-вызовов в чат |
Визуальные блоки на Telegram: график → PNG (sendPhoto), таблица → markdown-строки.
19.3 VK (сообщество)
Бот сообщества на Long Poll API — не нужен публичный HTTPS. Один бот на
шаблон; запускается при старте сервера, если задан token_env. Токен сообщества
читается из env (никогда не в YAML).
vk:
token_env: VK_GROUP_TOKEN # имя env с group access token
group_id: 123456789 # id сообщества (для longpoll и сообщений от имени группы)
allowed_user_ids: [] # пусто = любой; список = только эти VK user id
show_typing: true # индикатор «печатает…» (messages.setActivity)
show_tool_calls: true # эхо tool-вызовов в чат
poll_wait: 25 # wait для longpoll (сек, 1..25)
| Поле | По умолч. | Описание |
|---|---|---|
token_env |
пусто | имя env с токеном; пусто = бот выключен |
group_id |
0 |
id сообщества; 0 = вывести из токена |
allowed_user_ids |
[] |
ограничение отправителей по VK user id |
show_typing |
true |
показывать typing-индикатор |
show_tool_calls |
true |
эхо tool-вызовов в чат |
poll_wait |
25 |
интервал ожидания longpoll-запроса (сек) |
Сессия — vk:{template}:{peer_id} (для беседы peer_id = 2000000000 + chat_id).
Права токена: messages (и photos/docs для загрузки медиа). Визуальные
блоки: график → PNG через photos.getMessagesUploadServer, таблица → текстовые
строки, файл → документ через docs.getMessagesUploadServer.
Настройка сообщества
Чтобы бот получал сообщения, в сообществе нужно сделать две вещи:
- Включить Long Poll API (Управление → API → Long Poll API → «Включён»).
- Включить тип события «Новые сообщения» — по умолчанию VK включает Long
Poll, но все типы событий выключены (
message_new: 0), поэтому бот не получает ничего. В UI — галочка «Новые сообщения» в Long Poll API; или через API:
curl -X POST "https://api.vk.com/method/groups.setLongPollSettings" \
-d "group_id=<id>&access_token=<token>&v=5.199" \
-d "message_new=1&message_reply=1&message_edit=1&message_allow=1&message_deny=1&message_typing_state=1"
Проверить текущие настройки: groups.getLongPollSettings (поле
events.message_new).
19.4 Email
Опрос IMAP-ящика: каждое новое письмо запускает one-shot ход и отвечает по
SMTP. Контекст между письмами — через долгую память (хук memory), ключ —
канонический user id отправителя.
email:
imap_host: imap.example.com
imap_port: 993
imap_username: support@example.com
imap_password_env: EMAIL_PASSWORD # пароль из env, не в YAML
allowed_senders: [] # пусто = любой; "@domain" = весь домен
smtp: # reply-настройки (опусти = только обработка)
host: smtp.example.com
username: support@example.com
password_env: SMTP_PASSWORD
from: support@example.com
notify: [] # доп. sink'и (как у cron)
poll_secs: 60
| Поле | По умолч. | Описание |
|---|---|---|
imap_host |
пусто | IMAP-хост; пусто = канал выключен |
imap_port |
993 |
порт IMAP (implicit TLS) |
imap_username |
пусто | логин (обычно адрес ящика) |
imap_password_env |
пусто | имя env с паролем IMAP |
allowed_senders |
[] |
разрешённые отправители (точный адрес или @домен) |
smtp |
нет | SMTP для ответа: host, username, password_env, from, tls, port |
notify |
[] |
доп. sink'и результата |
poll_secs |
60 |
интервал опроса ящика |
19.5 Программные каналы (указатели)
- Чат по HTTP (SSE) —
POST /v1/chat/completions, поля и события — §8.2. - Входящий webhook —
POST /v1/inbound/:template(синхронный ответ) — §8.8. - Webhook воркфлоу —
POST /v1/workflows/<name>/webhook— §12.5. - Sink'и результата (куда доставить ответ) —
notifyв cron — §11.