AI-автоматизація бронювання столиків та номерів
«Забронювати столик на двох, у п'ятницю ввечері, бажано біля вікна» — стандартний запит, який кнопковий чат-бот обробляє за 5–7 кроків. AI-бронювання столиків та номерів — це автоматизація, яка обробляє природні запити гостей. Наш AI-агент розбирає намір із першого повідомлення, витягує дату, час і вподобання, перевіряє доступність через API ресторану та підтверджує бронювання в одному діалозі. Ми реалізували архітектуру з agentic loop. LLM викликає інструменти та ітеративно уточнює дані.
Гість пише «у суботу ввечері нас буде п'ятеро». Агент нормалізує дату в ISO, парсить час за діапазоном (18:00–22:00), витягує кількість гостей і перевіряє доступність. Без форм, без оператора. Це ключова відмінність від простого чат-бота. Agentic loop дозволяє LLM викликати інструменти — перевірка доступності, створення бронювання, надсилання підтвердження — та ітеративно збирати інформацію через діалог. Промпт включає вилучення сутностей перед викликом інструментів. Це знижує кількість помилок на 83% за даними наших проєктів.
Архітектура AI-агента: agentic loop
from anthropic import Anthropic
from datetime import datetime, timedelta
import json
import re
client = Anthropic()
class BookingAgent:
BOOKING_TOOLS = [
{
"name": "check_table_availability",
"description": "Перевіряє доступність столиків у ресторані",
"input_schema": {
"type": "object",
"properties": {
"date": {"type": "string", "description": "Дата у форматі YYYY-MM-DD"},
"time": {"type": "string", "description": "Час у форматі HH:MM"},
"guests": {"type": "integer", "description": "Кількість гостей"},
"preferences": {
"type": "array",
"items": {"type": "string"},
"description": "Уподобання: window, terrace, private, bar",
},
},
"required": ["date", "time", "guests"],
},
},
{
"name": "check_room_availability",
"description": "Перевіряє доступність номерів у готелі",
"input_schema": {
"type": "object",
"properties": {
"check_in": {"type": "string", "description": "Дата заїзду YYYY-MM-DD"},
"check_out": {"type": "string", "description": "Дата виїзду YYYY-MM-DD"},
"guests": {"type": "integer"},
"room_type": {
"type": "string",
"enum": ["standard", "superior", "deluxe", "suite", "family"],
},
},
"required": ["check_in", "check_out", "guests"],
},
},
{
"name": "create_booking",
"description": "Створює підтверджене бронювання",
"input_schema": {
"type": "object",
"properties": {
"booking_type": {"type": "string", "enum": ["table", "room"]},
"slot_id": {"type": "string", "description": "ID слоту з check_availability"},
"guest_name": {"type": "string"},
"guest_phone": {"type": "string"},
"guest_email": {"type": "string"},
"special_requests": {"type": "string"},
},
"required": ["booking_type", "slot_id", "guest_name", "guest_phone"],
},
},
{
"name": "send_confirmation",
"description": "Надсилає підтвердження бронювання через SMS/email/WhatsApp",
"input_schema": {
"type": "object",
"properties": {
"booking_id": {"type": "string"},
"channel": {"type": "string", "enum": ["sms", "email", "whatsapp"]},
},
"required": ["booking_id", "channel"],
},
},
{
"name": "cancel_booking",
"description": "Скасовує бронювання за номером або іменем гостя",
"input_schema": {
"type": "object",
"properties": {
"booking_id": {"type": "string"},
"guest_phone": {"type": "string"},
},
},
},
]
def __init__(self, booking_backend, notification_service):
self.backend = booking_backend
self.notifier = notification_service
self.sessions: dict[str, dict] = {}
async def _execute_tool(self, tool_name: str, tool_input: dict) -> str:
"""Виконує інструмент і повертає результат"""
try:
if tool_name == "check_table_availability":
slots = await self.backend.get_table_slots(
date=tool_input["date"],
time=tool_input["time"],
guests=tool_input["guests"],
preferences=tool_input.get("preferences", []),
)
if not slots:
alternatives = await self.backend.get_alternative_slots(
date=tool_input["date"],
guests=tool_input["guests"],
time_range=("18:00", "22:00"),
)
return json.dumps({
"available": False,
"alternatives": alternatives[:3],
}, ensure_ascii=False)
return json.dumps({"available": True, "slots": slots[:5]}, ensure_ascii=False)
elif tool_name == "check_room_availability":
rooms = await self.backend.get_available_rooms(
check_in=tool_input["check_in"],
check_out=tool_input["check_out"],
guests=tool_input["guests"],
room_type=tool_input.get("room_type"),
)
return json.dumps({"rooms": rooms[:4]}, ensure_ascii=False)
elif tool_name == "create_booking":
booking = await self.backend.create_booking(**tool_input)
return json.dumps({
"success": True,
"booking_id": booking["id"],
"confirmation_code": booking["code"],
"details": booking["summary"],
}, ensure_ascii=False)
elif tool_name == "send_confirmation":
await self.notifier.send(
booking_id=tool_input["booking_id"],
channel=tool_input["channel"],
)
return '{"sent": true}'
elif tool_name == "cancel_booking":
result = await self.backend.cancel(**tool_input)
return json.dumps(result, ensure_ascii=False)
except Exception as e:
return json.dumps({"error": str(e)})
return '{"error": "unknown tool"}'
async def process_message(self, session_id: str, message: str) -> str:
"""Агентний діалог бронювання"""
session = self.sessions.get(session_id, {"history": [], "context": {}})
system = f"""Ти — агент бронювання. Сьогодні: {datetime.now().strftime('%A, %d %B %Y, %H:%M')}.
Допомагаєш забронювати столик або номер. Збери необхідні дані в діалозі:
- Для столика: дата, час, кількість гостей, уподобання (опціонально), ім'я та телефон
- Для номера: дати заїзду/виїзду, кількість гостей, тип номера (опціонально), ім'я та телефон
Не став усі запитання одразу. З'ясовуй по одній-двох деталях за раз.
Після підтвердження гостем — створи бронювання та надішли підтвердження."""
session["history"].append({"role": "user", "content": message})
messages = session["history"].copy()
while True:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=512,
system=system,
tools=self.BOOKING_TOOLS,
messages=messages,
)
if response.stop_reason == "end_turn":
reply = response.content[0].text
session["history"].append({"role": "assistant", "content": reply})
self.sessions[session_id] = session
return reply
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = await self._execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
Як agentic loop прискорює бронювання?
Кнопковий чат-бот вимагає 7 натискань для бронювання столика (вибір дати, часу, кількості гостей, уподобань, підтвердження). AI-агент обробляє запит у 3 рази швидше. Середній час бронювання — 90 секунд проти 5 хвилин по телефону. Помилки в датах знижуються на 83%, а відсоток no-show падає з 18% до 9% завдяки автоматичним нагадуванням. Порівняння методів бронювання наведено в таблиці.
| Параметр | Телефон | Кнопковий чат-бот | AI-агент |
|---|---|---|---|
| Середній час бронювання | 3–5 хв | 2 хв | 90 сек |
| Помилки при бронюванні | ~15% | ~8% | ~2% |
| No-show | 18% | 15% | 9% |
| Операційні витрати | Високі | Середні | Низькі |
Які проблеми вирішує AI-агент?
Основний біль — неструктуровані запити гостей. Чат-бот на кнопках вимагає багатьох кроків, а оператори не встигають обробляти пікові навантаження. AI-агент вирішує обидві проблеми: парсить природну мову та масштабується до тисяч запитів на хвилину. Додатково знижується відсоток no-show завдяки автоматичним нагадуванням.
Інтеграція з системами бронювання
Приклад бекенду для ресторану через iiko API:
import aiohttp
class IikoBokingBackend:
def __init__(self, api_url: str, api_key: str):
self.api_url = api_url
self.headers = {"Authorization": f"Bearer {api_key}"}
async def get_table_slots(self, date: str, time: str, guests: int, preferences: list) -> list:
async with aiohttp.ClientSession() as session:
async with session.post(
f"{self.api_url}/api/0/reserve/available_tables",
headers=self.headers,
json={
"restaurantId": self.restaurant_id,
"datetime": f"{date}T{time}:00",
"numberOfPersons": guests,
}
) as resp:
data = await resp.json()
tables = data.get("reserveTables", [])
if "window" in preferences:
tables = [t for t in tables if t.get("tags", {}).get("window")]
if "terrace" in preferences:
tables = [t for t in tables if "терраса" in t.get("name", "").lower()]
return [
{
"slot_id": t["id"],
"table_name": t["name"],
"capacity": t["capacity"],
"tags": t.get("tags", {}),
}
for t in tables
]
async def create_booking(self, booking_type: str, slot_id: str,
guest_name: str, guest_phone: str,
guest_email: str = None, special_requests: str = None) -> dict:
async with aiohttp.ClientSession() as session:
async with session.post(
f"{self.api_url}/api/0/reserve/add_reserve",
headers=self.headers,
json={
"tableId": slot_id,
"guestName": guest_name,
"phone": guest_phone,
"email": guest_email,
"comment": special_requests,
"source": "ai_bot",
}
) as resp:
result = await resp.json()
return {
"id": result["reserveId"],
"code": result.get("reserveCode", result["reserveId"][:6].upper()),
"summary": f"Столик {result.get('tableName', slot_id)}, {guest_name}",
}
Практичний кейс: мережа ресторанів, 4 заклади
Цифри до впровадження: 35–40% бронювань через телефон, 25–30 хвилин роботи хостес у пік, черга з дзвінків.
Після впровадження нашого агента:
- WhatsApp-бот через 360dialog + Telegram-бот
- Інтеграція з iiko для всіх 4 закладів
- SMS-підтвердження через SMS.ru
Результати з нашої практики:
- 68% бронювань переведено в автоматичний режим
- Час створення бронювання: з 3–5 хв (телефон) до 90 сек (бот)
- Помилки бронювання (неправильне ім'я, дата): знижено на 83%
- Нагадування за 2 години → no-show знизився з 18% до 9%
- Економія на операційних витратах: скорочення витрат на персонал до 40%
Проблема: гості пишуть неструктуровано. Рішення — промпт із вилученням сутностей перед викликом інструментів.
Канали зв'язку та їх пропускна здатність
| Канал | Час обробки повідомлення | Пропускна здатність у пік |
|---|---|---|
| WhatsApp Business API | 1–2 сек | 500 повідомлень/хв |
| Telegram Bot | 0.5–1 сек | 1000 повідомлень/хв |
| SMS-шлюз | 3–5 сек | 100 повідомлень/хв |
| Віджет на сайті | 1–2 сек | 300 повідомлень/хв |
Що входить у нашу роботу
Повний перелік етапів
- Аналіз поточних процесів бронювання (аудит дзвінків, вибір точок інтеграції)
- Проектування AI-агента: вибір LLM, налаштування tool-use, промпт-інжиніринг
- Інтеграція з POS/CRM (iiko, r-keeper, 1C) — гарантуємо сумісність через REST API
- Налаштування каналів: WhatsApp Business API, Telegram Bot, віджет на сайт
- Розробка системи сповіщень (нагадування, підтвердження, скасування)
- Тестування на реальних бронюваннях, A/B-тест
- Запуск і моніторинг протягом 2 тижнів після старту
Як впровадити AI-агента: покроковий план
- Аудит — аналізуємо поточні бронювання, виявляємо больові точки
- Проектування — визначаємо архітектуру, обираємо LLM та інструменти
- Інтеграція — підключаємо API ресторану/готелю та канали зв'язку
- Навчання — налаштовуємо промпти на історичних даних (few-shot)
- A/B тест — запускаємо агента паралельно з операторами, порівнюємо метрики
- Запуск — переводимо 100% потоку на агента з моніторингом
Терміни
- Агент бронювання (діалог + логіка): 1 тиждень
- Інтеграція з iiko / r-keeper / 1C: 1–2 тижні
- WhatsApp / Telegram канали: 3–5 днів
- SMS/email підтвердження + нагадування: 3–5 днів
- Повна система для мережі закладів: 4–6 тижнів
Як ми гарантуємо якість?
Кожне бронювання проходить валідацію на стороні бекенду: перевірка наявності місць, запобігання подвійним бронюванням, підтвердження через SMS. Наш досвід роботи з ресторанними мережами (понад 10 проєктів) дозволяє мінімізувати ризики. Хочете аналогічний результат? Отримайте консультацію. Замовте аудит поточних процесів бронювання та дізнайтеся, як AI-агент скоротить ваші витрати.







