Библиотека · Поддержка клиентов и голосовые агенты

Голосовые AI-агенты — Vapi, Retell, Bland.ai, реальные звонки

Строитель65 минОбновлено: октябрь 2026
63 из 105 в библиотеке

Модуль: Voice & Real-Time AI | Время: ~25 мин теории + 40 мин практики


Суть урока

Чат-боты пишут. Голосовые агенты звонят.

Это разные классы инструментов. Чат-бот ждёт когда клиент напишет. Голосовой агент может сам набрать номер вскоре после того, как клиент оставил заявку и разрешил позвонить, — и квалифицировать его, задать нужные вопросы, записать на встречу. Без участия человека.

В этом уроке строим настоящего голосового агента через Vapi: он звонит, разговаривает, а после звонка Claude анализирует транскрипт и сохраняет данные в CRM.

🎨 Образ: голосовой агент — невидимый сотрудник. Работает 24/7, не болеет, не устаёт, говорит по скрипту, одновременно ведёт много звонков (предел зависит от тарифа). Оплачивается поминутно, а не фиксированной зарплатой.


Ключевые концепции

  • Голосовой AI-агент — система которая звонит реальным людям и разговаривает с ними голосом
  • Latency — задержка ответа. Чем она короче, тем естественнее разговор; длинные паузы звучат как робот
  • STT (Speech-to-Text) — распознаёт речь клиента в текст
  • TTS (Text-to-Speech) — превращает ответ LLM в голос
  • Vapi — платформа для разработчиков: API-first, Claude подключается как провайдер модели, настраивается под разные сценарии
  • Webhook — url на который Vapi отправляет события (статус звонка, а после звонка — отчёт с транскриптом)
  • Первое сообщение (firstMessage) — то что агент произнесёт в момент когда клиент снимет трубку

Теория

Почему голосовые агенты — отдельная история

Чат-боты и голосовые агенты решают разные проблемы.

Чат-бот: клиент должен сам зайти, написать, ждать ответа. Инициатива на стороне клиента.

Голосовой агент: система сама инициирует контакт, сама управляет разговором, сама решает что спросить следующим. Инициатива на стороне бизнеса.

Именно поэтому голосовые агенты используют там где скорость реакции критична:

  • Квалификация входящих лидов — заявка пришла, агент звонит почти сразу (если клиент разрешил звонок). Быстрый отклик обычно помогает, но эффект зависит от ниши: проверяй на своих данных
  • Напоминания о встречах — звонок за сутки помогает снизить число неявок
  • Обзвон после покупки — собирает отзывы и оценку без колл-центра
  • Исходящие кампании — стоимость считается поминутно (см. раздел о стоимости), звонить можно только тем, кто дал согласие

🎨 Образ: форма на сайте без голосового агента — это почтовый ящик. Форма с голосовым агентом — это телефон который сам звонит когда письмо брошено.


Главное техническое ограничение: latency

Голосовой разговор требует ответа в реальном времени. Для человека комфортна короткая пауза в разговоре, около полусекунды. Всё что дольше — ощущается как "робот думает".

Цепочка latency в голосовом агенте:

Код
Клиент говорит
  → STT (распознавание речи): сотни миллисекунд
  → LLM (генерация ответа): сотни миллисекунд
  → TTS (синтез голоса): сотни миллисекунд
  → Клиент слышит ответ
  
Итого: нужно уложиться примерно в секунду; чем быстрее, тем лучше

Точные задержки зависят от выбранных провайдеров и модели, поэтому измеряй их на своём стеке тестовыми звонками.

Именно поэтому платформы вроде Vapi и Retell вкладывают основные усилия в оптимизацию этой цепочки. Они не просто оборачивают Whisper + GPT + ElevenLabs — они оптимизируют каждый шаг на инфраструктурном уровне.


Сравнение платформ

Платформа Фокус Оплата (на октябрь 2026) Модели
Vapi.ai Разработчикам, API-first $0.05/мин за платформу (на октябрь 2026), остальное оплачивается отдельно по ценам провайдеров Claude, GPT, Gemini и другие (список в документации)
Retell AI Бизнесу, быстрый старт поминутно, в зависимости от выбранных модели и голоса (смотри сайт) выбор в настройках платформы
Bland.ai Outbound/SDR звонки поминутные тарифы (модель, распознавание и голос включены) и тарифы с абонентской платой (смотри сайт) модели платформы
ElevenLabs (голосовые агенты) Качество голоса смотри тарифы на сайте выбор в настройках
Twilio + Claude DIY Максимальный контроль оплата телефонии Twilio плюс провайдеры речи и модели Любой

