다들 OpenClaw(ex-Clawdbot) 이야기는 많이 하지만, 정작 어떻게 돌아가는지는 잘 모릅니다.

TMT

https://x.com/Hesamation/status/2017038553058857413

저는 OpenClaw(일명 Moltbot, Clawdbot)의 아키텍처를 살펴보며, 에이전트 실행, 툴 사용, 브라우저 처리 등을 어떻게 다루는지 분석했습니다. 여기에는 AI 엔지니어들이 배울 수 있는 점이 매우 많습니다.

Clawd가 내부적으로 어떻게 동작하는지를 이해하면, 이 시스템과 그 능력을 더 잘 파악할 수 있고, 무엇보다도 이 시스템이 잘하는 것과 못하는 것이 무엇인지 알 수 있습니다.

이 탐구는 Clawd가 메모리를 어떻게 다루는지, 그리고 그 신뢰성이 어느 정도인지에 대한 개인적인 호기심에서 출발했습니다.

이 글에서는 Clawd가 어떻게 동작하는지 겉핥기 수준에서 전체적인 구조를 살펴보겠습니다.

Clawd의 기술

모두가 Clawd를 로컬에서 실행하거나 모델 API를 통해 실행할 수 있고 휴대폰처럼 쉽게 접근할 수 있는 개인 비서로 알고 있습니다. 하지만, 기술적으로 보면 Clawd는 도대체 무엇일까요?

핵심적으로 Clawdbot은 TypeScript로 작성된 CLI 애플리케이션입니다.

이것은 Python도, Next.js도, 웹 애플리케이션도 아닙니다.

이것은 다음과 같은 일을 수행하는 하나의 프로세스입니다.

  • 여러분의 머신에서 실행되며, 게이트웨이 서버를 열어 모든 채널 연결(텔레그램, 왓츠앱, 슬랙 등)을 처리하고,
  • LLM API(Anthropic, OpenAI, 로컬 모델 등)에 요청을 보내며,
  • 로컬에서 각종 도구를 실행하고,
  • 여러분이 컴퓨터에서 하고 싶어 하는 거의 모든 일을 대신 수행합니다.

아키텍처

아키텍처를 더 쉽게 설명하기 위해, Clawd에게 메시지를 보낸 순간부터 응답을 받기까지 어떤 일이 일어나는지 예시로 살펴보겠습니다.

Image

메신저에서 Clawd에게 프롬프트를 보냈을 때 내부적으로 일어나는 과정은 다음과 같습니다.

1. 채널 어댑터(Channel Adapter)

채널 어댑터는 여러분이 보낸 메시지를 받아 정규화하고(normalize), 첨부 파일을 추출하는 등의 전처리를 합니다. 서로 다른 메신저나 입력 스트림마다 전용 어댑터가 따로 존재합니다.

2. 게이트웨이 서버(Gateway Server)

게이트웨이 서버는 태스크/세션 코디네이터 역할을 하며, 여러분의 메시지를 받아 알맞은 세션으로 전달합니다. 이것이 바로 Clawd의 심장부입니다. 이 서버가 여러 겹쳐지는 요청들을 처리합니다.

연산을 직렬화하기 위해 Clawd는 lane 기반 명령 큐를 사용합니다. 각 세션은 자신만의 전용 lane을 가지고 있고, 위험도가 낮고 병렬화가 가능한 작업들은 별도의 lane(예: 크론 잡)에서 병렬로 실행될 수 있습니다.

이는 이른바 async/await 스파게티 코드 접근 방식과는 대조적입니다. 과도한 병렬화는 신뢰성을 떨어뜨리고, 디버깅 악몽을 대량으로 만들어냅니다.

기본값은 직렬 실행으로 두고, 병렬 실행은 명시적으로 선택하라

에이전트 시스템을 다뤄본 적이 있다면 어느 정도는 이미 느꼈을 것입니다. 이 통찰은 Cognition의 Don’t Build Multi-Agents 블로그 글에서도 언급됩니다.

각 에이전트마다 단순히 async 구조를 얹어두기만 하면, 서로 뒤섞인 로그와 결과물 덤프만 남게 됩니다. 로그는 읽을 수 없게 되고, 에이전트들이 상태를 공유한다면 레이스 컨디션에 대한 두려움이 개발 내내 따라다니게 됩니다.

