NanoClaw 완전 가이드: 컨테이너 격리형 Claude AI 에이전트 구축 및 활용법 (2026 최신)

0
109
Architecture diagram of NanoClaw showing Claude Agent SDK integration with isolated Docker containers, SQLite persistence, and messaging channels like WhatsApp and Telegram.
완전히 격리된 Linux 컨테이너 내부에서 자율 명령을 수행하는 Claude Agent SDK 기반 NanoClaw 핵심 인프라 레이어 구조
기준2026년 6월 14일 최신 · nanoclaw.dev 공식 문서 기준
버전NanoClaw 최신 (github.com/qwibitai/nanoclaw)
환경Linux (Docker) · macOS (Apple Container / Docker) · WSL2
섹션11개 섹션
🤖 NanoClaw 🐳 Docker 💬 WhatsApp · Telegram ⚡ Claude Agent SDK 🔒 컨테이너 격리 Custom Skill · Swarm · Cron
⚠️
2026-02-19 Anthropic OAuth 정책 변경 — 반드시 확인

Anthropic의 Claude Code OAuth 연동 약관이 2026년 2월 19일 변경됐습니다. 정책 리스크가 명확해질 때까지 Claude Code OAuth 방식 연동을 피하고, ANTHROPIC_API_KEY 직접 입력 방식을 권장합니다. NanoClaw 공식 문서에서도 동일한 주의사항을 공지하고 있습니다.

NanoClaw는 Claude Agent SDK 기반의 완전 자율 개인 AI 어시스턴트입니다. WhatsApp·Telegram·Discord·Slack 등 메신저로 Claude에게 메시지를 보내면, 격리된 Linux 컨테이너 안에서 에이전트가 웹 검색·파일 관리·코드 실행·예약 작업을 자율적으로 처리합니다. 3개의 흩어진 시리즈 글을 2026년 6월 기준 최신 정보로 완전히 통합하고 오류를 수정한 마스터 가이드입니다.
SECTION01

NanoClaw란? — 아키텍처 & 2026 포지셔닝

NanoClaw는 ~700줄의 TypeScript로 구현된 경량 개인용 Claude AI 어시스턴트입니다. “20분 만에 전체 코드베이스를 읽고 모든 줄을 이해했다”는 사용자 후기처럼, 다른 AI 에이전트 프레임워크와 달리 투명하고 감사 가능한 코드베이스를 지향합니다. MIT 라이선스 오픈소스이며 공식 저장소는 github.com/qwibitai/nanoclaw입니다.

🏗️ 핵심 아키텍처 — Node.js 호스트 + 격리 에이전트 컨테이너

아키텍처 다이어그램
[사용자] WhatsApp / Telegram / Discord / Slack
         ↓ 메시지
[Node.js Host Process] ─── SQLite DB (영구 메모리)
  ├── WhatsApp (Baileys 라이브러리)  ← 내장 기본 채널
  ├── Telegram / Discord / Slack    ← /add-* 스킬로 추가
  ├── Cron 예약 작업 엔진
  └── 에이전트 컨테이너 오케스트레이터
         ↓ 메시지 + 컨텍스트 전달
[Per-Session Agent Container] (Linux · Docker / Apple Container)
  ├── Claude Code (Claude Agent SDK)
  ├── CLAUDE.md  ← 그룹별 독립 지식/메모리
  ├── 내장 도구: shell · 파일 읽기/쓰기 · 웹 검색 · Chromium 브라우저
  └── 에이전트 위임 (Swarm 서브에이전트)
         ↓ 응답
[Node.js Host] → 사용자에게 메시지 전송

📊 지원 채널 전체 목록 (2026년 6월 기준)

채널방식추가 방법비고
WhatsAppBaileys 라이브러리기본 내장npm run auth로 QR 페어링
TelegramBot API/add-telegram 스킬@BotFather에서 토큰 발급
DiscordGateway API/add-discord 스킬Discord Application Bot 생성
SlackEvents API/add-slack 스킬Slack App Manifest 설정
Microsoft TeamsBot Framework/add-teams 스킬Azure Bot 등록 필요
iMessageAppleScript/add-imessage 스킬macOS 전용
Google ChatChat API/add-googlechat 스킬Google Workspace 필요
EmailResend API/add-email 스킬Resend 계정 필요
Matrix · Webex · WeChat · Linear · GitHub각 플랫폼 API/add-* 스킬온디맨드 스킬 설치

