OpenClaw 4계층 아키텍처 분석 – LLM Agent 구조와 실행 흐름

AI 에이전트를 다루다 보면 결국 이런 질문에 도달한다. “챗봇이랑 에이전트가 정확히 뭐가 다른 거지?” 챗GPT에 질문을 던져도 답을 해주고, 오픈클로에 질문을 던져도 답을 해준다. 겉보기엔 비슷하다. 하지만 내부 구조를 들여다보면 완전히 다른 세계다. 내가 메시지를 보내면 알아서 판단하고, 도구를 선택하고, 실행하고, 결과를 돌려준다. 이 과정이 어떤 구조 위에서 돌아가는 건지, 오늘은 그 속을 제대로 열어보려 한다. 오픈클로가 처음이라면 오픈클로 완벽 가이드를 먼저 읽어보길 추천한다.

오픈클로 설치방법 링크 – 오픈클로(OpenClaw) 설치 방법 및 첫 대화 시작 방법

챗봇에서 에이전트까지, AI 구조의 진화

AI 시스템의 발전을 네 단계로 나눌 수 있다.

가장 기본 형태인 일반 LLM Chat은 프롬프트를 받아 텍스트를 생성해 돌려주는 구조다. 우리가 쓰는 챗GPT나 클로드 웹이 여기에 해당한다. “회의 잡아줘”라고 해도 방법만 알려줄 뿐, 실제 캘린더에 등록하지는 못한다. 외부 세계와 상호작용하는 능력이 전혀 없다.

두 번째 단계인 Tool Calling LLM에서는 LLM이 외부 도구를 호출할 수 있다. “서울 날씨”를 물으면 API를 호출해 실시간 데이터를 가져온다. 하지만 한 번의 요청에 한 번의 호출이고, 다음 단계는 사람이 지시해야 한다. 주도권이 여전히 사람에게 있다.

세 번째 Autonomous Agent부터 게임이 바뀐다. 에이전트는 목표를 받으면 스스로 계획을 세우고, 여러 도구를 순차적으로 호출하며, 중간 결과를 평가해 다음 행동을 결정한다. “스케줄 정리하고 빈 시간에 회의 잡아줘”라고 하면 캘린더 확인부터 참석자 연락까지 자율적으로 처리한다. 오픈클로가 바로 이 단계의 구현체다.

네 번째 Multi-Agent Orchestration은 전문화된 여러 에이전트가 역할을 나눠 협업하는 단계다. 오픈클로의 멀티 에이전트 라우팅이 이를 지원한다. 알트먼이 “미래는 극도로 멀티 에이전트 환경”이라고 한 것이 이 단계를 가리킨다.

OpenClaw 4계층 아키텍처 개요

오픈클로의 공식 문서와 소스코드를 분석해보면, 내부 구조가 명확하게 네 개의 계층으로 분리되어 있다는 걸 알 수 있다. 각 계층이 뚜렷한 책임 영역을 갖고 있고, 이 분리 덕분에 한 계층에 문제가 생겨도 다른 계층에 영향을 주지 않는다. 오픈클로를 단순한 챗봇 래퍼가 아니라 “AI 에이전트를 위한 운영체제”라고 부르는 이유가 여기에 있다. 하나씩 뜯어보자.

1계층 – 게이트웨이 컨트롤 플레인

게이트웨이는 오픈클로의 심장이다. Node.js 22 이상에서 실행되는 단일 데몬 프로세스로, 기본적으로 127.0.0.1:18789 포트에 바인딩된다. 루프백 전용으로 바인딩하는 건 보안을 위한 의도적인 설계다. 외부에서 직접 접근할 수 없게 막아놓고, 필요한 경우에만 토큰 인증이나 패스워드 인증을 거쳐 원격 접속을 허용한다.

