노코드 빌더를 활용한 AI 음성 에이전트의 빠른 배포

발행: (2025년 12월 15일 오전 09:43 GMT+9)
9 min read
원문: Dev.to

Source: Dev.to

TL;DR

대부분의 음성 에이전트는 팀이 모든 통합을 직접 코딩하기 때문에 배포에 몇 주가 걸립니다. 이 가이드는 코드 없이 자동화만으로 4시간 이내에 프로덕션 음성 에이전트를 배포하는 방법을 보여줍니다.

구축 내용: 인바운드 전화를 처리하고 Zapier 워크플로우(CRM 업데이트, 알림)를 트리거하며 Twilio를 통해 전화 라우팅을 수행하는 음성 에이전트 – 백엔드 코드 전혀 없음.

스택: Retell AI (음성 로직) + Zapier (워크플로우 연결) + Twilio (전화 라우팅)

결과: CRM 동기화가 포함된 실시간 에이전트가 4시간 이내에 실제 전화를 처리합니다.


Prerequisites

API Access & Authentication

  • Retell AI API 키 (dashboard.retellai.com) – 사용 가능한 크레딧 보유
  • Twilio Account SID + Auth Token (console.twilio.com)
  • Zapier 프리미엄 계정 (웹훅 트리거 및 다단계 Zap에 필요)
  • 음성용으로 프로비저닝된 Twilio 전화번호 (월 최소 $1)

Technical Requirements

  • Node.js 18+ (ngrok을 이용한 로컬 웹훅 테스트용)
  • ngrok 또는 유사한 터널링 도구 (무료 플랜 충분)
  • REST API와 JSON 페이로드에 대한 기본 이해
  • 웹훅 개념(요청/응답 흐름) 숙지

System Setup

  • 웹훅 핸들러용 공개 HTTPS 엔드포인트 (ngrok이 제공)
  • 환경 변수 관리 (.env 파일 사용; 키를 절대 하드코딩 금지)
  • API 테스트용 Postman 또는 curl (선택 사항이지만 권장)

Cost Awareness

  • Retell AI: 음성 합성 $0.02 / 분
  • Twilio: 인바운드 통화 $0.0085 / 분
  • Zapier: Zap 실행은 월간 작업 제한에 포함

Twilio Voice API: Get Twilio


Configuration & Setup

Retell AI는 특정 스코프가 적용된 API 키가 필요합니다—assistant에 대한 읽기/쓰기와 전화 시작을 위한 텔레포니 권한. Retell 대시보드 API Settings에서 키를 생성하고 환경 변수에 저장하세요.

// server.js – Express webhook handler with signature validation
const express = require('express');
const crypto = require('crypto');
const fetch = require('node-fetch'); // or native fetch in Node 18+

const app = express();
app.use(express.json());

app.post('/webhook/retell', async (req, res) => {
  const signature = req.headers['x-retell-signature'];
  const secret = process.env.RETELL_WEBHOOK_SECRET;

  // Validate webhook signature
  const hash = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (hash !== signature) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process webhook event
  const { event_type, call_id, transcript, call_duration_ms } = req.body;

  if (event_type === 'call_ended') {
    // Trigger Zapier webhook asynchronously
    await fetch(process.env.ZAPIER_WEBHOOK_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        call_id,
        transcript,
        duration: call_duration_ms,
        timestamp: new Date().toISOString(),
      }),
    });
  }

  // Return immediately to avoid Zapier timeout
  res.status(200).json({ received: true });
});

app.listen(3000, () => console.log('Webhook server listening on port 3000'));

왜 중요한가: Zapier는 30초 타임아웃이 있습니다. 200 OK를 즉시 반환하고, 처리는 비동기로 수행해 CRM 중복 입력을 방지하세요.


Architecture & Flow

  1. Retell AI – 음성 상호작용을 처리하고 웹훅 이벤트를 발생시킴.
  2. Your server – 서명을 검증하고 이벤트를 버퍼링한 뒤 Zapier에 전달.
  3. Zapier – JSON을 파싱해 CRM을 업데이트하고 Twilio 알림을 트리거.
  4. Twilio – SMS 또는 음성 콜백을 전송.

주의해야 할 실패 모드

  • Retell은 웹훅을 3번까지 지수 백오프로 재시도합니다.
  • Zapier는 2xx 응답에 대해 재시도하지 않습니다.
  • Twilio 체험 계정은 초당 1건 메시지로 제한됩니다.

핵심 레이스 컨디션: 사용자가 문장 중간에 전화를 끊으면 call_endedtranscript_final보다 먼저 발생할 수 있습니다. 이벤트를 약 2초간 버퍼링하고 타임스탬프 기준으로 정렬한 뒤 처리하세요.


