Перейти к содержанию

События и автоматизация

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

Как это устроено

Внешняя система ──▶ POST /api/v2/events ──▶ Router ──▶ сессия агента
                                              │
                       привязки / правила / auto-bind / режим по умолчанию
  1. Приём. Внешняя система отправляет нормализованное событие на POST /api/v2/events.
  2. Маршрутизация. Ядро решает, куда направить событие: сначала — явная привязка источника, затем — правила маршрутизации, затем — запасной режим (авто-привязка чата или поведение по умолчанию). Каждое решение попадает в журнал.
  3. Ответ. Сессия получает событие как сообщение и отвечает обычным образом; ответ можно вернуть внешней системе (например, отправить в чат — см. Интеграция с Telegram).

Приём события

Событие отправляется обычным аутентифицированным запросом:

curl -X POST http://localhost:5000/api/v2/events \
  -H 'Authorization: Bearer <api-key>' \
  -H 'Content-Type: application/json' \
  -d '{"source":"billing","type":"invoice_paid","payload":{"id":"INV-1"},"dedupKey":"inv-1-paid"}'

В ответ приходит 201 с телом {event, decision, sessionId}: нормализованное событие, принятое решение и id сессии (null, если событие отброшено).

  • source — источник события; type — его тип; payload — произвольные данные.
  • identity — кто отправил (principalId, chatKey, threadKey, roles) — используется для маршрутизации и прав.
  • dedupKey и ts опциональны; без dedupKey повторы отсекаются по источнику, типу и содержимому.

Мастер-выключатель

Приём событий можно полностью отключить (events.enabled: false): тогда POST /api/v2/events отвечает 503.

Привязки: источник → сессия

Привязка закрепляет источник, чат или тред за сессией. Если событие приходит из известного источника, оно идёт прямо в его сессию, без создания новых.

Режим Поведение
bound Событие всегда идёт в постоянную сессию привязки
ephemeral Под событие создаётся временная сессия; она живёт ограниченное время и архивируется
queue Событие ставится в очередь уже существующей сессии

Привязки создаются и удаляются в разделе «События» (создание — роли LEAD и ADMIN) или через API (/api/v2/events/bindings).

API-ключи привязок

Внешнему отправителю (шлюзу мессенджера и т. п.) можно выдать API-ключ привязки — секрет вида synth_evt_…. С таким ключом событие отправляется без пользовательских учётных данных, а источник и чат берутся из самой привязки.

  • Метка label обязательна и уникальна по инстансу; можно задать описание, срок действия и лимит запросов в минуту.
  • Секрет показывается один раз при создании; в списке виден только префикс.
  • Ключ можно отозвать; при удалении привязки её ключи удаляются каскадно.
  • При превышении лимита сервер отвечает 429.

Правила маршрутизации

Когда явной привязки нет, в дело вступают правила маршрутизации. Правило сопоставляет событие по источнику, типу, чату, треду, отправителю, метке или ключевым словам и задаёт цель — привязать к сессии, создать временную сессию или закрепить чат за новой сессией.

  • Правила упорядочены по приоритету; более приоритетное срабатывает первым.
  • Правило можно включить или отключить, не удаляя.
  • Авто-привязка (events.autoBind): если у события есть чат или тред, платформа при отсутствии правила сама закрепляет его за новой сессией.

Запасной режим, когда не подошло ни одно правило:

events.defaultMode Поведение
bound Событие отбрасывается как «без маршрута»
ephemeral Создаётся временная сессия

Журнал решений

Каждое решение Router фиксируется в журнале: GET /api/v2/events/journal (параметр limit). В интерфейсе журнал виден в разделе «События» и дублируется в «Логи и аудит». Использование API-ключа привязки отмечается идентификатором ключа.

Идентичности и подтверждение (claim-flow)

Внешний отправитель может быть сопоставлен с профилем Synth — тогда его сессии видны ему в интерфейсе, а права берутся из профиля. Если отправитель неизвестен, в ответе на приём события приходит одноразовый код подтверждения (identityHint). Пользователь вводит код, подтверждая владение идентичностью, — и внешняя привязка появляется в его профиле.

  • Свои идентичности можно посмотреть и отвязать: GET / DELETE /api/v2/me/identities.
  • Подтверждение по коду: POST /api/v2/me/identities/claim.
  • Код одноразовый и ограничен по времени.

Код — только в приватном канале

Код подтверждения имеет смысл передавать лично (в приватный чат), а не в общий: кто получил код, тот может привязать идентичность.

Права внешних отправителей

Сопоставленный с профилем отправитель действует с правами своего профиля. Роль, пришедшая из внешнего источника, может эти права только сузить, но не расширить. Несопознанный отправитель прав Synth не получает — доступно лишь «транспортное» участие (сессия и чат).

Права определяют доступность эндпоинтов; внутри сессии набор инструментов одинаков для всех и задаётся режимом, агентом, MCP и скиллами.

Настройка

Раздел «События» (просмотр доступен всем ролям, создание — LEAD/ADMIN) содержит привязки, ключи и журнал. Глобальные параметры — в админ-секции «Параметры событий»:

Параметр Назначение
enabled Приём событий включён или выключен
defaultMode Поведение без маршрута: bound или ephemeral
ephemeralTtl Время жизни временной сессии (например, 24h)
journalRetentionDays Срок хранения журнала решений
allowedSources Список разрешённых источников (пусто — все)
unknownAgentTemplate Что делать при неизвестном шаблоне агента: drop или default-agent
keyRateLimitPerMinute Лимит запросов для ключей привязок по умолчанию
decisionRouting Включать decision-маршрутизацию событий
autoBind / autoBindAgentTemplate Авто-привязка чата/треда и агент для неё
identityMap Ручное сопоставление внешних идентификаторов с пользователями

Тот же набор доступен через GET/PUT/DELETE /api/v2/settings/events — изменения применяются без перезапуска.

Что дальше