⚠️ Цена платформы — это не вся цена минуты. У Vapi $0.05/мин — только оркестрация; распознавание речи, модель, голос и телефония оплачиваются отдельно. Разбивку см. в разделе «Реальная стоимость минуты». Актуальные цены и версии: Актуальное сейчас.

Рекомендация: Vapi для разработчиков — понятное API, Claude подключается как провайдер модели, есть документация и сообщество. Retell если нужен быстрый старт без кода. Bland.ai если цель — outbound продажи. Цены и возможности платформ меняются, сверяй их на сайтах.


Vapi: как устроена платформа

Vapi — это три компонента:

  1. Assistant — конфигурация агента: системный промпт, голос, первое сообщение, настройки LLM
  2. Call — конкретный звонок: кому звонить, какой assistant использовать
  3. Webhook — что делать после звонка: транскрипт, статус, запись

Всё управляется через REST API или через Dashboard на vapi.ai. Для продакшена — API. Для тестирования — Dashboard.


Практика

Шаг 1: Регистрация и первый тест

  1. Зарегистрируйся на vapi.ai — при регистрации дают стартовые кредиты (на октябрь 2026: $5), этого хватает на тестовые звонки
  2. В Dashboard → API Keys → скопируй ключ
  3. В Dashboard → Phone Numbers → купи номер или подключи свой номер Twilio. Скопируй ID номера (phoneNumberId): он нужен для исходящих звонков

Сохрани ключ в .env:

bash
VAPI_KEY=your-vapi-key-here
VAPI_PHONE_NUMBER_ID=your-phone-number-id
ANTHROPIC_API_KEY=sk-ant-your-key-here

Шаг 2: Минимальный голосовой агент

Создаём ассистента и делаем первый тестовый звонок.

python
# voice_agent.py
import requests
import os
from dotenv import load_dotenv

load_dotenv()

VAPI_KEY = os.getenv("VAPI_KEY")
HEADERS = {"Authorization": f"Bearer {VAPI_KEY}"}

def create_lead_qualifier() -> str:
    """
    Создаёт голосового агента для квалификации лидов.
    Возвращает ID созданного ассистента.
    """
    assistant = requests.post(
        "https://api.vapi.ai/assistant",
        headers=HEADERS,
        json={
            "name": "Lead Qualifier RU",
            "model": {
                "provider": "anthropic",
                "model": "claude-sonnet-5-5",   # проверь, что модель есть в списке Vapi; актуальные модели: страница «Актуальное сейчас»
                "messages": [{"role": "system", "content": """Ты профессиональный менеджер по продажам.
Твоя задача — квалифицировать входящий лид за 3-5 минут.

Задай эти четыре вопроса в ходе разговора:
1. Какой бюджет рассматривает клиент?
2. Какие сроки — когда планирует принять решение?
3. Что именно ищет — конкретные требования?
4. Кто принимает финальное решение?

Правила разговора:
- Говори кратко, дружелюбно, без скриптового звучания
- Не задавай все вопросы подряд — вплетай в диалог
- Если клиент уже ответил на вопрос — не повторяй его
- В конце предложи записаться на встречу с менеджером
- Разговор не дольше 5 минут
- Если спросят, ты ли человек, честно скажи, что ты AI-ассистент"""}],
                "temperature": 0.7,
                "maxTokens": 150
            },
            "voice": {
                "provider": "11labs",
                "voiceId": "pNInz6obpgDQGcFmaJgB"
            },
            "firstMessage": "Добрый день! Это AI-ассистент компании. Вы оставили заявку на нашем сайте — удобно поговорить пару минут?",
            "endCallMessage": "Отлично, я записал всё что нужно. Наш менеджер свяжется с вами в течение часа. Хорошего дня!",
            "maxDurationSeconds": 300
        }
    ).json()

    assistant_id = assistant["id"]
    print(f"Ассистент создан: {assistant_id}")
    return assistant_id


