ML.
← Writing

OpenClaw 아키텍처 분석 보고서 / 실사용 시나리오 Q&A

TypeScript 기반 Personal AI Assistant 프레임워크 OpenClaw의 전체 아키텍처 분석. 기술 스택, 핵심 모듈, 메시지 파이프라인, 채널 시스템 등을 상세하게 다룹니다.

SeongHwa Lee··53 min read

분석 일자: 2026-03-11 대상 버전: v2026.3.8 저장소: https://github.com/openclaw/openclaw


This article is mostly written by Cluade Code


1. 프로젝트 개요

OpenClaw는 TypeScript 기반의 Personal AI Assistant 프레임워크로, 사용자의 기기에서 직접 실행되는 로컬 퍼스트 AI 비서입니다.

  • 슬로건: "OpenClaw is the AI that actually does things. It runs on your devices, in your channels, with your rules."
  • 핵심 가치: 로컬 실행, 프라이버시, 보안 기본값, 확장성
  • 지원 채널: WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, BlueBubbles, IRC, Microsoft Teams, Matrix, Feishu, LINE, Mattermost, Nextcloud Talk, Nostr, Synology Chat, Tlon, Twitch, Zalo, Zalo Personal, WebChat (22개+)
  • 지원 플랫폼: macOS, Linux, Windows (WSL2), Raspberry Pi + iOS/Android 앱

2. 기술 스택

영역기술
언어TypeScript (ES2023, ESM)
런타임Node.js v22+ (Bun 선택 지원)
패키지 관리pnpm 모노레포
빌드tsdown, esbuild
테스트Vitest (커버리지 70% 임계값)
린터/포매터Oxlint + Oxfmt
CLI 프레임워크Commander.js 14.0.3
HTTP 서버Express 5.2.1
WebSocketws 8.18.1
AI 런타임@mariozechner/pi-* (Pi agent)
웹 UILit 3.3.2 + Vite
스케줄러croner 10.0.1
파일 감시chokidar 5.0.0
스키마 검증AJV 8.18.0 + Zod

채널별 SDK

채널라이브러리
WhatsApp@whiskeysockets/baileys 7.0.0-rc.9
TelegramgrammY 4.18.2
Slack@slack/bolt 4.6.0
Discorddiscord.js
LINE@line/bot-sdk 10.6.0
Signalsignal-cli (subprocess)

3. 전체 아키텍처

╔══════════════════════════════════════════════════════════════════════════╗
OpenClaw System║                                                                          ║
║  ┌─────────────────────────────────────────────────────────────────┐    ║
║  │                    CLI Entry Layer                               │    ║
║  │  entry.ts → run-main.ts → program.tsCommander.js commands    │    ║
║  │  openclaw onboard / gateway / agent / send / doctor / config    │    ║
║  └───────────────────────┬─────────────────────────────────────────┘    ║
║                          │ start                                         ║
║  ┌───────────────────────▼─────────────────────────────────────────┐    ║
║  │                    Gateway (Control Plane)                       │    ║
║  │   ws://127.0.0.1:18789  +  HTTP                                 │    ║
║  │                                                                  │    ║
║  │  server.impl.ts ──┬── server-http.ts (Express + WS)             │    ║
║  │                   ├── server-chat.ts (ChatRunRegistry)           │    ║
║  │                   ├── server-channels.ts (ChannelManager)        │    ║
║  │                   ├── server-cron.ts (Croner scheduler)          │    ║
║  │                   ├── server-plugins.ts (Plugin registry)        │    ║
║  │                   └── server-methods/ (100+ RPC handlers)        │    ║
║  └──────────┬─────────────────────────────┬───────────────────────┘    ║
║             │ WebSocket frames             │ Channel events              ║
║             ▼                             ▼                              ║
║  ┌──────────────────┐         ┌──────────────────────────────────────┐  ║
║  │   WS Clients     │         │         Channel Manager              │  ║
║  │                  │         │                                      │  ║
║  │ • Control UI     │         │  telegram/ discord/ slack/           │  ║
║  │ • macOS app      │         │  signal/  imessage/ whatsapp/        │  ║
║  │ • iOS/Android    │         │  line/    + 15개 extensions          │  ║
║  │ • WebChat        │         └──────────────┬───────────────────────┘  ║
║  └──────────────────┘                        │ inbound/outbound          ║
║                                              ▼                           ║
║  ┌───────────────────────────────────────────────────────────────────┐  ║
║  │                      Agent Engine                                 │  ║
║  │                                                                   │  ║
║  │  agent-scope.ts ──→ ResolvedAgentConfig                          │  ║
║  │                     (workspace, model, skills, heartbeat)        │  ║
║  │       ▼                                                           │  ║
║  │  pi-embedded-runner/ ──→ Pi Agent (RPC)                          │  ║
║  │       │                                                           │  ║
║  │       ├── tools/         (browser, canvas, cron, system)         │  ║
║  │       ├── skills/        (notion, github, spotify...)            │  ║
║  │       ├── memory/        (vector search, session files)          │  ║
║  │       └── infra/agent-events.ts (EventBus)                      │  ║
║  └───────────────────────────────────────────────────────────────────┘  ║
║             │                                                            ║
║             ▼                                                            ║
║  ┌──────────────────────────┐                                           ║
║  │   LLM Providers          │                                           ║
║  │  OpenAI / Anthropic /    │                                           ║
║  │  Google / 20+ others     │                                           ║
║  └──────────────────────────┘                                           ║
╚══════════════════════════════════════════════════════════════════════════╝

4. 핵심 모듈 구조

모듈역할핵심 파일
CLI사용자 인터페이스entry.ts, cli/run-main.ts, cli/program.ts
Gateway중앙 오케스트레이션 + WS 서버gateway/server.impl.ts, server-http.ts, server-chat.ts
Agents에이전트 생명주기 & 실행agents/agent-scope.ts, agents/pi-embedded-runner/
Channels메시징 채널 플러그인channels/plugins/index.ts, channels/dock.ts
Config설정 관리config/config.ts, config/io.ts, config/sessions/
ProtocolWebSocket 프레임 정의gateway/protocol/index.ts, gateway/server/ws-connection.ts
Infra공통 유틸 (이벤트, 인증, 실행)infra/agent-events.ts, infra/outbound/
Secrets자격증명 관리secrets/command-config.ts, secrets/runtime.ts
Memory에이전트 지식 저장소memory/, memory/session-files.ts
Process서브프로세스 실행 & 승인process/exec.ts, infra/exec-approval-forwarder.ts

5. 메시지 처리 파이프라인

[사용자 WhatsApp 메시지 수신]
src/web/ (WhatsApp Web handler)
  └── 메시지 파싱 & 정규화
src/routing/session-key.ts
  └── "agent:main:whatsapp/+1234567890" 세션 키 생성
src/channels/allowlists/
  └── dmPolicy 검사
        ├── "pairing" → 페어링 코드 요청
        ├── "open"    → 처리 허용
        └── "block"   → 차단
              │ 허용된 경우
src/gateway/server-chat.ts (ChatRunRegistry)
  └── 세션에 runId 할당, 큐 등록
