개요
빠르게 찾아보는 참조 장입니다. 명령어 표·서비스 심화·자주 묻는 질문·문제 해결을 정리합니다. 핵심 개념은 핵심 개념, 프로바이더 연동의 큰 그림은 연동을 보세요.
명령어 표
OpenArms의 공식 CLI는 python -m openarms 입니다. 점검 계열(doctor·board·inventory·
session·phase·status)은 읽기 전용이고, setup·enroll만 설정을 기록합니다(미리보기·계획
모드 제공).
| 명령 | 하는 일 |
|---|---|
python -m openarms doctor | 토큰 값을 읽거나 출력하지 않고 로컬 설정을 점검합니다. |
python -m openarms setup --provider <id> | 온보딩 마법사 — 필요한 설정을 git 제외 비공개 런타임 env 파일에 기록합니다(--dry-run 미리보기, --from-env 비대화). |
python -m openarms board | PM이 읽는 보드 투영(projection)을 렌더합니다. |
python -m openarms provider inventory | 텔레그램 프로바이더 서비스 인벤토리(읽기 전용). |
python -m openarms provider session | 프로바이더 전경 세션 레지스트리를 점검합니다. |
python -m openarms provider enroll <id> | 프로바이더 스킬을 등록합니다(기본 계획, --apply로 기록). id는 hermes·codex·gemini·antigravity. |
python -m openarms phase | 페이즈 커서·라이브 재개 준비 상태를 점검합니다. |
python -m openarms status | 현재 페이즈 상태(읽기 전용). |
python -m openarms --version | 버전을 출력합니다(현재 0.0.2.5). |
python openarms/paths.py bootstrap | ~/.openarms 골격을 멱등하게 만듭니다. |
python3 scripts/dev_preflight.py | 의존성 import 점검(설치·네트워크 없음). |
PYTHONIOENCODING=utf-8 python3 -m pytest -q | 테스트 스위트를 돌립니다. |
공통 옵션: --format text|json · --report <path> · --strict(블로커·위험 상태면 비-0
종료).
서비스 심화 — 왜 / 어떻게 / 훅 연동
이 장이 이름만 흘리던 서비스들을 실제 깊이로 채웁니다. 각 항목은 왜 골랐는지(대안 대비 장점) · 어떻게 구성하는지(스택·연결·설정) · 배포판에서 훅을 어떻게 쓰는지(릴리스 hook 연동 + 짧은 예시) 세 축으로 봅니다.
Hermes (현재 PM 역할 프로바이더)
왜. OpenArms는 “한 에이전트를 돌리는 프레임워크”가 아니라 여러 워커를 공유 기억·사람
점검과 함께 굴리는 관제면입니다. 그러려면 외부 CLI 에이전트를 코어를 패치하지 않고
붙일 수 있어야 합니다. Hermes는 공식 플러그인 훅 레이어를 노출하므로, 코어에 손대지
않고 메시지 흐름에 끼어들 수 있다는 점에서 PM(조율자) 역할의 첫 증명 프로바이더로
골랐습니다. 역할(PM)이 안정 개념이고 hermes는 그 자리를 채우는 교체 가능한
프로바이더입니다 — 라이브 테스트베드의 인스턴스 바인딩일 뿐 제품 기본값이 아닙니다.
어떻게 구성. 브리지는 integrations/hermes/openarms_contract_bridge/에 있는 공식
Hermes 사용자-플러그인이며, Hermes의 진짜 플러그인 로더가 이걸 로드합니다.
plugin.yaml— 매니페스트.pip_dependencies: [telethon](https://docs.telethon.dev/)>=1.36, 필수 환경변수 (OPENARMS_ROOT·OPENARMS_HERMES_ROUTE_TARGET·OPENARMS_HERMES_ROUTE_EXECUTOR·OPENARMS_TMUX_BIN), 그리고 등록할 훅 4종을 선언합니다.__init__.py— 훅 어댑터(register(ctx)진입점).- 어댑터 코어:
openarms/hermes_adapter.py(외부 결정 어댑터),openarms/providers/hermes.py(HermesAdapter). - 이 플러그인이 구동하는 리스너는 중립 코어인
scripts/telegram_thread_router_listener.py입니다. Hermes가 지금 PM으로 몰지만 리스너 자체는 프로바이더 비종속입니다.
라우팅 연결은 env로 합니다(config/openarms.hermes.env.example 발췌):
OPENARMS_HERMES_ROUTE_TARGET=[tmux](https://github.com/tmux/tmux):hermes-cli:0.0 # 전경 CLI가 사는 tmux pane
OPENARMS_HERMES_ROUTE_EXECUTOR=tmux # 라우트 실행 backend
OPENARMS_TMUX_BIN=tmux
OPENARMS_HERMES_CLI_RESPONSE_MIRROR=hermes-send # 답변 미러 방식봇 토큰·대상 채팅은 git에서 제외된 owner-local 비밀이며, env 키 전체 표면은
OPENARMS_HERMES_* 프리픽스입니다(역할-우선 중립 후속 키는 OPENARMS_*).
훅 연동 (배포판). 매니페스트가 선언하는 훅은 pre_gateway_dispatch,
transform_llm_output, cli_input_before_submit, cli_response_after_render
4종입니다. Hermes는 시작 시 플러그인의 register(ctx)를 호출하고, 거기서 지원되는
훅만 골라 등록합니다(미지원 훅은 조용히 건너뜀):
# integrations/hermes/openarms_contract_bridge/__init__.py
def register(ctx):
_register_if_supported(ctx, HERMES_HOOK_PRE_GATEWAY_DISPATCH, pre_gateway_dispatch)
_register_if_supported(ctx, HERMES_HOOK_TRANSFORM_LLM_OUTPUT, transform_llm_output)
if _register_foreground_hooks_enabled():
_register_if_supported(ctx, HERMES_HOOK_CLI_INPUT_BEFORE_SUBMIT, cli_input_before_submit)
_register_if_supported(ctx, HERMES_HOOK_CLI_RESPONSE_AFTER_RENDER, cli_response_after_render)핵심 훅은 pre_gateway_dispatch입니다. 들어온 메시지를 OpenArms 어댑터에 넘겨
skip·rewrite·allow·route 결정을 받습니다. OPENARMS_HERMES_ROUTE_EXECUTOR=tmux
일 때 route 결정이면 선언된 전경 tmux pane으로 턴을 밀어넣고, 응답 미러가 켜져 있으면
skip을 반환해 Hermes가 답을 두 번 내보내지 않게 합니다(미러 꺼져 있으면 allow로
사용자에게 답이 가게 둡니다). 즉, 외부 플러그인이 Hermes 코어를 패치하지 않고도 라우팅
판단을 코어 흐름에 주입합니다.
AGY / Antigravity (현재 worker 역할 프로바이더)
왜. PM이 하나만 있으면 조율할 게 없습니다. Hermes와 짝이 되는 두 번째 증명
프로바이더가 필요했고, Antigravity CLI는 네이티브 thread affordance(MCP 스타일 워커
스레드 도구)를 가진 별도 CLI라 “역할≠프로바이더” 규칙을 실증하기에 좋았습니다. AGY는
worker 역할에 바인딩됩니다 — 역시 인스턴스 바인딩이지 기본값이 아니며, 중립 후속 키는
OPENARMS_WORKER_*입니다. PM(hermes)+worker(agy) 조합이 현재의 라이브 증명 쌍입니다.
어떻게 구성. AGY 쪽은 두 갈래로 붙습니다.
- 프로바이더-네이티브 플러그인 —
integrations/antigravity/openarms_provider/:plugin.json(매니페스트),commands/openarms-worker.md,hooks/openarms.json,skills/openarms-worker/SKILL.md. 글로벌 워커 페르소나는agy-global-AGENTS.md(대화 우선, 강한 도구 게이트). - 어댑터/리스너 —
openarms/providers/antigravity.py(AntigravityAdapter),openarms/providers/agy_turns.py(전경 pane 턴 파서),scripts/agy_telegram_listener.py(텔레그램 인바운드 → AGY 전경 pane),scripts/agy_cli_to_telegram_mirror_once.py(완료된 한 턴만 최종-only 미러). - 워커-스레드 MCP —
integrations/antigravity/adapter/openarms_worker_threads_mcp.py(stdio JSON-RPC MCP 서버, AGY 네이티브 스레드 어포던스).
필수 게이트 키는 OPENARMS_AGY_TELEGRAM_CHAT_ID입니다(fail-closed — 이게 없으면 AGY가
복원되지 않습니다). 봇 토큰·전경 세션은 각각
OPENARMS_AGY_TELEGRAM_BOT_TOKEN·OPENARMS_AGY_FOREGROUND_SESSION이고, 중립 후속은
OPENARMS_WORKER_BOT_TOKEN·OPENARMS_WORKER_FOREGROUND_SESSION입니다.
훅 연동 (배포판). AGY 훅 와이어링은 JSON으로 선언적입니다
(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"
}
}이 선언은 두 가지를 강제합니다. (1) 권위는 공식 Antigravity CLI 표면 — 텔레그램·보드가
전경과 어긋나면 전경을 기준으로 맞춥니다. (2) 첨부는 네이티브 어포던스를 먼저 쓰고
실패할 때만 폴백합니다. 인바운드 흐름은 리스너가 받아 전경 pane에 넣고
(agy_telegram_listener.py), 한 턴이 끝나면 최종-only 미러가 그 결과만 텔레그램으로
돌려보냅니다 — 부분 출력이 새어 나가지 않습니다.
tmux (현재 라이브 전경 실행석 backend)
왜. Hermes·AGY 같은 CLI 에이전트는 진짜 터미널을 요구하는 대화형 도구입니다.
일반 bash 파이프로는 REPL·대화형 프롬프트를 몰 수 없습니다. tmux는 분리(detached)
세션을 만들어 send-keys로 키 입력을 주입하고 capture-pane으로 화면 상태를 읽어낼 수
있어, 전경 CLI를 “붙잡아 두는 좌석” 역할에 맞습니다. libtmux나 control mode 같은 더 무거운
대안 대신, OpenArms는 단순·이식 가능한 raw send-keys/capture-pane 호출을 씁니다.
중요: tmux는 제품 정체성이 아니라 현재 구현의 backend입니다. 로드맵상
execution_seat는 tmux/pty/ssh/windows-terminal/provider-native로 추상화될 예정이라,
tmux를 코어에 굳히지 않습니다(자세한 설계는 핵심 개념).
어떻게 구성. tmux는 OpenArms의 공식 base dependency입니다. 바이너리 해석은
openarms/runtime_config.py의 tmux_bin()이 단일 진실 원천입니다:
OPENARMS_TMUX_BIN(명시) >shutil.which("tmux")(PATH) > Homebrew 폴백/opt/homebrew/bin/tmux(존재 시) > 맨"tmux"(exec 시 OS PATH 해석)
pane 좌표는 tmux:<session>:<window>.<pane> 형식으로 env에 둡니다(예:
OPENARMS_HERMES_ROUTE_TARGET=tmux:hermes-cli:0.0). WSL/Linux/macOS/Mac VM에서
자연 동작하고, Windows native는 비주력입니다(tmux 기본 환경이 아니므로 GUI 확인 쪽으로).
훅 연동 (배포판). 라우트 실행기를 tmux로 켜면(OPENARMS_HERMES_ROUTE_EXECUTOR=tmux)
플러그인 훅의 route 결정이 곧장 tmux로 흘러갑니다. 리스너 측 I/O는
listener_tmux_io의 tmux_send/tmux_capture로 추상화되어 있고, 실제 인입은 대략
이런 모양입니다(개념 예시):
# 전경 CLI가 사는 pane에 한 턴을 주입
tmux send-keys -t hermes-cli:0.0 '<user turn text>' Enter
# 짧게 대기 후 pane 상태를 읽어 턴 완료를 판정
tmux capture-pane -p -J -t hermes-cli:0.0 -S -200배포판은 시작 시 require_tmux()로 base dependency를 fail-fast 점검합니다(없으면
크래시 대신 명료한 경고). 즉 훅은 “무엇을 라우팅할지”만 정하고, tmux는 그 결정을
전경 좌석에 물리적으로 전달하는 backend입니다.
telethon (Telegram 트랜스포트 — MTProto)
왜. OpenArms의 1차 표면은 텔레그램이고, 핵심 라이브러리는 telethon입니다. HTTP Bot API 대신 **MTProto**를 고른 이유:
- 사용자 기능 — 봇 API로는 못 하는 일(소유자 세션으로 토픽 열람·정리, 사용자 말풍선 미러, 방 기억 갈무리)이 가능합니다. OpenArms는 봇 토큰 경로와 owner MTProto 세션 경로를 둘 다 씁니다.
- 대량 작업 — 토픽 삭제 같은 작업은 봇 API → owner-MTProto 사다리(ladder)로 처리하고, 최대 100건 일괄 삭제/포워드가 됩니다.
- 회복력·한도 — Telegram 서버에 직결이라 Bot API 엔드포인트가 죽어도 연결이 살아 있고, 파일 한도가 훨씬 큽니다(다운 2GiB).
대안인 python-telegram-bot(Bot API)은 단순 봇엔 충분하지만 위 사용자-레벨 기능을 막습니다.
어떻게 구성. 런타임 floor는 telethon>=1.24,<2이고(파이썬 3.9 라이브 VM 호환의
보수적 하한; 라이브는 1.43.x 사용), Hermes 플러그인은 telethon>=1.36을 요구합니다.
인증은 Telethon StringSession 문자열로 합니다 — 온보딩 마법사가 API id/hash와 세션
문자열을 받아 git 제외 비공개 env에 기록합니다(유저 MTProto 미러를 쓸 때만 필요).
messaging/·scripts/ 전반(~28개 모듈)에서 TelegramClient/StringSession을 import
합니다. 보안: bare MTProto string-session blob은 그 자체로 라이브 세션이므로 절대
텔레그램에 게시하지 않고, doctor도 토큰/세션 값을 출력하지 않습니다.
훅 연동 (배포판). telethon은 두 지점에서 훅과 만납니다. (1) 인바운드 — 리스너가
telethon 클라이언트로 메시지를 받아 플러그인 pre_gateway_dispatch 훅에 넘깁니다. (2)
아웃바운드 미러 — cli_response_after_render 훅이 만든 가시 응답을 telethon 경로로
다시 텔레그램에 보냅니다(OPENARMS_HERMES_CLI_RESPONSE_MIRROR=hermes-send, 유저 미러는
OPENARMS_HERMES_CLI_INPUT_MIRROR=user-mtproto). 즉 telethon이 양끝(받기·보내기)의
트랜스포트이고, 가운데 결정은 프로바이더 훅이 담당합니다. 프로바이더 교체 설계는
메시징 플랫폼 참조.
venv (가상환경 — 패키지/테스트 격리)
왜. 파이썬 표준 라이브러리 내장이라 추가 설치 없이 어디서나 동작하고, 의존성 없는
단순 프로젝트·CI 부트스트랩에 마찰이 가장 적습니다. OpenArms 권위 문서는 python -m [venv](https://docs.python.org/3/library/venv.html)
pip install -e .[dev](editable 설치)를 1차 경로로 둡니다. (외부 best practice로는 2026년 uv가 10~100배 빠른 설치·lock 파일·자동 venv 관리로 떠올랐고, 같은pyproject.toml을 읽으므로 선택지로 둘 수 있습니다 — 다만 본 배포판의 검증된 floor는 venv+pip입니다.)
어떻게 구성 (Quickstart).
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]" # editable + dev extras
pytest -q테스트는 **WSL/Linux/macOS의 python3**로 레포 루트에서 돕니다. Windows의
hermes-agent venv는 지원 러너가 아닙니다(거기엔 pytest·telethon이 없어 수집 자체가 안
됨). editable(-e) 설치를 쓰는 이유는 라이브 VM(PYTHONPATH=<repo root>, python3 scripts/...)과 테스트(import openarms.*/import scripts.*)가 같은 import 경로를
보게 하기 위함입니다.
훅 연동 (배포판). 설치 전 그 인터프리터로 한 번 점검합니다:
python3 scripts/dev_preflight.py # import-only, 설치/네트워크 없음필수(telethon·jsonschema·pytest)가 다 있으면 exit 0, 하나라도 빠지면 비-0입니다. CI는
.[dev]를 설치하고 pyproject.toml/requirements-dev.txt를 lockstep으로 둡니다. 즉
venv는 훅을 직접 부르진 않지만, 훅을 실행하는 인터프리터 경계를 정의합니다 — 어떤
venv에서 돌리느냐가 telethon/jsonschema 가용 여부, 따라서 훅 동작 여부를 가릅니다.
jsonschema (리포트-스키마 검증 게이트)
왜. OpenArms의 머지 게이트와 결정 아카이브는 자유 텍스트가 아니라 스키마로 검증된
리포트로 닫힙니다. jsonschema는 표준이고, Draft202012Validator를 쓰기 위해
>=4.18을 floor로 둡니다. 게이트가 통과하려면 리포트가 구조적으로 맞아야 하므로,
“증거가 계약을 닫았는지”를 사람이 아니라 코드가 1차로 강제합니다.
어떻게 구성. 런타임 필수 의존성(jsonschema>=4.18)이고,
openarms/checklist_actionability_gate.py·live_attempt_progression_gate.py·
provider_persona_preservation_gate.py 등에서 import합니다. 프로바이더 setup 매니페스트
(config/providers/<id>/setup_manifest.json)도 게시된 JSON Schema로 검증합니다(필드
선언만, 비밀 값은 절대 넣지 않음).
훅 연동 (배포판). 새 메시징 프로바이더를 붙일 때
config/providers/<id>/setup_manifest.json이 스키마를 통과해야 코어 setup <id>가
받아들입니다. 즉 jsonschema는 프로바이더 온보딩 훅의 fail-closed 검문소입니다 —
코어 마법사는 특정 프로바이더로 분기하지 않고, 스키마 검증만으로 새 프로바이더를 안전히
받습니다(설계: 연동).
자주 묻는 질문
- OpenArms는 에이전트인가요? — 아니요. 에이전트가 받는 전경 세션과 사람이 보는 표면을 일치시키는 계약 브리지입니다.
- 어떤 메신저를 쓰나요? — 현재는 텔레그램이 1차 표면이고, 프로바이더는 교체 가능합니다.
- 어떤 CLI 에이전트를 붙일 수 있나요? — 기동·입력 전달·출력 포착·결과 마커 인식을 하는 어댑터가 있으면 어떤 CLI 에이전트든 붙습니다. Hermes·AGY가 현재 증명 쌍입니다.
- 왜 클라우드 벡터를 안 쓰나요? — 검색을 그래프 탐색 + BM25 어휘 일치로 하기 때문입니다. 마크다운이 권위이고 파생물은 다시 계산됩니다.
- 끝난 작업은 지워지나요? — 아니요. supersede-not-delete로 보관에 물러나며 이력이 남습니다.
- 여러 프로젝트의 기억이 섞이지 않나요? — 프로젝트 루트 경로로 기억을 칸 나눠 무관한 프로젝트의 검색·군집(community detection)이 섞이지 않습니다.
- Bot API가 아니라 telethon(MTProto)인 이유는? — 봇 API로는 못 하는 사용자-레벨 작업(토픽 정리·말풍선 미러·대량 삭제)이 필요하고, 서버 직결이라 회복력·파일 한도가 유리하기 때문입니다(서비스 심화의 telethon 절 참조).
심화 질문
- 에이전트 프레임워크와 무엇이 다른가요? — 한 에이전트를 돌리는 것은 프레임워크 문제이고, 여러 워커를 공유 기억·사람 점검·거버넌스 기록과 함께 예측 가능하게 돌리는 것은 조율(관제) 문제입니다. OpenArms는 후자 — 에이전트 운영 관제면입니다.
- 사람 점검(human-in-the-loop)은 어디 있나요? — PM 판단이 그 자리입니다. 증거 강도가 오르지 않으면 슬라이스를 멈춰 사람에게 넘기고, 모든 개입이 보드·기억에 기록됩니다.
- 관측성은 어떻게 확보하나요? — 칸반 표면과 결정 아카이브가 추적 가능성입니다. 무엇이 결정됐고 왜 막혔는지, 어떤 증거가 계약을 닫았는지가 남습니다. 조율은 관측 없이는 추측입니다.
- 왜 tmux 실행석인가요? — 현재 라이브 전경 실행석의 backend일 뿐 제품 정체성이 아닙니다. 실행석은 pty·ssh 등으로 추상화될 예정입니다(서비스 심화의 tmux 절 참조).
- 비밀은 어떻게 다루나요? — 봇 토큰·대상 채널·MTProto 세션 문자열은 소유자 로컬 비밀로
git 제외 env에 두고,
doctor도 토큰/세션 값을 출력하지 않습니다.
문제 해결
- 워커가 막혔습니다 — 블로커를 기록하고 다음 판단 소유자를 명시합니다. 증거 강도가 오르지
않으면 슬라이스를 멈추고(
stop_and_report) 사람 판단으로 넘깁니다. - 표면이 갈라집니다 — 전경 세션이 권위입니다. 텔레그램·보드가 전경과 어긋나면 전경을
기준으로 맞춥니다(AGY는
authority: official_antigravity_cli_surface로 이를 선언). - 맥락을 잃었습니다 — 회상으로 과거 결정을 다시 불러옵니다. 종결된 결정은 되살아나지 않습니다.
- 설정이 의심스럽습니다 —
python -m openarms doctor로 토큰 노출 없이 로컬 설정을 점검하고,python3 scripts/dev_preflight.py로 의존성을 확인합니다. - tmux가 없어 라우트가 안 갑니다 —
OPENARMS_TMUX_BIN을 명시하거나 PATH에 tmux를 두세요. 배포판은 시작 시require_tmux()로 fail-fast 점검합니다(WSL/Linux/macOS 권장). - AGY가 복원되지 않습니다 — fail-closed 게이트 키
OPENARMS_AGY_TELEGRAM_CHAT_ID가 비어 있는지 확인하세요. 이 키가 없으면 AGY는 의도적으로 기동하지 않습니다. - 답변이 두 번 옵니다 — 라우트 실행기가 tmux일 때 응답 미러가 켜져 있으면
pre_gateway_dispatch가skip을 반환해 중복을 막습니다. 미러 설정(*_CLI_RESPONSE_MIRROR)을 점검하세요.
출처: AI Agent Orchestration Guide 2026 (Knowlee) · Agentic AI Observability Playbook 2026 (Arthur) · HTTP Bot API vs MTProto (Telethon 공식) · Scripting tmux (tao-of-tmux) · venv vs uv 2026 (BSWEN)