Logo
Published on

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

Authors

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


This article is mostly written by Cluade Code

목차

  1. 프로젝트 개요
  2. 기술 스택
  3. 전체 아키텍처
  4. 핵심 모듈 구조
  5. 메시지 처리 파이프라인
  6. Gateway 서버 상세
  7. Agent 엔진
  8. 채널 시스템
  9. 설정 시스템
  10. 플러그인 & 확장 시스템
  11. 핵심 데이터 구조
  12. 레이어별 의존 관계
  13. 일반 LLM과의 차별점
  14. 디렉토리 트리
  15. 핵심 개념 설명
  16. 기술적 계보 & 이후 동향
  17. Q&A: 실제 사용 시나리오
  18. Skill 시스템 심층 분석

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 코딩 에이전트에 위임하는 방법을 가르칩니다:

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

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

### 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의 행동 패턴을 완전히 바꿀 수 있습니다.