Tauri 기반 데스크톱 에이전트 하네스. 118+ 서비스를 OAuth로 빨아들여 메모리 트리에 압축, 마스코트로 말한다.
왜 LLM 단독으로는 부족하고, 왜 메모리 트리가 필요한가.
2024~2026년 사이 ChatGPT·Claude·Gemini는 점점 똑똑해졌지만, "내 일상을 진짜로 이해하고 대신 일해주는" 에이전트는 여전히 부족했다. 이메일·노션·슬랙·캘린더가 다 흩어져 있고, 모델은 매 대화마다 컨텍스트를 처음부터 다시 배워야 했기 때문이다.
해법은 LLM을 둘러싸는 "외골격(harness)"이다. 도구 호출, 외부 데이터 자동 수집, 장기 기억, 모델 라우팅, UI까지 책임지는 운영 레이어. OpenHuman은 이 외골격을 데스크톱 네이티브 앱으로 끝까지 밀어붙인 첫 사례다.
openhuman-core(Rust)가 하네스를 맡고, Tauri 앱이 UI를 맡는다.≤3k 토큰 청크로 잘라 계층적으로 요약해 만드는 트리. 상위 노드는 자식 노드들의 요약. LLM이 "최근 이메일 요약" 요청 시 트리 상단만 읽고, 필요하면 자식으로 내려간다. Karpathy의 obsidian-wiki 트윗을 코드화한 결과.한 문장으로 줄이면.
OpenHuman은 단순 챗봇이 아니라 로컬 우선·키 통합·데스크톱 네이티브를 모두 채택한 에이전트 하네스다. SQLite에 메모리 트리를 쌓고, Obsidian 호환 마크다운으로 미러링해 사용자에게 데이터 주권을 돌려준다.
"AI가 내 또 다른 자아가 되되, 내가 통제 가능한 형태로" — Karpathy가 X에 던진 비전을 처음으로 제품화한 사례.
시대적 배경 + 경쟁 우위.
기존 에이전트(Hermes, OpenClaw 등)는 사용자를 학습하는 데 며칠~몇 주가 걸렸다. 매일 대화하며 선호도를 알아내야 했기 때문. OpenHuman은 OAuth 한 번으로 118+ 서비스를 한꺼번에 흡수해 이 콜드 스타트 시간을 분 단위로 단축한다.
또 하나 — "BYOK(Bring Your Own Key) 지옥" 탈출. 보통 에이전트는 OpenAI·Anthropic·ElevenLabs 키를 각각 발급받아야 했지만, OpenHuman은 구독 하나 + 자동 모델 라우팅(reasoning/fast/vision)으로 끝낸다. Karpathy가 X에 올린 "obsidian-style wiki + memory tree" 워크플로우를 실제 작동하는 데스크톱 앱으로 구현한 첫 사례라는 점이 화제의 핵심.
| 비교 항목 | Claude Cowork | OpenClaw / Hermes | OpenHuman |
|---|---|---|---|
| 오픈소스 | 독점 | MIT | GPL-3.0 |
| 시작 난이도 | 데스크톱+CLI | 터미널 우선 | 클린 UI, 수 분 내 |
| 비용 | 구독+애드온 | BYO 모델 키 | 구독 1 + TokenJuice 압축 |
| 메모리 | 채팅 스코프 | 플러그인/자가학습 | Memory Tree + Obsidian 미러 |
| 통합 수 | 소수 | BYO | 118+ OAuth 빌트인 |
| 오토페치 | 없음 | 없음 | 20분 주기 자동 |
| 모델 라우팅 | 단일 | 수동 | 빌트인 (reasoning/fast/vision) |
| 네이티브 도구 | 코드만 | 코드만 | 코드+검색+스크래핑+음성+Meet |
새로 산 스마트폰을 떠올려보라. 처음 며칠은 자동완성이 멍청하고, 추천 앱도 엉터리다. AI에이전트도 똑같았다 — 너를 모르니까. OpenHuman은 그 며칠을 OAuth 한 클릭으로 압축한다. 마치 새 폰에 백업을 통째로 복원하는 것과 같다.
백엔드(Rust 61.6%) · 프론트(TS 35.5%) · 인프라 · 보안.
:7788 포트에서 RPC + WebSocketline-tables-only로 Sentry 심볼리케이션 최적화scheduler_gateapp (openhuman-app), packages/tauri-plugin-ptt (remotion/은 별도 package.json, 워크스페이스 외부)scripts/i18n-coverage.ts — 다국어 커버리지 검증openhuman-core만 컨테이너화 (멤버 클라이언트는 데스크톱 네이티브)curl ... | bash / irm ... | iexprofile.ci Cargo 프로파일 (opt-level=1, codegen-units=16, lto=false)전체 구조도 → 핵심 패턴 하나하나.
┌─────────────────────────────────────────────────────────────────────┐
│ OpenHuman Desktop App │
│ (Tauri 2.x Window) │
│ │
│ ┌──────────────┐ ┌─────────────────┐ ┌───────────────────┐ │
│ │ Mascot UI │ │ Chat Panel │ │ Obsidian Vault │ │
│ │ (Remotion + │ │ (TypeScript) │ │ Viewer (.md) │ │
│ │ Lip-sync) │ │ │ │ │ │
│ └──────┬───────┘ └────────┬────────┘ └─────────┬─────────┘ │
│ │ │ │ │
│ └─────────┬───────────┴──────────────────────┘ │
│ │ Tauri IPC (RPC over JSON) │
└───────────────────┼─────────────────────────────────────────────────┘
│
┌───────────▼────────────────────────────────────────┐
│ openhuman-core (Rust binary :7788) │
│ ┌──────────────────────────────────────────────┐ │
│ │ Axum HTTP/WS Server (/rpc, /health) │ │
│ └──────────────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────────────▼──────────────────┐ │
│ │ Agent Orchestrator │ │
│ │ - Tool dispatcher (typed) │ │
│ │ - Model router (reasoning/fast/vis) │ │
│ └─────┬───────────┬────────────┬──────┘ │
│ │ │ │ │
│ ┌─────▼─────┐ ┌───▼──────┐ ┌──▼──────────┐ │
│ │Auto-Fetch │ │TokenJuice│ │Memory Tree │ │
│ │(20min loop│ │Compressor│ │(SQLite + │ │
│ │ per conn) │ │ │ │ Obsidian MD)│ │
│ └─────┬─────┘ └──────────┘ └──────┬──────┘ │
│ │ │ │
│ ┌─────▼────────────────────┐ ┌─────▼─────────┐ │
│ │ Integrations (118+) │ │ Native Tools │ │
│ │ Gmail/Slack/Notion/GH/.. │ │ FS/Git/Lint │ │
│ └──────────────────────────┘ │ Web Fetch/Sea │ │
│ │ STT/TTS/Meet │ │
│ └───────────────┘ │
└────────────────────────────────────────────────────┘
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ OAuth API │ │ Whisper │ │ ElevenLabs│
│ (Gmail..) │ │ Local │ │ TTS API │
└───────────┘ └───────────┘ └───────────┘
OpenHuman의 가장 독창적인 발명. 모든 외부 데이터(이메일, 노션 페이지, 슬랙 메시지 등)는 다음 파이프라인을 통과한다.
원본 → 정규화(Canonicalize) → ≤3k 토큰 Markdown 청크 분할 → 스코어링
→ 계층적 요약 트리(상위 노드는 하위 노드의 요약) → SQLite 저장
→ 동시에 Obsidian 호환 .md 파일로 vault에 미러링
덕분에 LLM이 "오늘 이메일 요약해줘"라고 요청받으면 트리 상단의 요약 노드만 읽으면 되고, 자세한 게 필요하면 자식 노드로 내려가면서 점진적으로 확장한다. 이것이 Karpathy가 X에서 제안한 "obsidian-wiki" 패턴의 코드화다.
대기업에서 사장은 매일의 모든 디테일을 알 수 없다. 부장 → 임원 → 사장으로 올라가며 보고가 요약된다. 사장은 평소엔 임원 요약만 읽고, 궁금한 게 있으면 "그 건 자세히"라고 묻는다. Memory Tree가 LLM에게 해주는 일이 정확히 이거다.
모든 도구 호출 결과는 LLM에 도달하기 전에 압축 레이어를 거친다. 백엔드 코드(fast_html_to_text)에서 흥미로운 디테일이 발견된다.
원래 html2md 크레이트를 썼는데, dhat-rs 프로파일링으로 Otter.ai 스타일 이메일(10KB HTML)에서 894MB 피크 힙을 찍는 걸 발견.
의존성 주석에 이 디버깅 흔적이 그대로 남아 있어 실제 프로덕션 운영의 깊이를 보여준다. 단순 라이브러리 갈아끼우기가 아니라 "왜 갈았는지"가 코드에 박혀 있는 게 학습 포인트.
요청의 성격에 따라 자동으로 적절한 LLM을 선택. 사용자는 키 하나만 등록하면 되고, 라우팅 로직이 알아서 최적 모델을 호출한다.
| 요청 타입 | 라우팅 대상 | 예시 모델 |
|---|---|---|
| Reasoning (논리 추론) | 큰 모델 | Claude Opus, GPT-5-pro |
| Fast (간단 요약, 분류) | 작은 모델 | Haiku, Mini |
| Vision (스크린샷 이해) | 비전 가능 모델 | GPT-4o, Claude Sonnet |
| Local (옵션) | 온디바이스 | Ollama 호환 모델 |
starship-battery 크레이트로 노트북 배터리 잔량을 감지. 배터리가 적으면 백그라운드 LLM 작업(오토페치, 메모리 정리)을 throttle. 이런 디테일이 OpenHuman을 "데스크톱 시민(desktop citizen)"이라 부르게 만드는 이유다 — OS 위에 얹혀살되 OS 자원을 존중한다.
enigo(마우스/키보드 제어), arboard(클립보드), rdev(전역 이벤트 캡처) 조합으로 마스코트가 사용자 화면 위에서 직접 행동한다. Google Meet 참가자로 들어갈 수 있는 것도 이 컴퓨터 제어 + Whisper(STT) + ElevenLabs(TTS) + 립싱크 비주얼의 조합이다.
다마고치를 떠올렸다면 절반만 맞다. OpenHuman 마스코트는 다마고치 + RPA 봇 + 실시간 통역사를 합친 형태. 화면 위에 떠 있다가, 사용자가 회의를 놓치면 대신 입장해 회의 참가자처럼 발언한다.
어디에 뭐가 있는지.
openhuman/ ├── .agents/agents/ # 에이전트 정의 (페르소나, 도구 셋, 시스템 프롬프트) ├── .claude/ # Claude Code 설정 (이 레포 자체가 Claude로 개발됨!) ├── .codex/commands/ # Codex CLI 명령어 정의 ├── app/ # Tauri 데스크톱 앱 (TypeScript 본체) ├── packages/ # 공유 TypeScript 패키지 (pnpm workspace) ├── src/ # Rust 코어 메인 소스 │ └── bin/ # 보조 바이너리들 │ ├── slack_backfill.rs # 슬랙 과거 메시지 일괄 수집 │ ├── gmail_backfill_3d.rs # Gmail 3일치 백필 │ ├── memory_tree_init_smoke.rs # 메모리 트리 초기화 스모크 테스트 │ ├── inference_probe.rs # LLM 추론 헬스 체크 │ └── test_mcp_stub.rs # MCP 스텁 테스트용 바이너리 ├── docs/ # 개발자 문서 ├── e2e/ # Playwright E2E 테스트 ├── examples/ # 사용 예제 ├── gitbooks/ # 사용자 문서 (Gitbook 호스팅) ├── remotion/ # 마스코트 애니메이션 렌더링 (React + Remotion) ├── scripts/ # 빌드/배포/CI 스크립트 │ ├── deep-work/ # 집중 작업 모드 CLI │ ├── shortcuts/ # 개발자 단축 명령 │ └── tests/ # 설치 스크립트 테스트 ├── tests/ # Rust 통합 테스트 ├── Cargo.toml # Rust 의존성 (위 분석 참조) ├── package.json # 모노레포 루트 (pnpm 스크립트만) ├── docker-compose.yml # 헤드리스 코어 셀프호스팅 ├── Dockerfile # 코어 빌드 ├── AGENTS.md # 에이전트 아키텍처 가이드 └── CLAUDE.md # Claude Code용 프로젝트 가이드
.claude/ + CLAUDE.md — 이 프로젝트 자체가 Claude Code로 개발됨. AI 에이전트 만드는 사람들이 AI 에이전트로 코딩하는 메타적 풍경.remotion/ — Remotion(React로 비디오를 만드는 프레임워크)으로 마스코트 애니메이션을 렌더링. pnpm mascot:render로 빌드.scripts/deep-work/ — "집중 작업 모드" CLI. 마스코트가 방해를 차단해주는 기능이 별도 스크립트로 패키징됨.마이크로서비스 아닌데 왜 분리했을까? — 백필은 Gmail 3일치, 슬랙 전체 같은 거대한 작업이라 메모리를 많이 먹는다. 메인 프로세스에 묶이면 한 번 죽을 때 데스크톱 앱 전체가 깜빡인다. OS 프로세스 격리를 활용해 안정성을 산 것.
기술 영역마다 무엇을 가져갈지.
parking_lot/once_cell로 동시성 처리실습: 작은 RPC 서버를 Axum으로 만들고 SQLite에 메모를 저장하는 토이 프로젝트 → Tokio mpsc 채널로 백그라운드 워커 추가
@tauri-apps/api 사용법실습: Tauri로 로컬 파일 검색 앱 만들기 — Rust에서 ripgrep 같은 검색, TS에서 결과 표시
실습: 자기 노션 페이지를 export → 청크 분할 → OpenAI 임베딩 → 트리 노드별로 GPT-4o-mini로 요약 → SQLite 저장
실습: Gmail OAuth → 최근 50개 메일 가져와 GPT로 분류하는 미니 에이전트
실습: Whisper로 회의 녹음을 로컬에서 트랜스크립트 → 요약 → Notion에 자동 업로드
실습: 자신의 사이드 프로젝트 컨테이너에 같은 패턴 적용해 변조 못 하는 컨테이너 만들기
최소·권장 사양과 개발 환경.
| 항목 | 최소 | 권장 | 비고 |
|---|---|---|---|
| OS | macOS 12+ / Windows 10+ / Linux x64 | macOS 14+ (Metal 가속) | 설치 스크립트 3개 플랫폼 지원 |
| RAM | 8 GB | 16 GB+ | Docker 코어는 mem_limit: 4g |
| 디스크 | 10 GB | 50 GB+ | Obsidian 볼트 + SQLite + Whisper 모델 |
| CPU | x64 / ARM64 | M1+ / Ryzen | 로컬 Whisper는 멀티코어 활용 |
| GPU | 불필요 | Apple Silicon Metal / NVIDIA | whisper-rs Metal feature |
| 네트워크 | 인터넷 필수 | 안정 광대역 | OAuth 콜백 + LLM API + 통합 폴링 |
| 포트 | — | 7788 (오픈) | OPENHUMAN_CORE_PORT 환경변수 |
| Rust 개발 | Rust stable | rust-toolchain.toml 참조 | 기여 시 |
| Node 개발 | Node 20+, pnpm 10+ | — | 기여 시 |
설치 스크립트는 PowerShell irm ... | iex 형태. UAC 권한과 실행 정책(Set-ExecutionPolicy RemoteSigned -Scope CurrentUser)을 먼저 확인. WSL이 아닌 네이티브 Windows에서 돌릴 때 일부 통합(Whisper-rs Metal)은 비활성화된다.
난이도별 실습 — Easy → Hard.
1) 설치 스크립트(curl ... | bash)로 OpenHuman 띄우기 2) Gmail OAuth 연결 3) "지난 일주일 이메일 요약해줘" 명령 4) 메모리 트리가 어떻게 SQLite에 쌓이는지 sqlite3 CLI로 직접 들여다보기
배우는 것: 메모리 트리 구조 직관, OAuth 흐름 체험, SQLite 스키마
1) OpenHuman이 생성한 Obsidian 호환 볼트를 Obsidian 앱으로 열기 2) 어떤 노드가 어떤 데이터에서 생성됐는지 추적 3) 백링크 구조와 그래프 뷰로 시각화 4) 직접 노드를 편집하면 OpenHuman이 어떻게 반응하는지 관찰
배우는 것: 계층적 요약 트리의 시각적 이해, 데이터 주권 의미
1) Python으로 HTML → Markdown 변환기 작성 2) "긴 URL 단축 + 비-ASCII 제거 + 표 보존" 룰 적용 3) tiktoken으로 토큰 카운트 측정 4) 압축률 표로 정리 (원본 vs 변환 후)
배우는 것: 토큰 비용 절감 실전 감각, 정규식·파서 설계
1) Tauri 앱 생성, 항상 떠 있는 작은 캐릭터 윈도우 2) always-on-top + 투명 배경 + 무프레임 윈도우 설정 3) Rust에서 시스템 알림 감지 → IPC로 TS에 전달 → 캐릭터가 손 흔들기 4) 트레이 메뉴로 토글
배우는 것: Tauri IPC, 데스크톱 OS API, 윈도우 매니지먼트
1) 임의의 마크다운 코퍼스 입력 2) ≤3k 토큰 청크 분할 + 임베딩 + 클러스터링 3) 각 클러스터를 LLM에 요약시켜 부모 노드 생성 (재귀) 4) SQLite에 트리 저장 + Obsidian용 .md 미러링 5) "이 트리에서 X에 대한 정보 찾아줘" 쿼리 모드 — top-down 탐색 알고리즘
배우는 것: 진짜 어드밴스드 RAG, 계층적 메모리 알고리즘, RAPTOR 논문 구현
1) Puppeteer/Playwright로 Meet에 자동 입장 2) 시스템 오디오 캡처 → Whisper로 STT 3) LLM이 발화 응답 생성 4) ElevenLabs TTS로 회의에 발화 5) 윤리·동의 문제도 함께 고민 (참가자 고지 필수)
배우는 것: 멀티모달 에이전트, 실시간 오디오 파이프라인, 컴퓨터 제어, AI 윤리
주차별로 따라가면 전체 스택 마스터.
The Rust Book 1~10장, tokio.rs/tokio/tutorial로 비동기. cargo new로 echo TCP 서버 만들기
Axum 0.8 튜토리얼로 RPC 서버 구축. rusqlite로 메모 저장. OpenHuman의 src/main.rs 패턴 따라하기
공식 Tauri 튜토리얼. Rust 함수를 TS에서 호출하는 IPC 명령 5개 작성. 시스템 트레이, 글로벌 단축키
OpenAI API + Google OAuth로 "내 캘린더 요약기" 만들기. Refresh token 처리, scope 설계
OpenAI text-embedding-3 + Chroma/Qdrant. 청크 사이즈 실험(500/1500/3000 토큰)으로 검색 품질 비교
RAPTOR 논문, Karpathy의 obsidian-wiki 트윗 정독. 자체 Memory Tree 토이 구현
whisper-rs로 로컬 STT. enigo로 마우스 자동화. ElevenLabs TTS 호출
위 모든 걸 합쳐 자신의 "1인용 AI 에이전트" 만들기. README + 데모 영상 작성 후 GitHub 공개
자주 마주칠 단어들.
.md + 백링크). OpenHuman은 메모리 트리를 이 형식으로 미러링.공식 · 영감 · 학습 리소스.
curl ... | bash로 띄우고 Gmail 1개만 먼저 연결. 첫 오토페치(20분)가 끝날 때까지 기다리기. 이 시간이 콜드 스타트의 종착점.sqlite3 ~/.openhuman/memory.db로 직접 들어가 SELECT * FROM nodes LIMIT 20; — 트리 노드가 어떻게 부모/자식 관계로 저장되는지 눈으로 확인.docker-compose.yml로 :7788 코어만 띄워보기. read_only·cap_drop 옵션이 빠지면 어떻게 되는지 일부러 망가뜨려 보기 — 프로덕션 보안의 감 잡기.