← 블로그 목록
가이드2026-05-21

ClawOps Node.js SDK 완전 가이드: TypeScript로 AI 전화 에이전트 만들기

ClawOps Node.js SDK 완전 가이드: TypeScript로 AI 전화 에이전트 만들기

ClawOps - AI 전화 에이전트 플랫폼

Python 진영이 AI 개발의 중심이지만, 실제 서비스 백엔드는 Node.js/TypeScript로 구축하는 팀이 압도적으로 많습니다. ClawOps는 공식 Node.js SDK(@teamlearners/clawops)를 제공해 TypeScript의 타입 안전성과 AI 음성 에이전트를 동시에 활용할 수 있습니다.

이 글에서는 설치부터 REST API 호출, AI Agent 구축, Tool 등록, MCP 연동까지 Node.js SDK의 모든 기능을 실전 코드와 함께 다룹니다.

왜 Node.js SDK인가?

  • TypeScript 퍼스트 — 모든 메서드에 타입 정의와 JSDoc이 포함돼 IDE 자동완성이 완벽합니다
  • AI Agent 내장ClawOpsAgent로 인바운드·아웃바운드 전화를 AI가 처리합니다. ngrok 불필요
  • REST + Agent 통합 — 하나의 패키지에서 REST API와 Voice Agent를 모두 사용 가능
  • Node.js 18+ — ESM 환경에서 await 기반의 깔끔한 코드

1단계: 설치 및 환경 설정

패키지 설치

용도에 따라 설치 범위가 다릅니다:

# REST API만 사용 (전화 발신, 문자, 번호 관리)
npm install @teamlearners/clawops

# AI Agent 모드 (OpenAI Realtime)
npm install @teamlearners/clawops ws openai

# AI Agent 모드 (Gemini Realtime)
npm install @teamlearners/clawops ws @google/genai

# AI Agent — Pipeline (Deepgram STT + OpenAI LLM + ElevenLabs TTS)
npm install @teamlearners/clawops ws @deepgram/sdk openai elevenlabs

환경변수 설정

export CLAWOPS_API_KEY="sk_live_..."
export CLAWOPS_ACCOUNT_ID="AC1a2b3c4d"
export OPENAI_API_KEY="sk-..."   # AI Agent 사용 시

ClawOps 대시보드에서 API Key와 Account ID를 확인할 수 있습니다.

2단계: REST API — 전화·문자·번호 관리

클라이언트 초기화

import ClawOps from '@teamlearners/clawops';

// 환경변수가 설정돼 있으면 인자 생략 가능
const client = new ClawOps();

// 또는 직접 지정
const client2 = new ClawOps({
  apiKey: 'sk_live_...',
  accountId: 'AC1a2b3c4d',
});

전화번호 발급·관리

// 070 번호 발급
const number = await client.numbers.create({
  webhookUrl: 'https://my-app.com/voice',
});
console.log(number.phoneNumber); // "07012340001"

// 번호 목록 조회
const numbers = await client.numbers.list();

// 웹훅 URL 변경
await client.numbers.update('07012340001', {
  webhookUrl: 'https://my-app.com/new-voice',
});

// 번호 해제
await client.numbers.delete('07012340001');

전화 발신

const call = await client.calls.create({
  to: '01012345678',
  from: '07052358010',
  url: 'https://my-app.com/twiml',
  statusCallback: 'https://my-app.com/status',
  statusCallbackEvent: 'initiated ringing answered completed',
});
console.log(call.callId); // "CA..."

통화 목록·상세 조회

// 목록 (자동 페이지네이션)
for await (const call of (await client.calls.list()).autoPagingIter()) {
  console.log(call.callId, call.status);
}

// 단건 조회
const detail = await client.calls.get('CA1a2b3c4d5e6f7890');
console.log(detail.status, detail.direction);

// 진행 중 통화 종료
await client.calls.update('CA1a2b3c4d5e6f7890', { status: 'completed' });