def make_call(assistant_id: str, phone_number: str) -> dict:
    """
    Инициирует звонок клиенту.
    phone_number в формате E.164: +79161234567
    Звонить можно только тем, кто дал согласие (см. раздел о законах ниже).
    """
    call = requests.post(
        "https://api.vapi.ai/call",
        headers=HEADERS,
        json={
            "assistantId": assistant_id,
            "phoneNumberId": os.getenv("VAPI_PHONE_NUMBER_ID"),   # номер, с которого звоним
            "customer": {
                "number": phone_number,
                "name": "Клиент"  # опционально, для логов
            }
        }
    ).json()

    print(f"Звонок инициирован: {call['id']}")
    print(f"Статус: {call['status']}")
    return call


def get_call_transcript(call_id: str) -> str:
    """
    Получает транскрипт завершённого звонка.
    """
    call = requests.get(
        f"https://api.vapi.ai/call/{call_id}",
        headers=HEADERS
    ).json()

    if call.get("artifact", {}).get("transcript"):
        return call["artifact"]["transcript"]
    return ""


# Запуск
if __name__ == "__main__":
    assistant_id = create_lead_qualifier()

    # Для теста — звоним на свой номер
    call = make_call(assistant_id, "+79161234567")
    print(f"\nID звонка для получения транскрипта: {call['id']}")

Установка зависимостей:

bash
pip install requests python-dotenv

Шаг 3: RAG — агент знает ваш продукт

Агент должен знать ваши услуги, цены, FAQ. Это делается через системный промпт с контекстом.

python
# knowledge_loader.py
from pathlib import Path

def load_knowledge_base(filename: str) -> str:
    """Читает файл с базой знаний"""
    path = Path("knowledge") / filename
    if path.exists():
        return path.read_text(encoding="utf-8")
    return ""


def build_system_prompt() -> str:
    """Собирает системный промпт с базой знаний"""

    services = load_knowledge_base("services.md")
    faq = load_knowledge_base("faq.md")
    objections = load_knowledge_base("objections.md")

    return f"""Ты консультант агентства недвижимости в Эквадоре.

НАШИ УСЛУГИ И ЦЕНЫ:
{services}

ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ:
{faq}

КАК ОТВЕЧАТЬ НА ВОЗРАЖЕНИЯ:
{objections}

ПРАВИЛА:
- Не называй цены выше указанных — всегда "от X"
- Если вопрос не в FAQ — говори "уточню детали и перезвоним"
- Всегда предлагай записаться на встречу или видеоконсультацию
- Говори на русском, если клиент не переходит на другой язык
- Не читай списком — вплетай информацию в разговор"""


# Пример: создать ассистента с базой знаний
def create_realty_agent() -> str:
    import requests
    import os

    VAPI_KEY = os.getenv("VAPI_KEY")

    assistant = requests.post(
        "https://api.vapi.ai/assistant",
        headers={"Authorization": f"Bearer {VAPI_KEY}"},
        json={
            "name": "Realty Consultant",
            "model": {
                "provider": "anthropic",
                "model": "claude-sonnet-5-5",
                "messages": [{"role": "system", "content": build_system_prompt()}]
            },
            "voice": {
                "provider": "11labs",
                "voiceId": "pNInz6obpgDQGcFmaJgB"
            },
            "firstMessage": "Добрый день! Это AI-консультант агентства. Чем могу помочь?"
        }
    ).json()

    return assistant["id"]

Создай папку knowledge/ с тремя файлами:

Код
knowledge/
  services.md    — список услуг с ценами
  faq.md         — 10-15 частых вопросов с ответами
  objections.md  — типичные возражения и как на них отвечать

Шаг 4: Webhook — что делать после звонка

После каждого звонка Vapi отправляет данные на ваш webhook. Здесь Claude анализирует транскрипт и сохраняет результат.

python
# webhook_handler.py
from flask import Flask, request, jsonify
import anthropic
import json
import os
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)
claude = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))