🆚 NanoClaw vs OpenClaw 비교 (2026)

항목NanoClawOpenClaw
코드베이스~700줄 TypeScript대형 · 복잡
설치bash nanoclaw.sh (5분)복잡한 다단계
보안퍼세션 컨테이너 격리공유 인프라
감사 가능성전체 코드 20분 독파 가능제한적
멀티 LLMClaude 전용다수 LLM 지원
채널 생태계스킬로 확장대형 통합 생태계
라이선스MIT 오픈소스혼합
SECTION02

사전 요구사항 & 환경 검증

⚠️
2026년 6월 기준 최소 요구사항 변경 사항

이전 가이드에서 Node.js 18+로 명시됐으나 2026년 현재 공식 요구사항은 Node.js 20+, pnpm 10+입니다. Docker Compose의 node:18-alpine이미지도 node:20-alpine 이상으로 업데이트하세요. bash nanoclaw.sh 실행 시 자동으로 올바른 버전이 설치됩니다.

구성 요소최소 버전권장비고
Node.js20.x LTS22.x LTS18.x는 EOL 근접, 지원 종료 예정
pnpm10.x최신npm install -g pnpm
Docker24.x최신 stableLinux: Docker Engine / macOS: Docker Desktop or Apple Container
Claude Code최신최신npm install -g @anthropic-ai/claude-code
RAM4GB8GB+Swarm 멀티에이전트 사용 시 더 필요
Anthropic API Key필수console.anthropic.com에서 발급
환경 사전 검증 스크립트
# Node.js 버전 확인 (20+ 필요)
node --version
# v20.x 이상이어야 함

# pnpm 설치 확인
pnpm --version || npm install -g pnpm

# Docker 확인
docker --version       # 24.x 이상
docker info            # Docker daemon 실행 확인

# Claude Code 설치 (없으면)
npm install -g @anthropic-ai/claude-code
claude --version       # 설치 확인

# Anthropic API 키 환경변수 확인
echo $ANTHROPIC_API_KEY  # 비어있으면 다음 단계에서 설정
SECTION03

설치 완전 가이드 — 2026 최신 방식

권장 설치: bash nanoclaw.sh 한 줄이면 끝

2026년 현재 NanoClaw 공식 설치 방법은 git clone 후 bash nanoclaw.sh 실행입니다. Node.js, pnpm, Docker가 없어도 설치 스크립트가 자동으로 설치합니다. 단계가 실패하면 Claude Code가 자동으로 진단하고 재개합니다.

방법 A — 자동 설치 스크립트 (권장, 5분)

1
GitHub에서 Fork 후 Clone
bash
# 1. github.com/qwibitai/nanoclaw 에서 Fork 클릭 (본인 계정으로 복사)
# 2. 내 저장소 Clone
git clone https://github.com/[내아이디]/nanoclaw.git
cd nanoclaw
2
자동 설치 스크립트 실행
bash
bash nanoclaw.sh
# 스크립트가 자동으로:
# - Node.js 20+, pnpm 10+, Docker 설치
# - ANTHROPIC_API_KEY 설정 안내
# - 에이전트 컨테이너 빌드
# - WhatsApp QR 페어링 안내
3
WhatsApp QR 코드 스캔
터미널에 QR 코드가 나타납니다. WhatsApp 앱 → 연결된 기기 → 기기 연결 → QR 스캔. 브라우저의 QR이 작동 안 하면 터미널의 텍스트 QR을 사용하세요.

방법 B — Claude Code /setup 스킬 (대화형)

terminal
cd nanoclaw
claude             # Claude Code 실행
# Claude Code 안에서:
/setup             # 대화형 설치 시작 — Claude가 각 단계를 안내
# 의존성 설치, 컨테이너 빌드, 채널 페어링까지 자동 진행

방법 C — Docker 수동 설치 (고급, R730 홈랩 권장)

docker-compose.yml (2026 업데이트 버전)
version: '3.8'