Lane은 큐 위에 구축된 추상화이며, 직렬화가 사후 보강이 아니라 기본 아키텍처로 설계되어 있습니다. 개발자는 평범하게 코드를 작성하고, 레이스 컨디션에 대한 처리는 큐가 대신 맡습니다.

이 설계에서는 사고 방식이 **“무엇을 락으로 보호해야 하지?”**에서 **“무엇을 병렬로 돌려도 안전하지?”**로 전환됩니다.

3. 에이전트 러너(Agent Runner)

여기서부터 실제 AI가 등장합니다. 에이전트 러너는 어떤 모델을 사용할지 결정하고, 사용할 API 키를 선택합니다(어느 키도 동작하지 않으면 해당 프로필에 쿨다운을 걸고 다음 키를 시도합니다). 기본 모델이 실패하면 다른 모델로 폴백(fallback)합니다.

에이전트 러너는 사용 가능한 도구, 스킬, 메모리 정보를 모아 동적으로 시스템 프롬프트를 구성한 뒤,⁠.jsonl⁠ 파일에 저장된 세션 히스토리를 추가합니다.

그 다음 이 정보는 컨텍스트 윈도우 가드로 전달되어, 남아 있는 컨텍스트 공간이 충분한지 확인합니다. 컨텍스트가 거의 가득 차면, 세션을 압축(컨텍스트 요약)하거나, 우아하게 실패 처리합니다.

4. LLM API 호출

LLM 호출 자체는 스트리밍 방식으로 응답을 전달하며, 다양한 제공자를 포괄하는 추상화 레이어 위에서 동작합니다. 모델이 이를 지원한다면, extended thinking(확장된 사고/추론)을 요청할 수도 있습니다.

5. 에이전틱 루프(Agentic Loop)

LLM이 툴 호출(tool call) 응답을 반환하면, Clawd는 해당 툴을 로컬에서 실행하고 그 결과를 대화에 추가합니다. 이 과정은 LLM이 최종 텍스트를 반환하거나, 최대 턴 수(기본값 약 20회)에 도달할 때까지 반복됩니다.

바로 이 지점에서 마법 같은 일이 벌어집니다.

Computer Use

이에 대해서는 뒤에서 자세히 다루겠습니다.

6. 응답 경로(Response Path)

이 부분은 꽤 표준적인 구조입니다. 응답은 다시 채널을 통해 여러분에게 전달됩니다. 동시에 세션은 기본적인 JSONL 형식으로 영구 저장되며, 각 줄은 사용자 메시지, 툴 호출, 실행 결과, LLM 응답 등을 담고 있는 하나의 JSON 객체입니다. Clawd가 이를 통해 세션 기반 메모리를 유지합니다.


여기까지가 기본적인 아키텍처 개요입니다.

이제 더 핵심적인 컴포넌트들을 살펴보겠습니다.

Clawd는 어떻게 기억하는가

제대로 된 메모리 시스템이 없다면, AI 비서는 금붕어와 다를 바가 없습니다. Clawd는 다음 두 가지 시스템을 통해 이를 해결합니다.

  1. 앞에서 언급한 JSONL 형식의 세션 대화 기록.
  2. ⁠MEMORY[.]md⁠ 파일이나 ⁠memory/⁠ 폴더에 저장되는 마크다운 형식의 메모리 파일.

검색을 위해 Clawd는 벡터 검색과 키워드 매칭을 혼합한 하이브리드 방식을 사용합니다. 이를 통해 두 방식의 장점을 모두 취합니다.

예를 들어, “authentication bug”를 검색하면, “auth issues”를 언급하는 문서들(의미 기반 검색)과 정확히 “authentication bug”라는 문구가 포함된 문서들(키워드 매칭)을 모두 찾을 수 있습니다.

벡터 검색에는 SQLite를 사용하고, 키워드 검색에는 SQLite의 확장 기능인 FTS5를 사용합니다. 임베딩 제공자는 설정을 통해 구성 가능합니다.

또한 파일 변경을 감지하는 파일 워처가 동작할 때 트리거되는 Smart Synching 기능의 장점도 누리고 있습니다.

이 마크다운 파일은 에이전트가 표준 ‘write’ 파일 툴을 사용해 직접 생성합니다. 별도의 특수한 메모리-쓰기 API는 존재하지 않으며, 에이전트는 단순히 ⁠memory/\*.md⁠에 파일을 쓸 뿐입니다.

