테스트
OpenClaw에는 세 가지 Vitest 스위트(unit/integration, e2e, live)와 소수의 Docker 러너가 있습니다. 이 문서는 “우리가 테스트하는 방법” 가이드입니다.- 각 스위트가 무엇을 다루는지(그리고 의도적으로 무엇을 다루지 않는지)
- 일반적인 워크플로(로컬, 푸시 전, 디버깅)에서 어떤 명령을 실행해야 하는지
- live 테스트가 자격 증명을 어떻게 찾고 모델/Provider를 어떻게 선택하는지
- 실제 모델/Provider 이슈에 대한 회귀 테스트를 추가하는 방법
빠른 시작
대부분의 날에는:- 전체 게이트(푸시 전 기대되는 항목):
pnpm build && pnpm check && pnpm test - 여유 있는 머신에서 더 빠른 로컬 전체 스위트 실행:
pnpm test:max - 직접 Vitest watch 루프 실행:
pnpm test:watch - 이제 직접 파일 지정 시 extension/channel 경로도 라우팅됩니다:
pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts - 단일 실패를 반복적으로 수정하는 중이라면 먼저 범위를 좁힌 실행을 선호하세요.
- Docker 기반 QA 사이트:
pnpm qa:lab:up - Linux VM 기반 QA 레인:
pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline
- 커버리지 게이트:
pnpm test:coverage - E2E 스위트:
pnpm test:e2e
- live 스위트(모델 + Gateway tool/image 프로브):
pnpm test:live - 하나의 live 파일만 조용히 타깃팅:
pnpm test:live -- src/agents/models.profiles.live.test.ts
QA 전용 러너
이 명령들은 QA-lab 수준의 현실성이 필요할 때 메인 테스트 스위트와 함께 사용합니다.pnpm openclaw qa suite- 호스트에서 리포지토리 기반 QA 시나리오를 직접 실행합니다.
- 기본적으로 격리된 Gateway 워커와 함께 여러 선택된 시나리오를 병렬 실행하며, 최대 64개 워커 또는 선택한 시나리오 수까지 사용합니다. 워커 수를 조정하려면
--concurrency <count>를, 이전 직렬 레인을 사용하려면--concurrency 1을 사용하세요.
pnpm openclaw qa suite --runner multipass- 동일한 QA 스위트를 일회용 Multipass Linux VM 내부에서 실행합니다.
- 호스트의
qa suite와 동일한 시나리오 선택 동작을 유지합니다. qa suite와 동일한 Provider/모델 선택 플래그를 재사용합니다.- live 실행은 게스트에서 실용적으로 전달 가능한 지원 QA 인증 입력을 포워딩합니다:
env 기반 Provider 키, QA live Provider config 경로, 그리고 존재할 경우
CODEX_HOME. - 출력 디렉터리는 게스트가 마운트된 워크스페이스를 통해 결과를 다시 쓸 수 있도록 리포지토리 루트 아래에 있어야 합니다.
- 일반 QA 보고서 + 요약과 함께 Multipass 로그를
.artifacts/qa-e2e/...아래에 기록합니다.
pnpm qa:lab:up- 운영자 스타일 QA 작업을 위한 Docker 기반 QA 사이트를 시작합니다.
pnpm openclaw qa matrix- 일회용 Docker 기반 Tuwunel homeserver를 상대로 Matrix live QA 레인을 실행합니다.
- 임시 Matrix 사용자 세 명(
driver,sut,observer)과 하나의 비공개 room을 프로비저닝한 뒤, 실제 Matrix Plugin을 SUT transport로 사용하는 QA Gateway 자식을 시작합니다. - 기본적으로 고정된 stable Tuwunel 이미지
ghcr.io/matrix-construct/tuwunel:v1.5.1를 사용합니다. 다른 이미지를 테스트해야 할 때는OPENCLAW_QA_MATRIX_TUWUNEL_IMAGE로 재정의하세요. - Matrix는 현재 레인이 로컬에서 일회용 사용자를 프로비저닝하므로
--credential-source env만 지원합니다. - Matrix QA 보고서, 요약, observed-events artifact를
.artifacts/qa-e2e/...아래에 기록합니다.
pnpm openclaw qa telegram- env의 driver 및 SUT bot 토큰을 사용해 실제 비공개 그룹을 상대로 Telegram live QA 레인을 실행합니다.
OPENCLAW_QA_TELEGRAM_GROUP_ID,OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN,OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN가 필요합니다. group id는 숫자형 Telegram chat id여야 합니다.- 공유된 풀 자격 증명을 위해
--credential-source convex를 지원합니다. 기본적으로는 env 모드를 사용하거나, 풀 임대를 사용하려면OPENCLAW_QA_CREDENTIAL_SOURCE=convex를 설정하세요. - 동일한 비공개 그룹 안에 있는 서로 다른 두 bot이 필요하며, SUT bot은 Telegram username을 노출해야 합니다.
- 안정적인 bot 간 관찰을 위해
@BotFather에서 두 bot 모두에 대해 Bot-to-Bot Communication Mode를 활성화하고, driver bot이 그룹 내 bot 트래픽을 관찰할 수 있도록 하세요. - Telegram QA 보고서, 요약, observed-messages artifact를
.artifacts/qa-e2e/...아래에 기록합니다.
qa-channel은 여전히 광범위한 synthetic QA 스위트이며 live transport 커버리지 매트릭스의 일부는 아닙니다.
| 레인 | Canary | 멘션 게이팅 | Allowlist 차단 | 최상위 답글 | 재시작 복구 | 스레드 후속 응답 | 스레드 격리 | 반응 관찰 | 도움말 명령 |
|---|---|---|---|---|---|---|---|---|---|
| Matrix | x | x | x | x | x | x | x | x | |
| Telegram | x | x |
Convex를 통한 공유 Telegram 자격 증명 (v1)
openclaw qa telegram에 대해 --credential-source convex(또는 OPENCLAW_QA_CREDENTIAL_SOURCE=convex)가 활성화되면, QA lab은 Convex 기반 풀에서 독점 임대를 획득하고, 레인이 실행되는 동안 해당 임대에 Heartbeat를 보내며, 종료 시 임대를 해제합니다.
참조용 Convex 프로젝트 스캐폴드:
qa/convex-credential-broker/
OPENCLAW_QA_CONVEX_SITE_URL(예:https://your-deployment.convex.site)- 선택한 역할에 대한 secret 하나:
maintainer의 경우OPENCLAW_QA_CONVEX_SECRET_MAINTAINERci의 경우OPENCLAW_QA_CONVEX_SECRET_CI
- 자격 증명 역할 선택:
- CLI:
--credential-role maintainer|ci - env 기본값:
OPENCLAW_QA_CREDENTIAL_ROLE(기본값은maintainer)
- CLI:
OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS(기본값1200000)OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS(기본값30000)OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS(기본값90000)OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS(기본값15000)OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX(기본값/qa-credentials/v1)OPENCLAW_QA_CREDENTIAL_OWNER_ID(선택적 trace id)OPENCLAW_QA_ALLOW_INSECURE_HTTP=1은 로컬 전용 개발을 위해 loopbackhttp://Convex URL을 허용합니다.
OPENCLAW_QA_CONVEX_SITE_URL에 https://를 사용해야 합니다.
Maintainer 관리자 명령(풀 추가/제거/목록)은 구체적으로 OPENCLAW_QA_CONVEX_SECRET_MAINTAINER가 필요합니다.
maintainer용 CLI helper:
--json을 사용하세요.
기본 endpoint 계약(OPENCLAW_QA_CONVEX_SITE_URL + /qa-credentials/v1):
POST /acquire- 요청:
{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs } - 성공:
{ status: "ok", credentialId, leaseToken, payload, leaseTtlMs?, heartbeatIntervalMs? } - 소진/재시도 가능:
{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }
- 요청:
POST /heartbeat- 요청:
{ kind, ownerId, actorRole, credentialId, leaseToken, leaseTtlMs } - 성공:
{ status: "ok" }(또는 빈2xx)
- 요청:
POST /release- 요청:
{ kind, ownerId, actorRole, credentialId, leaseToken } - 성공:
{ status: "ok" }(또는 빈2xx)
- 요청:
POST /admin/add(maintainer secret 전용)- 요청:
{ kind, actorId, payload, note?, status? } - 성공:
{ status: "ok", credential }
- 요청:
POST /admin/remove(maintainer secret 전용)- 요청:
{ credentialId, actorId } - 성공:
{ status: "ok", changed, credential } - 활성 임대 보호:
{ status: "error", code: "LEASE_ACTIVE", ... }
- 요청:
POST /admin/list(maintainer secret 전용)- 요청:
{ kind?, status?, includePayload?, limit? } - 성공:
{ status: "ok", credentials, count }
- 요청:
{ groupId: string, driverToken: string, sutToken: string }groupId는 숫자형 Telegram chat id 문자열이어야 합니다.admin/add는kind: "telegram"에 대해 이 형태를 검증하고 잘못된 payload를 거부합니다.
QA에 채널 추가하기
markdown QA 시스템에 채널을 추가하려면 정확히 두 가지가 필요합니다.- 해당 채널용 transport adapter
- 채널 계약을 검증하는 scenario pack
qa-lab 러너가 흐름을 소유할 수 있는 경우 채널 전용 QA 러너를 추가하지 마세요.
qa-lab은 공유 메커니즘을 소유합니다.
- 스위트 시작 및 종료
- 워커 동시성
- artifact 기록
- 보고서 생성
- 시나리오 실행
- 이전
qa-channel시나리오를 위한 호환성 alias
- 해당 transport에 대해 Gateway가 어떻게 구성되는지
- readiness를 어떻게 확인하는지
- inbound event를 어떻게 주입하는지
- outbound 메시지를 어떻게 관찰하는지
- transcript와 정규화된 transport 상태를 어떻게 노출하는지
- transport 기반 작업을 어떻게 실행하는지
- transport별 reset 또는 cleanup을 어떻게 처리하는지
- 공유
qa-labseam에 transport adapter를 구현합니다. - transport registry에 adapter를 등록합니다.
- transport별 메커니즘은 adapter 또는 채널 harness 내부에 유지합니다.
qa/scenarios/아래에 markdown 시나리오를 작성하거나 조정합니다.- 새 시나리오에는 generic scenario helper를 사용합니다.
- 리포지토리가 의도적인 마이그레이션을 수행 중인 경우가 아니라면 기존 호환성 alias가 계속 동작하게 유지합니다.
- 동작을
qa-lab에서 한 번만 표현할 수 있다면,qa-lab에 넣으세요. - 동작이 하나의 채널 transport에 의존한다면, 해당 adapter 또는 Plugin harness에 유지하세요.
- 시나리오에 둘 이상의 채널이 사용할 수 있는 새 capability가 필요하다면,
suite.ts에 채널별 분기를 추가하는 대신 generic helper를 추가하세요. - 동작이 오직 하나의 transport에만 의미가 있다면, 해당 시나리오를 transport 전용으로 유지하고 시나리오 계약에서 이를 명시하세요.
waitForTransportReadywaitForChannelReadyinjectInboundMessageinjectOutboundMessagewaitForTransportOutboundMessagewaitForChannelOutboundMessagewaitForNoTransportOutboundgetTransportSnapshotreadTransportMessagereadTransportTranscriptformatTransportTranscriptresetTransport
waitForQaChannelReadywaitForOutboundMessagewaitForNoOutboundformatConversationTranscriptresetBus
테스트 스위트(무엇이 어디서 실행되는가)
스위트를 “현실성이 점점 증가하는 단계”라고 생각하세요(그리고 불안정성/비용도 함께 증가합니다).Unit / integration (기본값)
- 명령:
pnpm test - 구성: 기존 범위별 Vitest 프로젝트 전반에 걸친 10개의 순차 샤드 실행(
vitest.full-*.config.ts) - 파일:
src/**/*.test.ts,packages/**/*.test.ts,test/**/*.test.ts아래의 core/unit 인벤토리와vitest.unit.config.ts에서 다루는 허용된uinode 테스트 - 범위:
- 순수 unit 테스트
- 프로세스 내부 integration 테스트(Gateway 인증, 라우팅, tooling, 파싱, config)
- 알려진 버그에 대한 결정적 회귀 테스트
- 기대사항:
- CI에서 실행됨
- 실제 키 불필요
- 빠르고 안정적이어야 함
- 프로젝트 참고:
- 이제 타깃을 지정하지 않은
pnpm test는 하나의 거대한 native 루트 프로젝트 프로세스 대신 11개의 더 작은 샤드 구성(core-unit-src,core-unit-security,core-unit-ui,core-unit-support,core-support-boundary,core-contracts,core-bundled,core-runtime,agentic,auto-reply,extensions)을 실행합니다. 이렇게 하면 부하가 있는 머신에서 피크 RSS를 줄이고 auto-reply/extension 작업이 관련 없는 스위트를 잠식하는 것을 방지할 수 있습니다. pnpm test --watch는 다중 샤드 watch 루프가 실용적이지 않기 때문에 여전히 native 루트vitest.config.ts프로젝트 그래프를 사용합니다.pnpm test,pnpm test:watch,pnpm test:perf:imports는 명시적인 파일/디렉터리 타깃을 먼저 범위별 레인으로 라우팅하므로,pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts는 전체 루트 프로젝트 시작 비용을 치르지 않아도 됩니다.pnpm test:changed는 변경 diff가 라우팅 가능한 소스/테스트 파일만 건드릴 경우 변경된 git 경로를 동일한 범위별 레인으로 확장합니다. config/setup 편집은 여전히 더 넓은 루트 프로젝트 재실행으로 폴백됩니다.- agents, commands, plugins, auto-reply helper,
plugin-sdk및 유사한 순수 유틸리티 영역의 import가 가벼운 unit 테스트는test/setup-openclaw-runtime.ts를 건너뛰는unit-fast레인으로 라우팅됩니다. 상태가 있거나 runtime이 무거운 파일은 기존 레인에 남습니다. - 선택된
plugin-sdk및commandshelper 소스 파일도 changed 모드 실행을 이러한 가벼운 레인의 명시적인 형제 테스트로 매핑하므로, helper 편집 시 해당 디렉터리의 전체 무거운 스위트를 다시 실행하지 않아도 됩니다. auto-reply는 이제 세 개의 전용 버킷을 가집니다: 최상위 core helper, 최상위reply.*integration 테스트, 그리고src/auto-reply/reply/**하위 트리. 이렇게 하면 가장 무거운 reply harness 작업이 가벼운 status/chunk/token 테스트에 영향을 주지 않습니다.
- 이제 타깃을 지정하지 않은
- 내장 러너 참고:
- 메시지 tool discovery 입력 또는 Compaction runtime context를 변경할 때는 두 수준의 커버리지를 모두 유지하세요.
- 순수 라우팅/정규화 경계에 대해 집중된 helper 회귀 테스트를 추가하세요.
- 또한 내장 러너 integration 스위트도 정상 상태를 유지해야 합니다:
src/agents/pi-embedded-runner/compact.hooks.test.ts,src/agents/pi-embedded-runner/run.overflow-compaction.test.ts,src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts. - 이 스위트들은 범위가 지정된 id와 Compaction 동작이 실제
run.ts/compact.ts경로를 통해 계속 흐르는지 검증합니다. helper 전용 테스트만으로는 이러한 integration 경로를 충분히 대체할 수 없습니다.
- 풀 참고:
- 기본 Vitest 구성은 이제 기본값으로
threads를 사용합니다. - 공유 Vitest 구성은 또한
isolate: false를 고정하고 루트 프로젝트, e2e, live 구성 전반에서 비격리 러너를 사용합니다. - 루트 UI 레인은
jsdomsetup 및 optimizer를 유지하지만, 이제 공유 비격리 러너에서도 실행됩니다. - 각
pnpm test샤드는 공유 Vitest 구성에서 동일한threads+isolate: false기본값을 상속받습니다. - 공유
scripts/run-vitest.mjs런처는 큰 로컬 실행 중 V8 컴파일 churn을 줄이기 위해 기본적으로 Vitest 자식 Node 프로세스에--no-maglev도 추가합니다. 기본 V8 동작과 비교해야 한다면OPENCLAW_VITEST_ENABLE_MAGLEV=1을 설정하세요.
- 기본 Vitest 구성은 이제 기본값으로
- 빠른 로컬 반복 참고:
pnpm test:changed는 변경 경로가 더 작은 스위트에 깔끔하게 매핑될 때 범위별 레인을 통해 라우팅됩니다.pnpm test:max와pnpm test:changed:max는 같은 라우팅 동작을 유지하되, 더 높은 워커 상한을 사용합니다.- 로컬 워커 자동 스케일링은 이제 의도적으로 더 보수적이며, 호스트 load average가 이미 높을 때도 물러나므로 여러 개의 동시 Vitest 실행이 기본적으로 덜 큰 피해를 주게 됩니다.
- 기본 Vitest 구성은 프로젝트/config 파일을
forceRerunTriggers로 표시하여 테스트 wiring이 변경될 때 changed 모드 재실행이 정확하게 유지되도록 합니다. - 구성은 지원되는 호스트에서
OPENCLAW_VITEST_FS_MODULE_CACHE를 계속 활성화합니다. 직접 프로파일링을 위한 명시적 캐시 위치 하나를 원하면OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path를 설정하세요.
- 성능 디버그 참고:
pnpm test:perf:imports는 Vitest import-duration 보고와 import-breakdown 출력을 활성화합니다.pnpm test:perf:imports:changed는 동일한 프로파일링 보기를origin/main이후 변경된 파일로 범위를 좁힙니다.
pnpm test:perf:changed:bench -- --ref <git-ref>는 해당 커밋 diff에 대해 라우팅된test:changed와 native 루트 프로젝트 경로를 비교하고 wall time과 macOS max RSS를 출력합니다.pnpm test:perf:changed:bench -- --worktree는 변경된 파일 목록을scripts/test-projects.mjs와 루트 Vitest 구성으로 라우팅해 현재 dirty tree를 벤치마크합니다.pnpm test:perf:profile:main은 Vitest/Vite 시작 및 transform 오버헤드에 대한 메인 스레드 CPU 프로파일을 기록합니다.pnpm test:perf:profile:runner는 파일 병렬화를 비활성화한 unit 스위트에 대해 러너 CPU+heap 프로파일을 기록합니다.
E2E (Gateway 스모크)
- 명령:
pnpm test:e2e - 구성:
vitest.e2e.config.ts - 파일:
src/**/*.e2e.test.ts,test/**/*.e2e.test.ts - runtime 기본값:
- 리포지토리의 나머지와 동일하게 Vitest
threads와isolate: false를 사용합니다. - 적응형 워커를 사용합니다(CI: 최대 2, 로컬: 기본값 1).
- 콘솔 I/O 오버헤드를 줄이기 위해 기본적으로 silent 모드로 실행됩니다.
- 리포지토리의 나머지와 동일하게 Vitest
- 유용한 재정의:
- 워커 수를 강제하려면
OPENCLAW_E2E_WORKERS=<n>(상한 16) - 자세한 콘솔 출력을 다시 활성화하려면
OPENCLAW_E2E_VERBOSE=1
- 워커 수를 강제하려면
- 범위:
- 다중 인스턴스 Gateway 엔드투엔드 동작
- WebSocket/HTTP 표면, Node 페어링, 더 무거운 네트워킹
- 기대사항:
- CI에서 실행됨(파이프라인에서 활성화된 경우)
- 실제 키 불필요
- unit 테스트보다 더 많은 가변 요소가 있음(더 느릴 수 있음)
E2E: OpenShell 백엔드 스모크
- 명령:
pnpm test:e2e:openshell - 파일:
test/openshell-sandbox.e2e.test.ts - 범위:
- Docker를 통해 호스트에서 격리된 OpenShell Gateway를 시작합니다.
- 임시 로컬 Dockerfile에서 sandbox를 생성합니다.
- 실제
sandbox ssh-config+ SSH exec를 통해 OpenClaw의 OpenShell 백엔드를 실행합니다. - sandbox fs bridge를 통해 원격 canonical filesystem 동작을 검증합니다.
- 기대사항:
- 옵트인 전용이며 기본
pnpm test:e2e실행의 일부가 아닙니다. - 로컬
openshellCLI와 정상 동작하는 Docker 데몬이 필요합니다. - 격리된
HOME/XDG_CONFIG_HOME을 사용한 뒤 테스트 Gateway와 sandbox를 제거합니다.
- 옵트인 전용이며 기본
- 유용한 재정의:
- 더 넓은 e2e 스위트를 수동으로 실행할 때 테스트를 활성화하려면
OPENCLAW_E2E_OPENSHELL=1 - 기본이 아닌 CLI 바이너리 또는 wrapper 스크립트를 지정하려면
OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell
- 더 넓은 e2e 스위트를 수동으로 실행할 때 테스트를 활성화하려면
Live (실제 Provider + 실제 모델)
- 명령:
pnpm test:live - 구성:
vitest.live.config.ts - 파일:
src/**/*.live.test.ts - 기본값:
pnpm test:live에 의해 활성화됨(OPENCLAW_LIVE_TEST=1설정) - 범위:
- “이 Provider/모델이 오늘 실제 자격 증명으로 정말 동작하는가?”
- Provider 포맷 변경, tool-calling 특이사항, 인증 문제, rate limit 동작 포착
- 기대사항:
- 설계상 CI에서 안정적이지 않음(실제 네트워크, 실제 Provider 정책, quota, 장애)
- 비용이 들고 / rate limit을 사용함
- “전부”보다는 범위를 좁힌 하위 집합 실행을 선호
- live 실행은 누락된 API 키를 가져오기 위해
~/.profile을 소스합니다. - 기본적으로 live 실행은 여전히
HOME을 격리하고 config/auth 자료를 임시 테스트 홈에 복사하므로 unit fixture가 실제~/.openclaw를 변경할 수 없습니다. - live 테스트가 실제 홈 디렉터리를 사용하도록 의도적으로 해야 할 때만
OPENCLAW_LIVE_USE_REAL_HOME=1을 설정하세요. - 이제
pnpm test:live는 기본적으로 더 조용한 모드입니다.[live] ...진행 출력은 유지하지만, 추가~/.profile알림을 숨기고 Gateway bootstrap 로그/Bonjour chatter를 음소거합니다. 전체 시작 로그가 다시 필요하면OPENCLAW_LIVE_TEST_QUIET=0을 설정하세요. - API 키 로테이션(Provider별): 쉼표/세미콜론 형식의
*_API_KEYS또는*_API_KEY_1,*_API_KEY_2를 설정하거나(예:OPENAI_API_KEYS,ANTHROPIC_API_KEYS,GEMINI_API_KEYS), live별 재정의를 위해OPENCLAW_LIVE_*_KEY를 설정하세요. 테스트는 rate limit 응답 시 재시도합니다. - 진행/Heartbeat 출력:
- live 스위트는 이제 진행 줄을 stderr로 내보내므로, Vitest 콘솔 캡처가 조용한 경우에도 긴 Provider 호출이 눈에 보이게 활성 상태로 표시됩니다.
vitest.live.config.ts는 Vitest 콘솔 가로채기를 비활성화하여 Provider/Gateway 진행 줄이 live 실행 중 즉시 스트리밍되도록 합니다.- 직접 모델 Heartbeat는
OPENCLAW_LIVE_HEARTBEAT_MS로 조정합니다. - Gateway/프로브 Heartbeat는
OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS로 조정합니다.
어떤 스위트를 실행해야 하나요?
다음 결정 표를 사용하세요.- 로직/테스트를 수정 중:
pnpm test실행(많이 변경했다면pnpm test:coverage도) - Gateway 네트워킹 / WS 프로토콜 / 페어링을 건드림:
pnpm test:e2e추가 - “내 봇이 다운되었어요” / Provider별 실패 / tool calling 디버깅: 범위를 좁힌
pnpm test:live실행
Live: Android Node capability 스윕
- 테스트:
src/gateway/android-node.capabilities.live.test.ts - 스크립트:
pnpm android:test:integration - 목표: 연결된 Android Node가 현재 광고하는 모든 명령을 호출하고 명령 계약 동작을 검증합니다.
- 범위:
- 사전 조건이 갖춰진 수동 setup(이 스위트는 앱을 설치/실행/페어링하지 않음)
- 선택된 Android Node에 대한 명령별 Gateway
node.invoke검증
- 필요한 사전 setup:
- Android 앱이 이미 Gateway에 연결되고 페어링되어 있어야 함
- 앱이 포그라운드에 유지되어야 함
- 통과를 기대하는 capability에 대해 권한/캡처 동의가 부여되어야 함
- 선택적 타깃 재정의:
OPENCLAW_ANDROID_NODE_ID또는OPENCLAW_ANDROID_NODE_NAMEOPENCLAW_ANDROID_GATEWAY_URL/OPENCLAW_ANDROID_GATEWAY_TOKEN/OPENCLAW_ANDROID_GATEWAY_PASSWORD
- 전체 Android setup 세부사항: Android 앱
Live: 모델 스모크(프로필 키)
live 테스트는 실패를 분리할 수 있도록 두 계층으로 나뉩니다.- “직접 모델”은 해당 Provider/모델이 주어진 키로 최소한 응답할 수 있는지를 알려줍니다.
- “Gateway 스모크”는 해당 모델에 대해 전체 Gateway+에이전트 파이프라인(세션, 히스토리, tools, sandbox 정책 등)이 동작하는지를 알려줍니다.
계층 1: 직접 모델 completion(Gateway 없음)
- 테스트:
src/agents/models.profiles.live.test.ts - 목표:
- 발견된 모델을 나열
getApiKeyForModel을 사용해 자격 증명이 있는 모델 선택- 모델별로 작은 completion 실행(그리고 필요한 경우 타깃 회귀 테스트)
- 활성화 방법:
pnpm test:live(또는 Vitest를 직접 호출하는 경우OPENCLAW_LIVE_TEST=1)
- 이 스위트를 실제로 실행하려면
OPENCLAW_LIVE_MODELS=modern(또는all,modern의 alias)을 설정하세요. 그렇지 않으면pnpm test:live가 Gateway 스모크에 집중되도록 이 스위트는 건너뜁니다. - 모델 선택 방법:
- 최신 allowlist를 실행하려면
OPENCLAW_LIVE_MODELS=modern(Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4) OPENCLAW_LIVE_MODELS=all은 최신 allowlist의 alias- 또는
OPENCLAW_LIVE_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,..."(쉼표로 구분한 allowlist) - modern/all 스윕은 기본적으로 큐레이션된 높은 신호 상한을 사용합니다. exhaustive modern 스윕을 원하면
OPENCLAW_LIVE_MAX_MODELS=0을, 더 작은 상한을 원하면 양수를 설정하세요.
- 최신 allowlist를 실행하려면
- Provider 선택 방법:
OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"(쉼표로 구분한 allowlist)
- 키 출처:
- 기본값: 프로필 저장소와 env 폴백
- 프로필 저장소만 강제하려면
OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1설정
- 이 계층이 존재하는 이유:
- “Provider API가 깨졌음 / 키가 유효하지 않음”과 “Gateway 에이전트 파이프라인이 깨졌음”을 분리합니다.
- 작고 격리된 회귀 테스트를 담습니다(예: OpenAI Responses/Codex Responses reasoning replay + tool-call 흐름)
계층 2: Gateway + dev agent 스모크(@openclaw가 실제로 하는 일)
- 테스트:
src/gateway/gateway-models.profiles.live.test.ts - 목표:
- 프로세스 내부 Gateway를 띄웁니다.
agent:dev:*세션을 생성/패치합니다(실행별 모델 재정의).- 키가 있는 모델들을 순회하며 다음을 검증합니다:
- “의미 있는” 응답(tools 없음)
- 실제 tool 호출이 동작함(
read프로브) - 선택적 추가 tool 프로브(
exec+read프로브) - OpenAI 회귀 경로(tool-call-only → 후속 응답)가 계속 동작함
- 프로브 세부사항(실패를 빠르게 설명할 수 있도록):
read프로브: 테스트가 워크스페이스에 nonce 파일을 쓰고, 에이전트에게 이를read한 뒤 nonce를 다시 echo하도록 요청합니다.exec+read프로브: 테스트가 에이전트에게exec로 임시 파일에 nonce를 쓰게 한 다음, 이를 다시read하도록 요청합니다.- image 프로브: 테스트가 생성된 PNG(고양이 + 무작위 코드)를 첨부하고, 모델이
cat <CODE>를 반환할 것으로 기대합니다. - 구현 참조:
src/gateway/gateway-models.profiles.live.test.ts및src/gateway/live-image-probe.ts.
- 활성화 방법:
pnpm test:live(또는 Vitest를 직접 호출하는 경우OPENCLAW_LIVE_TEST=1)
- 모델 선택 방법:
- 기본값: 최신 allowlist(Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4)
OPENCLAW_LIVE_GATEWAY_MODELS=all은 최신 allowlist의 alias입니다.- 또는 범위를 좁히기 위해
OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"(또는 쉼표 목록)을 설정하세요. - modern/all Gateway 스윕은 기본적으로 큐레이션된 높은 신호 상한을 사용합니다. exhaustive modern 스윕을 원하면
OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0을, 더 작은 상한을 원하면 양수를 설정하세요.
- Provider 선택 방법(“OpenRouter 전부” 피하기):
OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"(쉼표 allowlist)
- 이 live 테스트에서는 tool + image 프로브가 항상 활성화됩니다:
read프로브 +exec+read프로브(tool 스트레스)- 모델이 image 입력 지원을 광고하는 경우 image 프로브 실행
- 흐름(상위 수준):
- 테스트가 “CAT” + 무작위 코드가 들어간 작은 PNG를 생성합니다(
src/gateway/live-image-probe.ts) agentattachments: [{ mimeType: "image/png", content: "<base64>" }]를 통해 전송합니다- Gateway가 첨부 파일을
images[]로 파싱합니다(src/gateway/server-methods/agent.ts+src/gateway/chat-attachments.ts) - 내장 에이전트가 multimodal 사용자 메시지를 모델로 전달합니다
- 검증: 응답에
cat+ 코드가 포함됨(OCR 허용 오차: 사소한 실수 허용)
- 테스트가 “CAT” + 무작위 코드가 들어간 작은 PNG를 생성합니다(
provider/model id)를 보려면 다음을 실행하세요.
Live: CLI 백엔드 스모크(Claude, Codex, Gemini 또는 기타 로컬 CLI)
- 테스트:
src/gateway/gateway-cli-backend.live.test.ts - 목표: 기본 config를 건드리지 않고 로컬 CLI 백엔드를 사용해 Gateway + 에이전트 파이프라인을 검증합니다.
- 백엔드별 스모크 기본값은 해당 extension의
cli-backend.ts정의에 있습니다. - 활성화:
pnpm test:live(또는 Vitest를 직접 호출하는 경우OPENCLAW_LIVE_TEST=1)OPENCLAW_LIVE_CLI_BACKEND=1
- 기본값:
- 기본 Provider/모델:
claude-cli/claude-sonnet-4-6 - 명령/args/image 동작은 해당 CLI 백엔드 Plugin 메타데이터에서 가져옵니다.
- 기본 Provider/모델:
- 재정의(선택 사항):
OPENCLAW_LIVE_CLI_BACKEND_MODEL="codex-cli/gpt-5.4"OPENCLAW_LIVE_CLI_BACKEND_COMMAND="/full/path/to/codex"OPENCLAW_LIVE_CLI_BACKEND_ARGS='["exec","--json","--color","never","--sandbox","read-only","--skip-git-repo-check"]'- 실제 image 첨부를 전송하려면
OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1(경로는 프롬프트에 주입됨) - 프롬프트 주입 대신 image 파일 경로를 CLI 인자로 전달하려면
OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image" IMAGE_ARG가 설정된 경우 image 인자 전달 방식을 제어하려면OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"(또는"list")- 두 번째 턴을 보내고 resume 흐름을 검증하려면
OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1 - 기본 Claude Sonnet -> Opus 동일 세션 연속성 프로브를 비활성화하려면
OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0(선택한 모델이 전환 타깃을 지원할 때 강제로 켜려면1)
- Docker 러너는
scripts/test-live-cli-backend-docker.sh에 있습니다. - 리포지토리 Docker 이미지 안에서 비루트
node사용자로 live CLI 백엔드 스모크를 실행합니다. - 해당 extension에서 CLI 스모크 메타데이터를 확인한 뒤, 캐시 가능한 쓰기 가능한 prefix
OPENCLAW_DOCKER_CLI_TOOLS_DIR(기본값:~/.cache/openclaw/docker-cli-tools)에 일치하는 Linux CLI 패키지(@anthropic-ai/claude-code,@openai/codex,@google/gemini-cli)를 설치합니다. pnpm test:docker:live-cli-backend:claude-subscription은~/.claude/.credentials.json의claudeAiOauth.subscriptionType또는claude setup-token의CLAUDE_CODE_OAUTH_TOKEN을 통한 portable Claude Code subscription OAuth가 필요합니다. 먼저 Docker에서 직접claude -p를 증명한 다음, Anthropic API 키 env var를 보존하지 않고 두 번의 Gateway CLI 백엔드 턴을 실행합니다. 이 subscription 레인은 현재 Claude가 일반 subscription 플랜 제한 대신 추가 사용량 과금을 통해 서드파티 앱 사용을 라우팅하므로 기본적으로 Claude MCP/tool 및 image 프로브를 비활성화합니다.- live CLI 백엔드 스모크는 이제 Claude, Codex, Gemini에 대해 동일한 엔드투엔드 흐름을 실행합니다: 텍스트 턴, image 분류 턴, 그다음 Gateway CLI를 통해 검증되는 MCP
crontool 호출. - Claude의 기본 스모크는 또한 세션을 Sonnet에서 Opus로 패치하고, 재개된 세션이 이전 메모를 여전히 기억하는지도 검증합니다.
Live: ACP 바인드 스모크(/acp spawn ... --bind here)
- 테스트:
src/gateway/gateway-acp-bind.live.test.ts - 목표: live ACP 에이전트로 실제 ACP 대화 바인드 흐름을 검증합니다:
/acp spawn <agent> --bind here전송- synthetic message-channel 대화를 그 자리에서 바인드
- 같은 대화에서 일반 후속 메시지 전송
- 후속 메시지가 바인드된 ACP 세션 transcript에 기록되는지 검증
- 활성화:
pnpm test:live src/gateway/gateway-acp-bind.live.test.tsOPENCLAW_LIVE_ACP_BIND=1
- 기본값:
- Docker 내 ACP 에이전트:
claude,codex,gemini - 직접
pnpm test:live ...용 ACP 에이전트:claude - synthetic 채널: Slack DM 스타일 대화 컨텍스트
- ACP 백엔드:
acpx
- Docker 내 ACP 에이전트:
- 재정의:
OPENCLAW_LIVE_ACP_BIND_AGENT=claudeOPENCLAW_LIVE_ACP_BIND_AGENT=codexOPENCLAW_LIVE_ACP_BIND_AGENT=geminiOPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex,geminiOPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND='npx -y @agentclientprotocol/claude-agent-acp@<version>'
- 참고:
- 이 레인은 admin 전용 synthetic originating-route 필드가 있는 Gateway
chat.send표면을 사용하므로, 테스트가 외부 전달을 가장하지 않고도 message-channel 컨텍스트를 붙일 수 있습니다. OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND가 설정되지 않으면, 테스트는 선택한 ACP harness 에이전트에 대해 내장acpxPlugin의 기본 agent registry를 사용합니다.
- 이 레인은 admin 전용 synthetic originating-route 필드가 있는 Gateway
- Docker 러너는
scripts/test-live-acp-bind-docker.sh에 있습니다. - 기본적으로 지원되는 모든 live CLI 에이전트(
claude,codex,gemini)에 대해 ACP 바인드 스모크를 순서대로 실행합니다. - 매트릭스 범위를 좁히려면
OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,OPENCLAW_LIVE_ACP_BIND_AGENTS=codex, 또는OPENCLAW_LIVE_ACP_BIND_AGENTS=gemini를 사용하세요. ~/.profile을 소스하고, 일치하는 CLI 인증 자료를 컨테이너에 스테이징하며, 쓰기 가능한 npm prefix에acpx를 설치한 다음, 요청된 live CLI(@anthropic-ai/claude-code,@openai/codex,@google/gemini-cli)가 없으면 설치합니다.- Docker 내부에서는 러너가
OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx를 설정하여, 소스된 profile의 Provider env var가 자식 harness CLI에서도 계속 사용 가능하도록 합니다.
Live: Codex app-server harness 스모크
- 목표: 일반 Gateway
agent메서드를 통해 Plugin 소유 Codex harness를 검증합니다:- 번들된
codexPlugin 로드 OPENCLAW_AGENT_RUNTIME=codex선택- 첫 번째 Gateway agent 턴을
codex/gpt-5.4로 전송 - 동일한 OpenClaw 세션에 두 번째 턴을 전송하고 app-server thread가 재개될 수 있는지 검증
- 동일한 Gateway 명령
경로를 통해
/codex status및/codex models실행
- 번들된
- 테스트:
src/gateway/gateway-codex-harness.live.test.ts - 활성화:
OPENCLAW_LIVE_CODEX_HARNESS=1 - 기본 모델:
codex/gpt-5.4 - 선택적 image 프로브:
OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1 - 선택적 MCP/tool 프로브:
OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1 - 이 스모크는
OPENCLAW_AGENT_HARNESS_FALLBACK=none을 설정하므로, 깨진 Codex harness가 PI로 조용히 폴백해서 통과할 수 없습니다. - 인증: 셸/profile의
OPENAI_API_KEY와 선택적으로 복사된~/.codex/auth.json및~/.codex/config.toml
- Docker 러너는
scripts/test-live-codex-harness-docker.sh에 있습니다. - 마운트된
~/.profile을 소스하고,OPENAI_API_KEY를 전달하며, Codex CLI 인증 파일이 있으면 복사하고, 쓰기 가능한 마운트된 npm prefix에@openai/codex를 설치한 뒤, 소스 트리를 스테이징하고, Codex-harness live 테스트만 실행합니다. - Docker는 기본적으로 image 및 MCP/tool 프로브를 활성화합니다. 더 좁은 디버그 실행이 필요하면
OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0또는OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0을 설정하세요. - Docker는 또한
OPENCLAW_AGENT_HARNESS_FALLBACK=none을 export하여 live 테스트 구성과 일치시킵니다. 따라서openai-codex/*또는 PI 폴백이 Codex harness 회귀를 숨길 수 없습니다.
권장 live 레시피
범위가 좁고 명시적인 allowlist가 가장 빠르고 가장 덜 불안정합니다.-
단일 모델, 직접 실행(Gateway 없음):
OPENCLAW_LIVE_MODELS="openai/gpt-5.4" pnpm test:live src/agents/models.profiles.live.test.ts
-
단일 모델, Gateway 스모크:
OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts
-
여러 Provider에 걸친 tool calling:
OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3-flash-preview,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts
-
Google 집중(Gemini API 키 + Antigravity):
- Gemini(API 키):
OPENCLAW_LIVE_GATEWAY_MODELS="google/gemini-3-flash-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts - Antigravity(OAuth):
OPENCLAW_LIVE_GATEWAY_MODELS="google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-pro-high" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts
- Gemini(API 키):
google/...는 Gemini API(API 키)를 사용합니다.google-antigravity/...는 Antigravity OAuth 브리지(Cloud Code Assist 스타일 agent endpoint)를 사용합니다.google-gemini-cli/...는 로컬 머신의 Gemini CLI를 사용합니다(별도 인증 + tooling 특이사항).- Gemini API와 Gemini CLI의 차이:
- API: OpenClaw가 Google의 호스팅된 Gemini API를 HTTP로 호출합니다(API 키 / 프로필 인증). 대부분의 사용자가 “Gemini”라고 말할 때 의미하는 것이 이것입니다.
- CLI: OpenClaw가 로컬
gemini바이너리를 셸 실행합니다. 자체 인증이 있으며 동작이 다를 수 있습니다(스트리밍/tool 지원/버전 불일치).
Live: 모델 매트릭스(무엇을 커버하는가)
고정된 “CI 모델 목록”은 없습니다(live는 옵트인). 하지만 개발 머신에서 키를 가지고 정기적으로 커버하기를 권장하는 모델은 다음과 같습니다.최신 스모크 세트(tool calling + image)
이것은 계속 동작해야 한다고 기대하는 “공통 모델” 실행입니다.- OpenAI (비-Codex):
openai/gpt-5.4(선택 사항:openai/gpt-5.4-mini) - OpenAI Codex:
openai-codex/gpt-5.4 - Anthropic:
anthropic/claude-opus-4-6(또는anthropic/claude-sonnet-4-6) - Google (Gemini API):
google/gemini-3.1-pro-preview및google/gemini-3-flash-preview(구형 Gemini 2.x 모델은 피하세요) - Google (Antigravity):
google-antigravity/claude-opus-4-6-thinking및google-antigravity/gemini-3-flash - Z.AI (GLM):
zai/glm-4.7 - MiniMax:
minimax/MiniMax-M2.7
OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,openai-codex/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3.1-pro-preview,google/gemini-3-flash-preview,google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-flash,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts
기준선: tool calling(Read + 선택적 Exec)
Provider 계열마다 최소 하나는 선택하세요.- OpenAI:
openai/gpt-5.4(또는openai/gpt-5.4-mini) - Anthropic:
anthropic/claude-opus-4-6(또는anthropic/claude-sonnet-4-6) - Google:
google/gemini-3-flash-preview(또는google/gemini-3.1-pro-preview) - Z.AI (GLM):
zai/glm-4.7 - MiniMax:
minimax/MiniMax-M2.7
- xAI:
xai/grok-4(또는 최신 사용 가능 버전) - Mistral:
mistral/… (활성화된 “tools” 지원 모델 하나 선택) - Cerebras:
cerebras/… (접근 권한이 있다면) - LM Studio:
lmstudio/… (로컬; tool calling은 API 모드에 따라 달라짐)
비전: image 전송(attachment → multimodal 메시지)
image 프로브를 실행하려면OPENCLAW_LIVE_GATEWAY_MODELS에 image 지원 모델(Claude/Gemini/OpenAI 비전 지원 변형 등) 최소 하나를 포함하세요.
Aggregator / 대체 Gateway
키가 활성화되어 있다면 다음을 통한 테스트도 지원합니다.- OpenRouter:
openrouter/...(수백 개 모델; tool+image 지원 후보를 찾으려면openclaw models scan사용) - OpenCode: Zen용
opencode/..., Go용opencode-go/...(OPENCODE_API_KEY/OPENCODE_ZEN_API_KEY로 인증)
- 내장:
openai,openai-codex,anthropic,google,google-vertex,google-antigravity,google-gemini-cli,zai,openrouter,opencode,opencode-go,xai,groq,cerebras,mistral,github-copilot models.providers를 통해(custom endpoint):minimax(cloud/API), 그리고 모든 OpenAI/Anthropic 호환 프록시(LM Studio, vLLM, LiteLLM 등)
discoverModels(...)가 반환하는 것과 사용 가능한 키 조합입니다.
자격 증명(절대 커밋 금지)
live 테스트는 CLI와 같은 방식으로 자격 증명을 찾습니다. 실질적인 의미는 다음과 같습니다.- CLI가 동작하면, live 테스트도 같은 키를 찾아야 합니다.
-
live 테스트가 “자격 증명 없음”이라고 하면,
openclaw models list/ 모델 선택을 디버깅하듯이 똑같이 디버깅하세요. -
에이전트별 인증 프로필:
~/.openclaw/agents/<agentId>/agent/auth-profiles.json(live 테스트에서 “프로필 키”라고 하는 것이 이것입니다) -
config:
~/.openclaw/openclaw.json(또는OPENCLAW_CONFIG_PATH) -
레거시 상태 디렉터리:
~/.openclaw/credentials/(존재할 경우 staging된 live 홈으로 복사되지만, 메인 프로필 키 저장소는 아님) -
로컬 live 실행은 기본적으로 활성 config, 에이전트별
auth-profiles.json파일, 레거시credentials/, 지원되는 외부 CLI 인증 디렉터리를 임시 테스트 홈으로 복사합니다. staging된 live 홈은workspace/와sandboxes/를 건너뛰며,agents.*.workspace/agentDir경로 재정의도 제거되어 프로브가 실제 호스트 워크스페이스를 건드리지 않도록 합니다.
~/.profile에서 export됨)에 의존하려면, 로컬 테스트를 source ~/.profile 후에 실행하거나, 아래 Docker 러너를 사용하세요(이들은 ~/.profile을 컨테이너에 마운트할 수 있습니다).
Deepgram live(오디오 전사)
- 테스트:
src/media-understanding/providers/deepgram/audio.live.test.ts - 활성화:
DEEPGRAM_API_KEY=... DEEPGRAM_LIVE_TEST=1 pnpm test:live src/media-understanding/providers/deepgram/audio.live.test.ts
BytePlus coding plan live
- 테스트:
src/agents/byteplus.live.test.ts - 활성화:
BYTEPLUS_API_KEY=... BYTEPLUS_LIVE_TEST=1 pnpm test:live src/agents/byteplus.live.test.ts - 선택적 모델 재정의:
BYTEPLUS_CODING_MODEL=ark-code-latest
ComfyUI workflow media live
- 테스트:
extensions/comfy/comfy.live.test.ts - 활성화:
OPENCLAW_LIVE_TEST=1 COMFY_LIVE_TEST=1 pnpm test:live -- extensions/comfy/comfy.live.test.ts - 범위:
- 번들된 comfy image, video,
music_generate경로를 실행합니다. models.providers.comfy.<capability>가 구성되지 않은 capability는 각각 건너뜁니다.- comfy workflow 제출, 폴링, 다운로드 또는 Plugin 등록을 변경한 뒤 유용합니다.
- 번들된 comfy image, video,
이미지 생성 live
- 테스트:
src/image-generation/runtime.live.test.ts - 명령:
pnpm test:live src/image-generation/runtime.live.test.ts - 하니스:
pnpm test:live:media image - 범위:
- 등록된 모든 이미지 생성 Provider Plugin을 열거합니다.
- 프로브 전에 로그인 셸(
~/.profile)에서 누락된 Provider env var를 불러옵니다. - 기본적으로 저장된 인증 프로필보다 live/env API 키를 우선 사용하므로,
auth-profiles.json의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않습니다. - 사용 가능한 인증/프로필/모델이 없는 Provider는 건너뜁니다.
- 공유 runtime capability를 통해 기본 이미지 생성 변형을 실행합니다:
google:flash-generategoogle:pro-generategoogle:pro-editopenai:default-generate
- 현재 커버되는 번들 Provider:
openaigoogle
- 선택적 범위 축소:
OPENCLAW_LIVE_IMAGE_GENERATION_PROVIDERS="openai,google"OPENCLAW_LIVE_IMAGE_GENERATION_MODELS="openai/gpt-image-1,google/gemini-3.1-flash-image-preview"OPENCLAW_LIVE_IMAGE_GENERATION_CASES="google:flash-generate,google:pro-edit"
- 선택적 인증 동작:
- 프로필 저장소 인증을 강제하고 env 전용 재정의를 무시하려면
OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1
- 프로필 저장소 인증을 강제하고 env 전용 재정의를 무시하려면
음악 생성 live
- 테스트:
extensions/music-generation-providers.live.test.ts - 활성화:
OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/music-generation-providers.live.test.ts - 하니스:
pnpm test:live:media music - 범위:
- 공유 번들 음악 생성 Provider 경로를 실행합니다.
- 현재 Google과 MiniMax를 커버합니다.
- 프로브 전에 로그인 셸(
~/.profile)에서 Provider env var를 불러옵니다. - 기본적으로 저장된 인증 프로필보다 live/env API 키를 우선 사용하므로,
auth-profiles.json의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않습니다. - 사용 가능한 인증/프로필/모델이 없는 Provider는 건너뜁니다.
- 가능한 경우 선언된 두 runtime 모드를 모두 실행합니다:
- 프롬프트 전용 입력을 사용하는
generate - Provider가
capabilities.edit.enabled를 선언하면edit
- 프롬프트 전용 입력을 사용하는
- 현재 공유 레인 커버리지:
google:generate,editminimax:generatecomfy: 별도 Comfy live 파일에서 다루며, 이 공유 스윕에서는 다루지 않음
- 선택적 범위 축소:
OPENCLAW_LIVE_MUSIC_GENERATION_PROVIDERS="google,minimax"OPENCLAW_LIVE_MUSIC_GENERATION_MODELS="google/lyria-3-clip-preview,minimax/music-2.5+"
- 선택적 인증 동작:
- 프로필 저장소 인증을 강제하고 env 전용 재정의를 무시하려면
OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1
- 프로필 저장소 인증을 강제하고 env 전용 재정의를 무시하려면
비디오 생성 live
- 테스트:
extensions/video-generation-providers.live.test.ts - 활성화:
OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/video-generation-providers.live.test.ts - 하니스:
pnpm test:live:media video - 범위:
- 공유 번들 비디오 생성 Provider 경로를 실행합니다.
- 프로브 전에 로그인 셸(
~/.profile)에서 Provider env var를 불러옵니다. - 기본적으로 저장된 인증 프로필보다 live/env API 키를 우선 사용하므로,
auth-profiles.json의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않습니다. - 사용 가능한 인증/프로필/모델이 없는 Provider는 건너뜁니다.
- 가능한 경우 선언된 두 runtime 모드를 모두 실행합니다:
- 프롬프트 전용 입력을 사용하는
generate - Provider가
capabilities.imageToVideo.enabled를 선언하고 선택된 Provider/모델이 공유 스윕에서 buffer 기반 로컬 image 입력을 허용하면imageToVideo - Provider가
capabilities.videoToVideo.enabled를 선언하고 선택된 Provider/모델이 공유 스윕에서 buffer 기반 로컬 video 입력을 허용하면videoToVideo
- 프롬프트 전용 입력을 사용하는
- 공유 스윕에서 현재 선언되었지만 건너뛰는
imageToVideoProvider:vydra: 번들veo3는 텍스트 전용이고 번들kling은 원격 image URL이 필요하기 때문
- Provider별 Vydra 커버리지:
OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_VYDRA_VIDEO=1 pnpm test:live -- extensions/vydra/vydra.live.test.ts- 이 파일은 기본적으로 원격 image URL fixture를 사용하는
kling레인과 함께veo3text-to-video를 실행합니다.
- 현재
videoToVideolive 커버리지:- 선택된 모델이
runway/gen4_aleph일 때만runway
- 선택된 모델이
- 공유 스윕에서 현재 선언되었지만 건너뛰는
videoToVideoProvider:alibaba,qwen,xai: 이 경로들은 현재 원격http(s)/ MP4 참조 URL이 필요하기 때문google: 현재 공유 Gemini/Veo 레인은 로컬 buffer 기반 입력을 사용하고, 이 경로는 공유 스윕에서 허용되지 않기 때문openai: 현재 공유 레인에는 org별 비디오 인페인트/리믹스 접근 보장이 없기 때문
- 선택적 범위 축소:
OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="google,openai,runway"OPENCLAW_LIVE_VIDEO_GENERATION_MODELS="google/veo-3.1-fast-generate-preview,openai/sora-2,runway/gen4_aleph"
- 선택적 인증 동작:
- 프로필 저장소 인증을 강제하고 env 전용 재정의를 무시하려면
OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1
- 프로필 저장소 인증을 강제하고 env 전용 재정의를 무시하려면
미디어 live 하니스
- 명령:
pnpm test:live:media - 목적:
- 공유 image, music, video live 스위트를 하나의 리포지토리 기본 진입점으로 실행합니다.
~/.profile에서 누락된 Provider env var를 자동으로 불러옵니다.- 기본적으로 현재 사용 가능한 인증이 있는 Provider로 각 스위트를 자동 축소합니다.
scripts/test-live.mjs를 재사용하므로 Heartbeat와 quiet 모드 동작이 일관되게 유지됩니다.
- 예시:
pnpm test:live:mediapnpm test:live:media image video --providers openai,google,minimaxpnpm test:live:media video --video-providers openai,runway --all-providerspnpm test:live:media music --quiet
Docker 러너(선택적 “Linux에서도 동작하는가” 확인)
이 Docker 러너는 두 가지 범주로 나뉩니다:- live 모델 러너:
test:docker:live-models와test:docker:live-gateway는 리포지토리 Docker 이미지 안에서 해당 프로필 키 live 파일만 실행합니다(src/agents/models.profiles.live.test.ts및src/gateway/gateway-models.profiles.live.test.ts). 이때 로컬 config 디렉터리와 워크스페이스를 마운트하고(마운트된 경우~/.profile도 소스함), 대응하는 로컬 진입점은test:live:models-profiles와test:live:gateway-profiles입니다. - Docker live 러너는 전체 Docker 스윕이 실용적이도록 기본적으로 더 작은 스모크 상한을 사용합니다:
test:docker:live-models는 기본적으로OPENCLAW_LIVE_MAX_MODELS=12를 사용하고,test:docker:live-gateway는 기본적으로OPENCLAW_LIVE_GATEWAY_SMOKE=1,OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8,OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000, 그리고OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000를 사용합니다. 더 큰 exhaustive 스캔이 필요할 때는 이 env var들을 명시적으로 재정의하세요. test:docker:all은 먼저test:docker:live-build를 통해 live Docker 이미지를 한 번 빌드한 다음, 두 개의 live Docker 레인에서 이를 재사용합니다.- 컨테이너 스모크 러너:
test:docker:openwebui,test:docker:onboard,test:docker:gateway-network,test:docker:mcp-channels,test:docker:plugins는 하나 이상의 실제 컨테이너를 부팅하고 더 높은 수준의 integration 경로를 검증합니다.
- 직접 모델:
pnpm test:docker:live-models(스크립트:scripts/test-live-models-docker.sh) - ACP 바인드 스모크:
pnpm test:docker:live-acp-bind(스크립트:scripts/test-live-acp-bind-docker.sh) - CLI 백엔드 스모크:
pnpm test:docker:live-cli-backend(스크립트:scripts/test-live-cli-backend-docker.sh) - Codex app-server harness 스모크:
pnpm test:docker:live-codex-harness(스크립트:scripts/test-live-codex-harness-docker.sh) - Gateway + dev 에이전트:
pnpm test:docker:live-gateway(스크립트:scripts/test-live-gateway-models-docker.sh) - Open WebUI live 스모크:
pnpm test:docker:openwebui(스크립트:scripts/e2e/openwebui-docker.sh) - 온보딩 wizard(TTY, 전체 scaffolding):
pnpm test:docker:onboard(스크립트:scripts/e2e/onboard-docker.sh) - Gateway 네트워킹(두 컨테이너, WS auth + health):
pnpm test:docker:gateway-network(스크립트:scripts/e2e/gateway-network-docker.sh) - MCP 채널 브리지(seed된 Gateway + stdio 브리지 + 원시 Claude notification-frame 스모크):
pnpm test:docker:mcp-channels(스크립트:scripts/e2e/mcp-channels-docker.sh) - Plugins(설치 스모크 +
/pluginalias + Claude 번들 재시작 semantics):pnpm test:docker:plugins(스크립트:scripts/e2e/plugins-docker.sh)
.pnpm-store, .worktrees, __openclaw_vitest__, app 로컬 .build,
Gradle 출력 디렉터리 같은 큰 로컬 전용 캐시와 앱 빌드 출력을 건너뛰므로
Docker live 실행이 머신별 artifact를 복사하느라 몇 분씩 소비하지 않습니다.
또한 OPENCLAW_SKIP_CHANNELS=1을 설정하므로 Gateway live 프로브가
컨테이너 내부에서 실제 Telegram/Discord 등의 채널 워커를 시작하지 않습니다.
test:docker:live-models는 여전히 pnpm test:live를 실행하므로,
해당 Docker 레인에서 Gateway live 커버리지를 좁히거나 제외해야 할 때는
OPENCLAW_LIVE_GATEWAY_*도 함께 전달하세요.
test:docker:openwebui는 더 높은 수준의 호환성 스모크입니다. 이 레인은
OpenAI 호환 HTTP endpoint가 활성화된 OpenClaw Gateway 컨테이너를 시작하고,
해당 Gateway를 대상으로 고정된 Open WebUI 컨테이너를 시작한 뒤,
Open WebUI를 통해 로그인하고, /api/models가 openclaw/default를 노출하는지 확인한 다음,
Open WebUI의 /api/chat/completions 프록시를 통해
실제 chat 요청을 전송합니다.
첫 실행은 Docker가
Open WebUI 이미지를 pull해야 하거나 Open WebUI가 자체 cold-start setup을 마쳐야 할 수 있으므로
눈에 띄게 더 느릴 수 있습니다.
이 레인은 사용 가능한 live 모델 키를 기대하며,
OPENCLAW_PROFILE_FILE(~/.profile이 기본값)이
Dockerized 실행에서 이를 제공하는 기본 방식입니다.
성공적으로 실행되면 { "ok": true, "model": "openclaw/default", ... }와 같은 작은 JSON payload가 출력됩니다.
test:docker:mcp-channels는 의도적으로 결정적이며
실제 Telegram, Discord 또는 iMessage 계정이 필요하지 않습니다. 이 레인은
seed된 Gateway 컨테이너를 부팅하고,
openclaw mcp serve를 spawn하는 두 번째 컨테이너를 시작한 뒤,
실제 stdio MCP 브리지를 통해 라우팅된 대화 검색, transcript 읽기, attachment 메타데이터,
live event queue 동작, outbound 전송 라우팅, Claude 스타일 채널 +
권한 알림을 검증합니다. notification 검사는
원시 stdio MCP 프레임을 직접 검사하므로, 이 스모크는
특정 client SDK가 우연히 표면화하는 내용이 아니라 브리지가 실제로 방출하는 것을 검증합니다.
수동 ACP plain-language 스레드 스모크(CI 아님):
bun scripts/dev/discord-acp-plain-language-smoke.ts --channel <discord-channel-id> ...- 이 스크립트는 회귀/디버그 워크플로를 위해 유지하세요. ACP 스레드 라우팅 검증에 다시 필요할 수 있으므로 삭제하지 마세요.
OPENCLAW_CONFIG_DIR=...(기본값:~/.openclaw)를/home/node/.openclaw에 마운트OPENCLAW_WORKSPACE_DIR=...(기본값:~/.openclaw/workspace)를/home/node/.openclaw/workspace에 마운트OPENCLAW_PROFILE_FILE=...(기본값:~/.profile)를/home/node/.profile에 마운트하고 테스트 실행 전 소스OPENCLAW_DOCKER_CLI_TOOLS_DIR=...(기본값:~/.cache/openclaw/docker-cli-tools)를/home/node/.npm-global에 마운트하여 Docker 내부 CLI 설치 캐시로 사용$HOME아래의 외부 CLI 인증 디렉터리/파일은/host-auth...아래에 읽기 전용으로 마운트된 다음, 테스트 시작 전에/home/node/...로 복사됩니다- 기본 디렉터리:
.minimax - 기본 파일:
~/.codex/auth.json,~/.codex/config.toml,.claude.json,~/.claude/.credentials.json,~/.claude/settings.json,~/.claude/settings.local.json - 범위를 좁힌 Provider 실행은
OPENCLAW_LIVE_PROVIDERS/OPENCLAW_LIVE_GATEWAY_PROVIDERS에서 추론된 필요한 디렉터리/파일만 마운트합니다 - 수동 재정의:
OPENCLAW_DOCKER_AUTH_DIRS=all,OPENCLAW_DOCKER_AUTH_DIRS=none, 또는OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex같은 쉼표 목록
- 기본 디렉터리:
- 실행 범위를 좁히려면
OPENCLAW_LIVE_GATEWAY_MODELS=.../OPENCLAW_LIVE_MODELS=... - 컨테이너 내부 Provider 필터링을 위해
OPENCLAW_LIVE_GATEWAY_PROVIDERS=.../OPENCLAW_LIVE_PROVIDERS=... - 재빌드가 필요 없는 재실행에서 기존
openclaw:local-live이미지를 재사용하려면OPENCLAW_SKIP_DOCKER_BUILD=1 - 자격 증명이 프로필 저장소에서 오도록 보장하려면(환경 변수 아님)
OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1 - Open WebUI 스모크를 위해 Gateway가 노출할 모델을 선택하려면
OPENCLAW_OPENWEBUI_MODEL=... - Open WebUI 스모크에서 사용하는 nonce 확인 프롬프트를 재정의하려면
OPENCLAW_OPENWEBUI_PROMPT=... - 고정된 Open WebUI 이미지 태그를 재정의하려면
OPENWEBUI_IMAGE=...
문서 sanity 확인
문서를 수정한 뒤에는 docs 검사를 실행하세요:pnpm check:docs.
페이지 내 heading 검사도 필요할 때는 전체 Mintlify anchor 검증을 실행하세요: pnpm docs:check-links:anchors.
오프라인 회귀(CI 안전)
이들은 실제 Provider 없이 “실제 파이프라인” 회귀를 검증합니다.- Gateway tool calling(mock OpenAI, 실제 Gateway + 에이전트 루프):
src/gateway/gateway.test.ts(케이스: “runs a mock OpenAI tool call end-to-end via gateway agent loop”) - Gateway wizard(WS
wizard.start/wizard.next, config + auth 강제 기록):src/gateway/gateway.test.ts(케이스: “runs wizard over ws and writes auth token config”)
에이전트 신뢰성 평가(Skills)
이미 “에이전트 신뢰성 평가”처럼 동작하는 몇 가지 CI 안전 테스트가 있습니다.- 실제 Gateway + 에이전트 루프를 통한 mock tool-calling(
src/gateway/gateway.test.ts) - 세션 wiring과 config 효과를 검증하는 엔드투엔드 wizard 흐름(
src/gateway/gateway.test.ts)
- 의사결정: 프롬프트에 Skills가 나열되었을 때, 에이전트가 올바른 skill을 선택하는가(또는 관련 없는 skill을 피하는가)?
- 준수: 에이전트가 사용 전에
SKILL.md를 읽고 필수 단계/인자를 따르는가? - 워크플로 계약: tool 순서, 세션 히스토리 유지, sandbox 경계를 검증하는 다중 턴 시나리오.
- mock Provider를 사용해 tool 호출 + 순서, skill 파일 읽기, 세션 wiring을 검증하는 시나리오 러너
- skill 중심 시나리오의 소규모 스위트(사용 vs 회피, 게이팅, 프롬프트 인젝션)
- CI 안전 스위트가 마련된 뒤에만 선택적으로 live 평가(옵트인, env 게이트)
계약 테스트(Plugin 및 채널 형태)
계약 테스트는 등록된 모든 Plugin과 채널이 해당 인터페이스 계약을 준수하는지 검증합니다. 이 테스트들은 발견된 모든 Plugin을 순회하며 형태 및 동작 검증 스위트를 실행합니다. 기본pnpm test unit 레인은
의도적으로 이러한 공유 seam 및 스모크 파일을 건너뛰므로, 공유 채널 또는 Provider 표면을 건드렸다면
계약 명령을 명시적으로 실행하세요.
명령
- 모든 계약:
pnpm test:contracts - 채널 계약만:
pnpm test:contracts:channels - Provider 계약만:
pnpm test:contracts:plugins
채널 계약
src/channels/plugins/contracts/*.contract.test.ts에 위치:
- plugin - 기본 Plugin 형태(id, name, capability)
- setup - setup wizard 계약
- session-binding - 세션 바인딩 동작
- outbound-payload - 메시지 payload 구조
- inbound - inbound 메시지 처리
- actions - 채널 action 핸들러
- threading - 스레드 ID 처리
- directory - 디렉터리/roster API
- group-policy - 그룹 정책 강제
Provider 상태 계약
src/plugins/contracts/*.contract.test.ts에 위치합니다.
- status - 채널 상태 프로브
- registry - Plugin registry 형태
Provider 계약
src/plugins/contracts/*.contract.test.ts에 위치:
- auth - 인증 흐름 계약
- auth-choice - 인증 선택/선정
- catalog - 모델 catalog API
- discovery - Plugin 검색
- loader - Plugin 로딩
- runtime - Provider runtime
- shape - Plugin 형태/인터페이스
- wizard - setup wizard
실행 시점
- Plugin SDK export 또는 subpath를 변경한 후
- 채널 또는 Provider Plugin을 추가하거나 수정한 후
- Plugin 등록 또는 검색을 리팩터링한 후
회귀 테스트 추가하기(가이드)
live에서 발견된 Provider/모델 이슈를 수정할 때:- 가능하다면 CI 안전 회귀 테스트를 추가하세요(mock/stub Provider 또는 정확한 요청 형태 변환 캡처)
- 본질적으로 live 전용인 경우(rate limit, 인증 정책), live 테스트를 좁게 유지하고 env var로 옵트인되게 하세요
- 버그를 포착하는 가장 작은 계층을 타깃팅하는 것을 선호하세요:
- Provider 요청 변환/리플레이 버그 → 직접 모델 테스트
- Gateway 세션/히스토리/tool 파이프라인 버그 → Gateway live 스모크 또는 CI 안전 Gateway mock 테스트
- SecretRef 순회 가드레일:
src/secrets/exec-secret-ref-id-parity.test.ts는 registry 메타데이터(listSecretTargetRegistryEntries())에서 SecretRef 클래스별 샘플 타깃 하나를 도출한 뒤, 순회 세그먼트 exec id가 거부되는지 검증합니다.src/secrets/target-registry-data.ts에 새includeInPlanSecretRef 타깃 계열을 추가한다면, 해당 테스트의classifyTargetClass를 업데이트하세요. 이 테스트는 분류되지 않은 타깃 id에서 의도적으로 실패하므로 새 클래스가 조용히 건너뛰어질 수 없습니다.