External Agent доступен на тарифных планах YCloud Pro и выше.
Перед началом работы
Подготовьте:- Публично доступную конечную точку HTTPS, принимающую запросы JSON
POST. - Сервис, который проверяет подписи Webhook, сохраняет события, предотвращает дублирование обработки и запускает вашего ИИ-агента.
- Стандартный API-ключ аккаунта YCloud, хранящийся на вашем сервере. Ключи API приложений разработчика (Developer App) не поддерживаются этими конечными точками Inbox.
- Бизнес-номер WhatsApp, подключенный к YCloud, а также команду операторов или отдельного сотрудника для перевода обращений.
https://api.ycloud.com в качестве базового URL API.
Подключение агента
1. Создайте External Agent
- В консоли YCloud перейдите в раздел AI Agent > AI Agent.
- Выберите Create Agent > External Agent.
- Укажите Name и ваш Webhook URL, например
https://agent.example.com/webhooks/ycloud. - Нажмите Save.
- Скопируйте сгенерированный Bot ID из параметров агента. Используйте это значение как
botIdв запросах к API; передавать идентификатор из вашей собственной ИИ-системы не требуется.

Create an External Agent with a name and a webhook URL. This example shows the form before saving.
X-API-Key аутентифицирует ваши исходящие REST-запросы. Bot ID является идентификатором, а не учетными данными.
2. Назначьте номер WhatsApp
Перейдите в WhatsApp Manager > WhatsApp accounts, откройте настройки бизнес-номера и выберите Inbox > Assignment. В блоке Priority 3 Assign to выберите AI Agent, а затем укажите своего агента в разделе External Agent списка агентов. Проверьте приоритет правил: назначение ответственному за клиента сотруднику или последнему обрабатывавшему оператору может иметь более высокий приоритет. См. Conversation assignment rules. Один External Agent может обрабатывать несколько номеров. Каждый номер связывается только с одним ботом одновременно. Управлять этими связями можно в настройках назначения номера.3. Обработайте диалог
- Клиент отправляет сообщение в WhatsApp на ваш бизнес-номер.
- YCloud открывает или продолжает диалог в Inbox и применяет правила назначения для этого номера.
- Когда ваш External Agent обрабатывает диалог, YCloud отправляет соответствующие события Webhook на его конечную точку.
- Ваш сервис проверяет и сохраняет событие, возвращает
2xxи обрабатывает входящие данные от клиента асинхронно. - Ваш сервис вызывает API Inbox для отправки ответа, перевода диалога или его закрытия.
- Ваш сервис отслеживает статус доставки с помощью
whatsapp.message.updated.
Идентификаторы и их назначение
Идентификаторы представляют собой строки. Метки времени используют формат UTC RFC 3339. Используйте
dialogId, а не conversationId, в путях API для диалогов.
Получение событий Webhook
Все четыре типа событий поступают на один и тот же webhook URL. Каждая специальная доставка External Agent включаетid, type, apiVersion, createTime и externalBotContext, а также соответствующий бизнес-объект.
Проверка, сохранение и подтверждение
Проверяйте заголовокYCloud-Signature с помощью секретного ключа подписи эндпоинта и необработанного тела HTTP-запроса перед парсингом JSON. Формат подписи:
2xx. Выполняйте инференс ИИ и другие ресурсоемкие операции асинхронно. Ответы, отличные от 2xx, и таймауты могут приводить к ограниченному количеству повторных попыток.
Выполняйте дедупликацию по (botId, event.id) в рамках вашего аккаунта YCloud. Изменение назначения может отправлять уведомления как исходящему, так и входящему агентам; использование только глобального ID события может привести к отбрасыванию уведомления для одного из агентов. Сохраняйте состояние обработки, чтобы повторное событие не вызвало отправку второго ответа.
Пример: сообщение клиента
inboxMessage.inbound. События создания исходящих сообщений используют вместо этого inboxMessage.outbound. Сохраняйте неизвестные типы сообщений и поля для совместимости, а не обрабатывайте их как текст.
Решение об ответе
externalBotContext — это снимок состояния, сделанный в момент формирования уведомления. Поле botId определяет бота-получателя; assignee определяет фактического обработчика в этом снимке. После передачи диалога эти значения могут различаться.
Значение actionable=true означает, что в этот момент бот-получатель обрабатывал открытый диалог. Оно также может быть true в событии создания исходящего сообщения или в отчете о доставке.
События могут приходить неоднократно или в нарушенном порядке. Поле очередности событий отсутствует. Группируйте задачи по dialogId и избегайте повторной обработки одних и тех же входящих данных клиента. Событие первоначального назначения не должно отдельно вызывать второй ответ на первое сообщение клиента.
Что происходит после передачи диалога или его закрытия?
Новые сообщения клиентов и ответы операторов больше не доставляются предыдущему External Agent, как только диалог переходит к человеку, попадает в очередь, остается без исполнителя или закрывается. Предыдущий агент по-прежнему получает соответствующее уведомление о передаче диалога или его закрытии. Уведомления о создании сообщений и отчеты о доставке для сообщений, которые он уже отправил, остаются связанными с этим агентом-отправителем даже после передачи диалога или смены привязки номера. Ранее созданные уведомления могут поступать с опозданием. Отменяйте ожидающие задачи при смене ответственного или закрытии диалога и не возобновляйте их только потому, что у старого события указаноactionable=true.
Обычные эндпоинты webhook сохраняют существующее поведение подписки и формат полезной нагрузки. Специальная доставка External Agent добавляет поле externalBotContext; не требуйте наличия этого поля при обычных доставках whatsapp.message.updated.
Использование Inbox API
ПередавайтеX-API-Key в каждом запросе и Content-Type: application/json в запросах POST. Во всех приведенных ниже примерах используются плейсхолдеры идентификаторов. Замените их значениями вашего агента и полученных событий.
Успешные ответы возвращают бизнес-объект напрямую, без оболочки
data. Операции записи проверяют, открыт ли диалог и обрабатывается ли он указанным ботом в данный момент. YCloud определяет отправителя и клиента по диалогу; не передавайте tenantId, from, to, recipient, operatorId или source для их переопределения.
Получение текущего диалога
status, assignee и canAct. Поле bot может указывать на последнего связанного внешнего бота и не является подтверждением текущего владения диалогом. canAct отражает разрешения запрашиваемого бота на момент запроса; последующая запись все равно выполняет свои собственные проверки.
Получение истории переписки
items и nextCursor. Каждый элемент включает сообщение Inbox id, direction, type, content и createTime. Для текстового сообщения прочитайте content.text.body.
История включает видимые клиенту сообщения из той же переписки, возможно, из предыдущих диалогов. Собственное значение dialogId сообщения может отличаться от запрашиваемого диалога или отсутствовать в более старой истории. Внутренние заметки, приватные сводки передачи диалога и внутренние системные сообщения исключаются.
Сообщения возвращаются по возрастанию ID сообщения, от более старых к более новым. Опустите after в первом запросе; передавайте nextCursor без изменений в качестве after в последующих запросах, пока оно не станет null. Значение limit по умолчанию равно 50, допустимый диапазон — от 1 до 100. Список целей для передачи диалога использует ту же схему пагинации.
Отправка ответа
botId и message обязательны. sourceEventId и replyToMessageId необязательны. Ссылка на ответ представляет собой ID сообщения Inbox, например inboxMessage.id; она не является wamid.
status, даже когда HTTP возвращает 200. accepted означает, что сообщение поступило в конвейер отправки, а не то, что оно дошло до клиента. Ответ 200 также может содержать failed; поле channelMessageId может быть еще недоступно.
Используйте whatsapp.message.updated для отслеживания последующих состояний, включая sent, delivered, read, failed, expired или deleted. Сопоставляйте externalBotContext.inboxMessageId в квитанции с inboxMessageId из ответа на отправку. Проверяйте whatsappMessage.errorCode и errorMessage на предмет ошибок.
Типы сообщений
Объектmessage использует стандартную модель сообщений WhatsApp: type плюс соответствующее поле с контентом. Примеры включают text, image, video, audio, document, sticker, location, contacts, interactive, template и reaction. Существующие требования WhatsApp к отправке сообщений и шаблонам по-прежнему действуют.
Например, замените объект message на:
id, либо link. Сведения о структуре тела сообщения см. в разделе Отправка сообщения WhatsApp. Отправляйте ответ через указанный выше эндпоинт Inbox, чтобы он использовал проверки обработчика диалога и контекст Inbox. Не передавайте и не полагайтесь на filterUnsubscribed или filterBlocked в этом запросе на отправку сообщения Inbox.
Ответы клиентов могут содержать interactive.button_reply, interactive.list_reply, interactive.nfm_reply или button. Поле response_json в ответе Flow является строкой JSON. Входящий тип button не является исходящим типом сообщения для этого эндпоинта.
Передача диалога человеку
Сначала запросите список доступных команд или операторов для бизнес-номера диалога:type=agent, чтобы вместо этого получить список участников. Каждый возвращенный целевой объект предоставляет id и type для запроса на передачу диалога. Необязательное поле online оператора отражает статус присутствия; оно не гарантирует немедленного назначения.
target с type (team или agent) и id. Запасного варианта передачи человеку по умолчанию нет. Необязательное поле reason поддерживает до 256 символов; необязательное поле summary поддерживает до 4 000 символов и не отображается в видимой клиенту истории сообщений.
Ответ содержит outcome и обновленный dialog. Возможные результаты: assigned, queued, team_unassigned или unassigned. Проверяйте фактический результат, а не предполагайте, что человек принял диалог.
При передаче сохраняется тот же dialogId. Как только ваш агент теряет владение, прекратите отвечать или пытаться закрыть этот диалог.
Закрытие решенного диалога
dialog с status=closed и canAct=false. Ваш агент не может продолжать отправку сообщений или передачу этого закрытого диалога. Последующее валидное сообщение от клиента начинает новый диалог и повторно запускает правила распределения для этого номера.
Обработка ошибок и повторные попытки
В ответах с ошибками используется объектerror с status, code, message и requestId. Сохраняйте ID запроса при обращении в службу поддержки YCloud.
Отслеживайте ошибки Webhook в разделе View delivery logs . Сохраняйте идентификаторы событий, диалогов, сообщений, запросов и результаты обработки. Количество повторных попыток отправки Webhook ограничено, поэтому при необходимости используйте запросы диалогов и истории для восстановления контекста.
Часто задаваемые вопросы
Можно ли подключить агента, созданного на базе моего собственного ИИ-фреймворка?
Да. Ваш сервис должен принимать и верифицировать вебхуки YCloud, а также вызывать REST API Inbox. Вы сами определяете, как ваш сервис генерирует ответы, обращается к базе знаний и вызывает собственные инструменты.Будет ли мой агент получать все переписки Inbox?
Нет. Его выделенный эндпоинт получает события только в рамках назначенной ему зоны ответственности, а также соответствующие уведомления о назначении и закрытии и отчеты о доставке для отправленных им сообщений. Новые сообщения после передачи диалога человеку не пересылаются предыдущему агенту. Ранее сгенерированные события могут приходить с задержкой.Может ли мой агент использовать сообщения из предыдущих диалогов?
Да. Эндпоинт истории возвращает видимую клиенту историю переписки, включая более ранние диалоги. Используйте собственное значениеdialogId каждого сообщения, если оно доступно; не предполагайте, что каждое возвращенное сообщение относится к текущей сессии обслуживания.
Что произойдет, если я сменю агента, назначенного на номер?
Открытые диалоги, которые в данный момент обрабатываются ботом, асинхронно переназначаются в соответствии с правилами маршрутизации номера. Сменяемый агент получаетassignmentRole=outgoing и должен прекратить работу. Новый агент получает reason=phone_binding_changed со значением assignmentRole=incoming; он должен запросить текущий диалог и историю, прежде чем продолжить.
Идентификатор диалога и история остаются неизменными. Диалоги, которые в данный момент обрабатываются оператором-человеком, не передаются новому боту при таком переназначении номера. После того как другой бот заменит его, прежний бот больше не сможет запрашивать этот диалог через данные эндпоинты.
Становится ли ответ моего вебхука ответом клиенту?
Нет. Верните2xx, чтобы подтвердить получение события, а затем отправьте ответ клиенту через POST /v2/inbox/dialogs/{dialogId}/messages.
Почему мой агент получает actionable=true для своего собственного ответа?
Это поле описывает, кто вел открытый диалог в момент генерации события. Поэтому события создания исходящих сообщений и отчеты о доставке могут содержать actionable=true. Запускайте стандартный ответ ИИ только для входящего события inbox.message.created и учитывайте изменения владельца активного диалога.
