ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OpenClaw Gateway - Pi Agent 시스템 분석 리포트
    Knowledge Base/Foundations 2026. 1. 31. 15:23

    https://docs.openclaw.ai/index#how-it-works

     

    Author: Claude Code, mangowhoiscloud
    Purpose: LLM 에이전트/어시스턴스 제작에 활용할 수 있는 아키텍처 인사이트 도출
    Target: https://github.com/openclaw/openclaw
    Date: 2026-01-31


    Executive Summary

    OpenClaw는 Gateway + Pi Agent 이중 구조의 멀티채널 AI 어시스턴트 플랫폼입니다.
    LangGraph를 사용하지 않고 TypeScript로 자체 구현된 에이전트 시스템으로, 다음과 같은 핵심 특징을 가집니다:

    특징 설명
    Gateway 중심 모든 채널/에이전트의 중앙 제어 플레인
    Session 격리 agent:{id}:{context} 형식의 세션 키로 컨텍스트 분리
    Multi-Agent Routing Binding 기반 결정적 라우팅
    Sub-agent Spawn 비동기 병렬 작업 + Announce 패턴
    Policy-based Tool Control 다층 정책에 의한 도구 접근 제어

    Part 1: Gateway 아키텍처

    1.1 시스템 구조

    ┌─────────────────────────────────────────────────────────────────────────────┐
    │                           OpenClaw Gateway                                   │
    ├─────────────────────────────────────────────────────────────────────────────┤
    │                                                                              │
    │  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐     │
    │  │   HTTP      │   │  WebSocket  │   │   OpenAI    │   │  Control    │     │
    │  │   Server    │   │   Server    │   │   Compat    │   │     UI      │     │
    │  └──────┬──────┘   └──────┬──────┘   └──────┬──────┘   └──────┬──────┘     │
    │         │                 │                 │                 │             │
    │         └─────────────────┴─────────────────┴─────────────────┘             │
    │                                    │                                        │
    │                    ┌───────────────┴───────────────┐                       │
    │                    │       Gateway Methods          │                       │
    │                    │   (RPC Handler Routing)        │                       │
    │                    └───────────────┬───────────────┘                       │
    │                                    │                                        │
    │         ┌──────────────────────────┼──────────────────────────┐            │
    │         │                          │                          │            │
    │  ┌──────▼──────┐   ┌───────────────▼───────────────┐   ┌──────▼──────┐    │
    │  │   Session   │   │       Channel Manager         │   │    Node     │    │
    │  │   Manager   │   │  ┌─────┬─────┬─────┬─────┐   │   │   Registry  │    │
    │  │             │   │  │ TG  │ WA  │ DC  │ ... │   │   │             │    │
    │  └─────────────┘   │  └─────┴─────┴─────┴─────┘   │   └─────────────┘    │
    │                    └───────────────────────────────┘                       │
    │                                                                              │
    └─────────────────────────────────────────────────────────────────────────────┘

    1.2 Gateway Protocol

    Gateway는 WebSocket 기반 JSON 프로토콜을 사용합니다.
    프레임 타입:

    // Request
    { type: "req", id: string, method: string, params?: unknown }
    
    // Response
    { type: "res", id: string, ok: boolean, payload?: unknown, error?: ErrorShape }
    
    // Event (브로드캐스트)
    { type: "event", event: string, payload?: unknown, seq?: number }

    핸드셰이크 흐름:

    1. 서버 → 클라이언트: connect.challenge (nonce + timestamp)
    2. 클라이언트 → 서버: connect (역할, 범위, 장치 신원)
    3. 서버 → 클라이언트: hello-ok (승인 + 정책)

    1.3 Session Key 설계

    세션 키는 에이전트, 채널, 피어를 조합한 계층적 구조입니다:

    agent:{agentId}:{context}
    
    Examples:
    ├── agent:main:main                    # 메인 에이전트 기본 세션
    ├── agent:main:telegram:dm:123456      # 텔레그램 DM 세션
    ├── agent:work:discord:group:789       # 디스코드 그룹 세션
    └── agent:main:subagent:run-abc123     # 서브에이전트 세션

    세션 키 생성 함수:

    // 메인 세션
    buildAgentMainSessionKey({ agentId: "main", mainKey: "main" })
    // → "agent:main:main"
    
    // 피어 세션 (DM/그룹)
    buildAgentPeerSessionKey({
      agentId: "main",
      channel: "telegram",
      peerKind: "dm",
      peerId: "123456",
      dmScope: "per-peer"
    })
    // → "agent:main:telegram:dm:123456"

    1.4 Channel Manager

    7개 이상의 메시징 플랫폼을 플러그인 구조로 통합:

    채널 SDK 특징
    WhatsApp @whiskeysockets/baileys Multi-account 지원
    Telegram grammy Bot API + 그룹 라우팅
    Discord discord.js Guild/Channel 바인딩
    Slack @slack/bolt Team/Channel 분리
    Signal signal-cli E2E 암호화
    iMessage 자체 구현 macOS 전용
    + Extensions Matrix, Teams, Zalo 플러그인 확장

    채널 메시지 흐름:

    [External Channel] → Channel Plugin → Session Key Builder → Agent Runner
                                                  ↓
                                  buildAgentPeerSessionKey()
                                                  ↓
                                  runEmbeddedPiAgent()

    1.5 Multi-Agent Routing (Bindings)

    Binding은 인바운드 메시지를 특정 에이전트로 라우팅하는 규칙입니다:

    {
      agents: {
        list: [
          { id: "home", workspace: "~/.openclaw/workspace-home" },
          { id: "work", workspace: "~/.openclaw/workspace-work" }
        ]
      },
      bindings: [
        // 채널별 라우팅
        { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
        { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },
    
        // 피어별 오버라이드 (가장 구체적인 매치가 우선)
        { agentId: "work", match: {
          channel: "whatsapp",
          peer: { kind: "group", id: "work-group@g.us" }
        }}
      ]
    }

    라우팅 우선순위 (Most-specific wins):

    1. peer 매치 (정확한 DM/그룹)
    2. guildId (Discord)
    3. teamId (Slack)
    4. accountId 매치
    5. 채널 레벨 매치
    6. 기본 에이전트

    Part 2: Pi Agent 시스템

    2.1 아키텍처 개요

    Pi Agent는 LangGraph 없이 자체 구현된 에이전트 런타임입니다:

    ┌─────────────────────────────────────────────────────────────────────────────┐
    │                           Pi Agent System                                    │
    ├─────────────────────────────────────────────────────────────────────────────┤
    │                                                                              │
    │  ┌─────────────────────────────────────────────────────────────────────┐   │
    │  │                    runEmbeddedPiAgent()                              │   │
    │  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                  │   │
    │  │  │   Auth      │  │   Model     │  │   Attempt   │                  │   │
    │  │  │   Profile   │→ │   Resolver  │→ │   Loop      │                  │   │
    │  │  │   Rotation  │  │             │  │             │                  │   │
    │  │  └─────────────┘  └─────────────┘  └──────┬──────┘                  │   │
    │  └───────────────────────────────────────────┼──────────────────────────┘   │
    │                                              │                              │
    │  ┌───────────────────────────────────────────▼──────────────────────────┐   │
    │  │                    runEmbeddedAttempt()                              │   │
    │  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │   │
    │  │  │  Sandbox    │  │   Tool      │  │  System     │  │  Session    │ │   │
    │  │  │  Context    │→ │  Creation   │→ │  Prompt     │→ │  Execute    │ │   │
    │  │  └─────────────┘  └─────────────┘  └─────────────┘  └──────┬──────┘ │   │
    │  └────────────────────────────────────────────────────────────┼─────────┘   │
    │                                                               │             │
    │  ┌────────────────────────────────────────────────────────────▼─────────┐   │
    │  │                subscribeEmbeddedPiSession()                          │   │
    │  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐             │   │
    │  │  │ message  │  │  tool    │  │lifecycle │  │ announce │             │   │
    │  │  │ stream   │  │ events   │  │  events  │  │  events  │             │   │
    │  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘             │   │
    │  └──────────────────────────────────────────────────────────────────────┘   │
    │                                                                              │
    └─────────────────────────────────────────────────────────────────────────────┘

    2.2 Agent Loop 실행 흐름

    5단계 실행 사이클:

    1. 입력 처리
       └── agent RPC → 파라미터 검증 → 세션 해석 → {runId, acceptedAt} 반환
    
    2. 모델 준비
       └── agentCommand → 모델/사고 모드 결정 → 스킬 로드 → runEmbeddedPiAgent 호출
    
    3. 핵심 루프 (runEmbeddedPiAgent)
       ├── Lane Queueing (세션 + 글로벌 레인)
       ├── Auth Profile Resolution (failover 지원)
       └── Attempt Loop:
           ├── 모델 생각 → 도구 호출 → 스트리밍
           ├── Context Overflow → Auto-compaction
           ├── Auth 실패 → Profile Rotation
           └── Thinking 미지원 → Level Fallback
    
    4. 이벤트 브릿징 (subscribeEmbeddedPiSession)
       ├── 도구 이벤트 → stream: "tool"
       ├── 텍스트 응답 → stream: "assistant"
       └── 생명주기 → stream: "lifecycle" (start/end/error)
    
    5. 완료 대기
       └── agent.wait → lifecycle end/error 대기 → 최종 상태 반환

    2.3 Tool Execution 메커니즘

    도구 생성 (createOpenClawCodingTools):

    // Core Tools
    const coreTools = [
      // 파일 조작
      "read", "write", "edit", "apply_patch",
      // 쉘 실행
      "exec", "process",
      // 브라우저/캔버스
      "browser", "canvas",
      // 세션 관리
      "sessions_spawn", "sessions_send", "sessions_list", "sessions_history",
      // 플랫폼 기능
      "message", "cron", "gateway", "nodes"
    ];

    Policy Resolution Chain (다층 필터링):

    Profile Policy
        ↓
    Global Policy
        ↓
    Agent Policy
        ↓
    Group Policy (채널 레벨)
        ↓
    Sandbox Policy
        ↓
    Subagent Policy
        ↓
    [최종 허용된 도구 목록]

    도구 실행 이벤트 흐름:

    Tool Call Decision (LLM)
            ↓
    handleToolExecutionStart()
    ├── Block reply buffer flush
    ├── Tool meta 추적
    ├── Agent event 발행 (stream: "tool", phase: "start")
    └── Messaging tool 추적 (중복 감지)
            ↓
        [도구 실행]
            ↓
    handleToolExecutionEnd()
    ├── 결과 정리 및 에러 추적
    ├── Messaging tool 커밋
    └── Agent event 발행 (stream: "tool", phase: "result")

    2.4 Sub-agent Spawn 패턴

    핵심 개념: 백그라운드 에이전트 실행 → 완료 시 결과 Announce

    ┌─────────────────────────────────────────────────────────────────────────────┐
    │                         Sub-agent Pattern                                    │
    ├─────────────────────────────────────────────────────────────────────────────┤
    │                                                                              │
    │    ┌─────────────────────────────────────────────────────────┐              │
    │    │                  Parent Agent                            │              │
    │    │               (agent:main:main)                          │              │
    │    │                                                          │              │
    │    │   sessions_spawn({                                       │              │
    │    │     task: "Reddit 감성 분석",                            │              │
    │    │     label: "social-scout",                               │              │
    │    │     model: "sonnet",                                     │              │
    │    │     cleanup: "keep"                                      │              │
    │    │   })                                                     │              │
    │    └────────────────────────┬────────────────────────────────┘              │
    │                             │                                                │
    │              ┌──────────────┴──────────────┐                                │
    │              │    비동기 즉시 반환          │                                │
    │              │  {status: "accepted",        │                                │
    │              │   runId: "...",              │                                │
    │              │   childSessionKey: "..."}    │                                │
    │              └──────────────┬──────────────┘                                │
    │                             │                                                │
    │    ┌────────────────────────▼────────────────────────┐                      │
    │    │              Sub-agent                           │                      │
    │    │    (agent:main:subagent:run-abc123)              │                      │
    │    │                                                  │                      │
    │    │    • 독립 세션에서 실행                          │                      │
    │    │    • 세션 도구 미제공 (격리)                     │                      │
    │    │    • 다른 sub-agent spawn 불가                   │                      │
    │    └────────────────────────┬────────────────────────┘                      │
    │                             │                                                │
    │              ┌──────────────▼──────────────┐                                │
    │              │         완료 시              │                                │
    │              │    Announce Flow            │                                │
    │              │                              │                                │
    │              │  Status: success/error       │                                │
    │              │  Result: 분석 결과 요약      │                                │
    │              │  Notes: 실행 시간, 토큰 등   │                                │
    │              └──────────────┬──────────────┘                                │
    │                             │                                                │
    │                             ▼                                                │
    │                   [Parent 세션에 결과 전달]                                  │
    │                                                                              │
    └─────────────────────────────────────────────────────────────────────────────┘

    Subagent Registry:

    type SubagentRunRecord = {
      runId: string;
      childSessionKey: string;           // agent:main:subagent:run-xxx
      requesterSessionKey: string;       // 부모 세션
      task: string;
      cleanup: "delete" | "keep";
    
      // Lifecycle
      createdAt: number;
      startedAt?: number;
      endedAt?: number;
    
      // Result
      outcome?: { status: "ok" } | { status: "error"; error?: string };
      archiveAtMs?: number;              // 자동 아카이빙 시간
    };
    
    // 글로벌 레지스트리 (프로세스 재시작 후에도 복구)
    const subagentRuns = new Map<string, SubagentRunRecord>();

    동시성 제어:

    • 전용 큐 레인: subagent
    • 기본 동시 실행 수: maxConcurrent = 8
    • 타임아웃: runTimeoutSeconds 지원
    • 자동 아카이빙: 60분 후

    2.5 Skill 시스템

    스킬은 워크스페이스별로 관리되는 확장 기능입니다:

    스킬 로딩 우선순위 (낮음 → 높음):
    1. Bundled Skills     (openclaw-bundled)
    2. Extra Dirs         (config에서 지정)
    3. Managed Skills     (~/.openclaw/skills)
    4. Workspace Skills   (./skills)

    스킬 구조:

    type SkillEntry = {
      skill: Skill;                       // 스킬 정의
      frontmatter: ParsedSkillFrontmatter; // YAML 메타데이터
      metadata: OpenClawSkillMetadata;     // 런타임 메타
      invocation: SkillInvocationPolicy;   // 호출 정책
    };
    
    type SkillSnapshot = {
      prompt: string;           // 시스템 프롬프트에 주입
      skills: Array<{ name: string; primaryEnv?: string }>;
      resolvedSkills: Skill[];
    };

    Part 3: 핵심 설계 패턴

    3.1 사용된 패턴 요약

    Registry NodeRegistry, ChannelManager, SubagentRegistry 런타임 컴포넌트 등록/조회
    Factory createOpenClawTools, createChannelManager 복잡한 객체 생성 캡슐화
    Strategy Tool Policy, Auth Profile 런타임에 동작 전환
    Observer onAgentEvent, broadcast 이벤트 기반 통신
    Command Gateway Methods (RPC) 요청 처리 캡슐화
    Plugin Channel/Tool Plugins 확장 가능한 아키텍처
    Queue/Lane Session Lane, Global Lane 동시성 제어

    3.2 Failover 전략

    ┌─────────────────────────────────────────────────────────────────────────────┐
    │                         Failover Strategies                                  │
    ├─────────────────────────────────────────────────────────────────────────────┤
    │                                                                              │
    │  1. Auth Profile Rotation                                                   │
    │     Rate Limit → 다음 프로필 → 재시도                                       │
    │     Auth Error → 다음 프로필 → 재시도                                       │
    │                                                                              │
    │  2. Thinking Level Fallback                                                 │
    │     high 미지원 → medium → low → off                                        │
    │                                                                              │
    │  3. Context Overflow Handling                                               │
    │     Overflow 감지 → Auto-compaction → 압축 후 재시도                        │
    │                                                                              │
    │  4. Model Failover                                                          │
    │     Primary 실패 → Fallback 모델 → 재시도                                   │
    │                                                                              │
    └─────────────────────────────────────────────────────────────────────────────┘

    Part 4: 핵심 차별점

    OpenClaw가 메시징 채널 통합에 최적화되어 있습니다.

    입력 사용자 메시지
    출력 대화 응답
    세션 사용자별 대화
    Sub-agent 백그라운드 작업

    결론

    OpenClaw의 아키텍처에서 추출할 수 있는 인사이트

    1. Gateway 중심 설계: 모든 에이전트/데이터 소스의 중앙 제어점
    2. Session Key 계층 구조: IP별/분석 단계별 컨텍스트 격리
    3. Binding 기반 라우팅: 데이터 소스 → 전문 에이전트 결정적 매핑
    4. Sub-agent Spawn + Announce: 병렬 분석 실행 및 결과 집계 (LangGraph Send API-> Aggregation과 유사)
    5. Policy-based Tool Control: API/도구별 접근 권한 세분화

    이 패턴들은 LangGraph의 StateGraph, Checkpointer, parallel nodes로 자연스럽게 대응됩니다.


    References

    댓글

ABOUT ME

🎓 부산대학교 정보컴퓨터공학과 학사: 2017.03 - 2023.08
☁️ Rakuten Symphony Jr. Cloud Engineer: 2024.12.09 - 2025.08.31
🏆 2025 AI 새싹톤 우수상 수상: 2025.10.30 - 2025.12.02
🌏 이코에코(Eco²) 백엔드/인프라 고도화 중: 2025.12 - Present

Designed by Mango