API для ИИ-агентов
Подключите ИИ-агента Agent Rails к конструктору ботов, CRM или своему сервису. Ваша система отправляет вопрос клиента и получает готовый ответ агента.
Агент настраивается в кабинете Agent Rails, как обычно: инструкция, база знаний, функции, рабочие часы, корректор. Через API передаются только сообщения. Каждый ответ ИИ списывает одно сообщение с баланса, так же как в любом другом канале.
reply и доставляет клиентуБазовый адрес
Все запросы и ответы в формате JSON (UTF-8). Диалоги из API видны в разделе «Диалоги» кабинета с меткой API.
Быстрый старт
- В кабинете откройте Интеграции → API для агентов и нажмите «Создать ключ». Ключ показывается один раз, сохраните его.
- На той же странице включите API для нужного агента и скопируйте его ID.
- Отправьте первое сообщение:
curl -X POST 'https://agent-rails.ru/api/public/v1/agents/AGENT_ID/messages' \
-H 'Authorization: Bearer ВАШ_API_КЛЮЧ' \
-H 'Content-Type: application/json' \
-d '{"user":{"id":"user_123456","name":"Анна"},"message":"Сколько стоит доставка?"}'
const res = await fetch('https://agent-rails.ru/api/public/v1/agents/AGENT_ID/messages', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.AGENT_RAILS_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({ user: { id: 'user_123456', name: 'Анна' }, message: 'Сколько стоит доставка?' }),
})
const data = await res.json()
console.log(data.status, data.reply)
import os, requests
resp = requests.post(
"https://agent-rails.ru/api/public/v1/agents/AGENT_ID/messages",
headers={"Authorization": f"Bearer {os.environ['AGENT_RAILS_API_KEY']}"},
json={"user": {"id": "user_123456", "name": "Анна"}, "message": "Сколько стоит доставка?"},
timeout=60,
)
data = resp.json()
print(data["status"], data["reply"])
Ответ:
{
"status": "completed",
"reply": "Здравствуйте, Анна! Доставка по городу стоит 300 ₽, привезём завтра.",
"reply_id": "f639f508-3c3e-4e71-b9cc-2041a0e877a0",
"message_id": "850f0ad7-a3d3-4d77-a6e1-05e502b056fd",
"seq": 1288,
"conversation_id": "19008257-f70e-42d4-a0ec-7eb9880c600f",
"reason": ""
}
Аутентификация
Передайте ключ в одном из заголовков, какой удобнее вашей системе:
Authorization: Bearer ar_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # или X-Api-Key: ar_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Ключ принадлежит аккаунту и работает только с агентами этого аккаунта, у которых включён доступ по API. У аккаунта может быть до 10 активных ключей. Отозванный ключ перестаёт работать сразу.
Вызывайте API с сервера или из конструктора ботов. Не размещайте ключ в коде сайта или мобильного приложения: любой, кто его увидит, сможет тратить ваши сообщения. Если ключ попал в чужие руки, отзовите его в кабинете.
Отправить сообщение
Сохраняет сообщение клиента в диалоге и возвращает ответ агента. Диалог определяется парой «агент + user.id», поэтому агент помнит всю переписку с клиентом.
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
user.idобязательно | string | Постоянный ID клиента в вашей системе. 1–128 символов: латиница, цифры, _ . : @ -. |
user.name | string | Имя клиента, до 100 символов. Агент сможет обращаться по имени; имя видно в «Диалогах». |
messageобязательно | string | Текст клиента, до 32 000 символов. |
context | string | Что уже известно о клиенте, например «Выбрал: тариф Стандарт, самовывоз». До 8 000 символов. Передаётся агенту, когда меняется. |
metadata | object | До 20 пар «ключ: строка» (например, UTM-метки). Видны оператору в карточке диалога, агенту не передаются. Ключ: 1–64 символа, латиница, цифры, _ . -, не начинается с «_». Значение до 512 символов. |
timeout_seconds | integer | Сколько ждать ответ в рамках запроса: 1–55 секунд, по умолчанию 25. Не успел — придёт pending. |
idempotency_key | string | Ключ безопасного повтора, 1–128 символов. Можно передать заголовком Idempotency-Key. См. Повторы запросов. |
Ответ
Всегда код 200 и плоский JSON: все поля присутствуют всегда, удобно сохранять их в переменные.
| Поле | Тип | Описание |
|---|---|---|
status | string | completed, pending, merged или no_reply. См. Статусы. |
reply | string | Текст ответа агента. Заполнен только при completed. |
reply_id | string | ID ответа агента. |
message_id | string | ID сохранённого сообщения клиента. Нужен, чтобы получить отложенный ответ. |
seq | integer | Порядковый номер сообщения клиента в истории. |
conversation_id | string | ID диалога в Agent Rails. |
reason | string | Причина при no_reply, иначе пустая строка. |
Пример с контекстом
{
"user": { "id": "user_123456", "name": "Анна" },
"message": "А можно забрать заказ сегодня?",
"context": "Выбрала в меню: самовывоз",
"metadata": { "utm_source": "newsletter", "utm_campaign": "autumn" },
"timeout_seconds": 25,
"idempotency_key": "msg-000123"
}
Получить отложенный ответ
Если пришёл pending, запросите ответ через 5–15 секунд по message_id. Формат ответа такой же, как у отправки сообщения. Запрос ничего не генерирует и не списывает сообщения, его можно повторять.
Обычно ответ готов за 5–30 секунд. Если модель временно недоступна, агент сам повторит попытку через 5 и 15 минут, а статус всё это время будет pending.
История диалога
| Параметр | Тип | Описание |
|---|---|---|
after_seq | integer | Вернуть сообщения после этого номера. По умолчанию 0 (с начала). |
limit | integer | От 1 до 200, по умолчанию 50. |
{
"conversation_id": "19008257-f70e-42d4-a0ec-7eb9880c600f",
"messages": [
{ "seq": 1288, "id": "850f0ad7-…", "role": "user", "text": "Сколько стоит доставка?", "is_manual": false, "created_at": "2026-09-25T09:12:04Z" },
{ "seq": 1289, "id": "f639f508-…", "role": "assistant", "text": "Здравствуйте, Анна! Доставка по городу стоит 300 ₽…", "is_manual": false, "created_at": "2026-09-25T09:12:08Z" }
],
"next_after_seq": 1289
}
Передайте next_after_seq в after_seq, чтобы получать только новые сообщения.
Список агентов
Агенты аккаунта с включённым доступом по API. Удобно для проверки ключа.
{ "agents": [ { "id": "2b34cd48-5898-4308-9890-6e67fd0d01b9", "name": "Консультант" } ] }
Статусы и причины
Поле status
| status | Что делать |
|---|---|
completed | Отправьте клиенту текст из reply. |
pending | Ответ ещё готовится. Запросите его позже. |
merged | Клиент прислал несколько сообщений подряд, и агент ответил на них одним ответом в другом запросе. Ничего не отправляйте, иначе клиент получит ответ дважды. |
no_reply | Агент не отвечает; сообщение клиента сохранено. Причина в reason. |
Поле reason
| reason | Значение |
|---|---|
paused | Оператор остановил ИИ в этом диалоге. Возобновить можно кнопкой «Возобновить ИИ» в «Диалогах». |
stopped | Диалог остановлен оператором или функцией остановки диалога. |
off_hours | Сейчас вне рабочих часов агента. |
agent_inactive | Агент выключен. |
insufficient_balance | На балансе закончились сообщения. |
unavailable | Агент не смог ответить. Повторите позже с тем же idempotency_key. |
not_answered | Только для отложенного ответа: ответа нет и не будет. |
Диалоги и контекст
- Один клиент = один диалог. Все сообщения с одинаковым
user.idпопадают в один диалог агента, и агент видит историю. - Имя и контекст передаются агенту только при изменении, поэтому их можно отправлять в каждом запросе.
- Метаданные видит только оператор (например, чтобы понимать источник клиента). Агенту они не передаются.
- Оператор может остановить ИИ в любом диалоге. Пока ИИ остановлен, запросы получают
no_reply/paused. Писать клиенту из кабинета в API-диалог нельзя: ответы клиенту доставляет ваша система. - Буферизация сообщений агента в API не применяется: каждое сообщение обрабатывается сразу.
Повторы запросов
Соединение может оборваться, когда агент уже отвечает. Чтобы повтор не создал второе сообщение и не списал сообщение дважды, передавайте уникальный idempotency_key для каждого сообщения клиента, например его ID в вашей системе.
- Повтор с тем же ключом и тем же телом возвращает результат исходного запроса: дожидается идущего ответа, возвращает готовый или повторяет неотвеченное сообщение.
- Тот же ключ с другим телом вернёт ошибку
idempotency_key_reused. - Ключ действует 24 часа.
Ошибки
Ошибки запроса возвращаются с кодом 4xx/5xx:
{ "error": { "code": "unauthorized", "message": "Неверный или отозванный API-ключ." } }
| HTTP | code | Причина |
|---|---|---|
| 400 | validation_error | Неверное тело или параметры запроса; подробности в message. |
| 401 | unauthorized | Ключ не передан, неверен или отозван. |
| 403 | plan_required | API недоступно на тарифе аккаунта. |
| 404 | agent_not_found | Агента нет в аккаунте, или для него выключен доступ по API. |
| 404 | message_not_found | Сообщение не найдено у этого агента. |
| 422 | idempotency_key_reused | Ключ повтора уже использован с другим телом. |
| 429 | rate_limited | Слишком много запросов; повторите через Retry-After секунд. |
| 429 | busy | Слишком много одновременных ответов. Ничего не сохранено; повторите через Retry-After. |
| 5xx | internal_error, unavailable | Временная ошибка. Повторите с тем же idempotency_key. |
Лимиты
| Лимит | Значение |
|---|---|
| Запросы на ключ | 10 в секунду, кратковременно до 30 |
| Одновременные ответы | до 10 на аккаунт |
| Размер тела запроса | до 1 МБ |
| Ожидание ответа в запросе | до 55 секунд (timeout_seconds) |
| Активные ключи | до 10 на аккаунт |
Подключение конструктора ботов
Сценарий: воронку ведёт конструктор ботов (кнопки, сбор данных), а ИИ-агент отвечает, когда клиент пишет вопрос текстом. Отдельно включать и выключать агента не нужно: он отвечает только на те сообщения, которые передаёт конструктор.
Шаги
- В кабинете создайте API-ключ и включите API для агента. Загрузите базу знаний. Если заявки в CRM создаёт сам конструктор, отключите у агента функции создания лида.
- В сценарии конструктора сохраните текст клиента в переменную.
- Добавьте блок HTTP-запроса: метод
POST, адресhttps://agent-rails.ru/api/public/v1/agents/AGENT_ID/messages, заголовкиAuthorization: Bearer ВАШ_API_КЛЮЧиContent-Type: application/json. - В тело подставьте переменные конструктора: ID пользователя в
user.id, имя вuser.name, текст вmessage, выбор из меню вcontext, UTM-метки вmetadata. - Сохраните ответ в переменную. Если
statusравенcompleted, отправьте клиенту значениеreply. - Если
statusравенpending, сделайте паузу 10–15 секунд и запроситеGET …/messages/{message_id}/reply. Приmergedиno_replyничего не отправляйте или передайте клиента менеджеру.
Ставьте timeout_seconds меньше таймаута HTTP-запроса в конструкторе. Тогда вместо обрыва соединения вы получите pending и заберёте ответ позже.
Примеры кода
Отправка с повтором и ожиданием отложенного ответа
const BASE = 'https://agent-rails.ru/api/public/v1'
const headers = { Authorization: 'Bearer ' + process.env.AGENT_RAILS_API_KEY, 'Content-Type': 'application/json' }
async function ask(agentId, userId, text, messageKey) {
const res = await fetch(`${BASE}/agents/${agentId}/messages`, {
method: 'POST',
headers: { ...headers, 'Idempotency-Key': messageKey },
body: JSON.stringify({ user: { id: userId }, message: text }),
})
let data = await res.json()
for (let i = 0; data.status === 'pending' && i < 6; i++) {
await new Promise((r) => setTimeout(r, 10000))
data = await (await fetch(`${BASE}/agents/${agentId}/messages/${data.message_id}/reply`, { headers })).json()
}
return data.status === 'completed' ? data.reply : null // null: ничего не отправлять
}
import os, time, requests
BASE = "https://agent-rails.ru/api/public/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['AGENT_RAILS_API_KEY']}"}
def ask(agent_id, user_id, text, message_key):
data = requests.post(
f"{BASE}/agents/{agent_id}/messages",
headers={**HEADERS, "Idempotency-Key": message_key},
json={"user": {"id": user_id}, "message": text},
timeout=60,
).json()
for _ in range(6):
if data["status"] != "pending":
break
time.sleep(10)
data = requests.get(f"{BASE}/agents/{agent_id}/messages/{data['message_id']}/reply", headers=HEADERS, timeout=30).json()
return data["reply"] if data["status"] == "completed" else None # None: ничего не отправлять
OpenAPI
Машиночитаемое описание API в формате OpenAPI 3.1: openapi.json. Его можно импортировать в Postman, Insomnia или генератор клиентов.
Вопросы по подключению: support@agent-rails.ru.