Step‑by‑Step Implementation

1. Retell Assistant Configuration

  • 함수 호출을 활성화합니다.
  • 구조화된 JSON 응답을 반환하도록 시스템 프롬프트를 설정합니다(예: { "action": "create_lead", "data": { ... } }).
  • “친절하게 해 주세요”와 같은 모호한 프롬프트는 피하세요. Zapier 매핑을 깨는 비구조화된 출력이 발생합니다.

2. Webhook Endpoint Deployment

  • Express 서버를 공개 URL에 배포합니다(로컬 테스트는 ngrok, 프로덕션은 Railway, Render, Vercel 등).
  • URL을 Retell 대시보드에 등록합니다.
  • 수동 호출로 테스트하고, 서버 로그에 서명 검증 결과가 출력되는지 확인합니다.

3. Zapier Workflow Design

Zap TriggerActionNotes
Webhooks by Zapier – Catch HookCode by Zapier (optional) – flatten payloadZapier 파서는 중첩 JSON을 잘 처리하지 못하므로 평탄화 후 전달
Google Sheets – Create Row (or Salesforce – Create Lead)transcriptcall_id를 매핑. 필드 누락 방지를 위해 기본값 제공
Twilio – Send SMS (optional)자동 레이트‑리밋 처리를 위해 Messaging Service SID 사용

4. Twilio Notification Layer

  • urgent 또는 callback 같은 키워드가 transcript에 나타날 때 SMS를 전송하도록 Zapier 액션을 추가합니다.
  • 단일 전화번호 대신 Messaging Service SID를 사용해 구성합니다.

Error Handling & Edge Cases

  • Webhook timeout: Retell은 5초 이내에 200 응답을 받지 못하면 재시도합니다. 중복 방지를 위해 call_id 같은 멱등성 키를 사용하세요.
  • Zapier 필드 매핑 실패: 누락된 필드가 있으면 전체 액션이 건너뛰어집니다. 페이로드에 기본값을 포함시키세요, 예: transcript: req.body.transcript || "No transcript available"
  • Twilio 전송 실패: 착신 번호가 유선인 경우 오류 21211(잘못된 수신자) 발생. 해당 오류를 로그에 남기고 재시도는 건너뛰세요.

Testing & Validation

  1. 테스트 전화를 걸어봅니다.
  2. 확인 항목:
    • Retell 웹훅이 서버에 도달했는지(로그 확인).
    • Zapier가 페이로드를 받았는지(Zapier 작업 기록).
    • Twilio가 SMS를 전송했는지(Twilio 콘솔).
  3. 지연 시간을 측정합니다. 어느 단계라도 ~5초를 초과하면 차단 코드가 있는지 확인하고, 무거운 작업은 async/백그라운드 잡으로 옮기세요.

System Diagram

graph LR
    Input[Microphone] --> Buffer[Audio Buffer]
    Buffer --> VAD[Voice Activity Detection]
    VAD --> STT[Speech-to-Text]
    STT --> NLU[Intent Detection]
    NLU --> LLM[Response Generation]
    LLM --> TTS[Text-to-Speech]
    TTS --> Output[Speaker]

    VAD -->|Silence Detected| ErrorHandler[Error Handler]
    STT -->|Transcription Error| ErrorHandler
    NLU -->|Intent Not Found| ErrorHandler
    ErrorHandler --> Log[Logging System]

Local Testing

ngrok으로 웹훅을 노출하고 서명 검증을 확인합니다:

// Local webhook signature test (same as production handler)
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());

app.post('/webhook/retell', (req, res) => {
  const signature = req.headers['x-retell-signature'];
  const secret = process.env.RETELL_WEBHOOK_SECRET;

  const hash = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (hash !== signature) {
    console.error('Signature mismatch');
    return res.status(401).json({ error: 'Invalid signature' });
  }

  console.log('Webhook validated:', req.body.event);
  res.status(200).json({ received: true });
});

app.listen(3000, () => console.log('Local webhook listening on :3000'));

ngrok http 3000을 실행하고, HTTPS URL을 Retell AI 대시보드 웹훅 설정에 붙여넣은 뒤 테스트 전화를 걸어보세요. 콘솔에 “Webhook validated” 메시지가 표시되는지 확인합니다.


Webhook Validation

  • Retell AI 대시보드에서 웹훅 로그를 확인합니다.
  • 401 → 서명 검증 실패 (RETELL_WEBHOOK_SECRET 확인).
  • 200 → 정상 수신; 서버가 5초 이내에 응답하도록 하여 재시도를 방지합니다.
Back to Blog

관련 글

더 보기 »