src/agents/pi-embedded-runner/
  └── Pi Agent RPC 실행
        ├── LLM API 호출 (스트리밍)
        └── Tool 실행 (필요 시)
              │ 완료
src/infra/agent-events.ts (EventBus)
  └── AgentEventPayload 발행
      { stream: "assistant", data: "응답 텍스트" }
        ├── → gateway/server/ws-connection.ts
WebSocket으로 Control UI에 실시간 전달
        └── → src/infra/outbound/
                  └── 원본 채널(WhatsApp)로 응답 전송

큐 처리 모드

모드설명
FIFO선입선출 (기본값)
LIFO후입선출
Random무작위 처리

6. Gateway 서버 상세

초기화 시퀀스 (src/gateway/server.impl.ts)

1. 설정 로드 & 검증 (config/config.ts)
2. 인증 초기화 (auth.ts)
3. 플러그인 로드 (server-plugins.ts)
4. 채널 매니저 생성 (server-channels.ts)
5. HTTP/HTTPS 서버 생성 (server-http.ts)
6. WebSocket 서버 연결
7. RPC 메서드 등록 (server-methods/)
8. 헬스 모니터링 시작
9. Cron 서비스 시작
10. 메인터넌스 타이머 시작

RPC 메서드 카테고리

카테고리메서드 예시
chat.*chat.send, chat.history
agents.*에이전트 생명주기 관리
config.*설정 CRUD
channels.*채널 작업
node.*원격 노드 실행
cron.*잡 스케줄링
device.pair.*디바이스 페어링
exec-approvals.*시스템 실행 승인

WebSocket 프레임 타입 (src/gateway/protocol/index.ts)

GatewayFrame // 요청/응답 (메서드 호출)
EventFrame // 브로드캐스트 이벤트
ChatEvent // 채팅 스트리밍 업데이트
AgentEvent // 에이전트 상태 업데이트
HelloOk // 연결 핸드셰이크

7. Agent 엔진

에이전트 설정 체인

OpenClawConfig.agents.list[n]
  → ResolvedAgentConfig {
      name,
      workspace,    // ~/.openclaw/agents/<id>/
      model,        // LLM 모델 설정
      skills,       // 사용 가능한 스킬 목록
      heartbeat,    // 주기적 실행 설정
      sandbox       // 샌드박스 정책
    }
  → AgentScope
  → Agent 실행 컨텍스트

에이전트 이벤트 버스 (src/infra/agent-events.ts)

AgentEventPayload {
  runId: string        // 실행 단위 ID
  seq: number          // 단조증가 시퀀스 번호
  stream:              // 이벤트 스트림 타입
    | "lifecycle"      // 에이전트 시작/종료
    | "tool"           // 툴 실행 이벤트
    | "assistant"      // 응답 텍스트
    | "error"          // 에러 이벤트
  data: Record<string, unknown>
  sessionKey?: string  // 세션 라우팅
}

지원 도구 (Tools)

도구설명
BrowserPlaywright 기반 웹 자동화
CanvasA2UI 에이전트 제어 시각화 UI
Cron시간 기반 자동 실행
Terminal (PTY)터미널 명령 실행
Memory벡터 검색 기반 메모리
File I/O파일 읽기/쓰기

8. 채널 시스템

채널 설정 해결 (src/channels/channel-config.ts)

ChannelEntryMatch {
  entry,           // 직접 매칭 (예: telegram/+1234)
  wildcardEntry,   // 와일드카드 매칭 (*)
  parentEntry,     // 부모 채널 설정 상속
  matchSource      // 매칭 출처 추적
}

보안 정책 (DM Access)

# config.yml
channels:
  telegram:
    dmPolicy: 'pairing' # 기본: 페어링 코드 필요
    # dmPolicy: "open"    # 명시적 허용 필요
    # dmPolicy: "block"   # 전체 차단
    allowFrom:
      - '+1234567890' # 허용된 연락처
      # - "*"             # 전체 허용 (위험)

채널 런타임 상태

ChannelRuntimeSnapshot {
  channels: Map<channelId, ChannelPlugin>
  channelAccounts: Map<accountId, ChannelAccountSnapshot>
}

ChannelAccountSnapshot {
  accountId: string
  defaultRuntime: ChannelRuntime
  health: "ok" | "degraded" | "down"
}

9. 설정 시스템

설정 파일 위치