def analyze_call(transcript: str) -> dict:
    """
    Claude анализирует транскрипт и извлекает структурированные данные.
    """
    response = "".join(b.text for b in claude.messages.create(
        model="claude-sonnet-5-5",   # актуальные модели: страница «Актуальное сейчас»
        max_tokens=600,
        messages=[{
            "role": "user",
            "content": f"""Проанализируй разговор с клиентом и верни JSON.

ТРАНСКРИПТ:
{transcript}

Верни ТОЛЬКО валидный JSON без пояснений:
{{
  "qualified": true или false,
  "budget": "сумма или диапазон, или 'не уточнил'",
  "timeline": "когда планирует принять решение",
  "requirements": "что именно ищет (2-3 предложения)",
  "decision_maker": true или false,
  "next_action": "что делать дальше (например: позвонить менеджеру, отправить презентацию, убрать из воронки)",
  "sentiment": "позитивный, нейтральный или негативный",
  "summary": "2-3 предложения о разговоре"
}}"""
        }]
    ).content if b.type == "text")

    # Очищаем от markdown если модель добавила
    if "```json" in response:
        response = response.split("```json")[1].split("```")[0]
    elif "```" in response:
        response = response.split("```")[1].split("```")[0]

    try:
        return json.loads(response.strip())
    except json.JSONDecodeError:
        return {
            "qualified": False,
            "summary": "Не удалось проанализировать транскрипт",
            "raw_response": response
        }


def save_to_crm(analysis: dict, customer: dict, call_id: str):
    """
    Сохраняет результат в вашу систему.
    Здесь замени на реальный CRM: Notion, Airtable, Google Sheets, AmoCRM.
    """
    record = {
        "call_id": call_id,
        "customer_phone": customer.get("number", "unknown"),
        "customer_name": customer.get("name", "unknown"),
        **analysis
    }

    # Простой вариант — сохранить в JSON файл
    import datetime
    filename = f"calls/call-{call_id}-{datetime.date.today()}.json"
    os.makedirs("calls", exist_ok=True)

    with open(filename, "w", encoding="utf-8") as f:
        json.dump(record, f, ensure_ascii=False, indent=2)

    print(f"Сохранено: {filename}")

    # Если квалифицирован — отправь уведомление менеджеру
    if analysis.get("qualified"):
        notify_manager(record)


def notify_manager(record: dict):
    """
    Отправляет уведомление менеджеру о квалифицированном лиде.
    Замени на реальный канал: Telegram, Slack, email.
    """
    # Пример: вывод в консоль (в продакшене — Telegram Bot API)
    print(f"""
=== КВАЛИФИЦИРОВАННЫЙ ЛИД ===
Телефон: {record['customer_phone']}
Бюджет: {record.get('budget', 'не уточнил')}
Сроки: {record.get('timeline', 'не уточнил')}
Следующий шаг: {record.get('next_action', '')}
Резюме: {record.get('summary', '')}
==============================
    """)


@app.post("/vapi-webhook")
def handle_vapi_event():
    """Основной обработчик событий от Vapi"""
    # Vapi кладёт событие внутрь ключа "message"
    message = (request.json or {}).get("message", {})
    event_type = message.get("type")

    if event_type == "end-of-call-report":
        call = message.get("call", {})
        call_id = call.get("id", "unknown")
        customer = call.get("customer", {})
        transcript = message.get("artifact", {}).get("transcript", "")

        print(f"Звонок завершён: {call_id}")
        print(f"Причина завершения: {message.get('endedReason', 'unknown')}")

        if transcript:
            print("Анализирую транскрипт...")
            analysis = analyze_call(transcript)
            save_to_crm(analysis, customer, call_id)
        else:
            print("Транскрипт пустой — звонок не состоялся или клиент не ответил")

    elif event_type == "status-update":
        call_id = message.get("call", {}).get("id", "unknown")
        print(f"Статус звонка {call_id}: {message.get('status', '?')}")

    return jsonify({"status": "ok"})


if __name__ == "__main__":
    # В продакшне закрой webhook секретом в заголовке и не включай debug
    app.run(port=5000, debug=False)

Установка:

bash
pip install flask anthropic requests python-dotenv

Запуск локально (для теста):

bash
# Запусти webhook сервер
python webhook_handler.py

# В другом терминале — пробрось порт через ngrok для тестирования
ngrok http 5000
# ngrok даст публичный URL вроде https://abc123.ngrok.io

Регистрируй webhook в Vapi:

python
# Обнови ассистента чтобы он отправлял события на твой webhook
import requests

VAPI_KEY = "your-key"
ASSISTANT_ID = "your-assistant-id"
WEBHOOK_URL = "https://abc123.ngrok.io/vapi-webhook"

requests.patch(
    f"https://api.vapi.ai/assistant/{ASSISTANT_ID}",
    headers={"Authorization": f"Bearer {VAPI_KEY}"},
    json={"server": {"url": WEBHOOK_URL}}   # в старых примерах встречается поле serverUrl
)

Шаг 5: Автоматический обзвон лидов

Реальный сценарий: новая заявка с сайта → агент звонит автоматически. Автозвонок допустим, только если человек в заявке дал согласие на звонок (см. раздел о законах ниже).

python
# auto_caller.py
"""
Скрипт для автоматического обзвона.
Подключи к вебхуку вашей CRM или формы обратной связи.
"""
import requests
import os
from dotenv import load_dotenv

load_dotenv()

VAPI_KEY = os.getenv("VAPI_KEY")
ASSISTANT_ID = os.getenv("VAPI_ASSISTANT_ID")
PHONE_NUMBER_ID = os.getenv("VAPI_PHONE_NUMBER_ID")


def call_new_lead(phone: str, name: str = "", source: str = "") -> str:
    """
    Звонит новому лиду сразу после подачи заявки.
    Возвращает call_id для отслеживания.
    """
    call = requests.post(
        "https://api.vapi.ai/call",
        headers={"Authorization": f"Bearer {VAPI_KEY}"},
        json={
            "assistantId": ASSISTANT_ID,
            "phoneNumberId": PHONE_NUMBER_ID,
            "customer": {
                "number": phone,
                "name": name
            },
            # Передаём контекст агенту через overrides
            "assistantOverrides": {
                "variableValues": {
                    "lead_source": source,
                    "lead_name": name
                }
            }
        }
    ).json()

    return call.get("id", "")


def batch_call(leads: list) -> list:
    """
    Обзванивает список лидов.
    leads = [{"phone": "+7...", "name": "...", "source": "..."}, ...]
    """
    results = []

    for lead in leads:
        print(f"Звоним: {lead['name']} ({lead['phone']})")
        call_id = call_new_lead(
            phone=lead["phone"],
            name=lead.get("name", ""),
            source=lead.get("source", "")
        )
        results.append({
            "lead": lead,
            "call_id": call_id
        })

        # Пауза между звонками чтобы не перегружать
        import time
        time.sleep(2)

    return results


# Пример: обзвон после выгрузки из CRM
if __name__ == "__main__":
    today_leads = [
        {"phone": "+79161111111", "name": "Иван Иванов", "source": "Сайт"},
        {"phone": "+79162222222", "name": "Мария Петрова", "source": "Реклама"},
    ]

    results = batch_call(today_leads)
    print(f"\nЗапущено звонков: {len(results)}")
    for r in results:
        print(f"  {r['lead']['name']}: call_id = {r['call_id']}")

Реальная стоимость минуты — разбивка полного стека

Vapi называет "$0.05/мин", но это только orchestration layer. Реальный стек оплачивается по частям. Цена каждой части зависит от выбранного провайдера и меняется, поэтому актуальные цифры бери на странице тарифов Vapi и на сайтах провайдеров:

Компонент Стоимость Что это
Vapi platform $0.05/мин Orchestration STT→LLM→TTS pipeline
STT (Deepgram) поминутно, смотри цены провайдера Распознавание речи
LLM зависит от модели "Мозг" агента; для Claude считай по цене токенов выбранной модели
TTS (ElevenLabs) поминутно или по подписке Синтез голоса
Telephony (Twilio) поминутно, зависит от страны и номера Телефонная линия
ИТОГО сумма всех строк выше Реальная цена минуты, сильно зависит от модели и голоса

Цены моделей (на октябрь 2026), за миллион токенов вход/выход:

  • Claude Haiku 4.5: $1 / $5 — для FAQ и простых интентов (проверь, что модель ещё доступна: Anthropic указывает «не раньше 15.10.2026» для её вывода)
  • Claude Sonnet 5.5: $2 / $10 — баланс цены и качества для продакшена
  • Claude Opus 5.5: $4 / $20 — для сложных разговоров, дороже

