노코드 빌더를 활용한 AI 음성 에이전트의 빠른 배포
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
- Retell AI – 음성 상호작용을 처리하고 웹훅 이벤트를 발생시킴.
- Your server – 서명을 검증하고 이벤트를 버퍼링한 뒤 Zapier에 전달.
- Zapier – JSON을 파싱해 CRM을 업데이트하고 Twilio 알림을 트리거.
- Twilio – SMS 또는 음성 콜백을 전송.
주의해야 할 실패 모드
- Retell은 웹훅을 3번까지 지수 백오프로 재시도합니다.
- Zapier는 2xx 응답에 대해 재시도하지 않습니다.
- Twilio 체험 계정은 초당 1건 메시지로 제한됩니다.
핵심 레이스 컨디션: 사용자가 문장 중간에 전화를 끊으면 call_ended가 transcript_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 Trigger | Action | Notes |
|---|---|---|
| Webhooks by Zapier – Catch Hook | Code by Zapier (optional) – flatten payload | Zapier 파서는 중첩 JSON을 잘 처리하지 못하므로 평탄화 후 전달 |
| — | Google Sheets – Create Row (or Salesforce – Create Lead) | transcript와 call_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
- 테스트 전화를 걸어봅니다.
- 확인 항목:
- Retell 웹훅이 서버에 도달했는지(로그 확인).
- Zapier가 페이로드를 받았는지(Zapier 작업 기록).
- Twilio가 SMS를 전송했는지(Twilio 콘솔).
- 지연 시간을 측정합니다. 어느 단계라도 ~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초 이내에 응답하도록 하여 재시도를 방지합니다.