개요
OpenArms를 받아 개발·테스트 환경을 세우고 첫 연결까지 가는 과정입니다. 의존성의 권위는 코드
메타데이터(pyproject.toml·requirements-dev.txt)이고, 이 장은 그 위의 사람용 안내입니다.
요구 사항은 Python 3.9 이상입니다(requires-python = ">=3.9"). 라이브 전경 실행석은
현재 tmux를 backend로 쓰므로, tmux가 자연히 도는 macOS·Linux·WSL2를 권합니다(Windows
네이티브는 비주력입니다).
이 장 뒤로 메시징 플랫폼(텔레그램 연결), 연동(프로바이더 CLI), OpenArms 사용(PM 운용 루프)으로 이어집니다.
환경별 설치
macOS · Linux
python3 -m [venv](https://docs.python.org/3/library/venv.html) .venv && source .venv/bin/activate
pip install -e ".[dev]"
python3 scripts/dev_preflight.py # 의존성 점검(설치·네트워크 없이 import만)
PYTHONIOENCODING=utf-8 python3 -m pytest -q라이브 전경 실행석으로는 tmux를 씁니다.
Windows (WSL2 권장)
Windows에서는 WSL2 안에서 위 macOS·Linux 단계를 그대로 따릅니다. 프로젝트 파일은 Windows 드라이브 마운트
가 아니라 WSL2 네이티브 홈(~/)에 두는 편이 파일 입출력에 유리합니다. Windows 네이티브의
hermes venv는 지원 테스트 러너가 아닙니다 — pytest·[telethon](https://docs.telethon.dev/)이 없어 수집 자체가 되지
않습니다.
서버 (헤드리스 Linux)
서버에서도 같은 venv·pip 단계를 따릅니다. tmux가 전경 실행석이 되고, 메신저 연결은 환경 변수로 둡니다. 다만 현재 라이브 운영의 실증 권위 경로는 GUI 확인(Windows GUI + Mac VM 전경) 조합이라, 완전 헤드리스 운영은 사용자가 명명할 분화 버전 목표입니다.
이 장이 다루는 도구·서비스 — 선택 근거·구성·훅
아래는 빠른 시작에서 이름이 나오는 모든 도구/서비스에 대해, 왜 골랐는지 · 어떻게 붙이는지 · 배포판에서 훅을 어떻게 쓰는지를 한 항목씩 적은 것입니다. 이름만 흘리지 않고 실제 구성까지 내려갑니다.
venv (Python 가상환경)
왜 이걸 골랐나. OpenArms 코어는 의존성이 얇습니다 — 런타임은 telethon·[jsonschema](https://json-schema.org/)
둘, 개발은 거기에 pytest·build 정도입니다. 이 정도 표면에서는 표준 라이브러리에 들어
있는 venv로 충분하고, 추가 도구를 강제하지 않는 게 기여자 진입 장벽을 가장 낮춥니다.
pip install -e ".[dev]"의 editable 설치가 핵심 근거입니다 — 소스 트리를 그대로 import
경로로 노출하므로, 라이브 VM 런타임이 쓰는 PYTHONPATH=<repo root> 실행 모델과 dev 환경이
동일해집니다. scripts.<module>이 PEP 420 namespace 패키지로 같은 방식으로 풀리는 것도
이 editable 설치 덕입니다.
대안 대비. [uv](https://docs.astral.sh/uv/)는 venv 생성이 venv보다 대략 200배 빠르고 uv.lock으로 재현성을 잠가
줍니다. 빠른 반복이 필요하면 uv venv && uv pip install -e ".[dev]"로 그대로 드롭인됩니다
— 코어가 pip 호환 인터페이스만 요구하므로 구조 변경 없이 속도만 얻습니다. 다만 OpenArms는
권위를 pyproject.toml/requirements-dev.txt에 두지, lock 파일을 강제하지 않습니다. conda는
이 의존성 폭에 과합니다.
어떻게 구성하나. 위 명령 그대로입니다. 단, 인터프리터 일관성이 함정입니다 — 테스트는
**WSL/Linux/macOS의 python3**로 레포 루트에서 돌립니다. Windows hermes-agent venv
(...\hermes\hermes-agent\venv\Scripts\python.exe)는 pytest/telethon이 없어 지원
러너가 아닙니다. 그래서 설치 직후 scripts/dev_preflight.py를 그 인터프리터로 한 번
돌려 PASS/MISSING을 확인합니다(import-only 검사, 설치·네트워크 없음, 필수 누락 시 비-0 종료).
배포판 훅 연동. venv 자체엔 훅이 없지만, 프로바이더 플러그인은 레포 밖에 설치됩니다
(예: ~/.hermes/hermes-agent/plugins/openarms_contract_bridge). 그 위치에서 import openarms가 풀리도록 부트스트랩이 OPENARMS_ROOT 환경변수 → ~/openarms → 체크아웃 부모
순서로 레포 루트를 sys.path에 넣습니다. 배포 시 venv를 만들었으면 OPENARMS_ROOT를 그
체크아웃으로 가리키게 두는 것이 가장 안전한 한 줄입니다.
export OPENARMS_ROOT="$HOME/openarms" # 플러그인이 레포 밖에서도 openarms를 importtmux (전경 실행석 backend)
왜 이걸 골랐나. tmux는 OpenArms의 공식 base 의존성이자 통합 실행석(seat) substrate
입니다. 프로바이더 CLI(Hermes/AGY/Claude)는 사람처럼 대화형으로 살아 있어야 하는데, tmux의
detached 세션은 터미널이 안 붙어 있어도 프로세스가 계속 돌고, send-keys로 보이지 않는
pane에도 입력을 넣고, capture-pane으로 출력을 읽어옵니다. HTTP 데몬을 새로 띄우는 대신
잘 검증된 안정 API 위에 좌석을 올리는 선택입니다. @fg/@bg 토글과 좌석 매니저가 모두
tmux 바이너리를 전제합니다.
대안 대비. 세션 영속성과 프로그램 제어, 출력 캡처를 한 번에 주는 도구로 tmux는 사실상
표준이고 문서·이식성이 가장 좋습니다. 신생 cmux 류는 macOS 네이티브 앱이라 이식성이 약하고,
원시 pty/ssh 직접 제어는 재연결·버퍼·diff를 직접 구현해야 합니다. 그래서 0.0.2.x는 tmux를
backend로 굳혔습니다 — 단, 제품 정체성이 아니라 현재 구현의 backend라서, 이후
execution_seat를 tmux/pty/ssh/windows-terminal/provider-native로 추상화할 방향입니다.
어떻게 구성하나. tmux 바이너리 해석은 한 곳(openarms.runtime_config.tmux_bin)에서
일어나며 우선순위가 OPENARMS_TMUX_BIN(명시) > which tmux(PATH) > Homebrew 폴백 > 맨
tmux입니다. 설치 점검은 openarms.tmux_runtime.require_tmux가 tmux -V로 하되 절대
예외를 던지지 않습니다(tmux 없는 CI 박스에서도 리스너는 import·실행돼야 함). 없으면 안내가
나옵니다: “tmux를 설치하거나 OPENARMS_TMUX_BIN 환경변수를 설정하세요.”
export OPENARMS_TMUX_BIN="$(which tmux)" # 비표준 경로일 때만 명시
tmux new-session -d -s pm-hermes # detached 좌석(예시)배포판 훅 연동. Hermes 플러그인 매니페스트(plugin.yaml)는 requires_env에
OPENARMS_TMUX_BIN을 선언합니다. 라우트 실행기를 켜면(OPENARMS_HERMES_ROUTE_EXECUTOR=tmux)
pre_gateway_dispatch 훅이 선언된 전경 tmux pane으로 그 턴을 제출합니다. 즉 배포판에서
tmux는 “있으면 좋은 것”이 아니라 훅이 실제로 의존하는 좌석입니다.
telethon (Telegram MTProto 클라이언트)
왜 이걸 골랐나. 텔레그램이 현재 1차 메신저 어댑터이고, OpenArms는 봇 답변만이 아니라 사용자 계정 컨텍스트(방 기억 캡처, 사용자 말풍선 미러)가 필요합니다. 사용자 계정은 반드시 MTProto로만 접근할 수 있고, telethon이 그 순수 Python MTProto 구현입니다. MTProto는 텔레그램 서버에 TCP로 직접 붙어 HTTP 폴링·웹훅이 없어 오버헤드가 작고, Bot API의 다운로드 20MiB / 업로드 50MiB 한도 대신 최대 2GiB까지 다룹니다. 봇과 사용자 두 경로를 한 라이브러리로 처리할 수 있는 것도 채택 이유입니다.
대안 대비. 순수 봇 워크플로면 Bot API 래퍼로 족하지만, OpenArms가 요구하는 사용자측
말풍선·방 히스토리·미러링은 Bot API로는 불가능합니다. 그래서 telethon으로 통일합니다. 버전은
Python 3.9를 지원하는 보수적 하한 telethon>=1.24,<2로 고정합니다(플러그인 측은 >=1.36).
어떻게 구성하나. 네 값이 함께 있어야 MTProto 미러가 켜집니다 —
TELEGRAM_API_ID·TELEGRAM_API_HASH(https://my.telegram.org 에서 발급),
그리고 미러링 계정의 StringSession(OPENARMS_TELEGRAM_USER_SESSION)입니다. StringSession은
세션 데이터를 Base64로 직렬화한 이식 가능한 인증 토큰이라 서버·컨테이너로 그대로 옮길 수
있습니다. 봇만 쓸 거면 이 네 값은 비워 두고 봇 토큰·대상 채팅 id만 채웁니다. 이 값들은
소유자 로컬 비밀이라 레포에 커밋하지 않고 .env(또는 ~/.config/openarms/hermes.env)에
둡니다 — .env.example이 모든 키의 플레이스홀더를 담고 있습니다.
cp .env.example .env
# OPENARMS_TELEGRAM_BOT_TOKEN, OPENARMS_TELEGRAM_SLOT_CHAT_ID 채우기(필수)
# 미러까지 쓰면 TELEGRAM_API_ID/HASH + OPENARMS_TELEGRAM_USER_SESSION
python -m openarms doctor # 어떤 필수 값이 비었는지 점검배포판 훅 연동. Hermes 플러그인은 telethon을 pip_dependencies로 선언하고, 사용자측
말풍선 전송은 cli_input_before_submit 훅에서 일어납니다 — 입력 전달 모드가
user-mtproto일 때 telethon 사용자 클라이언트로 말풍선을 보내고, 그 메시지 id로 suppress
키를 만들어 미러된 풍선이 두 번째 턴으로 다시 들어오는 것을 막습니다.
Hermes (PM 역할 프로바이더 CLI)
왜 이걸 골랐나. OpenArms는 프로바이더-중립 엔진 + 교체 가능한 어댑터 구조입니다. 역할(PM/worker)이 안정 개념이고 프로바이더는 그 역할을 채우는 교체 가능한 구현입니다. 현재 라이브 테스트베드는 Hermes를 PM(조율자) 역할에 바인딩합니다 — 이는 라이브 배치의 한 인스턴스이지 제품 기본값이 아닙니다. Hermes를 PM에 둔 이유는 그 공식 플러그인 hook 레이어가 스레드 라우팅·게이트웨이 디스패치를 깔끔히 가로챌 수 있어, Hermes 코어를 패치하지 않고 OpenArms로 흘려보낼 수 있기 때문입니다.
어떻게 구성하나. OpenArms는 Hermes를 설치·패치하지 않고 어댑터로 붙입니다. 연결
표면은 전부 환경변수입니다(OPENARMS_HERMES_*): 프로세스(OPENARMS_HERMES_BIN), tmux
좌석(OPENARMS_HERMES_CLI_PANE·OPENARMS_HERMES_CLI_SESSION), 라우팅 계약
(OPENARMS_HERMES_ROUTE_TARGET·OPENARMS_HERMES_ROUTE_EXECUTOR). 라이브가 드라이브하는
리스너는 중립 코어인 scripts/telegram_thread_router_listener.py입니다 — Hermes가 PM으로
이 리스너를 몰지만 리스너 자체는 프로바이더-중립으로 남습니다.
배포판 훅 연동. 공식 Hermes 플러그인 브리지(integrations/hermes/openarms_contract_bridge/)
는 레포 밖 플러그인 디렉터리에 설치되어 Hermes의 실제 플러그인 로더가 적재합니다. 매니페스트
plugin.yaml이 네 훅을 선언합니다:
# integrations/hermes/openarms_contract_bridge/plugin.yaml
name: openarms-contract-bridge
hooks:
- pre_gateway_dispatch # 에이전트 이전 라우트 결정(skip/rewrite/allow/route)
- transform_llm_output # 출력 변환
- cli_input_before_submit # 사용자 입력 관측 + 미러
- cli_response_after_render # 렌더된 응답 미러
requires_env:
- OPENARMS_ROOT
- OPENARMS_HERMES_ROUTE_TARGET
- OPENARMS_HERMES_ROUTE_EXECUTOR
- OPENARMS_TMUX_BIN핵심 동작: pre_gateway_dispatch는 OpenArms의 “에이전트 이전” 결정으로 매핑되고,
OPENARMS_HERMES_ROUTE_EXECUTOR=tmux로 라우트 실행이 명시적으로 켜졌을 때만 턴을 전경 tmux
pane으로 제출합니다. 응답 미러가 켜져 있으면 게이트웨이는 skip을 돌려 Hermes 답변이 두 번
나가지 않게 하고, 미러가 꺼져 있으면 allow로 사용자가 답을 받게 합니다. 즉 훅은 Hermes
코어를 건드리지 않고 OpenArms 라우팅을 끼워 넣는 단 하나의 접점입니다.
AGY / Antigravity (worker 역할 프로바이더 CLI)
왜 이걸 골랐나. 같은 역할≠프로바이더 원칙에서, 라이브 테스트베드는 Antigravity CLI(짧게
agy)를 worker 역할에 바인딩합니다. 이것도 라이브 인스턴스이지 제품 기본값이 아닙니다
(제품 기본은 단일 PM). AGY를 worker로 둔 이유는 그 네이티브 첨부/파일 표면이 강해, 이미지·
파일이 섞인 작업 턴을 폴백 없이 프로바이더 고유 표면으로 처리할 수 있기 때문입니다.
어떻게 구성하나. 연결은 OPENARMS_AGY_* 환경변수입니다 — 텔레그램/표면 바인딩
(OPENARMS_AGY_TELEGRAM_BOT_TOKEN·OPENARMS_AGY_TELEGRAM_CHAT_ID), 전경 tmux 좌석
(OPENARMS_AGY_FOREGROUND_SESSION·OPENARMS_AGY_PANE), 턴 동작
(OPENARMS_AGY_INBOUND·OPENARMS_AGY_RESULT). OPENARMS_AGY_TELEGRAM_CHAT_ID는 AGY를
복구하는 fail-closed 게이트 키라 비면 worker가 살아나지 않습니다. 엔진이 역할-우선
네이밍으로 옮겨가면 이 키들은 중립 OPENARMS_WORKER_*(예: OPENARMS_WORKER_BOT_TOKEN)로
승계됩니다 — 마이그레이션 목표일 뿐 오늘의 라이브 키는 OPENARMS_AGY_*입니다.
배포판 훅 연동. AGY는 Antigravity-네이티브 플러그인 번들(integrations/antigravity/ openarms_provider/)로 붙고, 훅 매니페스트가 역할·프로바이더·권위·첨부 정책을 선언합니다:
// integrations/antigravity/openarms_provider/hooks/openarms.json
{
"openarms_provider_bridge": {
"role": "worker",
"provider": "antigravity",
"authority": "official_antigravity_cli_surface",
"attachment_policy": "use_native_attachment_surface_before_fallback"
}
}worker 페르소나는 agy-global-AGENTS.md가 세션 시작 시 작업 디렉터리에서 자동 적재해
강제합니다(대화 우선, 하드 tool 게이트, 한국어 사용자 응답, 내부 표면 비노출). 첨부가 있는
턴은 attachment_policy대로 네이티브 첨부 표면을 먼저 거칩니다.
Claude · 기타 프로바이더 CLI
왜·어떻게. Claude를 비롯한 다른 CLI도 같은 어댑터 규약으로 붙일 수 있습니다 — OpenArms는
이들을 설치·패치하지 않고, 중립 역할 계약(PM/worker, 라우팅, 레지스트리, 표면)을 그 CLI의
고유 affordance로 매핑하는 얇은 어댑터만 둡니다. 표준 규칙: 프로바이더 라벨이 제품 역할을
대체(supersede)하지 않게 하고, 한 프로바이더의 기계적 idiom이나 깨지기 쉬운 키워드 휴리스틱을 중립
코어에 하드코딩하지 않습니다. 그래서 매니페스트/문서는 “PM 프로바이더”, “worker 프로바이더”
처럼 역할-우선으로 적고 hermes/antigravity는 현재 바인딩으로만 다룹니다.
doctor / preflight (설치 점검 도구)
왜·어떻게. 두 점검 도구는 “설치가 됐다”와 “라이브가 뜬다” 사이의 흔한 함정을 잡습니다.
scripts/dev_preflight.py는 import-only로 필수 의존성(pytest·telethon·jsonschema)
존재만 보고(설치·네트워크 없음), 누락 시 비-0으로 끝납니다. python -m openarms doctor
(= scripts/openarms_setup_doctor.py)는 메신저 연결 쪽을 봅니다 — 봇 토큰과 대상 채팅 id가
필수 finding이고, 포럼 토픽/비즈니스/MTProto 미러는 선택 finding입니다. 비밀 값은
redact_value로 마스킹해 stdout에 원문이 새지 않게 합니다.
python3 scripts/dev_preflight.py # 인터프리터 의존성 점검(필수 누락 시 비-0)
python -m openarms doctor # 메신저 연결 필수/선택 점검첫 연결 설정
- 홈 골격: OpenArms는
~/.openarms(또는OPENARMS_HOME)에 설정·자격·기억 골격을 둡니다. - 메신저: 현재 1차 어댑터는 텔레그램입니다. 봇 토큰과 대상 채널은 소유자 로컬 비밀이라
레포에 커밋하지 않고
.env로 둡니다(.env.example참조). - 프로바이더 CLI: Hermes·AGY·Claude 등은 외부 CLI입니다. OpenArms는 이들을 설치·패치하지 않고 어댑터로 붙입니다.
OS 지원 현황 (0.0.2.x)
| OS | 패키지·CLI·테스트 | 라이브 운영 |
|---|---|---|
| macOS · Mac VM | 가능 | 현재 전경·tmux 기준석 |
| Linux | 근거 있음(CI) | tmux 구조에 적합 |
| Windows | 가능(CI) | 비주력(GUI 확인 쪽) |
멀티 OS 동일 완전 사용은 사용자가 명명할 분화 버전 목표이지 현재 상태가 아닙니다.
출처: WSL2 Setup Guide 2026 · Modern Python on WSL2 · Scripting tmux (tao-of-tmux) · HTTP Bot API vs MTProto (Telethon docs) · uv vs pip (Real Python)