services:
  nanoclaw-core:
    image: node:20-alpine    # ⚠️ 18-alpine → 20-alpine 필수 업데이트
    container_name: nanoclaw-core
    restart: unless-stopped
    working_dir: /app
    command: sh -c "pnpm install && npm start"
    volumes:
      - ./:/app
      - /var/run/docker.sock:/var/run/docker.sock  # DooD: 에이전트 컨테이너 생성용
      - nanoclaw-data:/app/data
    environment:
      - NODE_ENV=production
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}    # .env 파일에서 주입
      - NANOCLAW_SECRET_KEY=${NANOCLAW_SECRET_KEY}
    ports:
      - "3000:3000"    # API 포트 (내부망만 노출 권장)
    networks:
      - nanoclaw-net

volumes:
  nanoclaw-data:

networks:
  nanoclaw-net:
    driver: bridge
.env 설정 (수동 설치 시)
ANTHROPIC_API_KEY=sk-ant-여기에입력
NANOCLAW_SECRET_KEY=$(openssl rand -base64 32)   # 웹훅 서명용
NODE_ENV=production
# Telegram (선택)
TELEGRAM_BOT_TOKEN=
TELEGRAM_WEBHOOK_URL=https://yourdomain.com/webhooks/telegram
# Discord (선택)
DISCORD_BOT_TOKEN=
💡
macOS에서는 Apple Container가 기본값

macOS에서 NanoClaw를 실행하면 기본적으로 Apple Container(경량, Apple Silicon 최적화)를 사용합니다. Docker로 변환하려면 Claude Code에서 /convert-to-docker 스킬을 실행하세요. Linux에서는 Docker만 지원합니다.

SECTION04

채널 연결 — WhatsApp QR & 추가 채널

⚠️
WhatsApp 구현 방식 정정 — Chromium 아님, Baileys 라이브러리

이전 가이드에서 WhatsApp을 Chromium 브라우저 자동화(whatsapp-web.js + Puppeteer)로 설명했으나, 현재 NanoClaw의 WhatsApp은 Baileys Node.js 라이브러리를 통해 직접 WhatsApp 웹소켓 프로토콜에 연결합니다. Chromium 오버헤드가 없어 훨씬 가볍고 안정적입니다.

WhatsApp QR 페어링 상세

1
npm run auth 실행 (설치 후 최초 1회)
bash
npm run auth
# ⚠️ 반드시 포그라운드에서 실행 — 백그라운드 실행 금지
# QR 코드는 멀티라인 ASCII 아트. 전체가 표시되어야 스캔 가능
# 120초 이상의 타임아웃 허용 (스캔 시간 충분히 확보)
2
WhatsApp 앱에서 스캔
Android: 우측 상단 점 메뉴 → 연결된 기기 → 기기 연결 → QR 스캔
iPhone: 설정 → 연결된 기기 → 기기 연결 → QR 스캔
터미널의 텍스트 QR이 브라우저 QR보다 안정적 (네트워크 문제 시)
3
Successfully authenticated 확인 후 npm start
bash
npm start
# 에이전트가 WhatsApp 메시지를 수신 대기 시작
# 세션은 ./data/whatsapp-sessions/에 저장됨 (재시작 시 자동 복원)

추가 채널 설치 — Claude Code 스킬 방식

Claude Code 내에서 실행
# Claude Code 실행
claude

# Telegram Bot 추가
/add-telegram
# → 스킬이 소스 코드에 Telegram 어댑터를 직접 추가
# → .env에 TELEGRAM_BOT_TOKEN 추가 안내

# Discord 추가
/add-discord

# Slack 추가
/add-slack

# ⚠️ 스킬은 소스 코드를 직접 수정하므로 git commit 권장
git add . && git commit -m "feat: add telegram channel"

Telegram 채널 설정 상세

1
@BotFather에서 봇 생성
Telegram에서 @BotFather → /newbot → 봇 이름·유저네임 입력 → Bot Token 복사
2
.env에 TELEGRAM_BOT_TOKEN 추가
TELEGRAM_BOT_TOKEN=7654321098:AAF_여기에입력
3
Webhook 등록 (외부 접근 가능 도메인 또는 ngrok)
bash
# 개발 환경: ngrok으로 로컬 포트 외부 노출
ngrok http 3000
# Webhook 등록
curl -X POST http://localhost:3000/api/v1/integrations/telegram/register-webhook \
  -H "Authorization: Bearer ${NANOCLAW_SECRET_KEY}"