새로운 대화가 시작되면, 훅(hook)이 이전 대화를 가져와 마크다운 형식의 요약본을 작성합니다.

Clawd의 메모리 시스템은 놀라울 정도로 단순하며, 우리가 @CamelAIOrg에서 workflow memories로 구현해 둔 것과 매우 유사합니다. 메모리를 병합하거나, 월간/주간 단위로 압축하는 과정은 없습니다.

이 단순함은 보는 관점에 따라 장점이 될 수도, 함정이 될 수도 있습니다. 하지만 저는 언제나 복잡한 스파게티 구조보다는 설명 가능한 단순함을 선호합니다.

메모리는 사실상 영구적으로 유지되며, 오래된 메모리도 거의 동일한 가중치를 지니기 때문에, 이 시스템에는 ‘망각 곡선’이 없다고 볼 수 있습니다.

Clawd의 집게: 컴퓨터를 어떻게 사용하는가

이것은 Clawd가 가진 일종의 해자(MOAT) 중 하나입니다. 여러분은 Clawd에게 컴퓨터를 내어주고, Clawd가 이를 사용하도록 맡깁니다. 그렇다면 Clawd는 컴퓨터를 어떻게 사용할까요? 기본적으로 여러분이 상상하는 방식과 크게 다르지 않습니다.

Clawd는 에이전트에게 상당한 수준의 컴퓨터 접근 권한을 부여하며, 이는 전적으로 사용자의 책임 하에 이루어집니다. Clawd는exec 툴을 사용해 쉘 명령을 다음 환경에서 실행할 수 있습니다.

  • sandbox: 기본 모드로, 명령이 Docker 컨테이너 내부에서 실행됩니다.
  • 호스트 머신에서 직접 실행
  • 원격 장치에서 실행

이 외에도 Clawd는 파일 시스템 툴(읽기, 쓰기, 편집),

Playwright 기반의 Browser 툴(semantic snapshots 지원),

그리고 백그라운드 장기 실행 명령, 프로세스 종료 등을 위한 프로세스 관리(프로세스 툴) 기능을 갖추고 있습니다.

안전 장치(혹은 그 부재?)

Claude Code와 마찬가지로, 사용자가 승인하고자 하는 명령에 대해 allowlist를 둘 수 있습니다(한 번 허용, 항상 허용, 거부 등을 사용자에게 프롬프트로 물어봄).

// ~/.clawdbot/exec-approvals.json
{
  "agents": {
    "main": {
      "allowlist": [
        { "pattern": "/usr/bin/npm", "lastUsedAt": 1706644800 },
        { "pattern": "/opt/homebrew/bin/git", "lastUsedAt": 1706644900 }
      ]
    }
  }
}

jq, grep, cut, sort, uniq, head, tail, tr, wc 같은 비교적 안전한 명령들은 이미 사전 승인(pre-approved) 상태입니다.

위험한 셸 구조는 기본적으로 차단됩니다.

# 이러한 명령들은 실행 전에 곧바로 거부됩니다.
npm install $(cat /etc/passwd)     # command substitution
cat file > /etc/hosts              # redirection
rm -rf / || echo "failed"          # chained with ||
(sudo rm -rf /)                    # subshell

이 안전장치는 Claude Code에 구현되어 있는 것과 상당히 유사합니다.

기본 아이디어는 “사용자가 허용하는 만큼 최대한의 자율성을 부여하자”는 것입니다.

브라우저: 시맨틱 스냅샷(Semantic Snapshots)

브라우저 툴은 주로 스크린샷에 의존하지 않고, 대신 semantic snapshots를 사용합니다. 이는 페이지의 접근성 트리(ARIA)를 텍스트 기반으로 표현한 것입니다.

따라서 에이전트는 페이지를 다음과 같이 보게 됩니다.

- button "Sign In" [ref=1]
- textbox "Email" [ref=2]
- textbox "Password" [ref=3]
- link "Forgot password?" [ref=4]
- heading "Welcome back"
- list
  - listitem "Dashboard"
  - listitem "Settings"

이 방식에는 네 가지 중요한 장점이 있습니다. 짐작했겠지만, 웹사이트를 탐색하는 행위는 반드시 시각적인 작업일 필요가 없습니다.

스크린샷 하나가 5MB에 이를 수 있는 반면, 시맨틱 스냅샷은 50KB 미만으로 매우 작으며, 이미지 대비 토큰 비용도 극히 일부만 차지합니다.

Edit this page