SMS/MMS 발송

// SMS (단문)
await client.messages.create({
  to: '01012345678',
  from: '07052358010',
  body: '안녕하세요, ClawOps입니다.',
});

// MMS (이미지 첨부)
await client.messages.create({
  to: '01012345678',
  from: '07052358010',
  body: '사진을 보내드립니다.',
  type: 'mms',
  subject: '알림',
  mediaUrl: ['https://example.com/photo.jpg'],
});

3단계: AI Agent — 전화를 AI가 받고 거는 코드

Node.js SDK의 ClawOpsAgent는 ngrok 없이 WebSocket 역방향 연결로 동작합니다. 로컬에서 바로 테스트 가능합니다.

인바운드 (전화 수신)

import { ClawOpsAgent, OpenAIRealtime } from '@teamlearners/clawops/agent';

const agent = new ClawOpsAgent({
  from: '07012341234',  // 발급받은 070 번호
  session: new OpenAIRealtime({
    systemPrompt: '친절한 고객 상담원입니다. 한국어로 응대합니다.',
    voice: 'marin',
    language: 'ko',
  }),
});

await agent.serve(); // Ctrl+C로 종료

실행 후 070-1234-1234로 전화하면 AI가 받습니다.

아웃바운드 (전화 발신)

const agent = new ClawOpsAgent({
  from: '07012341234',
  session: new OpenAIRealtime({
    systemPrompt: '예약 확인 전화를 하는 도우미입니다.',
    language: 'ko',
  }),
});

const session = await agent.call('01012345678', { timeout: 30 });
console.log(`발신 중... (callId: ${session.callId})`);
await session.wait();      // 통화 종료까지 대기
await agent.disconnect();

Tool 등록 — AI에게 기능을 부여하기

const agent = new ClawOpsAgent({
  from: '07012341234',
  session: new OpenAIRealtime({
    systemPrompt: '주문 상담원입니다. 고객이 주문 상태를 물으면 확인해주세요.',
    voice: 'marin',
    language: 'ko',
  }),
});

// AI가 호출할 수 있는 Tool 등록
agent.tool(
  'check_order',
  '주문 상태를 확인합니다.',
  { orderId: { type: 'string' } },
  async ({ orderId }) => {
    // 실제로는 DB나 API를 조회
    return `주문 ${orderId}은 배송 중입니다. 내일 도착 예정입니다.`;
  },
);

await agent.serve();

이벤트 핸들링

agent.on('call_start', async (call) => {
  console.log(`통화 시작: ${call.fromNumber} -> ${call.toNumber}`);
});

agent.on('call_end', async (call) => {
  console.log(`통화 종료 (${call.callId})`);
});

MCP 서버 연동

외부 MCP 서버를 연결해 AI 에이전트의 능력을 확장할 수 있습니다:

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://my-mcp-server.com', {
      headers: { Authorization: 'Bearer token' },
    }),
  ],
});

await agent.serve();

4단계: 에러 처리

SDK는 계층적 예외를 제공합니다:

import ClawOps, {
  AuthenticationError,
  NotFoundError,
  RateLimitError,
  APIStatusError,
} from '@teamlearners/clawops';

const client = new ClawOps();

try {
  await client.calls.get('CA_invalid_id');
} catch (e) {
  if (e instanceof NotFoundError) {
    console.log(`통화를 찾을 수 없습니다: ${e.message}`);
  } else if (e instanceof AuthenticationError) {
    console.log('API 키가 유효하지 않습니다.');
  } else if (e instanceof RateLimitError) {
    console.log(`동시 통화 한도 초과: ${e.message}`);
  } else if (e instanceof APIStatusError) {
    console.log(`API 에러: HTTP ${e.statusCode} - ${e.message}`);
  }
}

자동 재시도(지수 백오프, 기본 2회)가 내장되어 있어 일시적 오류는 자동 처리됩니다:

const client = new ClawOps({ maxRetries: 5 });   // 재시도 5회로 변경
const client2 = new ClawOps({ maxRetries: 0 });  // 비활성화

5단계: Webhook 서명 검증

프로덕션에서는 반드시 webhook 서명을 검증하세요:

import express from 'express';
import ClawOps, { WebhookVerificationError } from '@teamlearners/clawops';

const app = express();
const client = new ClawOps();

app.post('/webhook', express.urlencoded({ extended: false }), (req, res) => {
  try {
    client.webhooks.verify({
      url: 'https://my-app.com/webhook',
      params: req.body,
      signature: req.headers['x-signature'] as string,
      signingKey: 'your_signing_key',
    });
  } catch (e) {
    if (e instanceof WebhookVerificationError) {
      return res.status(401).send('Unauthorized');
    }
  }

  const callId = req.body.CallId;
  // ... 이벤트 처리
  res.sendStatus(204);
});

Python SDK와의 비교

기능Python SDKNode.js SDK
설치pip install clawopsnpm install @teamlearners/clawops
AI Agentpip install clawops[agent,openai]npm install @teamlearners/clawops ws openai
타입 지원타입 힌트 (mypy)TypeScript 네이티브
비동기AsyncClawOps / asyncio기본 async/await
Agent 패턴@agent.tool 데코레이터agent.tool() 메서드
발신자 번호from_= (예약어 회피)from: (객체 키)
MCP 연동MCPServerStdio()mcpServerStdio()

실전 예시: Express + ClawOps 전화 상담 서버

import express from 'express';
import { ClawOpsAgent, OpenAIRealtime, BuiltinTool } from '@teamlearners/clawops/agent';
import ClawOps from '@teamlearners/clawops';

const app = express();
const client = new ClawOps();

// AI 전화 에이전트 (인바운드 수신)
const agent = new ClawOpsAgent({
  from: '07012341234',
  session: new OpenAIRealtime({
    systemPrompt: `카페 예약 상담원입니다.
- 영업시간: 10:00-22:00
- 예약은 2인 이상만 가능합니다.
- 복잡한 문의는 상담원에게 전환하세요.`,
    voice: 'marin',
    language: 'ko',
  }),
  builtinTools: [BuiltinTool.HANG_UP, BuiltinTool.TRANSFER_CALL],
});

// Tool: 예약 가능 여부 확인
agent.tool(
  'check_availability',
  '특정 날짜와 시간의 예약 가능 여부를 확인합니다.',
  { date: { type: 'string' }, time: { type: 'string' }, people: { type: 'number' } },
  async ({ date, time, people }) => {
    // 실제로는 DB 조회
    return `${date} ${time}${people}명 예약 가능합니다.`;
  },
);

// 통화 로그
agent.on('call_start', async (call) => {
  console.log(`[${new Date().toISOString()}] 통화 시작: ${call.fromNumber}`);
});

// REST API: 최근 통화 조회
app.get('/api/calls', async (req, res) => {
  const page = await client.calls.list({ pageSize: 20 });
  res.json(page.data);
});

// 서버 시작
agent.serve();
app.listen(3000, () => console.log('API 서버 시작: http://localhost:3000'));

마무리

ClawOps Node.js SDK는 TypeScript의 타입 안전성과 AI 음성 에이전트를 결합해, 기존 Node.js 백엔드에 자연스럽게 AI 전화 기능을 추가할 수 있게 해줍니다.

3일 무료 Trial로 바로 시작해보세요 → claw-ops.com


관련 글: ClawOps Python SDK 완전 입문 · AI 전화 에이전트 만들기 · 웹훅으로 전화 자동화 구현하기

관련 글 더 보기

ClawOps AI 전화 API로 시작하기

070 번호 발급부터 AI 음성 통화까지, REST API 몇 줄이면 됩니다.