| name | ohmyclaw |
| description | OpenClaw 용 멀티프로바이더/멀티계정 라우팅 하네스. Z.ai 코딩플랜(Lite/Pro/Max) 모델 매트릭스 + ChatGPT Codex OAuth 다중 계정 풀(round-robin/cooldown/fan-out) + 추론 인식 모델 선택 + Plan→Work→Review 오케스트레이션 + 5관점 리뷰와 갭 감지. Use when: (1) Z.ai GLM 코딩 작업, (2) 다중 ChatGPT/Z.ai 계정으로 rate limit 분산, (3) 한국어 코딩/리뷰/리팩토링, (4) Plan→Work→Review 사이클로 다단계 작업 분해, (5) 같은 태스크를 여러 계정에 fan-out. NOT for: (a) 단순 1-line 수정, (b) read-only 탐색, (c) Z.ai/Codex 가 아닌 다른 프로바이더 단독 작업. |
| metadata | {"openclaw":{"emoji":"🦞","requires":{"anyBins":["jq"]},"install":[{"id":"brew-jq","kind":"brew","package":"jq","bins":["jq"],"label":"Install jq (routing engine prerequisite)"}]}} |
ohmyclaw — OpenClaw Multi-Provider/Multi-Account Harness
OpenClaw 의 @openclaw/zai-provider (와 선택적 ChatGPT Codex OAuth) 위에 올라가는 에이전트 하네스입니다. 다음을 한 번에 제공합니다:
- Z.ai 코딩플랜(Lite/Pro/Max) 멀티티어 라우팅
- ChatGPT Codex OAuth 다중 계정 풀 (round-robin / cooldown / fan-out)
- 추론 인식 모델 선택 (한/영 키워드 기반)
- Plan→Work→Review 파이프라인 + 5관점 리뷰 + 갭 감지
- OMX 호환 브릿지 알림
철학: bash 직역 거부. 결정론적 라우팅(routing.json + select-model.sh)과 계정 풀 (pool.sh) 은 코드로, 워크플로(계획/구현/리뷰/갭 수정) 는 본 스킬의 instructions 로 LLM 에이전트에게 가이드합니다.
1. Activation
$ohmyclaw 으로 호출되거나, 아래 조건이 감지되면 자동 활성화됩니다:
- 사용자가 "Z.ai" / "GLM" / "코딩플랜" / "lite/pro/max" 언급
- 한국어 비율 > 50% 인 코딩 태스크
- 다단계 작업이지만 단순
coding-agent 가 아닌 Plan→Work→Review 가 필요한 경우
본 스킬은 대화 시작 시 한 번 다음을 확인합니다:
echo "ZAI_CODING_PLAN=${ZAI_CODING_PLAN:-pro} CODEX_OAUTH_ENABLED=${CODEX_OAUTH_ENABLED:-false}"
ls "$(dirname $0)/routing.json" 2>/dev/null || \
ls skills/ohmyclaw/routing.json
확인 안 되면 ## 12. Doctor 섹션의 preflight 를 수행하세요.
슬래시 명령어 (Telegram/Discord/Web 공통)
모든 명령어는 /ohmyclaw 네임스페이스 아래에 있습니다 (다른 스킬의 /hud 등과 충돌 방지).
| 명령어 | 자연어 | 실행 | 출력 |
|---|
/ohmyclaw | "ohmyclaw 상태" "사용량 보여줘" | $SKILL/hud.sh | 플랜/계정/quota/모델 대시보드 |
/ohmyclaw compact | "상태 한 줄" | $SKILL/hud.sh --compact | 🦞 PRO | zai:230K | codex:32K | 3% |
/ohmyclaw route <task> | "이거 어떤 모델?" | $SKILL/select-model.sh "<task>" auto --json | 라우팅 JSON |
/ohmyclaw pool | "계정 상태" | $SKILL/pool.sh status | 풀 + cooldown 표 |
/ohmyclaw doctor | "점검해줘" | § 12 bash snippet | 10항목 점검 |
/ohmyclaw exec <task> | "이거 해줘" | § 7 → executor.md | 직접 실행 |
/ohmyclaw interview [topic] | "요구사항 좀 정리해줘" | $SKILL/cli.sh interview | Socratic 4차원 버튼 인터뷰 (우로보로스) |
/ohmyclaw menu | "명령어 보여줘" | $SKILL/cli.sh commands menu | 슬래시 명령 팔레트(버튼) |
/ohmyclaw plan <task> | "계획 세워줘" | § 7 → planner.md | 계획 수립 |
/ohmyclaw plan --consensus | "합의해서 계획" | § 7 → planner→architect→critic | 합의 루프 |
/ohmyclaw review | "리뷰 좀" | § 7 → reviewer.md | 5관점 + 갭 감지 |
/ohmyclaw team N <task> | "3명이서 해" | § 7 → team-*.md | 병렬 워커 |
/ohmyclaw ralph <task> | "끝까지 해" | § 7 → executor+verifier | 루프 |
/ohmyclaw debug <task> | "버그 잡아" | § 7 → debugger.md | 4단계 RCA |
에이전트 인식 규칙: 사용자가 /ohmyclaw 로 시작하는 명령어를 입력하면 ohmyclaw 스킬의 스크립트를 즉시 bash 로 실행하고 결과를 보여줍니다. OMC 의 /hud 와 혼동 금지 — /ohmyclaw 는 반드시 ohmyclaw 스킬 경로(~/.openclaw/skills/ohmyclaw/ 또는 ~/.openclaw/repos/ohmyclaw/skills/ohmyclaw/)의 스크립트를 실행합니다.
자연어 매핑: "ohmyclaw 사용량" → /ohmyclaw, "모델 뭐로?" → /ohmyclaw route, "계정 상태" → /ohmyclaw pool
주의: /hud 단독은 OMC HUD 입니다. ohmyclaw 대시보드는 반드시 /ohmyclaw 으로 호출하세요.
Telegram 슬래시 명령어 등록 + 버튼 팔레트 (v1.6.0)
cli.sh commands 가 텔레그램 슬래시 명령어를 관리합니다. omc_ 네임스페이스(예: /omc_interview, /omc_exec)로 타 봇 명령과 충돌을 막고, /interview·/ohmyclaw interview 같은 친근한 alias 도 인식합니다.
SKILL="$(dirname $(realpath skills/ohmyclaw/SKILL.md))/skills/ohmyclaw"
"$SKILL/cli.sh" commands list
"$SKILL/cli.sh" commands botfather
"$SKILL/cli.sh" commands register
"$SKILL/cli.sh" commands menu --to $CHAT_ID
"$SKILL/cli.sh" commands dispatch --to $CHAT_ID "/omc_interview 결제 모듈"
openclaw 2026.6.6 에는 setMyCommands 전용 CLI 가 없어 register 는 적용 페이로드를 출력합니다. 버튼은 모두 실제 openclaw message send --presentation (MessagePresentation) API 로 발화합니다 — 구버전 --buttons {inline_keyboard} 는 더 이상 인식되지 않습니다.
인터뷰: /ohmyclaw interview [topic] 은 goal/constraint/success/context 4차원을 Socratic 버튼 질문으로 구체화하여 모호성 ≤ 0.2 까지 좁힌 뒤 결과를 interview-result state 에 저장합니다. 자세한 흐름: docs/ask-flow.md.
🔴 인터뷰 비동기 오케스트레이션 (에이전트 필수 동작, v1.8.0)
순수 CLI interview <topic> 는 동기라 버튼 클릭을 못 받습니다(폴백 → degraded:true). 버튼이 실제로 동작하려면 에이전트가 아래 상태머신을 구동해야 합니다. openclaw 는 command-액션 버튼 클릭을 synthetic 메시지(/omc_iv <value>)로 에이전트에게 전달합니다.
| 인바운드 (사용자/버튼) | 에이전트가 실행할 것 |
|---|
/ohmyclaw interview <topic> 또는 /omc_interview <topic> | cli.sh interview start "<topic>" --to <chat_id> (chat_id = inbound_meta.chat_id) |
/omc_iv <value> (옵션 버튼 클릭) | cli.sh interview answer "<value>" |
/omc_iv __other__ (Other 버튼) | 사용자에게 "답을 입력하세요" 안내 후, 다음 사용자 텍스트를 받아 cli.sh interview answer "<사용자 텍스트>" |
start/answer 는 자동으로 다음 질문의 버튼을 발화합니다. 에이전트는 추가 메시지를 보낼 필요 없이 그대로 두면 됩니다({"status":"awaiting","dimension":...} 출력 = 다음 질문 대기 중).
- 종료 시
{"savedBy":"interview","mode":"async","degraded":false,...} 출력 + interview-result state 저장 + 요약 메시지 발송. 클릭으로 받은 답이므로 degraded:false(진짜 인터뷰).
- 진행 점검:
cli.sh interview status · 중단: cli.sh interview cancel.
⚠️ chat_id 없이(--to 누락 → 기본 self) 보내면 텔레그램이 거부합니다. 반드시 인바운드 컨텍스트의 chat_id 를 넘기세요.
2. Plan tiers
| 플랜 | 가격 | 모델 | 일일 토큰 | 동시 워커 | full 파이프라인 |
|---|
| Lite | $3/월 | GLM-5 Turbo, GLM-5 | 1.5M | 2 | ⚠️ 제한 |
| Pro | $15/월 | + GLM-5.1, GLM-5.2 | 8M | 4 | ✅ |
| Max | $30/월 | 풀 모델 + 우선 슬롯 | 25M | 7 | ✅ |
가입: https://z.ai/subscribe?ic=OTYO9JPFNV
활성 플랜 변경:
export ZAI_CODING_PLAN=pro
echo 'export ZAI_CODING_PLAN=pro' >> ~/.zshrc
export CODEX_OAUTH_ENABLED=true
Lite 플랜 사용자: GLM-5.1/GLM-5.2 미포함입니다. routing.json 의 plan_block 규칙(P95)이 자동으로 glm-5.1/glm-5.2 → glm-5 로 강등합니다.
3. Routing core
본 스킬의 결정론적 라우터는 select-model.sh 입니다. 모델/플랜/매트릭스/추론 키워드는 routing.json 단일 소스에서 읽습니다.
3-1. 단일 태스크 라우팅
SKILL_DIR="$(dirname $(realpath skills/ohmyclaw/SKILL.md))"
"$SKILL_DIR/select-model.sh" "REST API 인증 미들웨어 설계" auto
"$SKILL_DIR/select-model.sh" "분산 합의 알고리즘 정합성 증명" reasoning --plan=max
"$SKILL_DIR/select-model.sh" "전체 인증 시스템 마이그레이션 설계" coding_arch --plan=pro --codex --json
JSON 출력 예시:
{
"model": "gpt-5.5",
"category": "reasoning",
"complexity": { "score": 8, "tier": "MEDIUM" },
"koreanRatio": 1.0,
"reasoningHeavy": true,
"activePlan": "pro",
"codexOauthEnabled": true,
"reason": "reasoning_heavy + codex (P82, OMX frontier, extended thinking)",
"fallbackChain": ["gpt-5.5", "gpt-5.4", "glm-5.1", "glm-5", "glm-5-turbo"]
}
3-2. 라우팅 매트릭스 (Pro 기준)
| 카테고리 | LOW | MEDIUM | HIGH |
|---|
| 코딩 (일반) | glm-5-turbo | glm-5 | glm-5.1 |
| 코딩 (아키텍처) | glm-5 | glm-5.1 | glm-5.1 |
| 한국어 NLP | glm-5-turbo | glm-5 | glm-5.1 |
| 추론 | glm-5-turbo | glm-5 | glm-5.1 |
| 디버깅 | glm-5-turbo | glm-5 | glm-5.1 |
| 보안 | glm-5 | glm-5.1 | glm-5.1 |
| 콘텐츠 생성 | glm-5-turbo | glm-5 | glm-5.1 |
| 데이터 분석 | glm-5-turbo | glm-5 | glm-5.1 |
- Lite: HIGH 슬롯 전부
glm-5 로 강등 (GLM-5.1 미포함)
- Max: MEDIUM 코딩/리뷰도 적극적으로
glm-5.1 사용
- +Codex: 코딩(아키/일반 HIGH), 디버깅(HIGH), 보안(MEDIUM/HIGH), 추론(HIGH), 데이터분석(HIGH) →
gpt-5.5 (OMX frontier; gpt-5.4 는 legacy fallback)
전체 매트릭스: routing.json#matrix.<plan> 참조.
3-3. 우선순위 규칙 (first-match)
- P100 — 사용자 명시 오버라이드 (
--plan= / --codex)
- P95 — 활성 플랜 미허용 모델 자동 강등
- P90 — 한국어 비율 >70% + NLP/콘텐츠 → GLM 시리즈 우선
- P82 — 🧠 reasoning_heavy + Codex 활성 → gpt-5.5 (OMX frontier, extended thinking)
- P81 — 🧠 reasoning_heavy + Pro/Max → glm-5.1
- P81b — 🧠 reasoning_heavy + Lite → glm-5 (상한)
- P80 — Codex 활성 + 고난도 아키/보안/추론/분석 → gpt-5.5
- P75 — Pro/Max + HIGH 복잡도 → glm-5.1
- P70 — Lite + HIGH → glm-5 (상한)
- P50 — LOW → glm-5-turbo
- P0 — 기본 → glm-5
4. Reasoning-aware routing
본 스킬의 핵심 차별화. 복잡도 점수가 LOW 라도 추론 신호가 감지되면 reasoning_score 최상위 모델로 격상합니다 (짧지만 어려운 증명/알고리즘 태스크 대응).
4-1. 감지 키워드
- 한국어: 증명, 알고리즘, 복잡도, 수학, 최적화, 정합성, 상태 머신, 동형, 불변조건, race condition, 분산 합의, 정렬 증명, lock-free, Byzantine
- 영문: prove, proof, invariant, complexity, big-O, algorithm, optimization, theorem, derive, tradeoff, distributed consensus, lock-free, byzantine
- 카테고리 힌트:
reasoning, coding_arch, data_analysis, security
4-2. 점수 계산
- 한국어 키워드 매치: +2
- 영문 키워드 매치: +2
- 카테고리 힌트: +1
- 합산 ≥ 2 → reasoning_heavy = true
4-3. 격상 분기
| 조건 | 선택 모델 | 근거 |
|---|
| reasoning_heavy + Codex 활성 | gpt-5.5 | OMX DEFAULT_FRONTIER_MODEL (점수표 없음, frontier role) |
| reasoning_heavy + Pro/Max | glm-5.1 | reasoning 95 (Z.ai 자체 매트릭스 최상위) |
| reasoning_heavy + Lite | glm-5 (상한) | Lite 플랜 cap |
Codex fallback 시 gpt-5.4 (legacy) → glm-5.1 순으로 강등.
전체 정의: routing.json#reasoningDetection
5. Codex OAuth overlay (선택)
ChatGPT Plus($20/월) 또는 Pro($200/월) 구독 보유 시, OpenAI Codex CLI OAuth 로 gpt-5.5 (OMX DEFAULT_FRONTIER_MODEL) 을 추가 비용 없이 병행할 수 있습니다. gpt-5.4 는 legacy fallback 으로 유지됩니다.
5-1. 셋업 (한 번만)
brew install codex
codex login
codex whoami
CODEX_HOME=~/.codex-acct2 codex login
export CODEX_OAUTH_ENABLED=true
5-2. 오버레이 동작
CODEX_OAUTH_ENABLED=true 일 때 아래 슬롯이 gpt-5.5 로 자동 오버레이됩니다 (codex CLI 가 5.5 미인식 시 → gpt-5.4 legacy fallback):
| 카테고리 | 복잡도 | Z.ai 단독 | + Codex |
|---|
| coding_arch | MEDIUM/HIGH | glm-5.1 | gpt-5.5 |
| coding_general | HIGH | glm-5.1 | gpt-5.5 |
| debugging | HIGH | glm-5.1 | gpt-5.5 |
| security | MEDIUM/HIGH | glm-5.1 | gpt-5.5 |
| reasoning | HIGH | glm-5.1 | gpt-5.5 🧠 |
| data_analysis | HIGH | glm-5.1 | gpt-5.5 🧠 |
🧠 = extended thinking. gpt-5.5 는 OMX (oh-my-codex) 의 DEFAULT_FRONTIER_MODEL 로 박혀있어 점수표 추정 없이 frontier role 그대로 사용.
rate limit 보호: Codex 동시 워커는 최대 3개로 제한 (routing.json#concurrency)
5-3. 트러블슈팅
| 증상 | 해결 |
|---|
codex: command not found | brew install codex 또는 npm i -g @openai/codex |
| 401 Unauthorized 간헐 | codex login 재실행 (refresh token 30일) |
No subscription found | Free 계정. Plus/Pro 결제 후 재시도 |
| Rate limit 초과 | § 6 멀티 계정 풀 사용 |
Model login expired on the gateway for <p> 반복 | 게이트웨이 provider 로그인 만료. openclaw models auth login --provider <p> --force 후 자동 복구. provider-health 게이트가 만료 provider 를 자동으로 건너뛴다 (§ 6-6). 즉시 격리: pool.sh quarantine <p> |
Model Fallback: ... auth permanent 스팸 | 위와 동일 — 만료 provider 로 반복 호출 중. 재로그인하면 멈춘다 |
5-4. Experimental Claude Code CLI delegation (opt-in)
상태: 실험적 / 기본 비활성 / 언제든 제거 가능
공식 Claude Code CLI 를 로컬에서 직접 실행하는 delegation 경로만 다룹니다. 제3자 도구에서의 구독 사용 정책이 바뀌면 이 경로는 막히거나 지원 중단될 수 있습니다. 따라서 ohmyclaw 에서는 기본 라우팅으로 쓰지 않고, 명시 opt-in 일 때만 제한적으로 노출합니다.
활성화 조건:
export CLAUDECLI_DELEGATION_ENABLED=true
claude login
제한:
- 기본 경로 아님, fallback 우선
- HIGH 난도의
reasoning, coding_arch, security 만 제한적으로 오버레이
- direct OAuth token ingestion 금지, 공식 CLI 세션만 사용
- helper:
skills/ohmyclaw/claude-delegate.sh
예시 (단일 계정):
SKILL=skills/ohmyclaw
MODEL=$($SKILL/select-model.sh "보안 경계 재설계" security --claudecli --json)
$SKILL/claude-delegate.sh "보안 경계 재설계" --cwd="$PROJECT"
5-4-1. Claude CLI 멀티계정 (CLAUDE_CONFIG_DIR)
Codex 의 CODEX_HOME 과 동일 패턴으로 Claude CLI 도 계정별 분리 가능. 공식 환경변수 CLAUDE_CONFIG_DIR 가 keychain 대신 해당 디렉토리의 .credentials.json 을 우선 사용합니다 (anthropics/claude-code 공식 동작, "Respect CLAUDE_CONFIG_DIR everywhere").
셋업 (한 번만, 계정마다):
CLAUDE_CONFIG_DIR=~/.claude-acct2 claude login
CLAUDE_CONFIG_DIR=~/.claude-acct3 claude login
export CLAUDECLI_DELEGATION_ENABLED=true
3가지 호출 방식:
SKILL=skills/ohmyclaw
$SKILL/claude-delegate.sh "..." --config-dir=~/.claude-acct2 --cwd="$PROJECT"
CLAUDE_CONFIG_DIR=~/.claude-acct3 $SKILL/claude-delegate.sh "..." --cwd="$PROJECT"
$SKILL/claude-delegate.sh "..." --from-pool --cwd="$PROJECT"
--from-pool 사용 시 호출 실패하면 해당 계정에 자동으로 cooldown (60s → 120s → ... 최대 600s) 이 걸리고 다음 호출은 다른 계정 픽.
$SKILL/pool.sh status claudecli
$SKILL/pool.sh next claude-code-experimental
$SKILL/pool.sh fanout claudecli
macOS 주의: keychain 에 이미 저장된 credentials 가 있다면 첫 로그인이 keychain 으로 들어갈 수 있음. CLAUDE_CONFIG_DIR=... 를 명시하고 로그인하면 해당 디렉토리의 .credentials.json 으로 우선 저장됨. 문제가 생기면 claude doctor 로 진단.
6. Multi-account routing (계정 풀)
같은 모델을 여러 계정에 분산 해서 rate limit 을 회피하거나, 같은 태스크를 여러 계정에 동시 발사(fan-out) 할 수 있습니다. 본 기능은 pool.sh 가 담당합니다.
6-1. 풀 정의
routing.json#accounts.pools 에서 각 프로바이더 풀과 계정을 선언합니다:
{
"accounts": {
"pools": {
"zai": {
"providerId": "zai",
"modelPrefixes": ["glm-"],
"accounts": [
{ "id": "zai-primary", "authType": "oauth_zai", "openclawProfile": "default", "plan": "pro", "weight": 10, "enabled": true },
{ "id": "zai-secondary", "authType": "api_key", "envKey": "ZAI_API_KEY_2", "plan": "lite", "weight": 5, "enabled": false },
{ "id": "zai-team-max", "authType": "oauth_zai", "openclawProfile": "team", "plan": "max", "weight": 15, "enabled": false }
]
},
"codex": {
"providerId": "openai-codex",
"modelPrefixes": ["gpt-"],
"optional": true,
"accounts": [
{ "id": "codex-primary", "authType": "oauth_codex", "codexHome": "~/.codex", "weight": 10, "enabled": false },
{ "id": "codex-secondary", "authType": "oauth_codex", "codexHome": "~/.codex-acct2", "weight": 10, "enabled": false }
]
},
"claudecli": {
"providerId": "anthropic-claude-cli",
"modelPrefixes": ["claude-code-"],
"optional": true,
"accounts": [
{ "id": "claudecli-primary", "authType": "oauth_claude_cli", "claudeHome": "~/.claude", "weight": 10, "enabled": false },
{ "id": "claudecli-secondary", "authType": "oauth_claude_cli", "claudeHome": "~/.claude-acct2", "weight": 10, "enabled": false },
{ "id": "claudecli-tertiary", "authType": "oauth_claude_cli", "claudeHome": "~/.claude-acct3", "weight": 10, "enabled": false }
]
}
}
}
}
모델 → 풀 매핑: prefix 기반. glm-* → zai 풀, gpt-* → codex 풀, claude-code-* → claudecli 풀. 다른 모델은 reject.
6-2. pool.sh 액션
SKILL=skills/ohmyclaw
P=$SKILL/pool.sh
$P next glm-5.1
$P next gpt-5.5
$P status
$P status zai
$P cooldown zai-primary
$P release zai-primary
$P reset
$P fanout zai
state 파일: ${OHMYCLAW_STATE_DIR:-~/.cache/ohmyclaw}/pool-state.json
6-3. select-model + pool.sh 체이닝 (가장 일반적인 패턴)
SKILL=skills/ohmyclaw
MODEL=$($SKILL/select-model.sh "$TASK" auto --plan=$PLAN ${CODEX:+--codex})
ACCOUNT_LINE=$($SKILL/pool.sh next "$MODEL")
ACCOUNT_ID=$(echo "$ACCOUNT_LINE" | cut -d'|' -f1)
AUTH_TYPE=$(echo "$ACCOUNT_LINE" | cut -d'|' -f2)
AUTH_VALUE=$(echo "$ACCOUNT_LINE" | cut -d'|' -f3)
ENGINE_LINE=$($SKILL/engine.sh resolve "$MODEL" "$AUTH_TYPE" "${ROLE:-executor}")
ENGINE=${ENGINE_LINE%%|*}
CMD_TMPL=${ENGINE_LINE#*|}
case "$AUTH_TYPE" in
oauth_zai) openclaw-profile activate "$AUTH_VALUE" ;;
oauth_codex) export CODEX_HOME="$AUTH_VALUE" ;;
oauth_claude_cli) export CLAUDE_CONFIG_DIR="$AUTH_VALUE" ;;
api_key) export ZAI_API_KEY="${!AUTH_VALUE}" ;;
esac
SLOT=$($SKILL/pool.sh acquire-worker | sed -n 's/^TOKEN=//p')
[[ -z "$SLOT" ]] && { echo "[ohmyclaw] 워커 슬롯 만석 — 잠시 후 재시도"; exit 11; }
CMD=${CMD_TMPL//\{\{CWD\}\}/$(printf %q "$PROJECT")}
CMD=${CMD//\{\{TASK\}\}/$(printf %q "$TASK")}
ERRLOG=$(mktemp)
bash pty:true command:"$CMD" 2>"$ERRLOG" &
CHILD_PID=$!
echo "$CHILD_PID" > "$SLOT"
wait "$CHILD_PID"; STATUS=$?
$SKILL/pool.sh release-worker "$SLOT"
if [[ $STATUS -ne 0 ]]; then
$SKILL/pool.sh cooldown "$ACCOUNT_ID"
ACCOUNT_LINE=$($SKILL/pool.sh next "$MODEL")
fi
$SKILL/provider-health.sh scan-stderr "$ERRLOG" || true
rm -f "$ERRLOG"
6-4. Round-robin / Cooldown 동작
- Round-robin: 풀의 enabled 계정을 인덱스 modulo 회전. state 에
roundRobinIndex 저장.
- Cooldown: 실패 시
consecutiveFailures 증가, 백오프 = min(base × multiplier^(failures-1), maxCooldown). 기본: 60s → 120s → 240s → 480s → 600s (cap).
- 자동 해제: cooldown 만료 시 자동으로 다시 후보. 명시 해제는
release.
- 빈 풀: 모든 enabled 계정이 cooldown 이거나 enabled=false 면
next 가 에러.
6-6. Auth-expiry 게이트 (rate-limit cooldown 과 별개)
멀티계정 사용 중 특정 provider(openai/zai/claude-cli)의 게이트웨이 OAuth 로그인이
만료되면, openclaw 게이트웨이는 스스로 zai/glm 으로 폴백하며 exit 0(성공) 을
리턴한다. 그래서 exit code 기반 cooldown 은 발동하지 않고, 아무 처리도 안 하면
라운드로빈이 만료 provider 를 계속 되돌려줘 Model login expired ... 경고가 무한
반복된다. rate-limit(일시적, 지수 백오프)과 auth-expiry(반영구적, 재로그인 필요)는
성격이 다르므로 별도 격리(quarantine) 로 다룬다. 담당: provider-health.sh.
- 사전 게이트(proactive):
select-model.sh 가 매 선택 시 openclaw models status --json 을 TTL 캐시(기본 45s)로 조회해, 만료(expired/missing) 또는
격리된 provider 의 모델을 폴백 체인의 첫 정상 모델로 강등한다. (예:
openai 만료 → gpt-5.5 → glm-5.2)
- 사후 감지(reactive):
provider-health.sh scan-stderr 가 엔진 stderr 의
login expired / auth permanent 시그니처에서 provider 를 추출해 격리한다
(§ 6-3 recipe 8b). exit 0 폴백에도 안전.
- 격리(quarantine):
pool.sh quarantine <provider|pool> [reason] — 계정
단위 cooldown 과 달리 provider 단위, 600s cap 없이 재로그인까지 유지.
격리된 pool 의 next 는 exit 3 + 재로그인 안내를 낸다.
- 자동 복구: 재로그인 후 라이브
status=ok/static 이 감지되면 격리를 자동
해제(reconcile). 수동 해제는 pool.sh release-provider <provider>.
- 끄기:
OHMYCLAW_PROVIDER_HEALTH=false. openclaw 부재 시 무해(no-op).
provider-health.sh status
pool.sh quarantine openai auth_permanent
pool.sh release-provider openai
멀티계정 auth-order 동기화 (openclaw 네이티브 봇 경로): 한 provider 에 auth
프로파일이 여러 개(예: openai:default, openai:jjoongoo@gmail.com)면 openclaw 는
order override 가 없을 때 라운드로빈으로 번갈아 써서 만료 프로파일에 걸린다. ohmyclaw
하네스를 안 쓰는 봇(openclaw 네이티브 라우팅)에서도 이를 막으려면
provider-health.sh sync-auth-order --apply 가 프로파일 health 를 보고 openclaw
models auth order 를 동적 조정한다(전부 정상=clear/라운드로빈, 일부 만료=정상만 set,
회복 시 자동 복귀). launchd 로 주기 실행 권장 — 자세한 건 docs/auth-order-sync.md.
6-5. Fan-out 패턴 (대량 분산)
같은 태스크를 여러 계정에 동시 발사:
SKILL/pool.sh fanout zai | while IFS='|' read -r id authType authValue plan weight; do
bash pty:true workdir:~/project background:true command:"
case '$authType' in
oauth_zai) openclaw-profile activate '$authValue' ;;
esac
pi --provider zai --model glm-5.1 '$TASK'
"
done
process action:list
fan-out 권장 시점: 같은 태스크를 다른 계정으로 한 번씩 돌려서 결과를 비교하고 싶을 때 (consensus / cross-validation), 또는 한 계정 quota 가 부족할 때 분할.
6-6. 새 계정 등록 절차
Z.ai 보조 키 추가:
export ZAI_API_KEY_2="zai_..."
ChatGPT 두 번째 계정:
CODEX_HOME=~/.codex-acct2 codex login
ls ~/.codex-acct2/auth.json
CODEX_OAUTH_ENABLED=true skills/ohmyclaw/pool.sh status codex
Claude CLI 두 번째 계정:
CLAUDE_CONFIG_DIR=~/.claude-acct2 claude login
ls ~/.claude-acct2/.credentials.json
CLAUDECLI_DELEGATION_ENABLED=true skills/ohmyclaw/pool.sh status claudecli
CLAUDECLI_DELEGATION_ENABLED=true \
skills/ohmyclaw/claude-delegate.sh "리뷰 부탁" --from-pool --cwd="$PROJECT"
6-7. 전략 선택
| 전략 | 언제 | pool.sh 액션 |
|---|
round_robin (기본) | rate limit 분산, 계정별 부하 균등화 | next <model> |
fan_out | consensus, cross-validation, 대량 분할 | fanout <providerId> |
cooldown only | 단일 계정 + 실패 추적만 필요 | next + cooldown |
⚙️ Engine layer (oh-my-pi / omp via ACP)
ohmyclaw 는 모델·계정·키만 선택하고, 실제 코딩 에이전트 실행은 ACP(Agent Client Protocol) 경계로 위임합니다. 1순위 엔진은 oh-my-pi(omp) 입니다 — hashline 편집, LSP-연동 쓰기, DAP, 네이티브 grep/shell, 영속 Python 을 제공하는 코딩 엔진.
로버스트 결정 (no-fork): omp 의 27k LoC(TS+Rust) 를 포크/벤더링하지 않습니다. acpx(설치된 ACP 클라이언트) 의 escape hatch 로 omp acp 를 spawn 하므로 업스트림 유지보수 부담이 0 입니다. omp 미설치 시 acpx 내장 어댑터(pi/codex/claude)로, acpx 마저 없으면 직접 CLI 로 graceful fallback 합니다.
모델 선택 소유권 분할
| 레이어 | 소유 | 도구 |
|---|
| ohmyclaw | 모델 ID 선택, 계정/키, 풀 쿼터(round-robin/cooldown/fan-out), role→권한정책 | select-model.sh + pool.sh + routing.json |
| omp (엔진) | 엔진 툴(lsp/ast/hashline 편집), 세부 role 라우팅(smol subagent fan-out), 세션 권한(session/request_permission) | omp 내부 ModelRegistry |
ohmyclaw 가 고른 모델은 acpx --model 로 omp 세션에 주입됩니다(ACP session/set_model). omp 내부의 자체 모델 라우팅과 충돌하지 않도록, 외부에서 명시 모델을 넘기는 쪽(ohmyclaw)이 우선합니다.
engine.sh — 엔진/ACP 명령 리졸버
SKILL=skills/ohmyclaw
$SKILL/engine.sh resolve glm-5.1 oauth_zai reviewer
$SKILL/engine.sh acp-config
$SKILL/engine.sh doctor
- 후보 엔진 순서:
routing.json#engine.providerEngines[provider] (없으면 engine.preferred). glm-*→zai, gpt-*→codex, openrouter-*→openrouter.
- role→권한:
routing.json#engine.permissions (reviewer/planner/verifier → --approve-reads, executor/worker/debugger → --approve-all). omp 의 쓰기 권한 게이트와 정합.
{{CWD}} / {{TASK}} 플레이스홀더는 호출측이 치환합니다.
OHMYCLAW_ENGINE=<omp|pi|codex|claude> 로 엔진 강제, OHMYCLAW_ENGINE_FALLBACK=false 로 1순위 부재 시 에러.
acpx 실측 매핑 (v0.5.0)
| 형태 | 명령 |
|---|
| omp (escape hatch) | acpx --agent "omp acp" --model <m> --cwd <dir> <perm> --format text <task> |
| pi / codex / claude (내장 어댑터) | acpx --model <m> --cwd <dir> <perm> --format text <pi|codex|claude> <task> |
| omp (커스텀 등록 후) | acpx omp --model <m> <task> (← engine.sh acp-config 등록 시) |
acpx 글로벌 옵션(--model/--cwd/--approve-*/--format/--timeout)은 subcommand 앞에 위치해야 합니다.
7. Composable execution verbs (OMX-style)
기존 Plan→Work→Review 고정 파이프라인 대신, OMX (oh-my-codex) 의 composable verb 패턴을 채택합니다. 사용자가 동사를 선택하고, 각 동사가 prompts/ 의 role prompt 를 합성합니다.
왜 고정 파이프라인을 버렸나: OMX 의 교훈 — "사용자가 verb 를 고르는 게 더 유연하다". Plan 없이 바로 exec, review 만 따로, team 으로 병렬 — 동사별로 다른 prompt 를 조합하면 됨.
7-1. 동사 × Prompt 매핑
| 동사 | 사용법 | 합성 Prompt | 모델 카테고리 |
|---|
$ohmyclaw exec | $ohmyclaw exec "REST API 인증 미들웨어" | executor.md 단일 | auto |
$ohmyclaw team N:role | $ohmyclaw team 3:executor "타입 3개 동시 추가" | team-orchestrator.md + N × team-executor.md | reasoning / auto |
$ohmyclaw ralph | $ohmyclaw ralph "E2E 테스트 통과까지" | executor.md + verifier.md 루프 | auto + reasoning |
$ohmyclaw plan | $ohmyclaw plan "API gateway 마이그레이션" | planner.md 단일 | reasoning |
$ohmyclaw plan --consensus | $ohmyclaw plan --consensus "마이그레이션" | planner.md → architect.md → critic.md 합의 | reasoning + coding_arch |
$ohmyclaw deep-interview | $ohmyclaw deep-interview "기능 정의 명확화" | planner.md (ambiguity gating 부분만) | reasoning |
$ohmyclaw review | $ohmyclaw review src/ | reviewer.md (5관점 + 갭 감지) | reasoning |
$ohmyclaw debug | $ohmyclaw debug "TypeError at user.ts:42" | debugger.md (4단계 RCA, 3회 circuit breaker) | debugging |
$ohmyclaw verify | $ohmyclaw verify "빌드+테스트 통과" | verifier.md (PASS / FAIL / PARTIAL) | reasoning |
자세한 합성 규칙과 모델/계정 선택 패턴: prompts/README.md 참조.
7-2. Spawn 패턴 (모든 동사 공통)
ohmyclaw 는 기본적으로 에이전트가 직접 실행 합니다 (sub-agent spawn 없이). 라우터로 모델을 결정하고, 직접 코드를 읽고 쓰면서 해당 prompt 의 instructions 를 따릅니다.
직접 실행 (기본 — 권장)
SKILL=skills/ohmyclaw
MODEL=$($SKILL/select-model.sh "$TASK" <category> --plan=$PLAN ${CODEX:+--codex})
echo "추천 모델: $MODEL"
에이전트가 직접 실행할 수 있으면 별도 spawn 없이 진행합니다.
Sub-agent spawn (병렬/background — engine.sh 경유 ACP)
team 이나 ralph 처럼 병렬 또는 background 실행이 필요할 때는 engine.sh 가 결정한 ACP 명령으로 spawn 합니다. 엔진 선택(omp 우선)·권한·폴백은 engine.sh 가 담당하므로 CLI 를 직접 하드코딩하지 않습니다:
SKILL=skills/ohmyclaw
MODEL=$($SKILL/select-model.sh "$TASK" auto --plan=$PLAN ${CODEX:+--codex})
ENGINE_LINE=$($SKILL/engine.sh resolve "$MODEL" "" "${ROLE:-executor}")
CMD_TMPL=${ENGINE_LINE#*|}
CMD=${CMD_TMPL//\{\{CWD\}\}/$(printf %q "$PROJECT")}
CMD=${CMD//\{\{TASK\}\}/$(printf %q "$TASK")}
bash pty:true workdir:"$PROJECT" background:true command:"$CMD"
엔진 선택은 모델→provider→engine.sh 가 결정합니다:
glm-* → omp(설치 시) → pi 폴백 (Z.ai provider)
gpt-5.5 / gpt-5.4 → omp(설치 시) → codex 폴백 (Codex CLI + ChatGPT OAuth)
openrouter-* → omp → codex 폴백
실험적 Claude Code 위임은 skills/ohmyclaw/claude-delegate.sh 헬퍼로도 가능합니다 (engine.sh 폴백과 별개의 선택 경로).
계정 풀 연동 (선택)
ACCT=$($SKILL/pool.sh next "$MODEL")
ID=$(echo "$ACCT" | cut -d'|' -f1)
AUTH_TYPE=$(echo "$ACCT" | cut -d'|' -f2)
AUTH_VAL=$(echo "$ACCT" | cut -d'|' -f3)
case "$AUTH_TYPE" in
oauth_zai) openclaw-profile activate "$AUTH_VAL" ;;
oauth_codex) export CODEX_HOME="$AUTH_VAL" ;;
oauth_claude_cli) export CLAUDE_CONFIG_DIR="$AUTH_VAL" ;;
api_key) export ZAI_API_KEY="${!AUTH_VAL}" ;;
esac
[[ $? -ne 0 ]] && $SKILL/pool.sh cooldown "$ID"
7-3. $ohmyclaw ralph — 끝까지 루프
┌──────────────┐
│ executor │ ← prompts/executor.md
│ (구현) │
└──────┬───────┘
↓
┌──────────────┐
│ verifier │ ← prompts/verifier.md
│ (검증) │
└──────┬───────┘
┌───┴───┐
│PASS? │
└───┬───┘
예 │ │ 아니오
↓ ↓
COMPLETE 다시 executor (max N 회)
lite=2 / pro=3 / max=4
fixLoopMaxIterations: routing.json#plans 참조
- N 회 소진 → ESCALATED →
openclaw system event ... --mode now
7-4. $ohmyclaw plan --consensus — 합의 루프
planner → architect → critic
↑_________________________↓ (REJECT → planner 재시도, max 3 라운드)
planner.md 가 초안 작성 → .omx/plans/<name>.md 저장
architect.md 가 read-only 분석 + 트레이드오프 표
critic.md 가 OKAY / REJECT 판정
--interactive 플래그 시 사용자 승인 게이트 추가
7-5. $ohmyclaw team — 병렬 워커
team-orchestrator.md 1 인스턴스가 리더
team-executor.md × N 인스턴스가 워커
- 워커 간 context isolation (다른 워커 작업물 못 봄)
- 동시 워커 수: 활성 플랜의
concurrency.maxWorkers 자동 적용 (lite=2, pro=4, max=7)
7-6. $ohmyclaw review — 5관점 + 갭 감지
reviewer.md 가 단일 패스로 5 stage 를 수행합니다:
- Spec compliance — 요구사항 커버 여부
- Security (OWASP) — 비밀 키, injection, auth
- Quality — 로직 결함, 에러 핸들링, SOLID
- Maintainability — 명명, 복잡도, 테스트 가능성
- Gap detection — assumption_injection / scope_creep / direction_drift / missing_core / over_engineering
Verdict: APPROVE / REQUEST_CHANGES / GAP_DETECTED
갭 발견 시:
openclaw system event \
--text "[gap_detected] ${GAP_TYPE}: ${GAP_REASON}" --mode now
→ 1회 fix loop 후에도 남아있으면 ESCALATED.
우로보로스는 엔진 무관 (omp 이식 후에도 불변): prompts/reviewer.md 는 이미 omp 엔진 툴 lsp_diagnostics / ast_grep_search 를 호출하도록 작성돼 있습니다. 엔진을 omp 로 바꾸면 이 툴들이 실제로 채워져 5관점 리뷰가 더 정확해집니다. reviewer 는 read-only role 이므로 engine.sh 가 --approve-reads 권한으로 spawn 합니다(쓰기 차단 = omp session/request_permission 정합). 갭 5유형(assumption_injection/scope_creep/direction_drift/missing_core/over_engineering)과 GAP_DETECTED→fix 1회→재리뷰→ESCALATED 제어흐름은 프롬프트/오케스트레이션 계약이므로 엔진 교체와 무관하게 그대로 유지됩니다.
7-6-1. GAP_DETECTED 자동 게이트 (v1.5.0+)
오케스트레이터(이 SKILL.md 를 따르는 LLM 에이전트)는 reviewer 가 GAP_DETECTED verdict 를 JSON 으로 출력하면 그 JSON 을 즉시 cli.sh gap-gate 로 파이프해야 한다.
REVIEWER_JSON=$(bash workdir:"$PROJECT" command:"$RCMD")
echo "$REVIEWER_JSON" \
| skills/ohmyclaw/cli.sh gap-gate --to "$CHAT_ID" --timeout 120
gap-gate 는 사용자에게 3가지 선택지를 Telegram 인라인 버튼으로 제시한 후 응답을 action JSON 으로 변환한다. 오케스트레이터는 action 에 따라 다음 단계를 결정한다:
action | 오케스트레이터 다음 단계 |
|---|
fix-loop | executor 재호출. 요청 prompt 에 direction 필드(수정 방향)를 포함시킨다. fix loop 는 최대 1회 (fixIteration < 1). 재실행 후 반드시 reviewer 를 다시 호출해 재리뷰한다. |
force-approve | GAP_DETECTED verdict 를 APPROVE 로 처리하고 다음 파이프라인 단계(session-end 등)로 진행한다. |
escalated | 기존 ESCALATED 흐름과 동일. userInput 에 담긴 사용자 자유 답변을 그대로 다음 실행 지시로 사용하거나 보고 후 대기한다. |
GAP_RESULT=$(echo "$REVIEWER_JSON" | skills/ohmyclaw/cli.sh gap-gate --to "$CHAT_ID")
ACTION=$(echo "$GAP_RESULT" | jq -r '.action')
case "$ACTION" in
fix-loop)
DIRECTION=$(echo "$GAP_RESULT" | jq -r '.direction')
FIX_ITER=$(echo "$GAP_RESULT" | jq -r '.fixIteration')
if [[ "$FIX_ITER" -le 1 ]]; then
bash workdir:"$PROJECT" command:"$EXEC_CMD -- fix: $DIRECTION"
else
openclaw system event --text "[ESCALATED] fix loop 한도 초과" --mode now
fi
;;
force-approve)
openclaw system event --text "[session-end] user override: gap approved" --mode now
;;
escalated)
USER_INPUT=$(echo "$GAP_RESULT" | jq -r '.userInput')
openclaw system event --text "[ESCALATED] $USER_INPUT" --mode now
;;
esac
중요: prompts/reviewer.md 본문은 변경되지 않으며, 본 게이트는 오케스트레이터 레벨 에서만 동작한다. reviewer 는 여전히 동일한 5관점 + 갭 감지 verdict 를 출력할 뿐이고, cli.sh gap-gate 가 그 verdict 를 가로채어 사용자 결정을 중재한다. 우로보로스(prompts/reviewer.md) 본문 불변 원칙은 v1.5.0 에서도 유지된다.
8. Provenance (OMC + OMX 어디서 왔나)
본 스킬의 prompts 와 동사 어휘는 두 소스에서 영감을 받았습니다:
| 출처 | 가져온 것 | 어떻게 적응 |
|---|
| OMX (oh-my-codex, MIT) | prompts/ XML contract 포맷, verb 패턴 ($ralph/$team/$plan), role 분리 (executor/verifier/architect/critic) | 카피 + ## ohmyclaw integration 블록, 모델/계정 선택 통합 |
| OMC (oh-my-claudecode) | ralph loop, deep-interview gating, team isolation, ultraqa cycling, ai-slop-cleaner 원칙 | 동사 이름 공유, reviewer.md Stage 5 갭 감지 |
| Ouroboros (Q00/ouroboros) | 명확성 게이트 철학 (실제 매커니즘은 4차원 가중 Ambiguity Score ≤0.2). 갭 유형 5종(assumption_injection/scope_creep/direction_drift/missing_core/over_engineering)은 본 프로젝트 자체 분류 — Ouroboros 자체 enumerator 가 아님 | reviewer.md Stage 5 로 통합 |
원본 참조: https://github.com/Yeachan-Heo/oh-my-codex (MIT)
9. Bridge notifications (OMX 호환)
본 스킬은 OMX (oh-my-codex) 의 OpenClaw 통합 contract 를 따라 lifecycle 이벤트를 발신합니다.
9-1. 활성 게이트
export OMX_OPENCLAW=1
export OMX_OPENCLAW_COMMAND=1
export HOOKS_TOKEN="<bearer-token>"
export OMX_OPENCLAW_COMMAND_TIMEOUT_MS=120000
9-2. 상태 → 훅 매핑
| 상태 전이 | OMX 훅 |
|---|
IDLE → PLANNING | session-start |
WORKING → ESCALATED | ask-user-question |
→ COMPLETE | session-end |
사용자 취소 / kill | stop |
agent idle > 60s | session-idle |
9-3. 발신 예시 — 구조화 JSON 페이로드 (v1.1.0+)
v1.1.0 부터 이벤트는 schemas/bridge-event.schema.json 에 정합한 구조화 JSON 페이로드로 발신합니다. --text 가 그대로 들어가는 OMX 호환 슬롯에는 payload.summary 한 줄을 넣어 하위호환을 유지합니다.
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
PAYLOAD=$(jq -c -n \
--arg v "1.0.0" --arg t "session-start" --arg ts "$TS" \
--arg sid "$SESSION_ID" --arg cycle "$CYCLE_ID" --arg proj "$PROJECT" --arg phase "PLANNING" \
--arg sum "$SUMMARY" \
--argjson tasks "$(printf '%s\n' "${TOP_TASKS[@]}" | jq -R . | jq -cs .)" \
--argjson risks "$(printf '%s\n' "${RISKS[@]}" | jq -R . | jq -cs .)" \
'{version:$v, type:$t, ts:$ts,
session:{id:$sid, cycle:$cycle, project:$proj, phase:$phase},
payload:{summary:$sum, priorityTasks:$tasks, risks:$risks}}')
openclaw system event --text "$PAYLOAD" --mode now
PAYLOAD=$(jq -c -n \
--arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg sid "$SESSION_ID" \
--arg q "$Q" --arg imp "$IMPACT" --arg rec "$RECOMMENDED" \
'{version:"1.0.0", type:"ask-user-question", ts:$ts,
session:{id:$sid, phase:"ESCALATED"},
payload:{summary:$q, question:$q, impact:$imp, recommended:$rec}}')
openclaw system event --text "$PAYLOAD" --mode now
PAYLOAD=$(jq -c -n \
--arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg sid "$SESSION_ID" \
--arg gt "$GAP_TYPE" --arg gr "$GAP_REASON" --argjson fi "${FIX_ITER:-0}" \
'{version:"1.0.0", type:"gap-detected", ts:$ts,
session:{id:$sid, phase:"REVIEWING"},
payload:{summary:("[" + $gt + "] " + $gr), gapType:$gt, gapReason:$gr, fixIteration:$fi}}')
openclaw system event --text "$PAYLOAD" --mode now
- 스키마:
skills/ohmyclaw/schemas/bridge-event.schema.json
- 검증:
make schema (CI 에서 강제), 또는 engine.sh doctor
- type 종류:
session-start/session-end/session-idle/stop/ask-user-question/gap-detected/phase-transition
- gapType 5종:
assumption_injection / scope_creep / direction_drift / missing_core / over_engineering
- 하위호환: 외부 수신자가 텍스트 1줄만 기대해도
payload.summary 만 읽으면 동작
9-4. 한국어 우선 instruction
OMX 의 Korean-first 패턴을 따릅니다. 모든 hook instruction 은 한국어로 발신하고, 구조화된 필드를 사용합니다 (요약/우선순위/주의사항/성과/검증/다음).
10. Examples
10-1. 단순 1회성 라우팅
SKILL=skills/ohmyclaw
MODEL=$($SKILL/select-model.sh "이 함수에 한국어 주석 추가해줘" auto --plan=pro)
CMD_TMPL=$($SKILL/engine.sh resolve "$MODEL" "" executor | cut -d'|' -f2)
CMD=${CMD_TMPL//\{\{CWD\}\}/$(printf %q "$HOME/project")}
CMD=${CMD//\{\{TASK\}\}/$(printf %q "이 함수에 한국어 주석 추가해줘")}
bash workdir:~/project command:"$CMD"
10-2. parallel 모드 (3개 독립 task)
SKILL=skills/ohmyclaw
PLAN=pro
for i in 1 2 3; do
TASK="api/route$i.ts 에 인증 미들웨어 추가 (DoD: 기존 테스트 통과 + 새 인증 테스트 1개)"
MODEL=$($SKILL/select-model.sh "$TASK" coding_general --plan=$PLAN)
CMD_TMPL=$($SKILL/engine.sh resolve "$MODEL" "" executor | cut -d'|' -f2)
CMD=${CMD_TMPL//\{\{CWD\}\}/$(printf %q "$HOME/project")}
CMD=${CMD//\{\{TASK\}\}/$(printf %q "$TASK")}
bash pty:true workdir:~/project background:true command:"$CMD"
done
process action:list
process action:log sessionId:XXX
REVIEWER_MODEL=$($SKILL/select-model.sh "review 3 routes" reasoning --plan=$PLAN)
RCMD_TMPL=$($SKILL/engine.sh resolve "$REVIEWER_MODEL" "" reviewer | cut -d'|' -f2)
RCMD=${RCMD_TMPL//\{\{CWD\}\}/$(printf %q "$HOME/project")}
RCMD=${RCMD//\{\{TASK\}\}/$(printf %q "route1-3.ts 5관점 리뷰+갭 감지")}
bash workdir:~/project command:"$RCMD"
10-3. full 모드 (Plan→Work→Review)
SKILL=skills/ohmyclaw
PLAN=pro
CYCLE_ID=cycle-$(date +%Y%m%d-%H%M%S)
openclaw system event --text "[session-start] cycle=$CYCLE_ID 요약: TODO 검색/필터/영속화" --mode now
PLANNER=$($SKILL/select-model.sh "decompose: TODO 검색 필터 영속화" reasoning --plan=$PLAN)
PCMD_TMPL=$($SKILL/engine.sh resolve "$PLANNER" "" planner | cut -d'|' -f2)
PCMD=${PCMD_TMPL//\{\{CWD\}\}/$(printf %q "$HOME/project")}
PCMD=${PCMD//\{\{TASK\}\}/$(printf %q "plan-only: TODO 검색/필터/영속화 분해")}
bash workdir:~/project command:"$PCMD" > /tmp/plan_v1.yaml
cat /tmp/plan_v1.yaml
read -p "이 plan 으로 진행할까요? (y/n) " ans
[[ "$ans" != "y" ]] && exit 1
yq '.tasks[] | [.id, .content, .category, .dod] | @tsv' /tmp/plan_v1.yaml | \
while IFS=$'\t' read tid content cat dod; do
m=$($SKILL/select-model.sh "$content" "$cat" --plan=$PLAN)
CMD_TMPL=$($SKILL/engine.sh resolve "$m" "" executor | cut -d'|' -f2)
CMD=${CMD_TMPL//\{\{CWD\}\}/$(printf %q "$HOME/project")}
CMD=${CMD//\{\{TASK\}\}/$(printf %q "[$tid] $content (DoD: $dod)")}
bash pty:true workdir:~/project background:true command:"$CMD"
done
process action:list
REVIEWER=$($SKILL/select-model.sh "5-perspective review + gap" reasoning --plan=$PLAN)
RCMD_TMPL=$($SKILL/engine.sh resolve "$REVIEWER" "" reviewer | cut -d'|' -f2)
RCMD=${RCMD_TMPL//\{\{CWD\}\}/$(printf %q "$HOME/project")}
RCMD=${RCMD//\{\{TASK\}\}/$(printf %q "5관점 리뷰 + 갭 감지")}
bash workdir:~/project command:"$RCMD"
10-4. 추론 집약 + Codex
SKILL=skills/ohmyclaw
$SKILL/select-model.sh "분산 락의 정합성 증명과 race condition 케이스 분석" \
reasoning --plan=pro --codex --json
11. Doctor / preflight
스킬 시작 시 자동 또는 수동 점검:
SKILL=skills/ohmyclaw
echo "=== ohmyclaw doctor ==="
command -v jq >/dev/null && echo "✓ jq" || { echo "✗ jq missing"; exit 1; }
test -f "$SKILL/routing.json" && \
jq empty "$SKILL/routing.json" && echo "✓ routing.json valid" || echo "✗ routing.json invalid"
test -x "$SKILL/select-model.sh" && echo "✓ select-model.sh executable" || echo "✗ chmod +x needed"
test -x "$SKILL/pool.sh" && echo "✓ pool.sh executable" || echo "✗ chmod +x needed"
PLAN="${ZAI_CODING_PLAN:-pro}"
case "$PLAN" in lite|pro|max) echo "✓ plan=$PLAN" ;; *) echo "✗ invalid ZAI_CODING_PLAN" ;; esac
[[ -n "${ZAI_API_KEY:-}" ]] && echo "✓ ZAI_API_KEY set" || \
echo "⚠ ZAI_API_KEY not in env (openclaw config may have it)"
if [[ "${CODEX_OAUTH_ENABLED:-false}" == "true" ]]; then
test -f ~/.codex/auth.json && echo "✓ codex auth.json" || echo "✗ codex login needed"
test -f ~/.codex-acct2/auth.json && echo "✓ codex-acct2 auth.json" || echo "ℹ codex-acct2 (선택)"
fi
$SKILL/select-model.sh "smoke test" coding_general --plan=$PLAN >/dev/null && \
echo "✓ router smoke test" || echo "✗ router failed"
$SKILL/pool.sh status zai 2>&1 | grep -q "enabled=true" && echo "✓ zai pool has enabled account" || \
echo "⚠ zai pool 모든 계정 enabled=false (routing.json 확인)"
$SKILL/pool.sh next glm-5 >/dev/null 2>&1 && echo "✓ pool round-robin smoke test" || \
echo "✗ pool.sh next 실패"
test -x "$SKILL/engine.sh" && echo "✓ engine.sh executable" || echo "✗ chmod +x engine.sh needed"
command -v acpx >/dev/null && echo "✓ acpx ($(acpx --version 2>/dev/null | head -1))" || \
echo "⚠ acpx 미설치 — 'npm i -g @openclaw/acpx' (없으면 직접 CLI 폴백만 가능)"
command -v omp >/dev/null && echo "✓ omp (preferred engine)" || \
echo "⚠ omp 미설치 — 폴백 동작. 'curl -fsSL https://omp.sh/install | sh'"
$SKILL/engine.sh doctor >/dev/null 2>&1 && echo "✓ engine.sh doctor OK" || echo "✗ engine.sh doctor 실패"
기대 출력: ✓ * 10–14개 (omp/acpx 미설치는 ⚠ 폴백 정상). 실패(✗) 시 해당 항목 해결 후 재시도.
엔진 경계 상세 점검은 $SKILL/engine.sh doctor 단독 실행.
CI/로컬 통합 점검: 리포 루트에서 make ci 실행 — bash -n, shellcheck(설치 시), routing/bridge-event JSON Schema (ajv-cli), engine doctor, bats 58+ 케이스 까지 한 번에. CI 워크플로(.github/workflows/ci.yml)가 PR 마다 동일 게이트로 강제합니다.
12. Rules / safety
- 모델 선택은 항상
select-model.sh 통과 — 직접 모델 ID 하드코딩 금지. 플랜 변경 시 자동 강등이 깨집니다.
- Plan 단계 HITL 게이트는 절대 생략 금지 — full 모드에서 사용자 승인 없이 워커 스폰 금지. ralplan 패턴 강제.
- 워커 간 context isolation 유지 — 한 워커가 다른 워커의 작업물을 읽지 않도록.
team 패턴.
- 갭 감지 시 fix loop 1회 후 무조건 ESCALATED — 무한 fix 방지. 사용자 결정 우선.
- Codex OAuth 없으면 명시 안 함 —
CODEX_OAUTH_ENABLED=false (기본) 일 때 gpt-5.5 / gpt-5.4 추천 금지.
- Lite 플랜에서 glm-5.1 강제 금지 —
select-model.sh 의 cap_for_lite 가 자동 강등하지만, 사용자가 --plan=lite 명시 시 절대 우회 금지.
- bridge notification 은 best-effort — 발신 실패가 파이프라인을 차단하지 않도록
|| true 패턴.
- 모든 Korean-first instruction 은 한국어로 발신 — OMX 호환성.
- 민감 정보는 로그에 안 찍음 — API 키/토큰은 항상 env 참조, instruction 텍스트에 평문 포함 금지.
- destructive ops 는 ralplan 게이트 후 진행 —
git push --force, rm -rf, db drop 등은 사용자 명시 승인 필수.
🧬 자체 Runtime (v1.4.0+)
ohmyclaw 는 OpenClaw 스킬 안에 살되 OMC/Ouroboros/OMX 수준의 자체 runtime 을 보유한다. OpenClaw 호스팅과 무관하게 본 runtime 으로 단독 동작 가능.
구성 요소
| 컴포넌트 | 역할 | 파일 |
|---|
| state.sh | 세션 격리 state (read/write/clear/list-active/get-status) | skills/ohmyclaw/state.sh |
| hooks.sh | pre/post 훅 디스패처 (사용자 확장 진입점) | skills/ohmyclaw/hooks.sh |
| cli.sh | verb 통합 디스패처 + 라이프사이클(skill-active, trap, 훅 자동) | skills/ohmyclaw/cli.sh |
| mcp-server.ts | MCP 서버 (도구 5종 노출, stdio JSON-RPC 2.0) | skills/ohmyclaw/src/mcp-server.ts → dist/mcp-server.js |
사용
skills/ohmyclaw/cli.sh doctor
skills/ohmyclaw/cli.sh route "API 마이그레이션 설계" coding_arch --plan=pro
skills/ohmyclaw/cli.sh state write my-key '{"x":1}'
skills/ohmyclaw/cli.sh hooks list
skills/ohmyclaw/cli.sh cancel --force
npm install && npm run build:mcp
사용자 확장 — 훅
${OHMYCLAW_HOME:-~/.ohmyclaw}/hooks/{pre,post}-<verb>.sh 에 executable 스크립트를 두면 자동 발화. 받는 env: OHMYCLAW_ACTION, OHMYCLAW_PHASE, OHMYCLAW_SESSION, OHMYCLAW_HOME, OHMYCLAW_ARGS_JSON. pre 훅이 exit ≠0 이면 verb abort (cli.sh 가 exit 7 으로 표면화), post 훅 실패는 경고만.
세션 격리
OHMYCLAW_HOME=~/.ohmyclaw skills/ohmyclaw/cli.sh state write x '{"v":1}'
OHMYCLAW_SESSION_ID=alpha skills/ohmyclaw/cli.sh state write x '{"v":1}'
다른 하네스와의 비교 (v1.4.0 이후)
| 능력 | Ouroboros | OMC | OMX | ohmyclaw 1.4.0 |
|---|
| 자체 state (세션 격리) | ✅ event sourcing | ✅ MCP state | ✅ .omx/ | ✅ state.sh |
| 사용자 hooks | △ plugins | ✅ hooks | △ | ✅ hooks.sh |
| MCP 서버 | ✅ [mcp] 변종 | ✅ 플러그인 | △ | ✅ mcp-server.ts |
| 라이프사이클 (skill-active) | ✅ runtime | ✅ skill-active | ✅ tmux | ✅ cli.sh + trap |
| 멀티 엔진 ACP | △ LiteLLM | △ | ❌ codex-only | ✅ omp/pi/codex/claude |
| 자동 테스트 / CI | ✅ pytest | ✅ | △ | ✅ 114 bats + CI |
| 멀티계정 라운드로빈 | ❌ | ❌ | △ | ✅ pool.sh |
| 한국어/Z.ai 라우팅 | ❌ | ❌ | ❌ | ✅ |
기존 코드 리뷰에서 지적된 ohmyclaw 의 "engineered software" 격차는 v1.4.0 로 대부분 닫혔다. 자세한 매핑은 docs/architecture.md 참조.
💬 Interactive Ask Flow (v1.5.0+)
사용자에게 1/2/3 + Other 텔레그램 인라인 키보드 질문을 발동할 수 있다. 4 앵커 중 1-3 자동 트리거, prompts/reviewer.md 본문 보존.
Verb 요약
| Verb | 역할 | 트리거 |
|---|
cli.sh ask | 직접 ask (구조화 선택지) | 명시 호출 |
cli.sh exec <task> | Anchor 3: ambiguity gate + 자동 ask | task 진입 시 score>0.2 |
cli.sh plan-gate | Anchor 1: planner 출력 파싱 → ask | stdin JSON ask_required:true |
cli.sh gap-gate | Anchor 2: GAP_DETECTED → ask | stdin JSON verdict:GAP_DETECTED |
Ambiguity Score (휴리스틱, 4차원)
Ambiguity = 1 - Σ(clarity × weight). weights: goal 0.35 / constraint 0.25 / success 0.25 / context 0.15. 기본 게이트 0.2.
State 통합
- ask 응답 자동 저장:
state.sh write last-ask-answer (또는 --save-as <key>)
- 후속 verb prefetch:
_run_verb 가 OHMYCLAW_LAST_ANSWER env 자동 export (TTL 3600s)
우로보로스 정합
prompts/reviewer.md 본문 불변 — Stage 5 갭 5유형 + fix 1회 → ESCALATED 흐름 100% 보존
- gap-gate 는 오케스트레이터 레벨(§7-6-1)에서만 동작 — reviewer 출력 JSON 을 stdin 으로 받아 사용자 결정 매핑
자세한 다이어그램·공식·사용 예시: docs/ask-flow.md
13. Reference
13-1. 모델 카탈로그
| 모델 | 티어 | 컨텍스트 | 코딩 | 추론 | 한국어 | 플랜 / 풀 |
|---|
| GLM-5 Turbo | LOW | 128K | 70 | 60 | 95 | zai · lite/pro/max |
| GLM-5 | MEDIUM | 128K | 88 | 82 | 95 | zai · lite/pro/max |
| GLM-5.1 ⚡ | HIGH | 204.8K | 95 | 95 | 96 | zai · pro/max |
| GLM-5.2 ⚡ 🆕 | HIGH | 204.8K | 97 | 96 | 97 | zai · pro/max (HIGH 1순위) |
| GPT-5.5 ⚡ (선택) | HIGH | — | OMX frontier | OMX frontier | OMX frontier | codex · OAuth pool |
| GPT-5.4 (legacy) | HIGH | 256K | — | — | — | codex · OAuth pool (fallback) |
⚡ = extended thinking (reasoning_mode: true).
GPT-5.5 는 OMX (oh-my-codex) DEFAULT_FRONTIER_MODEL 로 박혀있어 점수 추정 없이 frontier role 그대로 사용. GPT-5.4 는 codex CLI 가 5.5 미인식 시 자동 강등용 legacy.
13-2. 파일 구조
skills/ohmyclaw/
├── SKILL.md # 본 파일 — 워크플로 instructions (15 섹션)
├── routing.json # 결정론적 단일 소스
│ # ├── models — 5 모델 메타 (gpt-5.5 frontier + gpt-5.4 legacy)
│ # ├── plans — lite/pro/max quota/concurrency
│ # ├── matrix — 3 플랜 × 8 카테고리 × 3 티어
│ # ├── codexOverlay — gpt-5.5 활성 슬롯 (gpt-5.4 fallback)
│ # ├── reasoningDetection — 한/영 키워드
│ # ├── koreanDetection
│ # ├── accounts — pools (zai + codex) + poolDefaults
│ # └── fallbackChains
├── select-model.sh # jq 기반 라우터 — routing.json 읽음, 모델 ID 출력
├── pool.sh # jq 기반 계정 풀 — round-robin/cooldown/fan-out
│ # 액션: next/fanout/cooldown/release/status/reset
├── engine.sh # ACP 엔진 리졸버 — omp 우선 spawn(acpx), 폴백 pi/codex/claude
│ # 액션: resolve/acp-config/doctor
├── schemas/ # P4/P6 — JSON Schema (ajv-cli, CI 강제)
│ ├── routing.schema.json # routing.json 구조 검증
│ └── bridge-event.schema.json # bridge 이벤트 페이로드 검증
└── docs/
└── engine-acp.md # 엔진 경계(ACP) 설계문서 — no-fork 근거, 소유권 분할, 폴백체인
리포 루트:
tests/ # P1 — bats 슈트 (58+ 케이스)
├── helpers.bash, select-model.bats, engine.bats, pool.bats
Makefile # test/lint/schema/doctor/syntax/ci 타깃
.github/workflows/ci.yml # P3 — PR/푸시 CI (ubuntu+macos)
CHANGELOG.md, VERSION # P7 — Keep a Changelog + semver
13-3. 환경변수
| 변수 | 기본값 | 용도 |
|---|
ZAI_CODING_PLAN | pro | 활성 Z.ai 플랜 (lite|pro|max) |
CODEX_OAUTH_ENABLED | false | Codex OAuth 풀 사용 게이트 |
ZAI_API_KEY | (openclaw config) | Z.AI 메인 API 키 |
ZAI_API_KEY_2 | (none) | Z.AI 보조 API 키 (zai-secondary 계정용) |
CODEX_HOME | ~/.codex | Codex OAuth 토큰 디렉토리 (계정별 분리 시 사용) |
CLAUDECLI_DELEGATION_ENABLED | false | Claude CLI delegation 게이트 (실험) |
CLAUDE_CONFIG_DIR | ~/.claude | Claude CLI 계정 디렉토리 (계정별 분리 시 사용; macOS 에서 keychain 우회) |
OHMYCLAW_STATE_DIR | ~/.cache/ohmyclaw | pool.sh state 디렉토리 |
OHMYCLAW_ENGINE | (none) | 엔진 강제 (omp|pi|codex|claude). 미설정 시 routing.json#engine 순서 |
OHMYCLAW_ENGINE_FALLBACK | true | false 시 1순위 엔진 부재면 폴백 없이 에러 |
OMX_OPENCLAW | (none) | bridge notifications 활성 |
HOOKS_TOKEN | (none) | bridge bearer token |
13-4. 외부 참조
14. Learnings (Apr 2026)
- 결정론과 워크플로의 분리: 모델 선택 같은 결정론적 로직은 코드(
select-model.sh + routing.json)에, 협상 가능한 워크플로는 instructions(SKILL.md)에. LLM 이 매번 매트릭스를 재해석하면 드리프트 발생.
- 추론 신호는 복잡도와 독립: "분산 합의 정합성 증명" 은 짧은 문장(LOW 복잡도)이지만 reasoning_score 최상위 모델이 필요. 키워드 기반 휴리스틱이 LOW 격상 트리거 역할.
- Lite 플랜은 적극적 강등: 자동
cap_for_lite 가 없으면 사용자가 코딩플랜 quota 초과 위험. P95 plan_block 규칙 필수.
- Codex OAuth 는 오버레이지 대체가 아님: GPT 계열을 frontier 슬롯에 오버레이. 점수 추정 대신 OMX 의
DEFAULT_FRONTIER_MODEL 라벨을 권위로 인용 (현재 gpt-5.5, fallback gpt-5.4).
- 점수표보다 OMX role 라벨: 새 OpenAI 모델이 나올 때마다 코딩/추론/한국어 점수를 추정하는 건 드리프트 위험.
oh-my-codex/src/config/models.ts 의 frontier/standard/spark 디폴트를 단일 권위로 따라가면 추정 자체를 회피.
- 갭 감지 1회 + ESCALATED: 무한 fix 시도는 사용자 입장에서 더 큰 비용. 1회 fix 후 명확히 사용자 결정 요청.
- bridge notification 은 fire-and-forget: 발신 실패가 파이프라인을 차단하면 안 됨. OMX 의
|| true 패턴 채택.
- bash 직역 거부: 원본 harness 의
route-task.sh 를 직역하지 않고, select-model.sh + routing.json 으로 데이터/로직 분리. 같은 결과지만 LLM 이 reasoning 을 routing.json 으로 위임 가능.