AI 전화 에이전트에 Tool 연동하기: 예약 조회, DB 검색, 외부 API 호출
AI 전화 에이전트에 Tool 연동하기: 예약 조회, DB 검색, 외부 API 호출

AI 전화 에이전트가 "안녕하세요"만 말할 수 있다면 ARS와 다를 게 없습니다. 진짜 가치는 AI가 대화 중에 시스템을 조회하고, 예약을 잡고, 주문을 확인할 수 있을 때 나옵니다.
ClawOps Voice Agent SDK는 @agent.tool 데코레이터(Python)와 agent.tool() 메서드(Node.js)로 AI에게 도구를 부여합니다. 이 글에서는 커스텀 Tool 등록부터 내장 Tool(통화 전환, DTMF), MCP 서버 연동까지 실전 패턴을 코드와 함께 다룹니다.
Tool이란?
Tool은 AI가 대화 맥락에서 "이 함수를 호출해야겠다"고 판단하면 자동으로 실행하는 함수입니다. OpenAI의 Function Calling과 동일한 개념이지만, ClawOps SDK는 함수 시그니처에서 스키마를 자동 생성해줘서 별도의 JSON Schema 작성이 필요 없습니다.
예시 흐름:
- 고객: "제 주문 상태 좀 확인해주세요. 주문번호는 A1234입니다."
- AI →
check_order("A1234")자동 호출 - Tool 함수가 DB를 조회해 "배송 중, 내일 도착 예정" 반환
- AI: "주문번호 A1234는 현재 배송 중이고, 내일 도착 예정입니다."
기본: 커스텀 Tool 등록
Python
from clawops.agent import ClawOpsAgent, OpenAIRealtime
import asyncio
agent = ClawOpsAgent(
from_="07012341234",
session=OpenAIRealtime(
system_prompt="쇼핑몰 고객 상담원입니다. 주문 조회와 반품 접수를 도와주세요.",
voice="marin",
language="ko",
),
)
@agent.tool
async def check_order(order_id: str) -> str:
"""주문 상태를 확인합니다. 고객이 주문 번호를 말하면 이 함수를 호출하세요."""
# 실제로는 DB나 ERP API를 조회
orders = {
"A1234": "배송 중 — 내일 도착 예정",
"B5678": "결제 완료 — 오늘 출고 예정",
}
return orders.get(order_id, f"주문번호 {order_id}을 찾을 수 없습니다.")
@agent.tool
async def request_return(order_id: str, reason: str) -> str:
"""반품을 접수합니다. 주문번호와 사유가 필요합니다."""
# 실제로는 반품 시스템에 등록
return f"주문 {order_id}의 반품 요청이 접수되었습니다. 3일 이내 수거됩니다."
asyncio.run(agent.serve())
핵심 규칙:
- Tool 함수는 반드시
async함수여야 합니다 - 반환값은
str타입이어야 합니다 - 함수의 독스트링이 AI에게 전달되는 도구 설명이 됩니다 — 명확하게 작성하세요
Node.js / TypeScript
import { ClawOpsAgent, OpenAIRealtime } from '@teamlearners/clawops/agent';
const agent = new ClawOpsAgent({
from: '07012341234',
session: new OpenAIRealtime({
systemPrompt: '쇼핑몰 고객 상담원입니다.',
voice: 'marin',
language: 'ko',
}),
});
agent.tool(
'check_order',
'주문 상태를 확인합니다. 고객이 주문 번호를 말하면 호출하세요.',
{ orderId: { type: 'string' } },
async ({ orderId }) => {
const orders: Record<string, string> = {
'A1234': '배송 중 — 내일 도착 예정',
'B5678': '결제 완료 — 오늘 출고 예정',
};
return orders[orderId] ?? `주문번호 ${orderId}을 찾을 수 없습니다.`;
},
);
agent.tool(
'request_return',
'반품을 접수합니다. 주문번호와 사유가 필요합니다.',
{ orderId: { type: 'string' }, reason: { type: 'string' } },
async ({ orderId, reason }) => {
return `주문 ${orderId}의 반품 요청이 접수되었습니다. 3일 이내 수거됩니다.`;
},
);
await agent.serve();
내장 Tool: 전화 제어
ClawOps SDK에는 통화 제어를 위한 4가지 내장 도구가 있습니다:
| 도구 | 상수 | 용도 |
|---|---|---|
hang_up | BuiltinTool.HANG_UP | 대화 완료 후 전화 종료 |
collect_dtmf | BuiltinTool.COLLECT_DTMF | 키패드 입력 수집 (본인 인증, 메뉴 선택) |
send_dtmf | BuiltinTool.SEND_DTMF | DTMF 신호 전송 (ARS 탐색, 내선번호) |
transfer_call | BuiltinTool.TRANSFER_CALL | 다른 번호로 통화 전환 (상담원 연결) |
기본적으로 모든 내장 도구가 활성화됩니다. 필요한 것만 선택할 수 있습니다:
from clawops.agent import ClawOpsAgent, BuiltinTool, OpenAIRealtime
# 기본: 모든 내장 도구 활성화
agent = ClawOpsAgent(from_="07012341234", session=session)
# hang_up만 사용 (다른 내장 도구 비활성화)
agent = ClawOpsAgent(
from_="07012341234",
session=session,
builtin_tools=[BuiltinTool.HANG_UP],
)
# 내장 도구 전부 비활성화 (커스텀 Tool만 사용)
agent = ClawOpsAgent(
from_="07012341234",
session=session,
builtin_tools=BuiltinTool.NONE,
)
ARS 아웃바운드 봇 처럼 발신 후 ARS를 탐색하는 경우:
agent = ClawOpsAgent(
from_="07012341234",
session=session,
builtin_tools=[BuiltinTool.HANG_UP, BuiltinTool.SEND_DTMF],
)
실전 사례 1: 병원 예약 확인 + DB 조회
from clawops.agent import ClawOpsAgent, OpenAIRealtime
import asyncio
import aiohttp
agent = ClawOpsAgent(
from_="07012341234",
session=OpenAIRealtime(
system_prompt="""치과 예약 상담원입니다.
- 예약 확인, 변경, 취소를 도와줍니다.
- 이름과 전화번호 뒷자리로 본인 확인 후 예약 정보를 알려주세요.
- 예약 변경은 최소 24시간 전에만 가능합니다.""",
voice="marin",
language="ko",
),
)
@agent.tool
async def find_appointment(name: str, phone_last4: str) -> str:
"""환자 예약을 조회합니다. 이름과 전화번호 뒷자리가 필요합니다."""
async with aiohttp.ClientSession() as session:
async with session.get(
"https://api.my-clinic.com/appointments",
params={"name": name, "phone_last4": phone_last4},
) as resp:
if resp.status == 200:
data = await resp.json()
if data["appointments"]:
appt = data["appointments"][0]
return f"{appt['date']} {appt['time']}에 {appt['doctor']} 선생님 예약이 있습니다."
return "해당 정보로 예약을 찾을 수 없습니다."
return "시스템 오류가 발생했습니다. 잠시 후 다시 시도해주세요."
@agent.tool
async def cancel_appointment(appointment_id: str) -> str:
"""예약을 취소합니다. 예약 ID가 필요합니다."""
async with aiohttp.ClientSession() as session:
async with session.delete(
f"https://api.my-clinic.com/appointments/{appointment_id}"
) as resp:
if resp.status == 200:
return "예약이 취소되었습니다."
return "취소 처리 중 오류가 발생했습니다."
asyncio.run(agent.serve())
실전 사례 2: 쇼핑몰 주문 + 배송 추적
@agent.tool
async def track_delivery(tracking_number: str) -> str:
"""배송 상태를 추적합니다. 운송장 번호가 필요합니다."""
async with aiohttp.ClientSession() as session:
async with session.get(
f"https://api.delivery-tracker.com/v1/tracks/{tracking_number}"
) as resp:
data = await resp.json()
status = data.get("status", "알 수 없음")
location = data.get("location", "")
return f"배송 상태: {status}. 현재 위치: {location}"
@agent.tool
async def get_store_hours(branch: str) -> str:
"""매장 영업시간을 조회합니다."""
hours = {
"강남점": "10:00-22:00 (연중무휴)",
"홍대점": "11:00-23:00 (매주 월요일 휴무)",
"판교점": "10:00-21:00 (연중무휴)",
}
return hours.get(branch, "해당 매장을 찾을 수 없습니다. 강남점, 홍대점, 판교점이 있습니다.")
MCP 서버 연동: 외부 도구 무한 확장
커스텀 Tool 외에도, Model Context Protocol (MCP) 서버를 연결해 외부 도구를 자동으로 AI에 추가할 수 있습니다.
Python
pip install clawops[agent,openai,mcp]
from clawops.agent import ClawOpsAgent, OpenAIRealtime
from clawops.agent.mcp import MCPServerStdio, MCPServerHTTP
import asyncio
agent = ClawOpsAgent(
from_="07012341234",
session=OpenAIRealtime(
system_prompt="다양한 도구를 활용하는 AI 상담원입니다.",
),
mcp_servers=[
MCPServerStdio(
command="npx",
args=["-y", "@modelcontextprotocol/server-google"],
env={"GOOGLE_API_KEY": "..."},
),
MCPServerHTTP(
url="https://mcp.example.com/sse",
headers={"Authorization": "Bearer your-token"},
),
],
)
asyncio.run(agent.serve())
Node.js
npm install @teamlearners/clawops ws @modelcontextprotocol/sdk
import {
ClawOpsAgent, OpenAIRealtime,
mcpServerStdio, mcpServerHTTP,
} from '@teamlearners/clawops/agent';
const agent = new ClawOpsAgent({
from: '07012341234',
session: new OpenAIRealtime({
systemPrompt: '다양한 도구를 활용하는 AI 상담원입니다.',
}),
mcpServers: [
mcpServerStdio('npx', {
args: ['@modelcontextprotocol/server-google'],
env: { GOOGLE_API_KEY: '...' },
}),
mcpServerHTTP('https://mcp.example.com/sse', {
headers: { Authorization: 'Bearer token' },
}),
],
});
await agent.serve();
MCP 서버는 통화별로 독립적으로 연결됩니다. 동시에 여러 통화가 진행되어도 Tool 이름 충돌 없이 안전하게 동작합니다.
Tool 설계 베스트 프랙티스
1. 독스트링을 명확하게
AI는 독스트링(설명)을 보고 "이 Tool을 호출할지 말지"를 판단합니다:
# ❌ 나쁜 예 — AI가 언제 호출해야 하는지 모름
@agent.tool
async def check(id: str) -> str:
"""체크합니다."""
...
# ✅ 좋은 예 — 호출 조건이 명확
@agent.tool
async def check_order(order_id: str) -> str:
"""주문 상태를 확인합니다. 고객이 주문번호를 말하면 이 함수를 호출하세요.
주문번호는 A로 시작하는 5자리 문자열입니다."""
...
2. 에러를 친절한 문자열로 반환
Tool 함수에서 예외가 발생하면 AI가 "오류가 발생했습니다"만 말할 수 있습니다. 대신 에러도 사람이 읽을 수 있는 문자열로 반환하세요:
@agent.tool
async def check_order(order_id: str) -> str:
"""주문 상태를 확인합니다."""
try:
result = await db.query_order(order_id)
return f"주문 {order_id}: {result.status}"
except OrderNotFoundError:
return f"주문번호 {order_id}를 찾을 수 없습니다. 주문번호를 다시 확인해주시겠어요?"
except Exception:
return "시스템에 일시적인 문제가 있습니다. 잠시 후 다시 시도해주세요."
3. Tool 개수는 적게 유지
Tool이 많을수록 AI가 선택에 혼란을 겪을 수 있습니다. 하나의 에이전트에 5~7개 이내로 유지하고, 복잡한 업무는 여러 에이전트로 나누세요.
4. 시스템 프롬프트에서 Tool 사용법 명시
session=OpenAIRealtime(
system_prompt="""카페 예약 상담원입니다.
규칙:
- 예약 전 반드시 check_availability로 가용 여부를 확인하세요.
- 예약 확정 전 고객에게 날짜, 시간, 인원을 반복 확인하세요.
- 2인 미만 예약은 불가합니다.
- 예약 변경/취소는 24시간 전까지만 가능합니다.""",
)
이벤트로 Tool 호출 로그 남기기
@agent.on("call_start")
async def on_call_start(call):
print(f"전화 수신: {call.from_number} -> {call.to_number}")
@agent.on("transcript")
async def on_transcript(call, role, text):
print(f"[{role}] {text}")
@agent.on("call_end")
async def on_call_end(call):
print(f"통화 종료: {call.call_id} ({call.duration:.1f}초)")
마무리
Tool 연동은 AI 전화 에이전트를 "말만 하는 봇"에서 "업무를 처리하는 에이전트"로 바꿔줍니다. 커스텀 Tool, 내장 Tool, MCP 서버를 조합하면 예약 시스템, ERP, CRM, 배송 추적 등 어떤 백엔드와도 연결할 수 있습니다.
ClawOps에서 3일 무료 Trial로 바로 테스트해보세요 → claw-ops.com
관련 글: AI 전화 에이전트 만들기 · MCP 서버로 Claude에게 전화 기능 붙이기 · AI 전화 에이전트 프롬프트 엔지니어링
관련 글 더 보기
AI 전화 에이전트 만들기: AI가 실제로 전화를 걸고 받도록 구축하는 방법
ClawOps MCP 서버를 활용해 한국어 AI 전화 에이전트을 처음부터 끝까지 구축하는 방법. 070 번호 발급, 발신/수신 전화 처리, 웹훅 연동까지 단계별로 안내합니다.
가이드한국 SMS/LMS/MMS API 완벽 가이드: Python으로 문자 보내기
한국에서 SMS, LMS, MMS를 API로 발송하는 방법. ClawOps Python SDK로 단문·장문·이미지 문자를 보내고, 수신 웹훅으로 자동 응답하는 실전 가이드입니다.
가이드웹훅으로 전화 자동화 구현하기: Python + FastAPI 실전 코드
Python과 FastAPI로 전화 웹훅 서버를 구축하는 실전 가이드. CRM 연동, 주문 확인 전화, 부재중 알림 등 비즈니스 자동화 시나리오를 코드로 구현합니다.
가이드ClawOps Node.js SDK 완전 가이드: TypeScript로 AI 전화 에이전트 만들기
ClawOps Node.js/TypeScript SDK로 AI 음성 에이전트를 구축하는 방법. 설치부터 REST API, AI Agent, Tool 등록, MCP 연동까지 실전 코드 예제와 함께 안내합니다.
가이드AI 전화 에이전트 성과 측정 KPI 10가지: 무엇을 추적해야 하나
AI 전화 에이전트의 성과를 측정하는 핵심 KPI 10가지. 통화 완료율, 응답 레이턴시, CSAT부터 비용 효율까지 실전 지표와 측정 방법을 정리합니다.