~/.openclaw/
  ├── config.yml          # 메인 설정 (JSON5 포맷)
  ├── credentials/        # 인증 정보 (암호화)
  ├── sessions/           # 세션 기록
  │   ├── main.json
  │   └── <agentId>.json
  └── agents/
      └── <agentId>/
          └── sessions/*.jsonl

설정 레이어

레이어설명
Gateway바인딩 모드, 인증, TLS, HTTP 엔드포인트
Agents에이전트 목록, 워크스페이스, 모델, 스킬
Channels채널별 설정, 기본값, 허용 목록
Hooks웹훅 핸들러, 인증, 게이팅
Secrets자격증명 참조 & 관리
Memory에이전트 메모리 (벡터 검색 등)
Cron잡 정의
Plugins플러그인별 설정

설정 핫 리로드 (src/gateway/config-reload.ts)

config.yml 파일 변경 감지 (chokidar)
  → 플러그인 재로드
  → 채널 재시작 (변경된 채널만)
  → 시크릿 업데이트
  → 메모리 인덱스 갱신

10. 플러그인 & 확장 시스템

Extensions (42개)

extensions/
  ├── 채널 플러그인
  │   ├── discord          # Discord 확장
  │   ├── line             # LINE 메시징
  │   ├── msteams          # Microsoft Teams
  │   ├── matrix           # Matrix 프로토콜
  │   ├── feishu           # Feishu/Lark
  │   ├── googlechat       # Google Chat
  │   ├── irc              # IRC
  │   ├── mattermost       # Mattermost
  │   ├── nostr            # Nostr 프로토콜
  │   ├── zalo / zalouser  # Zalo (베트남)
  │   ├── bluebubbles      # BlueBubbles (iMessage)
  │   └── ...
  ├── 메모리 플러그인
  │   ├── memory-core      # 기본 메모리
  │   └── memory-lancedb   # LanceDB 벡터 검색
  └── 통합 플러그인
      ├── llm-task         # LLM 태스크
      ├── diagnostics-otel # OpenTelemetry
      └── ...

Skills (50개+)

skills/
  ├── 개발
  │   ├── coding-agent     # 코딩 자동화
  │   └── gh-issues        # GitHub 이슈 관리
  ├── 생산성
  │   ├── notion           # Notion 연동
  │   ├── obsidian         # Obsidian 연동
  │   ├── things-mac       # Things 3 (macOS)
  │   └── trello           # Trello 연동
  ├── 콘텐츠
  │   ├── blogwatcher      # 블로그 모니터링
  │   └── summarize        # 콘텐츠 요약
  └── 시스템
      ├── healthcheck      # 시스템 헬스체크
      ├── tmux             # tmux 제어
      └── voice-call       # 음성 통화

플러그인 로드 방식

// plugins/registry.ts
// npm 패키지 또는 로컬 경로로 동적 로드
import { loadPlugin } from 'openclaw/plugin-sdk'

// 플러그인 인터페이스
interface OpenClawPlugin {
  id: string
  channels?: ChannelPlugin[]
  skills?: SkillPlugin[]
  memory?: MemoryPlugin
  cli?: CLIPlugin
}

11. 핵심 데이터 구조

세션 키 포맷

"agent:main:telegram/+1234567890"
   │     │    └── channel/account
   │     └── agentId ("main" or custom)
   └── prefix

특수 케이스:
  "agent:main:__default"  # 기본 계정
  "cron:<jobId>"          # 크론 잡 세션
  "acp:<id>"              # Agent Control Protocol

메시지 전달 흐름

ChannelId
Agent
SessionKey
ChatRunEntry { sessionKey, clientRunId }
AgentEventPayload (stream: lifecycle|tool|assistant)
ChatEvent (WS frame)
WebSocket Client (Control UI / 채널 응답)

에이전트 실행 컨텍스트

AgentRunContext {
  sessionKey: string
  verboseLevel: "low" | "medium" | "high"
  isHeartbeat: boolean
  runId: string
}

12. 레이어별 의존 관계

entry.ts
  └── cli/run-main.ts
        └── cli/program.ts (Commander.js)
              └── commands/ (284개 커맨드 핸들러)
                    └── gateway/server.impl.ts  ← 핵심 허브
                          ├── config/config.ts         (설정)
                          ├── channels/plugins/        (채널)
                          ├── agents/agent-scope.ts    (에이전트)
                          ├── infra/agent-events.ts    (EventBus)
                          ├── gateway/server-http.ts   (WS 서버)
                          └── gateway/server-methods/  (RPC API)

의존 방향:
  CLIGateway{Channels, Agents, Config, Infra}
  Agents{LLM Providers, Tools, Memory}
  Channels{Channel SDKs, Gateway EventBus}
  Config{File System, Migration, Zod Schemas}

13. 일반 LLM과의 차별점

특성일반 LLM (ChatGPT 등)OpenClaw
실행 위치외부 서버내 기기 (Local-first)
접근 방식웹/앱 직접 접속기존 메신저에서 대화
실행 권한대화만 가능실제 작업 실행 (브라우저, 파일, CLI)
메모리세션 종료 시 소멸영구 메모리 (LanceDB 벡터 검색)
상시 대기불가데몬으로 항상 실행
자동화제한적Cron으로 완전 자동화
연동공식 플러그인만50개+ 스킬, 42개+ 확장
보안플랫폼 의존DM 페어링, 허용 목록, 로컬 암호화
멀티 채널단일 인터페이스22개+ 메신저 동시 지원
음성제한적웨이크워드 (macOS/iOS) + Talk Mode (Android)

14. 디렉토리 트리

openclaw/
├── src/                      # TypeScript 소스
│   ├── entry.ts              # CLI 진입점
│   ├── index.ts              # Public API 익스포트
│   ├── cli/                  # CLI 레이어 (168 files)
│   │   ├── program/
│   │   ├── daemon-cli/
│   │   ├── gateway-cli/
│   │   ├── run-main.ts
│   │   └── argv.ts
│   ├── gateway/              # Gateway 서버 (236 files)
│   │   ├── server.impl.ts    # 메인 서버
│   │   ├── server-http.ts    # HTTP/WS
│   │   ├── server-chat.ts    # 채팅 이벤트
│   │   ├── server-channels.ts
│   │   ├── protocol/         # WS 프레임 스키마
│   │   └── server-methods/   # RPC 핸들러 (65 files)
│   ├── agents/               # 에이전트 엔진 (530 files)
│   │   ├── agent-scope.ts
│   │   ├── pi-embedded-runner/
│   │   ├── auth-profiles/
│   │   ├── skills/
│   │   └── tools/
│   ├── channels/             # 채널 추상화 (65 files)
│   │   ├── plugins/
│   │   ├── allowlists/
│   │   └── dock.ts
│   ├── config/               # 설정 관리 (207 files)
│   │   ├── config.ts
│   │   ├── sessions/
│   │   └── zod-schema.*.ts
│   ├── infra/                # 인프라 유틸 (297 files)
│   │   ├── agent-events.ts   # EventBus
│   │   ├── outbound/
│   │   └── heartbeat-runner.ts
│   ├── memory/               # 메모리 시스템 (97 files)
│   ├── browser/              # 브라우저 자동화 (127 files)
│   ├── media/                # 미디어 파이프라인
│   ├── routing/              # 메시지 라우팅
│   ├── secrets/              # 자격증명 관리
│   ├── security/             # 보안
│   ├── commands/             # 커맨드 핸들러 (284 files)
│   ├── telegram/             # Telegram 구현
│   ├── discord/              # Discord 구현
│   ├── slack/                # Slack 구현
│   ├── signal/               # Signal 구현
│   ├── imessage/             # iMessage 구현
│   └── web/                  # WhatsApp Web 구현
├── extensions/               # 42개 플러그인
├── skills/                   # 50+ 스킬
├── apps/                     # 네이티브 앱
│   ├── macos/                # SwiftUI 메뉴바 앱
│   ├── ios/                  # Swift/SwiftUI iOS
│   ├── android/              # Kotlin Android
│   └── shared/               # 크로스플랫폼 공통
├── ui/                       # 웹 UI (Lit + Vite)
├── docs/                     # 문서 (Mintlify)
├── scripts/                  # 자동화 스크립트 (100+)
├── packages/                 # 내부 패키지
├── package.json
├── pnpm-workspace.yaml
└── tsconfig.json

참고 자료


15. 핵심 개념 설명

15-1. Playwright

Playwright는 Microsoft가 만든 브라우저 자동화 라이브러리입니다. OpenClaw는 이것을 "사람 대신 마우스/키보드를 움직이는 엔진"으로 사용합니다.

사람이 하는 일                    Playwright가 하는 일
────────────────────────────────────────────────────
Chrome 창을 연다              →   chromium.launch()
주소창에 URL 입력              →   page.goto(url)
페이지 구조를 눈으로 파악       →   page.ariaSnapshot()
링크를 클릭한다               →   locator.click()
검색창에 타이핑한다            →   locator.fill("검색어")
JS 콘솔에서 코드 실행          →   page.evaluate(fn)
스크린샷 찍기                 →   page.screenshot()

OpenClaw에서의 Playwright 위치:

LLM (판단)
"이 버튼을 클릭해야겠다"
Browser Tool (src/agents/tools/browser-tool.ts)
{ action: "act", request: { kind: "click", ref: "e5" } }
Playwright API (src/browser/pw-tools-core.interactions.ts)
  │  locator.click({ timeout: 8000 })
Chrome DevTools Protocol (CDP) via WebSocket
실제 Chrome 브라우저

핵심: LLM은 "무엇을 할지" 결정하고, Playwright는 "어떻게 실행할지" 담당합니다.


15-2. Tool (도구)

Tool은 LLM이 텍스트 생성 외에 실제 작업을 수행할 수 있도록 제공되는 기능 단위입니다. LLM 단독으로는 파일을 읽거나 브라우저를 제어할 수 없기 때문에, Tool을 통해 외부 세계와 상호작용합니다.

Tool의 구조:

// src/agents/tools/browser-tool.ts 예시
{
  name: "browser",                    // LLM이 호출할 이름
  description: "Control a browser",  // LLM이 언제 쓸지 판단하는 설명
  inputSchema: {                      // LLM이 넘겨야 하는 파라미터 정의
    action: "navigate | snapshot | act | screenshot ...",
    url: "string",
    ref: "string",
  },
  execute: async (toolCallId, args) => {  // 실제 실행 코드
    return result
  }
}

OpenClaw에서 사용 가능한 Tool 목록:

Tool역할핵심 파일
browserChrome 제어 (크롤링, 클릭, JS실행)tools/browser-tool.ts
read로컬 파일 읽기tools/
write로컬 파일 생성tools/
edit로컬 파일 수정 (old→new 교체)tools/
exec터미널 명령 실행process/exec.ts
cron예약 작업 등록gateway/server-cron.ts
canvas에이전트 제어 시각 UIcanvas-host/
memory장기 기억 저장/검색memory/

Tool 실행 흐름:

LLM → tool_use 블록 생성
src/agents/pi-embedded-subscribe.handlers.ts
  case "tool_execution_start" → 툴 실행 시작 이벤트 발행
src/agents/tools/<tool>.ts
  execute(toolCallId, args) 호출
src/infra/agent-events.ts (EventBus)
  tool_execution_end → 결과 반환
LLM → 결과를 읽고 다음 판단

15-3. 멀티 턴 (Multi-turn)

멀티 턴은 LLM이 한 번의 응답으로 끝내지 않고, Tool 실행 결과를 받아가며 여러 번 대화를 반복하는 방식입니다.

단일 턴 vs 멀티 턴:

[단일 턴 - 일반 LLM]
사용자: "네이버 뉴스 크롤링해줘"
LLM:   "저는 인터넷에 접근할 수 없어서 직접 크롤링은 어렵습니다."
.

[멀티 턴 - OpenClaw]
사용자: "네이버 뉴스 크롤링해줘"

1: LLM → browser.open("sports.naver.com")
      결과: { url: "https://sports.naver.com", ok: true }

2: LLM → browser.snapshot()
      결과: { refs: { e1: "해외축구", e5: "기사1"... } }

3: LLM → browser.act({ kind: "click", ref: "e1" })
      결과: { ok: true }

4: LLM → browser.act({ kind: "evaluate", fn: "..." })
      결과: { articles: [...] }

5: LLM → 최종 응답 생성 (더 이상 툴 없음)
사용자: "뉴스 3건입니다: ..."

멀티 턴이 가능한 이유:

src/agents/pi-embedded-runner/run.ts

while (true) {
  response = await llm.send(messages + toolResults)

  if (response.stopReason === "end_turn") break  // 완료

  if (response.stopReason === "tool_use") {
    result = await executeTool(response.toolCall)
    messages.push({ role: "tool", content: result })
    // 다음 턴으로 계속
  }
}

턴 수 제한 및 비용:

  • 턴이 많아질수록 LLM API 호출 횟수 증가 → 비용/시간 증가
  • 복잡한 작업(쇼핑, 코딩)은 10~20턴도 발생 가능
  • 단순 질문은 1~2턴으로 종료

15-4. Action (액션)

Action은 Browser Tool 안에서 LLM이 Playwright에게 내리는 구체적인 명령 단위입니다.

사용 가능한 Action 전체 목록:

// 브라우저 관리
"status"     → 브라우저 실행 상태 확인
"start"      → 브라우저 시작
"stop"       → 브라우저 종료

// 탭 관리
"open"       → 새 탭 열기 (URL 지정 가능)
"tabs"       → 열린 탭 목록 조회
"focus"      → 특정 탭으로 포커스 이동
"close"      → 탭 닫기

// 페이지 파악
"navigate"URL로 이동
"snapshot"   → 페이지 구조 추출 (ARIA 트리, refs 생성)
"screenshot" → 화면 캡처 (PNG 저장)
"pdf"        → 페이지를 PDF로 저장

// 상호작용 (act)
"act" + kind:
  "click"          → 요소 클릭
  "dblclick"       → 더블 클릭
  "hover"          → 마우스 오버
  "type"           → 키보드 입력
  "fill"           → 폼 필드 채우기
  "press"          → 특정 키 누르기 (Enter, Tab 등)
  "select"         → 드롭다운 선택
  "drag"           → 드래그 앤 드롭
  "scrollIntoView" → 요소가 보이도록 스크롤
  "wait"           → 조건 대기
  "evaluate"       → 임의 JavaScript 실행
  "resize"         → 뷰포트 크기 변경

// 파일/다이얼로그
"upload"     → 파일 업로드
"dialog"     → 브라우저 다이얼로그 처리
"console"    → 개발자 콘솔 JavaScript 실행

ref 시스템 (snapshot ↔ act 연결고리):

snapshot() 호출
  → 페이지의 모든 요소를 ARIA 트리로 변환
  → 각 요소에 짧은 ref ID 부여: e1, e2, e3 ...
LLM에게 반환

LLM이 스냅샷 읽음:
  "link '해외축구' <e1>"
  "article '손흥민 골' <e5>"

act(click, ref: "e5") 호출
  → ref "e5"를 실제 DOM 요소로 역참조
Playwright locator로 변환 → 클릭 실행

15-5. 개념 간 관계도

┌─────────────────────────────────────────────────────────────┐
│                    멀티 턴 루프                               │
│                                                             │
│  ┌──────────┐    tool_use     ┌──────────────────────────┐  │
│  │          │ ─────────────→  │         Tool             │  │
│  │   LLM  (browser / read / exec) │  │
│  │          │ ←─────────────  │                          │  │
│  └──────────┘   tool_result   └────────────┬─────────────┘  │
│       │                                    │                │
 (다음 턴)Action 실행    │
│       └────────────────────────────────────┘                │
└─────────────────────────────────────────────────────────────┘
                    Action (navigate, snapshot, act ...)
                    ┌───────────────────────┐
Playwright                    │  page.goto()                    │  page.ariaSnapshot()                    │  locator.click()                    │  page.evaluate()                    └───────────┬───────────┘
                         실제 Chrome 브라우저
개념한 줄 설명담당 코드
PlaywrightChrome을 코드로 제어하는 라이브러리src/browser/pw-*.ts
ToolLLM이 실제 작업을 실행하는 기능 단위src/agents/tools/
멀티 턴툴 결과를 반영하며 LLM이 반복 판단하는 루프src/agents/pi-embedded-runner/
ActionBrowser Tool 내부의 구체적 명령 (click, fill...)src/agents/tools/browser-tool.ts

16. 기술적 계보 & 이후 동향

OpenClaw 이전: 어떤 프로젝트들이 있었나

OpenClaw 이전에도 LLM + 툴 조합을 시도한 프로젝트들은 있었습니다. 하지만 "상시 실행 + 메신저 연동 + 일반 사용자 대상"을 동시에 만족한 프로젝트는 없었습니다.

2022 ──────────────────────────────────────────────────── 2026

  [1세대: 자율 실험]   [2세대: 프레임워크]  [3세대: 표준화]  [4세대: 개인비서]
         │                    │                  │                 │
  2023.3 AutoGPT       2023   LangChain    2024.11 MCP      2025   OpenClaw
  2023.4 BabyAGI       2023.6 Function    (Anthropic)       2026.1 NanoClaw
  2023   AgentGPT            Calling                         2026   MicroClaw
  2024   CrewAI        2024   AutoGen
         SuperAGI

1세대 (2023 초): 자율 에이전트 실험 — AutoGPT 충격

AutoGPT (2023.3, 10+ GitHub Stars 폭발)
  - "목표만 주면 LLM이 스스로 계획·실행·반복"
  - 웹 검색, 파일 쓰기, 코드 실행 등 툴 연동
  - 구조: LLM → 태스크 분해 → 실행 → 결과 반영 → 반복

BabyAGI / AgentGPT (2023.4~)
  - Task queue + LLM 루프를 단순화한 파생 프로젝트들
  - BabyAGI: 태스크 생성 → 실행 → 우선순위 재정렬

당시 한계:

  • 한 번 실행하고 끝나는 구조 (상시 서버 아님)
  • 메신저 연동, 스케줄링, 개인 메모리 없음
  • 환각과 무한루프로 실사용 불가 수준
  • 개발자 전용 (일반인이 쓸 수 없음)

2세대 (2023 중~2024): 프레임워크 전쟁 — LangChain & ReAct

ReAct 패턴의 정립:

ReAct = Reasoning + Acting

LLM 판단: "날씨를 알아야 한다"
Tool 호출: weather_api("Seoul")
결과 관찰: "22°C, 맑음"
LLM 재판단: "충분한 정보가 있다, 응답 생성"
최종 응답

주요 프레임워크:

프레임워크특징한계
LangChain500개+ 툴, 일관된 인터페이스개발자 전용 라이브러리
CrewAI멀티 에이전트 역할 분담일회성 실행
AutoGen (Microsoft)에이전트 간 대화로 협업상시 서버 아님
Semantic Kernel기업용 AI 오케스트레이션복잡한 설정

Function Calling 등장 (OpenAI, 2023.6):

이전: LLM이 텍스트로 "웹 검색이 필요합니다" → 개발자가 파싱
이후: LLM{ "tool": "search", "query": "..." } 구조 반환
     → 툴 연동 표준화의 시작

3세대 (2024.11): 표준의 등장 — MCP

Model Context Protocol (Anthropic, 2024.11):

MCP 이전:
  Claude ──자체방식──→ 툴A
  GPT-4  ──자체방식──→ 툴B  (각자 다른 연동 방식)
  Gemini ──자체방식──→ 툴C

MCP 이후:
  Claude ─┐
  GPT-4  ─┼──[MCP]──→ 툴A /B /C
  Gemini ─┘           (공통 표준 인터페이스)
  • "AI용 USB-C"로 불림
  • 2025.3 OpenAI 공식 채택 → 사실상 업계 표준
  • LangChain, CrewAI, AutoGen 모두 MCP 통합

OpenClaw와 MCP: mcporter 브리지로 지원 (코어에 직접 내장하지 않고 분리).


4세대 (2025~): 상시 실행 개인비서 — OpenClaw

OpenClaw가 기존과 달랐던 5가지:

① 상시 실행 (Always-on)
   → 데몬으로 등록, 부팅 시 자동 시작

② 메신저 퍼스트 (Messenger-first)
22+ 메신저에서 직접 대화

③ 보안 기본값 (Secure defaults)
DM 페어링, exec-approval로 위험 명령 차단

④ 일반 사용자 대상 (Consumer-grade UX)
   → openclaw onboard 마법사로 설치, 코딩 지식 불필요

⑤ 로컬 퍼스트 (Local-first)
Gateway가 내 기기에서 실행, 데이터가 OpenClaw 서버를 통하지 않음

5세대 (2026~): NanoClaw와 파생 프로젝트들

NanoClaw (2026.1, MIT License)

"OpenClaw의 기능을 컨테이너 격리와 경량 코드베이스로 재구현"

개발 배경:

  • 개발자: Gavriel Cohen (이스라엘)
  • 도구: Anthropic Claude Code로 개발
  • 출시 1주일 만에 GitHub Stars 7,000+ 돌파

OpenClaw와의 핵심 차이:

항목OpenClawNanoClaw
코드베이스~50만 라인수백 줄 (파악 가능)
보안 방식앱 레벨 (allowlist)OS 레벨 (컨테이너 격리)
Agent 런타임자체 Pi AgentAnthropic Agent SDK 직접
실행 단위단일 Node 프로세스에이전트별 독립 컨테이너

컨테이너 격리 모델:

OpenClaw 방식 (앱 레벨 격리):
  개인 에이전트 ─┐
                 ├─ 단일 Node 프로세스 (메모리 공유)
  업무 에이전트 ─┘

NanoClaw 방식 (OS 레벨 격리):
  개인 에이전트 → Linux 컨테이너 A (독립 파일시스템)
  업무 에이전트 → Linux 컨테이너 B (독립 파일시스템)
Apple Container (macOS) / Docker 지원
  → 컨테이너는 매 실행마다 새로 생성 후 폐기 (ephemeral)

NanoClaw 최초 도입: Agent Swarms

기존: 사용자 → 에이전트 1개 → 응답

Swarms:
  사용자 → 매니저 에이전트
               ├─ 리서치 에이전트 (컨테이너 A)
               ├─ 코딩 에이전트   (컨테이너 B)
               └─ 검토 에이전트   (컨테이너 C)
            → 결과 취합 → 응답

MicroClaw (2026, Rust)

NanoClaw 설계 아이디어를 Rust로 재구현. 메모리 안전성 + 네이티브 성능 목표.


전체 기술 동향 타임라인

시기프로젝트/기술핵심 기여
2023.3AutoGPTLLM 자율 실행 가능성 증명
2023.4BabyAGI태스크 큐 + LLM 루프 패턴
2023LangChain툴 연동 프레임워크 표준화
2023.6Function Calling구조화된 툴 호출 (OpenAI)
2024CrewAI / AutoGen멀티 에이전트 협업
2024.11MCP (Anthropic)툴 연결 공통 표준 ("USB-C")
2025.3MCP (OpenAI 채택)사실상 업계 표준 확정
2025OpenClaw상시 실행 개인비서 (일반인 대상)
2026.1NanoClaw컨테이너 격리 + 경량화 + Agent Swarms
2026MicroClawRust 재구현

기술 흐름의 핵심 교훈

1세대 교훈: LLM은 자율 실행이 가능하지만, 안정성이 문제
2세대 교훈: 툴 연동 표준화 없이는 생태계 파편화
3세대 교훈: 공통 프로토콜(MCP)이 생태계를 폭발적으로 성장
4세대 교훈: 기술보다 UX먼저 (개발자 → 일반인 전환)
5세대 교훈: 보안은 앱 레벨이 아닌 OS 레벨에서 해결해야 
             (OpenClawNanoClaw의 컨테이너 격리)

참고 링크


17. Q&A: 실제 사용 시나리오

Q1. 네이버 스포츠 뉴스 크롤링 요청 시 어떤 일이 벌어지나요?

시나리오: 사용자가 "네이버 스포츠 해외축구 뉴스 크롤링해줘"라고 요청

전체 플로우

사용자 메시지
Pi Agent (pi-embedded-runner/run.ts)
LLM"browser 툴 필요" 판단
Browser Tool 등록 (src/agents/openclaw-tools.ts:125)
Chrome 실행 (src/browser/chrome.ts)
--remote-debugging-port 플래그로 실행
CDP WebSocket 연결 대기
Playwright 세션 연결 (src/browser/pw-session.ts)
멀티턴 실행 루프

멀티턴 실행 루프

액션설명
1opensports.naver.com 접속, SSRF 검사 통과
2snapshotARIA 트리 추출 → e1(해외축구 링크), e5(기사1) ...
3act: clickref: "e1" 해외축구 섹션 클릭
4snapshot기사 목록 재파악
5act: click첫 번째 기사 클릭
6act: evaluateJS 실행으로 제목/날짜/내용 추출
7(2~6 반복)나머지 기사 수집
완료응답수집된 기사 목록 반환

핵심 코드 위치

단계파일
툴 등록src/agents/openclaw-tools.ts:125
Chrome 실행src/browser/chrome.ts
Playwright 세션src/browser/pw-session.ts
페이지 스냅샷src/browser/pw-tools-core.snapshot.ts
클릭/JS실행src/browser/pw-tools-core.interactions.ts
SSRF 보안src/browser/navigation-guard.ts

Q2. WhatsApp으로 쿠팡 쇼핑을 요청하면 어떤 일이 벌어지나요?

시나리오: 사용자가 WhatsApp으로 "쿠팡에서 맥북 충전기 제일 싼 거 사줘" 요청

전체 플로우

📱 사용자 (WhatsApp)
1. WhatsApp 채널 수신 (src/web/, @whiskeysockets/baileys)
2. 보안 검사 (dmPolicy = "pairing")
   ├─ 등록된 번호 → 처리 허용 ✅
   └─ 미등록 번호 → 페어링 코드 요청 🔒
3. 세션 키 생성: "agent:main:whatsapp/+1234567890"
4. Pi AgentLLM 판단: "브라우저 툴 필요"
5. 브라우저 자동화 루프

브라우저 자동화 루프

액션설명
1opencoupang.com 접속
2snapshot검색창 ref 파악 (e1)
3act: fill검색창에 "맥북 충전기" 입력
4snapshot검색 결과 목록 파악
5act: evaluateJS로 상품 목록 추출 후 가격 정렬
6act: click최저가 상품 클릭
⚠️ 7act: click장바구니/결제 → exec-approval 발동

현실적 한계

장벽우회 방법
로그인 필요profile: "chrome" 으로 기존 Chrome 쿠키 재사용
봇 감지browser.headless: false 설정
자동 결제 차단exec-approval로 사용자 수동 승인 필수

Q3. WhatsApp으로 로컬 프로젝트에 기능 추가를 요청하면 어떤 일이 벌어지나요?

시나리오: 사용자가 WhatsApp으로 "todo-list 프로젝트에 완료된 항목 필터링 기능 추가해줘" 요청

멀티턴 코딩 루프

동작
1read~/workspace/todo-list/ 디렉토리 구조 파악
2readsrc/components/TodoList.tsx 기존 코드 읽기
3edit필터 기능 코드 삽입 (old → new 방식)
4execnpm run build 실행 → exec-approval 발동
5(에러 시)빌드 에러 로그 읽고 자동 재수정 반복
완료응답변경 내용 요약 WhatsApp 전송

크롤링과의 툴 비교

시나리오사용 툴
웹 크롤링Browser Tool (Chrome CDP)
로컬 파일 수정read / edit / write
명령 실행exec (승인 필요)
스케줄 자동화cron

Q4. 토큰이 폭증하고 컴팩션 후 크론 잡이 오작동하는 이유는 무엇인가요?

문제 상황:

  • 크론 잡 다수 설정
  • 매일 일기 기록 (MD 저장)
  • 수시로 간단한 질문
  • 단순 질문에도 토큰 10,000개 이상 소모
  • Context Compaction 이후 크론 잡이 지시한 대로 작동 안 함

원인 1: LLM 호출 시 매번 포함되는 컨텍스트

LLM API 호출 1= 아래 모든 것의 합산
──────────────────────────────────────────────────────
① 시스템 프롬프트          약 5,000~15,000 토큰
   - 에이전트 지시문
   - 워크스페이스 파일 (bootstrap)
   - 스킬 설명

② 툴 스키마                약 2,000~5,000 토큰
   - browser, read, edit, exec, memory...
   - 매 호출마다 전체 전송

③ 세션 히스토리            가변 (누적될수록 폭증)
   - 과거 대화 전체
   - 일기 항목들
   - 크론 잡 실행 결과들

④ 메모리 검색 결과          약 1,000~3,000 토큰

총합 → 작은 질문에도 10,000~20,000 토큰 소모

핵심 파일: src/agents/pi-embedded-runner/run/attempt.ts

runEmbeddedAttempt()
buildEmbeddedSystemPrompt()   ← ① 매번 재빌드
SessionManager.open()         ← ③ 전체 세션 파일 로드
limitHistoryTurns()DM 설정 있을 때만 제한

원인 2: 일기가 세션 히스토리를 비대하게 만드는 구조

세션 파일: ~/.openclaw/agents/{agentId}/sessions/{sessionId}.jsonl

일기 1건 기록
  → 세션에 메시지로 추가 (user + assistant + tool results)
  → 다음 질문 시 이 일기 내용이 히스토리에 포함

일기 30건 누적
  → 매 질문마다 30개 대화 히스토리 전부 포함
  → 단순 "오늘 날씨?" 질문도 과거 일기 전체가 컨텍스트에 포함

원인 3: Context Compaction이 크론 잡을 망가뜨리는 이유

컴팩션이 하는 일:

src/agents/pi-embedded-runner/compact.ts

compactEmbeddedPiSession()
  → sessionId.jsonl 파일 로드 (전체 대화 기록)
  → contextEngine.assemble() 로 요약/압축
  → 압축된 내용으로 파일 교체 (기존 내용 삭제)
  → sessions.json에 compactionCount++ 기록

크론 잡 정의 위치에 따른 영향:

케이스 A: config.yml에 명시적으로 정의된 크론 잡
  → 지시문이 config.yml에 있으므로 컴팩션 후에도 유지 ✅
BUT: 크론 잡 실행 결과의 축적 내용은 사라짐 ⚠️

케이스 B: 대화로 지시한 크론  ("매일 아침 일기 써줘")
  → 에이전트가 세션 히스토리 안에서만 "기억"
  → 컴팩션 후 해당 지시문이 히스토리에서 삭제됨 ❌
  → 에이전트가 지시를 "잊어버림" → 크론 잡 오작동

원인 요약 표

문제원인관련 파일
단순 질문에 10K+ 토큰시스템 프롬프트+툴스키마+전체 히스토리 매번 전송run/attempt.ts
일기 쌓일수록 느려짐일기가 세션 JSONL에 메시지로 누적sessions/{id}.jsonl
컴팩션 후 크론 오작동대화로 지시한 크론은 히스토리 삭제 시 "기억" 소멸compact.ts
크론 결과 컨텍스트 손실독립 세션도 컴팩션 대상cron/isolated-agent/session.ts

예방 및 개선 방법

1. 크론 잡은 반드시 config.yml에 명시적으로 정의

# ~/.openclaw/config.yml
cron:
  jobs:
    # ✅ 올바른 방법
    - id: 'daily-diary'
      name: '매일 일기 기록'
      schedule:
        kind: 'cron'
        expr: '0 22 * * *'
      payload:
        kind: 'agentTurn'
        message: '오늘 하루를 요약해서 ~/diary/YYYY-MM-DD.md 파일로 저장해줘'
      sessionKey: 'cron:daily-diary' # ← 독립 세션 사용


    # ❌ 잘못된 방법: 대화로 지시 → 컴팩션 후 잊어버림

2. 용도별로 에이전트 세션 분리

agents:
  list:
    - id: 'quick' # 일상 Q&A용
      model: { name: 'claude-haiku-4-5' }
      session:
        dmHistoryLimit: 5 # 최근 5턴만 유지

    - id: 'main' # 코딩/긴 작업용
      model: { name: 'claude-sonnet-4-6' }
      session:
        dmHistoryLimit: 20

3. 세션 히스토리 자동 정리 설정

agents:
  defaults:
    session:
      pruning:
        maxEntries: 50 # 최대 메시지 수 제한
        pruneAfter: '7d' # 7일 지난 메시지 자동 삭제
      dmHistoryLimit: 10 # DM 세션: 최근 10턴만 LLM에 전달

4. 메모리 플러그인으로 크론 지시문 영속화

사용자: "이 지시사항을 메모리에 저장해줘:
        '매일 밤 10시에 오늘 배운 것을 요약해서 diary 폴더에 저장'"

저장 위치: ~/.openclaw/agents/{agentId}/memory/instructions.md
→ 컴팩션 대상이 아님 (별도 파일)
→ memory_search 툴로 다시 로드 가능

개선 전후 토큰 소모 비교

[개선 전]
단순 질문 1:
  시스템 프롬프트:   8,000 토큰
  툴 스키마:         3,000 토큰
  세션 히스토리:    12,000 토큰 (일기 30+ 크론 결과 누적)
  메모리 결과:       2,000 토큰
  합계:             25,000 토큰

[개선 후] (quick 에이전트, haiku 모델, dmHistoryLimit=3)
  시스템 프롬프트:   5,000 토큰
  툴 스키마:         2,000 토큰
  세션 히스토리:       800 토큰 (최근 3턴만)
  메모리 결과:           0 토큰
  합계:              7,800 토큰  ← 약 70% 절감

핵심 관련 파일

파일역할
src/agents/pi-embedded-runner/run/attempt.tsLLM 컨텍스트 조립
src/agents/pi-embedded-runner/compact.ts컨텍스트 컴팩션 로직
src/config/sessions/store.ts세션 메타데이터 로드/저장
src/cron/isolated-agent/session.ts크론 전용 세션 해결
src/cron/isolated-agent/run.ts크론 잡 실행
src/config/zod-schema.session.ts세션 설정 스키마

18. Skill 시스템 심층 분석

Tool vs Skill: 근본적인 차이

OpenClaw의 가장 독특한 설계 결정 중 하나는 ToolSkill을 명확히 분리한 것입니다.

구분ToolSkill
정체실행 가능한 TypeScript 코드SKILL.md 텍스트 파일
등록 방식openclaw-tools.ts에 스키마 등록skills/ 디렉토리에 마크다운 배치
LLM과의 관계LLM이 JSON으로 호출 → 코드 실행 → 결과 반환시스템 프롬프트에 주입 → LLM이 읽고 행동 방식 학습
예시browser, exec, memory_search, read_filegh-issues, coding-agent, healthcheck
확장 방법TypeScript 코드 작성 필요마크다운 문서 작성만으로 가능

핵심 비유:

  • Tool = LLM의 "손" (실제로 뭔가를 실행하는 물리적 능력)
  • Skill = LLM에게 전달하는 "업무 매뉴얼" (어떻게 행동해야 하는지 가르치는 지식)

SKILL.md 구조

모든 Skill은 YAML 프론트매터 + 마크다운 본문으로 구성됩니다:

---
name: skill-name
version: "1.0"
description: "이 스킬이 하는 일"

# 스킬 활성화 조건 (게이팅)
requires:
  bins: ["gh", "git"]          # 이 바이너리가 있어야 활성화
  env: ["GITHUB_TOKEN"]        # 이 환경변수가 있어야 활성화
  config:                      # config.yml 값 조건
    - path: "features.github"
      value: true
  platform: ["darwin", "linux"] # macOS/Linux에서만 활성화
---

# Skill 본문 (마크다운 지침)

이 스킬이 활성화되면 다음과 같이 행동하세요:

## 언제 이 스킬을 사용하나요?
- 사용자가 ~를 요청할 때

## 단계별 절차
1. 먼저 X를 확인합니다
2. 그 다음 Y 툴을 사용합니다
3. 결과를 Z 형식으로 반환합니다

Skill 로딩 & 주입 플로우

agents/skills/workspace.ts
  → skills/ 디렉토리 스캔 (bundled 54)
~/.openclaw/skills/ 스캔 (workspace/managed)
  → 플러그인 스킬 스캔
  → 각 SKILL.md의 프론트매터 파싱
  → 게이팅 조건 검사 (bins/env/config/platform)
  → 통과한 스킬만 필터링

pi-embedded-runner/run/attempt.ts
assembleContext() 호출
  → 활성화된 스킬 내용을 시스템 프롬프트에 주입
LLM API 호출 시 전달

스킬 우선순위 (높음 → 낮음):

workspace > managed > plugin > bundled

같은 이름의 스킬이 여러 곳에 있으면 우선순위가 높은 것이 사용됩니다. 사용자는 ~/.openclaw/skills/에 같은 이름의 파일을 두면 기본 스킬을 오버라이드할 수 있습니다.


실제 스킬 예시 3가지

예시 1: gh-issues — GitHub 이슈 자동 수정 워크플로우

파일: skills/gh-issues/SKILL.md (약 34KB)

이 스킬은 GitHub 이슈를 자동으로 분석하고 수정하는 6단계 워크플로우를 LLM에게 가르칩니다:

Phase 1: 이슈 이해
  → gh issue view <number> 로 이슈 본문 읽기
  → 관련 코드 파일 탐색 (grep, find)
  → 재현 조건 파악

Phase 2: 환경 검증
  → 브랜치 생성: git checkout -b fix/issue-<number>
  → 의존성 설치, 빌드 가능 여부 확인

Phase 3: 근본 원인 분석
  → 관련 테스트 실행 → 실패 확인
  → 스택 트레이스 분석
5 Whys 방법론으로 원인 추적

Phase 4: 수정 구현
  → 최소 범위 수정 (관련 없는 리팩토링 금지)
  → 수정 후 테스트 재실행 → 통과 확인

Phase 5: PR 제출
  → 커밋 메시지 작성 (Conventional Commit 형식)
  → gh pr create 로 PR 생성
  → 이슈 번호 자동 링크

Phase 6: 검증
CI 통과 여부 확인
  → 리뷰어 지정 (CODEOWNERS 참조)

사용 예시:

사용자: "GitHub 이슈 #1234 수정해줘"

LLM이 gh-issues 스킬 지침에 따라:
1. exec 툴 → gh issue view 1234
2. read_file 툴 → 관련 파일 읽기
3. exec 툴 → git checkout -b fix/issue-1234
4. write_file 툴 → 코드 수정
5. exec 툴 → pnpm test
6. exec 툴 → gh pr create ...

예시 2: coding-agent — Claude Code / Codex 위임

파일: skills/coding-agent/SKILL.md

이 스킬은 OpenClaw가 복잡한 코딩 작업을 외부 AI 코딩 에이전트에 위임하는 방법을 가르칩니다:

이 점에서 Hermes와 방향이 갈립니다. OpenClaw는 Claude Code나 Codex 같은 외부 코딩 에이전트를 호출하는 절차를 스킬로 가르치는 쪽에 가깝고, Hermes는 delegate_task로 Hermes 내부의 서브에이전트를 직접 띄우는 구조를 함께 갖고 있습니다.

## 코딩 에이전트 위임 지침

복잡한 코딩 작업(수백 줄 이상 변경, 아키텍처 리팩토링)은
직접 처리하지 말고 전문 코딩 에이전트에 위임하세요.

### Claude Code 위임

exec 툴을 사용하여:
claude --dangerously-skip-permissions \
 -p "작업 지시문" \
 /path/to/project

### 위임 전 체크리스트

- [ ] 현재 git 상태 확인 (커밋되지 않은 변경 없음)
- [ ] 대상 디렉토리 명확히 지정
- [ ] 성공 기준 문서화 (테스트, 빌드 통과 등)

### 위임 후 검증

- 변경된 파일 목록 확인
- 테스트 실행 결과 확인
- 의도하지 않은 변경 없는지 git diff 검토

이 스킬이 없으면 LLM은 코드를 직접 작성하려 하지만, 스킬이 주입되면 LLM이 언제 외부에 위임할지 판단하는 기준을 갖게 됩니다.

예시 3: healthcheck — 8단계 보안 감사

파일: skills/healthcheck/SKILL.md

OpenClaw 설치 환경의 보안 상태를 점검하는 8단계 감사 절차:

Step 1: 실행 중인 프로세스 확인
  exec → ps aux | grep openclaw
  → 예상치 못한 프로세스 탐지

Step 2: 네트워크 연결 상태
  exec → ss -ltnp | grep 18789
  → 게이트웨이 포트 바인딩 확인 (loopback only?)

Step 3: 설정 파일 권한
  exec → ls -la ~/.openclaw/config.yml
0600 이어야  (owner read/write only)

Step 4: 자격증명 파일 검사
  exec → ls -la ~/.openclaw/credentials/
  → 각 파일 0600 권한 확인

Step 5: exec-approval 정책 검토
  read_file → ~/.openclaw/config.yml
  → execApproval.mode가 "always"인지 확인

Step 6: 플러그인 무결성
  → 설치된 플러그인 목록 확인
  → 알 수 없는 출처 플러그인 경고

Step 7: 세션 파일 크기 경고
  → 비정상적으로 큰 세션 파일 탐지 (토큰 폭증 징후)

Step 8: 보안 보고서 생성
  write_file → ~/.openclaw/health-report.md
  → 발견된 문제, 권장 조치 정리

사용 예시:

사용자: "보안 점검해줘"

LLM이 healthcheck 스킬 지침 읽음
→ exec 툴로 8단계 순서대로 실행
→ 각 단계 결과를 분석
→ 최종 보고서 파일로 저장

Skill 생태계: 번들 vs ClawHub

번들 스킬 (54개, skills/ 디렉토리)

카테고리예시 스킬
개발 도구gh-issues, coding-agent, git-workflow
생산성notion, summarize, translate
보안healthcheck, exec-review
미디어image-gen, voice-memo
데이터csv-analyze, pdf-extract

번들 스킬의 추가 기준은 엄격합니다. VISION.md에 명시된 정책:

"New skills should be published to ClawHub first (clawhub.ai), not added to core by default. Core skill additions should be rare and require a strong product or security reason."

ClawHub (커뮤니티 마켓플레이스)

  • URL: https://clawhub.ai
  • 스킬 수: 13,729개+ (2026.3 기준)
  • 설치: openclaw skill install <skill-name>
  • 개발: 개인 저장소에 SKILL.md 작성 후 제출

커뮤니티 인기 스킬 예시:

- pomodoro-timer: 뽀모도로 타이머 + 작업 기록
- stock-monitor: 주식 가격 모니터링 + 알림
- recipe-assistant: 냉장고 재료로 레시피 추천
- meeting-notes: 회의 내용 자동 요약 + Notion 저장
- github-reviewer: PR 자동 코드 리뷰 코멘트

Tool vs Skill 관계 다이어그램

사용자 메시지: "GitHub 이슈 #1234 수정해줘"
┌─────────────────────────────────────────────┐
LLM (Claude)│                                             │
│  시스템 프롬프트에 주입된 내용:│  ┌─────────────────────────────────────┐    │
│  │ [gh-issues SKILL.md 내용]            │   │
│  │ Phase 1: gh issue view 로 읽기        │   │
│  │ Phase 2: 브랜치 생성                   │   │
│  │ Phase 3: 원인 분석                    │   │
│  │ Phase 4: 코드 수정                    │   │
│  │ Phase 5: PR 제출                     │   │
│  │ Phase 6: 검증                        │   │
│  └─────────────────────────────────────┘   │
│                                             │
LLM이 스킬 지침을 읽고 판단:│  → "exec 툴로 gh issue view 1234 실행해야겠다"│  → "read_file 툴로 관련 파일 읽어야겠다"│  → "exec 툴로 git checkout -b 해야겠다"└─────────────────────────────────────────────┘
         ▼ tool_use 요청
┌─────────────────────────────────────────────┐
Tool 실행 레이어                  │
│  exec → 실제 gh/git 명령어 실행                 │
│  read_file → 실제 파일 읽기                    │
│  write_file → 실제 파일 쓰기                   │
│  browser → 실제 웹페이지 열기                   │
└─────────────────────────────────────────────┘
         ▼ tool_result 반환
  LLM이 결과를 받아 다음 단계 실행 반복...

핵심: Skill은 LLM에게 "무엇을 해야 하는지"를 가르치고, Tool은 LLM이 결정한 행동을 실제로 실행합니다. 이 분리 덕분에 코드 한 줄 없이 마크다운만 작성해도 LLM의 행동 패턴을 완전히 바꿀 수 있습니다.