이 게이트웨이가 하는 일을 구체적으로 보면 꽤 많다. 왓츠앱은 Baileys 라이브러리를 통해, 텔레그램은 grammY를 통해, 디스코드는 discord.js를 통해 각각 연결된다. CLI, 웹 UI, 모바일 앱 등 모든 클라이언트도 웹소켓으로 여기에 붙는다. 메시지가 들어오면 접근 제어를 거치고, 어떤 세션이 처리할지 결정하고, 적절한 에이전트에게 디스패치한다. 세션 상태, 프레즌스 정보, 헬스 모니터링, 크론 잡까지 시스템 전체의 상태를 총괄한다.

설계 원칙 몇 가지가 인상적이다. 먼저, 호스트당 게이트웨이는 정확히 하나만 존재한다. 왓츠앱 프로토콜이 엄격하게 단일 기기 방식이기 때문에 복수의 게이트웨이가 뜨면 세션 충돌이 발생한다. 그리고 프로토콜 전체가 타입 세이프하다. 모든 웹소켓 프레임이 TypeBox 정의에서 생성된 JSON Schema로 검증되기 때문에, 클라이언트가 잘못된 데이터를 보내면 즉시 거부된다. 폴링 방식이 아니라 이벤트 기반으로 동작한다는 점도 중요하다. 클라이언트가 agent, presence, health, tick 같은 이벤트를 구독하는 방식이라, 계속 “새 소식 있어?”하고 물어볼 필요가 없다. 부수 효과가 있는 모든 작업에는 멱등성 키가 필요하다. 재시도 로직이 안전해지고 중복 실행을 방지할 수 있다.

게이트웨이에 접속하는 컨트롤 인터페이스도 다양하다. 웹 UI는 Lit 기반 웹 컴포넌트로 구축되어 게이트웨이가 직접 서빙한다. 별도의 웹 서버가 필요 없다. CLI는 Commander.js 기반으로 구현되어 있어서, 게이트웨이 시작, 에이전트 직접 호출, 채널 로그인, 메시지 전송, 진단까지 터미널에서 전부 가능하다. macOS 앱은 Swift로 작성되어 메뉴바에 상주하면서 게이트웨이 생명주기를 관리하고, 음성 웨이크 기능과 네이티브 웹킷 뷰를 내장한다. iOS와 안드로이드 모바일 노드는 웹소켓으로 게이트웨이에 연결되면서, 카메라, 화면 녹화, 위치 서비스 같은 기기 고유 기능을 에이전트에게 노출한다. 스마트폰이 에이전트의 확장 도구가 되는 셈이다.

2계층 – 채널 어댑터와 통합 계층

통합 계층의 핵심 구성 요소는 채널 어댑터다. 각 메시징 플랫폼마다 전용 어댑터가 존재하고, 내장 어댑터는 소스코드의 src/telegram/, src/discord/, src/slack/, src/imessage/ 같은 디렉토리에 위치한다. 추가 플랫폼은 채널 플러그인으로 확장할 수 있다.

채널 어댑터가 처리하는 책임은 네 가지다. 첫째는 인증이다. 왓츠앱은 Baileys 라이브러리를 통한 QR 코드 페어링 방식이고, 자격증명은 ~/.openclaw/credentials에 저장된다. 텔레그램과 디스코드는 봇 토큰을 환경변수로 받는다. 아이메시지는 네이티브 macOS 통합이 필요해서 서명된 Messages 앱이 있어야 한다. 플랫폼마다 인증 방식이 완전히 다르지만, 어댑터가 이 차이를 흡수한다.

둘째는 인바운드 메시지 파싱이다. 각 플랫폼의 데이터 포맷은 제각각이다. 어댑터는 텍스트를 추출하고, 미디어 첨부파일(이미지, 오디오, 비디오, 문서)을 처리하고, 리액션과 이모지를 해석하고, 쓰레드나 답장 컨텍스트를 유지한다. 이 정규화 덕분에 오픈클로의 나머지 부분은 메시지가 왓츠앱에서 왔는지 디스코드에서 왔는지 신경 쓸 필요가 없다.

