chore(i18n): refresh ko translations
This commit is contained in:
parent
dfe2b55d05
commit
eede60d70e
@ -1,26 +1,26 @@
|
||||
---
|
||||
read_when:
|
||||
- /new, /reset, /stop 및 에이전트 수명 주기 이벤트를 위한 이벤트 기반 자동화가 필요합니다.
|
||||
- /new, /reset, /stop 및 에이전트 수명 주기 이벤트에 대한 이벤트 기반 자동화를 원합니다
|
||||
- 훅을 빌드, 설치 또는 디버그하려는 경우
|
||||
summary: '훅: 명령 및 수명 주기 이벤트를 위한 이벤트 기반 자동화'
|
||||
title: 훅
|
||||
title: 후크
|
||||
x-i18n:
|
||||
generated_at: "2026-05-03T21:27:26Z"
|
||||
generated_at: "2026-05-05T08:25:31Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 15f0d120ccf7314a991da5d66e65e5c78375222a846ba01d7a04ddfe1f02cb32
|
||||
source_hash: 321eb7a583d5e8c90d2c2026f6e1cf46cd207bef52213774b469a8d46b993967
|
||||
source_path: automation/hooks.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
훅은 Gateway 내부에서 어떤 일이 발생할 때 실행되는 작은 스크립트입니다. 디렉터리에서 발견할 수 있으며 `openclaw hooks`로 검사할 수 있습니다. Gateway는 훅을 활성화하거나 최소 하나의 훅 항목, 훅 팩, 레거시 핸들러 또는 추가 훅 디렉터리를 구성한 뒤에만 내부 훅을 로드합니다.
|
||||
훅은 Gateway 내부에서 어떤 일이 발생할 때 실행되는 작은 스크립트입니다. 디렉터리에서 발견할 수 있으며 `openclaw hooks`로 검사할 수 있습니다. Gateway는 훅을 활성화하거나 하나 이상의 훅 항목, 훅 팩, 레거시 핸들러 또는 추가 훅 디렉터리를 구성한 뒤에만 내부 훅을 로드합니다.
|
||||
|
||||
OpenClaw에는 두 종류의 훅이 있습니다.
|
||||
|
||||
- **내부 훅**(이 페이지): `/new`, `/reset`, `/stop` 또는 수명 주기 이벤트처럼 에이전트 이벤트가 발생할 때 Gateway 내부에서 실행됩니다.
|
||||
- **Webhook**: 다른 시스템이 OpenClaw에서 작업을 트리거할 수 있게 해주는 외부 HTTP 엔드포인트입니다. [Webhook](/ko/automation/cron-jobs#webhooks)을 참조하세요.
|
||||
- **Webhook**: 다른 시스템이 OpenClaw에서 작업을 트리거할 수 있게 하는 외부 HTTP 엔드포인트입니다. [Webhook](/ko/automation/cron-jobs#webhooks)을 참고하세요.
|
||||
|
||||
훅은 Plugin 안에 함께 번들될 수도 있습니다. `openclaw hooks list`는 독립 실행형 훅과 Plugin 관리 훅을 모두 표시합니다.
|
||||
훅은 Plugin 안에 번들로 포함될 수도 있습니다. `openclaw hooks list`는 독립 실행형 훅과 Plugin 관리 훅을 모두 표시합니다.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
@ -49,20 +49,20 @@ openclaw hooks info session-memory
|
||||
| `session:compact:before` | Compaction이 기록을 요약하기 전 |
|
||||
| `session:compact:after` | Compaction이 완료된 후 |
|
||||
| `session:patch` | 세션 속성이 수정될 때 |
|
||||
| `agent:bootstrap` | 워크스페이스 부트스트랩 파일이 주입되기 전 |
|
||||
| `agent:bootstrap` | 워크스페이스 부트스트랩 파일이 삽입되기 전 |
|
||||
| `gateway:startup` | 채널이 시작되고 훅이 로드된 후 |
|
||||
| `gateway:shutdown` | Gateway 종료가 시작될 때 |
|
||||
| `gateway:pre-restart` | 예상된 Gateway 재시작 전 |
|
||||
| `message:received` | 모든 채널에서 들어오는 메시지 |
|
||||
| `message:received` | 모든 채널에서 수신된 메시지 |
|
||||
| `message:transcribed` | 오디오 전사가 완료된 후 |
|
||||
| `message:preprocessed` | 미디어 및 링크 전처리가 완료되거나 건너뛰어진 후 |
|
||||
| `message:sent` | 보내는 메시지가 전달됨 |
|
||||
| `message:preprocessed` | 미디어 및 링크 전처리가 완료되거나 건너뛴 후 |
|
||||
| `message:sent` | 발신 메시지가 전달됨 |
|
||||
|
||||
## 훅 작성
|
||||
|
||||
### 훅 구조
|
||||
|
||||
각 훅은 두 파일을 포함하는 디렉터리입니다.
|
||||
각 훅은 두 파일이 포함된 디렉터리입니다.
|
||||
|
||||
```
|
||||
my-hook/
|
||||
@ -91,10 +91,10 @@ Detailed documentation goes here.
|
||||
| ---------- | ---------------------------------------------------- |
|
||||
| `emoji` | CLI에 표시할 이모지 |
|
||||
| `events` | 수신할 이벤트 배열 |
|
||||
| `export` | 사용할 명명된 내보내기(기본값은 `"default"`) |
|
||||
| `export` | 사용할 명명된 export(기본값은 `"default"`) |
|
||||
| `os` | 필요한 플랫폼(예: `["darwin", "linux"]`) |
|
||||
| `requires` | 필요한 `bins`, `anyBins`, `env` 또는 `config` 경로 |
|
||||
| `always` | 적격성 검사 우회(boolean) |
|
||||
| `requires` | 필요한 `bins`, `anyBins`, `env` 또는 `config` 경로 |
|
||||
| `always` | 적격성 검사를 우회함(불리언) |
|
||||
| `install` | 설치 방법 |
|
||||
|
||||
### 핸들러 구현
|
||||
@ -117,11 +117,11 @@ export default handler;
|
||||
|
||||
각 이벤트에는 `type`, `action`, `sessionKey`, `timestamp`, `messages`(사용자에게 보내려면 push), `context`(이벤트별 데이터)가 포함됩니다. 에이전트 및 도구 Plugin 훅 컨텍스트에는 `trace`도 포함될 수 있습니다. 이는 Plugin이 OTEL 상관관계를 위해 구조화된 로그에 전달할 수 있는 읽기 전용 W3C 호환 진단 추적 컨텍스트입니다.
|
||||
|
||||
### 이벤트 컨텍스트 주요 사항
|
||||
### 이벤트 컨텍스트 주요 내용
|
||||
|
||||
**명령 이벤트**(`command:new`, `command:reset`): `context.sessionEntry`, `context.previousSessionEntry`, `context.commandSource`, `context.workspaceDir`, `context.cfg`.
|
||||
|
||||
**메시지 이벤트**(`message:received`): `context.from`, `context.content`, `context.channelId`, `context.metadata`(`senderId`, `senderName`, `guildId`를 포함한 공급자별 데이터). `context.content`는 명령처럼 보이는 메시지에 대해 비어 있지 않은 명령 본문을 우선 사용하고, 그다음 원본 인바운드 본문과 일반 본문으로 대체됩니다. 스레드 기록이나 링크 요약 같은 에이전트 전용 보강 내용은 포함하지 않습니다.
|
||||
**메시지 이벤트**(`message:received`): `context.from`, `context.content`, `context.channelId`, `context.metadata`(`senderId`, `senderName`, `guildId`를 포함한 공급자별 데이터). `context.content`는 명령과 유사한 메시지의 비어 있지 않은 명령 본문을 우선 사용한 다음, 원시 수신 본문과 일반 본문으로 대체됩니다. 스레드 기록이나 링크 요약 같은 에이전트 전용 보강 정보는 포함하지 않습니다.
|
||||
|
||||
**메시지 이벤트**(`message:sent`): `context.to`, `context.content`, `context.success`, `context.channelId`.
|
||||
|
||||
@ -131,48 +131,51 @@ export default handler;
|
||||
|
||||
**부트스트랩 이벤트**(`agent:bootstrap`): `context.bootstrapFiles`(변경 가능한 배열), `context.agentId`.
|
||||
|
||||
**세션 패치 이벤트**(`session:patch`): `context.sessionEntry`, `context.patch`(변경된 필드만), `context.cfg`. 권한이 있는 클라이언트만 패치 이벤트를 트리거할 수 있습니다.
|
||||
**세션 패치 이벤트**(`session:patch`): `context.sessionEntry`, `context.patch`(변경된 필드만), `context.cfg`. 권한 있는 클라이언트만 패치 이벤트를 트리거할 수 있습니다.
|
||||
|
||||
**Compaction 이벤트**: `session:compact:before`에는 `messageCount`, `tokenCount`가 포함됩니다. `session:compact:after`는 `compactedCount`, `summaryLength`, `tokensBefore`, `tokensAfter`를 추가합니다.
|
||||
|
||||
`command:stop`은 사용자가 `/stop`을 실행하는 것을 관찰합니다. 이는 취소/명령 수명 주기이며, 에이전트 최종화 게이트가 아닙니다. 자연스러운 최종 답변을 검사하고 에이전트에 한 번 더 패스를 요청해야 하는 Plugin은 대신 타입이 지정된 Plugin 훅 `before_agent_finalize`를 사용해야 합니다. [Plugin 훅](/ko/plugins/hooks)을 참조하세요.
|
||||
`command:stop`은 사용자가 `/stop`을 실행하는 것을 관찰합니다. 이는 취소/명령
|
||||
수명 주기이며, 에이전트 최종화 게이트가 아닙니다. 자연스러운 최종 답변을 검사하고
|
||||
에이전트에 한 번 더 패스를 요청해야 하는 Plugin은 대신 타입이 지정된
|
||||
Plugin 훅 `before_agent_finalize`를 사용해야 합니다. [Plugin 훅](/ko/plugins/hooks)을 참고하세요.
|
||||
|
||||
**Gateway 수명 주기 이벤트**: `gateway:shutdown`은 `reason`과 `restartExpectedMs`를 포함하며 Gateway 종료가 시작될 때 발생합니다. `gateway:pre-restart`는 같은 컨텍스트를 포함하지만, 종료가 예상된 재시작의 일부이고 유한한 `restartExpectedMs` 값이 제공될 때만 발생합니다. 종료 중에는 각 수명 주기 훅 대기가 최선 노력 방식으로 제한되므로 핸들러가 멈춰도 종료가 계속됩니다.
|
||||
**Gateway 수명 주기 이벤트**: `gateway:shutdown`에는 `reason`과 `restartExpectedMs`가 포함되며 Gateway 종료가 시작될 때 발생합니다. `gateway:pre-restart`는 같은 컨텍스트를 포함하지만, 종료가 예상된 재시작의 일부이고 유한한 `restartExpectedMs` 값이 제공된 경우에만 발생합니다. 종료 중에는 각 수명 주기 훅 대기가 최선형이며 제한되어 있으므로 핸들러가 멈춰도 종료가 계속됩니다.
|
||||
|
||||
## 훅 발견
|
||||
|
||||
훅은 다음 디렉터리에서 발견되며, 아래 순서일수록 오버라이드 우선순위가 높아집니다.
|
||||
훅은 다음 디렉터리에서 발견되며, override 우선순위가 높아지는 순서입니다.
|
||||
|
||||
1. **번들 훅**: OpenClaw와 함께 제공됨
|
||||
2. **Plugin 훅**: 설치된 Plugin 안에 번들된 훅
|
||||
3. **관리형 훅**: `~/.openclaw/hooks/`(사용자 설치, 워크스페이스 간 공유). `hooks.internal.load.extraDirs`의 추가 디렉터리도 이 우선순위를 공유합니다.
|
||||
4. **워크스페이스 훅**: `<workspace>/hooks/`(에이전트별, 명시적으로 활성화할 때까지 기본적으로 비활성화됨)
|
||||
2. **Plugin 훅**: 설치된 Plugin 안에 번들로 포함된 훅
|
||||
3. **관리형 훅**: `~/.openclaw/hooks/`(사용자가 설치하며, 워크스페이스 간 공유됨). `hooks.internal.load.extraDirs`의 추가 디렉터리도 이 우선순위를 공유합니다.
|
||||
4. **워크스페이스 훅**: `<workspace>/hooks/`(에이전트별, 명시적으로 활성화하기 전까지 기본적으로 비활성화됨)
|
||||
|
||||
워크스페이스 훅은 새 훅 이름을 추가할 수 있지만, 이름이 같은 번들 훅, 관리형 훅 또는 Plugin 제공 훅을 오버라이드할 수는 없습니다.
|
||||
워크스페이스 훅은 새 훅 이름을 추가할 수 있지만, 같은 이름의 번들, 관리형 또는 Plugin 제공 훅을 override할 수 없습니다.
|
||||
|
||||
Gateway는 내부 훅이 구성될 때까지 시작 시 내부 훅 발견을 건너뜁니다. 번들 또는 관리형 훅을 `openclaw hooks enable <name>`으로 활성화하거나, 훅 팩을 설치하거나, `hooks.internal.enabled=true`를 설정하여 옵트인하세요. 명명된 훅 하나를 활성화하면 Gateway는 해당 훅의 핸들러만 로드합니다. `hooks.internal.enabled=true`, 추가 훅 디렉터리, 레거시 핸들러는 광범위한 발견에 옵트인합니다.
|
||||
Gateway는 내부 훅이 구성될 때까지 시작 시 내부 훅 발견을 건너뜁니다. `openclaw hooks enable <name>`으로 번들 또는 관리형 훅을 활성화하거나, 훅 팩을 설치하거나, `hooks.internal.enabled=true`를 설정하여 옵트인하세요. 하나의 명명된 훅을 활성화하면 Gateway는 해당 훅의 핸들러만 로드합니다. `hooks.internal.enabled=true`, 추가 훅 디렉터리, 레거시 핸들러는 광범위한 발견에 옵트인합니다.
|
||||
|
||||
### 훅 팩
|
||||
|
||||
훅 팩은 `package.json`의 `openclaw.hooks`를 통해 훅을 내보내는 npm 패키지입니다. 다음으로 설치합니다.
|
||||
Hook 팩은 `package.json`의 `openclaw.hooks`를 통해 Hook을 내보내는 npm 패키지입니다. 다음으로 설치합니다.
|
||||
|
||||
```bash
|
||||
openclaw plugins install <path-or-spec>
|
||||
```
|
||||
|
||||
Npm 사양은 레지스트리 전용입니다(패키지 이름 + 선택적 정확한 버전 또는 dist-tag). Git/URL/file 사양과 semver 범위는 거부됩니다.
|
||||
Npm spec은 레지스트리 전용입니다(패키지 이름 + 선택적 정확한 버전 또는 dist-tag). Git/URL/file spec과 semver 범위는 거부됩니다.
|
||||
|
||||
## 번들 훅
|
||||
## 번들 Hook
|
||||
|
||||
| 훅 | 이벤트 | 수행 작업 |
|
||||
| --------------------- | ------------------------------------------------ | -------------------------------------------------------------- |
|
||||
| session-memory | `command:new`, `command:reset` | 세션 컨텍스트를 `<workspace>/memory/`에 저장 |
|
||||
| bootstrap-extra-files | `agent:bootstrap` | glob 패턴에서 추가 부트스트랩 파일을 주입 |
|
||||
| command-logger | `command` | 모든 명령을 `~/.openclaw/logs/commands.log`에 기록 |
|
||||
| compaction-notifier | `session:compact:before`, `session:compact:after` | 세션 Compaction 시작/종료 시 보이는 채팅 알림을 보냄 |
|
||||
| boot-md | `gateway:startup` | Gateway가 시작될 때 `BOOT.md`를 실행 |
|
||||
| Hook | 이벤트 | 수행 작업 |
|
||||
| --------------------- | ------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| session-memory | `command:new`, `command:reset` | 세션 컨텍스트를 `<workspace>/memory/`에 저장합니다 |
|
||||
| bootstrap-extra-files | `agent:bootstrap` | glob 패턴에서 추가 bootstrap 파일을 주입합니다 |
|
||||
| command-logger | `command` | 모든 명령을 `~/.openclaw/logs/commands.log`에 기록합니다 |
|
||||
| compaction-notifier | `session:compact:before`, `session:compact:after` | 세션 Compaction 시작/종료 시 표시되는 채팅 알림을 보냅니다 |
|
||||
| boot-md | `gateway:startup` | Gateway가 시작될 때 `BOOT.md`를 실행합니다 |
|
||||
|
||||
번들 훅을 활성화합니다.
|
||||
번들 Hook을 활성화합니다.
|
||||
|
||||
```bash
|
||||
openclaw hooks enable <hook-name>
|
||||
@ -182,7 +185,7 @@ openclaw hooks enable <hook-name>
|
||||
|
||||
### session-memory 세부 정보
|
||||
|
||||
마지막 15개의 사용자/어시스턴트 메시지를 추출하고, LLM을 통해 설명적인 파일 이름 슬러그를 생성한 뒤, 호스트 로컬 날짜를 사용해 `<workspace>/memory/YYYY-MM-DD-slug.md`에 저장합니다. `workspace.dir` 구성이 필요합니다.
|
||||
마지막 사용자/어시스턴트 메시지 15개를 추출하여 호스트 로컬 날짜를 사용해 `<workspace>/memory/YYYY-MM-DD-HHMM.md`에 저장합니다. 메모리 캡처는 백그라운드에서 실행되므로 `/new` 및 `/reset` 확인 응답이 대화 기록 읽기나 선택적 slug 생성으로 지연되지 않습니다. 구성된 모델로 설명적인 파일 이름 slug를 생성하려면 `hooks.internal.entries.session-memory.llmSlug: true`를 설정합니다. `workspace.dir`이 구성되어 있어야 합니다.
|
||||
|
||||
<a id="bootstrap-extra-files"></a>
|
||||
|
||||
@ -203,7 +206,7 @@ openclaw hooks enable <hook-name>
|
||||
}
|
||||
```
|
||||
|
||||
경로는 워크스페이스를 기준으로 해석됩니다. 인식되는 부트스트랩 기본 이름만 로드됩니다(`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, `MEMORY.md`).
|
||||
경로는 workspace를 기준으로 해석됩니다. 인식되는 bootstrap 기본 이름만 로드됩니다(`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, `MEMORY.md`).
|
||||
|
||||
<a id="command-logger"></a>
|
||||
|
||||
@ -215,21 +218,21 @@ openclaw hooks enable <hook-name>
|
||||
|
||||
### compaction-notifier 세부 정보
|
||||
|
||||
OpenClaw가 세션 transcript 압축을 시작하고 완료할 때 현재 대화에 짧은 상태 메시지를 보냅니다. 사용자는 어시스턴트가 컨텍스트를 요약 중이며 Compaction 후 계속 진행한다는 것을 볼 수 있으므로, 채팅 화면에서 긴 턴을 덜 혼란스럽게 만듭니다.
|
||||
OpenClaw가 세션 대화 기록 압축을 시작하고 완료할 때 현재 대화에 짧은 상태 메시지를 보냅니다. 사용자는 어시스턴트가 컨텍스트를 요약 중이며 Compaction 후 계속 진행한다는 것을 볼 수 있으므로, 채팅 표면에서 긴 턴의 혼란을 줄일 수 있습니다.
|
||||
|
||||
<a id="boot-md"></a>
|
||||
|
||||
### boot-md 세부 정보
|
||||
|
||||
Gateway가 시작될 때 활성 워크스페이스의 `BOOT.md`를 실행합니다.
|
||||
Gateway가 시작될 때 활성 workspace의 `BOOT.md`를 실행합니다.
|
||||
|
||||
## Plugin 훅
|
||||
## Plugin Hook
|
||||
|
||||
Plugin은 더 깊은 통합을 위해 Plugin SDK를 통해 타입이 지정된 훅을 등록할 수 있습니다.
|
||||
도구 호출 가로채기, 프롬프트 수정, 메시지 흐름 제어 등을 수행할 수 있습니다.
|
||||
`before_tool_call`, `before_agent_reply`, `before_install` 또는 기타 인프로세스 수명 주기 훅이 필요할 때 Plugin 훅을 사용하세요.
|
||||
Plugin은 더 깊은 통합을 위해 Plugin SDK를 통해 형식화된 Hook을 등록할 수 있습니다.
|
||||
도구 호출 가로채기, 프롬프트 수정, 메시지 흐름 제어 등을 지원합니다.
|
||||
`before_tool_call`, `before_agent_reply`, `before_install` 또는 기타 프로세스 내 수명 주기 Hook이 필요할 때 Plugin Hook을 사용합니다.
|
||||
|
||||
전체 Plugin 훅 참조는 [Plugin 훅](/ko/plugins/hooks)을 참조하세요.
|
||||
전체 Plugin Hook 참조는 [Plugin Hook](/ko/plugins/hooks)을 참조하세요.
|
||||
|
||||
## 구성
|
||||
|
||||
@ -247,7 +250,7 @@ Plugin은 더 깊은 통합을 위해 Plugin SDK를 통해 타입이 지정된
|
||||
}
|
||||
```
|
||||
|
||||
훅별 환경 변수:
|
||||
Hook별 환경 변수:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -264,7 +267,7 @@ Plugin은 더 깊은 통합을 위해 Plugin SDK를 통해 타입이 지정된
|
||||
}
|
||||
```
|
||||
|
||||
추가 훅 디렉터리:
|
||||
추가 Hook 디렉터리:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -279,7 +282,7 @@ Plugin은 더 깊은 통합을 위해 Plugin SDK를 통해 타입이 지정된
|
||||
```
|
||||
|
||||
<Note>
|
||||
레거시 `hooks.internal.handlers` 배열 구성 형식은 이전 버전과의 호환성을 위해 계속 지원되지만, 새 훅은 발견 기반 시스템을 사용해야 합니다.
|
||||
레거시 `hooks.internal.handlers` 배열 구성 형식은 이전 버전과의 호환성을 위해 아직 지원되지만, 새 Hook은 검색 기반 시스템을 사용해야 합니다.
|
||||
</Note>
|
||||
|
||||
## CLI 참조
|
||||
@ -301,14 +304,14 @@ openclaw hooks disable <hook-name>
|
||||
|
||||
## 모범 사례
|
||||
|
||||
- **핸들러를 빠르게 유지하세요.** 후크는 명령 처리 중에 실행됩니다. 무거운 작업은 `void processInBackground(event)`로 실행만 시키고 기다리지 마세요.
|
||||
- **핸들러를 빠르게 유지하세요.** 후크는 명령 처리 중에 실행됩니다. 무거운 작업은 `void processInBackground(event)`로 백그라운드에서 실행하고 기다리지 마세요.
|
||||
- **오류를 우아하게 처리하세요.** 위험한 작업은 try/catch로 감싸세요. 다른 핸들러가 실행될 수 있도록 throw하지 마세요.
|
||||
- **이벤트를 일찍 필터링하세요.** 이벤트 유형/작업이 관련 없으면 즉시 반환하세요.
|
||||
- **구체적인 이벤트 키를 사용하세요.** 오버헤드를 줄이려면 `"events": ["command"]`보다 `"events": ["command:new"]`를 선호하세요.
|
||||
- **이벤트를 일찍 필터링하세요.** 이벤트 유형/동작이 관련이 없으면 즉시 반환하세요.
|
||||
- **구체적인 이벤트 키를 사용하세요.** 오버헤드를 줄이려면 `"events": ["command"]`보다 `"events": ["command:new"]`을 선호하세요.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 후크가 발견되지 않음
|
||||
### 후크가 검색되지 않음
|
||||
|
||||
```bash
|
||||
# Verify directory structure
|
||||
@ -335,7 +338,7 @@ openclaw hooks info my-hook
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [CLI 참조: 후크](/ko/cli/hooks)
|
||||
- [Webhook](/ko/automation/cron-jobs#webhooks)
|
||||
- [Plugin 후크](/ko/plugins/hooks) — 프로세스 내 Plugin 수명 주기 후크
|
||||
- [CLI 참조: hooks](/ko/cli/hooks)
|
||||
- [Webhooks](/ko/automation/cron-jobs#webhooks)
|
||||
- [Plugin 후크](/ko/plugins/hooks) — 프로세스 내부 Plugin 수명 주기 후크
|
||||
- [구성](/ko/gateway/configuration-reference#hooks)
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
---
|
||||
read_when:
|
||||
- 채널 전송 계층은 연결되었다고 표시되지만 답장이 실패함
|
||||
- 심층 프로바이더 문서에 들어가기 전에 채널별 확인이 필요합니다
|
||||
summary: 채널별 실패 시그니처와 해결 방법을 포함한 빠른 채널 수준 문제 해결
|
||||
- 채널 전송 계층은 연결됨으로 표시되지만 응답이 실패합니다
|
||||
- 자세한 프로바이더 문서 전에 채널별 확인이 필요합니다
|
||||
summary: 채널별 실패 징후와 수정 방법으로 빠르게 채널 수준 문제 해결
|
||||
title: 채널 문제 해결
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T02:22:21Z"
|
||||
generated_at: "2026-05-05T08:25:32Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: a3a0737156ae83897c44d18505e0355a5d8e5700106b984496d94874c270deb2
|
||||
source_hash: 360184c41ce6929c696688af597c5104a8a28b54620c354f7ee400a2e5490519
|
||||
source_path: channels/troubleshooting.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
채널이 연결되었지만 동작이 잘못된 경우 이 페이지를 사용하세요.
|
||||
채널은 연결되지만 동작이 잘못된 경우 이 페이지를 사용하세요.
|
||||
|
||||
## 명령 단계
|
||||
## 명령 실행 순서
|
||||
|
||||
먼저 다음을 순서대로 실행하세요.
|
||||
|
||||
@ -27,76 +27,77 @@ openclaw doctor
|
||||
openclaw channels status --probe
|
||||
```
|
||||
|
||||
정상 기준:
|
||||
정상 기준선:
|
||||
|
||||
- `Runtime: running`
|
||||
- `Connectivity probe: ok`
|
||||
- `Capability: read-only`, `write-capable`, 또는 `admin-capable`
|
||||
- 채널 프로브에 전송 계층이 연결된 것으로 표시되고, 지원되는 경우 `works` 또는 `audit ok`가 표시됨
|
||||
- 채널 프로브가 전송 계층이 연결되었음을 표시하고, 지원되는 경우 `works` 또는 `audit ok`를 표시합니다.
|
||||
|
||||
## WhatsApp
|
||||
|
||||
### WhatsApp 실패 징후
|
||||
### WhatsApp 장애 징후
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 연결되었지만 DM 응답 없음 | `openclaw pairing list whatsapp` | 발신자를 승인하거나 DM 정책/허용 목록을 전환하세요. |
|
||||
| 그룹 메시지가 무시됨 | 설정에서 `requireMention` + 멘션 패턴 확인 | 봇을 멘션하거나 해당 그룹의 멘션 정책을 완화하세요. |
|
||||
| QR 로그인 시간이 408로 초과됨 | Gateway `HTTPS_PROXY` / `HTTP_PROXY` env 확인 | 도달 가능한 프록시를 설정하세요. 우회할 때만 `NO_PROXY`를 사용하세요. |
|
||||
| 임의의 연결 해제/재로그인 루프 | `openclaw channels status --probe` + 로그 | 현재 연결되어 있어도 최근 재연결이 표시됩니다. 로그를 확인하고 Gateway를 다시 시작한 뒤, 계속 불안정하면 다시 연결하세요. |
|
||||
| 증상 | 가장 빠른 확인 방법 | 수정 방법 |
|
||||
| ----------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 연결되었지만 DM 답장이 없음 | `openclaw pairing list whatsapp` | 발신자를 승인하거나 DM 정책/허용 목록을 전환하세요. |
|
||||
| 그룹 메시지가 무시됨 | 구성에서 `requireMention` + 멘션 패턴 확인 | 봇을 멘션하거나 해당 그룹의 멘션 정책을 완화하세요. |
|
||||
| QR 로그인 시간이 408로 초과됨 | Gateway `HTTPS_PROXY` / `HTTP_PROXY` env 확인 | 도달 가능한 프록시를 설정하세요. `NO_PROXY`는 우회에만 사용하세요. |
|
||||
| 무작위 연결 끊김/재로그인 루프 | `openclaw channels status --probe` + 로그 | 현재 연결되어 있어도 최근 재연결은 플래그로 표시됩니다. 로그를 확인하고 Gateway를 재시작한 다음, 흔들림이 계속되면 다시 연결하세요. |
|
||||
| 답장이 몇 초/몇 분 늦게 도착함 | `openclaw doctor --fix` | 검증된 오래된 로컬 TUI 클라이언트가 Gateway 이벤트 루프를 저하시킬 때 Doctor가 이를 중지합니다. |
|
||||
|
||||
전체 문제 해결: [WhatsApp 문제 해결](/ko/channels/whatsapp#troubleshooting)
|
||||
|
||||
## Telegram
|
||||
|
||||
### Telegram 실패 징후
|
||||
### Telegram 장애 징후
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ----------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `/start` 후에도 사용할 수 있는 응답 흐름 없음 | `openclaw pairing list telegram` | 페어링을 승인하거나 DM 정책을 변경하세요. |
|
||||
| 봇이 온라인이지만 그룹이 계속 조용함 | 멘션 요구 사항과 봇 개인정보 보호 모드 확인 | 그룹 가시성을 위해 개인정보 보호 모드를 비활성화하거나 봇을 멘션하세요. |
|
||||
| 네트워크 오류로 전송 실패 | Telegram API 호출 실패 로그 검사 | `api.telegram.org`로 가는 DNS/IPv6/프록시 라우팅을 수정하세요. |
|
||||
| 시작 시 `getMe returned 401` 보고 | 구성된 토큰 소스 확인 | BotFather 토큰을 다시 복사하거나 재생성한 뒤 `botToken`, `tokenFile`, 또는 기본 계정 `TELEGRAM_BOT_TOKEN`을 업데이트하세요. |
|
||||
| 폴링이 멈추거나 재연결이 느림 | 폴링 진단을 위해 `openclaw logs --follow` 실행 | 업그레이드하세요. 재시작이 오탐이면 `pollingStallThresholdMs`를 조정하세요. 지속적인 멈춤은 여전히 프록시/DNS/IPv6를 가리킵니다. |
|
||||
| 시작 시 `setMyCommands`가 거부됨 | `BOT_COMMANDS_TOO_MUCH` 로그 검사 | Plugin/skill/사용자 지정 Telegram 명령을 줄이거나 네이티브 메뉴를 비활성화하세요. |
|
||||
| 업그레이드 후 허용 목록이 사용자를 차단함 | `openclaw security audit` 및 설정 허용 목록 확인 | `openclaw doctor --fix`를 실행하거나 `@username`을 숫자 발신자 ID로 바꾸세요. |
|
||||
| 증상 | 가장 빠른 확인 방법 | 수정 방법 |
|
||||
| ------------------------------------ | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `/start` 후 사용 가능한 답장 흐름이 없음 | `openclaw pairing list telegram` | 페어링을 승인하거나 DM 정책을 변경하세요. |
|
||||
| 봇이 온라인이지만 그룹이 계속 조용함 | 멘션 요구 사항과 봇 개인정보 보호 모드 확인 | 그룹 가시성을 위해 개인정보 보호 모드를 비활성화하거나 봇을 멘션하세요. |
|
||||
| 네트워크 오류로 전송 실패 | Telegram API 호출 실패가 있는지 로그 검사 | `api.telegram.org`로 향하는 DNS/IPv6/프록시 라우팅을 수정하세요. |
|
||||
| 시작 시 `getMe returned 401` 보고 | 구성된 토큰 소스 확인 | BotFather 토큰을 다시 복사하거나 재생성하고 `botToken`, `tokenFile` 또는 기본 계정 `TELEGRAM_BOT_TOKEN`을 업데이트하세요. |
|
||||
| 폴링이 멈추거나 느리게 재연결됨 | 폴링 진단용 `openclaw logs --follow` | 업그레이드하세요. 재시작이 오탐이면 `pollingStallThresholdMs`를 조정하세요. 지속적인 멈춤은 여전히 프록시/DNS/IPv6 문제를 가리킵니다. |
|
||||
| 시작 시 `setMyCommands`가 거부됨 | 로그에서 `BOT_COMMANDS_TOO_MUCH` 검사 | Plugin/skill/사용자 지정 Telegram 명령을 줄이거나 네이티브 메뉴를 비활성화하세요. |
|
||||
| 업그레이드 후 허용 목록이 사용자를 차단함 | `openclaw security audit` 및 구성 허용 목록 | `openclaw doctor --fix`를 실행하거나 `@username`을 숫자 발신자 ID로 바꾸세요. |
|
||||
|
||||
전체 문제 해결: [Telegram 문제 해결](/ko/channels/telegram#troubleshooting)
|
||||
|
||||
## Discord
|
||||
|
||||
### Discord 실패 징후
|
||||
### Discord 장애 징후
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ----------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| 봇이 온라인이지만 길드 응답 없음 | `openclaw channels status --probe` | 길드/채널을 허용하고 메시지 콘텐츠 intent를 확인하세요. |
|
||||
| 그룹 메시지가 무시됨 | 멘션 게이팅 드롭 로그 확인 | 봇을 멘션하거나 길드/채널 `requireMention: false`를 설정하세요. |
|
||||
| 입력/토큰 사용은 있지만 Discord 메시지 없음 | 세션 로그에 `didSendViaMessagingTool: false`가 포함된 어시스턴트 텍스트 표시 | 모델이 메시지 도구를 호출하는 대신 비공개로 답했습니다. 도구 호출이 안정적인 모델을 사용하거나, 자동 게시를 위해 `messages.groupChat.visibleReplies: "automatic"`을 설정하세요. |
|
||||
| DM 응답 누락 | `openclaw pairing list discord` | DM 페어링을 승인하거나 DM 정책을 조정하세요. |
|
||||
| 증상 | 가장 빠른 확인 방법 | 수정 방법 |
|
||||
| ----------------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 봇이 온라인이지만 길드 답장이 없음 | `openclaw channels status --probe` | 길드/채널을 허용하고 메시지 콘텐츠 intent를 확인하세요. |
|
||||
| 그룹 메시지가 무시됨 | 멘션 게이팅 드롭이 있는지 로그 확인 | 봇을 멘션하거나 길드/채널 `requireMention: false`를 설정하세요. |
|
||||
| 입력 중/토큰 사용량은 있지만 Discord 메시지가 없음 | 세션 로그에 `didSendViaMessagingTool: false`가 포함된 어시스턴트 텍스트 표시 | 모델이 메시지 도구를 호출하는 대신 비공개로 답했습니다. 도구 호출이 안정적인 모델을 사용하거나 `messages.groupChat.visibleReplies: "automatic"`을 설정해 자동 게시하세요. |
|
||||
| DM 답장이 누락됨 | `openclaw pairing list discord` | DM 페어링을 승인하거나 DM 정책을 조정하세요. |
|
||||
|
||||
전체 문제 해결: [Discord 문제 해결](/ko/channels/discord#troubleshooting)
|
||||
|
||||
## Slack
|
||||
|
||||
### Slack 실패 징후
|
||||
### Slack 장애 징후
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ----------------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Socket mode가 연결되었지만 응답 없음 | `openclaw channels status --probe` | app token + bot token 및 필요한 범위를 확인하세요. SecretRef 기반 설정에서는 `botTokenStatus` / `appTokenStatus = configured_unavailable`을 주시하세요. |
|
||||
| DM 차단됨 | `openclaw pairing list slack` | 페어링을 승인하거나 DM 정책을 완화하세요. |
|
||||
| 채널 메시지가 무시됨 | `groupPolicy`와 채널 허용 목록 확인 | 채널을 허용하거나 정책을 `open`으로 전환하세요. |
|
||||
| 증상 | 가장 빠른 확인 방법 | 수정 방법 |
|
||||
| -------------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 소켓 모드는 연결되었지만 응답이 없음 | `openclaw channels status --probe` | 앱 토큰 + 봇 토큰 및 필요한 범위를 확인하세요. SecretRef 기반 설정에서는 `botTokenStatus` / `appTokenStatus = configured_unavailable`를 주시하세요. |
|
||||
| DM이 차단됨 | `openclaw pairing list slack` | 페어링을 승인하거나 DM 정책을 완화하세요. |
|
||||
| 채널 메시지가 무시됨 | `groupPolicy` 및 채널 허용 목록 확인 | 채널을 허용하거나 정책을 `open`으로 전환하세요. |
|
||||
|
||||
전체 문제 해결: [Slack 문제 해결](/ko/channels/slack#troubleshooting)
|
||||
|
||||
## iMessage 및 BlueBubbles
|
||||
|
||||
### iMessage 및 BlueBubbles 실패 징후
|
||||
### iMessage 및 BlueBubbles 장애 징후
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ---------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------- |
|
||||
| 인바운드 이벤트 없음 | Webhook/서버 도달 가능성과 앱 권한 확인 | Webhook URL 또는 BlueBubbles 서버 상태를 수정하세요. |
|
||||
| macOS에서 전송은 되지만 수신 없음 | Messages 자동화에 대한 macOS 개인정보 보호 권한 확인 | TCC 권한을 다시 부여하고 채널 프로세스를 다시 시작하세요. |
|
||||
| DM 발신자가 차단됨 | `openclaw pairing list imessage` 또는 `openclaw pairing list bluebubbles` | 페어링을 승인하거나 허용 목록을 업데이트하세요. |
|
||||
| 증상 | 가장 빠른 확인 방법 | 수정 방법 |
|
||||
| -------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------- |
|
||||
| 인바운드 이벤트가 없음 | Webhook/서버 도달 가능성과 앱 권한 확인 | Webhook URL 또는 BlueBubbles 서버 상태를 수정하세요. |
|
||||
| macOS에서 보낼 수 있지만 받을 수 없음 | Messages 자동화를 위한 macOS 개인정보 보호 권한 확인 | TCC 권한을 다시 부여하고 채널 프로세스를 재시작하세요. |
|
||||
| DM 발신자가 차단됨 | `openclaw pairing list imessage` 또는 `openclaw pairing list bluebubbles` | 페어링을 승인하거나 허용 목록을 업데이트하세요. |
|
||||
|
||||
전체 문제 해결:
|
||||
|
||||
@ -105,40 +106,40 @@ openclaw channels status --probe
|
||||
|
||||
## Signal
|
||||
|
||||
### Signal 실패 징후
|
||||
### Signal 장애 징후
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ----------------------------- | ------------------------------------------ | ----------------------------------------------------------- |
|
||||
| 데몬에 도달 가능하지만 봇이 조용함 | `openclaw channels status --probe` | `signal-cli` 데몬 URL/계정과 수신 모드를 확인하세요. |
|
||||
| DM 차단됨 | `openclaw pairing list signal` | 발신자를 승인하거나 DM 정책을 조정하세요. |
|
||||
| 그룹 응답이 트리거되지 않음 | 그룹 허용 목록과 멘션 패턴 확인 | 발신자/그룹을 추가하거나 게이팅을 완화하세요. |
|
||||
| 증상 | 가장 빠른 확인 방법 | 수정 방법 |
|
||||
| ------------------------------- | ------------------------------------------ | -------------------------------------------------------- |
|
||||
| 데몬에 도달할 수 있지만 봇이 조용함 | `openclaw channels status --probe` | `signal-cli` 데몬 URL/계정 및 수신 모드를 확인하세요. |
|
||||
| DM이 차단됨 | `openclaw pairing list signal` | 발신자를 승인하거나 DM 정책을 조정하세요. |
|
||||
| 그룹 답장이 트리거되지 않음 | 그룹 허용 목록 및 멘션 패턴 확인 | 발신자/그룹을 추가하거나 게이팅을 완화하세요. |
|
||||
|
||||
전체 문제 해결: [Signal 문제 해결](/ko/channels/signal#troubleshooting)
|
||||
|
||||
## QQ Bot
|
||||
|
||||
### QQ Bot 실패 징후
|
||||
### QQ Bot 장애 징후
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ----------------------------------- | --------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| 봇이 "gone to Mars"라고 응답함 | 설정에서 `appId` 및 `clientSecret` 확인 | 자격 증명을 설정하거나 Gateway를 다시 시작하세요. |
|
||||
| 인바운드 메시지 없음 | `openclaw channels status --probe` | QQ Open Platform에서 자격 증명을 확인하세요. |
|
||||
| 음성이 전사되지 않음 | STT 제공자 설정 확인 | `channels.qqbot.stt` 또는 `tools.media.audio`를 구성하세요. |
|
||||
| 사전 메시지가 도착하지 않음 | QQ 플랫폼 상호작용 요구 사항 확인 | 최근 상호작용이 없으면 QQ가 봇이 시작한 메시지를 차단할 수 있습니다. |
|
||||
| 증상 | 가장 빠른 확인 방법 | 수정 방법 |
|
||||
| ------------------------------- | ------------------------------------------- | --------------------------------------------------------------- |
|
||||
| 봇이 "gone to Mars"라고 답함 | 구성에서 `appId` 및 `clientSecret` 확인 | 자격 증명을 설정하거나 Gateway를 재시작하세요. |
|
||||
| 인바운드 메시지가 없음 | `openclaw channels status --probe` | QQ Open Platform에서 자격 증명을 확인하세요. |
|
||||
| 음성이 전사되지 않음 | STT 제공자 구성 확인 | `channels.qqbot.stt` 또는 `tools.media.audio`를 구성하세요. |
|
||||
| 사전 메시지가 도착하지 않음 | QQ 플랫폼 상호작용 요구 사항 확인 | 최근 상호작용이 없으면 QQ가 봇이 시작한 메시지를 차단할 수 있습니다. |
|
||||
|
||||
전체 문제 해결: [QQ Bot 문제 해결](/ko/channels/qqbot#troubleshooting)
|
||||
|
||||
## Matrix
|
||||
|
||||
### Matrix 실패 징후
|
||||
### Matrix 장애 징후
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ------------------------------------- | --------------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| 로그인되었지만 방 메시지를 무시함 | `openclaw channels status --probe` | `groupPolicy`, 방 허용 목록, 멘션 게이팅을 확인하세요. |
|
||||
| DM이 처리되지 않음 | `openclaw pairing list matrix` | 발신자를 승인하거나 DM 정책을 조정하세요. |
|
||||
| 암호화된 방 실패 | `openclaw matrix verify status` | 디바이스를 다시 확인한 뒤 `openclaw matrix verify backup status`를 확인하세요. |
|
||||
| 백업 복원이 대기 중이거나 손상됨 | `openclaw matrix verify backup status` | `openclaw matrix verify backup restore`를 실행하거나 복구 키로 다시 실행하세요. |
|
||||
| 교차 서명/부트스트랩이 잘못된 것처럼 보임 | `openclaw matrix verify bootstrap` | 비밀 저장소, 교차 서명, 백업 상태를 한 번에 복구하세요. |
|
||||
| 증상 | 가장 빠른 확인 방법 | 수정 방법 |
|
||||
| ----------------------------------- | -------------------------------------- | ------------------------------------------------------------------------- |
|
||||
| 로그인되었지만 방 메시지를 무시함 | `openclaw channels status --probe` | `groupPolicy`, 방 허용 목록, 멘션 게이팅을 확인하세요. |
|
||||
| DM이 처리되지 않음 | `openclaw pairing list matrix` | 발신자를 승인하거나 DM 정책을 조정하세요. |
|
||||
| 암호화된 방이 실패함 | `openclaw matrix verify status` | 장치를 다시 검증한 다음 `openclaw matrix verify backup status`를 확인하세요. |
|
||||
| 백업 복원이 대기 중이거나 손상됨 | `openclaw matrix verify backup status` | `openclaw matrix verify backup restore`를 실행하거나 복구 키로 다시 실행하세요. |
|
||||
| 교차 서명/부트스트랩이 잘못된 것처럼 보임 | `openclaw matrix verify bootstrap` | 비밀 저장소, 교차 서명, 백업 상태를 한 번에 복구하세요. |
|
||||
|
||||
전체 설정 및 구성: [Matrix](/ko/channels/matrix)
|
||||
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
---
|
||||
read_when:
|
||||
- 연결/인증 문제가 있으며 안내에 따라 해결하고 싶은 경우
|
||||
- 업데이트 후 정상 여부를 확인하려는 경우
|
||||
- 연결/인증 문제가 있어 안내에 따라 해결하고 싶은 경우
|
||||
- 업데이트 후 정상 여부를 확인하고 싶습니다
|
||||
summary: '`openclaw doctor`용 CLI 참조(상태 점검 + 안내형 복구)'
|
||||
title: 진단
|
||||
x-i18n:
|
||||
generated_at: "2026-05-05T01:44:24Z"
|
||||
generated_at: "2026-05-05T08:25:38Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 079d7674ae2a259a0430e30e7577ac532135ad5461c57c4b3a6514a007bc9ea5
|
||||
source_hash: d6101008d1cb7e08f9902a8a29785710f325966524b003b87b5c628fe906ab78
|
||||
source_path: cli/doctor.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# `openclaw doctor`
|
||||
|
||||
Gateway 및 채널을 위한 상태 점검 + 빠른 수정.
|
||||
Gateway 및 채널의 상태 확인 + 빠른 수정.
|
||||
|
||||
관련 항목:
|
||||
|
||||
@ -34,45 +34,46 @@ openclaw doctor --generate-gateway-token
|
||||
|
||||
## 옵션
|
||||
|
||||
- `--no-workspace-suggestions`: 워크스페이스 메모리/검색 제안을 비활성화합니다
|
||||
- `--yes`: 묻지 않고 기본값을 수락합니다
|
||||
- `--repair`: 묻지 않고 권장되는 비서비스 수리를 적용합니다. Gateway 서비스 설치 및 재작성에는 여전히 대화형 확인 또는 명시적인 Gateway 명령이 필요합니다
|
||||
- `--fix`: `--repair`의 별칭입니다
|
||||
- `--force`: 필요할 때 사용자 지정 서비스 설정 덮어쓰기를 포함해 공격적인 수리를 적용합니다
|
||||
- `--non-interactive`: 프롬프트 없이 실행합니다. 안전한 마이그레이션과 비서비스 수리만 수행합니다
|
||||
- `--generate-gateway-token`: Gateway 토큰을 생성하고 설정합니다
|
||||
- `--deep`: 추가 Gateway 설치를 찾기 위해 시스템 서비스를 스캔합니다
|
||||
- `--no-workspace-suggestions`: 워크스페이스 메모리/검색 제안 비활성화
|
||||
- `--yes`: 프롬프트 없이 기본값 수락
|
||||
- `--repair`: 프롬프트 없이 권장되는 비서비스 복구 적용. Gateway 서비스 설치 및 다시 쓰기는 여전히 대화형 확인 또는 명시적인 Gateway 명령이 필요
|
||||
- `--fix`: `--repair`의 별칭
|
||||
- `--force`: 필요한 경우 사용자 지정 서비스 구성을 덮어쓰는 것을 포함하여 강력한 복구 적용
|
||||
- `--non-interactive`: 프롬프트 없이 실행. 안전한 마이그레이션 및 비서비스 복구만 수행
|
||||
- `--generate-gateway-token`: Gateway 토큰 생성 및 구성
|
||||
- `--deep`: 추가 Gateway 설치가 있는지 시스템 서비스를 스캔하고 최근 Gateway supervisor 재시작 인계를 보고
|
||||
|
||||
참고:
|
||||
|
||||
- 대화형 프롬프트(예: 키체인/OAuth 수정)는 stdin이 TTY이고 `--non-interactive`가 설정되어 있지 않을 때만 실행됩니다. 헤드리스 실행(cron, Telegram, 터미널 없음)은 프롬프트를 건너뜁니다.
|
||||
- 성능: 비대화형 `doctor` 실행은 헤드리스 상태 점검을 빠르게 유지하기 위해 즉시 Plugin 로드를 건너뜁니다. 대화형 세션은 점검에 Plugin 기여가 필요할 때 여전히 Plugin을 완전히 로드합니다.
|
||||
- `--fix`(`--repair`의 별칭)는 `~/.openclaw/openclaw.json.bak`에 백업을 작성하고 알 수 없는 설정 키를 제거하며, 각 제거 항목을 나열합니다.
|
||||
- `doctor --fix --non-interactive`는 누락되었거나 오래된 Gateway 서비스 정의를 보고하지만, 업데이트 수리 모드 밖에서는 설치하거나 재작성하지 않습니다. 누락된 서비스에는 `openclaw gateway install`을 실행하고, 런처를 의도적으로 교체하려면 `openclaw gateway install --force`를 실행하세요.
|
||||
- 상태 무결성 점검은 이제 세션 디렉터리의 고아 트랜스크립트 파일을 감지합니다. 이를 `.deleted.<timestamp>`로 아카이브하려면 대화형 확인이 필요합니다. `--fix`, `--yes`, 헤드리스 실행은 이를 그대로 둡니다.
|
||||
- Doctor는 또한 `~/.openclaw/cron/jobs.json`(또는 `cron.store`)에서 레거시 Cron 작업 형태를 스캔하고, 스케줄러가 런타임에 자동 정규화해야 하기 전에 제자리에서 재작성할 수 있습니다.
|
||||
- Linux에서 doctor는 사용자의 crontab이 여전히 레거시 `~/.openclaw/bin/ensure-whatsapp.sh`를 실행할 때 경고합니다. 이 스크립트는 더 이상 유지 관리되지 않으며 Cron에 systemd 사용자 버스 환경이 없을 때 잘못된 WhatsApp Gateway 중단 로그를 남길 수 있습니다.
|
||||
- Doctor는 이전 OpenClaw 버전이 만든 레거시 Plugin 의존성 스테이징 상태를 정리합니다. 또한 `plugins.entries`, 설정된 채널, 설정된 provider/검색 설정, 설정된 에이전트 런타임처럼 설정에서 참조하는 다운로드 가능한 Plugin이 누락된 경우 이를 복구합니다. 패키지 업데이트 중에는 패키지 교체가 완료될 때까지 doctor가 패키지 관리자 Plugin 복구를 건너뜁니다. 설정된 Plugin에 여전히 복구가 필요하면 이후 `openclaw doctor --fix`를 다시 실행하세요. 다운로드가 실패하면 doctor는 설치 오류를 보고하고 다음 수리 시도를 위해 설정된 Plugin 항목을 보존합니다.
|
||||
- Doctor는 Plugin 탐색이 정상일 때 `plugins.allow`/`plugins.entries`에서 누락된 Plugin ID와 일치하는 dangling 채널 설정, Heartbeat 대상, 채널 모델 재정의를 제거하여 오래된 Plugin 설정을 복구합니다.
|
||||
- Doctor는 영향을 받은 `plugins.entries.<id>` 항목을 비활성화하고 잘못된 `config` 페이로드를 제거하여 유효하지 않은 Plugin 설정을 격리합니다. Gateway 시작은 이미 해당 잘못된 Plugin만 건너뛰므로 다른 Plugin과 채널은 계속 실행될 수 있습니다.
|
||||
- 다른 supervisor가 Gateway 수명 주기를 소유할 때는 `OPENCLAW_SERVICE_REPAIR_POLICY=external`을 설정하세요. Doctor는 여전히 Gateway/서비스 상태를 보고하고 비서비스 수리를 적용하지만, 서비스 설치/시작/재시작/부트스트랩과 레거시 서비스 정리를 건너뜁니다.
|
||||
- Linux에서 doctor는 비활성 추가 Gateway 유사 systemd 유닛을 무시하며, 수리 중 실행 중인 systemd Gateway 서비스의 명령/엔트리포인트 메타데이터를 재작성하지 않습니다. 활성 런처를 의도적으로 교체하려면 먼저 서비스를 중지하거나 `openclaw gateway install --force`를 사용하세요.
|
||||
- Doctor는 레거시 플랫 Talk 설정(`talk.voiceId`, `talk.modelId` 및 관련 항목)을 `talk.provider` + `talk.providers.<provider>`로 자동 마이그레이션합니다.
|
||||
- `doctor --fix` 반복 실행은 유일한 차이가 객체 키 순서뿐일 때 더 이상 Talk 정규화를 보고/적용하지 않습니다.
|
||||
- Doctor에는 메모리 검색 준비 상태 점검이 포함되며, 임베딩 자격 증명이 누락된 경우 `openclaw configure --section model`을 권장할 수 있습니다.
|
||||
- Doctor는 명령 소유자가 설정되어 있지 않을 때 경고합니다. 명령 소유자는 소유자 전용 명령을 실행하고 위험한 작업을 승인할 수 있는 사람 운영자 계정입니다. DM 페어링은 누군가가 봇과 대화할 수 있게 할 뿐입니다. 첫 소유자 부트스트랩이 생기기 전에 발신자를 승인했다면 `commands.ownerAllowFrom`을 명시적으로 설정하세요.
|
||||
- Doctor는 Codex 모드 에이전트가 설정되어 있고 운영자의 Codex 홈에 개인 Codex CLI 자산이 존재할 때 경고합니다. 로컬 Codex 앱 서버 실행은 에이전트별로 격리된 홈을 사용하므로, 의도적으로 승격해야 하는 자산을 인벤터리하려면 `openclaw migrate codex --dry-run`을 사용하세요.
|
||||
- Doctor는 기본 에이전트에 허용된 Skills가 bin, env var, 설정 또는 OS 요구 사항 누락으로 인해 현재 런타임 환경에서 사용할 수 없을 때 경고합니다. `doctor --fix`는 `skills.entries.<skill>.enabled=false`로 사용할 수 없는 Skills를 비활성화할 수 있습니다. 해당 Skills를 활성 상태로 유지하려면 대신 누락된 요구 사항을 설치/설정하세요.
|
||||
- 샌드박스 모드가 활성화되어 있지만 Docker를 사용할 수 없는 경우, doctor는 해결 방법(`install Docker` 또는 `openclaw config set agents.defaults.sandbox.mode off`)이 포함된 고신호 경고를 보고합니다.
|
||||
- 레거시 샌드박스 레지스트리 파일(`~/.openclaw/sandbox/containers.json` 또는 `~/.openclaw/sandbox/browsers.json`)이 있으면 doctor가 이를 보고합니다. `openclaw doctor --fix`는 유효한 항목을 샤딩된 레지스트리 디렉터리로 마이그레이션하고 유효하지 않은 레거시 파일을 격리합니다.
|
||||
- `gateway.auth.token`/`gateway.auth.password`가 SecretRef로 관리되고 현재 명령 경로에서 사용할 수 없는 경우, doctor는 읽기 전용 경고를 보고하고 일반 텍스트 대체 자격 증명을 쓰지 않습니다.
|
||||
- 수정 경로에서 채널 SecretRef 검사가 실패하면 doctor는 일찍 종료하는 대신 계속 진행하고 경고를 보고합니다.
|
||||
- 상태 디렉터리 마이그레이션 후, 활성화된 기본 Telegram 또는 Discord 계정이 env 대체에 의존하지만 doctor 프로세스에서 `TELEGRAM_BOT_TOKEN` 또는 `DISCORD_BOT_TOKEN`을 사용할 수 없으면 doctor가 경고합니다.
|
||||
- Telegram `allowFrom` 사용자 이름 자동 확인(`doctor --fix`)에는 현재 명령 경로에서 확인 가능한 Telegram 토큰이 필요합니다. 토큰 검사를 사용할 수 없으면 doctor는 경고를 보고하고 해당 실행에서는 자동 확인을 건너뜁니다.
|
||||
- 대화형 프롬프트(예: 키체인/OAuth 수정)는 stdin이 TTY이고 `--non-interactive`가 설정되지 않은 경우에만 실행됩니다. 헤드리스 실행(cron, Telegram, 터미널 없음)은 프롬프트를 건너뜁니다.
|
||||
- 성능: 비대화형 `doctor` 실행은 헤드리스 상태 확인이 빠르게 유지되도록 적극적인 Plugin 로딩을 건너뜁니다. 대화형 세션은 확인에 Plugin 기여가 필요할 때 여전히 Plugin을 완전히 로드합니다.
|
||||
- `--fix`(`--repair`의 별칭)는 백업을 `~/.openclaw/openclaw.json.bak`에 쓰고 알 수 없는 구성 키를 제거하며, 각 제거 항목을 나열합니다.
|
||||
- `doctor --fix --non-interactive`는 누락되었거나 오래된 Gateway 서비스 정의를 보고하지만, 업데이트 복구 모드 외부에서는 이를 설치하거나 다시 쓰지 않습니다. 누락된 서비스에는 `openclaw gateway install`을 실행하고, 런처를 의도적으로 교체하려면 `openclaw gateway install --force`를 실행하세요.
|
||||
- 상태 무결성 검사는 이제 세션 디렉터리의 고아 transcript 파일을 감지합니다. 이를 `.deleted.<timestamp>`로 보관하려면 대화형 확인이 필요합니다. `--fix`, `--yes`, 헤드리스 실행은 그대로 둡니다.
|
||||
- Doctor는 또한 `~/.openclaw/cron/jobs.json`(또는 `cron.store`)에서 레거시 Cron 작업 형태를 스캔하며, 스케줄러가 런타임에 자동 정규화해야 하기 전에 제자리에서 다시 쓸 수 있습니다.
|
||||
- Linux에서 doctor는 사용자의 crontab이 여전히 레거시 `~/.openclaw/bin/ensure-whatsapp.sh`를 실행할 때 경고합니다. 이 스크립트는 더 이상 유지 관리되지 않으며, Cron에 systemd 사용자 버스 환경이 없을 때 잘못된 WhatsApp Gateway 중단을 기록할 수 있습니다.
|
||||
- WhatsApp이 활성화된 경우, doctor는 로컬 `openclaw-tui` 클라이언트가 계속 실행 중인 상태에서 성능 저하된 Gateway 이벤트 루프를 확인합니다. `doctor --fix`는 검증된 로컬 TUI 클라이언트만 중지하여 WhatsApp 응답이 오래된 TUI 새로 고침 루프 뒤에 대기하지 않도록 합니다.
|
||||
- Doctor는 이전 OpenClaw 버전에서 생성한 레거시 Plugin 의존성 스테이징 상태를 정리합니다. 또한 `plugins.entries`, 구성된 채널, 구성된 provider/search 설정, 구성된 agent runtime처럼 구성에서 참조되는 누락된 다운로드 가능 Plugin을 복구합니다. 패키지 업데이트 중에는 패키지 교체가 완료될 때까지 doctor가 패키지 관리자 Plugin 복구를 건너뜁니다. 구성된 Plugin에 여전히 복구가 필요하면 이후에 `openclaw doctor --fix`를 다시 실행하세요. 다운로드가 실패하면 doctor는 설치 오류를 보고하고 다음 복구 시도를 위해 구성된 Plugin 항목을 보존합니다.
|
||||
- Doctor는 Plugin 발견이 정상일 때 `plugins.allow`/`plugins.entries`에서 누락된 Plugin id를 제거하고, 일치하는 끊어진 채널 구성, Heartbeat 대상, 채널 모델 재정의를 제거하여 오래된 Plugin 구성을 복구합니다.
|
||||
- Doctor는 영향을 받은 `plugins.entries.<id>` 항목을 비활성화하고 잘못된 `config` 페이로드를 제거하여 유효하지 않은 Plugin 구성을 격리합니다. Gateway 시작은 이미 해당 잘못된 Plugin만 건너뛰므로 다른 Plugin과 채널은 계속 실행될 수 있습니다.
|
||||
- 다른 supervisor가 Gateway 수명 주기를 소유하는 경우 `OPENCLAW_SERVICE_REPAIR_POLICY=external`을 설정하세요. Doctor는 여전히 Gateway/서비스 상태를 보고하고 비서비스 복구를 적용하지만, 서비스 설치/시작/재시작/bootstrap 및 레거시 서비스 정리는 건너뜁니다.
|
||||
- Linux에서 doctor는 비활성 추가 Gateway 유사 systemd unit을 무시하며, 복구 중 실행 중인 systemd Gateway 서비스의 command/entrypoint 메타데이터를 다시 쓰지 않습니다. 활성 런처를 의도적으로 교체하려면 먼저 서비스를 중지하거나 `openclaw gateway install --force`를 사용하세요.
|
||||
- Doctor는 레거시 flat Talk 구성(`talk.voiceId`, `talk.modelId` 및 관련 항목)을 `talk.provider` + `talk.providers.<provider>`로 자동 마이그레이션합니다.
|
||||
- `doctor --fix` 반복 실행은 유일한 차이가 객체 키 순서인 경우 더 이상 Talk 정규화를 보고/적용하지 않습니다.
|
||||
- Doctor에는 메모리 검색 준비 상태 확인이 포함되며, embedding credentials가 누락된 경우 `openclaw configure --section model`을 권장할 수 있습니다.
|
||||
- Doctor는 명령 소유자가 구성되지 않은 경우 경고합니다. 명령 소유자는 소유자 전용 명령을 실행하고 위험한 작업을 승인할 수 있는 사람 운영자 계정입니다. DM 페어링은 누군가가 봇과 대화할 수 있게만 합니다. 첫 번째 소유자 bootstrap이 존재하기 전에 sender를 승인했다면 `commands.ownerAllowFrom`을 명시적으로 설정하세요.
|
||||
- Doctor는 Codex 모드 agent가 구성되어 있고 운영자의 Codex home에 개인 Codex CLI asset이 있을 때 경고합니다. 로컬 Codex app-server 실행은 격리된 agent별 home을 사용하므로, 의도적으로 승격해야 하는 asset을 인벤토리화하려면 `openclaw migrate codex --dry-run`을 사용하세요.
|
||||
- Doctor는 기본 agent에 허용된 Skills가 bin, env var, 구성 또는 OS 요구 사항 누락으로 인해 현재 런타임 환경에서 사용할 수 없을 때 경고합니다. `doctor --fix`는 사용할 수 없는 Skills를 `skills.entries.<skill>.enabled=false`로 비활성화할 수 있습니다. Skill을 활성 상태로 유지하려면 대신 누락된 요구 사항을 설치/구성하세요.
|
||||
- sandbox 모드가 활성화되어 있지만 Docker를 사용할 수 없는 경우, doctor는 해결 방법(`install Docker` 또는 `openclaw config set agents.defaults.sandbox.mode off`)과 함께 높은 신호의 경고를 보고합니다.
|
||||
- 레거시 sandbox registry 파일(`~/.openclaw/sandbox/containers.json` 또는 `~/.openclaw/sandbox/browsers.json`)이 있으면 doctor가 이를 보고합니다. `openclaw doctor --fix`는 유효한 항목을 sharded registry 디렉터리로 마이그레이션하고 유효하지 않은 레거시 파일을 격리합니다.
|
||||
- `gateway.auth.token`/`gateway.auth.password`가 SecretRef로 관리되고 현재 명령 경로에서 사용할 수 없는 경우, doctor는 읽기 전용 경고를 보고하며 plaintext fallback credentials를 쓰지 않습니다.
|
||||
- 수정 경로에서 채널 SecretRef 검사가 실패하면, doctor는 조기 종료하지 않고 계속 진행하며 경고를 보고합니다.
|
||||
- 상태 디렉터리 마이그레이션 후, 활성화된 기본 Telegram 또는 Discord 계정이 env fallback에 의존하고 `TELEGRAM_BOT_TOKEN` 또는 `DISCORD_BOT_TOKEN`을 doctor 프로세스에서 사용할 수 없는 경우 doctor가 경고합니다.
|
||||
- Telegram `allowFrom` 사용자 이름 자동 해결(`doctor --fix`)에는 현재 명령 경로에서 해결 가능한 Telegram 토큰이 필요합니다. 토큰 검사를 사용할 수 없으면 doctor는 경고를 보고하고 해당 실행의 자동 해결을 건너뜁니다.
|
||||
|
||||
## macOS: `launchctl` env 재정의
|
||||
## macOS: `launchctl` 환경 재정의
|
||||
|
||||
이전에 `launchctl setenv OPENCLAW_GATEWAY_TOKEN ...`(또는 `...PASSWORD`)를 실행했다면, 그 값이 설정 파일을 재정의하여 지속적인 “unauthorized” 오류를 일으킬 수 있습니다.
|
||||
이전에 `launchctl setenv OPENCLAW_GATEWAY_TOKEN ...`(또는 `...PASSWORD`)을 실행했다면, 해당 값이 구성 파일을 재정의하여 지속적인 “unauthorized” 오류를 일으킬 수 있습니다.
|
||||
|
||||
```bash
|
||||
launchctl getenv OPENCLAW_GATEWAY_TOKEN
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
---
|
||||
read_when:
|
||||
- CLI에서 Gateway 실행하기(개발 환경 또는 서버)
|
||||
- Gateway 인증, 바인드 모드 및 연결 디버깅
|
||||
- Gateway 인증, 바인드 모드 및 연결성 디버깅
|
||||
- Bonjour를 통한 Gateway 검색(로컬 + 광역 DNS-SD)
|
||||
sidebarTitle: Gateway
|
||||
summary: OpenClaw Gateway CLI (`openclaw gateway`) — Gateway 실행, 조회 및 검색
|
||||
summary: OpenClaw Gateway CLI (`openclaw gateway`) — 게이트웨이를 실행, 조회 및 검색
|
||||
title: Gateway
|
||||
x-i18n:
|
||||
generated_at: "2026-05-05T01:44:33Z"
|
||||
generated_at: "2026-05-05T08:25:41Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 521558189b150b2faa22f95ec32419ac9e02c5f47c72b9095f40d1432840c038
|
||||
source_hash: 89f798724971151cdd297fcdbbc1fe79dedc19f57521f2ad2c1fff0f9acf9b24
|
||||
source_path: cli/gateway.md
|
||||
workflow: 16
|
||||
---
|
||||
@ -18,13 +18,13 @@ x-i18n:
|
||||
Gateway는 OpenClaw의 WebSocket 서버입니다(채널, Node, 세션, 훅). 이 페이지의 하위 명령은 `openclaw gateway …` 아래에 있습니다.
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Bonjour discovery" href="/ko/gateway/bonjour">
|
||||
<Card title="Bonjour 검색" href="/ko/gateway/bonjour">
|
||||
로컬 mDNS + 광역 DNS-SD 설정.
|
||||
</Card>
|
||||
<Card title="Discovery overview" href="/ko/gateway/discovery">
|
||||
<Card title="검색 개요" href="/ko/gateway/discovery">
|
||||
OpenClaw가 Gateway를 알리고 찾는 방식.
|
||||
</Card>
|
||||
<Card title="Configuration" href="/ko/gateway/configuration">
|
||||
<Card title="구성" href="/ko/gateway/configuration">
|
||||
최상위 Gateway 구성 키.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@ -44,13 +44,13 @@ openclaw gateway run
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Startup behavior">
|
||||
<Accordion title="시작 동작">
|
||||
- 기본적으로 Gateway는 `~/.openclaw/openclaw.json`에 `gateway.mode=local`이 설정되어 있지 않으면 시작을 거부합니다. 임시/개발 실행에는 `--allow-unconfigured`를 사용하세요.
|
||||
- `openclaw onboard --mode local` 및 `openclaw setup`은 `gateway.mode=local`을 작성해야 합니다. 파일은 있지만 `gateway.mode`가 누락된 경우, 로컬 모드를 암묵적으로 가정하지 말고 손상되었거나 덮어써진 구성으로 취급하여 복구하세요.
|
||||
- 파일은 있지만 `gateway.mode`가 누락된 경우, Gateway는 이를 의심스러운 구성 손상으로 간주하고 사용자를 대신해 "guess local"하지 않습니다.
|
||||
- 인증 없이 루프백을 넘어 바인딩하는 것은 차단됩니다(안전 가드레일).
|
||||
- `SIGUSR1`은 승인된 경우 프로세스 내부 재시작을 트리거합니다(`commands.restart`는 기본적으로 활성화됨. 수동 재시작을 차단하려면 `commands.restart: false`를 설정하세요. Gateway 도구/구성 적용/업데이트는 계속 허용됩니다).
|
||||
- `SIGINT`/`SIGTERM` 핸들러는 Gateway 프로세스를 중지하지만, 사용자 지정 터미널 상태는 복원하지 않습니다. TUI 또는 raw-mode 입력으로 CLI를 감싸는 경우 종료 전에 터미널을 복원하세요.
|
||||
- `openclaw onboard --mode local` 및 `openclaw setup`은 `gateway.mode=local`을 작성해야 합니다. 파일은 있지만 `gateway.mode`가 없으면 이를 암묵적으로 로컬 모드로 가정하지 말고, 손상되었거나 덮어써진 구성으로 보고 복구하세요.
|
||||
- 파일은 있지만 `gateway.mode`가 없으면 Gateway는 이를 의심스러운 구성 손상으로 간주하고 사용자를 대신해 "guess local"하지 않습니다.
|
||||
- 인증 없이 loopback을 넘어 바인딩하는 것은 차단됩니다(안전 가드레일).
|
||||
- `SIGUSR1`은 승인된 경우 프로세스 내부 재시작을 트리거합니다(`commands.restart`는 기본적으로 활성화되어 있습니다. 수동 재시작을 차단하려면 `commands.restart: false`로 설정하세요. Gateway 도구/구성 적용/업데이트는 계속 허용됩니다).
|
||||
- `SIGINT`/`SIGTERM` 핸들러는 Gateway 프로세스를 중지하지만, 사용자 지정 터미널 상태를 복원하지는 않습니다. CLI를 TUI 또는 raw-mode 입력으로 감싸는 경우 종료 전에 터미널을 복원하세요.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@ -79,28 +79,28 @@ openclaw gateway run
|
||||
Tailscale을 통해 Gateway를 노출합니다.
|
||||
</ParamField>
|
||||
<ParamField path="--tailscale-reset-on-exit" type="boolean">
|
||||
종료 시 Tailscale serve/funnel 구성을 재설정합니다.
|
||||
종료 시 Tailscale serve/funnel 구성을 초기화합니다.
|
||||
</ParamField>
|
||||
<ParamField path="--allow-unconfigured" type="boolean">
|
||||
구성에 `gateway.mode=local`이 없어도 Gateway 시작을 허용합니다. 임시/개발 부트스트랩 전용으로 시작 가드를 우회하며, 구성 파일을 작성하거나 복구하지 않습니다.
|
||||
구성에 `gateway.mode=local`이 없어도 Gateway 시작을 허용합니다. 임시/개발 부트스트랩에만 시작 가드를 우회하며, 구성 파일을 작성하거나 복구하지는 않습니다.
|
||||
</ParamField>
|
||||
<ParamField path="--dev" type="boolean">
|
||||
누락된 경우 개발 구성 + 워크스페이스를 생성합니다(BOOTSTRAP.md 건너뜀).
|
||||
</ParamField>
|
||||
<ParamField path="--reset" type="boolean">
|
||||
개발 구성 + 자격 증명 + 세션 + 워크스페이스를 재설정합니다(`--dev` 필요).
|
||||
개발 구성 + 자격 증명 + 세션 + 워크스페이스를 초기화합니다(`--dev` 필요).
|
||||
</ParamField>
|
||||
<ParamField path="--force" type="boolean">
|
||||
시작 전에 선택한 포트의 기존 리스너를 종료합니다.
|
||||
시작하기 전에 선택한 포트의 기존 리스너를 모두 종료합니다.
|
||||
</ParamField>
|
||||
<ParamField path="--verbose" type="boolean">
|
||||
자세한 로그.
|
||||
</ParamField>
|
||||
<ParamField path="--cli-backend-logs" type="boolean">
|
||||
콘솔에 CLI 백엔드 로그만 표시합니다(stdout/stderr 활성화 포함).
|
||||
콘솔에 CLI 백엔드 로그만 표시합니다(stdout/stderr도 활성화).
|
||||
</ParamField>
|
||||
<ParamField path="--ws-log <auto|full|compact>" type="string" default="auto">
|
||||
WebSocket 로그 스타일.
|
||||
Websocket 로그 스타일.
|
||||
</ParamField>
|
||||
<ParamField path="--compact" type="boolean">
|
||||
`--ws-log compact`의 별칭.
|
||||
@ -120,7 +120,7 @@ openclaw gateway restart --safe
|
||||
openclaw gateway restart --force
|
||||
```
|
||||
|
||||
`openclaw gateway restart --safe`는 실행 중인 Gateway에 재시작 전에 활성 OpenClaw 작업을 사전 점검하도록 요청합니다. 대기 중인 작업, 답장 전달, 임베디드 실행 또는 작업 실행이 활성 상태이면 Gateway는 차단 요인을 보고하고, 중복 safe restart 요청을 병합하며, 활성 작업이 비워지면 재시작합니다. 일반 `restart`는 호환성을 위해 기존 서비스 관리자 동작을 유지합니다. 즉시 재정의 경로를 명시적으로 원하는 경우에만 `--force`를 사용하세요.
|
||||
`openclaw gateway restart --safe`는 실행 중인 Gateway에 재시작 전에 활성 OpenClaw 작업을 사전 점검하도록 요청합니다. 대기 중인 작업, 답장 전달, 임베디드 실행 또는 작업 실행이 활성 상태이면 Gateway는 차단 요인을 보고하고, 중복된 안전 재시작 요청을 병합하며, 활성 작업이 모두 빠진 뒤 재시작합니다. 일반 `restart`는 호환성을 위해 기존 서비스 관리자 동작을 유지합니다. 즉시 재정의 경로를 명시적으로 원할 때만 `--force`를 사용하세요.
|
||||
|
||||
<Warning>
|
||||
인라인 `--password`는 로컬 프로세스 목록에 노출될 수 있습니다. `--password-file`, env 또는 SecretRef 기반 `gateway.auth.password`를 선호하세요.
|
||||
@ -128,26 +128,26 @@ openclaw gateway restart --force
|
||||
|
||||
### 시작 프로파일링
|
||||
|
||||
- Gateway 시작 중 단계별 타이밍을 기록하려면 `OPENCLAW_GATEWAY_STARTUP_TRACE=1`을 설정하세요. 여기에는 단계별 `eventLoopMax` 지연과 설치된 인덱스, 매니페스트 레지스트리, 시작 계획, 소유자 맵 작업에 대한 Plugin 조회 테이블 타이밍이 포함됩니다.
|
||||
- 외부 QA 하니스용 best-effort JSONL 시작 진단 타임라인을 작성하려면 `OPENCLAW_DIAGNOSTICS_TIMELINE_PATH=<path>`와 함께 `OPENCLAW_DIAGNOSTICS=timeline`을 설정하세요. 구성에서 `diagnostics.flags: ["timeline"]`으로 플래그를 활성화할 수도 있으며, 경로는 여전히 env로 제공됩니다. 이벤트 루프 샘플을 포함하려면 `OPENCLAW_DIAGNOSTICS_EVENT_LOOP=1`을 추가하세요.
|
||||
- Gateway 시작을 벤치마크하려면 `pnpm test:startup:gateway -- --runs 5 --warmup 1`을 실행하세요. 벤치마크는 첫 프로세스 출력, `/healthz`, `/readyz`, 시작 트레이스 타이밍, 이벤트 루프 지연, Plugin 조회 테이블 타이밍 세부 정보를 기록합니다.
|
||||
- Gateway 시작 중 단계별 타이밍을 기록하려면 `OPENCLAW_GATEWAY_STARTUP_TRACE=1`을 설정하세요. 여기에는 단계별 `eventLoopMax` 지연 및 설치된 인덱스, 매니페스트 레지스트리, 시작 계획, 소유자 맵 작업에 대한 Plugin 조회 테이블 타이밍이 포함됩니다.
|
||||
- 외부 QA 하네스를 위한 최선형 JSONL 시작 진단 타임라인을 작성하려면 `OPENCLAW_DIAGNOSTICS_TIMELINE_PATH=<path>`와 함께 `OPENCLAW_DIAGNOSTICS=timeline`을 설정하세요. 구성에서 `diagnostics.flags: ["timeline"]`로 플래그를 활성화할 수도 있습니다. 경로는 여전히 env로 제공됩니다. 이벤트 루프 샘플을 포함하려면 `OPENCLAW_DIAGNOSTICS_EVENT_LOOP=1`을 추가하세요.
|
||||
- Gateway 시작을 벤치마크하려면 `pnpm test:startup:gateway -- --runs 5 --warmup 1`을 실행하세요. 벤치마크는 첫 프로세스 출력, `/healthz`, `/readyz`, 시작 추적 타이밍, 이벤트 루프 지연, Plugin 조회 테이블 타이밍 세부 정보를 기록합니다.
|
||||
|
||||
## 실행 중인 Gateway 쿼리
|
||||
|
||||
모든 쿼리 명령은 WebSocket RPC를 사용합니다.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Output modes">
|
||||
- 기본값: 사람이 읽기 쉬운 형식(TTY에서 색상 적용).
|
||||
<Tab title="출력 모드">
|
||||
- 기본값: 사람이 읽을 수 있는 형식(TTY에서 색상 표시).
|
||||
- `--json`: 기계가 읽을 수 있는 JSON(스타일/스피너 없음).
|
||||
- `--no-color`(또는 `NO_COLOR=1`): 사람이 읽는 레이아웃은 유지하면서 ANSI를 비활성화합니다.
|
||||
- `--no-color`(또는 `NO_COLOR=1`): 사람용 레이아웃은 유지하면서 ANSI를 비활성화합니다.
|
||||
|
||||
</Tab>
|
||||
<Tab title="Shared options">
|
||||
<Tab title="공유 옵션">
|
||||
- `--url <url>`: Gateway WebSocket URL.
|
||||
- `--token <token>`: Gateway 토큰.
|
||||
- `--password <password>`: Gateway 비밀번호.
|
||||
- `--timeout <ms>`: 제한 시간/예산(명령마다 다름).
|
||||
- `--timeout <ms>`: 타임아웃/예산(명령마다 다름).
|
||||
- `--expect-final`: "final" 응답을 기다립니다(에이전트 호출).
|
||||
|
||||
</Tab>
|
||||
@ -163,7 +163,7 @@ openclaw gateway restart --force
|
||||
openclaw gateway health --url ws://127.0.0.1:18789
|
||||
```
|
||||
|
||||
HTTP `/healthz` 엔드포인트는 활성 상태 프로브입니다. 서버가 HTTP에 응답할 수 있으면 반환됩니다. HTTP `/readyz` 엔드포인트는 더 엄격하며, 시작 Plugin 사이드카, 채널 또는 구성된 훅이 아직 안정화 중이면 빨간색 상태를 유지합니다. 로컬 또는 인증된 상세 준비 상태 응답에는 이벤트 루프 지연, 이벤트 루프 사용률, CPU 코어 비율, `degraded` 플래그가 포함된 `eventLoop` 진단 블록이 포함됩니다.
|
||||
HTTP `/healthz` 엔드포인트는 라이브니스 프로브입니다. 서버가 HTTP에 응답할 수 있으면 반환됩니다. HTTP `/readyz` 엔드포인트는 더 엄격하며, 시작 Plugin 사이드카, 채널 또는 구성된 훅이 아직 안정화 중이면 빨간 상태를 유지합니다. 로컬 또는 인증된 상세 준비 상태 응답에는 이벤트 루프 지연, 이벤트 루프 사용률, CPU 코어 비율, `degraded` 플래그가 포함된 `eventLoop` 진단 블록이 포함됩니다.
|
||||
|
||||
### `gateway usage-cost`
|
||||
|
||||
@ -181,7 +181,7 @@ openclaw gateway usage-cost --json
|
||||
|
||||
### `gateway stability`
|
||||
|
||||
실행 중인 Gateway에서 최근 진단 안정성 기록기를 가져옵니다.
|
||||
실행 중인 Gateway에서 최근 진단 안정성 레코더를 가져옵니다.
|
||||
|
||||
```bash
|
||||
openclaw gateway stability
|
||||
@ -195,13 +195,13 @@ openclaw gateway stability --json
|
||||
포함할 최근 이벤트의 최대 수(최대 `1000`).
|
||||
</ParamField>
|
||||
<ParamField path="--type <type>" type="string">
|
||||
`payload.large` 또는 `diagnostic.memory.pressure`와 같은 진단 이벤트 유형으로 필터링합니다.
|
||||
`payload.large` 또는 `diagnostic.memory.pressure` 같은 진단 이벤트 유형으로 필터링합니다.
|
||||
</ParamField>
|
||||
<ParamField path="--since-seq <seq>" type="number">
|
||||
진단 시퀀스 번호 이후의 이벤트만 포함합니다.
|
||||
</ParamField>
|
||||
<ParamField path="--bundle [path]" type="string">
|
||||
실행 중인 Gateway를 호출하는 대신 지속된 안정성 번들을 읽습니다. 상태 디렉터리 아래의 최신 번들은 `--bundle latest`(또는 단순히 `--bundle`)를 사용하거나, 번들 JSON 경로를 직접 전달하세요.
|
||||
실행 중인 Gateway를 호출하는 대신 유지된 안정성 번들을 읽습니다. 상태 디렉터리 아래의 최신 번들에는 `--bundle latest`(또는 단순히 `--bundle`)를 사용하거나, 번들 JSON 경로를 직접 전달하세요.
|
||||
</ParamField>
|
||||
<ParamField path="--export" type="boolean">
|
||||
안정성 세부 정보를 출력하는 대신 공유 가능한 지원 진단 zip을 작성합니다.
|
||||
@ -211,16 +211,16 @@ openclaw gateway stability --json
|
||||
</ParamField>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Privacy and bundle behavior">
|
||||
- 기록은 운영 메타데이터를 유지합니다: 이벤트 이름, 개수, 바이트 크기, 메모리 수치, 큐/세션 상태, 채널/Plugin 이름, 수정된 세션 요약. 채팅 텍스트, Webhook 본문, 도구 출력, 원시 요청 또는 응답 본문, 토큰, 쿠키, 비밀 값, 호스트 이름, 원시 세션 ID는 유지하지 않습니다. 기록기를 완전히 비활성화하려면 `diagnostics.enabled: false`를 설정하세요.
|
||||
- 치명적인 Gateway 종료, 종료 시간 초과, 재시작 시작 실패 시, 기록기에 이벤트가 있으면 OpenClaw는 동일한 진단 스냅샷을 `~/.openclaw/logs/stability/openclaw-stability-*.json`에 작성합니다. 최신 번들은 `openclaw gateway stability --bundle latest`로 검사하세요. `--limit`, `--type`, `--since-seq`도 번들 출력에 적용됩니다.
|
||||
<Accordion title="개인정보 보호 및 번들 동작">
|
||||
- 기록은 운영 메타데이터를 유지합니다. 이벤트 이름, 수, 바이트 크기, 메모리 측정값, 큐/세션 상태, 채널/Plugin 이름, 수정 처리된 세션 요약이 포함됩니다. 채팅 텍스트, Webhook 본문, 도구 출력, 원시 요청 또는 응답 본문, 토큰, 쿠키, 비밀 값, 호스트 이름 또는 원시 세션 ID는 유지하지 않습니다. 레코더를 완전히 비활성화하려면 `diagnostics.enabled: false`를 설정하세요.
|
||||
- 치명적인 Gateway 종료, 종료 타임아웃, 재시작 시작 실패 시 레코더에 이벤트가 있으면 OpenClaw는 동일한 진단 스냅샷을 `~/.openclaw/logs/stability/openclaw-stability-*.json`에 작성합니다. 최신 번들은 `openclaw gateway stability --bundle latest`로 검사하세요. `--limit`, `--type`, `--since-seq`도 번들 출력에 적용됩니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### `gateway diagnostics export`
|
||||
|
||||
버그 보고서에 첨부하도록 설계된 로컬 진단 zip을 작성합니다. 개인정보 보호 모델 및 번들 내용은 [Diagnostics Export](/ko/gateway/diagnostics)를 참조하세요.
|
||||
버그 보고서에 첨부하도록 설계된 로컬 진단 zip을 작성합니다. 개인정보 보호 모델 및 번들 내용은 [진단 내보내기](/ko/gateway/diagnostics)를 참조하세요.
|
||||
|
||||
```bash
|
||||
openclaw gateway diagnostics export
|
||||
@ -232,7 +232,7 @@ openclaw gateway diagnostics export --json
|
||||
출력 zip 경로. 기본값은 상태 디렉터리 아래의 지원 내보내기입니다.
|
||||
</ParamField>
|
||||
<ParamField path="--log-lines <count>" type="number" default="5000">
|
||||
포함할 정리된 로그 줄의 최대 수.
|
||||
포함할 최대 정리된 로그 줄 수.
|
||||
</ParamField>
|
||||
<ParamField path="--log-bytes <bytes>" type="number" default="1000000">
|
||||
검사할 최대 로그 바이트 수.
|
||||
@ -247,22 +247,22 @@ openclaw gateway diagnostics export --json
|
||||
상태 스냅샷용 Gateway 비밀번호.
|
||||
</ParamField>
|
||||
<ParamField path="--timeout <ms>" type="number" default="3000">
|
||||
상태/헬스 스냅샷 제한 시간.
|
||||
상태/상태 점검 스냅샷 타임아웃.
|
||||
</ParamField>
|
||||
<ParamField path="--no-stability-bundle" type="boolean">
|
||||
지속된 안정성 번들 조회를 건너뜁니다.
|
||||
유지된 안정성 번들 조회를 건너뜁니다.
|
||||
</ParamField>
|
||||
<ParamField path="--json" type="boolean">
|
||||
작성된 경로, 크기, 매니페스트를 JSON으로 출력합니다.
|
||||
</ParamField>
|
||||
|
||||
내보내기에는 매니페스트, Markdown 요약, 구성 형태, 정리된 구성 세부 정보, 정리된 로그 요약, 정리된 Gateway 상태/헬스 스냅샷, 그리고 존재하는 경우 최신 안정성 번들이 포함됩니다.
|
||||
내보내기에는 매니페스트, Markdown 요약, 구성 형태, 정리된 구성 세부 정보, 정리된 로그 요약, 정리된 Gateway 상태/상태 점검 스냅샷, 그리고 존재하는 경우 최신 안정성 번들이 포함됩니다.
|
||||
|
||||
이는 공유를 목적으로 합니다. 안전한 OpenClaw 로그 필드, 하위 시스템 이름, 상태 코드, 지속 시간, 구성된 모드, 포트, Plugin ID, 제공자 ID, 비밀이 아닌 기능 설정, 수정된 운영 로그 메시지처럼 디버깅에 도움이 되는 운영 세부 정보를 유지합니다. 채팅 텍스트, Webhook 본문, 도구 출력, 자격 증명, 쿠키, 계정/메시지 식별자, 프롬프트/지침 텍스트, 호스트 이름, 비밀 값은 생략하거나 수정합니다. LogTape 스타일 메시지가 사용자/채팅/도구 페이로드 텍스트처럼 보이면, 내보내기는 메시지가 생략되었다는 사실과 해당 바이트 수만 유지합니다.
|
||||
이는 공유를 목적으로 합니다. 디버깅에 도움이 되는 운영 세부 정보를 유지합니다. 예를 들어 안전한 OpenClaw 로그 필드, 하위 시스템 이름, 상태 코드, 기간, 구성된 모드, 포트, Plugin ID, 제공자 ID, 비밀이 아닌 기능 설정, 수정 처리된 운영 로그 메시지가 포함됩니다. 채팅 텍스트, Webhook 본문, 도구 출력, 자격 증명, 쿠키, 계정/메시지 식별자, 프롬프트/지침 텍스트, 호스트 이름, 비밀 값은 생략하거나 수정 처리합니다. LogTape 스타일 메시지가 사용자/채팅/도구 페이로드 텍스트처럼 보이면, 내보내기는 메시지가 생략되었다는 사실과 해당 바이트 수만 유지합니다.
|
||||
|
||||
### `gateway status`
|
||||
|
||||
`gateway status`는 Gateway 서비스(launchd/systemd/schtasks)와 연결/auth 기능에 대한 선택적 프로브를 표시합니다.
|
||||
`gateway status`는 Gateway 서비스(launchd/systemd/schtasks)와 연결성/인증 기능의 선택적 프로브를 표시합니다.
|
||||
|
||||
```bash
|
||||
openclaw gateway status
|
||||
@ -271,44 +271,45 @@ openclaw gateway status --require-rpc
|
||||
```
|
||||
|
||||
<ParamField path="--url <url>" type="string">
|
||||
명시적인 프로브 대상을 추가합니다. 구성된 원격 대상과 localhost도 계속 프로브합니다.
|
||||
명시적인 프로브 대상을 추가합니다. 구성된 원격 + localhost는 계속 프로브됩니다.
|
||||
</ParamField>
|
||||
<ParamField path="--token <token>" type="string">
|
||||
프로브용 토큰 인증입니다.
|
||||
프로브의 토큰 인증입니다.
|
||||
</ParamField>
|
||||
<ParamField path="--password <password>" type="string">
|
||||
프로브용 비밀번호 인증입니다.
|
||||
프로브의 비밀번호 인증입니다.
|
||||
</ParamField>
|
||||
<ParamField path="--timeout <ms>" type="number" default="10000">
|
||||
프로브 제한 시간입니다.
|
||||
</ParamField>
|
||||
<ParamField path="--no-probe" type="boolean">
|
||||
연결 프로브를 건너뜁니다(서비스 전용 보기).
|
||||
연결성 프로브를 건너뜁니다(서비스 전용 보기).
|
||||
</ParamField>
|
||||
<ParamField path="--deep" type="boolean">
|
||||
시스템 수준 서비스도 스캔합니다.
|
||||
</ParamField>
|
||||
<ParamField path="--require-rpc" type="boolean">
|
||||
기본 연결 프로브를 읽기 프로브로 업그레이드하고 해당 읽기 프로브가 실패하면 0이 아닌 코드로 종료합니다. `--no-probe`와 함께 사용할 수 없습니다.
|
||||
기본 연결성 프로브를 읽기 프로브로 업그레이드하고 해당 읽기 프로브가 실패하면 0이 아닌 코드로 종료합니다. `--no-probe`와 함께 사용할 수 없습니다.
|
||||
</ParamField>
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="상태 의미">
|
||||
- `gateway status`는 로컬 CLI 구성이 없거나 유효하지 않아도 진단용으로 계속 사용할 수 있습니다.
|
||||
- 기본 `gateway status`는 서비스 상태, WebSocket 연결, 핸드셰이크 시점에 보이는 인증 기능을 검증합니다. 읽기/쓰기/관리 작업은 검증하지 않습니다.
|
||||
- 진단 프로브는 최초 기기 인증에 대해 변경을 일으키지 않습니다. 기존 캐시된 기기 토큰이 있으면 재사용하지만, 상태 확인만을 위해 새 CLI 기기 ID나 읽기 전용 기기 페어링 레코드를 만들지는 않습니다.
|
||||
- `gateway status`는 가능하면 프로브 인증을 위해 구성된 인증 SecretRefs를 확인합니다.
|
||||
- 이 명령 경로에서 필수 인증 SecretRef를 확인할 수 없으면, 프로브 연결/인증이 실패할 때 `gateway status --json`이 `rpc.authWarning`을 보고합니다. `--token`/`--password`를 명시적으로 전달하거나 먼저 시크릿 소스를 확인하세요.
|
||||
- 프로브가 성공하면, 잘못된 양성 결과를 피하기 위해 확인되지 않은 auth-ref 경고가 억제됩니다.
|
||||
- 수신 중인 서비스만으로 충분하지 않고 읽기 범위 RPC 호출도 정상이어야 하는 스크립트와 자동화에서는 `--require-rpc`를 사용하세요.
|
||||
- `--deep`은 추가 launchd/systemd/schtasks 설치를 최선 방식으로 스캔합니다. 여러 Gateway 유사 서비스가 감지되면, 사람이 읽는 출력은 정리 힌트를 표시하고 대부분의 설정은 머신당 하나의 Gateway만 실행해야 한다고 경고합니다.
|
||||
- 사람이 읽는 출력에는 프로필 또는 상태 디렉터리 불일치를 진단하는 데 도움이 되도록 확인된 파일 로그 경로와 CLI-대-서비스 구성 경로/유효성 스냅샷이 포함됩니다.
|
||||
- 기본 `gateway status`는 서비스 상태, WebSocket 연결, 그리고 핸드셰이크 시점에 보이는 인증 기능을 증명합니다. 읽기/쓰기/관리 작업은 증명하지 않습니다.
|
||||
- 진단 프로브는 최초 장치 인증에 대해 비변경 작업입니다. 기존 캐시된 장치 토큰이 있으면 재사용하지만, 상태를 확인하기 위해 새 CLI 장치 ID나 읽기 전용 장치 페어링 레코드를 만들지는 않습니다.
|
||||
- `gateway status`는 가능하면 프로브 인증을 위해 구성된 인증 SecretRefs를 해석합니다.
|
||||
- 이 명령 경로에서 필수 인증 SecretRef가 해석되지 않으면, 프로브 연결성/인증이 실패할 때 `gateway status --json`이 `rpc.authWarning`을 보고합니다. `--token`/`--password`를 명시적으로 전달하거나 먼저 시크릿 소스를 해석하세요.
|
||||
- 프로브가 성공하면 거짓 양성을 피하기 위해 해석되지 않은 auth-ref 경고가 억제됩니다.
|
||||
- 수신 대기 중인 서비스만으로는 충분하지 않고 읽기 범위 RPC 호출도 정상이어야 하는 스크립트와 자동화에서는 `--require-rpc`를 사용하세요.
|
||||
- `--deep`은 추가 launchd/systemd/schtasks 설치에 대한 최선의 스캔을 추가합니다. 여러 Gateway 유사 서비스가 감지되면 사람이 읽는 출력에 정리 힌트를 표시하고 대부분의 설정은 머신당 하나의 Gateway를 실행해야 한다고 경고합니다.
|
||||
- `--deep`은 서비스 프로세스가 외부 슈퍼바이저 재시작을 위해 정상 종료된 경우 최근 Gateway 슈퍼바이저 재시작 인계도 보고합니다.
|
||||
- 사람이 읽는 출력에는 프로필 또는 state-dir 드리프트 진단을 돕기 위해 해석된 파일 로그 경로와 CLI 대비 서비스 구성 경로/유효성 스냅샷이 포함됩니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Linux systemd 인증 불일치 검사">
|
||||
- Linux systemd 설치에서는 서비스 인증 불일치 검사가 유닛의 `Environment=`와 `EnvironmentFile=` 값을 모두 읽습니다(`%h`, 따옴표로 감싼 경로, 여러 파일, 선택적 `-` 파일 포함).
|
||||
- 불일치 검사는 병합된 런타임 env(서비스 명령 env 우선, 그다음 프로세스 env 폴백)를 사용해 `gateway.auth.token` SecretRefs를 확인합니다.
|
||||
- 토큰 인증이 실제로 활성 상태가 아니면(명시적 `gateway.auth.mode`가 `password`/`none`/`trusted-proxy`이거나, 모드가 설정되지 않았고 비밀번호가 우선될 수 있으며 우선될 수 있는 토큰 후보가 없는 경우), 토큰 불일치 검사는 구성 토큰 확인을 건너뜁니다.
|
||||
<Accordion title="Linux systemd 인증 드리프트 검사">
|
||||
- Linux systemd 설치에서는 서비스 인증 드리프트 검사가 유닛의 `Environment=` 및 `EnvironmentFile=` 값을 모두 읽습니다(`%h`, 따옴표로 감싼 경로, 여러 파일, 선택적 `-` 파일 포함).
|
||||
- 드리프트 검사는 병합된 런타임 env를 사용해 `gateway.auth.token` SecretRefs를 해석합니다(먼저 서비스 명령 env, 그다음 프로세스 env 폴백).
|
||||
- 토큰 인증이 실질적으로 활성화되어 있지 않으면(`password`/`none`/`trusted-proxy`의 명시적 `gateway.auth.mode`, 또는 비밀번호가 우선될 수 있고 토큰 후보가 우선될 수 없는 모드 미설정 상태), 토큰 드리프트 검사는 구성 토큰 해석을 건너뜁니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@ -318,16 +319,16 @@ openclaw gateway status --require-rpc
|
||||
`gateway probe`는 "모든 것을 디버그"하는 명령입니다. 항상 다음을 프로브합니다.
|
||||
|
||||
- 구성된 원격 Gateway(설정된 경우), 그리고
|
||||
- 원격이 구성되어 있어도 localhost(loopback)를 **항상** 프로브합니다.
|
||||
- 원격이 구성되어 있어도 localhost(loopback)를 **프로브합니다**.
|
||||
|
||||
`--url`을 전달하면 해당 명시적 대상이 두 대상보다 앞에 추가됩니다. 사람이 읽는 출력은 대상을 다음처럼 표시합니다.
|
||||
`--url`을 전달하면 해당 명시적 대상이 둘보다 앞에 추가됩니다. 사람이 읽는 출력은 대상을 다음과 같이 표시합니다.
|
||||
|
||||
- `URL (explicit)`
|
||||
- `Remote (configured)` 또는 `Remote (configured, inactive)`
|
||||
- `Local loopback`
|
||||
|
||||
<Note>
|
||||
여러 Gateway에 연결할 수 있으면 모두 출력합니다. 분리된 프로필/포트(예: 구조 봇)를 사용할 때는 여러 Gateway가 지원되지만, 대부분의 설치는 여전히 단일 Gateway를 실행합니다.
|
||||
여러 Gateway에 연결할 수 있으면 모두 출력합니다. 격리된 프로필/포트(예: 복구 봇)를 사용할 때는 여러 Gateway가 지원되지만, 대부분의 설치는 여전히 단일 Gateway를 실행합니다.
|
||||
</Note>
|
||||
|
||||
```bash
|
||||
@ -337,66 +338,66 @@ openclaw gateway probe --json
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="해석">
|
||||
- `Reachable: yes`는 하나 이상의 대상이 WebSocket 연결을 수락했다는 뜻입니다.
|
||||
- `Capability: read-only|write-capable|admin-capable|pairing-pending|connect-only`는 프로브가 인증에 대해 검증할 수 있었던 내용을 보고합니다. 연결 가능성과는 별개입니다.
|
||||
- `Reachable: yes`는 적어도 하나의 대상이 WebSocket 연결을 수락했다는 뜻입니다.
|
||||
- `Capability: read-only|write-capable|admin-capable|pairing-pending|connect-only`는 프로브가 인증에 대해 증명할 수 있었던 내용을 보고합니다. 이는 연결 가능성과 별개입니다.
|
||||
- `Read probe: ok`는 읽기 범위 세부 RPC 호출(`health`/`status`/`system-presence`/`config.get`)도 성공했다는 뜻입니다.
|
||||
- `Read probe: limited - missing scope: operator.read`는 연결은 성공했지만 읽기 범위 RPC가 제한되었다는 뜻입니다. 이는 전체 실패가 아니라 **저하된** 연결 가능성으로 보고됩니다.
|
||||
- `Connect: ok` 이후의 `Read probe: failed`는 Gateway가 WebSocket 연결은 수락했지만 후속 읽기 진단이 시간 초과되었거나 실패했다는 뜻입니다. 이 역시 연결할 수 없는 Gateway가 아니라 **저하된** 연결 가능성입니다.
|
||||
- `gateway status`와 마찬가지로, 프로브는 기존 캐시된 기기 인증을 재사용하지만 최초 기기 ID나 페어링 상태를 만들지는 않습니다.
|
||||
- 종료 코드는 프로브한 대상 중 연결 가능한 대상이 하나도 없을 때만 0이 아닙니다.
|
||||
- `Connect: ok` 뒤의 `Read probe: failed`는 Gateway가 WebSocket 연결을 수락했지만 후속 읽기 진단이 시간 초과되었거나 실패했다는 뜻입니다. 이 또한 도달 불가능한 Gateway가 아니라 **저하된** 연결 가능성입니다.
|
||||
- `gateway status`와 마찬가지로 프로브는 기존 캐시된 장치 인증을 재사용하지만 최초 장치 ID나 페어링 상태를 생성하지는 않습니다.
|
||||
- 종료 코드는 프로브된 대상 중 도달 가능한 대상이 없을 때만 0이 아닙니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="JSON 출력">
|
||||
최상위 수준:
|
||||
최상위:
|
||||
|
||||
- `ok`: 하나 이상의 대상에 연결할 수 있습니다.
|
||||
- `degraded`: 하나 이상의 대상이 연결을 수락했지만 전체 세부 RPC 진단을 완료하지 못했습니다.
|
||||
- `capability`: 연결 가능한 대상 전체에서 확인된 최선의 기능(`read_only`, `write_capable`, `admin_capable`, `pairing_pending`, `connected_no_operator_scope` 또는 `unknown`).
|
||||
- `primaryTargetId`: 활성 승자로 취급할 최선의 대상입니다. 순서는 명시적 URL, SSH 터널, 구성된 원격, 그다음 local loopback입니다.
|
||||
- `warnings[]`: `code`, `message`, 선택적 `targetIds`가 있는 최선 방식의 경고 레코드입니다.
|
||||
- `ok`: 적어도 하나의 대상에 도달할 수 있습니다.
|
||||
- `degraded`: 적어도 하나의 대상이 연결을 수락했지만 전체 세부 RPC 진단을 완료하지 못했습니다.
|
||||
- `capability`: 도달 가능한 대상 전체에서 확인된 최상의 기능(`read_only`, `write_capable`, `admin_capable`, `pairing_pending`, `connected_no_operator_scope`, 또는 `unknown`).
|
||||
- `primaryTargetId`: 다음 순서로 활성 승자로 취급할 최상의 대상: 명시적 URL, SSH 터널, 구성된 원격, 그다음 local loopback.
|
||||
- `warnings[]`: `code`, `message`, 선택적 `targetIds`가 있는 최선의 경고 레코드입니다.
|
||||
- `network`: 현재 구성과 호스트 네트워킹에서 파생된 local loopback/tailnet URL 힌트입니다.
|
||||
- `discovery.timeoutMs` 및 `discovery.count`: 이 프로브 패스에 사용된 실제 검색 예산/결과 수입니다.
|
||||
- `discovery.timeoutMs` 및 `discovery.count`: 이 프로브 패스에 사용된 실제 발견 예산/결과 수입니다.
|
||||
|
||||
대상별(`targets[].connect`):
|
||||
|
||||
- `ok`: 연결 + 저하 분류 이후의 연결 가능성입니다.
|
||||
- `rpcOk`: 전체 세부 RPC 성공 여부입니다.
|
||||
- `scopeLimited`: operator 범위 누락으로 인해 세부 RPC가 실패했습니다.
|
||||
- `ok`: 연결 + 저하 분류 이후의 도달 가능성입니다.
|
||||
- `rpcOk`: 전체 세부 RPC 성공입니다.
|
||||
- `scopeLimited`: 필요한 operator 범위가 없어 세부 RPC가 실패했습니다.
|
||||
|
||||
대상별(`targets[].auth`):
|
||||
|
||||
- `role`: 사용 가능한 경우 `hello-ok`에 보고된 인증 역할입니다.
|
||||
- `scopes`: 사용 가능한 경우 `hello-ok`에 보고된 부여된 범위입니다.
|
||||
- `capability`: 해당 대상에 대해 표시된 인증 기능 분류입니다.
|
||||
- `role`: 사용 가능한 경우 `hello-ok`에서 보고된 인증 역할입니다.
|
||||
- `scopes`: 사용 가능한 경우 `hello-ok`에서 보고된 부여된 범위입니다.
|
||||
- `capability`: 해당 대상에 표시된 인증 기능 분류입니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="일반적인 경고 코드">
|
||||
- `ssh_tunnel_failed`: SSH 터널 설정에 실패했습니다. 명령이 직접 프로브로 폴백했습니다.
|
||||
- `multiple_gateways`: 둘 이상의 대상에 연결할 수 있었습니다. 구조 봇처럼 분리된 프로필을 의도적으로 실행하는 경우가 아니라면 이는 일반적이지 않습니다.
|
||||
- `auth_secretref_unresolved`: 실패한 대상에 대해 구성된 인증 SecretRef를 확인할 수 없었습니다.
|
||||
- `probe_scope_limited`: WebSocket 연결은 성공했지만, `operator.read` 누락으로 읽기 프로브가 제한되었습니다.
|
||||
- `ssh_tunnel_failed`: SSH 터널 설정에 실패했습니다. 명령은 직접 프로브로 폴백했습니다.
|
||||
- `multiple_gateways`: 둘 이상의 대상에 도달할 수 있었습니다. 복구 봇처럼 격리된 프로필을 의도적으로 실행하는 경우가 아니라면 이는 흔하지 않습니다.
|
||||
- `auth_secretref_unresolved`: 구성된 인증 SecretRef를 실패한 대상에 대해 해석할 수 없었습니다.
|
||||
- `probe_scope_limited`: WebSocket 연결은 성공했지만 읽기 프로브가 누락된 `operator.read`로 인해 제한되었습니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
#### SSH를 통한 원격 연결(Mac 앱 동등성)
|
||||
#### SSH를 통한 원격(Mac 앱 동등성)
|
||||
|
||||
macOS 앱의 "Remote over SSH" 모드는 로컬 포트 포워딩을 사용하므로 원격 Gateway(loopback에만 바인딩되어 있을 수 있음)에 `ws://127.0.0.1:<port>`에서 연결할 수 있습니다.
|
||||
macOS 앱의 "Remote over SSH" 모드는 로컬 포트 포워드를 사용하여 원격 Gateway(loopback에만 바인딩되어 있을 수 있음)가 `ws://127.0.0.1:<port>`에서 도달 가능하게 만듭니다.
|
||||
|
||||
CLI 동등 명령:
|
||||
CLI에 해당하는 명령:
|
||||
|
||||
```bash
|
||||
openclaw gateway probe --ssh user@gateway-host
|
||||
```
|
||||
|
||||
<ParamField path="--ssh <target>" type="string">
|
||||
`user@host` 또는 `user@host:port`(`port` 기본값은 `22`).
|
||||
`user@host` 또는 `user@host:port`(포트 기본값은 `22`).
|
||||
</ParamField>
|
||||
<ParamField path="--ssh-identity <path>" type="string">
|
||||
ID 파일입니다.
|
||||
</ParamField>
|
||||
<ParamField path="--ssh-auto" type="boolean">
|
||||
확인된 검색 엔드포인트(`local.` 및 구성된 광역 도메인, 있는 경우)에서 검색된 첫 번째 Gateway 호스트를 SSH 대상으로 선택합니다. TXT 전용 힌트는 무시됩니다.
|
||||
해석된 발견 엔드포인트(`local.`과 구성된 광역 도메인, 있는 경우)에서 처음 발견된 Gateway 호스트를 SSH 대상으로 선택합니다. TXT 전용 힌트는 무시됩니다.
|
||||
</ParamField>
|
||||
|
||||
구성(선택 사항, 기본값으로 사용):
|
||||
@ -406,7 +407,7 @@ openclaw gateway probe --ssh user@gateway-host
|
||||
|
||||
### `gateway call <method>`
|
||||
|
||||
저수준 RPC 도우미입니다.
|
||||
저수준 RPC 헬퍼입니다.
|
||||
|
||||
```bash
|
||||
openclaw gateway call status
|
||||
@ -432,7 +433,7 @@ openclaw gateway call logs.tail --params '{"sinceMs": 60000}'
|
||||
주로 최종 페이로드 전에 중간 이벤트를 스트리밍하는 에이전트 스타일 RPC용입니다.
|
||||
</ParamField>
|
||||
<ParamField path="--json" type="boolean">
|
||||
머신이 읽을 수 있는 JSON 출력입니다.
|
||||
기계가 읽을 수 있는 JSON 출력입니다.
|
||||
</ParamField>
|
||||
|
||||
<Note>
|
||||
@ -452,8 +453,8 @@ openclaw gateway uninstall
|
||||
### 래퍼로 설치
|
||||
|
||||
관리형 서비스가 다른 실행 파일을 통해 시작되어야 할 때 `--wrapper`를 사용하세요. 예를 들어
|
||||
시크릿 관리자 shim이나 run-as 도우미가 있습니다. 래퍼는 일반 Gateway 인수를 받고
|
||||
최종적으로 해당 인수로 `openclaw` 또는 Node를 exec해야 합니다.
|
||||
시크릿 관리자 shim 또는 run-as 헬퍼가 있습니다. 래퍼는 일반 Gateway 인자를 받고
|
||||
최종적으로 해당 인자로 `openclaw` 또는 Node를 exec할 책임이 있습니다.
|
||||
|
||||
```bash
|
||||
cat > ~/.local/bin/openclaw-doppler <<'EOF'
|
||||
@ -468,8 +469,8 @@ openclaw gateway restart
|
||||
```
|
||||
|
||||
환경을 통해 래퍼를 설정할 수도 있습니다. `gateway install`은 경로가
|
||||
실행 가능한 파일인지 검증하고, 래퍼를 서비스 `ProgramArguments`에 기록하며, 이후 강제 재설치, 업데이트, doctor
|
||||
수리를 위해 서비스 환경에 `OPENCLAW_WRAPPER`를 유지합니다.
|
||||
실행 가능한 파일인지 검증하고, 래퍼를 서비스 `ProgramArguments`에 쓰며, 이후 강제 재설치, 업데이트, doctor
|
||||
복구를 위해 서비스 환경에 `OPENCLAW_WRAPPER`를 유지합니다.
|
||||
|
||||
```bash
|
||||
OPENCLAW_WRAPPER="$HOME/.local/bin/openclaw-doppler" openclaw gateway install --force
|
||||
@ -492,41 +493,41 @@ openclaw gateway restart
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="수명 주기 동작">
|
||||
- 관리형 서비스를 다시 시작하려면 `gateway restart`를 사용하세요. 재시작 대체 수단으로 `gateway stop`과 `gateway start`를 연쇄 실행하지 마세요. macOS에서 `gateway stop`은 중지하기 전에 의도적으로 LaunchAgent를 비활성화합니다.
|
||||
- `gateway restart --safe`는 실행 중인 Gateway에 활성 OpenClaw 작업을 사전 점검하고, 응답 전달, 임베디드 실행, 작업 실행이 모두 비워질 때까지 재시작을 지연하도록 요청합니다. `--safe`는 `--force` 또는 `--wait`와 함께 사용할 수 없습니다.
|
||||
- `gateway restart --wait 30s`는 해당 재시작에 대해 구성된 재시작 드레인 예산을 재정의합니다. 단위 없는 숫자는 밀리초이며, `s`, `m`, `h` 같은 단위를 사용할 수 있습니다. `--wait 0`은 무기한 대기합니다.
|
||||
- `gateway restart --force`는 활성 작업 드레인을 건너뛰고 즉시 다시 시작합니다. 운영자가 나열된 작업 차단 요소를 이미 점검했고 지금 Gateway를 되돌리고자 할 때 사용하세요.
|
||||
- 관리형 서비스를 재시작하려면 `gateway restart`를 사용하세요. 재시작 대체 수단으로 `gateway stop`과 `gateway start`를 연결하지 마세요. macOS에서 `gateway stop`은 중지하기 전에 의도적으로 LaunchAgent를 비활성화합니다.
|
||||
- `gateway restart --safe`는 실행 중인 Gateway에 활성 OpenClaw 작업을 사전 점검하고 답장 전달, 임베디드 실행, 작업 실행이 모두 비워질 때까지 재시작을 지연하도록 요청합니다. `--safe`는 `--force` 또는 `--wait`와 함께 사용할 수 없습니다.
|
||||
- `gateway restart --wait 30s`는 해당 재시작에 대해 구성된 재시작 드레인 예산을 재정의합니다. 단위가 없는 숫자는 밀리초이며, `s`, `m`, `h` 같은 단위가 허용됩니다. `--wait 0`은 무기한 대기합니다.
|
||||
- `gateway restart --force`는 활성 작업 드레인을 건너뛰고 즉시 재시작합니다. 운영자가 나열된 작업 차단 항목을 이미 검사했고 지금 Gateway를 되돌리고자 할 때 사용하세요.
|
||||
- 수명 주기 명령은 스크립팅을 위해 `--json`을 허용합니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="설치 시 인증 및 SecretRefs">
|
||||
- 토큰 인증에 토큰이 필요하고 `gateway.auth.token`이 SecretRef로 관리되는 경우, `gateway install`은 SecretRef를 확인할 수 있는지 검증하지만 확인된 토큰을 서비스 환경 메타데이터에 저장하지 않습니다.
|
||||
- 토큰 인증에 토큰이 필요하고 구성된 토큰 SecretRef가 확인되지 않으면, 대체 일반 텍스트를 저장하는 대신 설치가 안전하게 실패합니다.
|
||||
- `gateway run`의 비밀번호 인증에는 인라인 `--password`보다 `OPENCLAW_GATEWAY_PASSWORD`, `--password-file` 또는 SecretRef 기반 `gateway.auth.password`를 사용하는 것을 권장합니다.
|
||||
- 추론된 인증 모드에서 셸 전용 `OPENCLAW_GATEWAY_PASSWORD`는 설치 토큰 요구 사항을 완화하지 않습니다. 관리형 서비스를 설치할 때는 영구 구성(`gateway.auth.password` 또는 구성 `env`)을 사용하세요.
|
||||
- `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있고 `gateway.auth.mode`가 설정되지 않은 경우, 모드를 명시적으로 설정할 때까지 설치가 차단됩니다.
|
||||
<Accordion title="Auth and SecretRefs at install time">
|
||||
- 토큰 인증에 토큰이 필요하고 `gateway.auth.token`이 SecretRef로 관리되는 경우, `gateway install`은 SecretRef를 해석할 수 있는지 검증하지만 해석된 토큰을 서비스 환경 메타데이터에 저장하지 않습니다.
|
||||
- 토큰 인증에 토큰이 필요하지만 구성된 토큰 SecretRef를 해석할 수 없는 경우, 설치는 대체 일반 텍스트를 저장하는 대신 안전하게 실패합니다.
|
||||
- `gateway run`에서 비밀번호 인증을 사용할 때는 인라인 `--password`보다 `OPENCLAW_GATEWAY_PASSWORD`, `--password-file` 또는 SecretRef 기반 `gateway.auth.password`를 선호하세요.
|
||||
- 추론된 인증 모드에서는 셸 전용 `OPENCLAW_GATEWAY_PASSWORD`가 설치 토큰 요구 사항을 완화하지 않습니다. 관리형 서비스를 설치할 때는 지속 구성(`gateway.auth.password` 또는 config `env`)을 사용하세요.
|
||||
- `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있고 `gateway.auth.mode`가 설정되지 않은 경우, 모드가 명시적으로 설정될 때까지 설치가 차단됩니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Gateway 찾기 (Bonjour)
|
||||
## Gateway 발견(Bonjour)
|
||||
|
||||
`gateway discover`는 Gateway 비콘(`_openclaw-gw._tcp`)을 스캔합니다.
|
||||
`gateway discover`는 Gateway 비컨(`_openclaw-gw._tcp`)을 스캔합니다.
|
||||
|
||||
- 멀티캐스트 DNS-SD: `local.`
|
||||
- 유니캐스트 DNS-SD(Wide-Area Bonjour): 도메인(예: `openclaw.internal.`)을 선택하고 분할 DNS + DNS 서버를 설정하세요. [Bonjour](/ko/gateway/bonjour)를 참조하세요.
|
||||
- 유니캐스트 DNS-SD(Wide-Area Bonjour): 도메인(예: `openclaw.internal.`)을 선택하고 split DNS + DNS 서버를 설정하세요. [Bonjour](/ko/gateway/bonjour)를 참조하세요.
|
||||
|
||||
Bonjour 검색이 활성화된 Gateway(기본값)만 비콘을 알립니다.
|
||||
Bonjour 발견이 활성화된 Gateway(기본값)만 비컨을 광고합니다.
|
||||
|
||||
Wide-Area 검색 레코드에는 다음이 포함됩니다(TXT).
|
||||
Wide-Area 발견 레코드에는 다음이 포함됩니다(TXT).
|
||||
|
||||
- `role`(Gateway 역할 힌트)
|
||||
- `transport`(전송 힌트, 예: `gateway`)
|
||||
- `gatewayPort`(WebSocket 포트, 일반적으로 `18789`)
|
||||
- `sshPort`(선택 사항. 없으면 클라이언트는 SSH 대상을 기본값 `22`로 사용)
|
||||
- `sshPort`(선택 사항; 없으면 클라이언트는 기본 SSH 대상을 `22`로 설정)
|
||||
- `tailnetDns`(사용 가능한 경우 MagicDNS 호스트 이름)
|
||||
- `gatewayTls` / `gatewayTlsSha256`(TLS 활성화 + 인증서 지문)
|
||||
- `cliPath`(Wide-Area 영역에 기록되는 원격 설치 힌트)
|
||||
- `cliPath`(wide-area 영역에 기록되는 원격 설치 힌트)
|
||||
|
||||
### `gateway discover`
|
||||
|
||||
@ -535,7 +536,7 @@ openclaw gateway discover
|
||||
```
|
||||
|
||||
<ParamField path="--timeout <ms>" type="number" default="2000">
|
||||
명령별 제한 시간(탐색/확인).
|
||||
명령별 타임아웃(찾아보기/해석).
|
||||
</ParamField>
|
||||
<ParamField path="--json" type="boolean">
|
||||
기계가 읽을 수 있는 출력(스타일/스피너도 비활성화).
|
||||
@ -549,9 +550,9 @@ openclaw gateway discover --json | jq '.beacons[].wsUrl'
|
||||
```
|
||||
|
||||
<Note>
|
||||
- CLI는 `local.`과 구성된 Wide-Area 도메인(활성화된 경우)을 함께 스캔합니다.
|
||||
- JSON 출력의 `wsUrl`은 `lanHost` 또는 `tailnetDns` 같은 TXT 전용 힌트가 아니라 확인된 서비스 엔드포인트에서 파생됩니다.
|
||||
- `local.` mDNS에서는 `discovery.mdns.mode`가 `full`인 경우에만 `sshPort`와 `cliPath`가 브로드캐스트됩니다. Wide-Area DNS-SD는 여전히 `cliPath`를 기록하며, `sshPort`도 거기에서 선택 사항으로 유지됩니다.
|
||||
- CLI는 `local.`과, 활성화된 경우 구성된 wide-area 도메인을 함께 스캔합니다.
|
||||
- JSON 출력의 `wsUrl`은 `lanHost` 또는 `tailnetDns` 같은 TXT 전용 힌트가 아니라 해석된 서비스 엔드포인트에서 파생됩니다.
|
||||
- `local.` mDNS에서는 `discovery.mdns.mode`가 `full`일 때만 `sshPort`와 `cliPath`가 브로드캐스트됩니다. Wide-area DNS-SD는 여전히 `cliPath`를 기록하며, `sshPort`도 그곳에서 선택 사항으로 유지됩니다.
|
||||
|
||||
</Note>
|
||||
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
---
|
||||
read_when:
|
||||
- 에이전트 훅을 관리하려고 합니다
|
||||
- 후크 사용 가능 여부를 확인하거나 작업 공간 후크를 활성화하려는 경우
|
||||
summary: '`openclaw hooks`의 CLI 참조(에이전트 훅)'
|
||||
- 에이전트 훅을 관리하려는 경우
|
||||
- 훅 사용 가능 여부를 검사하거나 워크스페이스 훅을 활성화하려는 경우
|
||||
summary: '`openclaw hooks`(에이전트 훅)에 대한 CLI 참조'
|
||||
title: 후크
|
||||
x-i18n:
|
||||
generated_at: "2026-05-02T20:45:29Z"
|
||||
generated_at: "2026-05-05T08:25:34Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 3b02c176b4a310adba3fa1fde3758f6c8a19d454aeec58e919458b3f1a66c87d
|
||||
source_hash: 8e860d4a20a09526e804fa1aff8c983a75396fcd1e6e24f742252fdf1812f6b7
|
||||
source_path: cli/hooks.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
# `openclaw hooks`
|
||||
|
||||
에이전트 훅(`/new`, `/reset`, Gateway 시작과 같은 명령을 위한 이벤트 기반 자동화)을 관리합니다.
|
||||
에이전트 훅(`/new`, `/reset`, Gateway 시작 같은 명령에 대한 이벤트 기반 자동화)을 관리합니다.
|
||||
|
||||
하위 명령 없이 `openclaw hooks`를 실행하는 것은 `openclaw hooks list`와 동일합니다.
|
||||
|
||||
@ -30,14 +30,14 @@ x-i18n:
|
||||
openclaw hooks list
|
||||
```
|
||||
|
||||
작업공간, 관리형, 추가, 번들 디렉터리에서 발견된 모든 훅을 나열합니다.
|
||||
Gateway 시작은 내부 훅이 하나 이상 구성될 때까지 내부 훅 핸들러를 로드하지 않습니다.
|
||||
워크스페이스, 관리형, 추가, 번들 디렉터리에서 발견된 모든 훅을 나열합니다.
|
||||
Gateway 시작 시에는 내부 훅이 하나 이상 구성될 때까지 내부 훅 핸들러를 로드하지 않습니다.
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `--eligible`: 적격 훅만 표시합니다(요구 사항 충족)
|
||||
- `--json`: JSON으로 출력합니다
|
||||
- `-v, --verbose`: 누락된 요구 사항을 포함한 자세한 정보를 표시합니다
|
||||
- `--eligible`: 요구사항을 충족한 적격 훅만 표시
|
||||
- `--json`: JSON으로 출력
|
||||
- `-v, --verbose`: 누락된 요구사항을 포함한 자세한 정보 표시
|
||||
|
||||
**예시 출력:**
|
||||
|
||||
@ -57,7 +57,7 @@ Ready:
|
||||
openclaw hooks list --verbose
|
||||
```
|
||||
|
||||
적격하지 않은 훅의 누락된 요구 사항을 표시합니다.
|
||||
부적격 훅의 누락된 요구사항을 표시합니다.
|
||||
|
||||
**예시(JSON):**
|
||||
|
||||
@ -65,7 +65,7 @@ openclaw hooks list --verbose
|
||||
openclaw hooks list --json
|
||||
```
|
||||
|
||||
프로그래밍 방식 사용을 위한 구조화된 JSON을 반환합니다.
|
||||
프로그래밍 방식으로 사용할 수 있는 구조화된 JSON을 반환합니다.
|
||||
|
||||
## 훅 정보 가져오기
|
||||
|
||||
@ -81,7 +81,7 @@ openclaw hooks info <name>
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `--json`: JSON으로 출력합니다
|
||||
- `--json`: JSON으로 출력
|
||||
|
||||
**예시:**
|
||||
|
||||
@ -113,11 +113,11 @@ Requirements:
|
||||
openclaw hooks check
|
||||
```
|
||||
|
||||
훅 적격성 상태 요약(준비됨과 준비되지 않음의 수)을 표시합니다.
|
||||
훅 적격성 상태 요약(준비됨과 준비되지 않음의 개수)을 표시합니다.
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `--json`: JSON으로 출력합니다
|
||||
- `--json`: JSON으로 출력
|
||||
|
||||
**예시 출력:**
|
||||
|
||||
@ -137,7 +137,7 @@ openclaw hooks enable <name>
|
||||
|
||||
구성(기본값은 `~/.openclaw/openclaw.json`)에 추가하여 특정 훅을 활성화합니다.
|
||||
|
||||
**참고:** 작업공간 훅은 여기 또는 구성에서 활성화하기 전까지 기본적으로 비활성화됩니다. Plugin이 관리하는 훅은 `openclaw hooks list`에 `plugin:<id>`로 표시되며 여기에서 활성화/비활성화할 수 없습니다. 대신 해당 Plugin을 활성화/비활성화하세요.
|
||||
**참고:** 워크스페이스 훅은 여기 또는 구성에서 활성화하기 전까지 기본적으로 비활성화됩니다. Plugin이 관리하는 훅은 `openclaw hooks list`에 `plugin:<id>`로 표시되며 여기서는 활성화/비활성화할 수 없습니다. 대신 Plugin을 활성화/비활성화하세요.
|
||||
|
||||
**인수:**
|
||||
|
||||
@ -157,15 +157,15 @@ openclaw hooks enable session-memory
|
||||
|
||||
**수행 작업:**
|
||||
|
||||
- 훅이 존재하고 적격한지 확인합니다
|
||||
- 구성에서 `hooks.internal.entries.<name>.enabled = true`를 업데이트합니다
|
||||
- 구성을 디스크에 저장합니다
|
||||
- 훅이 존재하고 적격인지 확인
|
||||
- 구성에서 `hooks.internal.entries.<name>.enabled = true`로 업데이트
|
||||
- 구성을 디스크에 저장
|
||||
|
||||
훅이 `<workspace>/hooks/`에서 온 경우, Gateway가 로드하기 전에 이 옵트인 단계가 필요합니다.
|
||||
훅이 `<workspace>/hooks/`에서 온 경우, Gateway가 이를 로드하려면 이 옵트인 단계가 필요합니다.
|
||||
|
||||
**활성화 후:**
|
||||
|
||||
- 훅이 다시 로드되도록 Gateway를 재시작하세요(macOS에서는 메뉴 막대 앱 재시작, 또는 개발 환경에서는 Gateway 프로세스 재시작).
|
||||
- 훅이 다시 로드되도록 Gateway를 다시 시작합니다(macOS에서는 메뉴 막대 앱 재시작, 또는 개발 환경에서는 Gateway 프로세스 재시작).
|
||||
|
||||
## 훅 비활성화
|
||||
|
||||
@ -193,12 +193,12 @@ openclaw hooks disable command-logger
|
||||
|
||||
**비활성화 후:**
|
||||
|
||||
- 훅이 다시 로드되도록 Gateway를 재시작하세요
|
||||
- 훅이 다시 로드되도록 Gateway를 다시 시작합니다.
|
||||
|
||||
## 참고
|
||||
|
||||
- `openclaw hooks list --json`, `info --json`, `check --json`는 구조화된 JSON을 stdout에 직접 작성합니다.
|
||||
- Plugin 관리형 훅은 여기에서 활성화하거나 비활성화할 수 없습니다. 대신 소유 Plugin을 활성화하거나 비활성화하세요.
|
||||
- `openclaw hooks list --json`, `info --json`, `check --json`은 구조화된 JSON을 stdout에 직접 씁니다.
|
||||
- Plugin 관리 훅은 여기서 활성화하거나 비활성화할 수 없습니다. 대신 소유 Plugin을 활성화하거나 비활성화하세요.
|
||||
|
||||
## 훅 팩 설치
|
||||
|
||||
@ -211,24 +211,24 @@ openclaw plugins install <path> # local path
|
||||
|
||||
통합 Plugin 설치 관리자를 통해 훅 팩을 설치합니다.
|
||||
|
||||
`openclaw hooks install`은 호환성 별칭으로 여전히 작동하지만, 지원 중단 경고를 출력하고 `openclaw plugins install`로 전달합니다.
|
||||
`openclaw hooks install`은 호환성 별칭으로 계속 동작하지만, 사용 중단 경고를 출력하고 `openclaw plugins install`로 전달합니다.
|
||||
|
||||
Npm 명세는 **레지스트리 전용**입니다(패키지 이름 + 선택적 **정확한 버전** 또는 **dist-tag**). Git/URL/파일 명세와 semver 범위는 거부됩니다. 종속성 설치는 셸에 전역 npm 설치 설정이 있더라도 안전을 위해 `--ignore-scripts`를 사용하여 프로젝트 로컬로 실행됩니다.
|
||||
Npm 명세는 **레지스트리 전용**입니다(패키지 이름 + 선택적 **정확한 버전** 또는 **dist-tag**). Git/URL/file 명세와 semver 범위는 거부됩니다. 종속성 설치는 셸에 전역 npm 설치 설정이 있더라도 안전을 위해 `--ignore-scripts`와 함께 프로젝트 로컬로 실행됩니다.
|
||||
|
||||
단순 명세와 `@latest`는 안정 트랙에 유지됩니다. npm이 둘 중 하나를 프리릴리스로 해석하면 OpenClaw는 중단하고 `@beta`/`@rc`와 같은 프리릴리스 태그 또는 정확한 프리릴리스 버전으로 명시적으로 옵트인하라고 요청합니다.
|
||||
Bare 명세와 `@latest`는 안정 트랙에 유지됩니다. npm이 이 둘 중 하나를 프리릴리스로 해석하면 OpenClaw는 중단하고 `@beta`/`@rc` 같은 프리릴리스 태그 또는 정확한 프리릴리스 버전으로 명시적으로 옵트인하라고 요청합니다.
|
||||
|
||||
**수행 작업:**
|
||||
|
||||
- 훅 팩을 `~/.openclaw/hooks/<id>`로 복사합니다
|
||||
- 설치된 훅을 `hooks.internal.entries.*`에서 활성화합니다
|
||||
- 설치를 `hooks.internal.installs` 아래에 기록합니다
|
||||
- 훅 팩을 `~/.openclaw/hooks/<id>`로 복사
|
||||
- 설치된 훅을 `hooks.internal.entries.*`에서 활성화
|
||||
- 설치를 `hooks.internal.installs` 아래에 기록
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `-l, --link`: 로컬 디렉터리를 복사하는 대신 링크합니다(`hooks.internal.load.extraDirs`에 추가)
|
||||
- `--pin`: npm 설치를 `hooks.internal.installs`에 정확히 해석된 `name@version`으로 기록합니다
|
||||
- `-l, --link`: 복사하는 대신 로컬 디렉터리를 링크합니다(`hooks.internal.load.extraDirs`에 추가)
|
||||
- `--pin`: npm 설치를 `hooks.internal.installs`에 정확히 해석된 `name@version`으로 기록
|
||||
|
||||
**지원되는 아카이브:** `.zip`, `.tgz`, `.tar.gz`, `.tar`
|
||||
**지원 아카이브:** `.zip`, `.tgz`, `.tar.gz`, `.tar`
|
||||
|
||||
**예시:**
|
||||
|
||||
@ -246,7 +246,7 @@ openclaw plugins install @openclaw/my-hook-pack
|
||||
openclaw plugins install -l ./my-hook-pack
|
||||
```
|
||||
|
||||
링크된 훅 팩은 작업공간 훅이 아니라 운영자가 구성한 디렉터리의 관리형 훅으로 처리됩니다.
|
||||
링크된 훅 팩은 워크스페이스 훅이 아니라 운영자가 구성한 디렉터리의 관리형 훅으로 처리됩니다.
|
||||
|
||||
## 훅 팩 업데이트
|
||||
|
||||
@ -255,16 +255,16 @@ openclaw plugins update <id>
|
||||
openclaw plugins update --all
|
||||
```
|
||||
|
||||
추적 중인 npm 기반 훅 팩을 통합 Plugin 업데이트 관리자를 통해 업데이트합니다.
|
||||
통합 Plugin 업데이트 도구를 통해 추적 중인 npm 기반 훅 팩을 업데이트합니다.
|
||||
|
||||
`openclaw hooks update`는 호환성 별칭으로 여전히 작동하지만, 지원 중단 경고를 출력하고 `openclaw plugins update`로 전달합니다.
|
||||
`openclaw hooks update`는 호환성 별칭으로 계속 동작하지만, 사용 중단 경고를 출력하고 `openclaw plugins update`로 전달합니다.
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `--all`: 추적 중인 모든 훅 팩을 업데이트합니다
|
||||
- `--dry-run`: 작성하지 않고 변경될 내용을 표시합니다
|
||||
- `--all`: 추적 중인 모든 훅 팩 업데이트
|
||||
- `--dry-run`: 쓰기 없이 변경될 내용을 표시
|
||||
|
||||
저장된 무결성 해시가 있고 가져온 아티팩트 해시가 변경되면 OpenClaw는 경고를 출력하고 계속하기 전에 확인을 요청합니다. CI/비대화형 실행에서 프롬프트를 건너뛰려면 전역 `--yes`를 사용하세요.
|
||||
저장된 무결성 해시가 있고 가져온 아티팩트 해시가 변경되면 OpenClaw는 경고를 출력하고 계속 진행하기 전에 확인을 요청합니다. CI/비대화형 실행에서 프롬프트를 건너뛰려면 전역 `--yes`를 사용하세요.
|
||||
|
||||
## 번들 훅
|
||||
|
||||
@ -278,7 +278,7 @@ openclaw plugins update --all
|
||||
openclaw hooks enable session-memory
|
||||
```
|
||||
|
||||
**출력:** `~/.openclaw/workspace/memory/YYYY-MM-DD-slug.md`
|
||||
**출력:** 기본값은 `~/.openclaw/workspace/memory/YYYY-MM-DD-HHMM.md`입니다. 모델 생성 파일 이름 슬러그를 사용하려면 `hooks.internal.entries.session-memory.llmSlug: true`를 설정하세요.
|
||||
|
||||
**참조:** [session-memory 문서](/ko/automation/hooks#session-memory)
|
||||
|
||||
@ -296,7 +296,7 @@ openclaw hooks enable bootstrap-extra-files
|
||||
|
||||
### command-logger
|
||||
|
||||
모든 명령 이벤트를 중앙 집중식 감사 파일에 기록합니다.
|
||||
모든 명령 이벤트를 중앙 감사 파일에 기록합니다.
|
||||
|
||||
**활성화:**
|
||||
|
||||
@ -323,7 +323,7 @@ grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
|
||||
|
||||
### boot-md
|
||||
|
||||
Gateway가 시작될 때(채널 시작 후) `BOOT.md`를 실행합니다.
|
||||
Gateway가 시작될 때(채널이 시작된 후) `BOOT.md`를 실행합니다.
|
||||
|
||||
**이벤트**: `gateway:startup`
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
---
|
||||
read_when:
|
||||
- 저장된 세션 목록을 보고 최근 활동을 확인하려는 경우
|
||||
summary: '`openclaw sessions`의 CLI 참조(저장된 세션 나열 + 사용법)'
|
||||
summary: '`openclaw sessions`에 대한 CLI 참조(저장된 세션 목록 표시 + 사용법)'
|
||||
title: 세션
|
||||
x-i18n:
|
||||
generated_at: "2026-05-05T01:44:16Z"
|
||||
generated_at: "2026-05-05T08:25:19Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 6eb484ab1fa7686cf42dd00e640c4ae8616c4ea1c29873ea72694d72b9c680e7
|
||||
source_hash: a204189952bc82788eb724c0a6b6db93c7d6795ad69bb6d498e8575236c3272e
|
||||
source_path: cli/sessions.md
|
||||
workflow: 16
|
||||
---
|
||||
@ -16,20 +16,20 @@ x-i18n:
|
||||
|
||||
저장된 대화 세션을 나열합니다.
|
||||
|
||||
세션 목록은 채널/제공자의 활성 상태 확인이 아닙니다. 세션 저장소에 유지된
|
||||
대화 행을 표시합니다. 조용한 Discord, Slack, Telegram 또는
|
||||
기타 채널은 메시지가 처리되기 전까지 새 세션 행을 만들지 않고도
|
||||
성공적으로 다시 연결될 수 있습니다. 실시간 채널 연결이 필요할 때는
|
||||
세션 목록은 채널/제공자 활성 상태 확인이 아닙니다. 세션 저장소에 유지된
|
||||
대화 행을 보여줍니다. 조용한 Discord, Slack, Telegram 또는
|
||||
다른 채널은 메시지가 처리되어 새 세션 행이 생성되기 전까지도
|
||||
성공적으로 다시 연결될 수 있습니다. 실시간 채널 연결이 필요하면
|
||||
`openclaw channels status --probe`, `openclaw status --deep` 또는
|
||||
`openclaw health --verbose`를 사용하세요.
|
||||
|
||||
`openclaw sessions` 및 Gateway `sessions.list` 응답은 기본적으로
|
||||
제한되므로, 크고 오래 유지되는 저장소가 CLI 프로세스나 Gateway
|
||||
이벤트 루프를 독점할 수 없습니다. CLI는 기본적으로 최신 세션 100개를 반환합니다.
|
||||
더 작거나 큰 범위를 보려면 `--limit <n>`을 전달하고, 의도적으로 전체 저장소가
|
||||
필요할 때는 `--limit all`을 전달하세요. JSON 응답에는 호출자가 더 많은 행이
|
||||
있음을 표시해야 할 때 사용할 수 있도록 `totalCount`, `limitApplied`, `hasMore`가
|
||||
포함됩니다.
|
||||
`openclaw sessions` 및 Gateway `sessions.list` 응답은 기본적으로 제한되어,
|
||||
크고 오래 실행되는 저장소가 CLI 프로세스나 Gateway 이벤트 루프를
|
||||
독점하지 못하게 합니다. CLI는 기본적으로 최신 100개 세션을 반환합니다.
|
||||
더 작거나 큰 범위가 필요하면 `--limit <n>`을 전달하고, 의도적으로 전체
|
||||
저장소가 필요하면 `--limit all`을 전달하세요. JSON 응답에는 호출자가 더 많은
|
||||
행이 있음을 표시해야 할 때 사용할 수 있도록 `totalCount`, `limitApplied`,
|
||||
`hasMore`가 포함됩니다.
|
||||
|
||||
```bash
|
||||
openclaw sessions
|
||||
@ -57,14 +57,15 @@ openclaw sessions export-trajectory --session-key "agent:main:telegram:direct:12
|
||||
openclaw sessions export-trajectory --session-key "agent:main:telegram:direct:123" --output bug-123 --json
|
||||
```
|
||||
|
||||
이것은 소유자가 exec 요청을 승인한 뒤 `/export-trajectory` 슬래시 명령이
|
||||
사용하는 명령 경로입니다. 출력 디렉터리는 항상 선택한 워크스페이스 아래의
|
||||
`.openclaw/trajectory-exports/` 내부로 해석됩니다.
|
||||
이는 소유자가 실행 요청을 승인한 뒤 `/export-trajectory` 슬래시 명령이
|
||||
사용하는 명령 경로입니다. 출력 디렉터리는 항상 선택된 워크스페이스 아래의
|
||||
`.openclaw/trajectory-exports/` 안에서 해석됩니다.
|
||||
|
||||
`openclaw sessions --all-agents`는 구성된 에이전트 저장소를 읽습니다. Gateway 및 ACP
|
||||
세션 검색은 더 넓습니다. 기본 `agents/` 루트 또는 템플릿화된 `session.store` 루트 아래에서
|
||||
찾은 디스크 전용 저장소도 포함합니다. 이렇게 검색된 저장소는 에이전트 루트 내부의
|
||||
일반 `sessions.json` 파일로 해석되어야 하며, 심볼릭 링크와 루트 외부 경로는 건너뜁니다.
|
||||
세션 검색은 더 넓은 범위를 다룹니다. 기본 `agents/` 루트 또는 템플릿화된
|
||||
`session.store` 루트 아래에서 발견된 디스크 전용 저장소도 포함합니다. 이렇게
|
||||
발견된 저장소는 에이전트 루트 안의 일반 `sessions.json` 파일로 해석되어야 하며,
|
||||
심볼릭 링크와 루트 밖 경로는 건너뜁니다.
|
||||
|
||||
JSON 예시:
|
||||
|
||||
@ -105,21 +106,22 @@ openclaw sessions cleanup --json
|
||||
|
||||
`openclaw sessions cleanup`은 구성의 `session.maintenance` 설정을 사용합니다.
|
||||
|
||||
- 범위 참고: `openclaw sessions cleanup`은 세션 저장소, transcript, trajectory sidecar를 유지 관리합니다. [Cron 구성](/ko/automation/cron-jobs#configuration)의 `cron.runLog.maxBytes` 및 `cron.runLog.keepLines`가 관리하고 [Cron 유지 관리](/ko/automation/cron-jobs#maintenance)에서 설명하는 cron 실행 로그(`cron/runs/<jobId>.jsonl`)는 정리하지 않습니다.
|
||||
- 범위 참고: `openclaw sessions cleanup`은 세션 저장소, transcript, trajectory 보조 파일을 유지 관리합니다. `cron/runs/<jobId>.jsonl`의 Cron 실행 로그는 정리하지 않으며, 이는 [Cron 구성](/ko/automation/cron-jobs#configuration)의 `cron.runLog.maxBytes` 및 `cron.runLog.keepLines`로 관리되고 [Cron 유지 관리](/ko/automation/cron-jobs#maintenance)에 설명되어 있습니다.
|
||||
- 정리는 `session.maintenance.pruneAfter`보다 오래된 참조되지 않는 기본 transcript, Compaction 체크포인트, trajectory 보조 파일도 정리합니다. `sessions.json`에서 아직 참조되는 파일은 보존됩니다.
|
||||
|
||||
- `--dry-run`: 쓰기 없이 얼마나 많은 항목이 제거/제한될지 미리 봅니다.
|
||||
- 텍스트 모드에서 dry-run은 세션별 작업 표(`Action`, `Key`, `Age`, `Model`, `Flags`)를 출력하므로 무엇이 유지되고 제거될지 확인할 수 있습니다.
|
||||
- `--dry-run`: 쓰지 않고 몇 개의 항목이 정리/제한될지 미리 봅니다.
|
||||
- 텍스트 모드에서 dry-run은 세션별 작업 표(`Action`, `Key`, `Age`, `Model`, `Flags`)를 출력하므로 무엇이 유지되고 무엇이 제거될지 확인할 수 있습니다.
|
||||
- `--enforce`: `session.maintenance.mode`가 `warn`이어도 유지 관리를 적용합니다.
|
||||
- `--fix-missing`: transcript 파일이 없고 아직 정상적으로는 age/count 기준에 걸리지 않더라도 해당 항목을 제거합니다.
|
||||
- `--active-key <key>`: 특정 활성 키를 디스크 예산 기반 제거에서 보호합니다. 그룹 세션 및 스레드 범위 채팅 세션 같은 지속 가능한 외부 대화 포인터도 age/count/disk-budget 유지 관리에서 보존됩니다.
|
||||
- `--agent <id>`: 구성된 에이전트 저장소 하나에 대해 cleanup을 실행합니다.
|
||||
- `--all-agents`: 구성된 모든 에이전트 저장소에 대해 cleanup을 실행합니다.
|
||||
- `--fix-missing`: transcript 파일이 없는 항목을 아직 일반적인 연령/개수 기준에서 제외되지 않더라도 제거합니다.
|
||||
- `--active-key <key>`: 특정 활성 키를 디스크 예산 기반 제거에서 보호합니다. 그룹 세션과 스레드 범위 채팅 세션 같은 내구성 있는 외부 대화 포인터도 연령/개수/디스크 예산 유지 관리에서 유지됩니다.
|
||||
- `--agent <id>`: 구성된 에이전트 저장소 하나에 대해 정리를 실행합니다.
|
||||
- `--all-agents`: 구성된 모든 에이전트 저장소에 대해 정리를 실행합니다.
|
||||
- `--store <path>`: 특정 `sessions.json` 파일을 대상으로 실행합니다.
|
||||
- `--json`: JSON 요약을 출력합니다. `--all-agents`와 함께 사용하면 출력에 저장소별 요약이 포함됩니다.
|
||||
- `--json`: JSON 요약을 출력합니다. `--all-agents`를 함께 사용하면 출력에 저장소별 요약이 포함됩니다.
|
||||
|
||||
Gateway에 도달할 수 있으면, 구성된 에이전트 저장소에 대한 non-dry-run cleanup은
|
||||
Gateway를 통해 전송되어 런타임 트래픽과 동일한 세션 저장소 writer를 공유합니다.
|
||||
저장소 파일의 명시적 오프라인 복구에는 `--store <path>`를 사용하세요.
|
||||
Gateway에 도달할 수 있으면, 구성된 에이전트 저장소에 대한 dry-run이 아닌 정리는
|
||||
Gateway를 통해 전송되어 런타임 트래픽과 동일한 세션 저장소 작성기를 공유합니다.
|
||||
저장소 파일을 명시적으로 오프라인 복구하려면 `--store <path>`를 사용하세요.
|
||||
|
||||
`openclaw sessions cleanup --all-agents --dry-run --json`:
|
||||
|
||||
|
||||
@ -1,54 +1,54 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw 버그에 대한 라이브 시각적 품질 보증 빌드 또는 실행
|
||||
- 풀 리퀘스트에 대한 사전 및 사후 검증 추가
|
||||
- OpenClaw 버그에 대한 라이브 시각적 QA 구축 또는 실행
|
||||
- 풀 리퀘스트에 전후 검증 추가하기
|
||||
- Discord, Slack, WhatsApp 또는 기타 실시간 전송 시나리오 추가
|
||||
- 스크린샷, 브라우저 자동화 또는 VNC 액세스가 필요한 QA 실행 디버깅
|
||||
summary: Mantis는 실제 전송 수단에서 OpenClaw 버그를 재현하고, 전후 증거를 캡처하며, PR에 아티팩트를 첨부하기 위한 시각적 엔드 투 엔드 검증 시스템입니다.
|
||||
summary: Mantis는 라이브 트랜스포트에서 OpenClaw 버그를 재현하고, 전후 증거를 캡처하며, 아티팩트를 PR에 첨부하기 위한 시각적 엔드투엔드 검증 시스템입니다.
|
||||
title: 사마귀
|
||||
x-i18n:
|
||||
generated_at: "2026-05-05T06:06:53Z"
|
||||
generated_at: "2026-05-05T08:25:48Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 26a9671135e38bf82d3627364f691f8d91cc8649ffc2e5fa782ebef474a44fa1
|
||||
source_hash: 6b287e2832e3e49de6b3cb65aeb1d381a36fc30ce9c94dc5b6b4d7e928c2706c
|
||||
source_path: concepts/mantis.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Mantis는 실제 런타임, 실제 전송, 그리고 눈에 보이는 증거가 필요한 버그를 위한 OpenClaw 종단 간 검증 시스템입니다. 알려진 문제가 있는 ref에 대해 시나리오를 실행하고, 증거를 캡처한 다음, 후보 ref에 대해 동일한 시나리오를 실행하고, 메인테이너가 PR이나 로컬 명령에서 검사할 수 있는 아티팩트로 비교 결과를 게시합니다.
|
||||
Mantis는 실제 런타임, 실제 전송 계층, 가시적인 증거가 필요한 버그를 위한 OpenClaw 엔드투엔드 검증 시스템입니다. 알려진 불량 ref에 대해 시나리오를 실행하고, 증거를 캡처한 뒤, 후보 ref에 대해 같은 시나리오를 실행하고, 관리자가 PR 또는 로컬 명령에서 검사할 수 있는 아티팩트로 비교 결과를 게시합니다.
|
||||
|
||||
Mantis는 Discord에서 시작합니다. Discord는 실제 봇 인증, 실제 길드 채널, 반응, 스레드, 네이티브 명령, 그리고 사람이 전송에 표시된 내용을 시각적으로 확인할 수 있는 브라우저 UI를 제공하는 고가치 첫 번째 레인이기 때문입니다.
|
||||
Mantis는 Discord부터 시작합니다. Discord는 실제 봇 인증, 실제 길드 채널, 반응, 스레드, 네이티브 명령, 그리고 사람이 전송 계층에 표시된 내용을 시각적으로 확인할 수 있는 브라우저 UI를 제공하므로 가치가 높은 첫 번째 레인을 제공하기 때문입니다.
|
||||
|
||||
## 목표
|
||||
|
||||
- GitHub 이슈나 PR의 버그를 사용자가 보는 것과 동일한 전송 형태로 재현합니다.
|
||||
- 수정 적용 전에 기준 ref에서 **before** 아티팩트를 캡처합니다.
|
||||
- 수정 적용 후 후보 ref에서 **after** 아티팩트를 캡처합니다.
|
||||
- 사용자가 보는 것과 같은 전송 계층 형태로 GitHub 이슈 또는 PR의 버그를 재현합니다.
|
||||
- 수정 사항을 적용하기 전에 기준 ref에서 **수정 전** 아티팩트를 캡처합니다.
|
||||
- 수정 사항을 적용한 후 후보 ref에서 **수정 후** 아티팩트를 캡처합니다.
|
||||
- 가능하면 Discord REST 반응 읽기나 채널 트랜스크립트 확인 같은 결정적 오라클을 사용합니다.
|
||||
- 버그에 눈에 보이는 UI 표면이 있을 때 스크린샷을 캡처합니다.
|
||||
- 버그에 표시되는 UI 표면이 있으면 스크린샷을 캡처합니다.
|
||||
- 에이전트가 제어하는 CLI에서 로컬로 실행하고 GitHub에서 원격으로 실행합니다.
|
||||
- 로그인, 브라우저 자동화, 또는 provider 인증이 막혔을 때 VNC 복구에 충분한 머신 상태를 보존합니다.
|
||||
- 로그인, 브라우저 자동화 또는 제공자 인증이 멈췄을 때 VNC 복구에 충분한 머신 상태를 보존합니다.
|
||||
- 실행이 차단되었거나, 수동 VNC 도움이 필요하거나, 완료되었을 때 운영자 Discord 채널에 간결한 상태를 게시합니다.
|
||||
|
||||
## 비목표
|
||||
## 범위 외
|
||||
|
||||
- Mantis는 단위 테스트를 대체하지 않습니다. 수정 사항이 이해된 뒤에는 일반적으로 Mantis 실행을 더 작은 회귀 테스트로 만들어야 합니다.
|
||||
- Mantis는 단위 테스트를 대체하지 않습니다. Mantis 실행은 보통 수정 사항을 이해한 뒤 더 작은 회귀 테스트가 되어야 합니다.
|
||||
- Mantis는 일반적인 빠른 CI 게이트가 아닙니다. 더 느리고, 라이브 자격 증명을 사용하며, 라이브 환경이 중요한 버그에만 사용됩니다.
|
||||
- Mantis는 정상 동작에 사람을 요구해서는 안 됩니다. 수동 VNC는 복구 경로이지 정상 경로가 아닙니다.
|
||||
- Mantis는 원시 시크릿을 아티팩트, 로그, 스크린샷, Markdown 보고서, 또는 PR 댓글에 저장하지 않습니다.
|
||||
- Mantis는 정상 동작에 사람이 필요하지 않아야 합니다. 수동 VNC는 정상 경로가 아니라 복구 경로입니다.
|
||||
- Mantis는 원시 시크릿을 아티팩트, 로그, 스크린샷, Markdown 보고서 또는 PR 댓글에 저장하지 않습니다.
|
||||
|
||||
## 소유권
|
||||
|
||||
Mantis는 OpenClaw QA 스택에 속합니다.
|
||||
Mantis는 OpenClaw QA 스택에 있습니다.
|
||||
|
||||
- OpenClaw는 `pnpm openclaw qa mantis` 아래의 시나리오 런타임, 전송 어댑터, 증거 스키마, 로컬 CLI를 소유합니다.
|
||||
- QA Lab은 라이브 전송 하네스 조각, 브라우저 캡처 헬퍼, 아티팩트 작성기를 소유합니다.
|
||||
- Crabbox는 원격 VM이 필요할 때 예열된 Linux 머신을 소유합니다.
|
||||
- OpenClaw는 `pnpm openclaw qa mantis` 아래의 시나리오 런타임, 전송 계층 어댑터, 증거 스키마, 로컬 CLI를 소유합니다.
|
||||
- QA Lab은 라이브 전송 계층 하네스 조각, 브라우저 캡처 헬퍼, 아티팩트 작성기를 소유합니다.
|
||||
- 원격 VM이 필요할 때 Crabbox는 예열된 Linux 머신을 소유합니다.
|
||||
- GitHub Actions는 원격 워크플로 진입점과 아티팩트 보존을 소유합니다.
|
||||
- ClawSweeper는 GitHub 댓글 라우팅을 소유합니다. 메인테이너 명령을 파싱하고, 워크플로를 디스패치하며, 최종 PR 댓글을 게시합니다.
|
||||
- OpenClaw 에이전트는 시나리오에 에이전트 기반 설정, 디버깅, 또는 막힌 상태 보고가 필요할 때 Codex를 통해 Mantis를 구동합니다.
|
||||
- ClawSweeper는 GitHub 댓글 라우팅을 소유합니다. 관리자 명령 파싱, 워크플로 디스패치, 최종 PR 댓글 게시를 담당합니다.
|
||||
- 시나리오에 에이전트 기반 설정, 디버깅 또는 멈춤 상태 보고가 필요할 때 OpenClaw 에이전트는 Codex를 통해 Mantis를 구동합니다.
|
||||
|
||||
이 경계는 전송 지식을 OpenClaw에, 머신 스케줄링을 Crabbox에, 메인테이너 워크플로 연결 로직을 ClawSweeper에 유지합니다.
|
||||
이 경계는 전송 계층 지식을 OpenClaw에, 머신 스케줄링을 Crabbox에, 관리자 워크플로 연결 로직을 ClawSweeper에 유지합니다.
|
||||
|
||||
## 명령 형태
|
||||
|
||||
@ -59,7 +59,7 @@ pnpm openclaw qa mantis discord-smoke \
|
||||
--output-dir .artifacts/qa-e2e/mantis/discord-smoke
|
||||
```
|
||||
|
||||
로컬 before 및 after 실행기는 다음 형태를 받습니다.
|
||||
로컬 수정 전/수정 후 러너는 다음 형태를 받습니다.
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis run \
|
||||
@ -70,26 +70,26 @@ pnpm openclaw qa mantis run \
|
||||
--output-dir .artifacts/qa-e2e/mantis/local-discord-status-reactions
|
||||
```
|
||||
|
||||
실행기는 출력 디렉터리 아래에 분리된 기준 및 후보 worktree를 만들고, 종속성을 설치하고, 각 ref를 빌드하고, `--allow-failures`로 시나리오를 실행한 다음 `baseline/`, `candidate/`, `comparison.json`, `mantis-report.md`를 작성합니다. 첫 번째 Discord 시나리오에서 검증 성공은 기준 상태가 `fail`이고 후보 상태가 `pass`임을 의미합니다.
|
||||
러너는 출력 디렉터리 아래에 분리된 기준 및 후보 워크트리를 만들고, 의존성을 설치하고, 각 ref를 빌드하고, `--allow-failures`로 시나리오를 실행한 뒤 `baseline/`, `candidate/`, `comparison.json`, `mantis-report.md`를 작성합니다. 첫 번째 Discord 시나리오에서 성공적인 검증은 기준 상태가 `fail`이고 후보 상태가 `pass`임을 의미합니다.
|
||||
|
||||
첫 번째 VM/브라우저 primitive는 데스크톱 smoke입니다.
|
||||
첫 번째 VM/브라우저 기본 기능은 데스크톱 스모크입니다.
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis desktop-browser-smoke \
|
||||
--output-dir .artifacts/qa-e2e/mantis/desktop-browser
|
||||
```
|
||||
|
||||
이 명령은 Crabbox 데스크톱 머신을 임대하거나 재사용하고, VNC 세션 안에서 보이는 브라우저를 시작하고, 데스크톱을 캡처하고, 아티팩트를 로컬 출력 디렉터리로 가져오며, 보고서에 재연결 명령을 작성합니다. 이 명령은 기본적으로 Hetzner provider를 사용합니다. Hetzner가 Mantis 레인에서 데스크톱/VNC 커버리지가 동작하는 첫 번째 provider이기 때문입니다. 다른 Crabbox 플릿에 대해 실행할 때는 `--provider`, `--crabbox-bin`, 또는 `OPENCLAW_MANTIS_CRABBOX_PROVIDER`로 재정의합니다.
|
||||
이 명령은 Crabbox 데스크톱 머신을 임대하거나 재사용하고, VNC 세션 안에서 표시되는 브라우저를 시작하고, 데스크톱을 캡처하고, 아티팩트를 로컬 출력 디렉터리로 가져오고, 보고서에 재연결 명령을 작성합니다. 이 명령은 Mantis 레인에서 작동하는 데스크톱/VNC 커버리지를 제공하는 첫 번째 제공자이므로 기본적으로 Hetzner 제공자를 사용합니다. 다른 Crabbox 플릿에 대해 실행할 때는 `--provider`, `--crabbox-bin` 또는 `OPENCLAW_MANTIS_CRABBOX_PROVIDER`로 재정의하세요.
|
||||
|
||||
유용한 데스크톱 smoke 플래그:
|
||||
유용한 데스크톱 스모크 플래그:
|
||||
|
||||
- `--lease-id <cbx_...>` 또는 `OPENCLAW_MANTIS_CRABBOX_LEASE_ID`는 예열된 데스크톱을 재사용합니다.
|
||||
- `--browser-url <url>`은 보이는 브라우저에서 열 페이지를 변경합니다.
|
||||
- `--html-file <path>`는 repo 로컬 HTML 아티팩트를 보이는 브라우저에서 렌더링합니다. Mantis는 실제 Crabbox 데스크톱을 통해 생성된 Discord 상태 반응 타임라인을 캡처하는 데 이것을 사용합니다.
|
||||
- `--keep-lease` 또는 `OPENCLAW_MANTIS_KEEP_VM=1`은 새로 생성되어 통과한 lease를 VNC 검사를 위해 열린 상태로 유지합니다. 실패한 실행은 lease가 생성된 경우 운영자가 재연결할 수 있도록 기본적으로 lease를 유지합니다.
|
||||
- `--class`, `--idle-timeout`, `--ttl`은 머신 크기와 lease 수명을 조정합니다.
|
||||
- `--browser-url <url>`은 표시되는 브라우저에서 열 페이지를 변경합니다.
|
||||
- `--html-file <path>`는 저장소 로컬 HTML 아티팩트를 표시되는 브라우저에서 렌더링합니다. Mantis는 실제 Crabbox 데스크톱을 통해 생성된 Discord 상태 반응 타임라인을 캡처하는 데 이것을 사용합니다.
|
||||
- `--keep-lease` 또는 `OPENCLAW_MANTIS_KEEP_VM=1`은 새로 생성되어 통과한 임대를 VNC 검사용으로 열린 상태로 유지합니다. 실패한 실행은 운영자가 다시 연결할 수 있도록 임대가 생성된 경우 기본적으로 임대를 유지합니다.
|
||||
- `--class`, `--idle-timeout`, `--ttl`은 머신 크기와 임대 수명을 조정합니다.
|
||||
|
||||
첫 번째 전체 데스크톱 전송 primitive는 Slack 데스크톱 smoke입니다.
|
||||
첫 번째 전체 데스크톱 전송 계층 기본 기능은 Slack 데스크톱 스모크입니다.
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis slack-desktop-smoke \
|
||||
@ -99,9 +99,9 @@ pnpm openclaw qa mantis slack-desktop-smoke \
|
||||
--keep-lease
|
||||
```
|
||||
|
||||
이 명령은 Crabbox 데스크톱 머신을 임대하거나 재사용하고, 현재 checkout을 VM에 동기화하고, 해당 VM 안에서 `pnpm openclaw qa slack`을 실행하고, VNC 브라우저에서 Slack Web을 열고, 보이는 데스크톱을 캡처하며, Slack QA 아티팩트와 VNC 스크린샷을 모두 로컬 출력 디렉터리로 복사합니다. 이것은 SUT OpenClaw Gateway와 브라우저가 같은 Linux 데스크톱 VM 안에 모두 존재하는 첫 번째 Mantis 형태입니다.
|
||||
이 명령은 Crabbox 데스크톱 머신을 임대하거나 재사용하고, 현재 체크아웃을 VM에 동기화하고, 해당 VM 안에서 `pnpm openclaw qa slack`을 실행하고, VNC 브라우저에서 Slack Web을 열고, 표시되는 데스크톱을 캡처하고, Slack QA 아티팩트와 VNC 스크린샷을 모두 로컬 출력 디렉터리로 복사합니다. 이것은 SUT OpenClaw Gateway와 브라우저가 모두 같은 Linux 데스크톱 VM 안에 있는 첫 번째 Mantis 형태입니다.
|
||||
|
||||
`--gateway-setup`을 사용하면 이 명령은 `$HOME/.openclaw-mantis/slack-openclaw`에 지속적인 폐기 가능 OpenClaw home을 준비하고, 선택한 채널에 대한 Slack Socket Mode 구성을 패치하고, 포트 `38973`에서 `openclaw gateway run`을 시작하며, VNC 세션에서 Chrome을 계속 실행합니다. 이것은 “Slack과 실행 중인 claw가 있는 Linux 데스크톱을 남겨 달라” 모드입니다. `--gateway-setup`이 생략되면 봇-대-봇 Slack QA 레인이 기본값으로 유지됩니다.
|
||||
`--gateway-setup`을 사용하면 명령은 `$HOME/.openclaw-mantis/slack-openclaw`에 지속형 일회용 OpenClaw 홈을 준비하고, 선택한 채널에 대한 Slack Socket Mode 구성을 패치하고, 포트 `38973`에서 `openclaw gateway run`을 시작하고, VNC 세션에서 Chrome을 계속 실행합니다. 이것은 "Slack과 claw가 실행 중인 Linux 데스크톱을 남겨 달라" 모드입니다. `--gateway-setup`을 생략하면 봇 대 봇 Slack QA 레인이 기본값으로 유지됩니다.
|
||||
|
||||
`--credential-source env`에 필요한 입력:
|
||||
|
||||
@ -109,32 +109,78 @@ pnpm openclaw qa mantis slack-desktop-smoke \
|
||||
- `OPENCLAW_QA_SLACK_DRIVER_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_SLACK_SUT_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_SLACK_SUT_APP_TOKEN`
|
||||
- 원격 모델 레인의 `OPENCLAW_LIVE_OPENAI_KEY`. 로컬에 `OPENAI_API_KEY`만 설정된 경우 Mantis는 Crabbox를 호출하기 전에 이를 `OPENCLAW_LIVE_OPENAI_KEY`에 매핑하여 Crabbox의 `OPENCLAW_*` env 전달이 VM 안으로 이를 전달할 수 있게 합니다.
|
||||
- 원격 모델 레인용 `OPENCLAW_LIVE_OPENAI_KEY`. 로컬에 `OPENAI_API_KEY`만 설정되어 있으면, Mantis는 Crabbox를 호출하기 전에 이를 `OPENCLAW_LIVE_OPENAI_KEY`로 매핑하여 Crabbox의 `OPENCLAW_*` env 전달이 VM 안으로 옮길 수 있게 합니다.
|
||||
|
||||
유용한 Slack 데스크톱 플래그:
|
||||
|
||||
- `--lease-id <cbx_...>`는 운영자가 이미 VNC를 통해 Slack Web에 로그인한 머신에 대해 다시 실행합니다.
|
||||
- `--gateway-setup`은 봇-대-봇 QA 레인만 실행하는 대신 VM에서 지속적인 OpenClaw Slack Gateway를 시작합니다.
|
||||
- `--slack-url <url>`은 특정 Slack Web URL을 엽니다. 지정하지 않으면 SUT 봇 토큰을 사용할 수 있을 때 Mantis가 Slack `auth.test`에서 `https://app.slack.com/client/<team>/<channel>`을 도출합니다.
|
||||
- `--slack-channel-id <id>`는 Gateway 설정에서 사용하는 Slack 채널 allowlist를 제어합니다.
|
||||
- `OPENCLAW_MANTIS_SLACK_BROWSER_PROFILE_DIR`은 VM 안의 지속적인 Chrome 프로필을 제어합니다. 기본값은 `$HOME/.config/openclaw-mantis/slack-chrome-profile`이므로, 같은 lease에서 다시 실행해도 수동 Slack Web 로그인이 유지됩니다.
|
||||
- `--gateway-setup`은 봇 대 봇 QA 레인만 실행하는 대신 VM에서 지속형 OpenClaw Slack Gateway를 시작합니다.
|
||||
- `--slack-url <url>`은 특정 Slack Web URL을 엽니다. 없으면 SUT 봇 토큰을 사용할 수 있을 때 Mantis가 Slack `auth.test`에서 `https://app.slack.com/client/<team>/<channel>`을 도출합니다.
|
||||
- `--slack-channel-id <id>`는 Gateway 설정에서 사용하는 Slack 채널 허용 목록을 제어합니다.
|
||||
- `OPENCLAW_MANTIS_SLACK_BROWSER_PROFILE_DIR`는 VM 안의 지속형 Chrome 프로필을 제어합니다. 기본값은 `$HOME/.config/openclaw-mantis/slack-chrome-profile`이므로 같은 임대에서 다시 실행할 때 수동 Slack Web 로그인이 유지됩니다.
|
||||
- `--credential-source convex --credential-role ci`는 직접 Slack env 토큰 대신 공유 자격 증명 풀을 사용합니다.
|
||||
- `--provider-mode`, `--model`, `--alt-model`, `--fast`는 Slack 라이브 레인으로 전달됩니다.
|
||||
|
||||
GitHub smoke 워크플로는 `Mantis Discord Smoke`입니다. 첫 번째 실제 시나리오의 before 및 after GitHub 워크플로는 `Mantis Discord Status Reactions`입니다. 이 워크플로는 다음을 받습니다.
|
||||
GitHub 스모크 워크플로는 `Mantis Discord Smoke`입니다. 첫 번째 실제 시나리오의 수정 전/수정 후 GitHub 워크플로는 `Mantis Discord Status Reactions`입니다. 다음을 받습니다.
|
||||
|
||||
- `baseline_ref`: queued-only 동작을 재현할 것으로 예상되는 ref입니다.
|
||||
- `candidate_ref`: `queued -> thinking -> done`을 표시할 것으로 예상되는 ref입니다.
|
||||
- `baseline_ref`: queued-only 동작을 재현할 것으로 예상되는 ref.
|
||||
- `candidate_ref`: `queued -> thinking -> done`을 표시할 것으로 예상되는 ref.
|
||||
|
||||
이 워크플로는 워크플로 하네스 ref를 checkout하고, 별도의 기준 및 후보 worktree를 빌드하고, 각 worktree에 대해 `discord-status-reactions-tool-only`를 실행하며, `baseline/`, `candidate/`, `comparison.json`, `mantis-report.md`를 Actions 아티팩트로 업로드합니다. 또한 Crabbox 데스크톱 브라우저에서 각 레인의 타임라인 HTML을 렌더링하고, 해당 VNC 스크린샷을 결정적 타임라인 PNG와 함께 PR 댓글에 게시합니다. 같은 PR 댓글은 VNC 브라우저 렌더 중 캡처된 데스크톱 MP4 녹화로 연결되며, 스크린샷은 빠른 검토를 위해 인라인으로 유지됩니다. 워크플로는 다음 Crabbox 바이너리 릴리스가 나오기 전에 현재 데스크톱/브라우저 lease 플래그를 사용할 수 있도록 `openclaw/crabbox` main에서 Crabbox CLI를 빌드합니다.
|
||||
워크플로 하네스 ref를 체크아웃하고, 별도의 기준 및 후보 워크트리를 빌드하고, 각 워크트리에 대해 `discord-status-reactions-tool-only`를 실행하고, `baseline/`, `candidate/`, `comparison.json`, `mantis-report.md`를 Actions 아티팩트로 업로드합니다. 또한 Crabbox 데스크톱 브라우저에서 각 레인의 타임라인 HTML을 렌더링하고, PR 댓글에서 결정적 타임라인 PNG 옆에 해당 VNC 스크린샷을 게시합니다. 같은 PR 댓글은 `crabbox media preview`로 생성된 가벼운 모션 트리밍 GIF 미리보기를 포함하고, 일치하는 모션 트리밍 MP4 클립으로 연결하며, 심층 검사를 위해 전체 데스크톱 MP4 파일을 유지합니다. 빠른 검토를 위해 스크린샷은 인라인으로 유지됩니다. 워크플로는 다음 Crabbox 바이너리 릴리스가 나오기 전에 현재 데스크톱/브라우저 임대 플래그를 사용할 수 있도록 `openclaw/crabbox` main에서 Crabbox CLI를 빌드합니다.
|
||||
|
||||
PR 댓글에서 status-reactions 실행을 직접 트리거할 수도 있습니다.
|
||||
`Mantis Scenario`는 범용 수동 진입점입니다. `scenario_id`, `candidate_ref`, 선택적 `baseline_ref`, 선택적 `pr_number`를 받은 뒤 시나리오가 소유한 워크플로를 디스패치합니다. 래퍼는 의도적으로 얇습니다. 시나리오 워크플로는 여전히 자체 전송 계층 설정, 자격 증명, VM 클래스, 예상 오라클, 아티팩트 매니페스트를 소유합니다.
|
||||
|
||||
`Mantis Slack Desktop Smoke`는 첫 번째 Slack VM 워크플로입니다. 별도 워크트리에서 신뢰할 수 있는 후보 ref를 체크아웃하고, Crabbox Linux 데스크톱을 임대하고, 해당 후보에 대해 `pnpm openclaw qa mantis slack-desktop-smoke --gateway-setup`을 실행하고, VNC 브라우저에서 Slack Web을 열고, 데스크톱을 녹화하고, `crabbox media preview`로 모션 트리밍 미리보기를 생성하고, 전체 아티팩트 디렉터리를 업로드하고, 선택적으로 대상 PR에 인라인 증거 댓글을 게시합니다. 봇 대 봇 Slack 트랜스크립트만 원할 때가 아니라 "Slack과 claw가 실행 중인 Linux 데스크톱"을 원할 때 이 레인을 사용하세요.
|
||||
|
||||
모든 PR 게시 시나리오는 보고서 옆에 `mantis-evidence.json`을 작성합니다. 이 스키마는 시나리오 코드와 GitHub 댓글 사이의 인계 지점입니다.
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "discord-status-reactions",
|
||||
"title": "Mantis Discord Status Reactions QA",
|
||||
"summary": "Human-readable top summary for the PR comment.",
|
||||
"scenario": "discord-status-reactions-tool-only",
|
||||
"comparison": {
|
||||
"baseline": { "sha": "...", "status": "fail", "expected": "queued-only" },
|
||||
"candidate": { "sha": "...", "status": "pass", "expected": "queued -> thinking -> done" },
|
||||
"pass": true
|
||||
},
|
||||
"artifacts": [
|
||||
{
|
||||
"kind": "timeline",
|
||||
"lane": "baseline",
|
||||
"label": "Baseline queued-only",
|
||||
"path": "baseline/timeline.png",
|
||||
"targetPath": "baseline.png",
|
||||
"alt": "Baseline Discord timeline",
|
||||
"width": 420
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
아티팩트 `path` 값은 매니페스트 디렉터리를 기준으로 한 상대 경로입니다. `targetPath` 값은 `qa-artifacts` 브랜치 게시 디렉터리 아래의 상대 경로입니다. 게시자는 경로 순회를 거부하고 선택적 미리보기나 동영상을 사용할 수 없을 때 `"required": false`로 표시된 항목을 건너뜁니다.
|
||||
|
||||
지원되는 아티팩트 종류:
|
||||
|
||||
- `timeline`: 결정적 시나리오 스크린샷으로, 보통 수정 전/수정 후입니다.
|
||||
- `desktopScreenshot`: VNC/브라우저 데스크톱 스크린샷입니다.
|
||||
- `motionPreview`: 데스크톱 녹화에서 생성한 인라인 애니메이션 GIF입니다.
|
||||
- `motionClip`: 정적 앞부분과 뒷부분을 제거한 모션 트리밍 MP4입니다.
|
||||
- `fullVideo`: 심층 검사용 전체 MP4 녹화입니다.
|
||||
- `metadata`: JSON/로그 사이드카입니다.
|
||||
- `report`: Markdown 보고서입니다.
|
||||
|
||||
재사용 가능한 게시자는 `scripts/mantis/publish-pr-evidence.mjs`입니다. 워크플로는 매니페스트, 대상 PR, `qa-artifacts` 대상 루트, 댓글 마커, Actions 아티팩트 URL, 실행 URL, 요청 소스를 함께 넘겨 이를 호출합니다. 선언된 아티팩트를 `qa-artifacts` 브랜치로 복사하고, 인라인 이미지/미리보기와 링크된 동영상이 포함된 요약 우선 PR 댓글을 만든 뒤, 기존 마커 댓글을 업데이트하거나 새로 만듭니다.
|
||||
|
||||
PR 댓글에서 상태 반응 실행을 직접 트리거할 수도 있습니다.
|
||||
|
||||
```text
|
||||
@Mantis discord status reactions
|
||||
```
|
||||
|
||||
댓글 트리거는 의도적으로 좁습니다. 이 트리거는 write, maintain, 또는 admin 접근 권한이 있는 사용자의 pull request 댓글에서만 실행되며, Discord 상태 반응 요청만 인식합니다. 기본적으로 알려진 문제가 있는 기준 ref와 현재 PR head SHA를 후보로 사용합니다. 메인테이너는 어느 ref든 재정의할 수 있습니다.
|
||||
댓글 트리거는 의도적으로 좁습니다. pull request 댓글에서 write, maintain 또는 admin 액세스 권한이 있는 사용자의 요청에 대해서만 실행되며, Discord 상태 반응 요청만 인식합니다. 기본적으로 알려진 불량 기준 ref와 현재 PR 헤드 SHA를 후보로 사용합니다. 관리자는 어느 ref든 재정의할 수 있습니다.
|
||||
|
||||
```text
|
||||
@Mantis discord status reactions baseline=origin/main candidate=HEAD
|
||||
@ -147,40 +193,40 @@ ClawSweeper 명령 예시:
|
||||
@clawsweeper verify e2e discord
|
||||
```
|
||||
|
||||
첫 번째 명령은 명시적이며 시나리오 중심입니다. 두 번째 명령은 나중에 라벨, 변경된 파일, ClawSweeper 검토 결과를 기반으로 PR이나 이슈를 권장 Mantis 시나리오에 매핑할 수 있습니다.
|
||||
첫 번째 명령은 명시적이며 시나리오에 초점을 둡니다. 두 번째 명령은 나중에 라벨, 변경된 파일, ClawSweeper 리뷰 결과를 바탕으로 PR이나 이슈를 권장 Mantis 시나리오에 매핑할 수 있습니다.
|
||||
|
||||
## 실행 수명 주기
|
||||
|
||||
1. 자격 증명을 획득합니다.
|
||||
2. VM을 할당하거나 재사용합니다.
|
||||
3. 시나리오에 UI 증거가 필요할 때 데스크톱/브라우저 프로필을 준비합니다.
|
||||
4. 기준 ref에 대한 깨끗한 checkout을 준비합니다.
|
||||
5. 종속성을 설치하고 시나리오에 필요한 것만 빌드합니다.
|
||||
6. 격리된 상태 디렉터리로 자식 OpenClaw Gateway를 시작합니다.
|
||||
7. 라이브 전송, provider, 모델, 브라우저 프로필을 구성합니다.
|
||||
4. 기준 ref용 깨끗한 체크아웃을 준비합니다.
|
||||
5. 의존성을 설치하고 시나리오에 필요한 것만 빌드합니다.
|
||||
6. 격리된 상태 디렉터리로 하위 OpenClaw Gateway를 시작합니다.
|
||||
7. 실제 전송, 제공자, 모델, 브라우저 프로필을 구성합니다.
|
||||
8. 시나리오를 실행하고 기준 증거를 캡처합니다.
|
||||
9. Gateway를 중지하고 로그를 보존합니다.
|
||||
10. 같은 VM에서 후보 ref를 준비합니다.
|
||||
11. 동일한 시나리오를 실행하고 후보 증거를 캡처합니다.
|
||||
11. 같은 시나리오를 실행하고 후보 증거를 캡처합니다.
|
||||
12. 오라클 결과와 시각적 증거를 비교합니다.
|
||||
13. Markdown, JSON, 로그, 스크린샷, 선택적 trace 아티팩트를 작성합니다.
|
||||
13. Markdown, JSON, 로그, 스크린샷, 선택적 추적 아티팩트를 작성합니다.
|
||||
14. GitHub Actions 아티팩트를 업로드합니다.
|
||||
15. 간결한 PR 또는 Discord 상태 메시지를 게시합니다.
|
||||
|
||||
시나리오는 서로 다른 두 가지 방식으로 실패할 수 있어야 합니다.
|
||||
시나리오는 두 가지 다른 방식으로 실패할 수 있어야 합니다.
|
||||
|
||||
- **버그 재현됨**: 기준이 예상된 방식으로 실패했습니다.
|
||||
- **하네스 실패**: 버그 오라클이 의미를 갖기 전에 환경 설정, 자격 증명, Discord API, 브라우저, 또는 provider가 실패했습니다.
|
||||
- **하네스 실패**: 버그 오라클이 의미를 갖기 전에 환경 설정, 자격 증명, Discord API, 브라우저 또는 제공자가 실패했습니다.
|
||||
|
||||
최종 보고서는 메인테이너가 불안정한 환경을 제품 동작과 혼동하지 않도록 이 사례들을 분리해야 합니다.
|
||||
최종 보고서는 유지관리자가 불안정한 환경을 제품 동작과 혼동하지 않도록 이 경우들을 분리해야 합니다.
|
||||
|
||||
## Discord MVP
|
||||
|
||||
첫 번째 시나리오는 소스 답장 전달 모드가 `message_tool_only`인 길드 채널의 Discord 상태 반응을 대상으로 해야 합니다.
|
||||
|
||||
이것이 좋은 Mantis 시드인 이유:
|
||||
좋은 Mantis 시드인 이유:
|
||||
|
||||
- 트리거 메시지의 반응으로 Discord에서 보입니다.
|
||||
- 트리거 메시지의 반응으로 Discord에 표시됩니다.
|
||||
- Discord 메시지 반응 상태를 통한 강력한 REST 오라클이 있습니다.
|
||||
- 실제 OpenClaw Gateway, Discord 봇 인증, 메시지 디스패치, 소스 답장 전달 모드, 상태 반응 상태, 모델 턴 수명 주기를 실행합니다.
|
||||
- 첫 구현을 정직하게 유지할 만큼 범위가 좁습니다.
|
||||
@ -216,9 +262,9 @@ evidence:
|
||||
screenshotMessageRow: true
|
||||
```
|
||||
|
||||
기준 증거는 tool-only 모드에서 queued 확인 반응은 있지만 수명 주기 전환은 없음을 보여야 합니다. 후보 증거는 `messages.statusReactions.enabled`가 명시적으로 true일 때 수명 주기 상태 반응이 실행됨을 보여야 합니다.
|
||||
기준 증거는 대기열에 들어간 확인 반응은 보이지만 도구 전용 모드에서 수명 주기 전환은 없음을 보여야 합니다. 후보 증거는 `messages.statusReactions.enabled`가 명시적으로 true일 때 수명 주기 상태 반응이 실행됨을 보여야 합니다.
|
||||
|
||||
실행 가능한 첫 번째 slice는 opt-in Discord 라이브 QA 시나리오입니다.
|
||||
실행 가능한 첫 조각은 옵트인 Discord 라이브 QA 시나리오입니다.
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa discord \
|
||||
@ -230,24 +276,24 @@ pnpm openclaw qa discord \
|
||||
--output-dir .artifacts/qa-e2e/mantis/discord-status-reactions-candidate
|
||||
```
|
||||
|
||||
이 명령은 항상 켜진 길드 처리, `visibleReplies:
|
||||
"message_tool"`, `ackReaction: "👀"`, 그리고 명시적 상태 반응으로 SUT를 구성합니다. 오라클은 실제 Discord 트리거 메시지를 폴링하고 관측된 시퀀스 `👀 -> 🤔 -> 👍`를 기대합니다. 아티팩트에는 `discord-qa-reaction-timelines.json`, `discord-status-reactions-tool-only-timeline.html`, 그리고 `discord-status-reactions-tool-only-timeline.png`가 포함됩니다.
|
||||
이는 SUT를 항상 켜진 길드 처리, `visibleReplies:
|
||||
"message_tool"`, `ackReaction: "👀"`, 명시적 상태 반응으로 구성합니다. 오라클은 실제 Discord 트리거 메시지를 폴링하고 관찰된 시퀀스 `👀 -> 🤔 -> 👍`를 기대합니다. 아티팩트에는 `discord-qa-reaction-timelines.json`, `discord-status-reactions-tool-only-timeline.html`, `discord-status-reactions-tool-only-timeline.png`가 포함됩니다.
|
||||
|
||||
## 기존 QA 구성 요소
|
||||
|
||||
Mantis는 처음부터 시작하는 대신 기존 비공개 QA 스택을 기반으로 구축해야 합니다.
|
||||
|
||||
- `pnpm openclaw qa discord`는 이미 드라이버 및 SUT 봇으로 라이브 Discord 레인을 실행합니다.
|
||||
- 라이브 전송 러너는 이미 `.artifacts/qa-e2e/` 아래에 보고서와 관측 메시지 아티팩트를 씁니다.
|
||||
- 라이브 전송 러너는 이미 `.artifacts/qa-e2e/` 아래에 보고서와 관찰된 메시지 아티팩트를 작성합니다.
|
||||
- Convex 자격 증명 임대는 이미 공유 라이브 전송 자격 증명에 대한 독점 접근을 제공합니다.
|
||||
- 브라우저 제어 서비스는 이미 스크린샷, 스냅샷, headless 관리 프로필, 원격 CDP 프로필을 지원합니다.
|
||||
- QA Lab에는 이미 전송 형태 테스트를 위한 디버거 UI와 버스가 있습니다.
|
||||
- 브라우저 제어 서비스는 이미 스크린샷, 스냅샷, 헤드리스 관리 프로필, 원격 CDP 프로필을 지원합니다.
|
||||
- QA Lab에는 이미 전송 형태 테스트용 디버거 UI와 버스가 있습니다.
|
||||
|
||||
첫 번째 Mantis 구현은 이러한 구성 요소 위에 얇은 전/후 러너와 하나의 시각적 증거 레이어를 더한 형태일 수 있습니다.
|
||||
첫 Mantis 구현은 이러한 구성 요소 위의 얇은 전/후 러너와 하나의 시각적 증거 레이어가 될 수 있습니다.
|
||||
|
||||
## 증거 모델
|
||||
|
||||
모든 실행은 안정적인 아티팩트 디렉터리를 씁니다.
|
||||
모든 실행은 안정적인 아티팩트 디렉터리를 작성합니다.
|
||||
|
||||
```text
|
||||
.artifacts/qa-e2e/mantis/<run-id>/
|
||||
@ -267,65 +313,65 @@ Mantis는 처음부터 시작하는 대신 기존 비공개 QA 스택을 기반
|
||||
run.log
|
||||
```
|
||||
|
||||
`mantis-summary.json`은 기계가 읽을 수 있는 단일 진실 공급원이어야 합니다. Markdown 보고서는 PR 댓글과 사람의 검토를 위한 것입니다.
|
||||
`mantis-summary.json`은 기계가 읽을 수 있는 단일 진실 공급원이어야 합니다. Markdown 보고서는 PR 댓글과 사람의 검토용입니다.
|
||||
|
||||
요약에는 다음이 포함되어야 합니다.
|
||||
|
||||
- 테스트한 refs와 SHA
|
||||
- 전송 및 시나리오 ID
|
||||
- 머신 제공자와 머신 ID 또는 임대 ID
|
||||
- 비밀 값 없는 자격 증명 출처
|
||||
- baseline 결과
|
||||
- candidate 결과
|
||||
- 버그가 baseline에서 재현되었는지 여부
|
||||
- candidate가 이를 수정했는지 여부
|
||||
- 테스트한 refs 및 SHAs
|
||||
- 전송 및 시나리오 id
|
||||
- 머신 제공자 및 머신 id 또는 임대 id
|
||||
- 시크릿 값을 제외한 자격 증명 출처
|
||||
- 기준 결과
|
||||
- 후보 결과
|
||||
- 기준에서 버그가 재현되었는지 여부
|
||||
- 후보가 이를 수정했는지 여부
|
||||
- 아티팩트 경로
|
||||
- 정리된 설정 또는 정리 문제
|
||||
|
||||
스크린샷은 증거이지 비밀이 아닙니다. 그래도 비공개 채널 이름, 사용자 이름, 메시지 내용이 나타날 수 있으므로 redact 규율이 필요합니다. 공개 PR의 경우 redact 방식이 더 견고해질 때까지 인라인 이미지보다 GitHub Actions 아티팩트 링크를 선호하세요.
|
||||
스크린샷은 증거이지 시크릿이 아닙니다. 그래도 비공개 채널 이름, 사용자 이름 또는 메시지 내용이 나타날 수 있으므로 수정 원칙이 필요합니다. 공개 PR의 경우 수정 방식이 더 강해질 때까지 인라인 이미지보다 GitHub Actions 아티팩트 링크를 선호합니다.
|
||||
|
||||
## 브라우저와 VNC
|
||||
## 브라우저 및 VNC
|
||||
|
||||
브라우저 레인에는 두 가지 모드가 있습니다.
|
||||
|
||||
- **Headless 자동화**: CI의 기본값입니다. Chrome은 CDP가 활성화된 상태로 실행되며, Playwright 또는 OpenClaw 브라우저 제어가 스크린샷을 캡처합니다.
|
||||
- **VNC 구조**: 로그인, MFA, Discord 자동화 방지, 또는 시각적 디버깅에 사람이 필요할 때 동일한 VM에서 활성화됩니다.
|
||||
- **헤드리스 자동화**: CI의 기본값입니다. Chrome은 CDP가 활성화된 상태로 실행되며, Playwright 또는 OpenClaw 브라우저 제어가 스크린샷을 캡처합니다.
|
||||
- **VNC 구조**: 로그인, MFA, Discord 자동화 방지 또는 시각적 디버깅에 사람이 필요할 때 같은 VM에서 활성화됩니다.
|
||||
|
||||
Discord 관찰자 브라우저 프로필은 매 실행마다 로그인하지 않아도 될 만큼 지속적이어야 하지만, 개인 브라우저 상태와는 격리되어야 합니다. 프로필은 개발자 노트북이 아니라 Mantis 머신 풀에 속합니다.
|
||||
|
||||
Mantis가 멈추면 다음 내용을 포함한 Discord 상태 메시지를 게시합니다.
|
||||
Mantis가 멈추면 다음이 포함된 Discord 상태 메시지를 게시합니다.
|
||||
|
||||
- 실행 ID
|
||||
- 시나리오 ID
|
||||
- 실행 id
|
||||
- 시나리오 id
|
||||
- 머신 제공자
|
||||
- 아티팩트 디렉터리
|
||||
- 가능한 경우 VNC 또는 noVNC 연결 지침
|
||||
- 짧은 차단 요인 설명
|
||||
- 사용 가능한 경우 VNC 또는 noVNC 연결 지침
|
||||
- 짧은 차단 사유 텍스트
|
||||
|
||||
첫 번째 비공개 배포는 이러한 메시지를 기존 운영자 채널에 게시하고, 나중에 전용 Mantis 채널로 이동할 수 있습니다.
|
||||
첫 비공개 배포는 이러한 메시지를 기존 운영자 채널에 게시할 수 있으며, 나중에 전용 Mantis 채널이 생기면 그곳으로 이동할 수 있습니다.
|
||||
|
||||
## 머신
|
||||
|
||||
Mantis는 첫 번째 원격 구현에서 Crabbox를 통한 AWS를 선호해야 합니다. Crabbox는 예열된 머신, 임대 추적, 하이드레이션, 로그, 결과, 정리를 제공합니다. AWS 용량이 너무 느리거나 사용할 수 없다면 동일한 머신 인터페이스 뒤에 Hetzner 제공자를 추가하세요.
|
||||
Mantis는 첫 원격 구현에서 Crabbox를 통한 AWS를 선호해야 합니다. Crabbox는 예열된 머신, 임대 추적, 하이드레이션, 로그, 결과, 정리를 제공합니다. AWS 용량이 너무 느리거나 사용할 수 없으면 같은 머신 인터페이스 뒤에 Hetzner 제공자를 추가합니다.
|
||||
|
||||
최소 VM 요구사항:
|
||||
최소 VM 요구 사항:
|
||||
|
||||
- 데스크톱이 가능한 Chrome 또는 Chromium 설치가 있는 Linux
|
||||
- 데스크톱 사용이 가능한 Chrome 또는 Chromium 설치가 있는 Linux
|
||||
- 브라우저 자동화를 위한 CDP 접근
|
||||
- 구조를 위한 VNC 또는 noVNC
|
||||
- 구조용 VNC 또는 noVNC
|
||||
- Node 22 및 pnpm
|
||||
- OpenClaw 체크아웃 및 의존성 캐시
|
||||
- Playwright를 사용할 때 Playwright Chromium 브라우저 캐시
|
||||
- OpenClaw Gateway 하나, 브라우저 하나, 모델 실행 하나를 위한 충분한 CPU와 메모리
|
||||
- OpenClaw Gateway 하나, 브라우저 하나, 모델 실행 하나에 충분한 CPU 및 메모리
|
||||
- Discord, GitHub, 모델 제공자, 자격 증명 브로커로의 아웃바운드 접근
|
||||
|
||||
VM은 예상된 자격 증명 또는 브라우저 프로필 저장소 밖에 수명이 긴 원시 비밀을 보관해서는 안 됩니다.
|
||||
VM은 예상된 자격 증명 또는 브라우저 프로필 저장소 외부에 장기 지속 원시 시크릿을 보관해서는 안 됩니다.
|
||||
|
||||
## 비밀
|
||||
## 시크릿
|
||||
|
||||
비밀은 원격 실행의 경우 GitHub 조직 또는 저장소 secrets에, 로컬 실행의 경우 로컬 운영자가 제어하는 비밀 파일에 저장됩니다.
|
||||
시크릿은 원격 실행의 경우 GitHub 조직 또는 저장소 시크릿에, 로컬 실행의 경우 로컬 운영자가 제어하는 시크릿 파일에 둡니다.
|
||||
|
||||
권장 비밀 이름:
|
||||
권장 시크릿 이름:
|
||||
|
||||
- `OPENCLAW_QA_DISCORD_MANTIS_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_DISCORD_DRIVER_BOT_TOKEN`
|
||||
@ -339,26 +385,26 @@ VM은 예상된 자격 증명 또는 브라우저 프로필 저장소 밖에 수
|
||||
- `OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR`
|
||||
- `OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR_TOKEN`
|
||||
|
||||
장기적으로 Convex 자격 증명 풀은 라이브 전송 자격 증명의 일반적인 출처로 남아 있어야 합니다. GitHub secrets는 브로커와 fallback 레인을 부트스트랩합니다. Discord 상태 반응 워크플로는 Mantis Crabbox secrets를 Crabbox CLI가 기대하는 `CRABBOX_COORDINATOR` 및 `CRABBOX_COORDINATOR_TOKEN` 환경 변수로 다시 매핑합니다. 일반 `CRABBOX_*` GitHub secret 이름은 호환성 fallback으로 계속 허용됩니다.
|
||||
장기적으로 Convex 자격 증명 풀은 라이브 전송 자격 증명의 일반 출처로 유지되어야 합니다. GitHub 시크릿은 브로커와 대체 레인을 부트스트랩합니다. Discord 상태 반응 워크플로는 Mantis Crabbox 시크릿을 Crabbox CLI가 기대하는 `CRABBOX_COORDINATOR` 및 `CRABBOX_COORDINATOR_TOKEN` 환경 변수로 다시 매핑합니다. 일반 `CRABBOX_*` GitHub 시크릿 이름은 호환성 대체 수단으로 계속 허용됩니다.
|
||||
|
||||
Mantis 러너는 절대 다음을 출력해서는 안 됩니다.
|
||||
Mantis 러너는 다음을 절대 출력해서는 안 됩니다.
|
||||
|
||||
- Discord 봇 토큰
|
||||
- 제공자 API 키
|
||||
- 브라우저 쿠키
|
||||
- 인증 프로필 내용
|
||||
- VNC 비밀번호
|
||||
- 원시 자격 증명 payload
|
||||
- 원시 자격 증명 페이로드
|
||||
|
||||
공개 아티팩트 업로드는 봇, 길드, 채널, 메시지 ID 같은 Discord 대상 메타데이터도 redact해야 합니다. GitHub smoke 워크플로는 이러한 이유로 `OPENCLAW_QA_REDACT_PUBLIC_METADATA=1`을 활성화합니다.
|
||||
공개 아티팩트 업로드는 봇, 길드, 채널, 메시지 id 같은 Discord 대상 메타데이터도 수정해야 합니다. GitHub 스모크 워크플로는 이 이유로 `OPENCLAW_QA_REDACT_PUBLIC_METADATA=1`을 활성화합니다.
|
||||
|
||||
토큰이 실수로 이슈, PR, 채팅, 로그에 붙여넣어진 경우 새 비밀이 저장된 뒤 해당 토큰을 교체하세요.
|
||||
토큰이 실수로 이슈, PR, 채팅 또는 로그에 붙여 넣어지면 새 시크릿이 저장된 후 이를 교체합니다.
|
||||
|
||||
## GitHub 아티팩트와 PR 댓글
|
||||
## GitHub 아티팩트 및 PR 댓글
|
||||
|
||||
Mantis 워크플로는 전체 증거 번들을 수명이 짧은 Actions 아티팩트로 업로드해야 합니다. 워크플로가 버그 보고서 또는 수정 PR을 위해 실행되는 경우, redact된 PNG 스크린샷도 `qa-artifacts` 브랜치에 게시하고 해당 버그 또는 수정 PR에 인라인 전/후 스크린샷이 포함된 댓글을 upsert해야 합니다. 기본 증거를 일반 QA 자동화 PR에만 게시하지 마세요. 원시 로그, 관측 메시지, 기타 큰 증거는 Actions 아티팩트에 남깁니다.
|
||||
Mantis 워크플로는 전체 증거 번들을 단기 Actions 아티팩트로 업로드해야 합니다. 워크플로가 버그 보고서 또는 수정 PR에 대해 실행될 때는 수정된 PNG 스크린샷도 `qa-artifacts` 브랜치에 게시하고, 해당 버그 또는 수정 PR에 인라인 전/후 스크린샷이 포함된 댓글을 upsert해야 합니다. 기본 증거를 일반 QA 자동화 PR에만 게시하지 마세요. 원시 로그, 관찰된 메시지, 기타 큰 증거는 Actions 아티팩트에 둡니다.
|
||||
|
||||
프로덕션 워크플로는 해당 댓글을 `github-actions[bot]`가 아니라 Mantis GitHub App으로 게시해야 합니다. 앱 ID와 private key를 `MANTIS_GITHUB_APP_ID` 및 `MANTIS_GITHUB_APP_PRIVATE_KEY` GitHub Actions secrets로 저장하세요. 워크플로는 숨겨진 마커를 upsert 키로 사용하고, 토큰이 편집할 수 있으면 해당 댓글을 업데이트하며, 더 오래된 봇 소유 마커를 편집할 수 없으면 Mantis 소유의 새 댓글을 만듭니다.
|
||||
프로덕션 워크플로는 이러한 댓글을 `github-actions[bot]`이 아니라 Mantis GitHub App으로 게시해야 합니다. 앱 id와 비공개 키를 `MANTIS_GITHUB_APP_ID` 및 `MANTIS_GITHUB_APP_PRIVATE_KEY` GitHub Actions 시크릿으로 저장합니다. 워크플로는 숨겨진 마커를 upsert 키로 사용하고, 토큰이 편집할 수 있으면 해당 댓글을 업데이트하며, 오래된 봇 소유 마커를 편집할 수 없으면 새 Mantis 소유 댓글을 만듭니다.
|
||||
|
||||
PR 댓글은 짧고 시각적이어야 합니다.
|
||||
|
||||
@ -380,60 +426,65 @@ candidate showed the expected queued -> thinking -> done sequence.
|
||||
| <inline screenshot> | <inline screenshot> |
|
||||
```
|
||||
|
||||
하네스 실패 때문에 실행이 실패한 경우, 댓글은 candidate가 실패했다고 암시하지 말고 그 사실을 말해야 합니다.
|
||||
하네스 실패 때문에 실행이 실패한 경우, 댓글은 후보가 실패했다고 암시하는 대신 그 사실을 말해야 합니다.
|
||||
|
||||
## 비공개 배포 참고 사항
|
||||
|
||||
비공개 배포에는 이미 Mantis Discord 애플리케이션이 있을 수 있습니다. 올바른 봇 권한이 있고 안전하게 교체할 수 있다면 다른 앱을 만들지 말고 해당 애플리케이션을 재사용하세요.
|
||||
비공개 배포에는 이미 Mantis Discord 애플리케이션이 있을 수 있습니다. 해당 애플리케이션에 올바른 봇 권한이 있고 안전하게 교체할 수 있다면 다른 앱을 만들지 말고 재사용하세요.
|
||||
|
||||
초기 운영자 알림 채널은 secrets 또는 배포 구성을 통해 설정하세요. 먼저 기존 maintainer 또는 운영 채널을 가리키게 한 뒤, 전용 Mantis 채널이 생기면 그곳으로 이동할 수 있습니다.
|
||||
초기 운영자 알림 채널은 시크릿 또는 배포 구성을 통해 설정합니다. 처음에는 기존 유지관리자 또는 운영 채널을 가리킬 수 있으며, 전용 Mantis 채널이 생기면 그곳으로 이동할 수 있습니다.
|
||||
|
||||
이 문서에 길드 ID, 채널 ID, 봇 토큰, 브라우저 쿠키, VNC 비밀번호를 넣지 마세요. GitHub secrets, 자격 증명 브로커, 또는 운영자의 로컬 비밀 저장소에 저장하세요.
|
||||
이 문서에 길드 id, 채널 id, 봇 토큰, 브라우저 쿠키 또는 VNC 비밀번호를 넣지 마세요. GitHub 시크릿, 자격 증명 브로커 또는 운영자의 로컬 시크릿 저장소에 저장하세요.
|
||||
|
||||
## 시나리오 추가하기
|
||||
## 시나리오 추가
|
||||
|
||||
Mantis 시나리오는 다음을 선언해야 합니다.
|
||||
|
||||
- ID와 제목
|
||||
- id 및 제목
|
||||
- 전송
|
||||
- 필요한 자격 증명
|
||||
- baseline ref 정책
|
||||
- candidate ref 정책
|
||||
- 기준 ref 정책
|
||||
- 후보 ref 정책
|
||||
- OpenClaw 구성 패치
|
||||
- 설정 단계
|
||||
- 자극
|
||||
- 예상 baseline 오라클
|
||||
- 예상 candidate 오라클
|
||||
- 예상 기준 오라클
|
||||
- 예상 후보 오라클
|
||||
- 시각적 캡처 대상
|
||||
- timeout 예산
|
||||
- 제한 시간 예산
|
||||
- 정리 단계
|
||||
|
||||
시나리오는 작고 타입이 지정된 오라클을 선호해야 합니다.
|
||||
시나리오는 작고 타입화된 오라클을 선호해야 합니다.
|
||||
|
||||
- 반응 버그를 위한 Discord 반응 상태
|
||||
- 스레딩 버그를 위한 Discord 메시지 참조
|
||||
- Slack 버그를 위한 Slack 스레드 ts 및 반응 API 상태
|
||||
- 이메일 버그를 위한 이메일 메시지 ID와 헤더
|
||||
- UI가 유일하게 신뢰할 수 있는 관측 대상일 때 브라우저 스크린샷
|
||||
- 반응 버그용 Discord 반응 상태
|
||||
- 스레딩 버그용 Discord 메시지 참조
|
||||
- Slack 버그용 Slack 스레드 ts 및 반응 API 상태
|
||||
- 이메일 버그용 이메일 메시지 id 및 헤더
|
||||
- UI가 유일하게 신뢰할 수 있는 관찰 대상일 때 브라우저 스크린샷
|
||||
|
||||
비전 검사는 추가적이어야 합니다. 플랫폼 API가 버그를 증명할 수 있다면 API를 통과/실패 오라클로 사용하고 스크린샷은 사람의 신뢰를 위해 유지하세요.
|
||||
비전 검사는 부가적이어야 합니다. 플랫폼 API로 버그를 증명할 수 있다면 API를 통과/실패 오라클로 사용하고 스크린샷은 사람의 확신을 위해 유지하세요.
|
||||
|
||||
## 제공자 확장
|
||||
|
||||
Discord 이후 동일한 러너는 다음을 추가할 수 있습니다.
|
||||
Discord 이후 같은 러너는 다음을 추가할 수 있습니다:
|
||||
|
||||
- Slack: 반응, 스레드, 앱 멘션, 모달, 파일 업로드.
|
||||
- 이메일: 커넥터만으로 충분하지 않은 경우 `gog`를 사용하는 Gmail 인증 및 메시지 스레딩.
|
||||
- 이메일: 커넥터만으로 충분하지 않은 경우 `gog`를 사용한 Gmail 인증 및 메시지
|
||||
스레딩.
|
||||
- WhatsApp: QR 로그인, 재식별, 메시지 전달, 미디어, 반응.
|
||||
- Telegram: 그룹 멘션 게이팅, 명령, 가능한 경우 반응.
|
||||
- Matrix: 암호화된 방, 스레드 또는 답장 관계, 재시작 재개.
|
||||
- Telegram: 그룹 멘션 게이팅, 명령, 사용 가능한 경우 반응.
|
||||
- Matrix: 암호화된 방, 스레드 또는 답글 관계, 재시작 후 재개.
|
||||
|
||||
각 전송에는 저렴한 smoke 시나리오 하나와 하나 이상의 버그 클래스 시나리오가 있어야 합니다. 비용이 큰 시각적 시나리오는 opt-in으로 유지해야 합니다.
|
||||
각 전송 방식에는 비용이 낮은 스모크 시나리오 하나와 하나 이상의 버그 유형
|
||||
시나리오가 있어야 합니다. 비용이 큰 시각적 시나리오는 선택 사항으로 유지해야 합니다.
|
||||
|
||||
## 미해결 질문
|
||||
|
||||
- 기존 Mantis 봇을 재사용할 때 어떤 Discord 봇이 드라이버가 되어야 하고 어떤 봇이 SUT가 되어야 하나요?
|
||||
- 관찰자 브라우저 로그인은 첫 단계에서 사람 Discord 계정, 테스트 계정, 또는 봇이 읽을 수 있는 REST 증거만 사용해야 하나요?
|
||||
- GitHub는 PR의 Mantis 아티팩트를 얼마나 오래 보존해야 하나요?
|
||||
- ClawSweeper는 언제 maintainer 명령을 기다리는 대신 Mantis를 자동으로 추천해야 하나요?
|
||||
- 공개 PR에 업로드하기 전에 스크린샷을 redact하거나 crop해야 하나요?
|
||||
- 기존 Mantis 봇을 재사용할 때 어떤 Discord 봇을 드라이버로 사용하고,
|
||||
어떤 봇을 SUT로 사용해야 합니까?
|
||||
- 관찰자 브라우저 로그인은 첫 단계에서 인간 Discord 계정, 테스트 계정,
|
||||
또는 봇이 읽을 수 있는 REST 증거만 사용해야 합니까?
|
||||
- GitHub는 PR의 Mantis 아티팩트를 얼마나 오래 보관해야 합니까?
|
||||
- ClawSweeper는 언제 유지관리자 명령을 기다리지 않고 Mantis를 자동으로
|
||||
권장해야 합니까?
|
||||
- 공개 PR에 업로드하기 전에 스크린샷을 삭제 처리하거나 잘라내야 합니까?
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
---
|
||||
read_when:
|
||||
- 진단 마이그레이션 추가 또는 수정
|
||||
- 호환성이 깨지는 구성 변경 사항 도입
|
||||
- doctor 마이그레이션 추가 또는 수정
|
||||
- 호환성을 깨는 구성 변경 도입
|
||||
sidebarTitle: Doctor
|
||||
summary: 'Doctor 명령: 상태 점검, 구성 마이그레이션 및 복구 단계'
|
||||
summary: 'Doctor 명령: 상태 검사, 설정 마이그레이션 및 복구 단계'
|
||||
title: 진단
|
||||
x-i18n:
|
||||
generated_at: "2026-05-05T01:46:14Z"
|
||||
generated_at: "2026-05-05T08:25:34Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 3e374f91d00d4b43a3852de6f746b044471e80af936d464a789061a31cadd09d
|
||||
source_hash: 360f9f7a349e4633ff61d526f1eb5b668b595b4f35c5e0fd2a314715a0599c4c
|
||||
source_path: gateway/doctor.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
`openclaw doctor`는 OpenClaw의 복구 + 마이그레이션 도구입니다. 오래된 구성/상태를 수정하고, 상태를 확인하며, 실행 가능한 복구 단계를 제공합니다.
|
||||
`openclaw doctor`는 OpenClaw의 복구 + 마이그레이션 도구입니다. 오래된 구성/상태를 수정하고, 상태를 점검하며, 실행 가능한 복구 단계를 제공합니다.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
@ -30,7 +30,7 @@ openclaw doctor
|
||||
openclaw doctor --yes
|
||||
```
|
||||
|
||||
프롬프트 없이 기본값을 수락합니다(해당되는 경우 재시작/서비스/샌드박스 복구 단계 포함).
|
||||
프롬프트 없이 기본값을 승인합니다(해당되는 경우 재시작/서비스/샌드박스 복구 단계 포함).
|
||||
|
||||
</Tab>
|
||||
<Tab title="--repair">
|
||||
@ -46,7 +46,7 @@ openclaw doctor
|
||||
openclaw doctor --repair --force
|
||||
```
|
||||
|
||||
공격적인 복구도 적용합니다(사용자 지정 슈퍼바이저 구성을 덮어씀).
|
||||
적극적인 복구도 적용합니다(사용자 지정 슈퍼바이저 구성을 덮어씀).
|
||||
|
||||
</Tab>
|
||||
<Tab title="--non-interactive">
|
||||
@ -54,7 +54,7 @@ openclaw doctor
|
||||
openclaw doctor --non-interactive
|
||||
```
|
||||
|
||||
프롬프트 없이 실행하고 안전한 마이그레이션만 적용합니다(구성 정규화 + 디스크상의 상태 이동). 사람의 확인이 필요한 재시작/서비스/샌드박스 작업은 건너뜁니다. 기존 상태 마이그레이션은 감지되면 자동으로 실행됩니다.
|
||||
프롬프트 없이 실행하고 안전한 마이그레이션만 적용합니다(구성 정규화 + 디스크의 상태 이동). 사람이 확인해야 하는 재시작/서비스/샌드박스 작업은 건너뜁니다. 레거시 상태 마이그레이션은 감지되면 자동으로 실행됩니다.
|
||||
|
||||
</Tab>
|
||||
<Tab title="--deep">
|
||||
@ -62,7 +62,7 @@ openclaw doctor
|
||||
openclaw doctor --deep
|
||||
```
|
||||
|
||||
추가 Gateway 설치를 찾기 위해 시스템 서비스를 스캔합니다(launchd/systemd/schtasks).
|
||||
추가 Gateway 설치를 시스템 서비스에서 스캔합니다(launchd/systemd/schtasks).
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@ -73,123 +73,124 @@ openclaw doctor
|
||||
cat ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
## 수행 작업(요약)
|
||||
## 수행하는 작업(요약)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="상태, UI, 업데이트">
|
||||
- git 설치의 선택적 사전 업데이트(대화형에서만).
|
||||
- UI 프로토콜 최신성 확인(프로토콜 스키마가 더 최신이면 Control UI를 다시 빌드).
|
||||
- git 설치에 대한 선택적 사전 업데이트(대화형 전용).
|
||||
- UI 프로토콜 최신 상태 확인(프로토콜 스키마가 더 최신이면 Control UI 재빌드).
|
||||
- 상태 확인 + 재시작 프롬프트.
|
||||
- Skills 상태 요약(적격/누락/차단됨) 및 plugin 상태.
|
||||
- Skills 상태 요약(적격/누락/차단됨) 및 Plugin 상태.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="구성 및 마이그레이션">
|
||||
- 기존 값에 대한 구성 정규화.
|
||||
- 기존 평면 `talk.*` 필드에서 `talk.provider` + `talk.providers.<provider>`로 Talk 구성 마이그레이션.
|
||||
- 기존 Chrome 확장 프로그램 구성 및 Chrome MCP 준비 상태에 대한 브라우저 마이그레이션 확인.
|
||||
- OpenCode provider override 경고(`models.providers.opencode` / `models.providers.opencode-go`).
|
||||
- Codex OAuth shadowing 경고(`models.providers.openai-codex`).
|
||||
- 레거시 값에 대한 구성 정규화.
|
||||
- 레거시 평면 `talk.*` 필드에서 `talk.provider` + `talk.providers.<provider>`로 Talk 구성 마이그레이션.
|
||||
- 레거시 Chrome 확장 구성 및 Chrome MCP 준비 상태에 대한 브라우저 마이그레이션 확인.
|
||||
- OpenCode 제공자 재정의 경고(`models.providers.opencode` / `models.providers.opencode-go`).
|
||||
- Codex OAuth 섀도잉 경고(`models.providers.openai-codex`).
|
||||
- OpenAI Codex OAuth 프로필에 대한 OAuth TLS 필수 조건 확인.
|
||||
- `plugins.allow`가 제한적이지만 도구 정책이 여전히 와일드카드 또는 plugin 소유 도구를 요청할 때의 Plugin/tool allowlist 경고.
|
||||
- 기존 디스크상 상태 마이그레이션(세션/agent 디렉터리/WhatsApp 인증).
|
||||
- 기존 plugin 매니페스트 계약 키 마이그레이션(`speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders`, `webSearchProviders` → `contracts`).
|
||||
- 기존 Cron 저장소 마이그레이션(`jobId`, `schedule.cron`, 최상위 delivery/payload 필드, payload `provider`, 단순 `notify: true` Webhook fallback 작업).
|
||||
- 기존 agent 런타임 정책을 `agents.defaults.agentRuntime` 및 `agents.list[].agentRuntime`으로 마이그레이션.
|
||||
- plugin이 활성화된 경우 오래된 plugin 구성 정리. `plugins.enabled=false`인 경우, 오래된 plugin 참조는 비활성 격리 구성으로 처리되어 보존됩니다.
|
||||
- `plugins.allow`가 제한적인데 도구 정책이 여전히 와일드카드 또는 Plugin 소유 도구를 요청하는 경우 Plugin/도구 허용 목록 경고.
|
||||
- 레거시 디스크 상태 마이그레이션(세션/에이전트 디렉터리/WhatsApp 인증).
|
||||
- 레거시 Plugin 매니페스트 계약 키 마이그레이션(`speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders`, `webSearchProviders` → `contracts`).
|
||||
- 레거시 Cron 저장소 마이그레이션(`jobId`, `schedule.cron`, 최상위 delivery/payload 필드, payload `provider`, 단순 `notify: true` Webhook 폴백 작업).
|
||||
- 레거시 에이전트 런타임 정책을 `agents.defaults.agentRuntime` 및 `agents.list[].agentRuntime`으로 마이그레이션.
|
||||
- Plugin이 활성화된 경우 오래된 Plugin 구성 정리. `plugins.enabled=false`인 경우 오래된 Plugin 참조는 비활성 격리 구성으로 처리되어 보존됩니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="상태 및 무결성">
|
||||
- 세션 잠금 파일 검사 및 오래된 잠금 정리.
|
||||
- 영향을 받은 2026.4.24 빌드에서 생성된 중복 prompt-rewrite 브랜치에 대한 세션 transcript 복구.
|
||||
- wedged subagent 재시작 복구 tombstone 감지. 시작 시 child를 계속 restart-aborted로 취급하지 않도록 오래된 aborted recovery flag를 지우는 `--fix` 지원 포함.
|
||||
- 상태 무결성 및 권한 확인(세션, transcript, 상태 디렉터리).
|
||||
- 영향을 받은 2026.4.24 빌드에서 생성된 중복 프롬프트 재작성 브랜치에 대한 세션 기록 복구.
|
||||
- 멈춘 하위 에이전트 재시작-복구 톰스톤 감지. 오래된 중단 복구 플래그를 지워 시작 시 하위 항목을 재시작 중단으로 계속 처리하지 않도록 하는 `--fix` 지원 포함.
|
||||
- 상태 무결성 및 권한 확인(세션, 기록, 상태 디렉터리).
|
||||
- 로컬에서 실행할 때 구성 파일 권한 확인(chmod 600).
|
||||
- 모델 인증 상태: OAuth 만료를 확인하고, 만료 임박 토큰을 갱신할 수 있으며, auth-profile cooldown/disabled 상태를 보고합니다.
|
||||
- 추가 workspace 디렉터리 감지(`~/openclaw`).
|
||||
- 모델 인증 상태: OAuth 만료를 확인하고, 만료 임박 토큰을 새로 고칠 수 있으며, 인증 프로필 쿨다운/비활성 상태를 보고합니다.
|
||||
- 추가 작업 공간 디렉터리 감지(`~/openclaw`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Gateway, 서비스, 슈퍼바이저">
|
||||
- 샌드박싱이 활성화된 경우 샌드박스 이미지 복구.
|
||||
- 기존 서비스 마이그레이션 및 추가 Gateway 감지.
|
||||
- Matrix 채널 기존 상태 마이그레이션(`--fix` / `--repair` 모드).
|
||||
- Gateway 런타임 확인(서비스가 설치되어 있지만 실행 중이 아님, 캐시된 launchd label).
|
||||
- 레거시 서비스 마이그레이션 및 추가 Gateway 감지.
|
||||
- Matrix 채널 레거시 상태 마이그레이션(`--fix` / `--repair` 모드).
|
||||
- Gateway 런타임 확인(서비스가 설치되었지만 실행 중이 아님, 캐시된 launchd 레이블).
|
||||
- 채널 상태 경고(실행 중인 Gateway에서 프로브).
|
||||
- 로컬 TUI 클라이언트가 계속 실행 중인 상태에서 Gateway 이벤트 루프 상태가 저하된 경우 WhatsApp 응답성 확인. `--fix`는 확인된 로컬 TUI 클라이언트만 중지합니다.
|
||||
- 선택적 복구가 포함된 슈퍼바이저 구성 감사(launchd/systemd/schtasks).
|
||||
- 설치 또는 업데이트 중 셸 `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` 값을 캡처한 Gateway 서비스의 임베디드 프록시 환경 정리.
|
||||
- Gateway 런타임 모범 사례 확인(Node vs Bun, version-manager 경로).
|
||||
- 설치 또는 업데이트 중 셸 `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` 값을 캡처한 Gateway 서비스의 내장 프록시 환경 정리.
|
||||
- Gateway 런타임 모범 사례 확인(Node 대 Bun, 버전 관리자 경로).
|
||||
- Gateway 포트 충돌 진단(기본값 `18789`).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="인증, 보안, 페어링">
|
||||
- 열린 DM 정책에 대한 보안 경고.
|
||||
- 로컬 토큰 모드에 대한 Gateway 인증 확인(토큰 소스가 없으면 토큰 생성을 제안함. 토큰 SecretRef 구성은 덮어쓰지 않음).
|
||||
- 기기 페어링 문제 감지(대기 중인 최초 페어링 요청, 대기 중인 role/scope 업그레이드, 오래된 로컬 device-token 캐시 드리프트, paired-record 인증 드리프트).
|
||||
- 공개 DM 정책에 대한 보안 경고.
|
||||
- 로컬 토큰 모드에 대한 Gateway 인증 확인(토큰 소스가 없으면 토큰 생성을 제안하며, 토큰 SecretRef 구성을 덮어쓰지 않음).
|
||||
- 기기 페어링 문제 감지(대기 중인 최초 페어링 요청, 대기 중인 역할/범위 업그레이드, 오래된 로컬 기기 토큰 캐시 드리프트, 페어링된 레코드 인증 드리프트).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Workspace 및 셸">
|
||||
<Accordion title="작업 공간 및 셸">
|
||||
- Linux에서 systemd linger 확인.
|
||||
- Workspace bootstrap 파일 크기 확인(context 파일에 대한 잘림/한계 근접 경고).
|
||||
- 기본 agent의 Skills 준비 상태 확인. 누락된 bin, env, config 또는 OS 요구 사항이 있는 허용된 skills를 보고하며, `--fix`는 `skills.entries`에서 사용할 수 없는 skills를 비활성화할 수 있습니다.
|
||||
- 셸 completion 상태 확인 및 자동 설치/업그레이드.
|
||||
- 메모리 검색 embedding provider 준비 상태 확인(로컬 모델, 원격 API 키 또는 QMD binary).
|
||||
- 소스 설치 확인(pnpm workspace 불일치, 누락된 UI asset, 누락된 tsx binary).
|
||||
- 업데이트된 구성 + wizard metadata를 작성합니다.
|
||||
- 작업 공간 부트스트랩 파일 크기 확인(컨텍스트 파일의 잘림/한계 근접 경고).
|
||||
- 기본 에이전트에 대한 Skills 준비 상태 확인. 누락된 바이너리, env, 구성 또는 OS 요구 사항이 있는 허용된 Skills를 보고하며, `--fix`는 `skills.entries`에서 사용할 수 없는 Skills를 비활성화할 수 있습니다.
|
||||
- 셸 완성 상태 확인 및 자동 설치/업그레이드.
|
||||
- 메모리 검색 임베딩 제공자 준비 상태 확인(로컬 모델, 원격 API 키 또는 QMD 바이너리).
|
||||
- 소스 설치 확인(pnpm 작업 공간 불일치, 누락된 UI 자산, 누락된 tsx 바이너리).
|
||||
- 업데이트된 구성 + 마법사 메타데이터를 씁니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Dreams UI 백필 및 재설정
|
||||
|
||||
Control UI Dreams scene에는 grounded dreaming 워크플로를 위한 **백필**, **재설정**, **Grounded 지우기** 작업이 포함되어 있습니다. 이 작업들은 gateway doctor 스타일 RPC 메서드를 사용하지만, `openclaw doctor` CLI 복구/마이그레이션의 일부는 **아닙니다**.
|
||||
Control UI Dreams 장면에는 근거 기반 Dreaming 워크플로를 위한 **백필**, **재설정**, **근거 항목 지우기** 작업이 포함됩니다. 이 작업들은 Gateway doctor 스타일 RPC 메서드를 사용하지만, `openclaw doctor` CLI 복구/마이그레이션의 일부는 **아닙니다**.
|
||||
|
||||
수행하는 작업:
|
||||
|
||||
- **백필**은 활성 workspace의 과거 `memory/YYYY-MM-DD.md` 파일을 스캔하고, grounded REM diary pass를 실행하며, 되돌릴 수 있는 백필 항목을 `DREAMS.md`에 작성합니다.
|
||||
- **재설정**은 `DREAMS.md`에서 표시된 백필 diary 항목만 제거합니다.
|
||||
- **Grounded 지우기**는 과거 재생에서 왔고 아직 live recall 또는 daily support가 누적되지 않은 staged grounded-only 단기 항목만 제거합니다.
|
||||
- **백필**은 활성 작업 공간의 과거 `memory/YYYY-MM-DD.md` 파일을 스캔하고, 근거 기반 REM 일기 패스를 실행하며, 되돌릴 수 있는 백필 항목을 `DREAMS.md`에 씁니다.
|
||||
- **재설정**은 표시된 백필 일기 항목만 `DREAMS.md`에서 제거합니다.
|
||||
- **근거 항목 지우기**는 과거 재생에서 온, 아직 실시간 회상이나 일일 지원을 누적하지 않은 준비된 근거 전용 단기 항목만 제거합니다.
|
||||
|
||||
자체적으로 수행하지 **않는** 작업:
|
||||
|
||||
- `MEMORY.md`를 편집하지 않습니다
|
||||
- 전체 doctor 마이그레이션을 실행하지 않습니다
|
||||
- staged CLI 경로를 명시적으로 먼저 실행하지 않는 한, grounded candidates를 live short-term promotion store에 자동으로 stage하지 않습니다
|
||||
- 준비된 CLI 경로를 먼저 명시적으로 실행하지 않는 한, 근거 후보를 실시간 단기 승격 저장소에 자동으로 스테이징하지 않습니다
|
||||
|
||||
grounded historical replay가 일반 deep promotion lane에 영향을 주게 하려면 대신 CLI 흐름을 사용하세요.
|
||||
근거 기반 과거 재생이 일반 심층 승격 경로에 영향을 주게 하려면 대신 CLI 흐름을 사용하세요.
|
||||
|
||||
```bash
|
||||
openclaw memory rem-backfill --path ./memory --stage-short-term
|
||||
```
|
||||
|
||||
이는 `DREAMS.md`를 검토 표면으로 유지하면서 grounded durable candidates를 short-term dreaming store에 stage합니다.
|
||||
그러면 `DREAMS.md`를 검토 표면으로 유지하면서 근거 기반 내구 후보를 단기 Dreaming 저장소에 스테이징합니다.
|
||||
|
||||
## 자세한 동작 및 근거
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="0. 선택적 업데이트(git 설치)">
|
||||
이것이 git checkout이고 doctor가 대화형으로 실행 중이면, doctor를 실행하기 전에 업데이트(fetch/rebase/build)를 제안합니다.
|
||||
이것이 git 체크아웃이고 doctor가 대화형으로 실행 중이면, doctor 실행 전에 업데이트(fetch/rebase/build)를 제안합니다.
|
||||
</Accordion>
|
||||
<Accordion title="1. 구성 정규화">
|
||||
구성에 기존 값 형태가 포함된 경우(예: 채널별 override 없이 `messages.ackReaction`), doctor는 이를 현재 스키마로 정규화합니다.
|
||||
구성에 레거시 값 형태가 포함되어 있으면(예: 채널별 재정의 없이 `messages.ackReaction`), doctor가 이를 현재 스키마로 정규화합니다.
|
||||
|
||||
여기에는 기존 Talk 평면 필드가 포함됩니다. 현재 공개 Talk 구성은 `talk.provider` + `talk.providers.<provider>`입니다. Doctor는 이전 `talk.voiceId` / `talk.voiceAliases` / `talk.modelId` / `talk.outputFormat` / `talk.apiKey` 형태를 provider map으로 다시 작성합니다.
|
||||
여기에는 레거시 Talk 평면 필드가 포함됩니다. 현재 공개 Talk 구성은 `talk.provider` + `talk.providers.<provider>`입니다. Doctor는 이전 `talk.voiceId` / `talk.voiceAliases` / `talk.modelId` / `talk.outputFormat` / `talk.apiKey` 형태를 제공자 맵으로 다시 씁니다.
|
||||
|
||||
Doctor는 또한 `plugins.allow`가 비어 있지 않고 도구 정책이
|
||||
와일드카드 또는 plugin 소유 도구 항목을 사용할 때 경고합니다. `tools.allow: ["*"]`는 실제로 로드되는 plugin의 도구에만 일치하며,
|
||||
배타적인 plugin allowlist를 우회하지 않습니다. Doctor는 기존 번들 provider 동작을 보존하기 위해 마이그레이션된
|
||||
기존 allowlist 구성에 `plugins.bundledDiscovery: "compat"`를 작성한 다음
|
||||
더 엄격한 `"allowlist"` 설정을 가리킵니다.
|
||||
와일드카드 또는 Plugin 소유 도구 항목을 사용하는 경우 경고합니다. `tools.allow: ["*"]`는 실제로 로드되는 Plugin의 도구에만 일치하며,
|
||||
독점 Plugin 허용 목록을 우회하지 않습니다. Doctor는 마이그레이션된
|
||||
레거시 허용 목록 구성에 대해 `plugins.bundledDiscovery: "compat"`를 써서 기존 번들 제공자 동작을 보존한 다음,
|
||||
더 엄격한 `"allowlist"` 설정을 안내합니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="2. 기존 구성 키 마이그레이션">
|
||||
구성에 더 이상 사용되지 않는 키가 포함되어 있으면, 다른 명령은 실행을 거부하고 `openclaw doctor`를 실행하라고 요청합니다.
|
||||
<Accordion title="2. 레거시 구성 키 마이그레이션">
|
||||
구성에 사용 중단된 키가 포함되어 있으면, 다른 명령은 실행을 거부하고 `openclaw doctor`를 실행하라고 요청합니다.
|
||||
|
||||
Doctor는 다음을 수행합니다.
|
||||
|
||||
- 발견된 기존 키를 설명합니다.
|
||||
- 발견된 레거시 키를 설명합니다.
|
||||
- 적용한 마이그레이션을 표시합니다.
|
||||
- 업데이트된 스키마로 `~/.openclaw/openclaw.json`을 다시 작성합니다.
|
||||
- 업데이트된 스키마로 `~/.openclaw/openclaw.json`을 다시 씁니다.
|
||||
|
||||
Gateway도 시작 시 기존 구성 형식을 감지하면 doctor 마이그레이션을 자동으로 실행하므로, 오래된 구성은 수동 개입 없이 복구됩니다. Cron job store 마이그레이션은 `openclaw doctor --fix`에서 처리됩니다.
|
||||
Gateway도 시작 시 레거시 구성 형식을 감지하면 doctor 마이그레이션을 자동 실행하므로, 오래된 구성은 수동 개입 없이 복구됩니다. Cron 작업 저장소 마이그레이션은 `openclaw doctor --fix`에서 처리됩니다.
|
||||
|
||||
현재 마이그레이션:
|
||||
|
||||
@ -198,313 +199,313 @@ openclaw memory rem-backfill --path ./memory --stage-short-term
|
||||
- `routing.groupChat.historyLimit` → `messages.groupChat.historyLimit`
|
||||
- `routing.groupChat.mentionPatterns` → `messages.groupChat.mentionPatterns`
|
||||
- `channels.telegram.requireMention` → `channels.telegram.groups."*".requireMention`
|
||||
- 표시 가능한 답장 정책이 누락된 구성된 채널 설정 → `messages.groupChat.visibleReplies: "message_tool"`
|
||||
- 표시 가능한 응답 정책이 누락된 구성된 채널 설정 → `messages.groupChat.visibleReplies: "message_tool"`
|
||||
- `routing.queue` → `messages.queue`
|
||||
- `routing.bindings` → 최상위 `bindings`
|
||||
- `routing.agents`/`routing.defaultAgentId` → `agents.list` + `agents.list[].default`
|
||||
- 기존 `talk.voiceId`/`talk.voiceAliases`/`talk.modelId`/`talk.outputFormat`/`talk.apiKey` → `talk.provider` + `talk.providers.<provider>`
|
||||
- 레거시 `talk.voiceId`/`talk.voiceAliases`/`talk.modelId`/`talk.outputFormat`/`talk.apiKey` → `talk.provider` + `talk.providers.<provider>`
|
||||
- `routing.agentToAgent` → `tools.agentToAgent`
|
||||
- `routing.transcribeAudio` → `tools.media.audio.models`
|
||||
- `messages.tts.<provider>`(`openai`/`elevenlabs`/`microsoft`/`edge`) → `messages.tts.providers.<provider>`
|
||||
- `messages.tts.<provider>` (`openai`/`elevenlabs`/`microsoft`/`edge`) → `messages.tts.providers.<provider>`
|
||||
- `messages.tts.provider: "edge"` 및 `messages.tts.providers.edge` → `messages.tts.provider: "microsoft"` 및 `messages.tts.providers.microsoft`
|
||||
- `channels.discord.voice.tts.<provider>`(`openai`/`elevenlabs`/`microsoft`/`edge`) → `channels.discord.voice.tts.providers.<provider>`
|
||||
- `channels.discord.accounts.<id>.voice.tts.<provider>`(`openai`/`elevenlabs`/`microsoft`/`edge`) → `channels.discord.accounts.<id>.voice.tts.providers.<provider>`
|
||||
- `plugins.entries.voice-call.config.tts.<provider>`(`openai`/`elevenlabs`/`microsoft`/`edge`) → `plugins.entries.voice-call.config.tts.providers.<provider>`
|
||||
- `channels.discord.voice.tts.<provider>` (`openai`/`elevenlabs`/`microsoft`/`edge`) → `channels.discord.voice.tts.providers.<provider>`
|
||||
- `channels.discord.accounts.<id>.voice.tts.<provider>` (`openai`/`elevenlabs`/`microsoft`/`edge`) → `channels.discord.accounts.<id>.voice.tts.providers.<provider>`
|
||||
- `plugins.entries.voice-call.config.tts.<provider>` (`openai`/`elevenlabs`/`microsoft`/`edge`) → `plugins.entries.voice-call.config.tts.providers.<provider>`
|
||||
- `plugins.entries.voice-call.config.tts.provider: "edge"` 및 `plugins.entries.voice-call.config.tts.providers.edge` → `provider: "microsoft"` 및 `providers.microsoft`
|
||||
- `plugins.entries.voice-call.config.provider: "log"` → `"mock"`
|
||||
- `plugins.entries.voice-call.config.twilio.from` → `plugins.entries.voice-call.config.fromNumber`
|
||||
- `plugins.entries.voice-call.config.streaming.sttProvider` → `plugins.entries.voice-call.config.streaming.provider`
|
||||
- `plugins.entries.voice-call.config.streaming.openaiApiKey|sttModel|silenceDurationMs|vadThreshold` → `plugins.entries.voice-call.config.streaming.providers.openai.*`
|
||||
- `bindings[].match.accountID` → `bindings[].match.accountId`
|
||||
- 이름이 지정된 `accounts`가 있지만 단일 계정용 최상위 채널 값이 남아 있는 채널의 경우, 해당 계정 범위 값을 그 채널에 대해 선택된 승격 계정으로 이동합니다(대부분의 채널은 `accounts.default`; Matrix는 일치하는 기존 이름 지정/기본 대상을 보존할 수 있음)
|
||||
- 이름이 지정된 `accounts`가 있지만 단일 계정용 최상위 채널 값이 남아 있는 채널의 경우, 해당 계정 범위 값을 그 채널에 대해 선택된 승격 계정으로 이동합니다(대부분의 채널은 `accounts.default`; Matrix는 기존의 일치하는 이름/기본 대상을 보존할 수 있음)
|
||||
- `identity` → `agents.list[].identity`
|
||||
- `agent.*` → `agents.defaults` + `tools.*`(tools/elevated/exec/sandbox/subagents)
|
||||
- `agent.*` → `agents.defaults` + `tools.*` (tools/elevated/exec/sandbox/subagents)
|
||||
- `agent.model`/`allowedModels`/`modelAliases`/`modelFallbacks`/`imageModelFallbacks` → `agents.defaults.models` + `agents.defaults.model.primary/fallbacks` + `agents.defaults.imageModel.primary/fallbacks`
|
||||
- `agents.defaults.llm` 제거; 느린 provider/model 시간 초과에는 `models.providers.<id>.timeoutSeconds`를 사용
|
||||
- `agents.defaults.llm` 제거; 느린 provider/model 시간 제한에는 `models.providers.<id>.timeoutSeconds` 사용
|
||||
- `browser.ssrfPolicy.allowPrivateNetwork` → `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork`
|
||||
- `browser.profiles.*.driver: "extension"` → `"existing-session"`
|
||||
- `browser.relayBindHost` 제거(기존 확장 릴레이 설정)
|
||||
- 기존 `models.providers.*.api: "openai"` → `"openai-completions"`(gateway 시작 시에도 `api`가 향후 또는 알 수 없는 enum 값으로 설정된 provider는 실패로 닫는 대신 건너뜁니다)
|
||||
- `browser.relayBindHost` 제거(레거시 extension relay 설정)
|
||||
- 레거시 `models.providers.*.api: "openai"` → `"openai-completions"`(Gateway 시작 시 `api`가 향후 또는 알 수 없는 enum 값으로 설정된 provider도 실패로 닫지 않고 건너뜀)
|
||||
|
||||
Doctor 경고에는 다중 계정 채널에 대한 계정 기본값 안내도 포함됩니다.
|
||||
|
||||
- 두 개 이상의 `channels.<channel>.accounts` 항목이 `channels.<channel>.defaultAccount` 또는 `accounts.default` 없이 구성된 경우, doctor는 fallback 라우팅이 예상치 못한 계정을 선택할 수 있다고 경고합니다.
|
||||
- `channels.<channel>.defaultAccount`가 알 수 없는 계정 ID로 설정된 경우, doctor는 경고하고 구성된 계정 ID 목록을 표시합니다.
|
||||
- 두 개 이상의 `channels.<channel>.accounts` 항목이 `channels.<channel>.defaultAccount` 또는 `accounts.default` 없이 구성된 경우, doctor는 fallback routing이 예상치 못한 계정을 선택할 수 있다고 경고합니다.
|
||||
- `channels.<channel>.defaultAccount`가 알 수 없는 계정 ID로 설정된 경우, doctor는 경고하고 구성된 계정 ID를 나열합니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="2b. OpenCode provider 재정의">
|
||||
`models.providers.opencode`, `opencode-zen` 또는 `opencode-go`를 수동으로 추가한 경우, `@mariozechner/pi-ai`의 기본 제공 OpenCode 카탈로그를 재정의합니다. 이로 인해 모델이 잘못된 API로 강제되거나 비용이 0으로 설정될 수 있습니다. Doctor는 재정의를 제거하고 모델별 API 라우팅 + 비용을 복원할 수 있도록 경고합니다.
|
||||
<Accordion title="2b. OpenCode provider overrides">
|
||||
`models.providers.opencode`, `opencode-zen` 또는 `opencode-go`를 수동으로 추가한 경우, `@mariozechner/pi-ai`의 내장 OpenCode catalog를 재정의합니다. 이로 인해 모델이 잘못된 API에 강제로 배치되거나 비용이 0으로 설정될 수 있습니다. Doctor가 경고하므로 재정의를 제거하고 모델별 API 라우팅 및 비용을 복원할 수 있습니다.
|
||||
</Accordion>
|
||||
<Accordion title="2c. Browser 마이그레이션 및 Chrome MCP 준비 상태">
|
||||
Browser 설정이 제거된 Chrome 확장 경로를 여전히 가리키는 경우, doctor는 이를 현재의 호스트 로컬 Chrome MCP attach 모델로 정규화합니다.
|
||||
<Accordion title="2c. Browser migration and Chrome MCP readiness">
|
||||
브라우저 설정이 아직 제거된 Chrome extension 경로를 가리키는 경우, doctor는 이를 현재의 호스트 로컬 Chrome MCP attach 모델로 정규화합니다.
|
||||
|
||||
- `browser.profiles.*.driver: "extension"`는 `"existing-session"`이 됩니다
|
||||
- `browser.profiles.*.driver: "extension"`은 `"existing-session"`이 됩니다
|
||||
- `browser.relayBindHost`가 제거됩니다
|
||||
|
||||
또한 Doctor는 `defaultProfile: "user"` 또는 구성된 `existing-session` 프로필을 사용할 때 호스트 로컬 Chrome MCP 경로를 감사합니다.
|
||||
또한 `defaultProfile: "user"` 또는 구성된 `existing-session` 프로필을 사용할 때 doctor는 호스트 로컬 Chrome MCP 경로를 감사합니다.
|
||||
|
||||
- 기본 자동 연결 프로필의 경우 같은 호스트에 Google Chrome이 설치되어 있는지 확인합니다
|
||||
- 기본 자동 연결 프로필에 대해 동일한 호스트에 Google Chrome이 설치되어 있는지 확인합니다
|
||||
- 감지된 Chrome 버전을 확인하고 Chrome 144 미만이면 경고합니다
|
||||
- 브라우저 inspect 페이지에서 원격 디버깅을 활성화하라고 알려줍니다(예: `chrome://inspect/#remote-debugging`, `brave://inspect/#remote-debugging` 또는 `edge://inspect/#remote-debugging`)
|
||||
- 브라우저 검사 페이지에서 원격 디버깅을 활성화하라고 알려줍니다(예: `chrome://inspect/#remote-debugging`, `brave://inspect/#remote-debugging` 또는 `edge://inspect/#remote-debugging`)
|
||||
|
||||
Doctor는 Chrome 쪽 설정을 대신 활성화할 수 없습니다. 호스트 로컬 Chrome MCP에는 여전히 다음이 필요합니다.
|
||||
|
||||
- Gateway/Node 호스트의 Chromium 기반 브라우저 144+
|
||||
- 로컬에서 실행 중인 브라우저
|
||||
- 해당 브라우저에서 활성화된 원격 디버깅
|
||||
- 해당 브라우저에서 원격 디버깅 활성화
|
||||
- 브라우저에서 첫 attach 동의 프롬프트 승인
|
||||
|
||||
여기서의 준비 상태는 로컬 attach 전제 조건에만 관한 것입니다. Existing-session은 현재 Chrome MCP 라우트 제한을 유지합니다. `responsebody`, PDF 내보내기, 다운로드 가로채기, 배치 작업 같은 고급 라우트에는 여전히 관리형 브라우저 또는 raw CDP 프로필이 필요합니다.
|
||||
여기서 준비 상태는 로컬 attach 사전 요구 사항에만 관한 것입니다. Existing-session은 현재 Chrome MCP 경로 제한을 유지합니다. `responsebody`, PDF 내보내기, 다운로드 가로채기, 일괄 작업 같은 고급 경로에는 여전히 관리형 브라우저 또는 원시 CDP 프로필이 필요합니다.
|
||||
|
||||
이 검사는 Docker, sandbox, remote-browser 또는 기타 headless 흐름에는 적용되지 않습니다. 이러한 흐름은 계속 raw CDP를 사용합니다.
|
||||
이 검사는 Docker, sandbox, remote-browser 또는 기타 headless flow에는 적용되지 않습니다. 이러한 flow는 계속 원시 CDP를 사용합니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="2d. OAuth TLS 전제 조건">
|
||||
OpenAI Codex OAuth 프로필이 구성된 경우, doctor는 OpenAI authorization 엔드포인트를 탐지하여 로컬 Node/OpenSSL TLS 스택이 인증서 체인을 검증할 수 있는지 확인합니다. 탐지가 인증서 오류(예: `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`, 만료된 인증서 또는 자체 서명 인증서)로 실패하면, doctor는 플랫폼별 수정 안내를 출력합니다. Homebrew Node를 사용하는 macOS에서는 보통 `brew postinstall ca-certificates`가 해결책입니다. `--deep`을 사용하면 gateway가 정상이어도 탐지가 실행됩니다.
|
||||
<Accordion title="2d. OAuth TLS prerequisites">
|
||||
OpenAI Codex OAuth 프로필이 구성되면, doctor는 OpenAI authorization endpoint를 probe하여 로컬 Node/OpenSSL TLS stack이 인증서 체인을 검증할 수 있는지 확인합니다. probe가 인증서 오류(예: `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`, 만료된 인증서 또는 자체 서명 인증서)로 실패하면, doctor는 플랫폼별 수정 안내를 출력합니다. macOS에서 Homebrew Node를 사용하는 경우 일반적으로 수정 방법은 `brew postinstall ca-certificates`입니다. `--deep`에서는 Gateway가 정상이어도 probe가 실행됩니다.
|
||||
</Accordion>
|
||||
<Accordion title="2e. Codex OAuth provider 재정의">
|
||||
이전에 기존 OpenAI 전송 설정을 `models.providers.openai-codex` 아래에 추가했다면, 최신 릴리스가 자동으로 사용하는 기본 제공 Codex OAuth provider 경로를 가릴 수 있습니다. Doctor는 Codex OAuth와 함께 이러한 오래된 전송 설정을 발견하면 경고하여, 오래된 전송 재정의를 제거하거나 다시 작성하고 기본 제공 라우팅/fallback 동작을 되돌릴 수 있게 합니다. 사용자 지정 프록시와 헤더 전용 재정의는 계속 지원되며 이 경고를 트리거하지 않습니다.
|
||||
<Accordion title="2e. Codex OAuth provider overrides">
|
||||
이전에 `models.providers.openai-codex` 아래에 레거시 OpenAI transport 설정을 추가했다면, 최신 릴리스가 자동으로 사용하는 내장 Codex OAuth provider 경로를 가릴 수 있습니다. Doctor는 Codex OAuth와 함께 이러한 오래된 transport 설정을 발견하면 경고하므로, 낡은 transport 재정의를 제거하거나 다시 작성하여 내장 라우팅/fallback 동작을 되돌릴 수 있습니다. 사용자 지정 proxy와 header-only 재정의는 계속 지원되며 이 경고를 발생시키지 않습니다.
|
||||
</Accordion>
|
||||
<Accordion title="2f. Codex Plugin 라우트 경고">
|
||||
번들된 Codex Plugin이 활성화된 경우, doctor는 `openai-codex/*` 기본 모델 참조가 여전히 기본 PI runner를 통해 resolve되는지도 확인합니다. PI를 통한 Codex OAuth/subscription auth를 원하는 경우 이 조합은 유효하지만, 네이티브 Codex app-server harness와 혼동하기 쉽습니다. Doctor는 경고하고 명시적인 app-server 형태를 안내합니다: `openai/*` + `agentRuntime.id: "codex"` 또는 `OPENCLAW_AGENT_RUNTIME=codex`.
|
||||
<Accordion title="2f. Codex plugin route warnings">
|
||||
번들된 Codex Plugin이 활성화되면, doctor는 `openai-codex/*` 기본 모델 ref가 여전히 기본 PI runner를 통해 resolve되는지도 확인합니다. 이 조합은 PI를 통한 Codex OAuth/subscription auth를 원할 때 유효하지만, 네이티브 Codex app-server harness와 혼동하기 쉽습니다. Doctor는 경고하고 명시적인 app-server 형태를 가리킵니다: `openai/*` plus `agentRuntime.id: "codex"` 또는 `OPENCLAW_AGENT_RUNTIME=codex`.
|
||||
|
||||
Doctor는 두 라우트가 모두 유효하므로 이를 자동으로 복구하지 않습니다.
|
||||
Doctor는 두 경로가 모두 유효하기 때문에 이를 자동으로 복구하지 않습니다.
|
||||
|
||||
- `openai-codex/*` + PI는 "일반 OpenClaw runner를 통해 Codex OAuth/subscription auth를 사용"한다는 뜻입니다.
|
||||
- `openai/*` + `agentRuntime.id: "codex"`는 "임베디드 turn을 네이티브 Codex app-server를 통해 실행"한다는 뜻입니다.
|
||||
- `/codex ...`는 "채팅에서 네이티브 Codex 대화를 제어하거나 바인딩"한다는 뜻입니다.
|
||||
- `/acp ...` 또는 `runtime: "acp"`는 "외부 ACP/acpx adapter를 사용"한다는 뜻입니다.
|
||||
- `openai-codex/*` + PI는 "일반 OpenClaw runner를 통해 Codex OAuth/subscription auth 사용"을 의미합니다.
|
||||
- `openai/*` + `agentRuntime.id: "codex"`는 "내장된 turn을 네이티브 Codex app-server를 통해 실행"을 의미합니다.
|
||||
- `/codex ...`는 "채팅에서 네이티브 Codex conversation을 제어하거나 bind"를 의미합니다.
|
||||
- `/acp ...` 또는 `runtime: "acp"`는 "외부 ACP/acpx adapter 사용"을 의미합니다.
|
||||
|
||||
경고가 표시되면 의도한 라우트를 선택하고 설정을 수동으로 편집하세요. PI Codex OAuth가 의도된 경우 경고를 그대로 유지하세요.
|
||||
경고가 나타나면 의도한 경로를 선택하고 config를 수동으로 편집하세요. PI Codex OAuth가 의도된 경우 경고를 그대로 유지하세요.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="2g. 세션 라우트 정리">
|
||||
Doctor는 구성된 기본/fallback 모델 또는 runtime을 Codex 같은 Plugin 소유 라우트에서 다른 곳으로 이동한 뒤, 활성 세션 저장소에서 오래된 자동 생성 라우트 상태도 스캔합니다.
|
||||
<Accordion title="2g. Session route cleanup">
|
||||
Doctor는 Codex 같은 Plugin 소유 경로에서 구성된 기본/fallback 모델 또는 runtime을 다른 곳으로 옮긴 뒤, active sessions store에 오래된 자동 생성 route state가 남아 있는지도 스캔합니다.
|
||||
|
||||
`openclaw doctor --fix`는 소유 라우트가 더 이상 구성되어 있지 않을 때 `modelOverrideSource: "auto"` 모델 핀, runtime 모델 메타데이터, 고정된 harness ID, CLI 세션 바인딩, 자동 auth-profile 재정의 같은 자동 생성된 오래된 상태를 지울 수 있습니다. 명시적인 사용자 또는 기존 세션 모델 선택은 수동 검토 대상으로 보고되고 건드리지 않습니다. 해당 라우트가 더 이상 의도한 것이 아니라면 `/model ...`, `/new`로 전환하거나 세션을 재설정하세요.
|
||||
`openclaw doctor --fix`는 소유 경로가 더 이상 구성되지 않은 경우 `modelOverrideSource: "auto"` 모델 pin, runtime 모델 metadata, pinned harness id, CLI session binding, 자동 auth-profile override 같은 자동 생성된 오래된 state를 지울 수 있습니다. 명시적인 사용자 또는 레거시 session 모델 선택은 수동 검토 대상으로 보고되고 그대로 둡니다. 해당 경로를 더 이상 의도하지 않는 경우 `/model ...`, `/new`로 전환하거나 session을 reset하세요.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="3. 기존 상태 마이그레이션(디스크 레이아웃)">
|
||||
Doctor는 오래된 온디스크 레이아웃을 현재 구조로 마이그레이션할 수 있습니다.
|
||||
<Accordion title="3. Legacy state migrations (disk layout)">
|
||||
Doctor는 오래된 온디스크 layout을 현재 구조로 migrate할 수 있습니다.
|
||||
|
||||
- 세션 저장소 + transcripts:
|
||||
- Sessions store + transcripts:
|
||||
- `~/.openclaw/sessions/`에서 `~/.openclaw/agents/<agentId>/sessions/`로
|
||||
- Agent dir:
|
||||
- `~/.openclaw/agent/`에서 `~/.openclaw/agents/<agentId>/agent/`로
|
||||
- WhatsApp auth 상태(Baileys):
|
||||
- 기존 `~/.openclaw/credentials/*.json`에서(`oauth.json` 제외)
|
||||
- `~/.openclaw/credentials/whatsapp/<accountId>/...`로(기본 계정 ID: `default`)
|
||||
- WhatsApp auth state (Baileys):
|
||||
- 레거시 `~/.openclaw/credentials/*.json`에서(`oauth.json` 제외)
|
||||
- `~/.openclaw/credentials/whatsapp/<accountId>/...`로(기본 account id: `default`)
|
||||
|
||||
이러한 마이그레이션은 최선 노력 방식이며 멱등적입니다. Doctor는 백업으로 남겨둔 기존 폴더가 있으면 경고를 출력합니다. Gateway/CLI도 시작 시 기존 세션 + agent dir을 자동 마이그레이션하여 history/auth/models가 수동 doctor 실행 없이 agent별 경로에 들어가도록 합니다. WhatsApp auth는 의도적으로 `openclaw doctor`를 통해서만 마이그레이션됩니다. 이제 Talk provider/provider-map 정규화는 구조적 동등성으로 비교하므로, key 순서만 다른 diff는 더 이상 반복적인 무효 `doctor --fix` 변경을 트리거하지 않습니다.
|
||||
이러한 migration은 최선 노력 방식이며 idempotent합니다. doctor는 백업으로 레거시 폴더를 남겨둘 때 경고를 출력합니다. Gateway/CLI도 시작 시 레거시 sessions + agent dir을 자동으로 migrate하여 history/auth/models가 수동 doctor 실행 없이 agent별 경로에 위치하도록 합니다. WhatsApp auth는 의도적으로 `openclaw doctor`를 통해서만 migrate됩니다. Talk provider/provider-map 정규화는 이제 구조적 동등성으로 비교하므로, key 순서만 다른 diff는 더 이상 반복적인 no-op `doctor --fix` 변경을 유발하지 않습니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="3a. 기존 Plugin manifest 마이그레이션">
|
||||
Doctor는 설치된 모든 Plugin manifest에서 더 이상 사용되지 않는 최상위 capability key(`speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders`, `webSearchProviders`)를 스캔합니다. 발견하면 이를 `contracts` 객체로 이동하고 manifest 파일을 제자리에서 다시 작성하도록 제안합니다. 이 마이그레이션은 멱등적입니다. `contracts` key에 이미 같은 값이 있으면 데이터를 중복하지 않고 기존 key를 제거합니다.
|
||||
<Accordion title="3a. Legacy plugin manifest migrations">
|
||||
Doctor는 설치된 모든 Plugin manifest에서 deprecated된 최상위 capability key(`speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders`, `webSearchProviders`)를 스캔합니다. 발견되면 이를 `contracts` 객체로 이동하고 manifest 파일을 제자리에서 다시 쓰도록 제안합니다. 이 migration은 idempotent합니다. `contracts` key에 이미 같은 값이 있으면, 데이터를 중복하지 않고 레거시 key를 제거합니다.
|
||||
</Accordion>
|
||||
<Accordion title="3b. 기존 Cron 저장소 마이그레이션">
|
||||
Doctor는 cron 작업 저장소(기본값은 `~/.openclaw/cron/jobs.json`, 재정의된 경우 `cron.store`)에서 scheduler가 호환성을 위해 여전히 허용하는 오래된 작업 형태도 확인합니다.
|
||||
<Accordion title="3b. Legacy cron store migrations">
|
||||
Doctor는 또한 cron job store(기본값은 `~/.openclaw/cron/jobs.json`, 재정의된 경우 `cron.store`)에서 scheduler가 호환성을 위해 아직 허용하는 오래된 job shape를 확인합니다.
|
||||
|
||||
현재 cron 정리에는 다음이 포함됩니다.
|
||||
현재 cron cleanup에는 다음이 포함됩니다.
|
||||
|
||||
- `jobId` → `id`
|
||||
- `schedule.cron` → `schedule.expr`
|
||||
- 최상위 payload 필드(`message`, `model`, `thinking`, ...) → `payload`
|
||||
- 최상위 delivery 필드(`deliver`, `channel`, `to`, `provider`, ...) → `delivery`
|
||||
- payload `provider` delivery alias → 명시적인 `delivery.channel`
|
||||
- 단순 기존 `notify: true` webhook fallback 작업 → `delivery.to=cron.webhook`이 포함된 명시적인 `delivery.mode="webhook"`
|
||||
- 최상위 payload field(`message`, `model`, `thinking`, ...) → `payload`
|
||||
- 최상위 delivery field(`deliver`, `channel`, `to`, `provider`, ...) → `delivery`
|
||||
- payload `provider` delivery alias → 명시적 `delivery.channel`
|
||||
- 단순 레거시 `notify: true` webhook fallback job → `delivery.to=cron.webhook`이 포함된 명시적 `delivery.mode="webhook"`
|
||||
|
||||
Doctor는 동작 변경 없이 처리할 수 있을 때만 `notify: true` 작업을 자동 마이그레이션합니다. 작업이 기존 notify fallback과 기존 non-webhook delivery 모드를 함께 사용하는 경우, doctor는 경고하고 해당 작업을 수동 검토 대상으로 남깁니다.
|
||||
Doctor는 동작 변경 없이 처리할 수 있을 때만 `notify: true` job을 자동으로 migrate합니다. job이 레거시 notify fallback과 기존 non-webhook delivery mode를 함께 사용하는 경우, doctor는 경고하고 해당 job을 수동 검토 대상으로 남겨둡니다.
|
||||
|
||||
Linux에서 doctor는 사용자의 crontab이 여전히 레거시 `~/.openclaw/bin/ensure-whatsapp.sh`를 호출하는 경우에도 경고합니다. 이 호스트 로컬 스크립트는 현재 OpenClaw에서 유지 관리되지 않으며, cron이 systemd 사용자 버스에 도달할 수 없을 때 `~/.openclaw/logs/whatsapp-health.log`에 잘못된 `Gateway inactive` 메시지를 기록할 수 있습니다. 오래된 crontab 항목은 `crontab -e`로 제거하고, 현재 상태 점검에는 `openclaw channels status --probe`, `openclaw doctor`, `openclaw gateway status`를 사용하세요.
|
||||
Linux에서는 사용자의 crontab이 여전히 레거시 `~/.openclaw/bin/ensure-whatsapp.sh`를 호출할 때 doctor도 경고합니다. 이 호스트 로컬 스크립트는 현재 OpenClaw에서 유지 관리되지 않으며, cron이 systemd 사용자 버스에 도달할 수 없을 때 `~/.openclaw/logs/whatsapp-health.log`에 잘못된 `Gateway inactive` 메시지를 쓸 수 있습니다. 오래된 crontab 항목은 `crontab -e`로 제거하고, 현재 상태 확인에는 `openclaw channels status --probe`, `openclaw doctor`, `openclaw gateway status`를 사용하세요.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="3c. 세션 잠금 정리">
|
||||
Doctor는 모든 에이전트 세션 디렉터리에서 오래된 쓰기 잠금 파일, 즉 세션이 비정상적으로 종료될 때 남겨진 파일을 검사합니다. 발견된 각 잠금 파일에 대해 경로, PID, PID가 아직 살아 있는지 여부, 잠금 나이, 오래된 것으로 간주되는지 여부(죽은 PID 또는 30분 초과)를 보고합니다. `--fix` / `--repair` 모드에서는 오래된 잠금 파일을 자동으로 제거하고, 그렇지 않으면 참고 사항을 출력하며 `--fix`로 다시 실행하라고 안내합니다.
|
||||
Doctor는 모든 에이전트 세션 디렉터리에서 오래된 쓰기 잠금 파일을 스캔합니다. 이는 세션이 비정상적으로 종료될 때 남겨진 파일입니다. 발견한 각 잠금 파일에 대해 경로, PID, PID가 아직 살아 있는지 여부, 잠금 나이, 오래된 것으로 간주되는지 여부(죽은 PID 또는 30분 초과)를 보고합니다. `--fix` / `--repair` 모드에서는 오래된 잠금 파일을 자동으로 제거합니다. 그렇지 않으면 참고 메시지를 출력하고 `--fix`로 다시 실행하라고 안내합니다.
|
||||
</Accordion>
|
||||
<Accordion title="3d. 세션 transcript 브랜치 복구">
|
||||
Doctor는 2026.4.24 프롬프트 transcript 재작성 버그로 생성된 중복 브랜치 형태를 찾기 위해 에이전트 세션 JSONL 파일을 검사합니다. 이 형태는 OpenClaw 내부 런타임 컨텍스트가 포함된 버려진 사용자 턴과, 같은 표시 사용자 프롬프트를 포함하는 활성 sibling으로 구성됩니다. `--fix` / `--repair` 모드에서 doctor는 영향을 받는 각 파일을 원본 옆에 백업한 뒤 transcript를 활성 브랜치로 다시 작성하여 Gateway 기록과 메모리 리더가 더 이상 중복 턴을 보지 않게 합니다.
|
||||
Doctor는 2026.4.24 프롬프트 transcript 재작성 버그로 생성된 중복 브랜치 형태를 찾기 위해 에이전트 세션 JSONL 파일을 스캔합니다. 이 형태는 OpenClaw 내부 런타임 컨텍스트가 포함된 버려진 사용자 턴과, 동일한 표시 사용자 프롬프트를 포함한 활성 형제 브랜치로 구성됩니다. `--fix` / `--repair` 모드에서는 doctor가 영향을 받은 각 파일을 원본 옆에 백업한 뒤 transcript를 활성 브랜치로 다시 작성하여 Gateway 기록 및 memory 리더가 더 이상 중복 턴을 보지 않게 합니다.
|
||||
</Accordion>
|
||||
<Accordion title="4. 상태 무결성 검사(세션 지속성, 라우팅, 안전)">
|
||||
상태 디렉터리는 운영상의 핵심 중추입니다. 이 디렉터리가 사라지면 세션, 자격 증명, 로그, 설정을 잃게 됩니다(다른 곳에 백업이 없는 경우).
|
||||
<Accordion title="4. 상태 무결성 검사(세션 지속성, 라우팅, 안전성)">
|
||||
상태 디렉터리는 운영상의 핵심 중추입니다. 이 디렉터리가 사라지면 다른 곳에 백업이 없는 한 세션, 자격 증명, 로그, 설정을 잃게 됩니다.
|
||||
|
||||
Doctor는 다음을 검사합니다.
|
||||
|
||||
- **상태 디렉터리 누락**: 치명적인 상태 손실을 경고하고, 디렉터리를 다시 만들지 묻고, 누락된 데이터는 복구할 수 없다고 알려 줍니다.
|
||||
- **상태 디렉터리 누락**: 치명적인 상태 손실을 경고하고, 디렉터리를 다시 만들지 묻고, 누락된 데이터는 복구할 수 없음을 알려줍니다.
|
||||
- **상태 디렉터리 권한**: 쓰기 가능 여부를 확인하고, 권한 복구를 제안합니다(소유자/그룹 불일치가 감지되면 `chown` 힌트도 출력).
|
||||
- **macOS 클라우드 동기화 상태 디렉터리**: 상태가 iCloud Drive(`~/Library/Mobile Documents/com~apple~CloudDocs/...`) 또는 `~/Library/CloudStorage/...` 아래로 해석되면 경고합니다. 동기화 기반 경로는 I/O를 느리게 하고 잠금/동기화 경합을 일으킬 수 있기 때문입니다.
|
||||
- **Linux SD 또는 eMMC 상태 디렉터리**: 상태가 `mmcblk*` 마운트 소스로 해석되면 경고합니다. SD 또는 eMMC 기반 랜덤 I/O는 세션 및 자격 증명 쓰기에서 더 느리고 더 빨리 마모될 수 있기 때문입니다.
|
||||
- **세션 디렉터리 누락**: 기록을 유지하고 `ENOENT` 충돌을 피하려면 `sessions/`와 세션 저장소 디렉터리가 필요합니다.
|
||||
- **Transcript 불일치**: 최근 세션 항목에 transcript 파일이 없으면 경고합니다.
|
||||
- **메인 세션 "1줄 JSONL"**: 메인 transcript가 한 줄뿐이면 플래그를 표시합니다(기록이 누적되지 않음).
|
||||
- **여러 상태 디렉터리**: 홈 디렉터리 전반에 여러 `~/.openclaw` 폴더가 있거나 `OPENCLAW_STATE_DIR`이 다른 위치를 가리키면 경고합니다(기록이 설치 간에 나뉠 수 있음).
|
||||
- **원격 모드 알림**: `gateway.mode=remote`이면 doctor는 원격 호스트에서 실행하라고 알려 줍니다(상태는 그곳에 있음).
|
||||
- **설정 파일 권한**: `~/.openclaw/openclaw.json`이 그룹/전 세계 읽기 가능이면 경고하고 `600`으로 강화할 것을 제안합니다.
|
||||
- **macOS 클라우드 동기화 상태 디렉터리**: 상태가 iCloud Drive(`~/Library/Mobile Documents/com~apple~CloudDocs/...`) 또는 `~/Library/CloudStorage/...` 아래로 해석될 때 경고합니다. 동기화 기반 경로는 I/O를 느리게 하고 잠금/동기화 경쟁을 일으킬 수 있기 때문입니다.
|
||||
- **Linux SD 또는 eMMC 상태 디렉터리**: 상태가 `mmcblk*` 마운트 소스로 해석될 때 경고합니다. SD 또는 eMMC 기반 랜덤 I/O는 세션 및 자격 증명 쓰기 중 더 느리고 더 빨리 마모될 수 있기 때문입니다.
|
||||
- **세션 디렉터리 누락**: `sessions/`와 세션 저장소 디렉터리는 기록을 유지하고 `ENOENT` 크래시를 피하는 데 필요합니다.
|
||||
- **Transcript 불일치**: 최근 세션 항목에 transcript 파일이 누락되어 있을 때 경고합니다.
|
||||
- **메인 세션 "1-line JSONL"**: 메인 transcript가 한 줄뿐일 때 표시합니다(기록이 누적되지 않음).
|
||||
- **여러 상태 디렉터리**: 여러 홈 디렉터리에 `~/.openclaw` 폴더가 있거나 `OPENCLAW_STATE_DIR`가 다른 곳을 가리킬 때 경고합니다(기록이 설치 간에 나뉠 수 있음).
|
||||
- **원격 모드 알림**: `gateway.mode=remote`이면 doctor는 원격 호스트에서 실행하라고 알려줍니다(상태가 그곳에 있음).
|
||||
- **설정 파일 권한**: `~/.openclaw/openclaw.json`이 그룹/전체 읽기 가능이면 경고하고 `600`으로 강화할 것을 제안합니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="5. 모델 인증 상태(OAuth 만료)">
|
||||
Doctor는 인증 저장소의 OAuth 프로필을 검사하고, 토큰이 곧 만료되거나 이미 만료된 경우 경고하며, 안전한 경우 갱신할 수 있습니다. Anthropic OAuth/토큰 프로필이 오래된 경우 Anthropic API 키 또는 Anthropic setup-token 경로를 제안합니다. 갱신 프롬프트는 대화형(TTY)으로 실행할 때만 표시되며, `--non-interactive`는 갱신 시도를 건너뜁니다.
|
||||
Doctor는 인증 저장소의 OAuth 프로필을 검사하고, 토큰이 곧 만료되거나 만료되었을 때 경고하며, 안전한 경우 새로 고칠 수 있습니다. Anthropic OAuth/토큰 프로필이 오래되었으면 Anthropic API 키 또는 Anthropic setup-token 경로를 제안합니다. 새로 고침 프롬프트는 대화형(TTY)으로 실행할 때만 표시됩니다. `--non-interactive`는 새로 고침 시도를 건너뜁니다.
|
||||
|
||||
OAuth 갱신이 영구적으로 실패하면(예: `refresh_token_reused`, `invalid_grant`, 또는 공급자가 다시 로그인하라고 안내하는 경우) doctor는 재인증이 필요하다고 보고하고 실행할 정확한 `openclaw models auth login --provider ...` 명령을 출력합니다.
|
||||
OAuth 새로 고침이 영구적으로 실패하면(예: `refresh_token_reused`, `invalid_grant`, 또는 provider가 다시 로그인하라고 알리는 경우) doctor는 재인증이 필요하다고 보고하고 실행할 정확한 `openclaw models auth login --provider ...` 명령을 출력합니다.
|
||||
|
||||
Doctor는 다음으로 인해 일시적으로 사용할 수 없는 인증 프로필도 보고합니다.
|
||||
|
||||
- 짧은 쿨다운(속도 제한/시간 초과/인증 실패)
|
||||
- 더 긴 비활성화(청구/크레딧 실패)
|
||||
- 더 긴 비활성화(결제/크레딧 실패)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="6. Hooks 모델 검증">
|
||||
`hooks.gmail.model`이 설정되어 있으면 doctor는 카탈로그와 허용 목록을 기준으로 모델 참조를 검증하고, 해석되지 않거나 허용되지 않는 경우 경고합니다.
|
||||
`hooks.gmail.model`이 설정되어 있으면 doctor는 카탈로그 및 allowlist를 기준으로 모델 참조를 검증하고, 해석되지 않거나 허용되지 않을 때 경고합니다.
|
||||
</Accordion>
|
||||
<Accordion title="7. 샌드박스 이미지 복구">
|
||||
샌드박싱이 활성화되어 있으면 doctor는 Docker 이미지를 검사하고, 현재 이미지가 없을 경우 빌드하거나 레거시 이름으로 전환하도록 제안합니다.
|
||||
샌드박스가 활성화되어 있으면 doctor는 Docker 이미지를 확인하고 현재 이미지가 없을 때 빌드하거나 레거시 이름으로 전환할 것을 제안합니다.
|
||||
</Accordion>
|
||||
<Accordion title="7b. Plugin 설치 정리">
|
||||
Doctor는 `openclaw doctor --fix` / `openclaw doctor --repair` 모드에서 레거시 OpenClaw 생성 Plugin 의존성 스테이징 상태를 제거합니다. 여기에는 오래된 생성 의존성 루트, 이전 설치 단계 디렉터리, 이전 번들 Plugin 의존성 복구 코드에서 남은 패키지 로컬 잔해, 현재 번들 manifest를 가릴 수 있는 고아 또는 복구된 번들 `@openclaw/*` Plugin의 관리형 npm 복사본이 포함됩니다.
|
||||
Doctor는 `openclaw doctor --fix` / `openclaw doctor --repair` 모드에서 레거시 OpenClaw 생성 Plugin 의존성 스테이징 상태를 제거합니다. 여기에는 오래된 생성 의존성 루트, 이전 설치 스테이지 디렉터리, 과거 번들 Plugin 의존성 복구 코드에서 남은 패키지 로컬 잔여물, 현재 번들 매니페스트를 가릴 수 있는 번들 `@openclaw/*` Plugin의 고아 또는 복구된 관리형 npm 사본이 포함됩니다.
|
||||
|
||||
Doctor는 설정에서 참조하지만 로컬 Plugin 레지스트리가 찾을 수 없는 누락된 다운로드 가능 Plugin도 다시 설치할 수 있습니다. 예로는 실질적인 `plugins.entries`, 설정된 채널/공급자/검색 설정, 설정된 에이전트 런타임이 있습니다. 패키지 업데이트 중에는 코어 패키지가 교체되는 동안 doctor가 패키지 관리자 Plugin 복구를 실행하지 않습니다. 설정된 Plugin에 여전히 복구가 필요하면 업데이트 후 `openclaw doctor --fix`를 다시 실행하세요. Gateway 시작과 설정 다시 로드는 패키지 관리자를 실행하지 않으며, Plugin 설치는 명시적인 doctor/install/update 작업으로 유지됩니다.
|
||||
Doctor는 설정에서 참조하지만 로컬 Plugin 레지스트리가 찾을 수 없는 다운로드 가능 Plugin도 다시 설치할 수 있습니다. 예시에는 실제 `plugins.entries`, 설정된 채널/provider/검색 설정, 설정된 에이전트 런타임이 포함됩니다. 패키지 업데이트 중에는 core 패키지가 교체되는 동안 doctor가 패키지 관리자 Plugin 복구를 실행하지 않습니다. 설정된 Plugin에 여전히 복구가 필요하면 업데이트 후 `openclaw doctor --fix`를 다시 실행하세요. Gateway 시작 및 설정 다시 로드는 패키지 관리자를 실행하지 않습니다. Plugin 설치는 명시적인 doctor/install/update 작업으로 유지됩니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="8. Gateway 서비스 마이그레이션 및 정리 힌트">
|
||||
Doctor는 레거시 gateway 서비스(launchd/systemd/schtasks)를 감지하고, 이를 제거한 뒤 현재 gateway 포트를 사용해 OpenClaw 서비스를 설치하도록 제안합니다. 추가 gateway 유사 서비스도 스캔하고 정리 힌트를 출력할 수 있습니다. 프로필 이름이 붙은 OpenClaw gateway 서비스는 일급 항목으로 간주되며 "추가"로 플래그되지 않습니다.
|
||||
Doctor는 레거시 gateway 서비스(launchd/systemd/schtasks)를 감지하고, 이를 제거한 뒤 현재 gateway 포트를 사용해 OpenClaw 서비스를 설치할 것을 제안합니다. 추가 gateway 유사 서비스를 스캔하고 정리 힌트를 출력할 수도 있습니다. 프로필 이름이 붙은 OpenClaw gateway 서비스는 일급 대상으로 간주되며 "extra"로 표시되지 않습니다.
|
||||
|
||||
Linux에서 사용자 수준 gateway 서비스가 없지만 시스템 수준 OpenClaw gateway 서비스가 있는 경우 doctor는 두 번째 사용자 수준 서비스를 자동으로 설치하지 않습니다. `openclaw gateway status --deep` 또는 `openclaw doctor --deep`으로 점검한 뒤, 중복 항목을 제거하거나 시스템 supervisor가 gateway 생명주기를 소유하는 경우 `OPENCLAW_SERVICE_REPAIR_POLICY=external`을 설정하세요.
|
||||
Linux에서 사용자 수준 gateway 서비스는 없지만 시스템 수준 OpenClaw gateway 서비스가 있으면 doctor는 두 번째 사용자 수준 서비스를 자동으로 설치하지 않습니다. `openclaw gateway status --deep` 또는 `openclaw doctor --deep`로 검사한 뒤, 중복 항목을 제거하거나 시스템 supervisor가 gateway 수명 주기를 소유하는 경우 `OPENCLAW_SERVICE_REPAIR_POLICY=external`을 설정하세요.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="8b. 시작 Matrix 마이그레이션">
|
||||
Matrix 채널 계정에 보류 중이거나 조치 가능한 레거시 상태 마이그레이션이 있으면 doctor는 (`--fix` / `--repair` 모드에서) 마이그레이션 전 스냅샷을 만든 다음 최선의 마이그레이션 단계인 레거시 Matrix 상태 마이그레이션과 레거시 암호화 상태 준비를 실행합니다. 두 단계 모두 치명적이지 않으며, 오류는 기록되고 시작은 계속됩니다. 읽기 전용 모드(`--fix` 없이 `openclaw doctor`)에서는 이 검사가 완전히 건너뛰어집니다.
|
||||
<Accordion title="8b. 시작 시 Matrix 마이그레이션">
|
||||
Matrix 채널 계정에 대기 중이거나 조치 가능한 레거시 상태 마이그레이션이 있으면 doctor는(`--fix` / `--repair` 모드에서) 마이그레이션 전 스냅샷을 만든 뒤 최선 노력 방식의 마이그레이션 단계인 레거시 Matrix 상태 마이그레이션과 레거시 암호화 상태 준비를 실행합니다. 두 단계 모두 치명적이지 않습니다. 오류는 로그에 기록되고 시작은 계속됩니다. 읽기 전용 모드(`--fix` 없이 `openclaw doctor`)에서는 이 검사를 완전히 건너뜁니다.
|
||||
</Accordion>
|
||||
<Accordion title="8c. 기기 페어링 및 인증 드리프트">
|
||||
Doctor는 이제 일반 상태 점검의 일부로 기기 페어링 상태를 검사합니다.
|
||||
|
||||
보고 항목:
|
||||
보고하는 항목은 다음과 같습니다.
|
||||
|
||||
- 보류 중인 최초 페어링 요청
|
||||
- 이미 페어링된 기기의 보류 중인 역할 업그레이드
|
||||
- 이미 페어링된 기기의 보류 중인 scope 업그레이드
|
||||
- 기기 id는 여전히 일치하지만 기기 identity가 승인된 record와 더 이상 일치하지 않는 공개 키 불일치 복구
|
||||
- 승인된 역할의 활성 token이 없는 페어링 record
|
||||
- scope가 승인된 페어링 기준선 밖으로 드리프트한 페어링 token
|
||||
- gateway 측 token rotation보다 오래되었거나 오래된 scope metadata를 지닌 현재 machine의 로컬 캐시 device-token 항목
|
||||
- 대기 중인 최초 페어링 요청
|
||||
- 이미 페어링된 기기의 대기 중인 역할 업그레이드
|
||||
- 이미 페어링된 기기의 대기 중인 scope 업그레이드
|
||||
- 기기 ID는 여전히 일치하지만 기기 identity가 승인된 레코드와 더 이상 일치하지 않는 공개 키 불일치 복구
|
||||
- 승인된 역할에 대한 활성 토큰이 누락된 페어링 레코드
|
||||
- scope가 승인된 페어링 baseline 밖으로 드리프트한 페어링 토큰
|
||||
- gateway 측 토큰 회전보다 오래되었거나 오래된 scope 메타데이터를 가진 현재 머신의 로컬 캐시 기기 토큰 항목
|
||||
|
||||
Doctor는 페어링 요청을 자동 승인하거나 기기 token을 자동 rotation하지 않습니다. 대신 정확한 다음 단계를 출력합니다.
|
||||
Doctor는 페어링 요청을 자동 승인하거나 기기 토큰을 자동 회전하지 않습니다. 대신 정확한 다음 단계를 출력합니다.
|
||||
|
||||
- `openclaw devices list`로 보류 중인 요청 점검
|
||||
- `openclaw devices list`로 대기 중인 요청 검사
|
||||
- `openclaw devices approve <requestId>`로 정확한 요청 승인
|
||||
- `openclaw devices rotate --device <deviceId> --role <role>`로 새 token rotation
|
||||
- `openclaw devices remove <deviceId>`로 오래된 record 제거 및 재승인
|
||||
- `openclaw devices rotate --device <deviceId> --role <role>`로 새 토큰 회전
|
||||
- `openclaw devices remove <deviceId>`로 오래된 레코드 제거 후 재승인
|
||||
|
||||
이는 흔한 "이미 페어링되었지만 여전히 페어링 필요가 표시됨" 문제를 해결합니다. doctor는 이제 최초 페어링, 보류 중인 역할/scope 업그레이드, 오래된 token/기기 identity 드리프트를 구분합니다.
|
||||
이는 흔한 "이미 페어링되었지만 여전히 페어링 필요가 표시됨" 문제를 해결합니다. doctor는 이제 최초 페어링, 대기 중인 역할/scope 업그레이드, 오래된 토큰/기기 identity 드리프트를 구분합니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="9. 보안 경고">
|
||||
Doctor는 공급자가 허용 목록 없이 DM에 열려 있거나 정책이 위험한 방식으로 설정되어 있을 때 경고를 출력합니다.
|
||||
Doctor는 provider가 allowlist 없이 DM에 열려 있거나 정책이 위험한 방식으로 설정되어 있을 때 경고를 출력합니다.
|
||||
</Accordion>
|
||||
<Accordion title="10. systemd linger(Linux)">
|
||||
systemd 사용자 서비스로 실행 중이면 doctor는 로그아웃 후에도 gateway가 계속 살아 있도록 lingering이 활성화되어 있는지 확인합니다.
|
||||
</Accordion>
|
||||
<Accordion title="11. 작업공간 상태(skills, plugins, legacy dirs)">
|
||||
Doctor는 기본 에이전트의 작업공간 상태 요약을 출력합니다.
|
||||
<Accordion title="11. 워크스페이스 상태(Skills, Plugin, 레거시 디렉터리)">
|
||||
Doctor는 기본 에이전트의 워크스페이스 상태 요약을 출력합니다.
|
||||
|
||||
- **Skills 상태**: 자격 있음, 요구 사항 누락, 허용 목록 차단 Skills 수를 계산합니다.
|
||||
- **레거시 작업공간 디렉터리**: 현재 작업공간과 함께 `~/openclaw` 또는 기타 레거시 작업공간 디렉터리가 있으면 경고합니다.
|
||||
- **Plugin 상태**: 활성화/비활성화/오류 Plugin 수를 계산하고, 오류가 있는 Plugin ID를 나열하며, 번들 Plugin 기능을 보고합니다.
|
||||
- **Plugin 호환성 경고**: 현재 런타임과 호환성 문제가 있는 Plugin에 플래그를 표시합니다.
|
||||
- **Plugin 진단**: Plugin 레지스트리가 로드 시 출력한 경고 또는 오류를 표시합니다.
|
||||
- **Skills 상태**: 적격, 요구 사항 누락, allowlist 차단 Skills 수를 셉니다.
|
||||
- **레거시 워크스페이스 디렉터리**: `~/openclaw` 또는 다른 레거시 워크스페이스 디렉터리가 현재 워크스페이스와 함께 존재할 때 경고합니다.
|
||||
- **Plugin 상태**: 활성화/비활성화/오류 Plugin 수를 셉니다. 오류가 있는 경우 Plugin ID를 나열하고 번들 Plugin capability를 보고합니다.
|
||||
- **Plugin 호환성 경고**: 현재 런타임과 호환성 문제가 있는 Plugin을 표시합니다.
|
||||
- **Plugin 진단**: Plugin 레지스트리에서 로드 시 출력한 경고나 오류를 표시합니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="11b. Bootstrap 파일 크기">
|
||||
Doctor는 작업공간 bootstrap 파일(예: `AGENTS.md`, `CLAUDE.md` 또는 기타 삽입된 컨텍스트 파일)이 설정된 문자 예산에 가깝거나 초과했는지 확인합니다. 파일별 원시 문자 수와 삽입된 문자 수, 잘림 비율, 잘림 원인(`max/file` 또는 `max/total`), 전체 예산 대비 총 삽입 문자 비율을 보고합니다. 파일이 잘렸거나 제한에 가까우면 doctor는 `agents.defaults.bootstrapMaxChars`와 `agents.defaults.bootstrapTotalMaxChars` 조정 팁을 출력합니다.
|
||||
Doctor는 워크스페이스 bootstrap 파일(예: `AGENTS.md`, `CLAUDE.md` 또는 기타 주입된 컨텍스트 파일)이 설정된 문자 예산에 가깝거나 초과했는지 확인합니다. 파일별 raw 문자 수와 주입된 문자 수, 잘림 비율, 잘림 원인(`max/file` 또는 `max/total`), 전체 예산 대비 총 주입 문자 비율을 보고합니다. 파일이 잘렸거나 제한에 가까우면 doctor는 `agents.defaults.bootstrapMaxChars` 및 `agents.defaults.bootstrapTotalMaxChars` 조정 팁을 출력합니다.
|
||||
</Accordion>
|
||||
<Accordion title="11d. 오래된 채널 Plugin 정리">
|
||||
`openclaw doctor --fix`가 누락된 채널 Plugin을 제거할 때, 해당 Plugin을 참조하던 dangling 채널 범위 설정도 제거합니다. `channels.<id>` 항목, 해당 채널을 이름으로 지정한 Heartbeat 대상, `agents.*.models["<channel>/*"]` override가 포함됩니다. 이렇게 하면 채널 런타임은 사라졌지만 설정이 여전히 gateway에 바인딩을 요청하여 발생하는 Gateway 부팅 루프를 방지합니다.
|
||||
`openclaw doctor --fix`가 누락된 채널 Plugin을 제거할 때, 해당 Plugin을 참조하던 매달린 채널 범위 설정도 제거합니다. `channels.<id>` 항목, 채널 이름을 지정한 Heartbeat 대상, `agents.*.models["<channel>/*"]` override가 여기에 포함됩니다. 이렇게 하면 채널 런타임은 사라졌지만 설정이 여전히 gateway에 바인딩을 요청하는 Gateway 부팅 루프를 방지합니다.
|
||||
</Accordion>
|
||||
<Accordion title="11c. 셸 완성">
|
||||
Doctor는 현재 셸(zsh, bash, fish 또는 PowerShell)에 탭 완성이 설치되어 있는지 확인합니다.
|
||||
<Accordion title="11c. 셸 completion">
|
||||
Doctor는 현재 셸(zsh, bash, fish, PowerShell)에 탭 completion이 설치되어 있는지 확인합니다.
|
||||
|
||||
- 셸 프로필이 느린 동적 완성 패턴(`source <(openclaw completion ...)`)을 사용하면 doctor는 더 빠른 캐시 파일 방식으로 업그레이드합니다.
|
||||
- 완성이 프로필에 설정되어 있지만 캐시 파일이 없으면 doctor가 캐시를 자동으로 다시 생성합니다.
|
||||
- 완성이 전혀 설정되어 있지 않으면 doctor가 설치 여부를 묻습니다(대화형 모드에서만, `--non-interactive`에서는 건너뜀).
|
||||
- 셸 프로필이 느린 동적 completion 패턴(`source <(openclaw completion ...)`)을 사용하면 doctor가 더 빠른 캐시 파일 변형으로 업그레이드합니다.
|
||||
- completion이 프로필에 설정되어 있지만 캐시 파일이 없으면 doctor가 캐시를 자동으로 다시 생성합니다.
|
||||
- completion이 전혀 설정되어 있지 않으면 doctor가 설치할지 묻습니다(대화형 모드에서만, `--non-interactive`에서는 건너뜀).
|
||||
|
||||
캐시를 수동으로 다시 생성하려면 `openclaw completion --write-state`를 실행하세요.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="12. Gateway 인증 검사(로컬 token)">
|
||||
Doctor는 로컬 gateway token 인증 준비 상태를 확인합니다.
|
||||
<Accordion title="12. Gateway 인증 검사(로컬 토큰)">
|
||||
Doctor는 로컬 gateway 토큰 인증 준비 상태를 확인합니다.
|
||||
|
||||
- token 모드에 token이 필요하지만 token 소스가 없으면 doctor가 생성을 제안합니다.
|
||||
- `gateway.auth.token`이 SecretRef로 관리되지만 사용할 수 없으면 doctor가 경고하고 이를 평문으로 덮어쓰지 않습니다.
|
||||
- `openclaw doctor --generate-gateway-token`은 token SecretRef가 설정되어 있지 않을 때만 생성을 강제합니다.
|
||||
- 토큰 모드에 토큰이 필요하지만 토큰 소스가 없으면 doctor가 생성할 것을 제안합니다.
|
||||
- `gateway.auth.token`이 SecretRef 관리형이지만 사용할 수 없으면 doctor가 경고하고 이를 평문으로 덮어쓰지 않습니다.
|
||||
- `openclaw doctor --generate-gateway-token`은 토큰 SecretRef가 설정되어 있지 않을 때만 생성을 강제합니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="12b. 읽기 전용 SecretRef 인식 복구">
|
||||
일부 복구 흐름은 런타임 fail-fast 동작을 약화하지 않고 설정된 자격 증명을 검사해야 합니다.
|
||||
일부 복구 흐름은 런타임 fail-fast 동작을 약화하지 않으면서 설정된 자격 증명을 검사해야 합니다.
|
||||
|
||||
- `openclaw doctor --fix`는 이제 대상 지정 config 복구에 대해 status 계열 명령과 동일한 읽기 전용 SecretRef 요약 모델을 사용합니다.
|
||||
- 예: Telegram `allowFrom` / `groupAllowFrom` `@username` 복구는 사용 가능할 때 구성된 봇 자격 증명을 사용하려고 시도합니다.
|
||||
- Telegram 봇 토큰이 SecretRef를 통해 구성되었지만 현재 명령 경로에서 사용할 수 없는 경우, doctor는 자격 증명이 구성되었지만 사용할 수 없다고 보고하고, 토큰이 누락되었다고 잘못 보고하거나 충돌하는 대신 자동 해결을 건너뜁니다.
|
||||
- `openclaw doctor --fix`는 이제 대상 지정 구성 복구에 상태 계열 명령과 동일한 읽기 전용 SecretRef 요약 모델을 사용합니다.
|
||||
- 예: Telegram `allowFrom` / `groupAllowFrom` `@username` 복구는 사용 가능한 경우 구성된 봇 자격 증명을 사용하려고 시도합니다.
|
||||
- Telegram 봇 토큰이 SecretRef를 통해 구성되어 있지만 현재 명령 경로에서 사용할 수 없는 경우, doctor는 토큰이 누락되었다고 잘못 보고하거나 충돌하는 대신 자격 증명이 구성되었지만 사용할 수 없다고 보고하고 자동 확인을 건너뜁니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="13. Gateway 상태 검사 + 재시작">
|
||||
Doctor는 상태 검사를 실행하고 Gateway가 비정상으로 보일 때 재시작을 제안합니다.
|
||||
<Accordion title="13. Gateway 상태 확인 + 재시작">
|
||||
Doctor는 상태 확인을 실행하고 Gateway가 비정상으로 보일 때 재시작을 제안합니다.
|
||||
</Accordion>
|
||||
<Accordion title="13b. 메모리 검색 준비 상태">
|
||||
Doctor는 구성된 메모리 검색 임베딩 공급자가 기본 에이전트에 대해 준비되었는지 확인합니다. 동작은 구성된 백엔드와 공급자에 따라 달라집니다.
|
||||
|
||||
- **QMD 백엔드**: `qmd` 바이너리를 사용할 수 있고 시작할 수 있는지 검사합니다. 그렇지 않으면 npm 패키지와 수동 바이너리 경로 옵션을 포함한 수정 안내를 출력합니다.
|
||||
- **명시적 로컬 공급자**: 로컬 모델 파일 또는 인식되는 원격/다운로드 가능한 모델 URL을 확인합니다. 누락된 경우 원격 공급자로 전환할 것을 제안합니다.
|
||||
- **명시적 원격 공급자**(`openai`, `voyage` 등): API 키가 환경 또는 인증 저장소에 있는지 확인합니다. 누락된 경우 실행 가능한 수정 힌트를 출력합니다.
|
||||
- **자동 공급자**: 먼저 로컬 모델 가용성을 확인한 다음, 자동 선택 순서에 따라 각 원격 공급자를 시도합니다.
|
||||
- **QMD 백엔드**: `qmd` 바이너리를 사용할 수 있고 시작 가능한지 검사합니다. 그렇지 않으면 npm 패키지와 수동 바이너리 경로 옵션을 포함한 수정 지침을 출력합니다.
|
||||
- **명시적 로컬 공급자**: 로컬 모델 파일 또는 인식 가능한 원격/다운로드 가능 모델 URL을 확인합니다. 없으면 원격 공급자로 전환할 것을 제안합니다.
|
||||
- **명시적 원격 공급자**(`openai`, `voyage` 등): API 키가 환경 또는 인증 저장소에 있는지 확인합니다. 없으면 실행 가능한 수정 힌트를 출력합니다.
|
||||
- **자동 공급자**: 먼저 로컬 모델 가용성을 확인한 다음, 자동 선택 순서대로 각 원격 공급자를 시도합니다.
|
||||
|
||||
캐시된 Gateway 검사 결과를 사용할 수 있는 경우(검사 시점에 Gateway가 정상 상태였던 경우), doctor는 그 결과를 CLI에서 볼 수 있는 config와 교차 확인하고 불일치를 기록합니다. Doctor는 기본 경로에서 새 임베딩 ping을 시작하지 않습니다. 실시간 공급자 확인이 필요하면 deep 메모리 상태 명령을 사용하세요.
|
||||
캐시된 Gateway 검사 결과를 사용할 수 있는 경우(확인 시점에 Gateway가 정상 상태였음), doctor는 해당 결과를 CLI에서 볼 수 있는 구성과 대조하고 불일치를 기록합니다. Doctor는 기본 경로에서 새 임베딩 핑을 시작하지 않습니다. 실시간 공급자 확인이 필요하면 심층 메모리 상태 명령을 사용하세요.
|
||||
|
||||
런타임에서 임베딩 준비 상태를 확인하려면 `openclaw memory status --deep`를 사용하세요.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="14. 채널 상태 경고">
|
||||
Gateway가 정상인 경우, doctor는 채널 상태 검사를 실행하고 제안된 수정 사항과 함께 경고를 보고합니다.
|
||||
Gateway가 정상 상태이면 doctor는 채널 상태 검사를 실행하고 제안된 수정 사항과 함께 경고를 보고합니다.
|
||||
</Accordion>
|
||||
<Accordion title="15. Supervisor config 감사 + 복구">
|
||||
Doctor는 설치된 supervisor config(launchd/systemd/schtasks)에 누락되었거나 오래된 기본값(예: systemd network-online 종속성 및 재시작 지연)이 있는지 확인합니다. 불일치를 발견하면 업데이트를 권장하고 서비스 파일/작업을 현재 기본값으로 다시 작성할 수 있습니다.
|
||||
<Accordion title="15. Supervisor 구성 감사 + 복구">
|
||||
Doctor는 설치된 supervisor 구성(launchd/systemd/schtasks)에 누락되었거나 오래된 기본값(예: systemd network-online 종속성과 재시작 지연)이 있는지 확인합니다. 불일치를 찾으면 업데이트를 권장하고 서비스 파일/작업을 현재 기본값으로 다시 작성할 수 있습니다.
|
||||
|
||||
참고:
|
||||
|
||||
- `openclaw doctor`는 supervisor config를 다시 쓰기 전에 확인을 요청합니다.
|
||||
- `openclaw doctor`는 supervisor 구성을 다시 작성하기 전에 확인을 요청합니다.
|
||||
- `openclaw doctor --yes`는 기본 복구 프롬프트를 수락합니다.
|
||||
- `openclaw doctor --repair`는 권장 수정 사항을 프롬프트 없이 적용합니다.
|
||||
- `openclaw doctor --repair --force`는 사용자 지정 supervisor config를 덮어씁니다.
|
||||
- `OPENCLAW_SERVICE_REPAIR_POLICY=external`은 Gateway 서비스 수명 주기에 대해 doctor를 읽기 전용으로 유지합니다. 서비스 상태를 계속 보고하고 서비스 외 복구를 실행하지만, 외부 supervisor가 해당 수명 주기를 소유하므로 서비스 설치/시작/재시작/부트스트랩, supervisor config 재작성, 레거시 서비스 정리는 건너뜁니다.
|
||||
- Linux에서 doctor는 일치하는 systemd Gateway 유닛이 활성 상태일 때 명령/엔트리포인트 메타데이터를 다시 쓰지 않습니다. 또한 중복 서비스 스캔 중 비활성 비레거시 추가 Gateway 유사 유닛을 무시하므로 companion 서비스 파일이 정리 잡음을 만들지 않습니다.
|
||||
- 토큰 인증에 토큰이 필요하고 `gateway.auth.token`이 SecretRef로 관리되는 경우, doctor 서비스 설치/복구는 SecretRef를 검증하지만 해결된 평문 토큰 값을 supervisor 서비스 환경 메타데이터에 유지하지 않습니다.
|
||||
- Doctor는 이전 LaunchAgent, systemd 또는 Windows Scheduled Task 설치가 인라인으로 포함한 관리형 `.env`/SecretRef 기반 서비스 환경 값을 감지하고, 해당 값이 supervisor 정의가 아니라 런타임 소스에서 로드되도록 서비스 메타데이터를 다시 작성합니다.
|
||||
- Doctor는 `gateway.port`가 변경된 후에도 서비스 명령이 오래된 `--port`를 계속 고정하는 경우를 감지하고, 서비스 메타데이터를 현재 포트로 다시 작성합니다.
|
||||
- 토큰 인증에 토큰이 필요하고 구성된 토큰 SecretRef가 해결되지 않은 경우, doctor는 실행 가능한 안내와 함께 설치/복구 경로를 차단합니다.
|
||||
- `openclaw doctor --repair`는 프롬프트 없이 권장 수정 사항을 적용합니다.
|
||||
- `openclaw doctor --repair --force`는 사용자 지정 supervisor 구성을 덮어씁니다.
|
||||
- `OPENCLAW_SERVICE_REPAIR_POLICY=external`은 Gateway 서비스 수명 주기에 대해 doctor를 읽기 전용으로 유지합니다. 여전히 서비스 상태를 보고하고 서비스가 아닌 복구를 실행하지만, 외부 supervisor가 해당 수명 주기를 소유하므로 서비스 설치/시작/재시작/bootstrap, supervisor 구성 재작성, 레거시 서비스 정리를 건너뜁니다.
|
||||
- Linux에서 doctor는 일치하는 systemd Gateway 유닛이 활성 상태일 때 명령/엔트리포인트 메타데이터를 다시 작성하지 않습니다. 또한 중복 서비스 스캔 중 비활성 비레거시 추가 Gateway 유사 유닛을 무시하여 동반 서비스 파일이 정리 잡음을 만들지 않게 합니다.
|
||||
- 토큰 인증에 토큰이 필요하고 `gateway.auth.token`이 SecretRef로 관리되는 경우, doctor 서비스 설치/복구는 SecretRef를 검증하지만 확인된 일반 텍스트 토큰 값을 supervisor 서비스 환경 메타데이터에 유지하지 않습니다.
|
||||
- Doctor는 이전 LaunchAgent, systemd 또는 Windows Scheduled Task 설치가 인라인으로 포함한 관리형 `.env`/SecretRef 기반 서비스 환경 값을 감지하고, 해당 값이 supervisor 정의 대신 런타임 소스에서 로드되도록 서비스 메타데이터를 다시 작성합니다.
|
||||
- Doctor는 `gateway.port` 변경 후 서비스 명령이 여전히 이전 `--port`를 고정하고 있는 경우를 감지하고 서비스 메타데이터를 현재 포트로 다시 작성합니다.
|
||||
- 토큰 인증에 토큰이 필요하고 구성된 토큰 SecretRef가 확인되지 않은 경우, doctor는 실행 가능한 지침과 함께 설치/복구 경로를 차단합니다.
|
||||
- `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있고 `gateway.auth.mode`가 설정되지 않은 경우, doctor는 모드가 명시적으로 설정될 때까지 설치/복구를 차단합니다.
|
||||
- Linux 사용자 systemd 유닛의 경우, doctor 토큰 드리프트 검사는 이제 서비스 인증 메타데이터를 비교할 때 `Environment=`와 `EnvironmentFile=` 소스를 모두 포함합니다.
|
||||
- Doctor 서비스 복구는 config가 더 최신 버전에 의해 마지막으로 작성된 경우, 더 오래된 OpenClaw 바이너리의 Gateway 서비스를 다시 쓰거나 중지하거나 재시작하지 않습니다. [Gateway 문제 해결](/ko/gateway/troubleshooting#split-brain-installs-and-newer-config-guard)을 참조하세요.
|
||||
- 언제든지 `openclaw gateway install --force`를 통해 전체 재작성을 강제할 수 있습니다.
|
||||
- Linux 사용자 systemd 유닛의 경우, doctor 토큰 드리프트 확인은 이제 서비스 인증 메타데이터를 비교할 때 `Environment=`와 `EnvironmentFile=` 소스를 모두 포함합니다.
|
||||
- 구성은 더 새로운 버전에서 마지막으로 작성되었는데 Gateway 서비스가 이전 OpenClaw 바이너리에서 실행 중인 경우, doctor 서비스 복구는 해당 서비스를 다시 작성하거나 중지하거나 재시작하지 않습니다. [Gateway 문제 해결](/ko/gateway/troubleshooting#split-brain-installs-and-newer-config-guard)을 참조하세요.
|
||||
- `openclaw gateway install --force`를 통해 언제든 전체 재작성을 강제할 수 있습니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="16. Gateway 런타임 + 포트 진단">
|
||||
Doctor는 서비스 런타임(PID, 마지막 종료 상태)을 검사하고, 서비스가 설치되어 있지만 실제로 실행 중이 아닐 때 경고합니다. 또한 Gateway 포트(기본값 `18789`)의 포트 충돌을 확인하고 가능한 원인(Gateway가 이미 실행 중, SSH 터널)을 보고합니다.
|
||||
Doctor는 서비스 런타임(PID, 마지막 종료 상태)을 검사하고 서비스가 설치되어 있지만 실제로 실행 중이 아닌 경우 경고합니다. 또한 Gateway 포트(기본값 `18789`)의 포트 충돌을 확인하고 가능한 원인(Gateway가 이미 실행 중, SSH 터널)을 보고합니다.
|
||||
</Accordion>
|
||||
<Accordion title="17. Gateway 런타임 모범 사례">
|
||||
Doctor는 Gateway 서비스가 Bun 또는 버전 관리 Node 경로(`nvm`, `fnm`, `volta`, `asdf` 등)에서 실행될 때 경고합니다. WhatsApp + Telegram 채널에는 Node가 필요하며, 버전 관리자 경로는 서비스가 셸 초기화를 로드하지 않기 때문에 업그레이드 후 중단될 수 있습니다. Doctor는 사용 가능한 경우 시스템 Node 설치(Homebrew/apt/choco)로 마이그레이션할 것을 제안합니다.
|
||||
Doctor는 Gateway 서비스가 Bun 또는 버전 관리 Node 경로(`nvm`, `fnm`, `volta`, `asdf` 등)에서 실행될 때 경고합니다. WhatsApp + Telegram 채널에는 Node가 필요하며, 서비스가 셸 초기화를 로드하지 않기 때문에 버전 관리자 경로는 업그레이드 후 중단될 수 있습니다. Doctor는 사용 가능한 경우 시스템 Node 설치(Homebrew/apt/choco)로 마이그레이션하도록 제안합니다.
|
||||
|
||||
새로 설치되거나 복구된 macOS LaunchAgent는 대화형 셸 PATH를 복사하는 대신 표준 시스템 PATH(`/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`)를 사용하므로 Volta, asdf, fnm, pnpm 및 기타 버전 관리자 디렉터리가 Node 자식 프로세스가 해석되는 위치를 변경하지 않습니다. Linux 서비스는 여전히 명시적 환경 루트(`NVM_DIR`, `FNM_DIR`, `VOLTA_HOME`, `ASDF_DATA_DIR`, `BUN_INSTALL`, `PNPM_HOME`)와 안정적인 사용자 bin 디렉터리를 유지하지만, 추정된 버전 관리자 대체 디렉터리는 해당 디렉터리가 디스크에 존재할 때만 서비스 PATH에 기록됩니다.
|
||||
새로 설치되거나 복구된 macOS LaunchAgent는 대화형 셸 PATH를 복사하는 대신 표준 시스템 PATH(`/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`)를 사용하므로 Volta, asdf, fnm, pnpm 및 기타 버전 관리자 디렉터리가 어떤 Node 자식 프로세스가 확인되는지 변경하지 않습니다. Linux 서비스는 여전히 명시적 환경 루트(`NVM_DIR`, `FNM_DIR`, `VOLTA_HOME`, `ASDF_DATA_DIR`, `BUN_INSTALL`, `PNPM_HOME`)와 안정적인 사용자 bin 디렉터리를 유지하지만, 추정된 버전 관리자 대체 디렉터리는 해당 디렉터리가 디스크에 존재할 때만 서비스 PATH에 기록됩니다.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="18. Config 쓰기 + 마법사 메타데이터">
|
||||
Doctor는 모든 config 변경 사항을 유지하고 doctor 실행을 기록하도록 마법사 메타데이터를 찍습니다.
|
||||
<Accordion title="18. 구성 쓰기 + 마법사 메타데이터">
|
||||
Doctor는 모든 구성 변경 사항을 유지하고 doctor 실행을 기록하도록 마법사 메타데이터에 스탬프를 찍습니다.
|
||||
</Accordion>
|
||||
<Accordion title="19. Workspace 팁(백업 + 메모리 시스템)">
|
||||
Doctor는 누락된 경우 workspace 메모리 시스템을 제안하고, workspace가 아직 git 아래에 있지 않은 경우 백업 팁을 출력합니다.
|
||||
<Accordion title="19. 워크스페이스 팁(백업 + 메모리 시스템)">
|
||||
Doctor는 워크스페이스 메모리 시스템이 없으면 이를 제안하고, 워크스페이스가 아직 git 아래에 있지 않으면 백업 팁을 출력합니다.
|
||||
|
||||
Workspace 구조와 git 백업(비공개 GitHub 또는 GitLab 권장)에 대한 전체 가이드는 [/concepts/agent-workspace](/ko/concepts/agent-workspace)를 참조하세요.
|
||||
워크스페이스 구조와 git 백업(비공개 GitHub 또는 GitLab 권장)에 대한 전체 가이드는 [/concepts/agent-workspace](/ko/concepts/agent-workspace)를 참조하세요.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [Gateway 실행 안내서](/ko/gateway)
|
||||
- [Gateway 런북](/ko/gateway)
|
||||
- [Gateway 문제 해결](/ko/gateway/troubleshooting)
|
||||
|
||||
@ -1,76 +1,78 @@
|
||||
---
|
||||
read_when:
|
||||
- 로컬 설치 대신 컨테이너화된 Gateway를 사용하려는 경우
|
||||
- 로컬 설치 대신 컨테이너화된 Gateway를 원하는 경우
|
||||
- Docker 흐름을 검증하고 있습니다
|
||||
summary: OpenClaw용 선택적 Docker 기반 설정 및 온보딩
|
||||
title: Docker
|
||||
x-i18n:
|
||||
generated_at: "2026-05-02T20:55:35Z"
|
||||
generated_at: "2026-05-05T08:26:03Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 5e57659c89a0b207b4b331752e7faaa814fe1f0043dad97043e95e460286c551
|
||||
source_hash: f57db2ec12f1a1fd681ec90cc43b2c945755a9240f571de46688777e957f1b8e
|
||||
source_path: install/docker.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Docker는 **선택 사항**입니다. 컨테이너화된 Gateway가 필요하거나 Docker 흐름을 검증하려는 경우에만 사용하세요.
|
||||
Docker는 **선택 사항**입니다. 컨테이너화된 Gateway를 사용하거나 Docker 흐름을 검증하려는 경우에만 사용하세요.
|
||||
|
||||
## Docker가 나에게 적합한가요?
|
||||
|
||||
- **예**: 격리된 일회용 Gateway 환경이 필요하거나 로컬 설치 없이 호스트에서 OpenClaw를 실행하려는 경우입니다.
|
||||
- **아니요**: 자체 머신에서 실행 중이고 가장 빠른 개발 루프만 원하는 경우입니다. 대신 일반 설치 흐름을 사용하세요.
|
||||
- **샌드박싱 참고**: 기본 샌드박스 백엔드는 샌드박싱이 활성화된 경우 Docker를 사용하지만, 샌드박싱은 기본적으로 꺼져 있으며 전체 Gateway를 Docker에서 실행할 필요는 **없습니다**. SSH 및 OpenShell 샌드박스 백엔드도 사용할 수 있습니다. [샌드박싱](/ko/gateway/sandboxing)을 참고하세요.
|
||||
- **예**: 격리된 일회용 Gateway 환경을 원하거나 로컬 설치 없이 호스트에서 OpenClaw를 실행하려는 경우입니다.
|
||||
- **아니요**: 본인 머신에서 실행 중이고 가장 빠른 개발 루프만 원하는 경우입니다. 대신 일반 설치 흐름을 사용하세요.
|
||||
- **샌드박싱 참고**: 기본 샌드박스 백엔드는 샌드박싱이 활성화된 경우 Docker를 사용하지만, 샌드박싱은 기본적으로 꺼져 있으며 전체 Gateway를 Docker에서 실행할 필요는 **없습니다**. SSH 및 OpenShell 샌드박스 백엔드도 사용할 수 있습니다. [샌드박싱](/ko/gateway/sandboxing)을 참조하세요.
|
||||
|
||||
## 필수 조건
|
||||
## 사전 요구 사항
|
||||
|
||||
- Docker Desktop(또는 Docker Engine) + Docker Compose v2
|
||||
- 이미지 빌드용 RAM 최소 2GB(`pnpm install`은 1GB 호스트에서 exit 137로 OOM 종료될 수 있음)
|
||||
- 이미지 빌드를 위한 최소 2GB RAM(`pnpm install`은 1GB 호스트에서 exit 137로 OOM 종료될 수 있음)
|
||||
- 이미지와 로그를 위한 충분한 디스크 공간
|
||||
- VPS/공개 호스트에서 실행하는 경우, 특히 Docker `DOCKER-USER` 방화벽 정책을 포함해
|
||||
- VPS/공개 호스트에서 실행하는 경우
|
||||
[네트워크 노출을 위한 보안 강화](/ko/gateway/security)를 검토하세요.
|
||||
특히 Docker `DOCKER-USER` 방화벽 정책을 확인하세요.
|
||||
|
||||
## 컨테이너화된 Gateway
|
||||
|
||||
<Steps>
|
||||
<Step title="이미지 빌드">
|
||||
리포지토리 루트에서 설정 스크립트를 실행하세요.
|
||||
저장소 루트에서 설정 스크립트를 실행하세요.
|
||||
|
||||
```bash
|
||||
./scripts/docker/setup.sh
|
||||
```
|
||||
|
||||
그러면 Gateway 이미지가 로컬에서 빌드됩니다. 대신 미리 빌드된 이미지를 사용하려면:
|
||||
이 명령은 Gateway 이미지를 로컬에서 빌드합니다. 대신 사전 빌드된 이미지를 사용하려면 다음을 실행하세요.
|
||||
|
||||
```bash
|
||||
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
|
||||
./scripts/docker/setup.sh
|
||||
```
|
||||
|
||||
미리 빌드된 이미지는
|
||||
사전 빌드된 이미지는
|
||||
[GitHub Container Registry](https://github.com/openclaw/openclaw/pkgs/container/openclaw)에 게시됩니다.
|
||||
일반 태그: `main`, `latest`, `<version>`(예: `2026.2.26`).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="온보딩 완료">
|
||||
설정 스크립트는 온보딩을 자동으로 실행합니다. 다음 작업을 수행합니다.
|
||||
설정 스크립트는 온보딩을 자동으로 실행합니다. 이 스크립트는 다음을 수행합니다.
|
||||
|
||||
- 제공자 API 키 입력 요청
|
||||
- 공급자 API 키 입력 요청
|
||||
- Gateway 토큰 생성 및 `.env`에 기록
|
||||
- Docker Compose를 통해 Gateway 시작
|
||||
|
||||
설정 중에는 시작 전 온보딩과 config 쓰기가
|
||||
설정 중에는 시작 전 온보딩과 구성 쓰기가
|
||||
`openclaw-gateway`를 통해 직접 실행됩니다. `openclaw-cli`는
|
||||
Gateway 컨테이너가 이미 존재한 뒤 실행하는 명령용입니다.
|
||||
Gateway 컨테이너가 이미 존재한 뒤 실행하는 명령에 사용됩니다.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Control UI 열기">
|
||||
<Step title="제어 UI 열기">
|
||||
브라우저에서 `http://127.0.0.1:18789/`를 열고 구성된
|
||||
공유 비밀을 Settings에 붙여넣으세요. 설정 스크립트는 기본적으로 `.env`에 토큰을 기록합니다.
|
||||
컨테이너 config를 비밀번호 인증으로 전환했다면 대신 해당 비밀번호를 사용하세요.
|
||||
공유 시크릿을 Settings에 붙여넣으세요. 설정 스크립트는 기본적으로
|
||||
토큰을 `.env`에 기록합니다. 컨테이너 구성을 비밀번호 인증으로 전환한 경우
|
||||
대신 해당 비밀번호를 사용하세요.
|
||||
|
||||
URL이 다시 필요하신가요?
|
||||
URL이 다시 필요한가요?
|
||||
|
||||
```bash
|
||||
docker compose run --rm openclaw-cli dashboard --no-open
|
||||
@ -99,7 +101,7 @@ Docker는 **선택 사항**입니다. 컨테이너화된 Gateway가 필요하거
|
||||
|
||||
### 수동 흐름
|
||||
|
||||
설정 스크립트를 사용하는 대신 각 단계를 직접 실행하려면:
|
||||
설정 스크립트를 사용하는 대신 각 단계를 직접 실행하려면 다음을 사용하세요.
|
||||
|
||||
```bash
|
||||
docker build -t openclaw:local -f Dockerfile .
|
||||
@ -111,53 +113,52 @@ docker compose up -d openclaw-gateway
|
||||
```
|
||||
|
||||
<Note>
|
||||
리포지토리 루트에서 `docker compose`를 실행하세요. `OPENCLAW_EXTRA_MOUNTS`
|
||||
또는 `OPENCLAW_HOME_VOLUME`을 활성화한 경우 설정 스크립트가 `docker-compose.extra.yml`을 기록합니다.
|
||||
저장소 루트에서 `docker compose`를 실행하세요. `OPENCLAW_EXTRA_MOUNTS`
|
||||
또는 `OPENCLAW_HOME_VOLUME`을 활성화한 경우 설정 스크립트가 `docker-compose.extra.yml`을 작성합니다.
|
||||
`-f docker-compose.yml -f docker-compose.extra.yml`로 포함하세요.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
`openclaw-cli`는 `openclaw-gateway`의 네트워크 네임스페이스를 공유하므로
|
||||
시작 후 도구입니다. `docker compose up -d openclaw-gateway` 전에
|
||||
온보딩과 설정 시점의 config 쓰기는 `--no-deps --entrypoint node`와 함께
|
||||
시작 후 도구입니다. `docker compose up -d openclaw-gateway` 전에 온보딩과
|
||||
설정 시점의 구성 쓰기는 `--no-deps --entrypoint node`와 함께
|
||||
`openclaw-gateway`를 통해 실행하세요.
|
||||
</Note>
|
||||
|
||||
### 환경 변수
|
||||
|
||||
설정 스크립트는 다음 선택적 환경 변수를 허용합니다.
|
||||
설정 스크립트는 다음 선택적 환경 변수를 받습니다.
|
||||
|
||||
| 변수 | 목적 |
|
||||
| ------------------------------------------ | --------------------------------------------------------------- |
|
||||
| `OPENCLAW_IMAGE` | 로컬 빌드 대신 원격 이미지 사용 |
|
||||
| `OPENCLAW_DOCKER_APT_PACKAGES` | 빌드 중 추가 apt 패키지 설치(공백으로 구분) |
|
||||
| `OPENCLAW_EXTENSIONS` | 빌드 시 선택한 번들 Plugin 헬퍼 포함 |
|
||||
| `OPENCLAW_IMAGE` | 로컬 빌드 대신 원격 이미지 사용 |
|
||||
| `OPENCLAW_DOCKER_APT_PACKAGES` | 빌드 중 추가 apt 패키지 설치(공백으로 구분) |
|
||||
| `OPENCLAW_EXTENSIONS` | 빌드 시 선택한 번들 Plugin 헬퍼 포함 |
|
||||
| `OPENCLAW_EXTRA_MOUNTS` | 추가 호스트 바인드 마운트(쉼표로 구분된 `source:target[:opts]`) |
|
||||
| `OPENCLAW_HOME_VOLUME` | 명명된 Docker 볼륨에 `/home/node` 유지 |
|
||||
| `OPENCLAW_HOME_VOLUME` | 명명된 Docker 볼륨에 `/home/node` 유지 |
|
||||
| `OPENCLAW_SANDBOX` | 샌드박스 부트스트랩 사용(`1`, `true`, `yes`, `on`) |
|
||||
| `OPENCLAW_SKIP_ONBOARDING` | 대화형 온보딩 단계 건너뛰기(`1`, `true`, `yes`, `on`) |
|
||||
| `OPENCLAW_DOCKER_SOCKET` | Docker 소켓 경로 재정의 |
|
||||
| `OPENCLAW_DISABLE_BONJOUR` | Bonjour/mDNS 광고 비활성화(Docker의 기본값은 `1`) |
|
||||
| `OPENCLAW_DISABLE_BUNDLED_SOURCE_OVERLAYS` | 번들 Plugin 소스 바인드 마운트 오버레이 비활성화 |
|
||||
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OpenTelemetry 내보내기용 공유 OTLP/HTTP 수집기 엔드포인트 |
|
||||
| `OTEL_EXPORTER_OTLP_*_ENDPOINT` | 트레이스, 메트릭 또는 로그용 신호별 OTLP 엔드포인트 |
|
||||
| `OTEL_EXPORTER_OTLP_PROTOCOL` | OTLP 프로토콜 재정의. 현재는 `http/protobuf`만 지원 |
|
||||
| `OPENCLAW_DOCKER_SOCKET` | Docker 소켓 경로 재정의 |
|
||||
| `OPENCLAW_DISABLE_BONJOUR` | Bonjour/mDNS 광고 비활성화(Docker에서는 기본값 `1`) |
|
||||
| `OPENCLAW_DISABLE_BUNDLED_SOURCE_OVERLAYS` | 번들 Plugin 소스 바인드 마운트 오버레이 비활성화 |
|
||||
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OpenTelemetry 내보내기용 공유 OTLP/HTTP 수집기 엔드포인트 |
|
||||
| `OTEL_EXPORTER_OTLP_*_ENDPOINT` | 트레이스, 메트릭 또는 로그용 신호별 OTLP 엔드포인트 |
|
||||
| `OTEL_EXPORTER_OTLP_PROTOCOL` | OTLP 프로토콜 재정의. 현재는 `http/protobuf`만 지원 |
|
||||
| `OTEL_SERVICE_NAME` | OpenTelemetry 리소스에 사용되는 서비스 이름 |
|
||||
| `OTEL_SEMCONV_STABILITY_OPT_IN` | 최신 실험적 GenAI 시맨틱 속성 사용 |
|
||||
| `OPENCLAW_OTEL_PRELOADED` | 하나가 미리 로드된 경우 두 번째 OpenTelemetry SDK 시작 건너뛰기 |
|
||||
| `OTEL_SEMCONV_STABILITY_OPT_IN` | 최신 실험적 GenAI 의미론 속성 사용 |
|
||||
| `OPENCLAW_OTEL_PRELOADED` | 하나가 사전 로드된 경우 두 번째 OpenTelemetry SDK 시작 건너뛰기 |
|
||||
|
||||
관리자는 예를 들어
|
||||
`OPENCLAW_EXTRA_MOUNTS=/path/to/fork/extensions/synology-chat:/app/extensions/synology-chat:ro`처럼
|
||||
하나의 Plugin 소스 디렉터리를 패키징된 소스 경로 위에 마운트하여
|
||||
패키징된 이미지에 대해 번들 Plugin 소스를 테스트할 수 있습니다.
|
||||
해당 마운트된 소스 디렉터리는 동일한 Plugin ID에 대해 일치하는 컴파일된
|
||||
관리자는 하나의 Plugin 소스 디렉터리를 패키지된 소스 경로 위에 마운트하여
|
||||
패키지 이미지에 대해 번들 Plugin 소스를 테스트할 수 있습니다. 예:
|
||||
`OPENCLAW_EXTRA_MOUNTS=/path/to/fork/extensions/synology-chat:/app/extensions/synology-chat:ro`.
|
||||
해당 마운트된 소스 디렉터리는 같은 Plugin id에 대해 일치하는 컴파일된
|
||||
`/app/dist/extensions/synology-chat` 번들을 재정의합니다.
|
||||
|
||||
### 관측성
|
||||
### 관측 가능성
|
||||
|
||||
OpenTelemetry 내보내기는 Gateway 컨테이너에서 OTLP 수집기로 나가는 방향입니다.
|
||||
게시된 Docker 포트가 필요하지 않습니다. 이미지를 로컬에서 빌드하고
|
||||
번들 OpenTelemetry 내보내기 도구를 이미지 안에서 사용할 수 있게 하려면
|
||||
번들 OpenTelemetry 내보내기를 이미지 안에서 사용할 수 있게 하려면
|
||||
런타임 의존성을 포함하세요.
|
||||
|
||||
```bash
|
||||
@ -167,38 +168,39 @@ export OTEL_SERVICE_NAME="openclaw-gateway"
|
||||
./scripts/docker/setup.sh
|
||||
```
|
||||
|
||||
내보내기를 활성화하기 전에 패키징된 Docker 설치에서 ClawHub의 공식
|
||||
`@openclaw/diagnostics-otel` Plugin을 설치하세요. 사용자 지정 소스 빌드 이미지는
|
||||
`OPENCLAW_EXTENSIONS=diagnostics-otel`로 로컬 Plugin 소스를 계속 포함할 수 있습니다.
|
||||
내보내기를 활성화하려면 config에서 `diagnostics-otel` Plugin을 허용하고 활성화한 다음
|
||||
`diagnostics.otel.enabled=true`를 설정하거나 [OpenTelemetry 내보내기](/ko/gateway/opentelemetry)의
|
||||
config 예제를 사용하세요. 수집기 인증 헤더는 Docker 환경 변수가 아니라
|
||||
`diagnostics.otel.headers`를 통해 구성됩니다.
|
||||
패키지된 Docker 설치에서 내보내기를 활성화하기 전에 ClawHub에서
|
||||
공식 `@openclaw/diagnostics-otel` Plugin을 설치하세요. 사용자 지정 소스 빌드
|
||||
이미지는 여전히 `OPENCLAW_EXTENSIONS=diagnostics-otel`로 로컬 Plugin 소스를
|
||||
포함할 수 있습니다. 내보내기를 활성화하려면 구성에서 `diagnostics-otel`
|
||||
Plugin을 허용하고 활성화한 뒤 `diagnostics.otel.enabled=true`를 설정하거나
|
||||
[OpenTelemetry 내보내기](/ko/gateway/opentelemetry)의 구성 예시를 사용하세요.
|
||||
수집기 인증 헤더는 Docker 환경 변수가 아니라 `diagnostics.otel.headers`를
|
||||
통해 구성됩니다.
|
||||
|
||||
Prometheus 메트릭은 이미 게시된 Gateway 포트를 사용합니다.
|
||||
`clawhub:@openclaw/diagnostics-prometheus`를 설치하고
|
||||
`diagnostics-prometheus` Plugin을 활성화한 다음 스크레이프하세요.
|
||||
`diagnostics-prometheus` Plugin을 활성화한 뒤 스크레이프하세요.
|
||||
|
||||
```text
|
||||
http://<gateway-host>:18789/api/diagnostics/prometheus
|
||||
```
|
||||
|
||||
이 라우트는 Gateway 인증으로 보호됩니다. 별도의 공개
|
||||
`/metrics` 포트나 인증되지 않은 리버스 프록시 경로를 노출하지 마세요.
|
||||
[Prometheus 메트릭](/ko/gateway/prometheus)을 참고하세요.
|
||||
이 라우트는 Gateway 인증으로 보호됩니다. 별도의 공개 `/metrics` 포트나
|
||||
인증되지 않은 리버스 프록시 경로를 노출하지 마세요.
|
||||
[Prometheus 메트릭](/ko/gateway/prometheus)을 참조하세요.
|
||||
|
||||
### 상태 확인
|
||||
|
||||
컨테이너 프로브 엔드포인트(인증 불필요):
|
||||
컨테이너 프로브 엔드포인트(인증 필요 없음):
|
||||
|
||||
```bash
|
||||
curl -fsS http://127.0.0.1:18789/healthz # liveness
|
||||
curl -fsS http://127.0.0.1:18789/readyz # readiness
|
||||
```
|
||||
|
||||
Docker 이미지에는 `/healthz`에 ping을 보내는 내장 `HEALTHCHECK`가 포함되어 있습니다.
|
||||
확인이 계속 실패하면 Docker가 컨테이너를 `unhealthy`로 표시하고
|
||||
오케스트레이션 시스템이 이를 재시작하거나 교체할 수 있습니다.
|
||||
Docker 이미지에는 `/healthz`를 ping하는 내장 `HEALTHCHECK`가 포함되어 있습니다.
|
||||
검사가 계속 실패하면 Docker는 컨테이너를 `unhealthy`로 표시하고
|
||||
오케스트레이션 시스템이 이를 다시 시작하거나 교체할 수 있습니다.
|
||||
|
||||
인증된 심층 상태 스냅샷:
|
||||
|
||||
@ -206,86 +208,86 @@ Docker 이미지에는 `/healthz`에 ping을 보내는 내장 `HEALTHCHECK`가
|
||||
docker compose exec openclaw-gateway node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN"
|
||||
```
|
||||
|
||||
### LAN과 loopback 비교
|
||||
### LAN과 loopback
|
||||
|
||||
`scripts/docker/setup.sh`는 기본적으로 `OPENCLAW_GATEWAY_BIND=lan`을 설정하므로
|
||||
Docker 포트 게시를 통해 호스트에서 `http://127.0.0.1:18789`에 접근할 수 있습니다.
|
||||
|
||||
- `lan`(기본값): 호스트 브라우저와 호스트 CLI가 게시된 Gateway 포트에 도달할 수 있습니다.
|
||||
- `loopback`: 컨테이너 네트워크 네임스페이스 내부의 프로세스만
|
||||
Gateway에 직접 도달할 수 있습니다.
|
||||
- `lan`(기본값): 호스트 브라우저와 호스트 CLI가 게시된 Gateway 포트에 접근할 수 있습니다.
|
||||
- `loopback`: 컨테이너 네트워크 네임스페이스 안의 프로세스만 Gateway에 직접 접근할 수 있습니다.
|
||||
|
||||
<Note>
|
||||
`0.0.0.0` 또는 `127.0.0.1` 같은 호스트 별칭이 아니라
|
||||
`gateway.bind`의 바인드 모드 값(`lan` / `loopback` / `custom` /
|
||||
`tailnet` / `auto`)을 사용하세요.
|
||||
`gateway.bind`에는 호스트 별칭인 `0.0.0.0` 또는 `127.0.0.1`이 아니라
|
||||
바인드 모드 값(`lan` / `loopback` / `custom` / `tailnet` / `auto`)을 사용하세요.
|
||||
</Note>
|
||||
|
||||
### 호스트 로컬 제공자
|
||||
### 호스트 로컬 공급자
|
||||
|
||||
OpenClaw가 Docker에서 실행될 때 컨테이너 내부의 `127.0.0.1`은
|
||||
호스트 머신이 아니라 컨테이너 자체입니다. 호스트에서 실행되는 AI 제공자에는
|
||||
`host.docker.internal`을 사용하세요.
|
||||
OpenClaw가 Docker에서 실행될 때 컨테이너 내부의 `127.0.0.1`은 호스트 머신이 아니라
|
||||
컨테이너 자체입니다. 호스트에서 실행되는 AI 공급자에는 `host.docker.internal`을 사용하세요.
|
||||
|
||||
| 제공자 | 호스트 기본 URL | Docker 설정 URL |
|
||||
| 공급자 | 호스트 기본 URL | Docker 설정 URL |
|
||||
| --------- | ------------------------ | ----------------------------------- |
|
||||
| LM Studio | `http://127.0.0.1:1234` | `http://host.docker.internal:1234` |
|
||||
| Ollama | `http://127.0.0.1:11434` | `http://host.docker.internal:11434` |
|
||||
|
||||
번들 Docker 설정은 LM Studio와 Ollama 온보딩 기본값으로 해당 호스트 URL을 사용하며,
|
||||
`docker-compose.yml`은 Linux Docker Engine용 Docker의 호스트 Gateway에
|
||||
`host.docker.internal`을 매핑합니다. Docker Desktop은 macOS와 Windows에서
|
||||
이미 동일한 호스트 이름을 제공합니다.
|
||||
번들 Docker 설정은 해당 호스트 URL을 LM Studio 및 Ollama 온보딩 기본값으로 사용하며,
|
||||
`docker-compose.yml`은 Linux Docker Engine에서 `host.docker.internal`을
|
||||
Docker의 호스트 Gateway에 매핑합니다. Docker Desktop은 macOS와 Windows에서
|
||||
이미 같은 호스트 이름을 제공합니다.
|
||||
|
||||
호스트 서비스도 Docker에서 도달 가능한 주소에서 수신 대기해야 합니다.
|
||||
호스트 서비스도 Docker에서 접근 가능한 주소에서 수신해야 합니다.
|
||||
|
||||
```bash
|
||||
lms server start --port 1234 --bind 0.0.0.0
|
||||
OLLAMA_HOST=0.0.0.0:11434 ollama serve
|
||||
```
|
||||
|
||||
자체 Compose 파일이나 `docker run` 명령을 사용하는 경우, 예를 들어
|
||||
`--add-host=host.docker.internal:host-gateway`처럼 동일한 호스트 매핑을 직접 추가하세요.
|
||||
자체 Compose 파일이나 `docker run` 명령을 사용하는 경우 같은 호스트
|
||||
매핑을 직접 추가하세요. 예:
|
||||
`--add-host=host.docker.internal:host-gateway`.
|
||||
|
||||
### Bonjour / mDNS
|
||||
|
||||
Docker 브리지 네트워킹은 일반적으로 Bonjour/mDNS 멀티캐스트
|
||||
(`224.0.0.251:5353`)를 안정적으로 전달하지 않습니다. 따라서 번들 Compose 설정은
|
||||
기본적으로 `OPENCLAW_DISABLE_BONJOUR=1`로 설정되어, 브리지가 멀티캐스트 트래픽을
|
||||
드롭할 때 Gateway가 크래시 루프에 빠지거나 광고를 반복 재시작하지 않도록 합니다.
|
||||
기본적으로 `OPENCLAW_DISABLE_BONJOUR=1`을 설정하여 브리지가 멀티캐스트 트래픽을
|
||||
드롭할 때 Gateway가 크래시 루프에 빠지거나 광고를 반복해서 다시 시작하지 않도록 합니다.
|
||||
|
||||
Docker 호스트에는 게시된 Gateway URL, Tailscale 또는 광역 DNS-SD를 사용하세요.
|
||||
호스트 네트워킹, macvlan 또는 mDNS 멀티캐스트가 동작하는 것으로 알려진 다른 네트워크에서
|
||||
호스트 네트워킹, macvlan 또는 mDNS 멀티캐스트가 작동한다고 알려진 다른 네트워크에서
|
||||
실행하는 경우에만 `OPENCLAW_DISABLE_BONJOUR=0`을 설정하세요.
|
||||
|
||||
주의 사항과 문제 해결은 [Bonjour 검색](/ko/gateway/bonjour)을 참고하세요.
|
||||
주의 사항과 문제 해결은 [Bonjour 검색](/ko/gateway/bonjour)을 참조하세요.
|
||||
|
||||
### 저장소 및 지속성
|
||||
### 스토리지와 지속성
|
||||
|
||||
Docker Compose는 `OPENCLAW_CONFIG_DIR`를 `/home/node/.openclaw`에,
|
||||
`OPENCLAW_WORKSPACE_DIR`를 `/home/node/.openclaw/workspace`에 바인드 마운트하므로
|
||||
해당 경로는 컨테이너 교체 후에도 유지됩니다. 두 변수 중 하나라도 설정되지 않은 경우
|
||||
번들 `docker-compose.yml`은 `${HOME}/.openclaw`(워크스페이스 마운트는
|
||||
`${HOME}/.openclaw/workspace`)로 폴백하거나, `HOME` 자체도 없으면 `/tmp/.openclaw`로
|
||||
폴백합니다. 이렇게 하면 기본 환경에서 `docker compose up`이 빈 소스 볼륨 사양을
|
||||
내보내지 않습니다.
|
||||
해당 경로는 컨테이너 교체 후에도 유지됩니다. 두 변수 중 하나가 설정되지 않은 경우
|
||||
번들 `docker-compose.yml`은 `${HOME}/.openclaw`(워크스페이스 마운트의 경우
|
||||
`${HOME}/.openclaw/workspace`)로 대체되며, `HOME` 자체도 없는 경우
|
||||
`/tmp/.openclaw`로 대체됩니다. 이렇게 하면 기본 환경에서 `docker compose up`이
|
||||
빈 소스 볼륨 사양을 출력하지 않습니다.
|
||||
|
||||
해당 마운트된 config 디렉터리는 OpenClaw가 다음을 보관하는 위치입니다.
|
||||
해당 마운트된 구성 디렉터리는 OpenClaw가 다음을 보관하는 위치입니다.
|
||||
|
||||
- 동작 config용 `openclaw.json`
|
||||
- 저장된 제공자 OAuth/API 키 인증용 `agents/<agentId>/agent/auth-profiles.json`
|
||||
- `OPENCLAW_GATEWAY_TOKEN` 같은 env 기반 런타임 비밀용 `.env`
|
||||
- 동작 구성을 위한 `openclaw.json`
|
||||
- 저장된 공급자 OAuth/API 키 인증을 위한 `agents/<agentId>/agent/auth-profiles.json`
|
||||
- `OPENCLAW_GATEWAY_TOKEN` 같은 환경 기반 런타임 시크릿을 위한 `.env`
|
||||
|
||||
설치된 다운로드 가능 Plugin은 패키지 상태를 마운트된 OpenClaw 홈 아래에 저장하므로,
|
||||
설치된 다운로드 가능 Plugin은 패키지 상태를 마운트된 OpenClaw 홈 아래에 저장하므로
|
||||
Plugin 설치 기록과 패키지 루트는 컨테이너 교체 후에도 유지됩니다.
|
||||
Gateway 시작은 번들 Plugin 의존성 트리를 생성하지 않습니다.
|
||||
|
||||
VM 배포의 전체 지속성 세부 정보는
|
||||
[Docker VM 런타임 - 무엇이 어디에 유지되는가](/ko/install/docker-vm-runtime#what-persists-where)를 참고하세요.
|
||||
[Docker VM 런타임 - 무엇이 어디에 유지되는가](/ko/install/docker-vm-runtime#what-persists-where)를 참조하세요.
|
||||
|
||||
**디스크 증가 주요 지점:** `/tmp/openclaw/` 아래의 `media/`, 세션 JSONL 파일, `cron/runs/*.jsonl`, 설치된 Plugin 패키지 루트, 순환 파일 로그를 확인하세요.
|
||||
**디스크 사용량 증가 주요 지점:** `media/`, 세션 JSONL 파일,
|
||||
`cron/runs/*.jsonl`, 설치된 Plugin 패키지 루트, `/tmp/openclaw/` 아래의
|
||||
롤링 파일 로그를 확인하세요.
|
||||
|
||||
### 셸 헬퍼(선택 사항)
|
||||
### 셸 도우미(선택 사항)
|
||||
|
||||
일상적인 Docker 관리를 더 쉽게 하려면 `ClawDock`을 설치하세요.
|
||||
|
||||
@ -294,19 +296,20 @@ mkdir -p ~/.clawdock && curl -sL https://raw.githubusercontent.com/openclaw/open
|
||||
echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc && source ~/.zshrc
|
||||
```
|
||||
|
||||
이전 `scripts/shell-helpers/clawdock-helpers.sh` 원시 경로에서 ClawDock을 설치했다면, 로컬 헬퍼 파일이 새 위치를 따라가도록 위 설치 명령을 다시 실행하세요.
|
||||
이전 `scripts/shell-helpers/clawdock-helpers.sh` 원시 경로에서 ClawDock을 설치했다면, 위의 설치 명령을 다시 실행하여 로컬 도우미 파일이 새 위치를 따르도록 하세요.
|
||||
|
||||
그런 다음 `clawdock-start`, `clawdock-stop`, `clawdock-dashboard` 등을 사용하세요. 모든 명령은 `clawdock-help`를 실행해 확인하세요.
|
||||
전체 헬퍼 가이드는 [ClawDock](/ko/install/clawdock)을 참고하세요.
|
||||
그런 다음 `clawdock-start`, `clawdock-stop`, `clawdock-dashboard` 등을 사용하세요. 모든 명령은
|
||||
`clawdock-help`를 실행해 확인하세요.
|
||||
전체 도우미 가이드는 [ClawDock](/ko/install/clawdock)을 참조하세요.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Docker Gateway용 에이전트 샌드박스 활성화">
|
||||
<Accordion title="Docker gateway용 에이전트 샌드박스 활성화">
|
||||
```bash
|
||||
export OPENCLAW_SANDBOX=1
|
||||
./scripts/docker/setup.sh
|
||||
```
|
||||
|
||||
사용자 지정 소켓 경로(예: rootless Docker):
|
||||
사용자 지정 소켓 경로(예: 루트리스 Docker):
|
||||
|
||||
```bash
|
||||
export OPENCLAW_SANDBOX=1
|
||||
@ -314,7 +317,9 @@ echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc && source ~/.zshrc
|
||||
./scripts/docker/setup.sh
|
||||
```
|
||||
|
||||
스크립트는 샌드박스 필수 조건을 통과한 뒤에만 `docker.sock`을 마운트합니다. 샌드박스 설정을 완료할 수 없으면 스크립트가 `agents.defaults.sandbox.mode`를 `off`로 재설정합니다.
|
||||
스크립트는 샌드박스 필수 조건을 통과한 후에만 `docker.sock`을 마운트합니다. 샌드박스
|
||||
설정을 완료할 수 없으면 스크립트는 `agents.defaults.sandbox.mode`를
|
||||
`off`로 재설정합니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -329,11 +334,16 @@ echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc && source ~/.zshrc
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="공유 네트워크 보안 참고">
|
||||
`openclaw-cli`는 CLI 명령이 `127.0.0.1`을 통해 Gateway에 도달할 수 있도록 `network_mode: "service:openclaw-gateway"`를 사용합니다. 이를 공유 신뢰 경계로 취급하세요. Compose 구성은 `NET_RAW`/`NET_ADMIN`을 제거하고 `openclaw-cli`에서 `no-new-privileges`를 활성화합니다.
|
||||
`openclaw-cli`는 `network_mode: "service:openclaw-gateway"`를 사용하므로 CLI
|
||||
명령이 `127.0.0.1`을 통해 gateway에 도달할 수 있습니다. 이를 공유
|
||||
신뢰 경계로 취급하세요. Compose 구성은 `NET_RAW`/`NET_ADMIN`을 제거하고
|
||||
`openclaw-gateway`와 `openclaw-cli` 모두에서
|
||||
`no-new-privileges`를 활성화합니다.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="권한 및 EACCES">
|
||||
이미지는 `node`(uid 1000)로 실행됩니다. `/home/node/.openclaw`에서 권한 오류가 보이면 호스트 바인드 마운트가 uid 1000 소유인지 확인하세요.
|
||||
이미지는 `node`(uid 1000)로 실행됩니다. `/home/node/.openclaw`에서 권한 오류가
|
||||
표시되면 호스트 바인드 마운트가 uid 1000 소유인지 확인하세요.
|
||||
|
||||
```bash
|
||||
sudo chown -R 1000:1000 /path/to/openclaw-config /path/to/openclaw-workspace
|
||||
@ -342,7 +352,8 @@ echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc && source ~/.zshrc
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="더 빠른 재빌드">
|
||||
의존성 레이어가 캐시되도록 Dockerfile 순서를 구성하세요. 이렇게 하면 lockfile이 변경되지 않는 한 `pnpm install`을 다시 실행하지 않아도 됩니다.
|
||||
의존성 레이어가 캐시되도록 Dockerfile 순서를 정하세요. 이렇게 하면 락파일이 변경되지 않는 한
|
||||
`pnpm install`을 다시 실행하지 않아도 됩니다.
|
||||
|
||||
```dockerfile
|
||||
FROM node:24-bookworm
|
||||
@ -365,43 +376,57 @@ echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc && source ~/.zshrc
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="고급 사용자용 컨테이너 옵션">
|
||||
기본 이미지는 보안을 우선하며 비루트 `node`로 실행됩니다. 더 많은 기능이 포함된 컨테이너가 필요하다면:
|
||||
기본 이미지는 보안 우선이며 루트가 아닌 `node`로 실행됩니다. 더 많은 기능을 갖춘
|
||||
컨테이너를 사용하려면:
|
||||
|
||||
1. **`/home/node` 유지**: `export OPENCLAW_HOME_VOLUME="openclaw_home"`
|
||||
2. **시스템 의존성 포함**: `export OPENCLAW_DOCKER_APT_PACKAGES="git curl jq"`
|
||||
2. **시스템 의존성 내장**: `export OPENCLAW_DOCKER_APT_PACKAGES="git curl jq"`
|
||||
3. **Playwright 브라우저 설치**:
|
||||
```bash
|
||||
docker compose run --rm openclaw-cli \
|
||||
node /app/node_modules/playwright-core/cli.js install chromium
|
||||
```
|
||||
4. **브라우저 다운로드 유지**: `PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright`를 설정하고 `OPENCLAW_HOME_VOLUME` 또는 `OPENCLAW_EXTRA_MOUNTS`를 사용하세요.
|
||||
4. **브라우저 다운로드 유지**: `PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright`를 설정하고
|
||||
`OPENCLAW_HOME_VOLUME` 또는 `OPENCLAW_EXTRA_MOUNTS`를 사용하세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="OpenAI Codex OAuth(헤드리스 Docker)">
|
||||
마법사에서 OpenAI Codex OAuth를 선택하면 브라우저 URL이 열립니다. Docker 또는 헤드리스 설정에서는 도착한 전체 리디렉션 URL을 복사해 마법사에 다시 붙여 넣어 인증을 완료하세요.
|
||||
마법사에서 OpenAI Codex OAuth를 선택하면 브라우저 URL이 열립니다. Docker 또는 헤드리스
|
||||
설정에서는 도착한 전체 리디렉션 URL을 복사해 마법사에 다시 붙여넣어 인증을 완료하세요.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="베이스 이미지 메타데이터">
|
||||
기본 Docker 런타임 이미지는 `node:24-bookworm-slim`을 사용하며 `org.opencontainers.image.base.name`, `org.opencontainers.image.source` 등을 포함한 OCI 베이스 이미지 주석을 게시합니다. Node 베이스 다이제스트는 Dependabot Docker 베이스 이미지 PR을 통해 갱신됩니다. 릴리스 빌드는 배포판 업그레이드 레이어를 실행하지 않습니다. [OCI 이미지 주석](https://github.com/opencontainers/image-spec/blob/main/annotations.md)을 참고하세요.
|
||||
<Accordion title="기본 이미지 메타데이터">
|
||||
기본 Docker 런타임 이미지는 `node:24-bookworm-slim`을 사용하며
|
||||
`org.opencontainers.image.base.name`, `org.opencontainers.image.source` 등을 포함한 OCI
|
||||
기본 이미지 주석을 게시합니다. Node 기본 다이제스트는 Dependabot Docker 기본 이미지 PR을 통해
|
||||
갱신됩니다. 릴리스 빌드는 배포판 업그레이드 레이어를 실행하지 않습니다. 다음을 참조하세요:
|
||||
[OCI 이미지 주석](https://github.com/opencontainers/image-spec/blob/main/annotations.md).
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### VPS에서 실행하나요?
|
||||
|
||||
바이너리 포함, 지속성, 업데이트를 포함한 공유 VM 배포 단계는 [Hetzner(Docker VPS)](/ko/install/hetzner) 및 [Docker VM 런타임](/ko/install/docker-vm-runtime)을 참고하세요.
|
||||
바이너리 내장, 지속성, 업데이트를 포함한 공유 VM 배포 단계는
|
||||
[Hetzner(Docker VPS)](/ko/install/hetzner) 및
|
||||
[Docker VM Runtime](/ko/install/docker-vm-runtime)을 참조하세요.
|
||||
|
||||
## 에이전트 샌드박스
|
||||
|
||||
Docker 백엔드로 `agents.defaults.sandbox`를 활성화하면 Gateway 자체는 호스트에 남아 있고, Gateway는 격리된 Docker 컨테이너 안에서 에이전트 도구 실행(셸, 파일 읽기/쓰기 등)을 실행합니다. 이렇게 하면 전체 Gateway를 컨테이너화하지 않고도 신뢰할 수 없거나 멀티 테넌트인 에이전트 세션 주변에 단단한 장벽을 둘 수 있습니다.
|
||||
Docker 백엔드로 `agents.defaults.sandbox`를 활성화하면, gateway는
|
||||
에이전트 도구 실행(셸, 파일 읽기/쓰기 등)을 격리된 Docker 컨테이너 안에서 실행하고
|
||||
gateway 자체는 호스트에 유지합니다. 이를 통해 전체 gateway를 컨테이너화하지 않고도
|
||||
신뢰할 수 없거나 다중 테넌트 에이전트 세션을 단단한 경계 안에 둘 수 있습니다.
|
||||
|
||||
샌드박스 범위는 에이전트별(기본값), 세션별 또는 공유로 설정할 수 있습니다. 각 범위에는 `/workspace`에 마운트되는 자체 작업 공간이 제공됩니다. 도구 허용/거부 정책, 네트워크 격리, 리소스 제한, 브라우저 컨테이너도 구성할 수 있습니다.
|
||||
샌드박스 범위는 에이전트별(기본값), 세션별 또는 공유로 설정할 수 있습니다. 각 범위에는
|
||||
`/workspace`에 마운트되는 자체 워크스페이스가 제공됩니다. 허용/차단 도구 정책,
|
||||
네트워크 격리, 리소스 제한, 브라우저 컨테이너도 구성할 수 있습니다.
|
||||
|
||||
전체 구성, 이미지, 보안 참고, 멀티 에이전트 프로필은 다음을 참고하세요.
|
||||
전체 구성, 이미지, 보안 참고, 다중 에이전트 프로필은 다음을 참조하세요.
|
||||
|
||||
- [샌드박싱](/ko/gateway/sandboxing) -- 전체 샌드박스 참조
|
||||
- [OpenShell](/ko/gateway/openshell) -- 샌드박스 컨테이너에 대한 대화형 셸 액세스
|
||||
- [멀티 에이전트 샌드박스 및 도구](/ko/tools/multi-agent-sandbox-tools) -- 에이전트별 재정의
|
||||
- [샌드박싱](/ko/gateway/sandboxing) -- 전체 샌드박스 참고 자료
|
||||
- [OpenShell](/ko/gateway/openshell) -- 샌드박스 컨테이너에 대한 대화형 셸 접근
|
||||
- [다중 에이전트 샌드박스 및 도구](/ko/tools/multi-agent-sandbox-tools) -- 에이전트별 재정의
|
||||
|
||||
### 빠른 활성화
|
||||
|
||||
@ -418,36 +443,41 @@ Docker 백엔드로 `agents.defaults.sandbox`를 활성화하면 Gateway 자체
|
||||
}
|
||||
```
|
||||
|
||||
기본 샌드박스 이미지를 빌드하세요(소스 체크아웃에서):
|
||||
기본 샌드박스 이미지를 빌드하세요(소스 체크아웃에서).
|
||||
|
||||
```bash
|
||||
scripts/sandbox-setup.sh
|
||||
```
|
||||
|
||||
소스 체크아웃이 없는 npm 설치의 경우, 인라인 `docker build` 명령은 [샌드박싱 § 이미지 및 설정](/ko/gateway/sandboxing#images-and-setup)을 참고하세요.
|
||||
소스 체크아웃 없는 npm 설치의 경우, 인라인 `docker build` 명령은 [샌드박싱 § 이미지 및 설정](/ko/gateway/sandboxing#images-and-setup)을 참조하세요.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="이미지가 없거나 샌드박스 컨테이너가 시작되지 않음">
|
||||
[`scripts/sandbox-setup.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/sandbox-setup.sh)(소스 체크아웃) 또는 [샌드박싱 § 이미지 및 설정](/ko/gateway/sandboxing#images-and-setup)의 인라인 `docker build` 명령(npm 설치)으로 샌드박스 이미지를 빌드하거나, `agents.defaults.sandbox.docker.image`를 사용자 지정 이미지로 설정하세요.
|
||||
[`scripts/sandbox-setup.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/sandbox-setup.sh)
|
||||
(소스 체크아웃) 또는 [샌드박싱 § 이미지 및 설정](/ko/gateway/sandboxing#images-and-setup)의 인라인 `docker build` 명령(npm 설치)으로
|
||||
샌드박스 이미지를 빌드하거나, `agents.defaults.sandbox.docker.image`를 사용자 지정 이미지로 설정하세요.
|
||||
컨테이너는 필요할 때 세션별로 자동 생성됩니다.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="샌드박스의 권한 오류">
|
||||
`docker.user`를 마운트된 작업 공간 소유권과 일치하는 UID:GID로 설정하거나, 작업 공간 폴더의 소유자를 변경하세요.
|
||||
마운트된 워크스페이스 소유권과 일치하는 UID:GID로 `docker.user`를 설정하거나
|
||||
워크스페이스 폴더에 chown을 실행하세요.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="샌드박스에서 사용자 지정 도구를 찾을 수 없음">
|
||||
OpenClaw는 `/etc/profile`을 소싱하고 PATH를 재설정할 수 있는 `sh -lc`(로그인 셸)로 명령을 실행합니다. 사용자 지정 도구 경로를 앞에 추가하도록 `docker.env.PATH`를 설정하거나 Dockerfile의 `/etc/profile.d/` 아래에 스크립트를 추가하세요.
|
||||
<Accordion title="사용자 지정 도구를 샌드박스에서 찾을 수 없음">
|
||||
OpenClaw는 `/etc/profile`을 소스하고 PATH를 재설정할 수 있는 `sh -lc`(로그인 셸)로
|
||||
명령을 실행합니다. 사용자 지정 도구 경로가 앞에 오도록 `docker.env.PATH`를 설정하거나,
|
||||
Dockerfile에서 `/etc/profile.d/` 아래에 스크립트를 추가하세요.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="이미지 빌드 중 OOM으로 종료됨(종료 137)">
|
||||
VM에는 최소 2GB RAM이 필요합니다. 더 큰 머신 클래스를 사용하고 다시 시도하세요.
|
||||
VM에는 최소 2GB RAM이 필요합니다. 더 큰 머신 클래스를 사용한 뒤 다시 시도하세요.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Control UI에서 권한 없음 또는 페어링 필요">
|
||||
새 대시보드 링크를 가져오고 브라우저 장치를 승인하세요.
|
||||
새 대시보드 링크를 가져와 브라우저 디바이스를 승인하세요.
|
||||
|
||||
```bash
|
||||
docker compose run --rm openclaw-cli dashboard --no-open
|
||||
@ -455,12 +485,12 @@ scripts/sandbox-setup.sh
|
||||
docker compose run --rm openclaw-cli devices approve <requestId>
|
||||
```
|
||||
|
||||
자세한 내용: [대시보드](/ko/web/dashboard), [장치](/ko/cli/devices).
|
||||
자세한 내용: [대시보드](/ko/web/dashboard), [디바이스](/ko/cli/devices).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Gateway 대상이 ws://172.x.x.x로 표시되거나 Docker CLI에서 페어링 오류 발생">
|
||||
Gateway 모드와 바인딩을 재설정하세요.
|
||||
Gateway 모드와 바인드를 재설정하세요.
|
||||
|
||||
```bash
|
||||
docker compose run --rm openclaw-cli config set --batch-json '[{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"lan"}]'
|
||||
@ -476,4 +506,4 @@ scripts/sandbox-setup.sh
|
||||
- [Podman](/ko/install/podman) — Docker의 Podman 대안
|
||||
- [ClawDock](/ko/install/clawdock) — Docker Compose 커뮤니티 설정
|
||||
- [업데이트](/ko/install/updating) — OpenClaw를 최신 상태로 유지
|
||||
- [구성](/ko/gateway/configuration) — 설치 후 Gateway 구성
|
||||
- [구성](/ko/gateway/configuration) — 설치 후 gateway 구성
|
||||
|
||||
@ -1,30 +1,30 @@
|
||||
---
|
||||
read_when:
|
||||
- 세션 ID, 대화 기록 JSONL 또는 sessions.json 필드를 디버그해야 하는 경우
|
||||
- 자동 Compaction 동작을 변경하거나 “Compaction 전” 정리 작업을 추가하고 있습니다
|
||||
- 메모리 플러시 또는 무음 시스템 턴을 구현하려는 경우
|
||||
summary: '심층 분석: 세션 저장소 + 트랜스크립트, 수명 주기 및 (자동)Compaction 내부 구조'
|
||||
- 세션 ID, 트랜스크립트 JSONL 또는 sessions.json 필드를 디버그해야 합니다
|
||||
- 자동 Compaction 동작을 변경하거나 “사전 Compaction” 정리 작업을 추가하는 경우
|
||||
- 메모리 플러시 또는 조용한 시스템 턴을 구현하려는 경우
|
||||
summary: '심층 분석: 세션 저장소 + 트랜스크립트, 생명주기 및 (자동)Compaction 내부 구조'
|
||||
title: 세션 관리 심층 분석
|
||||
x-i18n:
|
||||
generated_at: "2026-05-02T21:13:15Z"
|
||||
generated_at: "2026-05-05T08:26:21Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 8271d7b0786e1c47a8cec6e7bd73c3c86a433d629e17937fdd87fa756ed78d73
|
||||
source_hash: 3161dd9c98bff7ea24266f44a9261693d8a9ee2b47d9af2d152de7057016748b
|
||||
source_path: reference/session-management-compaction.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
OpenClaw는 다음 영역 전반에서 세션을 처음부터 끝까지 관리합니다.
|
||||
OpenClaw는 다음 영역 전반에서 세션을 엔드투엔드로 관리합니다:
|
||||
|
||||
- **세션 라우팅**(인바운드 메시지가 `sessionKey`에 매핑되는 방식)
|
||||
- **세션 저장소**(`sessions.json`)와 추적 항목
|
||||
- **트랜스크립트 지속성**(`*.jsonl`)과 그 구조
|
||||
- **트랜스크립트 위생**(실행 전 공급자별 수정)
|
||||
- **컨텍스트 제한**(컨텍스트 창과 추적된 토큰)
|
||||
- **컨텍스트 제한**(컨텍스트 창과 추적 토큰)
|
||||
- **Compaction**(수동 및 자동 Compaction)과 Compaction 전 작업을 연결할 위치
|
||||
- **무음 관리 작업**(사용자에게 보이는 출력을 만들지 않아야 하는 메모리 쓰기)
|
||||
- **조용한 하우스키핑**(사용자에게 표시되는 출력을 생성해서는 안 되는 메모리 쓰기)
|
||||
|
||||
먼저 더 높은 수준의 개요를 보고 싶다면 다음에서 시작하세요.
|
||||
먼저 더 높은 수준의 개요를 보고 싶다면 다음부터 시작하세요:
|
||||
|
||||
- [세션 관리](/ko/concepts/session)
|
||||
- [Compaction](/ko/concepts/compaction)
|
||||
@ -35,31 +35,31 @@ OpenClaw는 다음 영역 전반에서 세션을 처음부터 끝까지 관리
|
||||
|
||||
---
|
||||
|
||||
## 신뢰할 수 있는 출처: Gateway
|
||||
## 진실의 원천: Gateway
|
||||
|
||||
OpenClaw는 세션 상태를 소유하는 단일 **Gateway 프로세스**를 중심으로 설계되었습니다.
|
||||
|
||||
- UI(macOS 앱, 웹 제어 UI, TUI)는 세션 목록과 토큰 수를 Gateway에 질의해야 합니다.
|
||||
- UI(macOS 앱, 웹 Control UI, TUI)는 세션 목록과 토큰 수를 Gateway에 쿼리해야 합니다.
|
||||
- 원격 모드에서는 세션 파일이 원격 호스트에 있습니다. “로컬 Mac 파일 확인”은 Gateway가 사용하는 내용을 반영하지 않습니다.
|
||||
|
||||
---
|
||||
|
||||
## 두 가지 지속성 계층
|
||||
|
||||
OpenClaw는 세션을 두 계층에 지속합니다.
|
||||
OpenClaw는 세션을 두 계층에 지속화합니다:
|
||||
|
||||
1. **세션 저장소(`sessions.json`)**
|
||||
- 키/값 맵: `sessionKey -> SessionEntry`
|
||||
- 작고, 변경 가능하며, 편집(또는 항목 삭제)해도 안전함
|
||||
- 세션 메타데이터(현재 세션 ID, 마지막 활동, 토글, 토큰 카운터 등)를 추적함
|
||||
- 세션 메타데이터(현재 세션 id, 마지막 활동, 토글, 토큰 카운터 등)를 추적함
|
||||
|
||||
2. **트랜스크립트(`<sessionId>.jsonl`)**
|
||||
- 트리 구조를 가진 append-only 트랜스크립트(항목에는 `id` + `parentId`가 있음)
|
||||
- 트리 구조가 있는 추가 전용 트랜스크립트(항목에는 `id` + `parentId`가 있음)
|
||||
- 실제 대화 + 도구 호출 + Compaction 요약을 저장함
|
||||
- 이후 턴에서 모델 컨텍스트를 다시 빌드하는 데 사용됨
|
||||
- 활성 트랜스크립트가 체크포인트 크기 상한을 초과하면 대형 Compaction 전 디버그 체크포인트를 건너뛰어, 두 번째 거대한 `.checkpoint.*.jsonl` 복사본을 만들지 않습니다.
|
||||
- 활성 트랜스크립트가 체크포인트 크기 상한을 초과하면 큰 Compaction 전 디버그 체크포인트는 건너뛰어, 또 하나의 거대한 `.checkpoint.*.jsonl` 복사본을 만들지 않습니다.
|
||||
|
||||
Gateway 히스토리 리더는 해당 화면이 임의의 과거 접근을 명시적으로 필요로 하지 않는 한 전체 트랜스크립트를 메모리에 구체화하지 않아야 합니다. 첫 페이지 히스토리, 임베디드 채팅 히스토리, 재시작 복구, 토큰/사용량 확인은 제한된 tail 읽기를 사용합니다. 전체 트랜스크립트 스캔은 비동기 트랜스크립트 인덱스를 거치며, 이 인덱스는 파일 경로와 `mtimeMs`/`size`를 기준으로 캐시되고 동시 리더 간에 공유됩니다.
|
||||
Gateway 기록 리더는 해당 표면이 임의의 과거 접근을 명시적으로 필요로 하지 않는 한 전체 트랜스크립트를 구체화하지 않아야 합니다. 첫 페이지 기록, 임베디드 채팅 기록, 재시작 복구, 토큰/사용량 확인은 제한된 tail 읽기를 사용합니다. 전체 트랜스크립트 스캔은 비동기 트랜스크립트 인덱스를 거치며, 이 인덱스는 파일 경로와 `mtimeMs`/`size`를 기준으로 캐시되고 동시 리더 간에 공유됩니다.
|
||||
|
||||
---
|
||||
|
||||
@ -77,32 +77,32 @@ OpenClaw는 `src/config/sessions.ts`를 통해 이를 해석합니다.
|
||||
|
||||
## 저장소 유지 관리 및 디스크 제어
|
||||
|
||||
세션 지속성에는 `sessions.json`, 트랜스크립트 아티팩트, trajectory 사이드카를 위한 자동 유지 관리 제어(`session.maintenance`)가 있습니다.
|
||||
세션 지속성에는 `sessions.json`, 트랜스크립트 아티팩트, trajectory 사이드카를 위한 자동 유지 관리 제어(`session.maintenance`)가 있습니다:
|
||||
|
||||
- `mode`: `warn`(기본값) 또는 `enforce`
|
||||
- `pruneAfter`: 오래된 항목 나이 기준(기본값 `30d`)
|
||||
- `pruneAfter`: 오래된 항목 나이 컷오프(기본값 `30d`)
|
||||
- `maxEntries`: `sessions.json`의 항목 상한(기본값 `500`)
|
||||
- `resetArchiveRetention`: `*.reset.<timestamp>` 트랜스크립트 아카이브 보존 기간(기본값: `pruneAfter`와 동일, `false`는 정리를 비활성화)
|
||||
- `resetArchiveRetention`: `*.reset.<timestamp>` 트랜스크립트 아카이브 보존 기간(기본값: `pruneAfter`와 동일, `false`는 정리 비활성화)
|
||||
- `maxDiskBytes`: 선택적 세션 디렉터리 예산
|
||||
- `highWaterBytes`: 정리 후 선택적 목표값(기본값은 `maxDiskBytes`의 `80%`)
|
||||
|
||||
일반 Gateway 쓰기는 런타임 파일 잠금을 잡지 않고 프로세스 내 변경을 직렬화하는 저장소별 세션 작성기를 거칩니다. hot-path 패치 헬퍼는 해당 작성기 슬롯을 보유하는 동안 검증된 변경 가능 캐시를 빌리므로, 대형 `sessions.json` 파일을 모든 메타데이터 업데이트마다 복제하거나 다시 읽지 않습니다. 런타임 코드는 `updateSessionStore(...)` 또는 `updateSessionStoreEntry(...)`를 선호해야 합니다. 직접 전체 저장소를 저장하는 방식은 호환성 및 오프라인 유지 관리 도구용입니다. Gateway에 도달할 수 있는 경우, dry-run이 아닌 `openclaw sessions cleanup` 및 `openclaw agents delete`는 저장소 변경을 Gateway에 위임하여 정리가 동일한 작성기 큐에 합류하도록 합니다. `--store <path>`는 직접 파일 유지 관리를 위한 명시적 오프라인 복구 경로입니다. `maxEntries` 정리는 여전히 프로덕션 크기 상한에 맞춰 일괄 처리되므로, 다음 high-water 정리가 이를 다시 줄여 쓸 때까지 저장소가 구성된 상한을 잠시 초과할 수 있습니다. 세션 저장소 읽기는 Gateway 시작 중에 항목을 정리하거나 상한 적용하지 않습니다. 정리에는 쓰기 또는 `openclaw sessions cleanup --enforce`를 사용하세요. `openclaw sessions cleanup --enforce`는 구성된 상한을 즉시 적용합니다.
|
||||
일반 Gateway 쓰기는 런타임 파일 잠금을 잡지 않고 프로세스 내 변경을 직렬화하는 저장소별 세션 작성기를 거칩니다. 핫 경로 패치 헬퍼는 해당 작성기 슬롯을 보유하는 동안 검증된 변경 가능 캐시를 빌려 쓰므로, 큰 `sessions.json` 파일이 모든 메타데이터 업데이트마다 복제되거나 다시 읽히지 않습니다. 런타임 코드는 `updateSessionStore(...)` 또는 `updateSessionStoreEntry(...)`를 선호해야 합니다. 직접 전체 저장소 저장은 호환성 및 오프라인 유지 관리 도구입니다. Gateway에 도달할 수 있는 경우 dry-run이 아닌 `openclaw sessions cleanup` 및 `openclaw agents delete`는 저장소 변경을 Gateway에 위임하므로 정리가 동일한 작성기 큐에 합류합니다. `--store <path>`는 직접 파일 유지 관리를 위한 명시적 오프라인 복구 경로입니다. `maxEntries` 정리는 프로덕션 크기 상한에 대해서도 여전히 배치 처리되므로, 다음 high-water 정리가 이를 다시 줄여 쓰기 전까지 저장소가 구성된 상한을 잠시 초과할 수 있습니다. 세션 저장소 읽기는 Gateway 시작 중 항목을 정리하거나 제한하지 않습니다. 정리에는 쓰기 또는 `openclaw sessions cleanup --enforce`를 사용하세요. `openclaw sessions cleanup --enforce`는 디스크 예산이 구성되지 않은 경우에도 구성된 상한을 즉시 적용하고 오래된 참조되지 않은 트랜스크립트, 체크포인트, trajectory 아티팩트를 정리합니다.
|
||||
|
||||
유지 관리는 그룹 세션 및 스레드 범위 채팅 세션 같은 내구성 있는 외부 대화 포인터를 유지하지만, cron, hooks, heartbeat, ACP, 하위 에이전트의 합성 런타임 항목은 구성된 나이, 개수 또는 디스크 예산을 초과하면 제거될 수 있습니다.
|
||||
유지 관리는 그룹 세션과 스레드 범위 채팅 세션 같은 내구성 있는 외부 대화 포인터를 유지하지만, cron, hooks, heartbeat, ACP, 하위 에이전트를 위한 합성 런타임 항목은 구성된 나이, 개수, 디스크 예산을 초과하면 여전히 제거될 수 있습니다.
|
||||
|
||||
OpenClaw는 더 이상 Gateway 쓰기 중에 자동 `sessions.json.bak.*` 회전 백업을 만들지 않습니다. 기존 `session.maintenance.rotateBytes` 키는 무시되며 `openclaw doctor --fix`는 오래된 구성에서 이를 제거합니다.
|
||||
OpenClaw는 더 이상 Gateway 쓰기 중 자동 `sessions.json.bak.*` 순환 백업을 만들지 않습니다. 레거시 `session.maintenance.rotateBytes` 키는 무시되며 `openclaw doctor --fix`가 이전 구성에서 이를 제거합니다.
|
||||
|
||||
트랜스크립트 변경은 트랜스크립트 파일의 세션 쓰기 잠금을 사용합니다. 잠금 획득은 busy-session 오류를 표시하기 전에 최대 `session.writeLock.acquireTimeoutMs`까지 기다립니다. 기본값은 `60000`ms입니다. 합법적인 준비, 정리, Compaction 또는 트랜스크립트 미러 작업이 느린 머신에서 더 오래 경합하는 경우에만 이 값을 높이세요. stale-lock 감지와 최대 보유 경고는 별도의 정책으로 유지됩니다.
|
||||
트랜스크립트 변경은 트랜스크립트 파일의 세션 쓰기 잠금을 사용합니다. 잠금 획득은 busy-session 오류를 표시하기 전에 최대 `session.writeLock.acquireTimeoutMs`까지 대기합니다. 기본값은 `60000` ms입니다. 합법적인 준비, 정리, Compaction 또는 트랜스크립트 미러 작업이 느린 머신에서 더 오래 경합하는 경우에만 이 값을 올리세요. 오래된 잠금 감지와 최대 보유 경고는 별도 정책으로 유지됩니다.
|
||||
|
||||
디스크 예산 정리(`mode: "enforce"`)의 적용 순서:
|
||||
|
||||
1. 가장 오래된 아카이브, 고아 트랜스크립트 또는 고아 trajectory 아티팩트를 먼저 제거합니다.
|
||||
2. 그래도 목표값보다 높으면 가장 오래된 세션 항목과 해당 트랜스크립트/trajectory 파일을 축출합니다.
|
||||
2. 여전히 목표를 초과하면 가장 오래된 세션 항목과 해당 트랜스크립트/trajectory 파일을 제거합니다.
|
||||
3. 사용량이 `highWaterBytes` 이하가 될 때까지 계속합니다.
|
||||
|
||||
`mode: "warn"`에서 OpenClaw는 잠재적 축출을 보고하지만 저장소/파일은 변경하지 않습니다.
|
||||
`mode: "warn"`에서는 OpenClaw가 잠재적 제거를 보고하지만 저장소/파일을 변경하지 않습니다.
|
||||
|
||||
필요할 때 유지 관리를 실행하세요.
|
||||
필요할 때 유지 관리를 실행하세요:
|
||||
|
||||
```bash
|
||||
openclaw sessions cleanup --dry-run
|
||||
@ -113,22 +113,22 @@ openclaw sessions cleanup --enforce
|
||||
|
||||
## Cron 세션 및 실행 로그
|
||||
|
||||
격리된 cron 실행도 세션 항목/트랜스크립트를 만들며, 전용 보존 제어가 있습니다.
|
||||
격리된 Cron 실행도 세션 항목/트랜스크립트를 만들며, 전용 보존 제어가 있습니다:
|
||||
|
||||
- `cron.sessionRetention`(기본값 `24h`)은 세션 저장소에서 오래된 격리 cron 실행 세션을 정리합니다(`false`는 비활성화).
|
||||
- `cron.runLog.maxBytes` + `cron.runLog.keepLines`는 `~/.openclaw/cron/runs/<jobId>.jsonl` 파일을 정리합니다(기본값: `2_000_000`바이트 및 `2000`줄).
|
||||
- `cron.sessionRetention`(기본값 `24h`)은 오래된 격리 Cron 실행 세션을 세션 저장소에서 정리합니다(`false`는 비활성화).
|
||||
- `cron.runLog.maxBytes` + `cron.runLog.keepLines`는 `~/.openclaw/cron/runs/<jobId>.jsonl` 파일을 정리합니다(기본값: `2_000_000` 바이트 및 `2000`줄).
|
||||
|
||||
cron이 새 격리 실행 세션을 강제로 만들 때, 새 행을 쓰기 전에 이전 `cron:<jobId>` 세션 항목을 정리합니다. thinking/fast/verbose 설정, 레이블, 명시적으로 사용자가 선택한 모델/auth 재정의 같은 안전한 선호사항은 이어받습니다. 채널/그룹 라우팅, 전송 또는 큐 정책, 권한 상승, 출처, ACP 런타임 바인딩 같은 주변 대화 컨텍스트는 제거하여, 새 격리 실행이 이전 실행의 오래된 전달 또는 런타임 권한을 상속하지 못하게 합니다.
|
||||
Cron이 새 격리 실행 세션을 강제로 만들 때는 새 행을 쓰기 전에 이전 `cron:<jobId>` 세션 항목을 정리합니다. thinking/fast/verbose 설정, 레이블, 명시적 사용자 선택 모델/auth 재정의 같은 안전한 선호 설정은 유지합니다. 채널/그룹 라우팅, 전송 또는 큐 정책, 권한 상승, 출처, ACP 런타임 바인딩 같은 주변 대화 컨텍스트는 삭제하여 새 격리 실행이 이전 실행의 오래된 전달 또는 런타임 권한을 상속하지 못하게 합니다.
|
||||
|
||||
---
|
||||
|
||||
## 세션 키(`sessionKey`)
|
||||
|
||||
`sessionKey`는 사용자가 속한 _대화 버킷_(라우팅 + 격리)을 식별합니다.
|
||||
`sessionKey`는 현재 속한 _대화 버킷_(라우팅 + 격리)을 식별합니다.
|
||||
|
||||
일반적인 패턴:
|
||||
|
||||
- 메인/직접 채팅(에이전트별): `agent:<agentId>:<mainKey>`(기본값 `main`)
|
||||
- 기본/직접 채팅(에이전트별): `agent:<agentId>:<mainKey>`(기본값 `main`)
|
||||
- 그룹: `agent:<agentId>:<channel>:group:<id>`
|
||||
- 방/채널(Discord/Slack): `agent:<agentId>:<channel>:channel:<id>` 또는 `...:room:<id>`
|
||||
- Cron: `cron:<job.id>`
|
||||
@ -138,19 +138,19 @@ cron이 새 격리 실행 세션을 강제로 만들 때, 새 행을 쓰기 전
|
||||
|
||||
---
|
||||
|
||||
## 세션 ID(`sessionId`)
|
||||
## 세션 id(`sessionId`)
|
||||
|
||||
각 `sessionKey`는 현재 `sessionId`(대화를 이어가는 트랜스크립트 파일)를 가리킵니다.
|
||||
각 `sessionKey`는 현재 `sessionId`(대화를 이어 가는 트랜스크립트 파일)를 가리킵니다.
|
||||
|
||||
경험칙:
|
||||
|
||||
- **재설정**(`/new`, `/reset`)은 해당 `sessionKey`에 대한 새 `sessionId`를 만듭니다.
|
||||
- **일일 재설정**(기본값: Gateway 호스트의 로컬 시간 오전 4:00)은 재설정 경계 이후 다음 메시지에서 새 `sessionId`를 만듭니다.
|
||||
- **유휴 만료**(`session.reset.idleMinutes` 또는 기존 `session.idleMinutes`)는 유휴 창 이후 메시지가 도착하면 새 `sessionId`를 만듭니다. 일일 + 유휴가 모두 구성된 경우 먼저 만료되는 쪽이 적용됩니다.
|
||||
- **시스템 이벤트**(heartbeat, cron wakeups, exec notifications, gateway bookkeeping)는 세션 행을 변경할 수 있지만 일일/유휴 재설정 신선도를 연장하지 않습니다. 재설정 롤오버는 새 프롬프트를 만들기 전에 이전 세션에 대해 큐에 있던 시스템 이벤트 알림을 버립니다.
|
||||
- **상위 fork 정책**은 스레드 또는 하위 에이전트 fork를 만들 때 PI의 활성 브랜치를 사용합니다. 해당 브랜치가 너무 크면 OpenClaw는 실패하거나 사용할 수 없는 히스토리를 상속하는 대신 격리된 컨텍스트로 자식을 시작합니다. 크기 산정 정책은 자동입니다. 기존 `session.parentForkMaxTokens` 구성은 `openclaw doctor --fix`로 제거됩니다.
|
||||
- **Reset**(`/new`, `/reset`)은 해당 `sessionKey`에 새 `sessionId`를 만듭니다.
|
||||
- **일일 재설정**(기본값은 Gateway 호스트의 현지 시간 오전 4:00)은 재설정 경계를 지난 다음 메시지에서 새 `sessionId`를 만듭니다.
|
||||
- **유휴 만료**(`session.reset.idleMinutes` 또는 레거시 `session.idleMinutes`)는 유휴 창이 지난 뒤 메시지가 도착하면 새 `sessionId`를 만듭니다. 일일 + 유휴가 모두 구성된 경우 먼저 만료되는 쪽이 적용됩니다.
|
||||
- **시스템 이벤트**(heartbeat, Cron wakeups, exec 알림, Gateway bookkeeping)는 세션 행을 변경할 수 있지만 일일/유휴 재설정 신선도를 연장하지 않습니다. 재설정 롤오버는 새 프롬프트가 빌드되기 전에 이전 세션의 대기 중인 시스템 이벤트 알림을 폐기합니다.
|
||||
- **부모 포크 정책**은 스레드 또는 하위 에이전트 포크를 만들 때 Pi의 활성 브랜치를 사용합니다. 해당 브랜치가 너무 크면 OpenClaw는 실패하거나 사용할 수 없는 기록을 상속하는 대신 격리된 컨텍스트로 자식을 시작합니다. 크기 정책은 자동입니다. 레거시 `session.parentForkMaxTokens` 구성은 `openclaw doctor --fix`가 제거합니다.
|
||||
|
||||
구현 세부 정보: 결정은 `src/auto-reply/reply/session.ts`의 `initSessionState()`에서 이루어집니다.
|
||||
구현 세부 사항: 이 결정은 `src/auto-reply/reply/session.ts`의 `initSessionState()`에서 일어납니다.
|
||||
|
||||
---
|
||||
|
||||
@ -158,27 +158,27 @@ cron이 새 격리 실행 세션을 강제로 만들 때, 새 행을 쓰기 전
|
||||
|
||||
저장소의 값 타입은 `src/config/sessions.ts`의 `SessionEntry`입니다.
|
||||
|
||||
주요 필드(전체 목록은 아님):
|
||||
주요 필드(전체 목록 아님):
|
||||
|
||||
- `sessionId`: 현재 트랜스크립트 ID(`sessionFile`이 설정되지 않은 경우 파일 이름은 여기서 파생됨)
|
||||
- `sessionStartedAt`: 현재 `sessionId`의 시작 타임스탬프입니다. 일일 재설정 신선도는 이를 사용합니다. 기존 행은 JSONL 세션 헤더에서 이를 파생할 수 있습니다.
|
||||
- `lastInteractionAt`: 마지막 실제 사용자/채널 상호작용 타임스탬프입니다. 유휴 재설정 신선도는 이를 사용하므로 heartbeat, cron, exec 이벤트가 세션을 계속 살아 있게 하지 않습니다. 이 필드가 없는 기존 행은 복구된 세션 시작 시간으로 유휴 신선도를 대체합니다.
|
||||
- `updatedAt`: 마지막 저장소 행 변경 타임스탬프이며 목록, 정리, bookkeeping에 사용됩니다. 일일/유휴 재설정 신선도의 권위 있는 기준은 아닙니다.
|
||||
- `sessionFile`: 선택적 명시적 트랜스크립트 경로 재정의
|
||||
- `chatType`: `direct | group | room`(UI 및 전송 정책에 도움)
|
||||
- `provider`, `subject`, `room`, `space`, `displayName`: 그룹/채널 레이블링용 메타데이터
|
||||
- `sessionId`: 현재 트랜스크립트 id(`sessionFile`이 설정되지 않은 경우 파일 이름은 여기서 파생됨)
|
||||
- `sessionStartedAt`: 현재 `sessionId`의 시작 타임스탬프. 일일 재설정 신선도는 이를 사용합니다. 레거시 행은 JSONL 세션 헤더에서 이를 파생할 수 있습니다.
|
||||
- `lastInteractionAt`: 마지막 실제 사용자/채널 상호작용 타임스탬프. 유휴 재설정 신선도는 이를 사용하므로 heartbeat, Cron, exec 이벤트가 세션을 계속 활성 상태로 유지하지 않습니다. 이 필드가 없는 레거시 행은 유휴 신선도에 대해 복구된 세션 시작 시간으로 폴백합니다.
|
||||
- `updatedAt`: 마지막 저장소 행 변경 타임스탬프이며, 목록 표시, 정리, bookkeeping에 사용됩니다. 일일/유휴 재설정 신선도의 권위가 아닙니다.
|
||||
- `sessionFile`: 선택적 명시 트랜스크립트 경로 재정의
|
||||
- `chatType`: `direct | group | room`(UI와 전송 정책에 도움)
|
||||
- `provider`, `subject`, `room`, `space`, `displayName`: 그룹/채널 레이블링을 위한 메타데이터
|
||||
- 토글:
|
||||
- `thinkingLevel`, `verboseLevel`, `reasoningLevel`, `elevatedLevel`
|
||||
- `sendPolicy`(세션별 재정의)
|
||||
- 모델 선택:
|
||||
- `providerOverride`, `modelOverride`, `authProfileOverride`
|
||||
- 토큰 카운터(best-effort / 공급자 의존):
|
||||
- 토큰 카운터(최선 노력 / 공급자 의존):
|
||||
- `inputTokens`, `outputTokens`, `totalTokens`, `contextTokens`
|
||||
- `compactionCount`: 이 세션 키에 대해 자동 Compaction이 완료된 횟수
|
||||
- `memoryFlushAt`: 마지막 Compaction 전 메모리 flush의 타임스탬프
|
||||
- `memoryFlushCompactionCount`: 마지막 flush가 실행되었을 때의 Compaction 횟수
|
||||
- `compactionCount`: 이 세션 키에서 자동 Compaction이 완료된 횟수
|
||||
- `memoryFlushAt`: 마지막 Compaction 전 메모리 플러시의 타임스탬프
|
||||
- `memoryFlushCompactionCount`: 마지막 플러시가 실행되었을 때의 Compaction 횟수
|
||||
|
||||
저장소는 편집해도 안전하지만, Gateway가 권위 있는 기준입니다. 세션이 실행되는 동안 Gateway가 항목을 다시 쓰거나 다시 hydrate할 수 있습니다.
|
||||
저장소는 편집해도 안전하지만 Gateway가 권위입니다. 세션이 실행되면서 항목을 다시 쓰거나 재수화할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
@ -186,73 +186,74 @@ cron이 새 격리 실행 세션을 강제로 만들 때, 새 행을 쓰기 전
|
||||
|
||||
트랜스크립트는 `@mariozechner/pi-coding-agent`의 `SessionManager`가 관리합니다.
|
||||
|
||||
파일은 JSONL입니다.
|
||||
파일은 JSONL입니다:
|
||||
|
||||
- 첫 줄: 세션 헤더(`type: "session"`, `id`, `cwd`, `timestamp`, 선택적 `parentSession` 포함)
|
||||
- 이후: `id` + `parentId`를 가진 세션 항목(트리)
|
||||
- 이후: `id` + `parentId`가 있는 세션 항목(트리)
|
||||
|
||||
주목할 만한 항목 타입:
|
||||
주목할 항목 타입:
|
||||
|
||||
- `message`: 사용자/assistant/toolResult 메시지
|
||||
- `custom_message`: 모델 컨텍스트에 _들어가는_ extension 주입 메시지(UI에서 숨길 수 있음)
|
||||
- `custom`: 모델 컨텍스트에 _들어가지 않는_ extension 상태
|
||||
- `compaction`: `firstKeptEntryId` 및 `tokensBefore`가 포함된 지속된 Compaction 요약
|
||||
- `branch_summary`: 트리 브랜치를 탐색할 때 지속되는 요약
|
||||
- `message`: 사용자/어시스턴트/toolResult 메시지
|
||||
- `custom_message`: 모델 컨텍스트에 _들어가는_ 확장 주입 메시지(UI에서는 숨길 수 있음)
|
||||
- `custom`: 모델 컨텍스트에 _들어가지 않는_ 확장 상태
|
||||
- `compaction`: `firstKeptEntryId` 및 `tokensBefore`가 있는 지속화된 Compaction 요약
|
||||
- `branch_summary`: 트리 브랜치를 탐색할 때 지속화되는 요약
|
||||
|
||||
OpenClaw는 의도적으로 트랜스크립트를 “수정”하지 않습니다. Gateway는 `SessionManager`를 사용해 이를 읽고 씁니다.
|
||||
|
||||
---
|
||||
|
||||
## 컨텍스트 창과 추적된 토큰
|
||||
## 컨텍스트 창과 추적 토큰
|
||||
|
||||
두 가지 서로 다른 개념이 중요합니다.
|
||||
중요한 개념은 서로 다른 두 가지입니다:
|
||||
|
||||
1. **모델 컨텍스트 창**: 모델별 hard cap(모델에 보이는 토큰)
|
||||
1. **모델 컨텍스트 창**: 모델별 하드 상한(모델에 표시되는 토큰)
|
||||
2. **세션 저장소 카운터**: `sessions.json`에 기록되는 롤링 통계(/status 및 대시보드에 사용)
|
||||
|
||||
제한을 조정하는 경우:
|
||||
|
||||
- 컨텍스트 창은 모델 카탈로그에서 가져옵니다(구성을 통해 재정의 가능).
|
||||
- 저장소의 `contextTokens`는 런타임 추정/보고 값입니다. 이를 엄격한 보장으로 취급하지 마세요.
|
||||
- 저장소의 `contextTokens`는 런타임 추정/보고 값입니다. 엄격한 보장으로 취급하지 마세요.
|
||||
|
||||
자세한 내용은 [/token-use](/ko/reference/token-use)를 참조하세요.
|
||||
|
||||
---
|
||||
|
||||
## Compaction: 의미
|
||||
## Compaction: 정의
|
||||
|
||||
Compaction은 오래된 대화를 트랜스크립트의 지속된 `compaction` 항목으로 요약하고 최근 메시지는 그대로 유지합니다.
|
||||
Compaction은 오래된 대화를 트랜스크립트의 지속화된 `compaction` 항목으로 요약하고 최근 메시지는 그대로 유지합니다.
|
||||
|
||||
Compaction 이후 이후 턴에서 보이는 항목:
|
||||
Compaction 후 이후 턴에서는 다음이 표시됩니다:
|
||||
|
||||
- Compaction 요약
|
||||
- `firstKeptEntryId` 이후의 메시지
|
||||
|
||||
Compaction은 **지속적**입니다(세션 정리와 다름). [/concepts/session-pruning](/ko/concepts/session-pruning)을 참조하세요.
|
||||
Compaction은 **영구적**입니다(세션 정리와 달리). [/concepts/session-pruning](/ko/concepts/session-pruning)을 참조하세요.
|
||||
|
||||
## Compaction 청크 경계와 도구 페어링
|
||||
|
||||
OpenClaw가 긴 트랜스크립트를 Compaction 청크로 나눌 때, 어시스턴트 도구 호출을
|
||||
해당 `toolResult` 항목과 짝지어 유지합니다.
|
||||
OpenClaw가 긴 transcript를 Compaction 청크로 나눌 때는
|
||||
assistant 도구 호출을 그에 대응하는 `toolResult` 항목과 함께 유지합니다.
|
||||
|
||||
- 토큰 비율 기준 분할 지점이 도구 호출과 그 결과 사이에 걸리면, OpenClaw는
|
||||
쌍을 분리하지 않고 경계를 어시스턴트 도구 호출 메시지로 이동합니다.
|
||||
- 뒤쪽의 도구 결과 블록 때문에 청크가 목표치를 초과하게 되는 경우, OpenClaw는
|
||||
해당 대기 중인 도구 블록을 보존하고 요약되지 않은 꼬리 부분을 그대로 유지합니다.
|
||||
- 중단되었거나 오류가 발생한 도구 호출 블록은 대기 중인 분할을 열린 상태로 유지하지 않습니다.
|
||||
- token-share 분할 지점이 도구 호출과 그 결과 사이에 걸리면, OpenClaw는
|
||||
쌍을 분리하는 대신 경계를 assistant 도구 호출 메시지로 이동합니다.
|
||||
- 뒤따르는 도구 결과 블록 때문에 청크가 목표 크기를 초과하게 될 경우,
|
||||
OpenClaw는 해당 대기 중인 도구 블록을 보존하고 요약되지 않은 꼬리 부분을
|
||||
그대로 유지합니다.
|
||||
- 중단되었거나 오류가 난 도구 호출 블록은 대기 중인 분할을 열린 상태로 유지하지 않습니다.
|
||||
|
||||
---
|
||||
|
||||
## 자동 Compaction이 발생하는 경우(Pi 런타임)
|
||||
## 자동 Compaction이 발생하는 시점(Pi 런타임)
|
||||
|
||||
내장 Pi 에이전트에서는 자동 Compaction이 두 가지 경우에 트리거됩니다.
|
||||
임베디드 Pi 에이전트에서 자동 Compaction은 두 가지 경우에 트리거됩니다.
|
||||
|
||||
1. **오버플로 복구**: 모델이 컨텍스트 오버플로 오류
|
||||
1. **오버플로 복구**: 모델이 컨텍스트 오버플로 오류를 반환하는 경우
|
||||
(`request_too_large`, `context length exceeded`, `input exceeds the maximum
|
||||
number of tokens`, `input token count exceeds the maximum number of input
|
||||
tokens`, `input is too long for the model`, `ollama error: context length
|
||||
exceeded` 및 유사한 공급자별 변형)를 반환함 → 압축 → 재시도.
|
||||
2. **임계값 유지 관리**: 성공적인 턴 이후 다음 조건일 때:
|
||||
exceeded` 및 유사한 provider 형태의 변형) → compact → 재시도.
|
||||
2. **임계값 유지 관리**: 성공적인 턴 이후, 다음 조건일 때:
|
||||
|
||||
`contextTokens > contextWindow - reserveTokens`
|
||||
|
||||
@ -261,16 +262,24 @@ exceeded` 및 유사한 공급자별 변형)를 반환함 → 압축 → 재시
|
||||
- `contextWindow`는 모델의 컨텍스트 창입니다
|
||||
- `reserveTokens`는 프롬프트와 다음 모델 출력을 위해 예약된 여유 공간입니다
|
||||
|
||||
이는 Pi 런타임 의미 체계입니다(OpenClaw는 이벤트를 소비하지만, 언제 압축할지는 Pi가 결정합니다).
|
||||
이는 Pi 런타임 의미론입니다(OpenClaw는 이벤트를 소비하지만, 언제 compact할지는 Pi가 결정합니다).
|
||||
|
||||
OpenClaw는 `agents.defaults.compaction.maxActiveTranscriptBytes`가 설정되어 있고
|
||||
활성 트랜스크립트 파일이 해당 크기에 도달하면 다음 실행을 열기 전에 사전 점검 로컬 Compaction도 트리거할 수 있습니다. 이는 로컬 재개 비용을 위한 파일 크기 가드이며 원시 보관이 아닙니다. OpenClaw는 여전히 일반적인 의미 기반 Compaction을 실행하며,
|
||||
압축된 요약이 새 후속 트랜스크립트가 될 수 있도록 `truncateAfterCompaction`이 필요합니다.
|
||||
활성 transcript 파일이 해당 크기에 도달하면 다음 run을 열기 전에 preflight 로컬 Compaction을
|
||||
트리거할 수도 있습니다. 이는 로컬 재개 비용을 위한 파일 크기 보호 장치이지 원시 보관이 아닙니다.
|
||||
OpenClaw는 여전히 일반적인 의미 기반 Compaction을 실행하며, compact된 요약이
|
||||
새 successor transcript가 될 수 있도록 `truncateAfterCompaction`이 필요합니다.
|
||||
|
||||
내장 Pi 실행에서 `agents.defaults.compaction.midTurnPrecheck.enabled: true`는
|
||||
선택형 도구 루프 가드를 추가합니다. 도구 결과가 추가된 후 다음 모델 호출 전에,
|
||||
OpenClaw는 턴 시작 시 사용하는 것과 동일한 사전 점검 예산 로직으로 프롬프트 압력을 추정합니다. 컨텍스트가 더 이상 맞지 않으면, 가드는 Pi의 `transformContext` 훅 안에서 압축하지 않습니다. 대신 구조화된 턴 중간 사전 점검 신호를 발생시키고, 현재 프롬프트 제출을 중지한 뒤, 외부 실행 루프가 기존 복구 경로를 사용하도록 합니다. 그것만으로 충분하면 너무 큰 도구 결과를 잘라내고, 아니면 구성된 Compaction 모드를 트리거한 뒤 재시도합니다. 이 옵션은 기본적으로 비활성화되어 있으며, 공급자 기반 safeguard Compaction을 포함해 `default`와 `safeguard` Compaction 모드 모두에서 작동합니다.
|
||||
이는 `maxActiveTranscriptBytes`와 독립적입니다. 바이트 크기 가드는 턴이 열리기 전에 실행되고, 턴 중간 사전 점검은 새 도구 결과가 추가된 뒤 내장 Pi 도구 루프에서 나중에 실행됩니다.
|
||||
임베디드 Pi run의 경우, `agents.defaults.compaction.midTurnPrecheck.enabled: true`는
|
||||
옵트인 도구 루프 보호 장치를 추가합니다. 도구 결과가 추가된 뒤 다음 모델 호출 전에,
|
||||
OpenClaw는 턴 시작 시 사용하는 것과 동일한 preflight 예산 로직으로 프롬프트 압력을 추정합니다.
|
||||
컨텍스트가 더 이상 맞지 않으면, 보호 장치는 Pi의 `transformContext` 훅 안에서 compact하지 않습니다.
|
||||
대신 구조화된 mid-turn precheck 신호를 발생시키고, 현재 프롬프트 제출을 중지한 뒤,
|
||||
외부 run 루프가 기존 복구 경로를 사용하게 합니다. 충분하다면 너무 큰 도구 결과를 자르거나,
|
||||
설정된 Compaction 모드를 트리거하고 재시도합니다. 이 옵션은 기본적으로 비활성화되어 있으며,
|
||||
provider 기반 safeguard Compaction을 포함해 `default` 및 `safeguard` Compaction 모드 모두에서 작동합니다.
|
||||
이는 `maxActiveTranscriptBytes`와 독립적입니다. 바이트 크기 보호 장치는 턴이 열리기 전에 실행되고,
|
||||
mid-turn precheck는 새 도구 결과가 추가된 뒤 임베디드 Pi 도구 루프에서 나중에 실행됩니다.
|
||||
|
||||
---
|
||||
|
||||
@ -288,122 +297,132 @@ Pi의 Compaction 설정은 Pi 설정에 있습니다.
|
||||
}
|
||||
```
|
||||
|
||||
OpenClaw는 내장 실행에 대해 안전 하한도 적용합니다.
|
||||
OpenClaw는 임베디드 run에 대한 안전 하한도 강제합니다.
|
||||
|
||||
- `compaction.reserveTokens < reserveTokensFloor`이면 OpenClaw가 값을 올립니다.
|
||||
- 기본 하한은 `20000` 토큰입니다.
|
||||
- 하한을 비활성화하려면 `agents.defaults.compaction.reserveTokensFloor: 0`을 설정합니다.
|
||||
- 이미 더 높게 설정되어 있으면 OpenClaw는 그대로 둡니다.
|
||||
- 하한을 비활성화하려면 `agents.defaults.compaction.reserveTokensFloor: 0`을 설정하세요.
|
||||
- 이미 더 높으면 OpenClaw는 그대로 둡니다.
|
||||
- 수동 `/compact`는 명시적인 `agents.defaults.compaction.keepRecentTokens`를 존중하고
|
||||
Pi의 최근 꼬리 부분 절단 지점을 유지합니다. 명시적인 유지 예산이 없으면,
|
||||
Pi의 최근 꼬리 절단 지점을 유지합니다. 명시적인 유지 예산이 없으면
|
||||
수동 Compaction은 하드 체크포인트로 유지되며 재구성된 컨텍스트는
|
||||
새 요약에서 시작합니다.
|
||||
- 새 도구 결과 이후와 다음 모델 호출 전에 선택형 도구 루프 사전 점검을 실행하려면
|
||||
`agents.defaults.compaction.midTurnPrecheck.enabled: true`를 설정합니다. 이는 트리거일 뿐이며, 요약 생성은 여전히 구성된 Compaction 경로를 사용합니다. 이는 턴 시작 활성 트랜스크립트 바이트 크기 가드인 `maxActiveTranscriptBytes`와 독립적입니다.
|
||||
- 활성 트랜스크립트가 커졌을 때 턴 전에 로컬 Compaction을 실행하려면
|
||||
`agents.defaults.compaction.maxActiveTranscriptBytes`를 바이트 값 또는 `"20mb"` 같은
|
||||
문자열로 설정합니다. 이 가드는 `truncateAfterCompaction`도 활성화된 경우에만 동작합니다. 비활성화하려면 설정하지 않거나 `0`으로 설정합니다.
|
||||
새 요약부터 시작합니다.
|
||||
- 새 도구 결과 이후, 다음 모델 호출 전에 선택적 도구 루프 precheck를 실행하려면
|
||||
`agents.defaults.compaction.midTurnPrecheck.enabled: true`를 설정하세요.
|
||||
이는 트리거일 뿐이며, 요약 생성은 여전히 설정된 Compaction 경로를 사용합니다.
|
||||
턴 시작 시 활성 transcript 바이트 크기 보호 장치인 `maxActiveTranscriptBytes`와는 독립적입니다.
|
||||
- 활성 transcript가 커질 때 턴 전에 로컬 Compaction을 실행하려면
|
||||
`agents.defaults.compaction.maxActiveTranscriptBytes`를 바이트 값이나 `"20mb"` 같은
|
||||
문자열로 설정하세요. 이 보호 장치는 `truncateAfterCompaction`도 활성화된 경우에만
|
||||
동작합니다. 비활성화하려면 설정하지 않거나 `0`으로 설정하세요.
|
||||
- `agents.defaults.compaction.truncateAfterCompaction`이 활성화되면,
|
||||
OpenClaw는 Compaction 이후 활성 트랜스크립트를 압축된 후속 JSONL로 로테이션합니다.
|
||||
이전 전체 트랜스크립트는 제자리에서 다시 쓰이지 않고 보관되며 Compaction 체크포인트에서 링크됩니다.
|
||||
OpenClaw는 Compaction 후 활성 transcript를 compact된 successor JSONL로 회전합니다.
|
||||
이전 전체 transcript는 제자리에서 다시 쓰이지 않고 보관된 상태로 남으며
|
||||
Compaction 체크포인트에서 링크됩니다.
|
||||
|
||||
이유: Compaction이 불가피해지기 전에 여러 턴에 걸친 “정리 작업”(예: 메모리 쓰기)을 위한 충분한 여유 공간을 남기기 위해서입니다.
|
||||
이유: Compaction이 불가피해지기 전에 여러 턴의 “하우스키핑”(예: 메모리 쓰기)을 위한 충분한 여유 공간을 남기기 위해서입니다.
|
||||
|
||||
구현: `src/agents/pi-settings.ts`의 `ensurePiCompactionReserveTokens()`
|
||||
(`src/agents/pi-embedded-runner.ts`에서 호출됨).
|
||||
|
||||
---
|
||||
|
||||
## 플러그형 Compaction 공급자
|
||||
## Pluggable Compaction provider
|
||||
|
||||
Plugin은 Plugin API의 `registerCompactionProvider()`를 통해 Compaction 공급자를 등록할 수 있습니다. `agents.defaults.compaction.provider`가 등록된 공급자 ID로 설정되면, safeguard Plugin은 내장 `summarizeInStages` 파이프라인 대신 해당 공급자에 요약을 위임합니다.
|
||||
Plugin은 Plugin API의 `registerCompactionProvider()`를 통해 Compaction provider를 등록할 수 있습니다. `agents.defaults.compaction.provider`가 등록된 provider id로 설정되면, safeguard 확장은 내장 `summarizeInStages` 파이프라인 대신 해당 provider에 요약을 위임합니다.
|
||||
|
||||
- `provider`: 등록된 Compaction 공급자 Plugin의 ID입니다. 기본 LLM 요약을 사용하려면 설정하지 않습니다.
|
||||
- `provider`: 등록된 Compaction provider Plugin의 id입니다. 기본 LLM 요약을 사용하려면 설정하지 마세요.
|
||||
- `provider`를 설정하면 `mode: "safeguard"`가 강제됩니다.
|
||||
- 공급자는 내장 경로와 동일한 Compaction 지침 및 식별자 보존 정책을 받습니다.
|
||||
- safeguard는 공급자 출력 이후에도 최근 턴 및 분할 턴 접미사 컨텍스트를 보존합니다.
|
||||
- 내장 safeguard 요약은 전체 이전 요약을 그대로 보존하는 대신, 새 메시지와 함께 이전 요약을 다시 정제합니다.
|
||||
- safeguard 모드는 기본적으로 요약 품질 감사를 활성화합니다. 잘못된 형식의 출력에 대한 재시도 동작을 건너뛰려면
|
||||
`qualityGuard.enabled: false`를 설정합니다.
|
||||
- 공급자가 실패하거나 빈 결과를 반환하면 OpenClaw는 자동으로 내장 LLM 요약으로 대체합니다.
|
||||
- 중단/타임아웃 신호는 호출자 취소를 존중하기 위해 다시 던져집니다(삼키지 않음).
|
||||
- Provider는 내장 경로와 동일한 Compaction 지침과 식별자 보존 정책을 받습니다.
|
||||
- Safeguard는 provider 출력 이후에도 최근 턴 및 분할 턴 suffix 컨텍스트를 계속 보존합니다.
|
||||
- 내장 safeguard 요약은 전체 이전 요약을 그대로 보존하는 대신,
|
||||
새 메시지와 함께 이전 요약을 다시 distill합니다.
|
||||
- Safeguard 모드는 기본적으로 요약 품질 감사를 활성화합니다. 잘못된 형식의 출력에 대한 재시도 동작을 건너뛰려면
|
||||
`qualityGuard.enabled: false`를 설정하세요.
|
||||
- Provider가 실패하거나 빈 결과를 반환하면, OpenClaw는 자동으로 내장 LLM 요약으로 폴백합니다.
|
||||
- Abort/timeout 신호는 호출자 취소를 존중하기 위해 다시 throw됩니다(삼키지 않습니다).
|
||||
|
||||
출처: `src/plugins/compaction-provider.ts`, `src/agents/pi-hooks/compaction-safeguard.ts`.
|
||||
소스: `src/plugins/compaction-provider.ts`, `src/agents/pi-hooks/compaction-safeguard.ts`.
|
||||
|
||||
---
|
||||
|
||||
## 사용자에게 보이는 표면
|
||||
|
||||
다음을 통해 Compaction과 세션 상태를 관찰할 수 있습니다.
|
||||
다음으로 Compaction 및 세션 상태를 확인할 수 있습니다.
|
||||
|
||||
- `/status`(모든 채팅 세션에서)
|
||||
- `openclaw status`(CLI)
|
||||
- `openclaw sessions` / `sessions --json`
|
||||
- 자세한 모드: `🧹 Auto-compaction complete` + Compaction 횟수
|
||||
- 상세 모드: `🧹 Auto-compaction complete` + Compaction 횟수
|
||||
|
||||
---
|
||||
|
||||
## 조용한 정리 작업(`NO_REPLY`)
|
||||
## 조용한 하우스키핑(`NO_REPLY`)
|
||||
|
||||
OpenClaw는 사용자가 중간 출력을 보지 않아야 하는 백그라운드 작업을 위한 “조용한” 턴을 지원합니다.
|
||||
|
||||
규칙:
|
||||
|
||||
- 어시스턴트는 “사용자에게 답장을 전달하지 않음”을 나타내기 위해 정확한 조용한 토큰 `NO_REPLY` /
|
||||
- assistant는 “사용자에게 답장을 전달하지 않음”을 나타내기 위해 정확한 조용한 토큰 `NO_REPLY` /
|
||||
`no_reply`로 출력을 시작합니다.
|
||||
- OpenClaw는 전달 계층에서 이를 제거/억제합니다.
|
||||
- 정확한 조용한 토큰 억제는 대소문자를 구분하지 않으므로, 전체 페이로드가 조용한 토큰만인 경우
|
||||
`NO_REPLY`와 `no_reply`가 모두 해당됩니다.
|
||||
- 이는 실제 백그라운드/무전달 턴 전용입니다. 일반적인 실행 가능한 사용자 요청을 위한 지름길이 아닙니다.
|
||||
- OpenClaw는 delivery layer에서 이를 제거하거나 억제합니다.
|
||||
- 정확한 조용한 토큰 억제는 대소문자를 구분하지 않으므로, 전체 payload가 조용한 토큰뿐이면 `NO_REPLY`와
|
||||
`no_reply` 모두 해당됩니다.
|
||||
- 이는 실제 백그라운드/미전달 턴 전용입니다. 일반적인 실행 가능한 사용자 요청을 위한
|
||||
단축 수단이 아닙니다.
|
||||
|
||||
`2026.1.10`부터 OpenClaw는 부분 청크가 `NO_REPLY`로 시작할 때 **초안/입력 중 스트리밍**도 억제하므로, 조용한 작업이 턴 중간에 부분 출력을 노출하지 않습니다.
|
||||
`2026.1.10`부터 OpenClaw는 부분 청크가 `NO_REPLY`로 시작할 때 **draft/typing streaming**도 억제하므로,
|
||||
조용한 작업이 턴 중간에 부분 출력을 누출하지 않습니다.
|
||||
|
||||
---
|
||||
|
||||
## Compaction 전 “메모리 플러시”(구현됨)
|
||||
## Compaction 전 "메모리 플러시"(구현됨)
|
||||
|
||||
목표: 자동 Compaction이 발생하기 전에, 지속 가능한 상태를 디스크(예: 에이전트 워크스페이스의 `memory/YYYY-MM-DD.md`)에 쓰는 조용한 에이전트 턴을 실행하여 Compaction이 중요한 컨텍스트를 지우지 못하게 합니다.
|
||||
목표: 자동 Compaction이 발생하기 전에, 지속적인 상태를 디스크(예: 에이전트 workspace의 `memory/YYYY-MM-DD.md`)에 쓰는
|
||||
조용한 agentic 턴을 실행하여 Compaction이 중요한 컨텍스트를 지우지 못하게 합니다.
|
||||
|
||||
OpenClaw는 **사전 임계값 플러시** 접근 방식을 사용합니다.
|
||||
OpenClaw는 **pre-threshold flush** 접근 방식을 사용합니다.
|
||||
|
||||
1. 세션 컨텍스트 사용량을 모니터링합니다.
|
||||
2. Pi의 Compaction 임계값보다 낮은 “소프트 임계값”을 넘으면, 에이전트에 조용한
|
||||
“지금 메모리 쓰기” 지시문을 실행합니다.
|
||||
3. 정확한 조용한 토큰 `NO_REPLY` / `no_reply`를 사용하여 사용자가 아무것도 보지 않게 합니다.
|
||||
2. Pi의 Compaction 임계값보다 낮은 “soft threshold”를 넘으면, 에이전트에 조용한
|
||||
“지금 메모리 쓰기” 지시를 실행합니다.
|
||||
3. 사용자가 아무것도 보지 않도록 정확한 조용한 토큰 `NO_REPLY` / `no_reply`를 사용합니다.
|
||||
|
||||
구성(`agents.defaults.compaction.memoryFlush`):
|
||||
설정(`agents.defaults.compaction.memoryFlush`):
|
||||
|
||||
- `enabled`(기본값: `true`)
|
||||
- `model`(플러시 턴에 대한 선택적 정확한 공급자/모델 재정의, 예: `ollama/qwen3:8b`)
|
||||
- `model`(플러시 턴에 사용할 선택적 정확한 provider/model 재정의, 예: `ollama/qwen3:8b`)
|
||||
- `softThresholdTokens`(기본값: `4000`)
|
||||
- `prompt`(플러시 턴에 대한 사용자 메시지)
|
||||
- `systemPrompt`(플러시 턴에 추가로 덧붙이는 시스템 프롬프트)
|
||||
- `prompt`(플러시 턴의 사용자 메시지)
|
||||
- `systemPrompt`(플러시 턴에 추가로 붙는 시스템 프롬프트)
|
||||
|
||||
참고:
|
||||
|
||||
- 기본 프롬프트/시스템 프롬프트에는 전달을 억제하기 위한 `NO_REPLY` 힌트가 포함됩니다.
|
||||
- `model`이 설정되면, 플러시 턴은 활성 세션 대체 체인을 상속하지 않고 해당 모델을 사용하므로, 로컬 전용 정리 작업이 유료 대화 모델로 조용히 대체되지 않습니다.
|
||||
- 기본 prompt/system prompt에는 delivery를 억제하기 위한 `NO_REPLY` 힌트가 포함됩니다.
|
||||
- `model`이 설정되면, 플러시 턴은 활성 세션 fallback chain을 상속하지 않고 해당 모델을 사용하므로,
|
||||
로컬 전용 하우스키핑이 유료 대화 모델로 조용히 폴백하지 않습니다.
|
||||
- 플러시는 Compaction 주기마다 한 번 실행됩니다(`sessions.json`에서 추적).
|
||||
- 플러시는 내장 Pi 세션에 대해서만 실행됩니다(CLI 백엔드는 건너뜀).
|
||||
- 세션 워크스페이스가 읽기 전용(`workspaceAccess: "ro"` 또는 `"none"`)이면 플러시는 건너뜁니다.
|
||||
- 워크스페이스 파일 레이아웃과 쓰기 패턴은 [메모리](/ko/concepts/memory)를 참조하세요.
|
||||
- 플러시는 임베디드 Pi 세션에서만 실행됩니다(CLI 백엔드는 건너뜁니다).
|
||||
- 세션 workspace가 읽기 전용(`workspaceAccess: "ro"` 또는 `"none"`)이면 플러시를 건너뜁니다.
|
||||
- workspace 파일 레이아웃과 쓰기 패턴은 [Memory](/ko/concepts/memory)를 참조하세요.
|
||||
|
||||
Pi는 Plugin API에서 `session_before_compact` 훅도 노출하지만, OpenClaw의 플러시 로직은 현재 Gateway 쪽에 있습니다.
|
||||
Pi도 확장 API에서 `session_before_compact` 훅을 노출하지만, 현재 OpenClaw의
|
||||
플러시 로직은 Gateway 쪽에 있습니다.
|
||||
|
||||
---
|
||||
|
||||
## 문제 해결 체크리스트
|
||||
|
||||
- 세션 키가 잘못되었나요? [/concepts/session](/ko/concepts/session)에서 시작하고 `/status`의 `sessionKey`를 확인하세요.
|
||||
- 저장소와 트랜스크립트가 일치하지 않나요? `openclaw status`에서 Gateway 호스트와 저장소 경로를 확인하세요.
|
||||
- 세션 키가 잘못되었나요? [/concepts/session](/ko/concepts/session)에서 시작하여 `/status`의 `sessionKey`를 확인하세요.
|
||||
- 저장소와 transcript가 일치하지 않나요? `openclaw status`에서 Gateway 호스트와 저장소 경로를 확인하세요.
|
||||
- Compaction이 과도하게 발생하나요? 다음을 확인하세요.
|
||||
- 모델 컨텍스트 창(너무 작음)
|
||||
- Compaction 설정(모델 창에 비해 `reserveTokens`가 너무 높으면 더 이른 Compaction이 발생할 수 있음)
|
||||
- 도구 결과 비대화: 세션 가지치기를 활성화/조정하세요
|
||||
- 조용한 턴이 노출되나요? 답장이 `NO_REPLY`(대소문자를 구분하지 않는 정확한 토큰)로 시작하는지, 그리고 스트리밍 억제 수정이 포함된 빌드인지 확인하세요.
|
||||
- Compaction 설정(모델 창에 비해 `reserveTokens`가 너무 높으면 Compaction이 더 일찍 발생할 수 있음)
|
||||
- 도구 결과 팽창: 세션 정리를 활성화/조정하세요
|
||||
- 조용한 턴이 누출되나요? 답장이 `NO_REPLY`(대소문자 구분 없는 정확한 토큰)로 시작하는지, 그리고 streaming 억제 수정이 포함된 빌드인지 확인하세요.
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [세션 관리](/ko/concepts/session)
|
||||
- [세션 가지치기](/ko/concepts/session-pruning)
|
||||
- [세션 정리](/ko/concepts/session-pruning)
|
||||
- [컨텍스트 엔진](/ko/concepts/context-engine)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user