# 성공 응답: {"status": "success", "message": "Telegram webhook registered"}
💡
개인 채팅 vs 그룹 채팅 — 중요한 차이

개인 채팅(DM)은 시작 시 DB에 동기화되지 않습니다. 개인 사용자 메시지를 처리하려면 전화번호를 직접 사용해야 합니다: {"'{number}@s.whatsapp.net'".format(number="국가코드포함번호")} 형식. 그룹 채팅만 시작 시 자동 동기화됩니다.

SECTION05

메시징 I/O 파이프라인 아키텍처

NanoClaw의 메시지 처리는 채널 수신 → 큐잉 → 에이전트 컨테이너 스폰 → 응답 발송의 4단계로 이루어집니다. 각 메시지마다 독립된 컨테이너가 생성되어 세션 간 격리를 보장합니다.

메시지 처리 파이프라인 (개념)
[채널 수신] WhatsApp Baileys / Telegram Bot API / Discord Gateway
    ↓
[메시지 파서] 그룹 JID 추출 · 발신자 정보 · 메시지 타입
    ↓
[그룹 큐] 그룹별 FIFO 큐 (동일 그룹 메시지는 순서 보장)
    ↓
[컨테이너 스폰] Docker/Apple Container에서 에이전트 실행
  - CLAUDE.md 마운트 (그룹별 독립 메모리)
  - SQLite DB 마운트 (세션 영구 메모리)
  - 스킬 모듈 주입
    ↓
[Claude Agent SDK] 도구 실행 (shell·파일·웹검색·Chromium·Swarm 위임)
    ↓
[응답] 원본 채널로 메시지 전송

WhatsApp 그룹 큐 구현 (Baileys 기반, 2026 수정판)

TypeScript — WhatsApp 클라이언트 (Baileys 방식)
// ⚠️ 2026년 수정: whatsapp-web.js(Puppeteer) 아님 — Baileys 직접 연결 방식
// NanoClaw 공식 코드는 Baileys 라이브러리를 내부적으로 사용합니다.
// npm run auth로 QR 페어링 후 ./data/whatsapp-sessions/에 세션 저장

import { makeWASocket, useMultiFileAuthState, DisconnectReason } from '@whiskeysockets/baileys';
import { Boom } from '@hapi/boom';
import { enqueueMessage } from '../group-queue';

export async function startWhatsAppClient() {
  const { state, saveCreds } = await useMultiFileAuthState('./data/whatsapp-sessions');

  const sock = makeWASocket({
    auth: state,
    printQRInTerminal: true,   // 터미널 QR 출력 (브라우저보다 안정적)
  });

  sock.ev.on('creds.update', saveCreds);

  sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
    if (connection === 'close') {
      const shouldReconnect =
        (lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut;
      if (shouldReconnect) startWhatsAppClient(); // 자동 재연결
    }
  });

  sock.ev.on('messages.upsert', async ({ messages }) => {
    for (const msg of messages) {
      if (!msg.key.fromMe && msg.message) {
        const jid   = msg.key.remoteJid!;     // 그룹 또는 개인 JID
        const text  = msg.message.conversation
          || msg.message.extendedTextMessage?.text || '';
        if (text) enqueueMessage({ jid, text, sock });
      }
    }
  });
}

Telegram Polling Gateway (추가 채널)

TypeScript — Telegram Bot Polling
import TelegramBot from 'node-telegram-bot-api';
import { enqueueMessage } from '../group-queue';

export function startTelegramGateway(): void {
  const token = process.env.TELEGRAM_BOT_TOKEN;
  if (!token) { console.warn('[Telegram] TELEGRAM_BOT_TOKEN 없음 — 스킵'); return; }

  const bot = new TelegramBot(token, { polling: true });

  bot.on('message', (msg) => {
    const chatId  = String(msg.chat.id);
    const text    = msg.text || '';
    if (text) {
      enqueueMessage({
        jid: `tg-${chatId}`,     // Telegram 채팅 ID를 NanoClaw JID로 변환
        text,
        sendFn: (reply: string) => bot.sendMessage(msg.chat.id, reply),
      });
    }
  });

  console.log('[Telegram] Polling 시작됨');
}
SECTION06