셋째는 접근 제어다. 보안이 채널 레벨에서 시작되는 지점이다. 허용 목록(allowlist)으로 어떤 전화번호나 유저네임이 봇과 상호작용할 수 있는지 지정한다. DM 정책은 알 수 없는 발신자의 다이렉트 메시지를 어떻게 처리할지 결정하는데, 기본값은 페어링 모드로 승인 전까지 메시지를 처리하지 않는다. 그룹 정책에서는 멘션 요구 여부나 그룹별 허용 목록 같은 추가 레이어를 설정할 수 있다.

넷째는 아웃바운드 메시지 포맷팅이다. 각 플랫폼은 고유한 마크다운 방언, 메시지 크기 제한, 미디어 업로드 API를 갖고 있다. 어댑터가 긴 메시지를 플랫폼 제한에 맞춰 청크 단위로 분할하고, 마크다운을 적절히 렌더링하고, 미디어 파일을 업로드하고, 타이핑 인디케이터까지 관리한다.

통합 계층에는 플러그인 시스템도 포함된다. 오픈클로는 코어 코드를 수정하지 않고도 네 가지 방식으로 확장할 수 있도록 설계되어 있다. 채널 플러그인으로 새로운 메시징 플랫폼을 추가하고, 메모리 플러그인으로 벡터 스토어나 지식 그래프 같은 대체 스토리지 백엔드를 연결하고, 도구 플러그인으로 빌트인 도구 외의 커스텀 기능을 추가하고, 프로바이더 플러그인으로 셀프 호스팅 LLM이나 커스텀 모델을 연결한다. 플러그인 로더가 워크스페이스 패키지의 openclaw.extensions 필드를 스캔해서 자동으로 발견하고 로딩하는 구조다.

3계층 – 실행 계층과 레인 큐 시스템

실행 계층은 에이전트가 실제로 세상과 상호작용하는 곳이다. 쉘 명령 실행, 파일 읽기와 쓰기, 브라우저 자동화, API 호출 등 “행동”이 일어나는 계층이다.

이 계층에서 가장 주목해야 할 아키텍처적 결정이 레인 큐(Lane Queue) 시스템이다. 에이전트 개발에서 가장 흔한 실패가 비동기 작업의 무질서한 실행으로 인한 상태 오염인데, 오픈클로는 이걸 “기본 직렬, 명시적 병렬(Default Serial, Explicit Parallel)” 원칙으로 해결했다. 각 세션은 고유한 레인을 갖고, 레인 안에서 작업이 하나씩 순차적으로 실행된다. “이메일 보내기”와 “캘린더 등록”이 동시에 돌면서 서로의 결과를 덮어쓰는 일이 원천적으로 차단된다. 로그가 깔끔하게 유지되고, 장애가 발생해도 해당 세션 안에서 격리된다.

병렬 실행이 꼭 필요한 경우에는 명시적으로 병렬 레인을 지정할 수 있다. 다만 크론 작업이나 백그라운드 헬스체크처럼 상태를 변경하지 않는, 멱등성이 보장된 작업만 병렬로 내보내는 게 원칙이다.

세션 관리도 실행 계층의 중요한 역할이다. 메시지가 들어오면 런타임이 먼저 어떤 세션이 처리할지 결정한다. 사용자의 다이렉트 메시지는 main 세션으로, 채널을 통한 DM은 dm:채널:아이디 형태로, 그룹 채팅은 group:채널:아이디 형태로 매핑된다. 여기서 중요한 건 세션이 단순한 식별자가 아니라 보안 경계라는 점이다. 세션 타입별로 다른 권한과 샌드박싱 규칙을 적용할 수 있다. 예를 들어 main 세션은 호스트에서 도구를 직접 실행할 수 있지만, dm이나 group 세션은 도커 격리 환경에서만 실행되도록 제한할 수 있다.

브라우저 자동화에서도 독특한 설계가 드러난다. 스크린샷을 찍어 이미지로 분석하는 대신, 오픈클로는 시맨틱 스냅샷(Semantic Snapshot) 방식을 사용한다. 웹페이지의 접근성 트리(Accessibility Tree)를 파싱해서 텍스트 기반으로 페이지 구조를 이해하는 것이다. 원래 시각장애인용 스크린리더가 쓰는 정보인데, 이걸 LLM에 넘기면 이미지 분석 대비 토큰 소모가 대폭 줄어들면서 정확도는 오히려 높아진다. 버튼 위치, 폼 필드 이름, 링크 텍스트를 정확하게 파악할 수 있다.