Для голоса от ElevenLabs можно выбрать подписку вместо оплаты по факту: тарифы Starter и Creator смотри на странице elevenlabs.io/pricing. Актуальные цены и версии: Актуальное сейчас.


Сценарии использования

Цифры эффекта зависят от ниши, скрипта и качества лидов: измеряй их на своих данных, а не бери из рекламных обещаний.

Квалификация лидов: Заявка приходит → Vapi звонит вскоре после неё → агент за несколько минут собирает бюджет, сроки, требования → менеджер получает готовый профиль лида. Результат: менеджер сразу видит, с кем стоит говорить.

Appointment reminders: За 24 часа до встречи агент звонит, подтверждает время, уточняет нужно ли что-то подготовить. Результат: часть неявок удаётся предотвратить; сколько именно, покажет твой замер.

Post-sale follow-up: Через 7 дней после покупки агент звонит, узнаёт всё ли хорошо, собирает обратную связь. Результат: обратная связь без колл-центра, раннее выявление проблем.

Outbound кампании: Стоимость 1000 минут разговоров считай по полному стеку (Vapi + STT + LLM + TTS + телефония), а не по цене платформы: platform fee — только часть суммы. Агент проводит много звонков параллельно (предел зависит от тарифа), человеку на то же число звонков нужны дни.


Законы и этика звонков

Автоматические звонки регулируются законом, и правила зависят от страны. В США это, например, TCPA, в Канаде — правила CRTC, в ЕС — GDPR и ePrivacy. Общие принципы:

  • звони только тем, кто дал согласие на звонок (например, оставил заявку и разрешил связаться);
  • в начале разговора сообщай, что это AI-ассистент, и давай возможность отказаться от разговора и от повторных звонков;
  • если разговор записывается, предупреждай об этом: в ряде стран это обязательно;
  • храни транскрипты и телефоны как персональные данные: ограничь доступ, не отправляй лишнее в CRM.

Это общий ориентир, а не юридическая консультация: перед запуском проверь правила своей страны и страны клиентов у юриста.

Монетизация голосовых агентов

Это можно предлагать как услугу, но цены и спрос зависят от рынка и ниши, а заработок не гарантирован.

Модель 1: Единоразовая настройка — ассистент, база знаний, webhook с CRM-интеграцией, тестовые звонки перед запуском.

Модель 2: Поддержка и оптимизация — мониторинг транскриптов, улучшение промптов, добавление новых сценариев.

Как посчитать выгоду клиента: часы менеджера на звонки × его ставка за час против расхода на минуты разговора по полному стеку плюс твоя плата. Считай честно на данных клиента, не обещай экономию, которую не можешь подтвердить. Как собрать пакет и посчитать цену, смотри в уроках Упаковка предложения и Цены и монетизация.


Инструменты и ресурсы

  • Vapi.ai — платформа и документация API
  • Retell AI — альтернатива с упором на простоту старта
  • Bland.ai — специализация на outbound/SDR звонках
  • ElevenLabs — лучшие голоса для TTS (интегрируется с Vapi)
  • ngrok — локальный туннель для тестирования webhook
  • Flask — минимальный веб-сервер для webhook

Ключевые выводы

Голосовые агенты — не улучшенные чат-боты. Это другой класс инструментов: они звонят сами, ведут разговор, передают данные в CRM. Честный агент сразу говорит человеку, что он AI, и звонит только тем, кто дал согласие.

Vapi + Claude — рабочая связка: Claude подключается как провайдер модели, а русскоязычные сценарии проверь тестовыми звонками на своих скриптах.

После звонка — Claude снова: анализирует транскрипт, квалифицирует лида, определяет следующий шаг. Голосовой агент собирает данные, Claude их обрабатывает.

Latency критична. Если ваш DIY-стек Twilio + Claude + ElevenLabs даёт задержку в секунду и больше — разговор звучит неестественно. Используйте готовые платформы (Vapi, Retell) которые оптимизировали это на уровне инфраструктуры.


Следующий урок

→ Realtime AI — разговор в реальном времени через WebSocket без промежуточных сервисов

Отметка хранится только в этом браузере и никуда не отправляется. Мой прогресс