CLAUDE.md & SQLite 지식 영속화

🧠
벡터 DB 없는 격리형 메모리 — NanoClaw의 설계 철학

NanoClaw는 의도적으로 벡터 데이터베이스를 사용하지 않습니다. 각 에이전트 그룹마다 독립된 CLAUDE.md 파일이 있어 해당 그룹의 컨텍스트·히스토리·규칙을 담습니다. 이를 통해 그룹 간 메모리 오염이 원천 차단됩니다. 영구 데이터는 2개의 SQLite 파일로 관리됩니다.

구성위치역할특징
CLAUDE.md./data/groups/{jid}/CLAUDE.md그룹별 지식·규칙·히스토리에이전트 컨테이너 시작 시 자동 마운트
store/db.sqlite./data/store/db.sqlite메시지 히스토리·그룹 메타데이터단일 writer · 크로스 마운트 없음
session/db.sqlite./data/session/db.sqlite채널 인증·세션 상태단일 writer · IPC 없음

CLAUDE.md 표준 템플릿 (그룹별 설정 예시)

CLAUDE.md — 2026 권장 구조
# [에이전트 시스템 컨텍스트]
- 그룹 식별자: telegram--100123456
- 마지막 동기화: 2026-06-14T09:00:00Z
- 에이전트 역할: 개인 비서 및 리서치 어시스턴트

## 운영 규칙
- 모든 응답은 한국어로
- 코드 스니펫은 마크다운 코드 블록 사용
- 불확실한 정보는 반드시 "확인 필요" 명시
- 개인정보(이름·연락처·위치)는 응답에 포함 금지

## 영구 지식 베이스
- 사용자 선호 언어: 한국어
- 프로젝트 컨텍스트: agibop.com 블로그 운영
- 자주 쓰는 스택: Ubuntu 24.04, Docker, Ollama, n8n
- 홈 서버: Dell R730 (192.168.1.250), NAS DS925+

## 예약 작업 등록됨
- 매일 07:00 KST: 코스피 시황 브리핑
- 매주 일요일 09:00: 주간 요약 리포트

## 히스토리 요약
[에이전트가 대화 후 자동 업데이트하는 영역]

SQLite 메모리 초기화 (데이터 손상 시)

bash — DB 복구 절차
# 백업 후 재초기화
cp ./data/store/db.sqlite ./data/store/db.sqlite.backup
rm ./data/store/db.sqlite
npm run init        # DB 재생성