4계층 – 에이전트 런타임과 지능 계층

네 번째 계층이 에이전트 런타임이다. 소스코드에서 src/agents/piembeddedrunner.ts에 구현되어 있고, 실제 AI 상호작용이 일어나는 곳이다. 여기서 흥미로운 아키텍처적 결정이 하나 드러난다. 오픈클로는 자체 에이전트 런타임을 구현하지 않았다. 핵심 에이전트 루프, 즉 도구 호출과 컨텍스트 관리, LLM 상호작용은 Pi 에이전트 프레임워크(@mariozechner/pi-agent-core)가 담당한다. 오픈클로는 그 위에 게이트웨이, 오케스트레이션, 통합 계층을 구축했다.

이 분리가 말해주는 것이 있다. AI 에이전트의 진짜 어려운 문제는 “생각하고 행동하는” 에이전트 루프 자체가 아니라, 채널 정규화, 세션 관리, 메모리 지속성, 스킬 확장성, 보안이라는 주변의 모든 것이라는 프로젝트의 핵심 철학이다. Pi가 “생각하고 행동하는” 사이클을 처리하면, 오픈클로가 “연결하고, 큐잉하고, 기억하고, 확장하는” 계층을 맡는다.

에이전트 런타임은 매 턴마다 네 가지 작업을 수행한다. 세션 해석, 컨텍스트 조립, 모델 응답 스트리밍과 도구 호출 실행, 그리고 상태 디스크 저장이다.

컨텍스트 조립 과정이 특히 정교하다. 런타임은 여러 소스를 조합해서 최종 시스템 프롬프트를 만든다. AGENTS.md는 에이전트의 운영 기본선으로, 전역 제약 조건과 모든 세션에 적용되는 규칙이 담긴다. SOUL.md는 성격과 말투를 정의한다. TOOLS.md는 사용자 환경에서 도구를 어떻게 사용할지에 대한 개인 노트다. 여기에 세션 히스토리, 스킬 정의(skills/스킬명/SKILL.md), 시맨틱 검색으로 가져온 관련 과거 대화가 동적으로 결합된다.

중요한 디테일이 하나 있다. 스킬 디스커버리와 스킬 인젝션이 구분된다는 점이다. 오픈클로는 런타임에 스킬을 발견할 수 있지만, 모든 스킬을 무차별적으로 프롬프트에 주입하지 않는다. 현재 턴에 관련된 스킬만 선택적으로 주입해서, 프롬프트가 비대해지면서 모델 성능이 떨어지는 걸 방지한다. 100개 이상의 스킬이 등록되어 있어도 실제로 프롬프트에 들어가는 건 해당 요청에 필요한 것만이다.

모델 응답이 스트리밍되는 동안, 런타임은 도구 호출을 가로채서 실행한다. 세션의 샌드박스 정책에 따라 도커 격리 환경에서 실행될 수도 있다. 각 도구 실행 결과가 진행 중인 모델 생성에 스트리밍으로 다시 주입되고, 모델이 이를 반영해서 계속 응답을 생성한다. 턴이 완료되면 메시지, 도구 호출 결과, 기타 추적 상태가 디스크에 영속화된다.

Agent Core의 실행 흐름

사용자가 “내일 오후 3시에 팀 미팅 잡아줘”라고 보냈을 때 내부에서 일어나는 일을 따라가 보자.

먼저 채널 어댑터가 메시지를 수신해 표준 이벤트로 변환한다. 게이트웨이가 세션을 식별하고, 이전 대화 기록과 장기 메모리, 페르소나 설정(SOUL.md) 등을 컨텍스트로 로딩한다. 이 컨텍스트와 메시지가 Pi 에이전트 런타임으로 전달되면, 모델 리졸버가 LLM을 호출한다. 주 모델이 실패하면 자동으로 대체 모델로 전환하는 구조다.