# WhatsApp 세션 초기화 (QR 재스캔 필요)
rm -rf ./data/whatsapp-sessions/*
npm run auth        # QR 코드 재스캔
SECTION07

Cron 자동화 & 예약 작업 엔진

NanoClaw의 Cron 엔진은 Node.js 호스트 프로세스에서 직접 실행됩니다. 예약된 시간에 에이전트 컨테이너를 스폰하고, 실행 결과를 WhatsApp 또는 설정된 채널로 메시지를 보내줍니다.

TypeScript — Cron 작업 큐 구현
import cron from 'node-cron';
import { EventEmitter } from 'events';

export interface AutomatedJob {
  id:       string;
  cronExpr: string;     // 표준 cron 표현식
  targetJid:string;     // 메시지 전송 대상 그룹/채팅
  prompt:   string;     // 에이전트에게 전달할 명령
  enabled:  boolean;
}

const jobEmitter = new EventEmitter();

export function registerCronJob(job: AutomatedJob) {
  if (!job.enabled) return;

  cron.schedule(job.cronExpr, async () => {
    console.log(`[Cron] 작업 실행: ${job.id}`);
    jobEmitter.emit('trigger', { jid: job.targetJid, prompt: job.prompt });
  }, {
    timezone: 'Asia/Seoul'   // KST 기준
  });
}

실전 Cron 예약 작업 예시

cron-jobs.json — 2026 권장 설정
[
  {
    "id": "morning-market-brief",
    "cronExpr": "0 7 * * 1-5",
    "targetJid": "[email protected]",
    "prompt": "오늘 코스피·코스닥 시황과 주요 뉴스 3개를 한국어로 정리해줘.",
    "enabled": true
  },
  {
    "id": "weekly-review",
    "cronExpr": "0 9 * * 0",
    "targetJid": "[email protected]",
    "prompt": "지난 주 내가 진행한 작업들과 미완료 항목을 CLAUDE.md를 참고해서 정리해줘.",
    "enabled": true
  },
  {
    "id": "daily-server-health",
    "cronExpr": "0 8 * * *",
    "targetJid": "[email protected]",
    "prompt": "홈서버 상태를 확인해줘. docker ps 결과와 디스크 사용량을 보고해줘.",
    "enabled": true
  }
]
SECTION08

Python Custom Skill 개발 — 호스트 격리형 샌드박스

NanoClaw의 Custom Skill은 에이전트가 호출할 수 있는 외부 Python 스크립트입니다. 호스트와 격리된 환경에서 실행되며, 표준 입출력으로 에이전트와 통신합니다.

TypeScript — Python 스킬 샌드박스 브릿지
import { execFile } from 'child_process';
import * as path from 'path';
import * as fs from 'fs';

const SKILLS_DIR = path.resolve('./skills');

export function executePythonSkill(
  skillName: string,
  payload: Record
): Promise {
  return new Promise((resolve, reject) => {
    const skillPath = path.join(SKILLS_DIR, skillName, 'main.py');
    if (!fs.existsSync(skillPath)) {
      reject(new Error(`스킬 없음: ${skillName}`));
      return;
    }

    const input = JSON.stringify(payload);
    execFile('python3', [skillPath], {
      timeout: 30_000,          // 30초 타임아웃
      maxBuffer: 1024 * 1024,   // 1MB 출력 제한
    }, (err, stdout, stderr) => {
      if (err) { reject(new Error(stderr || err.message)); return; }
      try { resolve(JSON.parse(stdout)); }
      catch { resolve(stdout.trim()); }
    }).stdin?.end(input);
  });
}

실전 Python 스킬 예시 — KIS 주식 시세 조회

skills/stock-price/main.py
#!/usr/bin/env python3
"""KIS Developers API를 통한 주식 시세 조회 스킬"""
import sys, json, os, requests

def get_stock_price(ticker: str) -> dict:
    """한국투자증권 API로 실시간 시세 조회"""
    app_key    = os.environ.get('KIS_APP_KEY', '')
    app_secret = os.environ.get('KIS_APP_SECRET', '')
    # 실제 구현: 토큰 발급 → 시세 API 호출
    return {
        "ticker":  ticker,
        "price":   "실시간 조회 결과",
        "change":  "+1.23%",
        "volume":  "1,234,567주",
    }

if __name__ == '__main__':
    payload = json.loads(sys.stdin.read() or '{}')
    ticker  = payload.get('ticker', '005930')  # 삼성전자 기본값
    result  = get_stock_price(ticker)
    print(json.dumps(result, ensure_ascii=False))

스킬 등록 & CLAUDE.md에 선언

CLAUDE.md — 스킬 등록
## 사용 가능한 Custom Skills

### stock-price
- 용도: 한국 주식 실시간 시세 조회
- 호출: execute_python_skill("stock-price", {"ticker": "005930"})
- 반환: {ticker, price, change, volume}

### youtube-summary
- 용도: YouTube 영상 자막 추출 및 요약
- 호출: execute_python_skill("youtube-summary", {"url": "https://..."})
- 반환: {title, summary, key_points}

### translate
- 용도: 다국어 번역 (DeepL API)
- 호출: execute_python_skill("translate", {"text": "...", "target": "ko"})
SECTION09

Agent Swarm — 멀티에이전트 오케스트레이션

Swarm — NanoClaw의 킬러 피처

“하나의 질문을 던지면 서브에이전트들이 병렬로 리서치·요약·초안 작성을 처리합니다. 마치 팀을 가진 것 같습니다” — NanoClaw 공식 사용자 후기. Agent Swarm은 복잡한 태스크를 서브에이전트들에게 위임하고 결과를 통합하는 계층형 에이전트 군집입니다.

TypeScript — Swarm 오케스트레이터 (Claude Agent SDK)
import { Anthropic } from '@anthropic-ai/sdk';

const client = new Anthropic();

interface SubAgentTask {
  name:    string;
  prompt:  string;
  context: string;
}

async function runSwarm(
  masterPrompt: string,
  subTasks: SubAgentTask[]
): Promise {
  // 1단계: 서브에이전트 병렬 실행
  const subResults = await Promise.all(
    subTasks.map(async (task) => {
      const res = await client.messages.create({
        model: 'claude-sonnet-4-6',    // 서브에이전트 — 속도 최적화 모델
        max_tokens: 2048,
        messages: [{
          role: 'user',
          content: `컨텍스트: ${task.context}\n\n태스크: ${task.prompt}`
        }]
      });
      const text = res.content[0].type === 'text' ? res.content[0].text : '';
      return { name: task.name, result: text };
    })
  );

  // 2단계: 오케스트레이터가 서브에이전트 결과 통합
  const aggregated = subResults
    .map(r => `## ${r.name}\n${r.result}`)
    .join('\n\n');

  const final = await client.messages.create({
    model: 'claude-opus-4-6',    // 오케스트레이터 — 최고 품질 모델
    max_tokens: 4096,
    messages: [{
      role: 'user',
      content: `${masterPrompt}\n\n서브에이전트 결과:\n${aggregated}`
    }]
  });

  return final.content[0].type === 'text' ? final.content[0].text : '';
}

실전 Swarm 활용 예시

TypeScript — 주식 분석 Swarm
async function stockAnalysisSwarm(ticker: string) {
  return runSwarm(
    `${ticker}에 대한 종합 투자 분석 보고서를 작성해줘.`,
    [
      {
        name: '재무분석 에이전트',
        prompt: `${ticker}의 최근 4분기 재무제표를 분석해줘.`,
        context: '재무 분석 전문가. PER, PBR, ROE, 영업이익률 중심 분석.'
      },
      {
        name: '뉴스감성 에이전트',
        prompt: `${ticker} 관련 최근 뉴스 감성 분석을 해줘.`,
        context: '금융 뉴스 분석 전문가. 웹 검색 활용 가능.'
      },
      {
        name: '기술분석 에이전트',
        prompt: `${ticker} RSI, MACD 기술적 분석 결과를 알려줘.`,
        context: '기술적 분석 전문가. 매수/매도 신호 판별.'
      },
      {
        name: '리스크 에이전트',
        prompt: `${ticker} 투자 시 주요 리스크 요인을 정리해줘.`,
        context: '리스크 관리 전문가. 하방 시나리오 중심.'
      }
    ]
  );
}
SECTION10

보안 하드닝 & 입력 가드레일

🔒 컨테이너 격리 검증

bash — 컨테이너 격리 확인
# 에이전트 컨테이너 빌드 확인
echo '{}' | docker run -i --entrypoint /bin/echo \
  nanoclaw-agent:latest "Container OK"
# → "Container OK" 출력되면 격리 정상

# 실행 중인 에이전트 컨테이너 확인
docker ps --filter "name=nanoclaw-agent" --format "table {{.ID}}\t{{.Status}}\t{{.Names}}"

# 컨테이너 호스트 접근 제한 확인
docker inspect nanoclaw-agent:latest | grep -E "Privileged|CapAdd|NetworkMode"

🛡️ 입력 가드레일 — 프롬프트 인젝션 차단

TypeScript — 정규식 미들웨어
const BLACKLIST_PATTERNS = [
  /ignore\s+previous\s+instructions/i,
  /forget\s+(everything|all)/i,
  /you\s+are\s+now\s+(?:a|an)\s+/i,
  /act\s+as\s+(?:if\s+)?(?:you\s+(?:are|were)|an?)\s+/i,
  /system\s*:\s*/i,
  /\[INST\]/i,
  /<\|im_start\|>/i,
];

export function sanitizeInput(text: string): {
  safe: boolean;
  reason?: string;
} {
  for (const pattern of BLACKLIST_PATTERNS) {
    if (pattern.test(text)) {
      return { safe: false, reason: `금지 패턴 탐지: ${pattern}` };
    }
  }
  if (text.length > 4096) {
    return { safe: false, reason: '최대 입력 길이 초과 (4096자)' };
  }
  return { safe: true };
}

🔑 API 키 보안 — Agent Vault 패턴

Agent Vault 핵심 원칙 (2026 권장)
  • 에이전트는 원시 API 키를 보유하지 않습니다 — 아웃바운드 요청은 OneCLI Agent Vault를 통해 자격 증명이 주입됩니다.
  • 에이전트별 정책 시행 — 각 에이전트 컨테이너에 사용 가능한 API 범위와 레이트 리밋이 설정됩니다.
  • Docker Secrets 사용 — 프로덕션에서는 환경변수 직접 사용 대신 Docker Secrets로 API 키를 관리하세요.
  • NANOCLAW_SECRET_KEY 정기 교체 — 웹훅 서명키는 90일마다 교체를 권장합니다.

systemd 서비스 등록 (Linux 프로덕션)

/etc/systemd/system/nanoclaw.service
[Unit]
Description=NanoClaw Personal AI Agent
After=network.target docker.service
Requires=docker.service