LLM이 캘린더 스킬을 호출하기로 결정하면 실행 계층에서 해당 스킬이 동작한다. 매 단계의 도구 입출력이 “증거 우선 로깅”으로 기록된다. 다음 단계 진행 전에 반드시 현재 결과를 기록하는 원칙이다. 실행 결과가 다시 LLM으로 돌아가고, 성공이면 응답을, 실패면 대안을 찾아 재시도한다. 이 자동 판단과 재시도가 단순 도구 호출 챗봇과의 결정적 차이다.

전체 흐름을 정리하면 이렇다.

사용자 메시지 → 채널 어댑터(표준화) → 게이트웨이(세션 매칭) → 컨텍스트 로딩 → Pi 런타임(LLM 호출) → 의도 분석 → 도구 선택 → 스킬 실행 → 결과 로깅 → LLM 평가 → 응답 생성 → 사용자

메모리 시스템, 에이전트의 기억은 어떻게 작동하나

오픈클로의 메모리는 세 층위로 나뉜다. 세션 메모리는 현재 대화의 맥락을 유지하고, 장기 메모리는 사용자의 선호도와 습관이 마크다운 파일로 저장된다. 에피소드 메모리는 일별 JSONL 로그로, 에이전트 행동의 감사와 재현을 가능하게 한다. 모두 파일 기반이라 디버깅이 쉽고 이식성이 높다. 벡터 DB는 규모가 커졌을 때 메모리 플러그인으로 추가하면 된다.

메모리 검색에는 임베딩 기반 시맨틱 서치가 쓰인다. 대화가 길어지면 전체 히스토리를 프롬프트에 넣을 수 없기 때문에, 현재 질문과 의미적으로 관련된 과거 대화만 선별해서 컨텍스트에 주입한다. 기본 스토리지는 SQLite이고, 워크스페이스의 메모리 디렉토리에 인덱스 파일이 저장된다. 끊임없이 커지는 대화 기록 대신 가장 관련성 높은 역사적 맥락만 모델에게 보여주는 방식이라, 토큰 효율과 응답 품질을 동시에 확보할 수 있다.

보안 아키텍처의 세 요소

오픈클로의 보안 모델은 Brain(LLM의 판단), Hands(실행 계층의 행동), Guardrails(중재자) 세 요소로 구성된다. 가드레일의 핵심은 결정론적이라는 점이다. LLM이 아무리 교묘한 프롬프트를 만들어도 정책 엔진을 우회할 수 없다. 능력 토큰은 명시적으로 발급되고, 시간 제한이 있으며, 언제든 철회 가능하다.

다만 현재 기본 설정에서는 보안 기능이 모두 활성화되어 있지 않다. 이것이 보안 기업들이 우려하는 지점이고, 슈타인버거가 오픈AI에서 가장 먼저 해결하려는 과제이기도 하다.

마무리

오픈클로의 아키텍처를 한마디로 정리하면 이렇다. LLM은 지능을 제공하고, 오픈클로는 운영체제를 제공한다. 세션 관리, 메모리 지속성, 도구 샌드박싱, 메시지 라우팅, 동시성 제어 같은 시스템 레벨의 문제들은 프롬프트로 해결할 수 없다. 오픈클로는 이것들을 구조화된 실행 환경으로 풀어냈고, 그래서 실제로 작동하는 에이전트가 됐다. MIT 라이선스 소스코드를 직접 읽어보면 여기서 설명한 구조를 코드 레벨에서 확인할 수 있다. AI 에이전트를 만들고 싶은 개발자라면, 오픈클로는 현시점에서 가장 실전적인 아키텍처 교과서가 될 것이다.

오픈클로 탄생 배경, 핵심 특징은 아래 링크를 참조해 주세요.

오픈클로(OpenClaw) – 챗봇을 넘어 행동하는 AI 에이전트

Leave a Comment