[Service]
Type=simple
User=evan
WorkingDirectory=/opt/nanoclaw
ExecStart=/usr/bin/npm start
Restart=always
RestartSec=10
EnvironmentFile=/opt/nanoclaw/.env
StandardOutput=journal
StandardError=journal
SyslogIdentifier=nanoclaw

[Install]
WantedBy=multi-user.target
bash — 서비스 등록 & 시작
sudo systemctl daemon-reload
sudo systemctl enable --now nanoclaw
sudo systemctl status nanoclaw
journalctl -u nanoclaw -f    # 실시간 로그 확인
SECTION11

트러블슈팅 & 2026 운영 체크리스트

🔧 자주 발생하는 문제 & 해결책

문제원인해결책
WhatsApp QR 코드가 터미널에 안 나옴백그라운드 실행, 출력 잘림npm run auth를 포그라운드에서 실행. 타임아웃 120초 이상 설정
QR 스캔 후 연결 즉시 끊김동일 번호를 다른 기기에 이미 연결WhatsApp 앱 → 연결된 기기 → 기존 연결 모두 해제 후 재시도
Container build failedDocker 미실행 또는 버전 부족docker ps로 확인. Docker Desktop 시작 또는 sudo systemctl start docker
에이전트가 응답 없음ANTHROPIC_API_KEY 미설정 또는 잘못됨echo $ANTHROPIC_API_KEY 확인. .env 파일 재확인
포트 충돌 (3000)다른 서비스가 3000 포트 사용 중.env에서 PORT=3001로 변경 후 재시작
Telegram Webhook 등록 실패HTTPS URL 없음 (개발 환경)ngrok으로 로컬 포트 노출 후 Webhook 재등록
Node.js 버전 오류Node 18.x 이하 사용nvm으로 Node 20.x 설치: nvm install 20 && nvm use 20

✅ 2026년 6월 기준 프로덕션 운영 체크리스트

  • Node.js 20.x LTS 이상 사용 중 (18.x 아님)
  • Docker 24.x 이상, docker ps 정상 동작
  • ANTHROPIC_API_KEY 직접 입력 방식 사용 (OAuth 아님)
  • NANOCLAW_SECRET_KEY 환경변수 설정 및 .env git 제외(.gitignore)
  • WhatsApp 세션 파일(./data/whatsapp-sessions/) 정기 백업
  • 컨테이너 격리 확인: docker run nanoclaw-agent:latest echo OK
  • HTTPS 웹훅 사용 (Cloudflare Tunnel 또는 Nginx + SSL)
  • !Claude Code OAuth 연동 비활성화 (2026-02-19 정책 변경)
  • !systemd 서비스 등록으로 재부팅 자동 시작
  • !journalctl 또는 Grafana로 에이전트 로그 모니터링
  • i스킬 추가 후 git commit으로 코드베이스 추적
  • iToken 사용량 최적화: 레이어 템플릿 설정으로 최대 40% 절감 가능

🤖 마지막 한 마디: NanoClaw의 핵심 철학은 “적을수록 좋다(Less is More)”입니다. ~700줄의 투명한 코드, 20분에 전체를 읽을 수 있는 단순함, 각 세션마다 격리된 컨테이너 — 이것이 2026년에도 NanoClaw가 선택받는 이유입니다. bash nanoclaw.sh 한 줄로 지금 바로 시작해보세요.

Leave A Reply

Please enter your comment!
Please enter your name here