chore(i18n): refresh ko translations
This commit is contained in:
parent
928dc2730d
commit
414fd9db6d
81
docs/ko/.i18n/README.md
Normal file
81
docs/ko/.i18n/README.md
Normal file
@ -0,0 +1,81 @@
|
||||
---
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:05Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: adff26fa8858af2759b231ea48bfc01f89c110cd9b3774a8f783e282c16f77fb
|
||||
source_path: .i18n/README.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# OpenClaw 문서 i18n 자산
|
||||
|
||||
이 폴더에는 소스 문서 리포지토리용 번역 구성이 저장됩니다.
|
||||
|
||||
생성된 로캘 트리와 실시간 translation memory는 이제 게시 리포지토리에 있습니다:
|
||||
|
||||
- 리포지토리: `openclaw/docs`
|
||||
- 로컬 체크아웃: `~/Projects/openclaw-docs`
|
||||
|
||||
## 소스 오브 트루스
|
||||
|
||||
- 영어 문서는 `openclaw/openclaw`에서 작성됩니다.
|
||||
- 소스 문서 트리는 `docs/` 아래에 있습니다.
|
||||
- 소스 리포지토리는 더 이상 `docs/zh-CN/**`, `docs/ja-JP/**`, `docs/es/**`, `docs/pt-BR/**`, `docs/ko/**`, `docs/de/**`, `docs/fr/**`, 또는 `docs/ar/**` 같은 생성된 로캘 트리를 커밋된 상태로 유지하지 않습니다.
|
||||
|
||||
## 엔드투엔드 흐름
|
||||
|
||||
1. `openclaw/openclaw`에서 영어 문서를 수정합니다.
|
||||
2. `main`에 푸시합니다.
|
||||
3. `openclaw/openclaw/.github/workflows/docs-sync-publish.yml`이 문서 트리를 `openclaw/docs`로 미러링합니다.
|
||||
4. 동기화 스크립트는 게시 리포지토리의 `docs/docs.json`을 다시 작성하여, 소스 리포지토리에 더 이상 커밋되지 않더라도 생성된 로캘 선택기 블록이 그곳에 존재하도록 합니다.
|
||||
5. `openclaw/docs/.github/workflows/translate-zh-cn.yml`은 하루에 한 번, 필요 시, 그리고 소스 리포지토리의 릴리스 디스패치 이후에 `docs/zh-CN/**`를 새로 고칩니다.
|
||||
6. `openclaw/docs/.github/workflows/translate-ja-jp.yml`은 `docs/ja-JP/**`에 대해 동일하게 수행합니다.
|
||||
7. `openclaw/docs/.github/workflows/translate-es.yml`, `translate-pt-br.yml`, `translate-ko.yml`, `translate-de.yml`, `translate-fr.yml`, 그리고 `translate-ar.yml`은 `docs/es/**`, `docs/pt-BR/**`, `docs/ko/**`, `docs/de/**`, `docs/fr/**`, 그리고 `docs/ar/**`에 대해 동일하게 수행합니다.
|
||||
|
||||
## 분리 구조가 존재하는 이유
|
||||
|
||||
- 생성된 로캘 출력을 주 제품 리포지토리 밖에 유지하기 위해서입니다.
|
||||
- Mintlify를 단일 게시 문서 트리에서 유지하기 위해서입니다.
|
||||
- 게시 리포지토리가 생성된 로캘 트리를 소유하도록 하여 기본 제공 언어 전환기를 유지하기 위해서입니다.
|
||||
|
||||
## 이 폴더의 파일
|
||||
|
||||
- `glossary.<lang>.json` — 프롬프트 가이드로 사용되는 선호 용어 매핑.
|
||||
- `ar-navigation.json`, `de-navigation.json`, `es-navigation.json`, `fr-navigation.json`, `ja-navigation.json`, `ko-navigation.json`, `pt-BR-navigation.json`, `zh-Hans-navigation.json` — 동기화 중 게시 리포지토리에 다시 삽입되는 Mintlify 로캘 선택기 블록.
|
||||
- `<lang>.tm.jsonl` — 워크플로 + 모델 + 텍스트 해시를 키로 사용하는 translation memory.
|
||||
|
||||
이 리포지토리에서 `docs/.i18n/zh-CN.tm.jsonl`, `docs/.i18n/ja-JP.tm.jsonl`, `docs/.i18n/es.tm.jsonl`, `docs/.i18n/pt-BR.tm.jsonl`, `docs/.i18n/ko.tm.jsonl`, `docs/.i18n/de.tm.jsonl`, `docs/.i18n/fr.tm.jsonl`, 그리고 `docs/.i18n/ar.tm.jsonl` 같은 생성된 로캘 TM 파일은 의도적으로 더 이상 커밋되지 않습니다.
|
||||
|
||||
## 용어집 형식
|
||||
|
||||
`glossary.<lang>.json`은 항목 배열입니다:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": "troubleshooting",
|
||||
"target": "故障排除"
|
||||
}
|
||||
```
|
||||
|
||||
필드:
|
||||
|
||||
- `source`: 우선적으로 사용할 영어(또는 원본) 구문입니다.
|
||||
- `target`: 선호되는 번역 출력입니다.
|
||||
|
||||
## 번역 메커니즘
|
||||
|
||||
- `scripts/docs-i18n`은 여전히 번역 생성을 담당합니다.
|
||||
- 문서 모드는 각 번역된 페이지에 `x-i18n.source_hash`를 기록합니다.
|
||||
- 각 게시 워크플로는 현재 영어 소스 해시를 저장된 로캘 `x-i18n.source_hash`와 비교하여 보류 파일 목록을 미리 계산합니다.
|
||||
- 보류 개수가 `0`이면 비용이 큰 번역 단계는 완전히 건너뜁니다.
|
||||
- 보류 중인 파일이 있으면 워크플로는 해당 파일만 번역합니다.
|
||||
- 게시 워크플로는 일시적인 모델 형식 실패를 재시도하지만, 동일한 해시 검사가 각 재시도마다 실행되므로 변경되지 않은 파일은 계속 건너뜁니다.
|
||||
- 소스 리포지토리는 게시된 GitHub 릴리스 후에도 zh-CN, ja-JP, es, pt-BR, ko, de, fr, 및 ar 새로 고침을 디스패치하므로, 릴리스 문서가 일일 cron을 기다리지 않고도 따라잡을 수 있습니다.
|
||||
|
||||
## 운영 참고 사항
|
||||
|
||||
- 동기화 메타데이터는 게시 리포지토리의 `.openclaw-sync/source.json`에 기록됩니다.
|
||||
- 소스 리포지토리 시크릿: `OPENCLAW_DOCS_SYNC_TOKEN`
|
||||
- 게시 리포지토리 시크릿: `OPENCLAW_DOCS_I18N_OPENAI_API_KEY`
|
||||
- 로캘 출력이 오래된 것처럼 보이면 먼저 `openclaw/docs`에서 해당하는 `Translate <locale>` 워크플로를 확인하세요.
|
||||
79
docs/ko/auth-credential-semantics.md
Normal file
79
docs/ko/auth-credential-semantics.md
Normal file
@ -0,0 +1,79 @@
|
||||
---
|
||||
read_when:
|
||||
- 인증 프로필 해석 또는 자격 증명 라우팅 작업 중
|
||||
- 모델 인증 실패 또는 프로필 순서를 디버깅하는 중
|
||||
summary: 인증 프로필에 대한 정식 자격 증명 적격성 및 해석 의미 체계
|
||||
title: 인증 자격 증명 의미 체계
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:03Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: a4cd3e16cd25eb22c5e707311d06a19df1a59747ee3261c2d32c534a245fd7fb
|
||||
source_path: auth-credential-semantics.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 인증 자격 증명 의미 체계
|
||||
|
||||
이 문서는 다음 전반에서 사용되는 정식 자격 증명 적격성 및 해석 의미 체계를 정의합니다.
|
||||
|
||||
- `resolveAuthProfileOrder`
|
||||
- `resolveApiKeyForProfile`
|
||||
- `models status --probe`
|
||||
- `doctor-auth`
|
||||
|
||||
목표는 선택 시점 동작과 런타임 동작이 일치하도록 유지하는 것입니다.
|
||||
|
||||
## 안정적인 프로브 이유 코드
|
||||
|
||||
- `ok`
|
||||
- `excluded_by_auth_order`
|
||||
- `missing_credential`
|
||||
- `invalid_expires`
|
||||
- `expired`
|
||||
- `unresolved_ref`
|
||||
- `no_model`
|
||||
|
||||
## 토큰 자격 증명
|
||||
|
||||
토큰 자격 증명(`type: "token"`)은 인라인 `token` 및/또는 `tokenRef`를 지원합니다.
|
||||
|
||||
### 적격성 규칙
|
||||
|
||||
1. `token`과 `tokenRef`가 모두 없으면 토큰 프로필은 부적격입니다.
|
||||
2. `expires`는 선택 사항입니다.
|
||||
3. `expires`가 있으면 `0`보다 큰 유한한 숫자여야 합니다.
|
||||
4. `expires`가 유효하지 않으면(`NaN`, `0`, 음수, 비유한값 또는 잘못된 타입) 프로필은 `invalid_expires`와 함께 부적격입니다.
|
||||
5. `expires`가 과거 시점이면 프로필은 `expired`와 함께 부적격입니다.
|
||||
6. `tokenRef`는 `expires` 검사를 우회하지 않습니다.
|
||||
|
||||
### 해석 규칙
|
||||
|
||||
1. 리졸버 의미 체계는 `expires`에 대해 적격성 의미 체계와 일치합니다.
|
||||
2. 적격한 프로필의 경우 토큰 자료는 인라인 값 또는 `tokenRef`에서 해석될 수 있습니다.
|
||||
3. 해석할 수 없는 ref는 `models status --probe` 출력에서 `unresolved_ref`를 생성합니다.
|
||||
|
||||
## 명시적 인증 순서 필터링
|
||||
|
||||
- 공급자에 대해 `auth.order.<provider>` 또는 인증 저장소 순서 재정의가 설정되면 `models status --probe`는 해당 공급자에 대해 해석된 인증 순서에 남아 있는 프로필 ID만 프로브합니다.
|
||||
- 해당 공급자에 대한 저장된 프로필이 명시적 순서에서 생략된 경우 나중에 조용히 시도되지 않습니다. 프로브 출력은 이를 `reasonCode: excluded_by_auth_order` 및 세부 정보 `Excluded by auth.order for this provider.`와 함께 보고합니다.
|
||||
|
||||
## 프로브 대상 해석
|
||||
|
||||
- 프로브 대상은 인증 프로필, 환경 자격 증명 또는 `models.json`에서 올 수 있습니다.
|
||||
- 공급자에 자격 증명이 있지만 OpenClaw가 해당 공급자에 대해 프로브 가능한 모델 후보를 해석할 수 없으면 `models status --probe`는 `reasonCode: no_model`과 함께 `status: no_model`을 보고합니다.
|
||||
|
||||
## OAuth SecretRef 정책 가드
|
||||
|
||||
- SecretRef 입력은 정적 자격 증명에만 사용됩니다.
|
||||
- 프로필 자격 증명이 `type: "oauth"`이면 해당 프로필 자격 증명 자료에 대해 SecretRef 객체는 지원되지 않습니다.
|
||||
- `auth.profiles.<id>.mode`가 `"oauth"`이면 해당 프로필에 대한 SecretRef 기반 `keyRef`/`tokenRef` 입력은 거부됩니다.
|
||||
- 위반은 시작/리로드 인증 해석 경로에서 강한 실패로 처리됩니다.
|
||||
|
||||
## 레거시 호환 메시지
|
||||
|
||||
스크립트 호환성을 위해 프로브 오류는 이 첫 번째 줄을 변경하지 않고 유지합니다.
|
||||
|
||||
`Auth profile credentials are missing or expired.`
|
||||
|
||||
사람이 이해하기 쉬운 세부 정보와 안정적인 이유 코드는 후속 줄에 추가될 수 있습니다.
|
||||
15
docs/ko/automation/auth-monitoring.md
Normal file
15
docs/ko/automation/auth-monitoring.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
summary: '`/gateway/authentication`로 리디렉션'
|
||||
title: 인증 모니터링
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:33:52Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 42aa1b4aa76201b20e07d8ad77231607855e7e7421fa032830055144ccd8819a
|
||||
source_path: automation/auth-monitoring.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 인증 모니터링
|
||||
|
||||
이 페이지는 [인증](/gateway/authentication)(으)로 이동했습니다. 인증 모니터링 문서는 [인증](/gateway/authentication)에서 확인하세요.
|
||||
15
docs/ko/automation/clawflow.md
Normal file
15
docs/ko/automation/clawflow.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
summary: Task Flow로 리디렉션
|
||||
title: ClawFlow
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:33:52Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: e644237e0812f25b46a06ff125c8858dbc69a499aa43cfd73cf7cb37572e78e6
|
||||
source_path: automation/clawflow.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# ClawFlow
|
||||
|
||||
ClawFlow는 [Task Flow](/automation/taskflow)로 이름이 변경되었습니다. 현재 문서는 [Task Flow](/automation/taskflow)를 참조하세요.
|
||||
386
docs/ko/automation/cron-jobs.md
Normal file
386
docs/ko/automation/cron-jobs.md
Normal file
@ -0,0 +1,386 @@
|
||||
---
|
||||
read_when:
|
||||
- 백그라운드 작업 또는 깨우기 예약
|
||||
- 외부 트리거(웹훅, Gmail)를 OpenClaw에 연결
|
||||
- 예약 작업에 heartbeat와 cron 중 무엇을 사용할지 결정
|
||||
summary: Gateway 스케줄러를 위한 예약 작업, 웹훅, Gmail PubSub 트리거
|
||||
title: 예약 작업
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:54Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 43b906914461aba9af327e7e8c22aa856f65802ec2da37ed0c4f872d229cfde6
|
||||
source_path: automation/cron-jobs.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 예약 작업 (Cron)
|
||||
|
||||
Cron은 Gateway에 내장된 스케줄러입니다. 작업을 영속적으로 저장하고, 적절한 시간에 에이전트를 깨우며, 출력 결과를 채팅 채널이나 웹훅 엔드포인트로 다시 전달할 수 있습니다.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
```bash
|
||||
# 일회성 리마인더 추가
|
||||
openclaw cron add \
|
||||
--name "Reminder" \
|
||||
--at "2026-02-01T16:00:00Z" \
|
||||
--session main \
|
||||
--system-event "Reminder: check the cron docs draft" \
|
||||
--wake now \
|
||||
--delete-after-run
|
||||
|
||||
# 작업 확인
|
||||
openclaw cron list
|
||||
|
||||
# 실행 기록 보기
|
||||
openclaw cron runs --id <job-id>
|
||||
```
|
||||
|
||||
## cron 작동 방식
|
||||
|
||||
- Cron은 **Gateway 프로세스 내부에서** 실행됩니다(모델 내부가 아님).
|
||||
- 작업은 `~/.openclaw/cron/jobs.json`에 영속 저장되므로 재시작해도 일정이 사라지지 않습니다.
|
||||
- 모든 cron 실행은 [background task](/automation/tasks) 레코드를 생성합니다.
|
||||
- 일회성 작업(`--at`)은 기본적으로 성공 후 자동 삭제됩니다.
|
||||
- 격리된 cron 실행은 완료 시 해당 `cron:<jobId>` 세션에 대해 추적된 브라우저 탭/프로세스를 최선의 노력으로 종료하므로, 분리된 브라우저 자동화가 고아 프로세스를 남기지 않습니다.
|
||||
- 격리된 cron 실행은 오래된 확인 응답도 방지합니다. 첫 번째 결과가 단지 중간 상태 업데이트(`on it`, `pulling everything together` 및 유사한 힌트)이고, 최종 답변에 여전히 책임이 있는 하위 subagent 실행이 없다면, OpenClaw는 전달 전에 실제 결과를 얻기 위해 한 번 더 다시 프롬프트합니다.
|
||||
|
||||
cron의 작업 조정은 런타임이 소유합니다. 오래된 하위 세션 행이 여전히 존재하더라도, 활성 cron 작업은 cron 런타임이 해당 작업을 실행 중으로 추적하는 동안 계속 활성 상태로 유지됩니다.
|
||||
런타임이 더 이상 작업을 소유하지 않고 5분 유예 시간이 지나면, 유지보수에서 해당 작업을 `lost`로 표시할 수 있습니다.
|
||||
|
||||
## 일정 유형
|
||||
|
||||
| 종류 | CLI 플래그 | 설명 |
|
||||
| ------- | ---------- | --------------------------------------------------------- |
|
||||
| `at` | `--at` | 일회성 타임스탬프(ISO 8601 또는 `20m` 같은 상대 시간) |
|
||||
| `every` | `--every` | 고정 간격 |
|
||||
| `cron` | `--cron` | 선택적 `--tz`와 함께 사용하는 5필드 또는 6필드 cron 표현식 |
|
||||
|
||||
타임존이 없는 타임스탬프는 UTC로 처리됩니다. 로컬 벽시계 기준 예약에는 `--tz America/New_York`를 추가하세요.
|
||||
|
||||
정시 반복 표현식은 부하 급증을 줄이기 위해 최대 5분까지 자동으로 분산됩니다. 정확한 타이밍을 강제하려면 `--exact`를 사용하고, 명시적인 범위를 원하면 `--stagger 30s`를 사용하세요.
|
||||
|
||||
## 실행 스타일
|
||||
|
||||
| 스타일 | `--session` 값 | 실행 위치 | 적합한 용도 |
|
||||
| -------------- | ------------------- | ------------------------- | ------------------------------- |
|
||||
| 메인 세션 | `main` | 다음 heartbeat 턴 | 리마인더, 시스템 이벤트 |
|
||||
| 격리됨 | `isolated` | 전용 `cron:<jobId>` | 리포트, 백그라운드 작업 |
|
||||
| 현재 세션 | `current` | 생성 시점에 바인딩됨 | 컨텍스트 인지형 반복 작업 |
|
||||
| 커스텀 세션 | `session:custom-id` | 영속적인 이름 있는 세션 | 기록을 기반으로 쌓이는 워크플로 |
|
||||
|
||||
**메인 세션** 작업은 시스템 이벤트를 큐에 넣고 선택적으로 heartbeat를 깨웁니다(`--wake now` 또는 `--wake next-heartbeat`). **격리됨** 작업은 새 세션으로 전용 에이전트 턴을 실행합니다. **커스텀 세션**(`session:xxx`)은 실행 간 컨텍스트를 유지하므로, 이전 요약을 바탕으로 쌓이는 일일 스탠드업 같은 워크플로를 가능하게 합니다.
|
||||
|
||||
격리된 작업의 경우, 런타임 종료 단계에는 이제 해당 cron 세션에 대한 최선의 노력 기반 브라우저 정리가 포함됩니다. 정리 실패는 실제 cron 결과가 우선되도록 무시됩니다.
|
||||
|
||||
격리된 cron 실행이 subagent를 조정할 때는, 전달 시에도 오래된 상위 중간 텍스트보다 최종 하위 결과를 우선합니다. 하위 실행이 아직 진행 중이면, OpenClaw는 그 부분적인 상위 업데이트를 알리는 대신 억제합니다.
|
||||
|
||||
### 격리된 작업의 페이로드 옵션
|
||||
|
||||
- `--message`: 프롬프트 텍스트(격리됨에서 필수)
|
||||
- `--model` / `--thinking`: 모델 및 thinking 수준 재정의
|
||||
- `--light-context`: 워크스페이스 부트스트랩 파일 주입 건너뛰기
|
||||
- `--tools exec,read`: 작업이 사용할 수 있는 도구 제한
|
||||
|
||||
`--model`은 해당 작업에 대해 선택된 허용 모델을 사용합니다. 요청한 모델이 허용되지 않으면 cron은 경고를 기록하고, 대신 작업의 agent/default 모델 선택으로 대체합니다. 구성된 fallback 체인은 계속 적용되지만, 명시적 작업별 fallback 목록이 없는 단순 모델 재정의는 더 이상 숨겨진 추가 재시도 대상으로 agent primary를 덧붙이지 않습니다.
|
||||
|
||||
격리된 작업의 모델 선택 우선순위는 다음과 같습니다.
|
||||
|
||||
1. Gmail 훅 모델 재정의(실행이 Gmail에서 왔고 해당 재정의가 허용된 경우)
|
||||
2. 작업별 페이로드 `model`
|
||||
3. 저장된 cron 세션 모델 재정의
|
||||
4. Agent/default 모델 선택
|
||||
|
||||
빠른 모드도 해결된 라이브 선택을 따릅니다. 선택된 모델 구성에 `params.fastMode`가 있으면, 격리된 cron은 기본적으로 이를 사용합니다. 저장된 세션 `fastMode` 재정의는 어느 방향에서든 여전히 구성보다 우선합니다.
|
||||
|
||||
격리된 실행이 라이브 모델 전환 handoff에 도달하면, cron은 전환된 provider/model로 재시도하고 재시도 전에 해당 라이브 선택을 영속 저장합니다. 전환에 새 auth profile도 포함되어 있으면, cron은 그 auth profile 재정의도 저장합니다. 재시도는 제한됩니다. 초기 시도에 더해 전환 재시도 2회를 넘기면, cron은 무한 반복하는 대신 중단합니다.
|
||||
|
||||
## 전달 및 출력
|
||||
|
||||
| 모드 | 동작 |
|
||||
| ---------- | ------------------------------------------------------------ |
|
||||
| `announce` | 요약을 대상 채널로 전달(격리됨의 기본값) |
|
||||
| `webhook` | 완료된 이벤트 페이로드를 URL로 POST |
|
||||
| `none` | 내부 전용, 전달 없음 |
|
||||
|
||||
채널 전달에는 `--announce --channel telegram --to "-1001234567890"`를 사용하세요. Telegram 포럼 주제의 경우 `-1001234567890:topic:123`을 사용하세요. Slack/Discord/Mattermost 대상은 명시적 접두사(`channel:<id>`, `user:<id>`)를 사용해야 합니다.
|
||||
|
||||
cron이 소유한 격리된 작업의 경우, 실행기가 최종 전달 경로를 소유합니다. 에이전트는 일반 텍스트 요약을 반환하도록 프롬프트되며, 그 요약은 이후 `announce`, `webhook`으로 전송되거나 `none`일 경우 내부에만 유지됩니다. `--no-deliver`는 전달을 에이전트에 되돌리지 않으며, 실행을 내부 전용으로 유지합니다.
|
||||
|
||||
원래 작업이 어떤 외부 수신자에게 메시지를 보내라고 명시적으로 지시한 경우, 에이전트는 직접 전송을 시도하는 대신 그 메시지가 누구/어디로 가야 하는지를 출력에 적어야 합니다.
|
||||
|
||||
실패 알림은 별도의 대상 경로를 따릅니다.
|
||||
|
||||
- `cron.failureDestination`은 실패 알림의 전역 기본값을 설정합니다.
|
||||
- `job.delivery.failureDestination`은 작업별로 이를 재정의합니다.
|
||||
- 둘 다 설정되지 않았고 작업이 이미 `announce`를 통해 전달하는 경우, 실패 알림은 이제 기본 announce 대상으로 대체됩니다.
|
||||
- `delivery.failureDestination`은 기본 전달 모드가 `webhook`인 경우를 제외하면 `sessionTarget="isolated"` 작업에서만 지원됩니다.
|
||||
|
||||
## CLI 예시
|
||||
|
||||
일회성 리마인더(메인 세션):
|
||||
|
||||
```bash
|
||||
openclaw cron add \
|
||||
--name "Calendar check" \
|
||||
--at "20m" \
|
||||
--session main \
|
||||
--system-event "Next heartbeat: check calendar." \
|
||||
--wake now
|
||||
```
|
||||
|
||||
전달이 포함된 반복 격리 작업:
|
||||
|
||||
```bash
|
||||
openclaw cron add \
|
||||
--name "Morning brief" \
|
||||
--cron "0 7 * * *" \
|
||||
--tz "America/Los_Angeles" \
|
||||
--session isolated \
|
||||
--message "Summarize overnight updates." \
|
||||
--announce \
|
||||
--channel slack \
|
||||
--to "channel:C1234567890"
|
||||
```
|
||||
|
||||
모델 및 thinking 재정의가 포함된 격리 작업:
|
||||
|
||||
```bash
|
||||
openclaw cron add \
|
||||
--name "Deep analysis" \
|
||||
--cron "0 6 * * 1" \
|
||||
--tz "America/Los_Angeles" \
|
||||
--session isolated \
|
||||
--message "Weekly deep analysis of project progress." \
|
||||
--model "opus" \
|
||||
--thinking high \
|
||||
--announce
|
||||
```
|
||||
|
||||
## 웹훅
|
||||
|
||||
Gateway는 외부 트리거를 위해 HTTP 웹훅 엔드포인트를 노출할 수 있습니다. config에서 활성화하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
hooks: {
|
||||
enabled: true,
|
||||
token: "shared-secret",
|
||||
path: "/hooks",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 인증
|
||||
|
||||
모든 요청에는 헤더를 통해 훅 토큰이 포함되어야 합니다.
|
||||
|
||||
- `Authorization: Bearer <token>`(권장)
|
||||
- `x-openclaw-token: <token>`
|
||||
|
||||
쿼리 문자열 토큰은 거부됩니다.
|
||||
|
||||
### POST /hooks/wake
|
||||
|
||||
메인 세션에 시스템 이벤트를 큐에 넣습니다.
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:18789/hooks/wake \
|
||||
-H 'Authorization: Bearer SECRET' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"text":"New email received","mode":"now"}'
|
||||
```
|
||||
|
||||
- `text`(필수): 이벤트 설명
|
||||
- `mode`(선택 사항): `now`(기본값) 또는 `next-heartbeat`
|
||||
|
||||
### POST /hooks/agent
|
||||
|
||||
격리된 에이전트 턴을 실행합니다.
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:18789/hooks/agent \
|
||||
-H 'Authorization: Bearer SECRET' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.4-mini"}'
|
||||
```
|
||||
|
||||
필드: `message`(필수), `name`, `agentId`, `wakeMode`, `deliver`, `channel`, `to`, `model`, `thinking`, `timeoutSeconds`.
|
||||
|
||||
### 매핑된 훅(POST /hooks/\<name\>)
|
||||
|
||||
커스텀 훅 이름은 config의 `hooks.mappings`를 통해 해석됩니다. 매핑은 템플릿이나 코드 변환을 사용해 임의의 페이로드를 `wake` 또는 `agent` 작업으로 변환할 수 있습니다.
|
||||
|
||||
### 보안
|
||||
|
||||
- 훅 엔드포인트는 loopback, tailnet 또는 신뢰할 수 있는 리버스 프록시 뒤에 두세요.
|
||||
- 전용 훅 토큰을 사용하세요. gateway auth 토큰을 재사용하지 마세요.
|
||||
- `hooks.path`는 전용 하위 경로로 유지하세요. `/`는 거부됩니다.
|
||||
- 명시적 `agentId` 라우팅을 제한하려면 `hooks.allowedAgentIds`를 설정하세요.
|
||||
- 호출자가 세션을 선택해야 하는 경우가 아니라면 `hooks.allowRequestSessionKey=false`를 유지하세요.
|
||||
- `hooks.allowRequestSessionKey`를 활성화하는 경우, 허용된 세션 키 형태를 제한하기 위해 `hooks.allowedSessionKeyPrefixes`도 함께 설정하세요.
|
||||
- 훅 페이로드는 기본적으로 안전 경계로 감싸집니다.
|
||||
|
||||
## Gmail PubSub 통합
|
||||
|
||||
Google PubSub를 통해 Gmail 받은편지함 트리거를 OpenClaw에 연결하세요.
|
||||
|
||||
**사전 요구 사항**: `gcloud` CLI, `gog`(gogcli), OpenClaw hooks 활성화, 공개 HTTPS 엔드포인트용 Tailscale.
|
||||
|
||||
### 마법사 설정(권장)
|
||||
|
||||
```bash
|
||||
openclaw webhooks gmail setup --account openclaw@gmail.com
|
||||
```
|
||||
|
||||
이 명령은 `hooks.gmail` config를 기록하고, Gmail 프리셋을 활성화하며, 푸시 엔드포인트에 Tailscale Funnel을 사용합니다.
|
||||
|
||||
### Gateway 자동 시작
|
||||
|
||||
`hooks.enabled=true`이고 `hooks.gmail.account`가 설정되어 있으면, Gateway는 부팅 시 `gog gmail watch serve`를 시작하고 watch를 자동 갱신합니다. 제외하려면 `OPENCLAW_SKIP_GMAIL_WATCHER=1`을 설정하세요.
|
||||
|
||||
### 수동 1회 설정
|
||||
|
||||
1. `gog`가 사용하는 OAuth 클라이언트를 소유한 GCP 프로젝트를 선택합니다.
|
||||
|
||||
```bash
|
||||
gcloud auth login
|
||||
gcloud config set project <project-id>
|
||||
gcloud services enable gmail.googleapis.com pubsub.googleapis.com
|
||||
```
|
||||
|
||||
2. 토픽을 만들고 Gmail 푸시 액세스 권한을 부여합니다.
|
||||
|
||||
```bash
|
||||
gcloud pubsub topics create gog-gmail-watch
|
||||
gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \
|
||||
--member=serviceAccount:gmail-api-push@system.gserviceaccount.com \
|
||||
--role=roles/pubsub.publisher
|
||||
```
|
||||
|
||||
3. watch를 시작합니다.
|
||||
|
||||
```bash
|
||||
gog gmail watch start \
|
||||
--account openclaw@gmail.com \
|
||||
--label INBOX \
|
||||
--topic projects/<project-id>/topics/gog-gmail-watch
|
||||
```
|
||||
|
||||
### Gmail 모델 재정의
|
||||
|
||||
```json5
|
||||
{
|
||||
hooks: {
|
||||
gmail: {
|
||||
model: "openrouter/meta-llama/llama-3.3-70b-instruct:free",
|
||||
thinking: "off",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 작업 관리
|
||||
|
||||
```bash
|
||||
# 모든 작업 나열
|
||||
openclaw cron list
|
||||
|
||||
# 작업 편집
|
||||
openclaw cron edit <jobId> --message "Updated prompt" --model "opus"
|
||||
|
||||
# 지금 작업 강제 실행
|
||||
openclaw cron run <jobId>
|
||||
|
||||
# 기한이 지난 경우에만 실행
|
||||
openclaw cron run <jobId> --due
|
||||
|
||||
# 실행 기록 보기
|
||||
openclaw cron runs --id <jobId> --limit 50
|
||||
|
||||
# 작업 삭제
|
||||
openclaw cron remove <jobId>
|
||||
|
||||
# Agent 선택(멀티 agent 설정)
|
||||
openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops
|
||||
openclaw cron edit <jobId> --clear-agent
|
||||
```
|
||||
|
||||
모델 재정의 참고:
|
||||
|
||||
- `openclaw cron add|edit --model ...`은 작업의 선택된 모델을 변경합니다.
|
||||
- 모델이 허용되면, 정확히 그 provider/model이 격리된 agent 실행에 전달됩니다.
|
||||
- 허용되지 않으면, cron은 경고를 표시하고 작업의 agent/default 모델 선택으로 대체합니다.
|
||||
- 구성된 fallback 체인은 계속 적용되지만, 명시적 작업별 fallback 목록이 없는 일반 `--model` 재정의는 더 이상 조용한 추가 재시도 대상으로 agent primary로 넘어가지 않습니다.
|
||||
|
||||
## 구성
|
||||
|
||||
```json5
|
||||
{
|
||||
cron: {
|
||||
enabled: true,
|
||||
store: "~/.openclaw/cron/jobs.json",
|
||||
maxConcurrentRuns: 1,
|
||||
retry: {
|
||||
maxAttempts: 3,
|
||||
backoffMs: [60000, 120000, 300000],
|
||||
retryOn: ["rate_limit", "overloaded", "network", "server_error"],
|
||||
},
|
||||
webhookToken: "replace-with-dedicated-webhook-token",
|
||||
sessionRetention: "24h",
|
||||
runLog: { maxBytes: "2mb", keepLines: 2000 },
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
cron 비활성화: `cron.enabled: false` 또는 `OPENCLAW_SKIP_CRON=1`.
|
||||
|
||||
**일회성 재시도**: 일시적 오류(rate limit, overload, network, server error)는 지수 백오프와 함께 최대 3회 재시도합니다. 영구 오류는 즉시 비활성화됩니다.
|
||||
|
||||
**반복 재시도**: 재시도 사이에 지수 백오프(30초~60분)를 사용합니다. 다음 성공 실행 후에는 백오프가 초기화됩니다.
|
||||
|
||||
**유지보수**: `cron.sessionRetention`(기본값 `24h`)은 격리된 실행 세션 항목을 정리합니다. `cron.runLog.maxBytes` / `cron.runLog.keepLines`는 실행 로그 파일을 자동 정리합니다.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 명령 순서
|
||||
|
||||
```bash
|
||||
openclaw status
|
||||
openclaw gateway status
|
||||
openclaw cron status
|
||||
openclaw cron list
|
||||
openclaw cron runs --id <jobId> --limit 20
|
||||
openclaw system heartbeat last
|
||||
openclaw logs --follow
|
||||
openclaw doctor
|
||||
```
|
||||
|
||||
### Cron이 실행되지 않음
|
||||
|
||||
- `cron.enabled`와 `OPENCLAW_SKIP_CRON` 환경 변수를 확인하세요.
|
||||
- Gateway가 계속 실행 중인지 확인하세요.
|
||||
- `cron` 일정의 경우 타임존(`--tz`)과 호스트 타임존이 일치하는지 확인하세요.
|
||||
- 실행 출력의 `reason: not-due`는 수동 실행이 `openclaw cron run <jobId> --due`로 확인되었고 작업 기한이 아직 되지 않았음을 의미합니다.
|
||||
|
||||
### Cron이 실행되었지만 전달이 없음
|
||||
|
||||
- 전달 모드가 `none`이면 외부 메시지는 예상되지 않습니다.
|
||||
- 전달 대상이 없거나 잘못된 경우(`channel`/`to`) 아웃바운드가 건너뛰어집니다.
|
||||
- 채널 인증 오류(`unauthorized`, `Forbidden`)는 자격 증명 때문에 전달이 차단되었음을 의미합니다.
|
||||
- 격리된 실행이 무음 토큰(`NO_REPLY` / `no_reply`)만 반환하면, OpenClaw는 직접 아웃바운드 전달과 fallback 대기열 요약 경로도 모두 억제하므로 채팅으로 아무것도 게시되지 않습니다.
|
||||
- cron이 소유한 격리된 작업의 경우, fallback으로 에이전트가 message 도구를 사용할 것이라 기대하지 마세요. 최종 전달은 실행기가 소유하며, `--no-deliver`는 직접 전송을 허용하는 대신 내부 전용으로 유지합니다.
|
||||
|
||||
### 타임존 관련 주의사항
|
||||
|
||||
- `--tz`가 없는 cron은 gateway 호스트 타임존을 사용합니다.
|
||||
- 타임존이 없는 `at` 일정은 UTC로 처리됩니다.
|
||||
- Heartbeat `activeHours`는 구성된 타임존 해석을 사용합니다.
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [Automation & Tasks](/automation) — 모든 자동화 메커니즘 한눈에 보기
|
||||
- [Background Tasks](/automation/tasks) — cron 실행을 위한 작업 원장
|
||||
- [Heartbeat](/gateway/heartbeat) — 주기적인 메인 세션 턴
|
||||
- [Timezone](/concepts/timezone) — 타임존 구성
|
||||
15
docs/ko/automation/cron-vs-heartbeat.md
Normal file
15
docs/ko/automation/cron-vs-heartbeat.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
summary: /automation으로 리디렉션
|
||||
title: Cron vs Heartbeat
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:33:52Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 579c6618108ad7e2a71f53d5d6aa6550956fa0fdb2fe64ecdb7e8a0ce1366e33
|
||||
source_path: automation/cron-vs-heartbeat.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Cron vs Heartbeat
|
||||
|
||||
이 페이지는 [Automation & Tasks](/automation)(으)로 이동했습니다. cron과 heartbeat를 비교하는 결정 가이드는 [Automation & Tasks](/automation)를 참조하세요.
|
||||
15
docs/ko/automation/gmail-pubsub.md
Normal file
15
docs/ko/automation/gmail-pubsub.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
summary: /automation/cron-jobs로 리디렉션
|
||||
title: Gmail PubSub
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:33:53Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: c2e17fdc8c09d52b6dc9fb6c44053446f07d02c65a0ab725d4ea038bd035d889
|
||||
source_path: automation/gmail-pubsub.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Gmail PubSub
|
||||
|
||||
이 페이지는 [예약된 작업](/automation/cron-jobs#gmail-pubsub-integration)(으)로 이동했습니다. Gmail PubSub 문서는 [예약된 작업](/automation/cron-jobs#gmail-pubsub-integration)을 참조하세요.
|
||||
310
docs/ko/automation/hooks.md
Normal file
310
docs/ko/automation/hooks.md
Normal file
@ -0,0 +1,310 @@
|
||||
---
|
||||
read_when:
|
||||
- /new, /reset, /stop 및 에이전트 수명 주기 이벤트에 대한 이벤트 기반 자동화를 원합니다
|
||||
- Hooks를 빌드, 설치 또는 디버그하려고 합니다
|
||||
summary: 'Hooks: 명령 및 수명 주기 이벤트를 위한 이벤트 기반 자동화'
|
||||
title: Hooks
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:20Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 66eb75bb2b3b2ad229bf3da24fdb0fe021ed08f812fd1d13c69b3bd9df0218e5
|
||||
source_path: automation/hooks.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Hooks
|
||||
|
||||
Hooks는 Gateway 내부에서 어떤 일이 발생할 때 실행되는 작은 스크립트입니다. 디렉터리에서 자동으로 검색되며 `openclaw hooks`로 확인할 수 있습니다.
|
||||
|
||||
OpenClaw에는 두 종류의 hooks가 있습니다.
|
||||
|
||||
- **내부 hooks**(이 페이지): `/new`, `/reset`, `/stop` 또는 수명 주기 이벤트처럼 에이전트 이벤트가 발생할 때 Gateway 내부에서 실행됩니다.
|
||||
- **웹훅**: 다른 시스템이 OpenClaw에서 작업을 트리거할 수 있게 하는 외부 HTTP 엔드포인트입니다. [Webhooks](/automation/cron-jobs#webhooks)를 참조하세요.
|
||||
|
||||
Hooks는 plugins 내부에 번들로 포함될 수도 있습니다. `openclaw hooks list`는 독립형 hooks와 plugin이 관리하는 hooks를 모두 표시합니다.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
```bash
|
||||
# 사용 가능한 hooks 나열
|
||||
openclaw hooks list
|
||||
|
||||
# hook 활성화
|
||||
openclaw hooks enable session-memory
|
||||
|
||||
# hook 상태 확인
|
||||
openclaw hooks check
|
||||
|
||||
# 자세한 정보 가져오기
|
||||
openclaw hooks info session-memory
|
||||
```
|
||||
|
||||
## 이벤트 유형
|
||||
|
||||
| 이벤트 | 발생 시점 |
|
||||
| ------------------------ | ------------------------------------------------ |
|
||||
| `command:new` | `/new` 명령이 실행될 때 |
|
||||
| `command:reset` | `/reset` 명령이 실행될 때 |
|
||||
| `command:stop` | `/stop` 명령이 실행될 때 |
|
||||
| `command` | 모든 명령 이벤트(일반 리스너) |
|
||||
| `session:compact:before` | 압축이 기록을 요약하기 전 |
|
||||
| `session:compact:after` | 압축이 완료된 후 |
|
||||
| `session:patch` | 세션 속성이 수정될 때 |
|
||||
| `agent:bootstrap` | 워크스페이스 bootstrap 파일이 주입되기 전 |
|
||||
| `gateway:startup` | 채널이 시작되고 hooks가 로드된 후 |
|
||||
| `message:received` | 모든 채널의 수신 메시지 |
|
||||
| `message:transcribed` | 오디오 전사가 완료된 후 |
|
||||
| `message:preprocessed` | 모든 미디어 및 링크 이해가 완료된 후 |
|
||||
| `message:sent` | 발신 메시지가 전달된 후 |
|
||||
|
||||
## Hooks 작성하기
|
||||
|
||||
### Hook 구조
|
||||
|
||||
각 hook은 두 개의 파일이 포함된 디렉터리입니다.
|
||||
|
||||
```
|
||||
my-hook/
|
||||
├── HOOK.md # 메타데이터 + 문서
|
||||
└── handler.ts # 핸들러 구현
|
||||
```
|
||||
|
||||
### HOOK.md 형식
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: my-hook
|
||||
description: "이 hook이 수행하는 작업에 대한 짧은 설명"
|
||||
metadata:
|
||||
{ "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } }
|
||||
---
|
||||
|
||||
# My Hook
|
||||
|
||||
여기에 자세한 문서를 작성합니다.
|
||||
```
|
||||
|
||||
**메타데이터 필드** (`metadata.openclaw`):
|
||||
|
||||
| 필드 | 설명 |
|
||||
| ---------- | ---------------------------------------------------- |
|
||||
| `emoji` | CLI용 표시 이모지 |
|
||||
| `events` | 수신할 이벤트 배열 |
|
||||
| `export` | 사용할 이름 있는 export(기본값: `"default"`) |
|
||||
| `os` | 필요한 플랫폼(예: `["darwin", "linux"]`) |
|
||||
| `requires` | 필요한 `bins`, `anyBins`, `env` 또는 `config` 경로 |
|
||||
| `always` | 적격성 검사 우회(boolean) |
|
||||
| `install` | 설치 방법 |
|
||||
|
||||
### 핸들러 구현
|
||||
|
||||
```typescript
|
||||
const handler = async (event) => {
|
||||
if (event.type !== "command" || event.action !== "new") {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[my-hook] New command triggered`);
|
||||
// 여기에 로직 작성
|
||||
|
||||
// 선택적으로 사용자에게 메시지 전송
|
||||
event.messages.push("Hook executed!");
|
||||
};
|
||||
|
||||
export default handler;
|
||||
```
|
||||
|
||||
각 이벤트에는 `type`, `action`, `sessionKey`, `timestamp`, `messages`(사용자에게 보내려면 push), `context`(이벤트별 데이터)가 포함됩니다.
|
||||
|
||||
### 이벤트 컨텍스트 핵심 항목
|
||||
|
||||
**명령 이벤트** (`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`를 포함한 provider별 데이터).
|
||||
|
||||
**메시지 이벤트** (`message:sent`): `context.to`, `context.content`, `context.success`, `context.channelId`.
|
||||
|
||||
**메시지 이벤트** (`message:transcribed`): `context.transcript`, `context.from`, `context.channelId`, `context.mediaPath`.
|
||||
|
||||
**메시지 이벤트** (`message:preprocessed`): `context.bodyForAgent`(최종 보강된 본문), `context.from`, `context.channelId`.
|
||||
|
||||
**Bootstrap 이벤트** (`agent:bootstrap`): `context.bootstrapFiles`(변경 가능한 배열), `context.agentId`.
|
||||
|
||||
**세션 패치 이벤트** (`session:patch`): `context.sessionEntry`, `context.patch`(변경된 필드만), `context.cfg`. 패치 이벤트는 권한이 있는 클라이언트만 트리거할 수 있습니다.
|
||||
|
||||
**압축 이벤트**: `session:compact:before`에는 `messageCount`, `tokenCount`가 포함됩니다. `session:compact:after`에는 `compactedCount`, `summaryLength`, `tokensBefore`, `tokensAfter`가 추가됩니다.
|
||||
|
||||
## Hook 검색
|
||||
|
||||
Hooks는 다음 디렉터리에서 검색되며, 아래로 갈수록 재정의 우선순위가 높아집니다.
|
||||
|
||||
1. **번들 hooks**: OpenClaw와 함께 제공됨
|
||||
2. **Plugin hooks**: 설치된 plugins 내부에 번들된 hooks
|
||||
3. **관리형 hooks**: `~/.openclaw/hooks/` (사용자가 설치하며 워크스페이스 간 공유). `hooks.internal.load.extraDirs`의 추가 디렉터리도 이 우선순위를 공유합니다.
|
||||
4. **워크스페이스 hooks**: `<workspace>/hooks/` (에이전트별, 명시적으로 활성화하기 전까지 기본적으로 비활성화됨)
|
||||
|
||||
워크스페이스 hooks는 새 hook 이름을 추가할 수 있지만, 같은 이름의 번들, 관리형 또는 plugin 제공 hooks를 재정의할 수는 없습니다.
|
||||
|
||||
### Hook 팩
|
||||
|
||||
Hook 팩은 `package.json`의 `openclaw.hooks`를 통해 hooks를 export하는 npm 패키지입니다. 설치 방법:
|
||||
|
||||
```bash
|
||||
openclaw plugins install <path-or-spec>
|
||||
```
|
||||
|
||||
Npm spec은 레지스트리 전용입니다(패키지 이름 + 선택적 정확한 버전 또는 dist-tag). Git/URL/file spec 및 semver 범위는 거부됩니다.
|
||||
|
||||
## 번들 hooks
|
||||
|
||||
| Hook | 이벤트 | 수행 작업 |
|
||||
| --------------------- | ------------------------------ | ----------------------------------------------------- |
|
||||
| session-memory | `command:new`, `command:reset` | 세션 컨텍스트를 `<workspace>/memory/`에 저장 |
|
||||
| bootstrap-extra-files | `agent:bootstrap` | glob 패턴에서 추가 bootstrap 파일 주입 |
|
||||
| command-logger | `command` | 모든 명령을 `~/.openclaw/logs/commands.log`에 기록 |
|
||||
| boot-md | `gateway:startup` | gateway 시작 시 `BOOT.md` 실행 |
|
||||
|
||||
번들 hook 활성화:
|
||||
|
||||
```bash
|
||||
openclaw hooks enable <hook-name>
|
||||
```
|
||||
|
||||
### session-memory 세부 정보
|
||||
|
||||
최근 사용자/assistant 메시지 15개를 추출하고, LLM을 통해 설명적인 파일명 슬러그를 생성한 뒤 `<workspace>/memory/YYYY-MM-DD-slug.md`에 저장합니다. `workspace.dir`이 구성되어 있어야 합니다.
|
||||
|
||||
### bootstrap-extra-files 구성
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"internal": {
|
||||
"entries": {
|
||||
"bootstrap-extra-files": {
|
||||
"enabled": true,
|
||||
"paths": ["packages/*/AGENTS.md", "packages/*/TOOLS.md"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
경로는 워크스페이스를 기준으로 해석됩니다. 인식된 bootstrap basename만 로드됩니다(`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, `MEMORY.md`).
|
||||
|
||||
## Plugin hooks
|
||||
|
||||
Plugins는 더 깊은 통합을 위해 Plugin SDK를 통해 hooks를 등록할 수 있습니다. 예를 들어 도구 호출 가로채기, 프롬프트 수정, 메시지 흐름 제어 등이 가능합니다. Plugin SDK는 모델 확인, 에이전트 수명 주기, 메시지 흐름, 도구 실행, 서브에이전트 조정, gateway 수명 주기를 포괄하는 28개의 hooks를 제공합니다.
|
||||
|
||||
`before_tool_call`, `before_agent_reply`, `before_install` 및 기타 모든 plugin hooks를 포함한 전체 plugin hook 참조는 [Plugin Architecture](/plugins/architecture#provider-runtime-hooks)를 참조하세요.
|
||||
|
||||
## 구성
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"internal": {
|
||||
"enabled": true,
|
||||
"entries": {
|
||||
"session-memory": { "enabled": true },
|
||||
"command-logger": { "enabled": false }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Hook별 환경 변수:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"internal": {
|
||||
"entries": {
|
||||
"my-hook": {
|
||||
"enabled": true,
|
||||
"env": { "MY_CUSTOM_VAR": "value" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
추가 hook 디렉터리:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"internal": {
|
||||
"load": {
|
||||
"extraDirs": ["/path/to/more/hooks"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
레거시 `hooks.internal.handlers` 배열 구성 형식도 이전 버전과의 호환성을 위해 계속 지원되지만, 새 hooks는 검색 기반 시스템을 사용해야 합니다.
|
||||
</Note>
|
||||
|
||||
## CLI 참조
|
||||
|
||||
```bash
|
||||
# 모든 hooks 나열(--eligible, --verbose 또는 --json 추가 가능)
|
||||
openclaw hooks list
|
||||
|
||||
# hook의 자세한 정보 표시
|
||||
openclaw hooks info <hook-name>
|
||||
|
||||
# 적격성 요약 표시
|
||||
openclaw hooks check
|
||||
|
||||
# 활성화/비활성화
|
||||
openclaw hooks enable <hook-name>
|
||||
openclaw hooks disable <hook-name>
|
||||
```
|
||||
|
||||
## 모범 사례
|
||||
|
||||
- **핸들러를 빠르게 유지하세요.** Hooks는 명령 처리 중 실행됩니다. 무거운 작업은 `void processInBackground(event)`로 실행만 시작하고 기다리지 마세요.
|
||||
- **오류를 우아하게 처리하세요.** 위험한 작업은 try/catch로 감싸고, 다른 핸들러도 실행될 수 있도록 throw하지 마세요.
|
||||
- **이벤트를 초기에 필터링하세요.** 이벤트 type/action이 관련 없으면 즉시 반환하세요.
|
||||
- **구체적인 이벤트 키를 사용하세요.** 오버헤드를 줄이기 위해 `"events": ["command"]`보다 `"events": ["command:new"]`를 권장합니다.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### Hook이 검색되지 않음
|
||||
|
||||
```bash
|
||||
# 디렉터리 구조 확인
|
||||
ls -la ~/.openclaw/hooks/my-hook/
|
||||
# 표시되어야 함: HOOK.md, handler.ts
|
||||
|
||||
# 검색된 모든 hooks 나열
|
||||
openclaw hooks list
|
||||
```
|
||||
|
||||
### Hook이 적격하지 않음
|
||||
|
||||
```bash
|
||||
openclaw hooks info my-hook
|
||||
```
|
||||
|
||||
누락된 바이너리(PATH), 환경 변수, 구성 값 또는 OS 호환성을 확인하세요.
|
||||
|
||||
### Hook이 실행되지 않음
|
||||
|
||||
1. hook이 활성화되어 있는지 확인합니다: `openclaw hooks list`
|
||||
2. hooks가 다시 로드되도록 gateway 프로세스를 재시작합니다.
|
||||
3. gateway 로그를 확인합니다: `./scripts/clawlog.sh | grep hook`
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [CLI Reference: hooks](/cli/hooks)
|
||||
- [Webhooks](/automation/cron-jobs#webhooks)
|
||||
- [Plugin Architecture](/plugins/architecture#provider-runtime-hooks) — 전체 plugin hook 참조
|
||||
- [Configuration](/gateway/configuration-reference#hooks)
|
||||
122
docs/ko/automation/index.md
Normal file
122
docs/ko/automation/index.md
Normal file
@ -0,0 +1,122 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw로 작업을 자동화하는 방법을 결정할 때
|
||||
- heartbeat, cron, hooks, standing orders 중에서 선택할 때
|
||||
- 적절한 자동화 진입점을 찾고 있을 때
|
||||
summary: '자동화 메커니즘 개요: 작업, cron, hooks, standing orders, Task Flow'
|
||||
title: 자동화 및 작업
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:17Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 13cd05dcd2f38737f7bb19243ad1136978bfd727006fd65226daa3590f823afe
|
||||
source_path: automation/index.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 자동화 및 작업
|
||||
|
||||
OpenClaw는 작업, 예약 작업, 이벤트 hooks, 상시 지시를 통해 백그라운드에서 작업을 실행합니다. 이 페이지는 적절한 메커니즘을 선택하고 이들이 어떻게 함께 작동하는지 이해하는 데 도움을 줍니다.
|
||||
|
||||
## 빠른 결정 가이드
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
START([무엇이 필요하신가요?]) --> Q1{작업을 예약하시겠습니까?}
|
||||
START --> Q2{분리된 작업을 추적하시겠습니까?}
|
||||
START --> Q3{여러 단계의 흐름을 오케스트레이션하시겠습니까?}
|
||||
START --> Q4{수명 주기 이벤트에 반응하시겠습니까?}
|
||||
START --> Q5{에이전트에 지속적인 지침을 제공하시겠습니까?}
|
||||
|
||||
Q1 -->|예| Q1a{정확한 시간인가요, 아니면 유연해도 되나요?}
|
||||
Q1a -->|정확함| CRON["예약 작업 (Cron)"]
|
||||
Q1a -->|유연함| HEARTBEAT[Heartbeat]
|
||||
|
||||
Q2 -->|예| TASKS[백그라운드 작업]
|
||||
Q3 -->|예| FLOW[Task Flow]
|
||||
Q4 -->|예| HOOKS[Hooks]
|
||||
Q5 -->|예| SO[Standing Orders]
|
||||
```
|
||||
|
||||
| 사용 사례 | 권장 항목 | 이유 |
|
||||
| --------------------------------------- | ---------------------- | ------------------------------------------------ |
|
||||
| 매일 오전 9시에 정확히 일일 보고서 전송 | 예약 작업 (Cron) | 정확한 시간, 격리된 실행 |
|
||||
| 20분 후에 알림 보내기 | 예약 작업 (Cron) | 정밀한 시간의 일회성 작업 (`--at`) |
|
||||
| 매주 심층 분석 실행 | 예약 작업 (Cron) | 독립형 작업, 다른 모델 사용 가능 |
|
||||
| 30분마다 받은편지함 확인 | Heartbeat | 다른 점검과 일괄 처리, 컨텍스트 인식 |
|
||||
| 예정된 이벤트가 있는지 캘린더 모니터링 | Heartbeat | 주기적 인식에 자연스럽게 적합 |
|
||||
| 서브에이전트 또는 ACP 실행 상태 점검 | 백그라운드 작업 | 작업 원장이 모든 분리된 작업을 추적 |
|
||||
| 무엇이 언제 실행되었는지 감사 | 백그라운드 작업 | `openclaw tasks list` 및 `openclaw tasks audit` |
|
||||
| 여러 단계의 조사 후 요약 | Task Flow | 리비전 추적이 포함된 내구성 있는 오케스트레이션 |
|
||||
| 세션 재설정 시 스크립트 실행 | Hooks | 이벤트 기반, 수명 주기 이벤트에서 실행됨 |
|
||||
| 모든 도구 호출마다 코드 실행 | Hooks | Hooks는 이벤트 유형으로 필터링 가능 |
|
||||
| 응답 전에 항상 규정 준수 확인 | Standing Orders | 모든 세션에 자동으로 주입됨 |
|
||||
|
||||
### 예약 작업 (Cron)과 Heartbeat 비교
|
||||
|
||||
| 차원 | 예약 작업 (Cron) | Heartbeat |
|
||||
| --------------- | ----------------------------------- | ------------------------------------- |
|
||||
| 타이밍 | 정확함 (cron 표현식, 일회성) | 대략적임 (기본 30분마다) |
|
||||
| 세션 컨텍스트 | 새로 시작됨 (격리됨) 또는 공유됨 | 전체 메인 세션 컨텍스트 |
|
||||
| 작업 기록 | 항상 생성됨 | 생성되지 않음 |
|
||||
| 전달 | 채널, webhook 또는 무음 | 메인 세션 내 인라인 |
|
||||
| 가장 적합한 용도 | 보고서, 알림, 백그라운드 작업 | 받은편지함 확인, 캘린더, 알림 |
|
||||
|
||||
정확한 타이밍이나 격리된 실행이 필요할 때는 예약 작업 (Cron)을 사용하세요. 전체 세션 컨텍스트의 이점을 활용할 수 있고 대략적인 타이밍이면 충분할 때는 Heartbeat를 사용하세요.
|
||||
|
||||
## 핵심 개념
|
||||
|
||||
### 예약 작업 (cron)
|
||||
|
||||
Cron은 정확한 타이밍을 위한 Gateway의 내장 스케줄러입니다. 작업을 지속적으로 저장하고, 적절한 시간에 에이전트를 깨우며, 출력을 채팅 채널이나 webhook 엔드포인트로 전달할 수 있습니다. 일회성 알림, 반복 표현식, 인바운드 webhook 트리거를 지원합니다.
|
||||
|
||||
[예약 작업](/automation/cron-jobs)을 참조하세요.
|
||||
|
||||
### 작업
|
||||
|
||||
백그라운드 작업 원장은 모든 분리된 작업을 추적합니다: ACP 실행, 서브에이전트 생성, 격리된 cron 실행, CLI 작업. 작업은 스케줄러가 아니라 기록입니다. 이를 검사하려면 `openclaw tasks list` 및 `openclaw tasks audit`를 사용하세요.
|
||||
|
||||
[백그라운드 작업](/automation/tasks)을 참조하세요.
|
||||
|
||||
### Task Flow
|
||||
|
||||
Task Flow는 백그라운드 작업 위에 있는 흐름 오케스트레이션 기반입니다. 관리형 및 미러링 동기화 모드, 리비전 추적, 그리고 검사용 `openclaw tasks flow list|show|cancel`을 통해 내구성 있는 여러 단계의 흐름을 관리합니다.
|
||||
|
||||
[Task Flow](/automation/taskflow)를 참조하세요.
|
||||
|
||||
### 상시 지시
|
||||
|
||||
상시 지시는 정의된 프로그램에 대해 에이전트에 영구적인 운영 권한을 부여합니다. 이는 워크스페이스 파일(일반적으로 `AGENTS.md`)에 저장되며 모든 세션에 주입됩니다. 시간 기반 강제를 위해 cron과 함께 결합하세요.
|
||||
|
||||
[Standing Orders](/automation/standing-orders)를 참조하세요.
|
||||
|
||||
### Hooks
|
||||
|
||||
Hooks는 에이전트 수명 주기 이벤트(` /new`, `/reset`, `/stop`), 세션 압축, gateway 시작, 메시지 흐름, 도구 호출에 의해 트리거되는 이벤트 기반 스크립트입니다. Hooks는 디렉터리에서 자동으로 검색되며 `openclaw hooks`로 관리할 수 있습니다.
|
||||
|
||||
[Hooks](/automation/hooks)를 참조하세요.
|
||||
|
||||
### Heartbeat
|
||||
|
||||
Heartbeat는 주기적인 메인 세션 턴입니다(기본값: 30분마다). 전체 세션 컨텍스트를 사용해 여러 점검(받은편지함, 캘린더, 알림)을 하나의 에이전트 턴으로 일괄 처리합니다. Heartbeat 턴은 작업 기록을 생성하지 않습니다. 작은 체크리스트에는 `HEARTBEAT.md`를 사용하고, heartbeat 자체 내에서 기한이 된 주기적 점검만 원할 때는 `tasks:` 블록을 사용하세요. 비어 있는 heartbeat 파일은 `empty-heartbeat-file`로 건너뛰고, 기한 기반 전용 작업 모드는 `no-tasks-due`로 건너뜁니다.
|
||||
|
||||
[Heartbeat](/gateway/heartbeat)를 참조하세요.
|
||||
|
||||
## 함께 작동하는 방식
|
||||
|
||||
- **Cron**은 정확한 일정(일일 보고서, 주간 검토)과 일회성 알림을 처리합니다. 모든 cron 실행은 작업 기록을 생성합니다.
|
||||
- **Heartbeat**는 30분마다 한 번의 일괄 턴으로 일상적인 모니터링(받은편지함, 캘린더, 알림)을 처리합니다.
|
||||
- **Hooks**는 특정 이벤트(도구 호출, 세션 재설정, 압축)에 맞춰 사용자 지정 스크립트로 반응합니다.
|
||||
- **상시 지시**는 에이전트에 지속적인 컨텍스트와 권한 경계를 제공합니다.
|
||||
- **Task Flow**는 개별 작업 위에서 여러 단계의 흐름을 조정합니다.
|
||||
- **작업**은 모든 분리된 작업을 자동으로 추적하므로 이를 검사하고 감사할 수 있습니다.
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [예약 작업](/automation/cron-jobs) — 정확한 예약과 일회성 알림
|
||||
- [백그라운드 작업](/automation/tasks) — 모든 분리된 작업을 위한 작업 원장
|
||||
- [Task Flow](/automation/taskflow) — 내구성 있는 다단계 흐름 오케스트레이션
|
||||
- [Hooks](/automation/hooks) — 이벤트 기반 수명 주기 스크립트
|
||||
- [Standing Orders](/automation/standing-orders) — 지속적인 에이전트 지침
|
||||
- [Heartbeat](/gateway/heartbeat) — 주기적인 메인 세션 턴
|
||||
- [구성 참조](/gateway/configuration-reference) — 모든 구성 키
|
||||
15
docs/ko/automation/poll.md
Normal file
15
docs/ko/automation/poll.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
summary: /tools/message로 리디렉션
|
||||
title: 투표
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:33:55Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 8d69432ad8ba5fd80b59f8df779a1105ce0a2ff767d7dd5dc9d8e3ac1cb1ff1f
|
||||
source_path: automation/poll.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 투표
|
||||
|
||||
이 페이지는 [Message tool](/cli/message)(으)로 이동했습니다. 투표 문서는 [Message tool](/cli/message)를 참조하세요.
|
||||
261
docs/ko/automation/standing-orders.md
Normal file
261
docs/ko/automation/standing-orders.md
Normal file
@ -0,0 +1,261 @@
|
||||
---
|
||||
read_when:
|
||||
- 작업별 프롬프트 없이 실행되는 자율 에이전트 워크플로를 설정할 때
|
||||
- 에이전트가 독립적으로 수행할 수 있는 작업과 사람의 승인이 필요한 작업을 정의할 때
|
||||
- 명확한 경계와 에스컬레이션 규칙을 갖춘 다중 프로그램 에이전트를 구조화할 때
|
||||
summary: 자율 에이전트 프로그램을 위한 상시 운영 권한 정의
|
||||
title: 상시 지시
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:23Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 81347d7a51a6ce20e6493277afee92073770f69a91a2e6b3bf87b99bb586d038
|
||||
source_path: automation/standing-orders.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 상시 지시
|
||||
|
||||
상시 지시는 에이전트에 정의된 프로그램에 대한 **영구적인 운영 권한**을 부여합니다. 매번 개별 작업 지시를 내리는 대신, 명확한 범위, 트리거, 에스컬레이션 규칙을 갖춘 프로그램을 정의하면 에이전트는 그 경계 내에서 자율적으로 실행합니다.
|
||||
|
||||
이는 매주 금요일마다 비서에게 "주간 보고서를 보내"라고 말하는 것과 상시 권한을 부여하는 것의 차이입니다. 예: "주간 보고서는 네 책임이다. 매주 금요일에 작성해서 보내고, 이상해 보이는 점이 있을 때만 에스컬레이션해."
|
||||
|
||||
## 왜 상시 지시가 필요한가요?
|
||||
|
||||
**상시 지시가 없을 때:**
|
||||
|
||||
- 모든 작업마다 에이전트에 프롬프트를 제공해야 합니다
|
||||
- 에이전트는 요청 사이에 유휴 상태로 머뭅니다
|
||||
- 반복 작업이 잊히거나 지연됩니다
|
||||
- 사용자가 병목 지점이 됩니다
|
||||
|
||||
**상시 지시가 있을 때:**
|
||||
|
||||
- 에이전트가 정의된 경계 내에서 자율적으로 실행합니다
|
||||
- 반복 작업이 프롬프트 없이도 일정에 따라 수행됩니다
|
||||
- 예외와 승인에만 사용자가 개입하면 됩니다
|
||||
- 에이전트가 유휴 시간을 생산적으로 활용합니다
|
||||
|
||||
## 작동 방식
|
||||
|
||||
상시 지시는 [에이전트 워크스페이스](/concepts/agent-workspace) 파일에 정의됩니다. 권장되는 방식은 이를 `AGENTS.md`에 직접 포함하는 것입니다(`AGENTS.md`는 모든 세션에 자동 주입됨). 이렇게 하면 에이전트가 항상 이를 컨텍스트로 갖게 됩니다. 더 큰 구성에서는 `standing-orders.md` 같은 전용 파일에 두고 `AGENTS.md`에서 참조할 수도 있습니다.
|
||||
|
||||
각 프로그램은 다음을 지정합니다.
|
||||
|
||||
1. **범위** — 에이전트가 수행하도록 승인된 작업
|
||||
2. **트리거** — 실행 시점(일정, 이벤트 또는 조건)
|
||||
3. **승인 게이트** — 작업 전에 사람의 승인이 필요한 항목
|
||||
4. **에스컬레이션 규칙** — 중단하고 도움을 요청해야 하는 시점
|
||||
|
||||
에이전트는 워크스페이스 부트스트랩 파일을 통해 매 세션마다 이러한 지침을 로드하며([Agent Workspace](/concepts/agent-workspace)에서 자동 주입 파일의 전체 목록 확인), 시간 기반 집행을 위해 [cron jobs](/automation/cron-jobs)와 결합해 이를 실행합니다.
|
||||
|
||||
<Tip>
|
||||
상시 지시는 `AGENTS.md`에 넣어 매 세션마다 로드되도록 보장하세요. 워크스페이스 부트스트랩은 `AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, `MEMORY.md`를 자동 주입하지만, 하위 디렉터리의 임의 파일은 자동 주입하지 않습니다.
|
||||
</Tip>
|
||||
|
||||
## 상시 지시의 구성 요소
|
||||
|
||||
```markdown
|
||||
## Program: Weekly Status Report
|
||||
|
||||
**Authority:** Compile data, generate report, deliver to stakeholders
|
||||
**Trigger:** Every Friday at 4 PM (enforced via cron job)
|
||||
**Approval gate:** None for standard reports. Flag anomalies for human review.
|
||||
**Escalation:** If data source is unavailable or metrics look unusual (>2σ from norm)
|
||||
|
||||
### Execution Steps
|
||||
|
||||
1. Pull metrics from configured sources
|
||||
2. Compare to prior week and targets
|
||||
3. Generate report in Reports/weekly/YYYY-MM-DD.md
|
||||
4. Deliver summary via configured channel
|
||||
5. Log completion to Agent/Logs/
|
||||
|
||||
### What NOT to Do
|
||||
|
||||
- Do not send reports to external parties
|
||||
- Do not modify source data
|
||||
- Do not skip delivery if metrics look bad — report accurately
|
||||
```
|
||||
|
||||
## 상시 지시 + Cron Jobs
|
||||
|
||||
상시 지시는 에이전트가 수행하도록 승인된 **무엇을** 정의합니다. [Cron jobs](/automation/cron-jobs)는 **언제** 수행할지를 정의합니다. 둘은 함께 작동합니다.
|
||||
|
||||
```
|
||||
Standing Order: "You own the daily inbox triage"
|
||||
↓
|
||||
Cron Job (8 AM daily): "Execute inbox triage per standing orders"
|
||||
↓
|
||||
Agent: Reads standing orders → executes steps → reports results
|
||||
```
|
||||
|
||||
cron job 프롬프트는 상시 지시를 중복해서 쓰기보다 이를 참조해야 합니다.
|
||||
|
||||
```bash
|
||||
openclaw cron add \
|
||||
--name daily-inbox-triage \
|
||||
--cron "0 8 * * 1-5" \
|
||||
--tz America/New_York \
|
||||
--timeout-seconds 300 \
|
||||
--announce \
|
||||
--channel bluebubbles \
|
||||
--to "+1XXXXXXXXXX" \
|
||||
--message "Execute daily inbox triage per standing orders. Check mail for new alerts. Parse, categorize, and persist each item. Report summary to owner. Escalate unknowns."
|
||||
```
|
||||
|
||||
## 예시
|
||||
|
||||
### 예시 1: 콘텐츠 및 소셜 미디어(주간 주기)
|
||||
|
||||
```markdown
|
||||
## Program: Content & Social Media
|
||||
|
||||
**Authority:** Draft content, schedule posts, compile engagement reports
|
||||
**Approval gate:** All posts require owner review for first 30 days, then standing approval
|
||||
**Trigger:** Weekly cycle (Monday review → mid-week drafts → Friday brief)
|
||||
|
||||
### Weekly Cycle
|
||||
|
||||
- **Monday:** Review platform metrics and audience engagement
|
||||
- **Tuesday–Thursday:** Draft social posts, create blog content
|
||||
- **Friday:** Compile weekly marketing brief → deliver to owner
|
||||
|
||||
### Content Rules
|
||||
|
||||
- Voice must match the brand (see SOUL.md or brand voice guide)
|
||||
- Never identify as AI in public-facing content
|
||||
- Include metrics when available
|
||||
- Focus on value to audience, not self-promotion
|
||||
```
|
||||
|
||||
### 예시 2: 재무 운영(이벤트 트리거)
|
||||
|
||||
```markdown
|
||||
## Program: Financial Processing
|
||||
|
||||
**Authority:** Process transaction data, generate reports, send summaries
|
||||
**Approval gate:** None for analysis. Recommendations require owner approval.
|
||||
**Trigger:** New data file detected OR scheduled monthly cycle
|
||||
|
||||
### When New Data Arrives
|
||||
|
||||
1. Detect new file in designated input directory
|
||||
2. Parse and categorize all transactions
|
||||
3. Compare against budget targets
|
||||
4. Flag: unusual items, threshold breaches, new recurring charges
|
||||
5. Generate report in designated output directory
|
||||
6. Deliver summary to owner via configured channel
|
||||
|
||||
### Escalation Rules
|
||||
|
||||
- Single item > $500: immediate alert
|
||||
- Category > budget by 20%: flag in report
|
||||
- Unrecognizable transaction: ask owner for categorization
|
||||
- Failed processing after 2 retries: report failure, do not guess
|
||||
```
|
||||
|
||||
### 예시 3: 모니터링 및 알림(연속)
|
||||
|
||||
```markdown
|
||||
## Program: System Monitoring
|
||||
|
||||
**Authority:** Check system health, restart services, send alerts
|
||||
**Approval gate:** Restart services automatically. Escalate if restart fails twice.
|
||||
**Trigger:** Every heartbeat cycle
|
||||
|
||||
### Checks
|
||||
|
||||
- Service health endpoints responding
|
||||
- Disk space above threshold
|
||||
- Pending tasks not stale (>24 hours)
|
||||
- Delivery channels operational
|
||||
|
||||
### Response Matrix
|
||||
|
||||
| Condition | Action | Escalate? |
|
||||
| ---------------- | ------------------------ | ------------------------ |
|
||||
| Service down | Restart automatically | Only if restart fails 2x |
|
||||
| Disk space < 10% | Alert owner | Yes |
|
||||
| Stale task > 24h | Remind owner | No |
|
||||
| Channel offline | Log and retry next cycle | If offline > 2 hours |
|
||||
```
|
||||
|
||||
## 실행-검증-보고 패턴
|
||||
|
||||
상시 지시는 엄격한 실행 규율과 결합될 때 가장 잘 작동합니다. 상시 지시의 모든 작업은 이 루프를 따라야 합니다.
|
||||
|
||||
1. **실행** — 실제 작업을 수행합니다(지시를 확인만 하지 마세요)
|
||||
2. **검증** — 결과가 올바른지 확인합니다(파일 존재, 메시지 전달, 데이터 파싱 등)
|
||||
3. **보고** — 무엇을 수행했고 무엇을 검증했는지 소유자에게 알립니다
|
||||
|
||||
```markdown
|
||||
### Execution Rules
|
||||
|
||||
- Every task follows Execute-Verify-Report. No exceptions.
|
||||
- "I'll do that" is not execution. Do it, then report.
|
||||
- "Done" without verification is not acceptable. Prove it.
|
||||
- If execution fails: retry once with adjusted approach.
|
||||
- If still fails: report failure with diagnosis. Never silently fail.
|
||||
- Never retry indefinitely — 3 attempts max, then escalate.
|
||||
```
|
||||
|
||||
이 패턴은 가장 흔한 에이전트 실패 모드, 즉 작업을 완료하지 않은 채 작업을 확인만 하는 문제를 방지합니다.
|
||||
|
||||
## 다중 프로그램 아키텍처
|
||||
|
||||
여러 관심사를 관리하는 에이전트의 경우, 명확한 경계를 가진 개별 프로그램으로 상시 지시를 구성하세요.
|
||||
|
||||
```markdown
|
||||
# Standing Orders
|
||||
|
||||
## Program 1: [Domain A] (Weekly)
|
||||
|
||||
...
|
||||
|
||||
## Program 2: [Domain B] (Monthly + On-Demand)
|
||||
|
||||
...
|
||||
|
||||
## Program 3: [Domain C] (As-Needed)
|
||||
|
||||
...
|
||||
|
||||
## Escalation Rules (All Programs)
|
||||
|
||||
- [Common escalation criteria]
|
||||
- [Approval gates that apply across programs]
|
||||
```
|
||||
|
||||
각 프로그램은 다음을 가져야 합니다.
|
||||
|
||||
- 고유한 **트리거 주기**(주간, 월간, 이벤트 기반, 연속)
|
||||
- 고유한 **승인 게이트**(일부 프로그램은 다른 프로그램보다 더 많은 감독이 필요함)
|
||||
- 명확한 **경계**(에이전트가 어디서 한 프로그램이 끝나고 다른 프로그램이 시작되는지 알아야 함)
|
||||
|
||||
## 모범 사례
|
||||
|
||||
### 권장 사항
|
||||
|
||||
- 좁은 권한으로 시작하고 신뢰가 쌓이면서 확장하세요
|
||||
- 위험도가 높은 작업에는 명시적인 승인 게이트를 정의하세요
|
||||
- "하지 말아야 할 일" 섹션을 포함하세요 — 경계는 권한만큼 중요합니다
|
||||
- 신뢰할 수 있는 시간 기반 실행을 위해 cron jobs와 결합하세요
|
||||
- 상시 지시가 잘 지켜지는지 확인하기 위해 매주 에이전트 로그를 검토하세요
|
||||
- 필요가 변화함에 따라 상시 지시를 업데이트하세요 — 이는 살아 있는 문서입니다
|
||||
|
||||
### 피해야 할 사항
|
||||
|
||||
- 첫날부터 광범위한 권한을 부여하지 마세요("최선이라고 생각하는 대로 뭐든 해")
|
||||
- 에스컬레이션 규칙을 생략하지 마세요 — 모든 프로그램에는 "멈추고 물어봐야 하는 시점" 조항이 필요합니다
|
||||
- 에이전트가 구두 지시를 기억할 것이라고 가정하지 마세요 — 모든 것을 파일에 적어 두세요
|
||||
- 하나의 프로그램에 여러 관심사를 섞지 마세요 — 별개의 도메인에는 별개의 프로그램을 사용하세요
|
||||
- cron jobs로 강제하는 것을 잊지 마세요 — 트리거 없는 상시 지시는 제안 사항에 불과합니다
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [Automation & Tasks](/automation) — 모든 자동화 메커니즘 한눈에 보기
|
||||
- [Cron Jobs](/automation/cron-jobs) — 상시 지시를 위한 일정 기반 집행
|
||||
- [Hooks](/automation/hooks) — 에이전트 수명 주기 이벤트를 위한 이벤트 기반 스크립트
|
||||
- [Webhooks](/automation/cron-jobs#webhooks) — 인바운드 HTTP 이벤트 트리거
|
||||
- [Agent Workspace](/concepts/agent-workspace) — 상시 지시가 위치하는 곳이며, 자동 주입되는 부트스트랩 파일 전체 목록(AGENTS.md, SOUL.md 등)을 포함합니다
|
||||
89
docs/ko/automation/taskflow.md
Normal file
89
docs/ko/automation/taskflow.md
Normal file
@ -0,0 +1,89 @@
|
||||
---
|
||||
read_when:
|
||||
- Task Flow가 백그라운드 작업과 어떤 관련이 있는지 이해하고 싶을 때
|
||||
- 릴리스 노트나 문서에서 Task Flow 또는 openclaw tasks flow를 보게 되었을 때
|
||||
- 내구성 있는 흐름 상태를 검사하거나 관리하고 싶을 때
|
||||
summary: 백그라운드 작업 위의 Task Flow 흐름 오케스트레이션 계층
|
||||
title: Task Flow
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:08Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 172871206b839845db807d9c627015890f7733b862e276853d5dbfbe29e03883
|
||||
source_path: automation/taskflow.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Task Flow
|
||||
|
||||
Task Flow는 [백그라운드 작업](/automation/tasks) 위에 위치하는 흐름 오케스트레이션 기반 계층입니다. 개별 작업은 분리된 작업의 단위로 유지되는 반면, 자체 상태, 리비전 추적, 동기화 의미 체계를 갖춘 내구성 있는 다단계 흐름을 관리합니다.
|
||||
|
||||
## Task Flow를 사용해야 하는 경우
|
||||
|
||||
작업이 여러 순차적 단계 또는 분기 단계에 걸쳐 있고 게이트웨이 재시작 전반에 걸쳐 내구성 있는 진행 상황 추적이 필요하다면 Task Flow를 사용하세요. 단일 백그라운드 작업의 경우 일반 [작업](/automation/tasks)이면 충분합니다.
|
||||
|
||||
| 시나리오 | 사용 방식 |
|
||||
| ------------------------------------- | -------------------- |
|
||||
| 단일 백그라운드 작업 | 일반 작업 |
|
||||
| 다단계 파이프라인 (A 다음 B 다음 C) | Task Flow (관리형) |
|
||||
| 외부에서 생성된 작업 관찰 | Task Flow (미러링) |
|
||||
| 일회성 리마인더 | cron 작업 |
|
||||
|
||||
## 동기화 모드
|
||||
|
||||
### 관리형 모드
|
||||
|
||||
Task Flow는 수명 주기를 처음부터 끝까지 소유합니다. 흐름 단계로 작업을 생성하고, 완료될 때까지 구동하며, 흐름 상태를 자동으로 진행시킵니다.
|
||||
|
||||
예: 주간 보고서 흐름이 (1) 데이터를 수집하고, (2) 보고서를 생성하고, (3) 전달합니다. Task Flow는 각 단계를 백그라운드 작업으로 생성하고, 완료를 기다린 다음, 다음 단계로 이동합니다.
|
||||
|
||||
```
|
||||
Flow: weekly-report
|
||||
Step 1: gather-data → task created → succeeded
|
||||
Step 2: generate-report → task created → succeeded
|
||||
Step 3: deliver → task created → running
|
||||
```
|
||||
|
||||
### 미러링 모드
|
||||
|
||||
Task Flow는 외부에서 생성된 작업을 관찰하고 작업 생성에 대한 소유권을 갖지 않으면서 흐름 상태를 동기화된 상태로 유지합니다. 이는 작업이 cron 작업, CLI 명령 또는 기타 소스에서 시작되고, 이를 흐름으로서 진행 상황을 통합된 보기로 확인하고 싶을 때 유용합니다.
|
||||
|
||||
예: 함께 "아침 운영" 루틴을 구성하는 세 개의 독립적인 cron 작업. 미러링된 흐름은 작업의 실행 시점이나 실행 방식을 제어하지 않고도 이들의 전체 진행 상황을 추적합니다.
|
||||
|
||||
## 내구성 있는 상태 및 리비전 추적
|
||||
|
||||
각 흐름은 자체 상태를 유지하고 리비전을 추적하므로 게이트웨이가 재시작되어도 진행 상황이 유지됩니다. 리비전 추적은 여러 소스가 동시에 동일한 흐름을 진행시키려 할 때 충돌 감지를 가능하게 합니다.
|
||||
|
||||
## 취소 동작
|
||||
|
||||
`openclaw tasks flow cancel`은 흐름에 고정 취소 의도를 설정합니다. 흐름 내의 활성 작업은 취소되며 새 단계는 시작되지 않습니다. 취소 의도는 재시작 후에도 유지되므로, 모든 하위 작업이 종료되기 전에 게이트웨이가 재시작되더라도 취소된 흐름은 계속 취소된 상태로 유지됩니다.
|
||||
|
||||
## CLI 명령
|
||||
|
||||
```bash
|
||||
# 활성 및 최근 흐름 나열
|
||||
openclaw tasks flow list
|
||||
|
||||
# 특정 흐름의 세부 정보 표시
|
||||
openclaw tasks flow show <lookup>
|
||||
|
||||
# 실행 중인 흐름과 그 활성 작업 취소
|
||||
openclaw tasks flow cancel <lookup>
|
||||
```
|
||||
|
||||
| 명령 | 설명 |
|
||||
| --------------------------------- | --------------------------------------------- |
|
||||
| `openclaw tasks flow list` | 상태 및 동기화 모드와 함께 추적된 흐름 표시 |
|
||||
| `openclaw tasks flow show <id>` | 흐름 id 또는 조회 키로 하나의 흐름 검사 |
|
||||
| `openclaw tasks flow cancel <id>` | 실행 중인 흐름과 그 활성 작업 취소 |
|
||||
|
||||
## 흐름과 작업의 관계
|
||||
|
||||
흐름은 작업을 조정하는 것이지, 작업을 대체하는 것이 아닙니다. 하나의 흐름은 수명 주기 동안 여러 백그라운드 작업을 구동할 수 있습니다. 개별 작업 레코드를 검사하려면 `openclaw tasks`를 사용하고, 오케스트레이션하는 흐름을 검사하려면 `openclaw tasks flow`를 사용하세요.
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [백그라운드 작업](/automation/tasks) — 흐름이 조정하는 분리된 작업 원장
|
||||
- [CLI: tasks](/cli/index#tasks) — `openclaw tasks flow`용 CLI 명령 참조
|
||||
- [자동화 개요](/automation) — 모든 자동화 메커니즘 한눈에 보기
|
||||
- [Cron Jobs](/automation/cron-jobs) — 흐름으로 유입될 수 있는 예약된 작업
|
||||
317
docs/ko/automation/tasks.md
Normal file
317
docs/ko/automation/tasks.md
Normal file
@ -0,0 +1,317 @@
|
||||
---
|
||||
read_when:
|
||||
- 진행 중이거나 최근 완료된 백그라운드 작업을 검사할 때
|
||||
- 분리된 에이전트 실행의 전달 실패를 디버깅할 때
|
||||
- 백그라운드 실행이 세션, cron, heartbeat와 어떤 관련이 있는지 이해할 때
|
||||
summary: ACP 실행, 하위 에이전트, 격리된 cron 작업, 그리고 CLI 작업에 대한 백그라운드 작업 추적
|
||||
title: 배경 작업
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:39Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6c95ccf4388d07e60a7bb68746b161793f4bb5ff2ba3d5ce9e51f2225dab2c4d
|
||||
source_path: automation/tasks.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 배경 작업
|
||||
|
||||
> **스케줄링을 찾고 계신가요?** 적절한 메커니즘을 선택하려면 [Automation & Tasks](/automation)를 참조하세요. 이 페이지는 백그라운드 작업의 **추적**을 다루며, 스케줄링은 다루지 않습니다.
|
||||
|
||||
배경 작업은 **기본 대화 세션 외부**에서 실행되는 작업을 추적합니다:
|
||||
ACP 실행, 하위 에이전트 생성, 격리된 cron 작업 실행, 그리고 CLI로 시작된 작업입니다.
|
||||
|
||||
작업은 세션, cron 작업, heartbeat를 대체하지 않습니다 — 이것은 분리된 작업에서 무엇이 일어났는지, 언제 일어났는지, 그리고 성공했는지를 기록하는 **활동 원장**입니다.
|
||||
|
||||
<Note>
|
||||
모든 에이전트 실행이 작업을 생성하는 것은 아닙니다. Heartbeat 턴과 일반 대화형 채팅은 생성하지 않습니다. 모든 cron 실행, ACP 생성, 하위 에이전트 생성, 그리고 CLI 에이전트 명령은 생성합니다.
|
||||
</Note>
|
||||
|
||||
## 요약
|
||||
|
||||
- 작업은 스케줄러가 아니라 **기록**입니다 — cron과 heartbeat가 작업 실행 _시점_ 을 결정하고, 작업은 _무슨 일이 있었는지_ 를 추적합니다.
|
||||
- ACP, 하위 에이전트, 모든 cron 작업, 그리고 CLI 작업은 작업을 생성합니다. Heartbeat 턴은 생성하지 않습니다.
|
||||
- 각 작업은 `queued → running → terminal`(succeeded, failed, timed_out, cancelled, 또는 lost) 단계를 거칩니다.
|
||||
- Cron 작업은 cron 런타임이 여전히 해당 작업을 소유하는 동안 활성 상태를 유지합니다. 채팅 기반 CLI 작업은 소유 실행 컨텍스트가 아직 활성일 때만 활성 상태를 유지합니다.
|
||||
- 완료는 푸시 방식으로 처리됩니다. 분리된 작업은 완료 시 직접 알리거나 요청자 세션/heartbeat를 깨울 수 있으므로, 상태를 폴링하는 루프는 대개 적절한 방식이 아닙니다.
|
||||
- 격리된 cron 실행과 하위 에이전트 완료는 최종 정리 bookkeeping 전에 해당 하위 세션의 추적된 브라우저 탭/프로세스를 best-effort로 정리합니다.
|
||||
- 격리된 cron 전달은 하위 하위 에이전트 작업이 아직 비워지는 동안 오래된 중간 부모 응답을 억제하고, 전달 전에 최종 하위 출력이 도착하면 그것을 우선합니다.
|
||||
- 완료 알림은 채널로 직접 전달되거나 다음 heartbeat를 위해 대기열에 들어갑니다.
|
||||
- `openclaw tasks list`는 모든 작업을 표시하고, `openclaw tasks audit`는 문제를 표시합니다.
|
||||
- 종료된 기록은 7일 동안 유지된 후 자동으로 정리됩니다.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
```bash
|
||||
# 모든 작업 나열(최신순)
|
||||
openclaw tasks list
|
||||
|
||||
# 런타임 또는 상태별로 필터링
|
||||
openclaw tasks list --runtime acp
|
||||
openclaw tasks list --status running
|
||||
|
||||
# 특정 작업의 세부 정보 표시(ID, run ID 또는 session key로 조회)
|
||||
openclaw tasks show <lookup>
|
||||
|
||||
# 실행 중인 작업 취소(하위 세션 종료)
|
||||
openclaw tasks cancel <lookup>
|
||||
|
||||
# 작업의 알림 정책 변경
|
||||
openclaw tasks notify <lookup> state_changes
|
||||
|
||||
# 상태 감사 실행
|
||||
openclaw tasks audit
|
||||
|
||||
# 유지 관리 미리보기 또는 적용
|
||||
openclaw tasks maintenance
|
||||
openclaw tasks maintenance --apply
|
||||
|
||||
# TaskFlow 상태 검사
|
||||
openclaw tasks flow list
|
||||
openclaw tasks flow show <lookup>
|
||||
openclaw tasks flow cancel <lookup>
|
||||
```
|
||||
|
||||
## 작업을 생성하는 항목
|
||||
|
||||
| 소스 | 런타임 유형 | 작업 기록이 생성되는 시점 | 기본 알림 정책 |
|
||||
| ---------------------- | ------------ | ------------------------------------------------------ | --------------------- |
|
||||
| ACP 백그라운드 실행 | `acp` | 하위 ACP 세션 생성 | `done_only` |
|
||||
| 하위 에이전트 오케스트레이션 | `subagent` | `sessions_spawn`을 통해 하위 에이전트를 생성할 때 | `done_only` |
|
||||
| Cron 작업(모든 유형) | `cron` | 모든 cron 실행(메인 세션 및 격리형) | `silent` |
|
||||
| CLI 작업 | `cli` | 게이트웨이를 통해 실행되는 `openclaw agent` 명령 | `silent` |
|
||||
|
||||
메인 세션 cron 작업은 기본적으로 `silent` 알림 정책을 사용합니다 — 추적용 기록은 생성하지만 알림은 생성하지 않습니다. 격리된 cron 작업도 기본적으로 `silent`이지만 자체 세션에서 실행되므로 더 눈에 띕니다.
|
||||
|
||||
**작업을 생성하지 않는 항목:**
|
||||
|
||||
- Heartbeat 턴 — 메인 세션, [Heartbeat](/gateway/heartbeat) 참조
|
||||
- 일반 대화형 채팅 턴
|
||||
- 직접 `/command` 응답
|
||||
|
||||
## 작업 수명 주기
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> queued
|
||||
queued --> running : agent starts
|
||||
running --> succeeded : completes ok
|
||||
running --> failed : error
|
||||
running --> timed_out : timeout exceeded
|
||||
running --> cancelled : operator cancels
|
||||
queued --> lost : session gone > 5 min
|
||||
running --> lost : session gone > 5 min
|
||||
```
|
||||
|
||||
| 상태 | 의미 |
|
||||
| ----------- | -------------------------------------------------------------------------- |
|
||||
| `queued` | 생성되었고, 에이전트 시작을 기다리는 중 |
|
||||
| `running` | 에이전트 턴이 현재 실행 중 |
|
||||
| `succeeded` | 성공적으로 완료됨 |
|
||||
| `failed` | 오류와 함께 완료됨 |
|
||||
| `timed_out` | 구성된 제한 시간을 초과함 |
|
||||
| `cancelled` | 운영자가 `openclaw tasks cancel`로 중지함 |
|
||||
| `lost` | 5분 유예 기간 후 런타임이 권한 있는 백킹 상태를 잃음 |
|
||||
|
||||
전이는 자동으로 발생합니다 — 연결된 에이전트 실행이 끝나면 작업 상태가 이에 맞춰 업데이트됩니다.
|
||||
|
||||
`lost`는 런타임 인식 방식으로 처리됩니다:
|
||||
|
||||
- ACP 작업: 백킹 ACP 하위 세션 메타데이터가 사라졌습니다.
|
||||
- 하위 에이전트 작업: 대상 에이전트 저장소에서 백킹 하위 세션이 사라졌습니다.
|
||||
- Cron 작업: cron 런타임이 더 이상 해당 작업을 활성 상태로 추적하지 않습니다.
|
||||
- CLI 작업: 격리된 하위 세션 작업은 하위 세션을 사용하고, 채팅 기반 CLI 작업은 대신 활성 실행 컨텍스트를 사용하므로 남아 있는 채널/그룹/직접 세션 행만으로는 활성 상태가 유지되지 않습니다.
|
||||
|
||||
## 전달 및 알림
|
||||
|
||||
작업이 종료 상태에 도달하면 OpenClaw가 알립니다. 전달 경로는 두 가지입니다.
|
||||
|
||||
**직접 전달** — 작업에 채널 대상(`requesterOrigin`)이 있으면 완료 메시지가 해당 채널(Telegram, Discord, Slack 등)로 바로 전송됩니다. 하위 에이전트 완료의 경우 OpenClaw는 가능하면 바인딩된 스레드/토픽 라우팅도 보존하며, 직접 전달을 포기하기 전에 요청자 세션의 저장된 경로(`lastChannel` / `lastTo` / `lastAccountId`)에서 누락된 `to` / 계정을 채울 수 있습니다.
|
||||
|
||||
**세션 대기열 전달** — 직접 전달에 실패했거나 origin이 설정되지 않은 경우, 업데이트는 요청자 세션의 시스템 이벤트로 대기열에 들어가며 다음 heartbeat에서 표시됩니다.
|
||||
|
||||
<Tip>
|
||||
작업 완료는 즉시 heartbeat 깨우기를 트리거하므로 결과를 빠르게 확인할 수 있습니다 — 다음 예약된 heartbeat 틱까지 기다릴 필요가 없습니다.
|
||||
</Tip>
|
||||
|
||||
즉, 일반적인 워크플로는 푸시 기반입니다. 분리된 작업을 한 번 시작한 뒤, 완료 시 런타임이 깨우거나 알리도록 두세요. 디버깅, 개입, 또는 명시적인 감사가 필요할 때만 작업 상태를 폴링하세요.
|
||||
|
||||
### 알림 정책
|
||||
|
||||
각 작업에 대해 얼마나 많은 알림을 받을지 제어합니다.
|
||||
|
||||
| 정책 | 전달되는 내용 |
|
||||
| --------------------- | ----------------------------------------------------------------------- |
|
||||
| `done_only` (기본값) | 종료 상태(succeeded, failed 등)만 전달 — **이 값이 기본값입니다** |
|
||||
| `state_changes` | 모든 상태 전이와 진행 상황 업데이트 |
|
||||
| `silent` | 아무것도 전달하지 않음 |
|
||||
|
||||
작업이 실행 중일 때 정책을 변경할 수 있습니다.
|
||||
|
||||
```bash
|
||||
openclaw tasks notify <lookup> state_changes
|
||||
```
|
||||
|
||||
## CLI 참조
|
||||
|
||||
### `tasks list`
|
||||
|
||||
```bash
|
||||
openclaw tasks list [--runtime <acp|subagent|cron|cli>] [--status <status>] [--json]
|
||||
```
|
||||
|
||||
출력 열: 작업 ID, 종류, 상태, 전달, Run ID, 하위 세션, 요약.
|
||||
|
||||
### `tasks show`
|
||||
|
||||
```bash
|
||||
openclaw tasks show <lookup>
|
||||
```
|
||||
|
||||
조회 토큰은 작업 ID, run ID, 또는 session key를 받을 수 있습니다. 타이밍, 전달 상태, 오류, 종료 요약을 포함한 전체 기록을 표시합니다.
|
||||
|
||||
### `tasks cancel`
|
||||
|
||||
```bash
|
||||
openclaw tasks cancel <lookup>
|
||||
```
|
||||
|
||||
ACP 및 하위 에이전트 작업의 경우 하위 세션을 종료합니다. 상태는 `cancelled`로 전이되며 전달 알림이 전송됩니다.
|
||||
|
||||
### `tasks notify`
|
||||
|
||||
```bash
|
||||
openclaw tasks notify <lookup> <done_only|state_changes|silent>
|
||||
```
|
||||
|
||||
### `tasks audit`
|
||||
|
||||
```bash
|
||||
openclaw tasks audit [--json]
|
||||
```
|
||||
|
||||
운영상 문제를 표시합니다. 문제가 감지되면 결과는 `openclaw status`에도 나타납니다.
|
||||
|
||||
| 항목 | 심각도 | 트리거 |
|
||||
| ------------------------- | -------- | ----------------------------------------------------- |
|
||||
| `stale_queued` | warn | 10분 이상 queued 상태 |
|
||||
| `stale_running` | error | 30분 이상 running 상태 |
|
||||
| `lost` | error | 런타임 기반 작업 소유권이 사라짐 |
|
||||
| `delivery_failed` | warn | 전달이 실패했고 알림 정책이 `silent`가 아님 |
|
||||
| `missing_cleanup` | warn | cleanup 타임스탬프가 없는 종료 작업 |
|
||||
| `inconsistent_timestamps` | warn | 타임라인 위반(예: 시작 전에 종료됨) |
|
||||
|
||||
### `tasks maintenance`
|
||||
|
||||
```bash
|
||||
openclaw tasks maintenance [--json]
|
||||
openclaw tasks maintenance --apply [--json]
|
||||
```
|
||||
|
||||
이를 사용해 작업 및 Task Flow 상태의 조정, cleanup 스탬프 처리, 그리고 정리를 미리 보거나 적용할 수 있습니다.
|
||||
|
||||
조정은 런타임 인식 방식으로 처리됩니다.
|
||||
|
||||
- ACP/하위 에이전트 작업은 백킹 하위 세션을 확인합니다.
|
||||
- Cron 작업은 cron 런타임이 여전히 해당 작업을 소유하는지 확인합니다.
|
||||
- 채팅 기반 CLI 작업은 채팅 세션 행만이 아니라 소유하는 활성 실행 컨텍스트를 확인합니다.
|
||||
|
||||
완료 cleanup도 런타임 인식 방식으로 처리됩니다.
|
||||
|
||||
- 하위 에이전트 완료는 알림 cleanup이 계속되기 전에 하위 세션의 추적된 브라우저 탭/프로세스를 best-effort로 닫습니다.
|
||||
- 격리된 cron 완료는 실행이 완전히 종료되기 전에 cron 세션의 추적된 브라우저 탭/프로세스를 best-effort로 닫습니다.
|
||||
- 격리된 cron 전달은 필요할 때 하위 하위 에이전트 후속 작업이 끝날 때까지 기다리고, 이를 알리는 대신 오래된 부모 확인 텍스트를 억제합니다.
|
||||
- 하위 에이전트 완료 전달은 가장 최신의 표시 가능한 assistant 텍스트를 우선하며, 이것이 비어 있으면 정리된 최신 tool/toolResult 텍스트로 대체하고, 타임아웃만 발생한 tool-call 실행은 짧은 부분 진행 요약으로 축약될 수 있습니다.
|
||||
- Cleanup 실패가 실제 작업 결과를 가리지는 않습니다.
|
||||
|
||||
### `tasks flow list|show|cancel`
|
||||
|
||||
```bash
|
||||
openclaw tasks flow list [--status <status>] [--json]
|
||||
openclaw tasks flow show <lookup> [--json]
|
||||
openclaw tasks flow cancel <lookup>
|
||||
```
|
||||
|
||||
개별 백그라운드 작업 기록 하나보다 이를 오케스트레이션하는 Task Flow 자체가 더 중요할 때 사용하세요.
|
||||
|
||||
## 채팅 작업 보드(`/tasks`)
|
||||
|
||||
어떤 채팅 세션에서든 `/tasks`를 사용해 그 세션에 연결된 백그라운드 작업을 볼 수 있습니다. 보드에는 활성 작업과 최근 완료된 작업이 런타임, 상태, 타이밍, 그리고 진행 상황 또는 오류 세부 정보와 함께 표시됩니다.
|
||||
|
||||
현재 세션에 표시 가능한 연결 작업이 없으면 `/tasks`는 에이전트 로컬 작업 수로 대체되어, 다른 세션 세부 정보를 노출하지 않고도 개요를 제공합니다.
|
||||
|
||||
전체 운영자 원장을 보려면 CLI를 사용하세요: `openclaw tasks list`.
|
||||
|
||||
## 상태 통합(작업 압력)
|
||||
|
||||
`openclaw status`에는 한눈에 보는 작업 요약이 포함됩니다.
|
||||
|
||||
```
|
||||
Tasks: 3 queued · 2 running · 1 issues
|
||||
```
|
||||
|
||||
요약은 다음을 보고합니다.
|
||||
|
||||
- **active** — `queued` + `running` 개수
|
||||
- **failures** — `failed` + `timed_out` + `lost` 개수
|
||||
- **byRuntime** — `acp`, `subagent`, `cron`, `cli`별 분류
|
||||
|
||||
`/status`와 `session_status` 도구는 모두 cleanup 인식 작업 스냅샷을 사용합니다. 활성 작업이 우선되고, 오래된 완료 행은 숨겨지며, 최근 실패는 활성 작업이 남아 있지 않을 때만 표시됩니다. 이렇게 하면 상태 카드가 지금 중요한 내용에 집중됩니다.
|
||||
|
||||
## 저장소 및 유지 관리
|
||||
|
||||
### 작업이 저장되는 위치
|
||||
|
||||
작업 기록은 다음 SQLite 위치에 유지됩니다.
|
||||
|
||||
```
|
||||
$OPENCLAW_STATE_DIR/tasks/runs.sqlite
|
||||
```
|
||||
|
||||
레지스트리는 게이트웨이 시작 시 메모리에 로드되며, 재시작 간 내구성을 위해 쓰기 내용을 SQLite에 동기화합니다.
|
||||
|
||||
### 자동 유지 관리
|
||||
|
||||
스위퍼는 **60초**마다 실행되며 세 가지를 처리합니다.
|
||||
|
||||
1. **조정** — 활성 작업이 여전히 권한 있는 런타임 백킹을 가지고 있는지 확인합니다. ACP/하위 에이전트 작업은 하위 세션 상태를 사용하고, cron 작업은 활성 작업 소유권을 사용하며, 채팅 기반 CLI 작업은 소유하는 실행 컨텍스트를 사용합니다. 이 백킹 상태가 5분 이상 사라져 있으면 작업은 `lost`로 표시됩니다.
|
||||
2. **Cleanup 스탬프 처리** — 종료 작업에 `cleanupAfter` 타임스탬프를 설정합니다(`endedAt + 7 days`).
|
||||
3. **정리** — `cleanupAfter` 날짜가 지난 기록을 삭제합니다.
|
||||
|
||||
**보존 기간**: 종료된 작업 기록은 **7일** 동안 유지된 후 자동으로 정리됩니다. 별도의 구성은 필요하지 않습니다.
|
||||
|
||||
## 작업이 다른 시스템과 어떤 관련이 있는가
|
||||
|
||||
### 작업과 Task Flow
|
||||
|
||||
[Task Flow](/automation/taskflow)는 백그라운드 작업 위에 있는 플로우 오케스트레이션 계층입니다. 단일 플로우는 관리형 또는 미러링된 동기화 모드를 사용해 수명 주기 동안 여러 작업을 조정할 수 있습니다. 개별 작업 기록을 검사하려면 `openclaw tasks`를, 오케스트레이션 플로우를 검사하려면 `openclaw tasks flow`를 사용하세요.
|
||||
|
||||
자세한 내용은 [Task Flow](/automation/taskflow)를 참조하세요.
|
||||
|
||||
### 작업과 cron
|
||||
|
||||
Cron 작업 **정의**는 `~/.openclaw/cron/jobs.json`에 있습니다. **모든** cron 실행은 작업 기록을 생성합니다 — 메인 세션과 격리형 모두 포함됩니다. 메인 세션 cron 작업은 기본적으로 `silent` 알림 정책을 사용하므로 알림을 생성하지 않고 추적만 합니다.
|
||||
|
||||
[Scheduled Tasks](/automation/cron-jobs)를 참조하세요.
|
||||
|
||||
### 작업과 heartbeat
|
||||
|
||||
Heartbeat 실행은 메인 세션 턴입니다 — 작업 기록을 생성하지 않습니다. 작업이 완료되면 heartbeat 깨우기를 트리거해 결과를 빠르게 확인할 수 있습니다.
|
||||
|
||||
[Heartbeat](/gateway/heartbeat)를 참조하세요.
|
||||
|
||||
### 작업과 세션
|
||||
|
||||
작업은 `childSessionKey`(작업이 실행되는 곳)와 `requesterSessionKey`(누가 시작했는지)를 참조할 수 있습니다. 세션은 대화 컨텍스트이고, 작업은 그 위에서 활동을 추적합니다.
|
||||
|
||||
### 작업과 에이전트 실행
|
||||
|
||||
작업의 `runId`는 작업을 수행하는 에이전트 실행과 연결됩니다. 에이전트 수명 주기 이벤트(시작, 종료, 오류)는 작업 상태를 자동으로 업데이트합니다 — 수명 주기를 수동으로 관리할 필요가 없습니다.
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [Automation & Tasks](/automation) — 모든 자동화 메커니즘 한눈에 보기
|
||||
- [Task Flow](/automation/taskflow) — 작업 상위의 플로우 오케스트레이션
|
||||
- [Scheduled Tasks](/automation/cron-jobs) — 백그라운드 작업 스케줄링
|
||||
- [Heartbeat](/gateway/heartbeat) — 주기적인 메인 세션 턴
|
||||
- [CLI: Tasks](/cli/index#tasks) — CLI 명령 참조
|
||||
15
docs/ko/automation/troubleshooting.md
Normal file
15
docs/ko/automation/troubleshooting.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
summary: /automation/cron-jobs로 리디렉션
|
||||
title: 자동화 문제 해결
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:06Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6621342754fb56234b89e71167f73bad6c070273ff0b8d12dbb20854e32e7980
|
||||
source_path: automation/troubleshooting.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 자동화 문제 해결
|
||||
|
||||
이 페이지는 [예약된 작업](/automation/cron-jobs#troubleshooting)(으)로 이동되었습니다. 문제 해결 문서는 [예약된 작업](/automation/cron-jobs#troubleshooting)을(를) 참조하세요.
|
||||
15
docs/ko/automation/webhook.md
Normal file
15
docs/ko/automation/webhook.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
summary: /automation/cron-jobs로 리디렉션
|
||||
title: 웹훅
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:07Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 7511f6bc28e7f13ee1d9313bb5551825afb5706019068079603a44668c4dda34
|
||||
source_path: automation/webhook.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 웹훅
|
||||
|
||||
이 페이지는 [예약된 작업](/automation/cron-jobs#webhooks)으로 이동했습니다. 웹훅 문서는 [예약된 작업](/automation/cron-jobs#webhooks)을 참조하세요.
|
||||
110
docs/ko/brave-search.md
Normal file
110
docs/ko/brave-search.md
Normal file
@ -0,0 +1,110 @@
|
||||
---
|
||||
read_when:
|
||||
- web_search에 Brave Search를 사용하려는 경우
|
||||
- BRAVE_API_KEY 또는 요금제 세부 정보가 필요한 경우
|
||||
summary: web_search용 Brave Search API 설정
|
||||
title: Brave Search (레거시 경로)
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:22Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 7788e4cee7dc460819e55095c87df8cea29ba3a8bd3cef4c0e98ac601b45b651
|
||||
source_path: brave-search.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Brave Search API
|
||||
|
||||
OpenClaw는 Brave Search API를 `web_search` 공급자로 지원합니다.
|
||||
|
||||
## API 키 받기
|
||||
|
||||
1. [https://brave.com/search/api/](https://brave.com/search/api/)에서 Brave Search API 계정을 생성합니다.
|
||||
2. 대시보드에서 **Search** 요금제를 선택하고 API 키를 생성합니다.
|
||||
3. 키를 config에 저장하거나 Gateway 환경에서 `BRAVE_API_KEY`를 설정합니다.
|
||||
|
||||
## config 예시
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
brave: {
|
||||
config: {
|
||||
webSearch: {
|
||||
apiKey: "BRAVE_API_KEY_HERE",
|
||||
mode: "web", // or "llm-context"
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
tools: {
|
||||
web: {
|
||||
search: {
|
||||
provider: "brave",
|
||||
maxResults: 5,
|
||||
timeoutSeconds: 30,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
공급자별 Brave 검색 설정은 이제 `plugins.entries.brave.config.webSearch.*` 아래에 있습니다.
|
||||
레거시 `tools.web.search.apiKey`도 호환성 shim을 통해 계속 로드되지만, 더 이상 정식 config 경로는 아닙니다.
|
||||
|
||||
`webSearch.mode`는 Brave 전송 방식을 제어합니다.
|
||||
|
||||
- `web`(기본값): 제목, URL, 스니펫이 포함된 일반 Brave 웹 검색
|
||||
- `llm-context`: 근거 제시를 위해 미리 추출된 텍스트 청크와 출처를 제공하는 Brave LLM Context API
|
||||
|
||||
## 도구 매개변수
|
||||
|
||||
| 매개변수 | 설명 |
|
||||
| ------------- | ------------------------------------------------------------------- |
|
||||
| `query` | 검색어(필수) |
|
||||
| `count` | 반환할 결과 수(1-10, 기본값: 5) |
|
||||
| `country` | 2자리 ISO 국가 코드(예: "US", "DE") |
|
||||
| `language` | 검색 결과용 ISO 639-1 언어 코드(예: "en", "de", "fr") |
|
||||
| `search_lang` | Brave 검색 언어 코드(예: `en`, `en-gb`, `zh-hans`) |
|
||||
| `ui_lang` | UI 요소용 ISO 언어 코드 |
|
||||
| `freshness` | 시간 필터: `day`(24시간), `week`, `month` 또는 `year` |
|
||||
| `date_after` | 이 날짜(YYYY-MM-DD) 이후에 게시된 결과만 |
|
||||
| `date_before` | 이 날짜(YYYY-MM-DD) 이전에 게시된 결과만 |
|
||||
|
||||
**예시:**
|
||||
|
||||
```javascript
|
||||
// Country and language-specific search
|
||||
await web_search({
|
||||
query: "renewable energy",
|
||||
country: "DE",
|
||||
language: "de",
|
||||
});
|
||||
|
||||
// Recent results (past week)
|
||||
await web_search({
|
||||
query: "AI news",
|
||||
freshness: "week",
|
||||
});
|
||||
|
||||
// Date range search
|
||||
await web_search({
|
||||
query: "AI developments",
|
||||
date_after: "2024-01-01",
|
||||
date_before: "2024-06-30",
|
||||
});
|
||||
```
|
||||
|
||||
## 참고
|
||||
|
||||
- OpenClaw는 Brave **Search** 요금제를 사용합니다. 레거시 구독(예: 월 2,000회 쿼리를 제공하던 기존 Free 요금제)이 있는 경우 계속 유효하지만, LLM Context나 더 높은 속도 제한 같은 최신 기능은 포함되지 않습니다.
|
||||
- 각 Brave 요금제에는 매월 갱신되는 **월 \$5의 무료 크레딧**이 포함됩니다. Search 요금제 비용은 요청 1,000건당 \$5이므로, 이 크레딧으로 월 1,000회 쿼리를 사용할 수 있습니다. 예상치 못한 요금을 방지하려면 Brave 대시보드에서 사용량 한도를 설정하세요. 현재 요금제는 [Brave API 포털](https://brave.com/search/api/)을 참조하세요.
|
||||
- Search 요금제에는 LLM Context 엔드포인트와 AI 추론 권한이 포함됩니다. 모델을 학습하거나 튜닝하기 위해 결과를 저장하려면 명시적인 저장 권한이 포함된 요금제가 필요합니다. Brave [서비스 약관](https://api-dashboard.search.brave.com/terms-of-service)을 참조하세요.
|
||||
- `llm-context` 모드는 일반 웹 검색 스니펫 형태 대신 근거가 있는 출처 항목을 반환합니다.
|
||||
- `llm-context` 모드는 `ui_lang`, `freshness`, `date_after`, `date_before`를 지원하지 않습니다.
|
||||
- `ui_lang`에는 `en-US`와 같은 지역 하위 태그가 포함되어야 합니다.
|
||||
- 결과는 기본적으로 15분 동안 캐시됩니다(`cacheTtlMinutes`로 구성 가능).
|
||||
|
||||
전체 web_search config는 [웹 도구](/tools/web)를 참조하세요.
|
||||
441
docs/ko/channels/bluebubbles.md
Normal file
441
docs/ko/channels/bluebubbles.md
Normal file
@ -0,0 +1,441 @@
|
||||
---
|
||||
read_when:
|
||||
- BlueBubbles 채널 설정 시
|
||||
- 웹훅 페어링 문제 해결 시
|
||||
- macOS에서 iMessage 구성 시
|
||||
summary: BlueBubbles macOS 서버를 통한 iMessage(REST 송수신, 타이핑, 반응, 페어링, 고급 작업).
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:03Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ed8e59a165bdfb8fd794ee2ad6e4dacd44aa02d512312c5f2fd7d15f863380bb
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# BlueBubbles (macOS REST)
|
||||
|
||||
상태: HTTP를 통해 BlueBubbles macOS 서버와 통신하는 번들 plugin입니다. 기존 imsg 채널보다 API가 더 풍부하고 설정이 더 쉬우므로 **iMessage 통합에 권장됩니다**.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
현재 OpenClaw 릴리스에는 BlueBubbles가 번들로 포함되어 있으므로, 일반적인 패키지 빌드에서는 별도의 `openclaw plugins install` 단계가 필요하지 않습니다.
|
||||
|
||||
## 개요
|
||||
|
||||
- BlueBubbles helper 앱([bluebubbles.app](https://bluebubbles.app))을 통해 macOS에서 실행됩니다.
|
||||
- 권장/테스트 환경: macOS Sequoia (15). macOS Tahoe (26)에서도 작동하지만, 현재 Tahoe에서는 편집 기능이 깨져 있으며 그룹 아이콘 업데이트는 성공으로 표시되더라도 동기화되지 않을 수 있습니다.
|
||||
- OpenClaw는 REST API(`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`)를 통해 통신합니다.
|
||||
- 수신 메시지는 웹훅으로 도착하며, 발신 답장, 타이핑 표시기, 읽음 확인, 탭백은 REST 호출로 처리됩니다.
|
||||
- 첨부파일과 스티커는 수신 미디어로 수집되며(가능한 경우 에이전트에 표시됨).
|
||||
- 페어링/허용 목록은 다른 채널과 동일한 방식으로 작동하며(` /channels/pairing` 등), `channels.bluebubbles.allowFrom` + 페어링 코드를 사용합니다.
|
||||
- 반응은 Slack/Telegram과 마찬가지로 시스템 이벤트로 표시되므로, 에이전트는 답장 전에 이를 "언급"할 수 있습니다.
|
||||
- 고급 기능: 편집, 전송 취소, 답장 스레딩, 메시지 효과, 그룹 관리.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
1. Mac에 BlueBubbles 서버를 설치합니다([bluebubbles.app/install](https://bluebubbles.app/install)의 안내를 따르세요).
|
||||
2. BlueBubbles 설정에서 웹 API를 활성화하고 비밀번호를 설정합니다.
|
||||
3. `openclaw onboard`를 실행하고 BlueBubbles를 선택하거나, 수동으로 구성합니다:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
4. BlueBubbles 웹훅이 게이트웨이를 가리키도록 설정합니다(예: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
|
||||
5. 게이트웨이를 시작하면 웹훅 핸들러를 등록하고 페어링을 시작합니다.
|
||||
|
||||
보안 참고:
|
||||
|
||||
- 항상 웹훅 비밀번호를 설정하세요.
|
||||
- 웹훅 인증은 항상 필요합니다. OpenClaw는 루프백/프록시 토폴로지와 관계없이 `channels.bluebubbles.password`와 일치하는 비밀번호/guid를 포함하지 않는 BlueBubbles 웹훅 요청을 거부합니다(예: `?password=<password>` 또는 `x-password`).
|
||||
- 비밀번호 인증은 전체 웹훅 본문을 읽거나 파싱하기 전에 검사됩니다.
|
||||
|
||||
## Messages.app 활성 상태 유지하기(VM / 헤드리스 설정)
|
||||
|
||||
일부 macOS VM / 상시 실행 설정에서는 Messages.app이 “유휴” 상태가 되어(앱을 열거나 포그라운드로 가져올 때까지 수신 이벤트가 중지됨) 문제가 생길 수 있습니다. 간단한 해결 방법은 AppleScript + LaunchAgent를 사용해 **5분마다 Messages를 건드리는 것**입니다.
|
||||
|
||||
### 1) AppleScript 저장
|
||||
|
||||
다음 경로에 저장하세요:
|
||||
|
||||
- `~/Scripts/poke-messages.scpt`
|
||||
|
||||
예시 스크립트(비대화형, 포커스를 빼앗지 않음):
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
### 2) LaunchAgent 설치
|
||||
|
||||
다음 경로에 저장하세요:
|
||||
|
||||
- `~/Library/LaunchAgents/com.user.poke-messages.plist`
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 이는 **300초마다** 그리고 **로그인 시** 실행됩니다.
|
||||
- 첫 실행 시 macOS **Automation** 프롬프트(`osascript` → Messages)가 나타날 수 있습니다. LaunchAgent를 실행하는 동일한 사용자 세션에서 이를 승인하세요.
|
||||
|
||||
로드:
|
||||
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
|
||||
## 온보딩
|
||||
|
||||
BlueBubbles는 대화형 온보딩에서 사용할 수 있습니다:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
마법사는 다음 항목을 묻습니다:
|
||||
|
||||
- **Server URL** (필수): BlueBubbles 서버 주소(예: `http://192.168.1.100:1234`)
|
||||
- **Password** (필수): BlueBubbles Server 설정의 API 비밀번호
|
||||
- **Webhook path** (선택 사항): 기본값은 `/bluebubbles-webhook`
|
||||
- **DM policy**: pairing, allowlist, open, 또는 disabled
|
||||
- **Allow list**: 전화번호, 이메일 또는 채팅 대상
|
||||
|
||||
CLI를 통해 BlueBubbles를 추가할 수도 있습니다:
|
||||
|
||||
```
|
||||
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
|
||||
```
|
||||
|
||||
## 접근 제어(DM + 그룹)
|
||||
|
||||
DM:
|
||||
|
||||
- 기본값: `channels.bluebubbles.dmPolicy = "pairing"`.
|
||||
- 알 수 없는 발신자에게는 페어링 코드가 전송되며, 승인될 때까지 메시지는 무시됩니다(코드는 1시간 후 만료).
|
||||
- 다음으로 승인:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- 페어링이 기본 토큰 교환 방식입니다. 자세한 내용: [페어링](/channels/pairing)
|
||||
|
||||
그룹:
|
||||
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (기본값: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`은 `allowlist`가 설정된 경우 그룹에서 누가 트리거할 수 있는지 제어합니다.
|
||||
|
||||
### 연락처 이름 보강(macOS, 선택 사항)
|
||||
|
||||
BlueBubbles 그룹 웹훅은 종종 원시 참가자 주소만 포함합니다. 대신 `GroupMembers` 컨텍스트에 로컬 연락처 이름이 표시되도록 하려면 macOS에서 로컬 연락처 보강을 선택적으로 활성화할 수 있습니다:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true`는 조회를 활성화합니다. 기본값: `false`.
|
||||
- 조회는 그룹 접근, 명령 권한 부여, 멘션 게이팅이 모두 메시지 통과를 허용한 후에만 실행됩니다.
|
||||
- 이름이 없는 전화 참가자만 보강됩니다.
|
||||
- 로컬 일치 항목을 찾지 못하면 원시 전화번호가 대체값으로 유지됩니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enrichGroupParticipantsFromContacts: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 멘션 게이팅(그룹)
|
||||
|
||||
BlueBubbles는 그룹 채팅에서 멘션 게이팅을 지원하며, iMessage/WhatsApp 동작과 일치합니다:
|
||||
|
||||
- 멘션 감지에는 `agents.list[].groupChat.mentionPatterns`(또는 `messages.groupChat.mentionPatterns`)를 사용합니다.
|
||||
- 그룹에 대해 `requireMention`이 활성화되면, 에이전트는 멘션되었을 때만 응답합니다.
|
||||
- 권한 있는 발신자의 제어 명령은 멘션 게이팅을 우회합니다.
|
||||
|
||||
그룹별 구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // 모든 그룹의 기본값
|
||||
"iMessage;-;chat123": { requireMention: false }, // 특정 그룹에 대한 재정의
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 명령 게이팅
|
||||
|
||||
- 제어 명령(예: `/config`, `/model`)에는 권한 부여가 필요합니다.
|
||||
- 명령 권한 부여를 결정하는 데 `allowFrom`과 `groupAllowFrom`을 사용합니다.
|
||||
- 권한 있는 발신자는 그룹에서 멘션 없이도 제어 명령을 실행할 수 있습니다.
|
||||
|
||||
## ACP 대화 바인딩
|
||||
|
||||
BlueBubbles 채팅은 전송 계층을 변경하지 않고도 영속적인 ACP 워크스페이스로 전환할 수 있습니다.
|
||||
|
||||
빠른 운영자 흐름:
|
||||
|
||||
- DM 또는 허용된 그룹 채팅 안에서 `/acp spawn codex --bind here`를 실행합니다.
|
||||
- 이후 같은 BlueBubbles 대화의 메시지는 생성된 ACP 세션으로 라우팅됩니다.
|
||||
- `/new`와 `/reset`은 같은 바인딩된 ACP 세션을 그 자리에서 재설정합니다.
|
||||
- `/acp close`는 ACP 세션을 닫고 바인딩을 제거합니다.
|
||||
|
||||
구성된 영속 바인딩도 최상위 `bindings[]` 항목에서 `type: "acp"` 및 `match.channel: "bluebubbles"`를 통해 지원됩니다.
|
||||
|
||||
`match.peer.id`는 지원되는 모든 BlueBubbles 대상 형식을 사용할 수 있습니다:
|
||||
|
||||
- `+15555550123` 또는 `user@example.com` 같은 정규화된 DM 핸들
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
안정적인 그룹 바인딩에는 `chat_id:*` 또는 `chat_identifier:*`를 권장합니다.
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "bluebubbles",
|
||||
accountId: "default",
|
||||
peer: { kind: "dm", id: "+15555550123" },
|
||||
},
|
||||
acp: { label: "codex-imessage" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
공통 ACP 바인딩 동작은 [ACP Agents](/tools/acp-agents)를 참조하세요.
|
||||
|
||||
## 타이핑 + 읽음 확인
|
||||
|
||||
- **타이핑 표시기**: 응답 생성 전과 생성 중에 자동으로 전송됩니다.
|
||||
- **읽음 확인**: `channels.bluebubbles.sendReadReceipts`로 제어됩니다(기본값: `true`).
|
||||
- **타이핑 표시기**: OpenClaw는 타이핑 시작 이벤트를 전송하며, BlueBubbles는 전송 또는 타임아웃 시 자동으로 타이핑을 해제합니다(DELETE를 통한 수동 중지는 신뢰할 수 없음).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
sendReadReceipts: false, // 읽음 확인 비활성화
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 고급 작업
|
||||
|
||||
BlueBubbles는 구성에서 활성화하면 고급 메시지 작업을 지원합니다:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // 탭백 (기본값: true)
|
||||
edit: true, // 보낸 메시지 편집 (macOS 13+, macOS 26 Tahoe에서는 깨짐)
|
||||
unsend: true, // 메시지 전송 취소 (macOS 13+)
|
||||
reply: true, // 메시지 GUID 기준 답장 스레딩
|
||||
sendWithEffect: true, // 메시지 효과 (slam, loud 등)
|
||||
renameGroup: true, // 그룹 채팅 이름 변경
|
||||
setGroupIcon: true, // 그룹 채팅 아이콘/사진 설정 (macOS 26 Tahoe에서 불안정)
|
||||
addParticipant: true, // 그룹에 참가자 추가
|
||||
removeParticipant: true, // 그룹에서 참가자 제거
|
||||
leaveGroup: true, // 그룹 채팅 나가기
|
||||
sendAttachment: true, // 첨부파일/미디어 전송
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
사용 가능한 작업:
|
||||
|
||||
- **react**: 탭백 반응 추가/제거 (`messageId`, `emoji`, `remove`)
|
||||
- **edit**: 보낸 메시지 편집 (`messageId`, `text`)
|
||||
- **unsend**: 메시지 전송 취소 (`messageId`)
|
||||
- **reply**: 특정 메시지에 답장 (`messageId`, `text`, `to`)
|
||||
- **sendWithEffect**: iMessage 효과와 함께 전송 (`text`, `to`, `effectId`)
|
||||
- **renameGroup**: 그룹 채팅 이름 변경 (`chatGuid`, `displayName`)
|
||||
- **setGroupIcon**: 그룹 채팅의 아이콘/사진 설정 (`chatGuid`, `media`) — macOS 26 Tahoe에서 불안정(API가 성공을 반환해도 아이콘이 동기화되지 않을 수 있음).
|
||||
- **addParticipant**: 그룹에 사용자 추가 (`chatGuid`, `address`)
|
||||
- **removeParticipant**: 그룹에서 사용자 제거 (`chatGuid`, `address`)
|
||||
- **leaveGroup**: 그룹 채팅 나가기 (`chatGuid`)
|
||||
- **upload-file**: 미디어/파일 전송 (`to`, `buffer`, `filename`, `asVoice`)
|
||||
- 음성 메모: **MP3** 또는 **CAF** 오디오와 함께 `asVoice: true`를 설정하면 iMessage 음성 메시지로 전송됩니다. BlueBubbles는 음성 메모 전송 시 MP3 → CAF로 변환합니다.
|
||||
- 레거시 별칭: `sendAttachment`도 계속 작동하지만, 정식 작업 이름은 `upload-file`입니다.
|
||||
|
||||
### 메시지 ID(짧은 형식 vs 전체 형식)
|
||||
|
||||
OpenClaw는 토큰 절약을 위해 _짧은_ 메시지 ID(예: `1`, `2`)를 표시할 수 있습니다.
|
||||
|
||||
- `MessageSid` / `ReplyToId`는 짧은 ID일 수 있습니다.
|
||||
- `MessageSidFull` / `ReplyToIdFull`에는 provider의 전체 ID가 들어 있습니다.
|
||||
- 짧은 ID는 메모리 내 값이며, 재시작 또는 캐시 제거 시 만료될 수 있습니다.
|
||||
- 작업은 짧은 `messageId`와 전체 `messageId`를 모두 허용하지만, 더 이상 사용할 수 없는 짧은 ID는 오류가 발생합니다.
|
||||
|
||||
지속적인 자동화와 저장에는 전체 ID를 사용하세요:
|
||||
|
||||
- 템플릿: `{{MessageSidFull}}`, `{{ReplyToIdFull}}`
|
||||
- 컨텍스트: 수신 페이로드의 `MessageSidFull` / `ReplyToIdFull`
|
||||
|
||||
템플릿 변수는 [구성](/gateway/configuration)을 참조하세요.
|
||||
|
||||
## 블록 스트리밍
|
||||
|
||||
응답을 단일 메시지로 보낼지 블록 단위로 스트리밍할지 제어합니다:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
blockStreaming: true, // 블록 스트리밍 활성화(기본적으로 꺼짐)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 미디어 + 제한
|
||||
|
||||
- 수신 첨부파일은 다운로드되어 미디어 캐시에 저장됩니다.
|
||||
- 수신 및 발신 미디어의 용량 제한은 `channels.bluebubbles.mediaMaxMb`로 제어합니다(기본값: 8 MB).
|
||||
- 발신 텍스트는 `channels.bluebubbles.textChunkLimit`까지 청크로 분할됩니다(기본값: 4000자).
|
||||
|
||||
## 구성 참조
|
||||
|
||||
전체 구성: [구성](/gateway/configuration)
|
||||
|
||||
Provider 옵션:
|
||||
|
||||
- `channels.bluebubbles.enabled`: 채널 활성화/비활성화.
|
||||
- `channels.bluebubbles.serverUrl`: BlueBubbles REST API 기본 URL.
|
||||
- `channels.bluebubbles.password`: API 비밀번호.
|
||||
- `channels.bluebubbles.webhookPath`: 웹훅 엔드포인트 경로(기본값: `/bluebubbles-webhook`).
|
||||
- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (기본값: `pairing`).
|
||||
- `channels.bluebubbles.allowFrom`: DM 허용 목록(핸들, 이메일, E.164 번호, `chat_id:*`, `chat_guid:*`).
|
||||
- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (기본값: `allowlist`).
|
||||
- `channels.bluebubbles.groupAllowFrom`: 그룹 발신자 허용 목록.
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`: macOS에서 게이팅 통과 후 이름 없는 그룹 참가자를 로컬 연락처로부터 선택적으로 보강합니다. 기본값: `false`.
|
||||
- `channels.bluebubbles.groups`: 그룹별 구성(`requireMention` 등).
|
||||
- `channels.bluebubbles.sendReadReceipts`: 읽음 확인 전송(기본값: `true`).
|
||||
- `channels.bluebubbles.blockStreaming`: 블록 스트리밍 활성화(기본값: `false`; 스트리밍 답장에 필요).
|
||||
- `channels.bluebubbles.textChunkLimit`: 발신 청크 크기(문자 수, 기본값: 4000).
|
||||
- `channels.bluebubbles.chunkMode`: `length`(기본값)는 `textChunkLimit`를 초과할 때만 분할합니다. `newline`은 길이 기준 분할 전에 빈 줄(문단 경계)에서 분할합니다.
|
||||
- `channels.bluebubbles.mediaMaxMb`: 수신/발신 미디어 용량 제한(MB, 기본값: 8).
|
||||
- `channels.bluebubbles.mediaLocalRoots`: 발신 로컬 미디어 경로에 허용되는 절대 로컬 디렉터리의 명시적 허용 목록. 이를 구성하지 않으면 로컬 경로 전송은 기본적으로 거부됩니다. 계정별 재정의: `channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`.
|
||||
- `channels.bluebubbles.historyLimit`: 컨텍스트용 최대 그룹 메시지 수(0이면 비활성화).
|
||||
- `channels.bluebubbles.dmHistoryLimit`: DM 기록 제한.
|
||||
- `channels.bluebubbles.actions`: 특정 작업 활성화/비활성화.
|
||||
- `channels.bluebubbles.accounts`: 다중 계정 구성.
|
||||
|
||||
관련 전역 옵션:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns`(또는 `messages.groupChat.mentionPatterns`).
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## 주소 지정 / 전달 대상
|
||||
|
||||
안정적인 라우팅에는 `chat_guid`를 권장합니다:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123` (그룹에 권장)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- 직접 핸들: `+15555550123`, `user@example.com`
|
||||
- 직접 핸들에 기존 DM 채팅이 없으면 OpenClaw가 `POST /api/v1/chat/new`를 통해 새로 생성합니다. 이 기능을 사용하려면 BlueBubbles Private API가 활성화되어 있어야 합니다.
|
||||
|
||||
## 보안
|
||||
|
||||
- 웹훅 요청은 `guid`/`password` 쿼리 매개변수 또는 헤더를 `channels.bluebubbles.password`와 비교하여 인증됩니다.
|
||||
- API 비밀번호와 웹훅 엔드포인트는 비밀로 유지하세요(자격 증명처럼 취급하세요).
|
||||
- BlueBubbles 웹훅 인증에는 localhost 우회가 없습니다. 웹훅 트래픽을 프록시하는 경우 요청 전 구간에 걸쳐 BlueBubbles 비밀번호를 유지하세요. 여기서 `gateway.trustedProxies`는 `channels.bluebubbles.password`를 대체하지 않습니다. [게이트웨이 보안](/gateway/security#reverse-proxy-configuration)을 참조하세요.
|
||||
- LAN 외부에 노출하는 경우 BlueBubbles 서버에서 HTTPS + 방화벽 규칙을 활성화하세요.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
- 타이핑/읽음 이벤트가 더 이상 작동하지 않으면 BlueBubbles 웹훅 로그를 확인하고 게이트웨이 경로가 `channels.bluebubbles.webhookPath`와 일치하는지 검증하세요.
|
||||
- 페어링 코드는 1시간 후 만료됩니다. `openclaw pairing list bluebubbles` 및 `openclaw pairing approve bluebubbles <code>`를 사용하세요.
|
||||
- 반응 기능에는 BlueBubbles private API(`POST /api/v1/message/react`)가 필요합니다. 서버 버전이 이를 노출하는지 확인하세요.
|
||||
- 편집/전송 취소는 macOS 13+ 및 호환되는 BlueBubbles 서버 버전이 필요합니다. macOS 26(Tahoe)에서는 private API 변경으로 인해 현재 편집 기능이 깨져 있습니다.
|
||||
- 그룹 아이콘 업데이트는 macOS 26(Tahoe)에서 불안정할 수 있습니다. API는 성공을 반환해도 새 아이콘이 동기화되지 않을 수 있습니다.
|
||||
- OpenClaw는 BlueBubbles 서버의 macOS 버전을 기준으로 알려진 문제 있는 작업을 자동으로 숨깁니다. macOS 26(Tahoe)에서 여전히 편집이 표시되면 `channels.bluebubbles.actions.edit=false`로 수동 비활성화하세요.
|
||||
- 상태/헬스 정보는 `openclaw status --all` 또는 `openclaw status --deep`를 사용하세요.
|
||||
|
||||
일반적인 채널 워크플로 참조는 [채널](/channels) 및 [Plugins](/tools/plugin) 가이드를 참조하세요.
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 접근 모델 및 보안 강화
|
||||
449
docs/ko/channels/broadcast-groups.md
Normal file
449
docs/ko/channels/broadcast-groups.md
Normal file
@ -0,0 +1,449 @@
|
||||
---
|
||||
read_when:
|
||||
- 브로드캐스트 그룹을 구성할 때
|
||||
- WhatsApp에서 다중 에이전트 응답을 디버깅할 때
|
||||
status: experimental
|
||||
summary: WhatsApp 메시지를 여러 에이전트에 브로드캐스트합니다
|
||||
title: 브로드캐스트 그룹
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:44Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 1d117ae65ec3b63c2bd4b3c215d96f32d7eafa0f99a9cd7378e502c15e56ca56
|
||||
source_path: channels/broadcast-groups.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 브로드캐스트 그룹
|
||||
|
||||
**상태:** 실험적
|
||||
**버전:** 2026.1.9에 추가됨
|
||||
|
||||
## 개요
|
||||
|
||||
브로드캐스트 그룹을 사용하면 여러 에이전트가 동일한 메시지를 동시에 처리하고 응답할 수 있습니다. 이를 통해 하나의 WhatsApp 그룹 또는 DM에서 함께 작업하는 전문화된 에이전트 팀을 만들 수 있으며, 모두 하나의 전화번호를 사용합니다.
|
||||
|
||||
현재 범위: **WhatsApp 전용** (web 채널).
|
||||
|
||||
브로드캐스트 그룹은 채널 허용 목록과 그룹 활성화 규칙 이후에 평가됩니다. WhatsApp 그룹에서는 OpenClaw가 일반적으로 응답하는 경우(예: 그룹 설정에 따라 멘션이 있을 때) 브로드캐스트가 발생한다는 뜻입니다.
|
||||
|
||||
## 사용 사례
|
||||
|
||||
### 1. 전문화된 에이전트 팀
|
||||
|
||||
원자적이고 집중된 책임을 가진 여러 에이전트를 배포합니다:
|
||||
|
||||
```
|
||||
Group: "Development Team"
|
||||
Agents:
|
||||
- CodeReviewer (코드 스니펫 검토)
|
||||
- DocumentationBot (문서 생성)
|
||||
- SecurityAuditor (취약점 검사)
|
||||
- TestGenerator (테스트 케이스 제안)
|
||||
```
|
||||
|
||||
각 에이전트는 동일한 메시지를 처리하고 자신의 전문 관점을 제공합니다.
|
||||
|
||||
### 2. 다국어 지원
|
||||
|
||||
```
|
||||
Group: "International Support"
|
||||
Agents:
|
||||
- Agent_EN (영어로 응답)
|
||||
- Agent_DE (독일어로 응답)
|
||||
- Agent_ES (스페인어로 응답)
|
||||
```
|
||||
|
||||
### 3. 품질 보증 워크플로
|
||||
|
||||
```
|
||||
Group: "Customer Support"
|
||||
Agents:
|
||||
- SupportAgent (답변 제공)
|
||||
- QAAgent (품질 검토, 문제를 발견한 경우에만 응답)
|
||||
```
|
||||
|
||||
### 4. 작업 자동화
|
||||
|
||||
```
|
||||
Group: "Project Management"
|
||||
Agents:
|
||||
- TaskTracker (작업 데이터베이스 업데이트)
|
||||
- TimeLogger (소요 시간 기록)
|
||||
- ReportGenerator (요약 생성)
|
||||
```
|
||||
|
||||
## 구성
|
||||
|
||||
### 기본 설정
|
||||
|
||||
최상위 `broadcast` 섹션을 추가합니다(`bindings` 옆). 키는 WhatsApp 피어 ID입니다:
|
||||
|
||||
- 그룹 채팅: 그룹 JID(예: `120363403215116621@g.us`)
|
||||
- DM: E.164 전화번호(예: `+15551234567`)
|
||||
|
||||
```json
|
||||
{
|
||||
"broadcast": {
|
||||
"120363403215116621@g.us": ["alfred", "baerbel", "assistant3"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**결과:** OpenClaw가 이 채팅에 응답해야 할 때 세 에이전트가 모두 실행됩니다.
|
||||
|
||||
### 처리 전략
|
||||
|
||||
에이전트가 메시지를 처리하는 방식을 제어합니다:
|
||||
|
||||
#### 병렬(기본값)
|
||||
|
||||
모든 에이전트가 동시에 처리합니다:
|
||||
|
||||
```json
|
||||
{
|
||||
"broadcast": {
|
||||
"strategy": "parallel",
|
||||
"120363403215116621@g.us": ["alfred", "baerbel"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 순차
|
||||
|
||||
에이전트가 순서대로 처리합니다(이전 에이전트가 끝날 때까지 다음 에이전트가 대기):
|
||||
|
||||
```json
|
||||
{
|
||||
"broadcast": {
|
||||
"strategy": "sequential",
|
||||
"120363403215116621@g.us": ["alfred", "baerbel"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 전체 예제
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"list": [
|
||||
{
|
||||
"id": "code-reviewer",
|
||||
"name": "Code Reviewer",
|
||||
"workspace": "/path/to/code-reviewer",
|
||||
"sandbox": { "mode": "all" }
|
||||
},
|
||||
{
|
||||
"id": "security-auditor",
|
||||
"name": "Security Auditor",
|
||||
"workspace": "/path/to/security-auditor",
|
||||
"sandbox": { "mode": "all" }
|
||||
},
|
||||
{
|
||||
"id": "docs-generator",
|
||||
"name": "Documentation Generator",
|
||||
"workspace": "/path/to/docs-generator",
|
||||
"sandbox": { "mode": "all" }
|
||||
}
|
||||
]
|
||||
},
|
||||
"broadcast": {
|
||||
"strategy": "parallel",
|
||||
"120363403215116621@g.us": ["code-reviewer", "security-auditor", "docs-generator"],
|
||||
"120363424282127706@g.us": ["support-en", "support-de"],
|
||||
"+15555550123": ["assistant", "logger"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 작동 방식
|
||||
|
||||
### 메시지 흐름
|
||||
|
||||
1. **수신 메시지**가 WhatsApp 그룹에 도착합니다
|
||||
2. **브로드캐스트 확인**: 시스템이 피어 ID가 `broadcast`에 있는지 확인합니다
|
||||
3. **브로드캐스트 목록에 있으면**:
|
||||
- 나열된 모든 에이전트가 메시지를 처리합니다
|
||||
- 각 에이전트는 자체 세션 키와 격리된 컨텍스트를 가집니다
|
||||
- 에이전트는 병렬(기본값) 또는 순차적으로 처리합니다
|
||||
4. **브로드캐스트 목록에 없으면**:
|
||||
- 일반 라우팅이 적용됩니다(처음 일치하는 binding)
|
||||
|
||||
참고: 브로드캐스트 그룹은 채널 허용 목록이나 그룹 활성화 규칙(멘션/명령 등)을 우회하지 않습니다. 메시지가 처리 대상이 될 때 _어떤 에이전트가 실행되는지_ 만 변경합니다.
|
||||
|
||||
### 세션 격리
|
||||
|
||||
브로드캐스트 그룹의 각 에이전트는 다음을 완전히 분리해서 유지합니다:
|
||||
|
||||
- **세션 키** (`agent:alfred:whatsapp:group:120363...` 대 `agent:baerbel:whatsapp:group:120363...`)
|
||||
- **대화 기록** (에이전트는 다른 에이전트의 메시지를 보지 못함)
|
||||
- **워크스페이스** (구성된 경우 별도 샌드박스)
|
||||
- **도구 접근 권한** (서로 다른 허용/거부 목록)
|
||||
- **메모리/컨텍스트** (별도 `IDENTITY.md`, `SOUL.md` 등)
|
||||
- **그룹 컨텍스트 버퍼** (컨텍스트에 사용되는 최근 그룹 메시지)는 피어별로 공유되므로, 트리거될 때 모든 브로드캐스트 에이전트가 동일한 컨텍스트를 봅니다
|
||||
|
||||
이를 통해 각 에이전트는 다음을 가질 수 있습니다:
|
||||
|
||||
- 서로 다른 성격
|
||||
- 서로 다른 도구 접근 권한(예: 읽기 전용 대 읽기-쓰기)
|
||||
- 서로 다른 모델(예: opus 대 sonnet)
|
||||
- 서로 다른 Skills 설치
|
||||
|
||||
### 예: 격리된 세션
|
||||
|
||||
그룹 `120363403215116621@g.us`에 에이전트 `["alfred", "baerbel"]`가 있는 경우:
|
||||
|
||||
**Alfred의 컨텍스트:**
|
||||
|
||||
```
|
||||
Session: agent:alfred:whatsapp:group:120363403215116621@g.us
|
||||
History: [사용자 메시지, alfred의 이전 응답]
|
||||
Workspace: /Users/user/openclaw-alfred/
|
||||
Tools: read, write, exec
|
||||
```
|
||||
|
||||
**Bärbel의 컨텍스트:**
|
||||
|
||||
```
|
||||
Session: agent:baerbel:whatsapp:group:120363403215116621@g.us
|
||||
History: [사용자 메시지, baerbel의 이전 응답]
|
||||
Workspace: /Users/user/openclaw-baerbel/
|
||||
Tools: read only
|
||||
```
|
||||
|
||||
## 모범 사례
|
||||
|
||||
### 1. 에이전트의 역할을 집중시키기
|
||||
|
||||
각 에이전트를 하나의 명확한 책임으로 설계합니다:
|
||||
|
||||
```json
|
||||
{
|
||||
"broadcast": {
|
||||
"DEV_GROUP": ["formatter", "linter", "tester"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
✅ **좋음:** 각 에이전트에 하나의 역할이 있음
|
||||
❌ **나쁨:** 범용 "dev-helper" 에이전트 하나
|
||||
|
||||
### 2. 설명적인 이름 사용
|
||||
|
||||
각 에이전트가 무엇을 하는지 명확하게 만드세요:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"security-scanner": { "name": "Security Scanner" },
|
||||
"code-formatter": { "name": "Code Formatter" },
|
||||
"test-generator": { "name": "Test Generator" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 서로 다른 도구 접근 권한 구성
|
||||
|
||||
각 에이전트에 필요한 도구만 부여하세요:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"reviewer": {
|
||||
"tools": { "allow": ["read", "exec"] } // 읽기 전용
|
||||
},
|
||||
"fixer": {
|
||||
"tools": { "allow": ["read", "write", "edit", "exec"] } // 읽기-쓰기
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 성능 모니터링
|
||||
|
||||
에이전트가 많다면 다음을 고려하세요:
|
||||
|
||||
- 속도를 위해 `"strategy": "parallel"`(기본값) 사용
|
||||
- 브로드캐스트 그룹을 5~10개 에이전트로 제한
|
||||
- 더 단순한 에이전트에는 더 빠른 모델 사용
|
||||
|
||||
### 5. 실패를 우아하게 처리
|
||||
|
||||
에이전트는 독립적으로 실패합니다. 한 에이전트의 오류가 다른 에이전트를 막지 않습니다:
|
||||
|
||||
```
|
||||
Message → [Agent A ✓, Agent B ✗ error, Agent C ✓]
|
||||
Result: Agent A와 C는 응답, Agent B는 오류 기록
|
||||
```
|
||||
|
||||
## 호환성
|
||||
|
||||
### 제공자
|
||||
|
||||
브로드캐스트 그룹은 현재 다음과 함께 작동합니다:
|
||||
|
||||
- ✅ WhatsApp (구현됨)
|
||||
- 🚧 Telegram (계획됨)
|
||||
- 🚧 Discord (계획됨)
|
||||
- 🚧 Slack (계획됨)
|
||||
|
||||
### 라우팅
|
||||
|
||||
브로드캐스트 그룹은 기존 라우팅과 함께 작동합니다:
|
||||
|
||||
```json
|
||||
{
|
||||
"bindings": [
|
||||
{
|
||||
"match": { "channel": "whatsapp", "peer": { "kind": "group", "id": "GROUP_A" } },
|
||||
"agentId": "alfred"
|
||||
}
|
||||
],
|
||||
"broadcast": {
|
||||
"GROUP_B": ["agent1", "agent2"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `GROUP_A`: alfred만 응답함(일반 라우팅)
|
||||
- `GROUP_B`: agent1과 agent2가 모두 응답함(브로드캐스트)
|
||||
|
||||
**우선순위:** `broadcast`가 `bindings`보다 우선합니다.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 에이전트가 응답하지 않음
|
||||
|
||||
**확인할 사항:**
|
||||
|
||||
1. 에이전트 ID가 `agents.list`에 존재하는지
|
||||
2. 피어 ID 형식이 올바른지(예: `120363403215116621@g.us`)
|
||||
3. 에이전트가 거부 목록에 없는지
|
||||
|
||||
**디버그:**
|
||||
|
||||
```bash
|
||||
tail -f ~/.openclaw/logs/gateway.log | grep broadcast
|
||||
```
|
||||
|
||||
### 하나의 에이전트만 응답함
|
||||
|
||||
**원인:** 피어 ID가 `bindings`에는 있지만 `broadcast`에는 없을 수 있습니다.
|
||||
|
||||
**해결:** 브로드캐스트 구성에 추가하거나 bindings에서 제거하세요.
|
||||
|
||||
### 성능 문제
|
||||
|
||||
**에이전트가 많아 느릴 때:**
|
||||
|
||||
- 그룹당 에이전트 수 줄이기
|
||||
- 더 가벼운 모델 사용(opus 대신 sonnet)
|
||||
- 샌드박스 시작 시간 확인
|
||||
|
||||
## 예제
|
||||
|
||||
### 예제 1: 코드 리뷰 팀
|
||||
|
||||
```json
|
||||
{
|
||||
"broadcast": {
|
||||
"strategy": "parallel",
|
||||
"120363403215116621@g.us": [
|
||||
"code-formatter",
|
||||
"security-scanner",
|
||||
"test-coverage",
|
||||
"docs-checker"
|
||||
]
|
||||
},
|
||||
"agents": {
|
||||
"list": [
|
||||
{
|
||||
"id": "code-formatter",
|
||||
"workspace": "~/agents/formatter",
|
||||
"tools": { "allow": ["read", "write"] }
|
||||
},
|
||||
{
|
||||
"id": "security-scanner",
|
||||
"workspace": "~/agents/security",
|
||||
"tools": { "allow": ["read", "exec"] }
|
||||
},
|
||||
{
|
||||
"id": "test-coverage",
|
||||
"workspace": "~/agents/testing",
|
||||
"tools": { "allow": ["read", "exec"] }
|
||||
},
|
||||
{ "id": "docs-checker", "workspace": "~/agents/docs", "tools": { "allow": ["read"] } }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**사용자 전송:** 코드 스니펫
|
||||
**응답:**
|
||||
|
||||
- code-formatter: "들여쓰기를 수정하고 타입 힌트를 추가했습니다"
|
||||
- security-scanner: "⚠️ 12번째 줄에 SQL 인젝션 취약점이 있습니다"
|
||||
- test-coverage: "커버리지는 45%이며 오류 사례에 대한 테스트가 누락되어 있습니다"
|
||||
- docs-checker: "함수 `process_data`에 대한 docstring이 누락되어 있습니다"
|
||||
|
||||
### 예제 2: 다국어 지원
|
||||
|
||||
```json
|
||||
{
|
||||
"broadcast": {
|
||||
"strategy": "sequential",
|
||||
"+15555550123": ["detect-language", "translator-en", "translator-de"]
|
||||
},
|
||||
"agents": {
|
||||
"list": [
|
||||
{ "id": "detect-language", "workspace": "~/agents/lang-detect" },
|
||||
{ "id": "translator-en", "workspace": "~/agents/translate-en" },
|
||||
{ "id": "translator-de", "workspace": "~/agents/translate-de" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API 참조
|
||||
|
||||
### 구성 스키마
|
||||
|
||||
```typescript
|
||||
interface OpenClawConfig {
|
||||
broadcast?: {
|
||||
strategy?: "parallel" | "sequential";
|
||||
[peerId: string]: string[];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 필드
|
||||
|
||||
- `strategy` (선택 사항): 에이전트를 처리하는 방식
|
||||
- `"parallel"` (기본값): 모든 에이전트가 동시에 처리
|
||||
- `"sequential"`: 에이전트가 배열 순서대로 처리
|
||||
- `[peerId]`: WhatsApp 그룹 JID, E.164 번호 또는 기타 피어 ID
|
||||
- 값: 메시지를 처리해야 하는 에이전트 ID 배열
|
||||
|
||||
## 제한 사항
|
||||
|
||||
1. **최대 에이전트 수:** 하드 제한은 없지만 10개 이상 에이전트는 느릴 수 있습니다
|
||||
2. **공유 컨텍스트:** 에이전트는 서로의 응답을 보지 못합니다(의도된 동작)
|
||||
3. **메시지 순서:** 병렬 응답은 어떤 순서로든 도착할 수 있습니다
|
||||
4. **속도 제한:** 모든 에이전트가 WhatsApp 속도 제한에 포함됩니다
|
||||
|
||||
## 향후 개선 사항
|
||||
|
||||
계획된 기능:
|
||||
|
||||
- [ ] 공유 컨텍스트 모드(에이전트가 서로의 응답을 볼 수 있음)
|
||||
- [ ] 에이전트 조정(에이전트가 서로에게 신호를 보낼 수 있음)
|
||||
- [ ] 동적 에이전트 선택(메시지 내용에 따라 에이전트 선택)
|
||||
- [ ] 에이전트 우선순위(일부 에이전트가 다른 에이전트보다 먼저 응답)
|
||||
|
||||
## 함께 보기
|
||||
|
||||
- [다중 에이전트 구성](/tools/multi-agent-sandbox-tools)
|
||||
- [라우팅 구성](/channels/channel-routing)
|
||||
- [세션 관리](/concepts/session)
|
||||
138
docs/ko/channels/channel-routing.md
Normal file
138
docs/ko/channels/channel-routing.md
Normal file
@ -0,0 +1,138 @@
|
||||
---
|
||||
read_when:
|
||||
- 채널 라우팅 또는 받은편지함 동작을 변경할 때
|
||||
summary: 채널별 라우팅 규칙(WhatsApp, Telegram, Discord, Slack)과 공유 컨텍스트
|
||||
title: 채널 라우팅
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:38Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 63916c4dd0af5fc9bbd12581a9eb15fea14a380c5ade09323ca0c237db61e537
|
||||
source_path: channels/channel-routing.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 채널 및 라우팅
|
||||
|
||||
OpenClaw는 응답을 **메시지가 들어온 채널로 다시 라우팅합니다**. 모델이 채널을 선택하는 것이 아니라, 라우팅은 결정적이며 호스트 구성에 의해 제어됩니다.
|
||||
|
||||
## 주요 용어
|
||||
|
||||
- **채널**: `telegram`, `whatsapp`, `discord`, `irc`, `googlechat`, `slack`, `signal`, `imessage`, `line` 및 확장 채널. `webchat`은 내부 WebChat UI 채널이며 구성 가능한 아웃바운드 채널이 아닙니다.
|
||||
- **AccountId**: 채널별 계정 인스턴스(지원되는 경우).
|
||||
- 선택적 채널 기본 계정: `channels.<channel>.defaultAccount`는 아웃바운드 경로가 `accountId`를 지정하지 않을 때 사용할 계정을 선택합니다.
|
||||
- 다중 계정 구성에서는 두 개 이상의 계정이 설정되어 있을 때 명시적 기본값(`defaultAccount` 또는 `accounts.default`)을 설정하세요. 그렇지 않으면 폴백 라우팅이 첫 번째 정규화된 계정 ID를 선택할 수 있습니다.
|
||||
- **AgentId**: 격리된 워크스페이스 + 세션 저장소(“브레인”).
|
||||
- **SessionKey**: 컨텍스트를 저장하고 동시성을 제어하는 데 사용하는 버킷 키입니다.
|
||||
|
||||
## 세션 키 형태(예시)
|
||||
|
||||
다이렉트 메시지는 에이전트의 **메인** 세션으로 통합됩니다.
|
||||
|
||||
- `agent:<agentId>:<mainKey>` (기본값: `agent:main:main`)
|
||||
|
||||
그룹과 채널은 채널별로 계속 격리됩니다.
|
||||
|
||||
- 그룹: `agent:<agentId>:<channel>:group:<id>`
|
||||
- 채널/룸: `agent:<agentId>:<channel>:channel:<id>`
|
||||
|
||||
스레드:
|
||||
|
||||
- Slack/Discord 스레드는 기본 키에 `:thread:<threadId>`를 추가합니다.
|
||||
- Telegram 포럼 토픽은 그룹 키에 `:topic:<topicId>`를 포함합니다.
|
||||
|
||||
예시:
|
||||
|
||||
- `agent:main:telegram:group:-1001234567890:topic:42`
|
||||
- `agent:main:discord:channel:123456:thread:987654`
|
||||
|
||||
## 메인 DM 경로 고정
|
||||
|
||||
`session.dmScope`가 `main`일 때 다이렉트 메시지는 하나의 메인 세션을 공유할 수 있습니다.
|
||||
메인 세션의 `lastRoute`가 소유자가 아닌 DM에 의해 덮어써지는 것을 방지하기 위해,
|
||||
OpenClaw는 다음 조건이 모두 참일 때 `allowFrom`에서 고정된 소유자를 추론합니다.
|
||||
|
||||
- `allowFrom`에 와일드카드가 아닌 항목이 정확히 하나 있습니다.
|
||||
- 해당 항목을 그 채널의 구체적인 발신자 ID로 정규화할 수 있습니다.
|
||||
- 인바운드 DM 발신자가 그 고정된 소유자와 일치하지 않습니다.
|
||||
|
||||
이 불일치 사례에서 OpenClaw는 여전히 인바운드 세션 메타데이터를 기록하지만,
|
||||
메인 세션 `lastRoute` 업데이트는 건너뜁니다.
|
||||
|
||||
## 라우팅 규칙(에이전트가 선택되는 방식)
|
||||
|
||||
라우팅은 각 인바운드 메시지에 대해 **하나의 에이전트**를 선택합니다.
|
||||
|
||||
1. **정확한 피어 일치** (`peer.kind` + `peer.id`가 있는 `bindings`)
|
||||
2. **상위 피어 일치** (스레드 상속)
|
||||
3. **길드 + 역할 일치** (Discord) via `guildId` + `roles`
|
||||
4. **길드 일치** (Discord) via `guildId`
|
||||
5. **팀 일치** (Slack) via `teamId`
|
||||
6. **계정 일치** (채널의 `accountId`)
|
||||
7. **채널 일치** (해당 채널의 모든 계정, `accountId: "*"` )
|
||||
8. **기본 에이전트** (`agents.list[].default`, 없으면 첫 번째 목록 항목, 폴백은 `main`)
|
||||
|
||||
바인딩에 여러 일치 필드(`peer`, `guildId`, `teamId`, `roles`)가 포함된 경우, 해당 바인딩이 적용되려면 **제공된 모든 필드가 일치해야 합니다**.
|
||||
|
||||
일치한 에이전트가 어떤 워크스페이스와 세션 저장소를 사용할지 결정합니다.
|
||||
|
||||
## 브로드캐스트 그룹(여러 에이전트 실행)
|
||||
|
||||
브로드캐스트 그룹을 사용하면 **OpenClaw가 일반적으로 응답하는 경우**(예: WhatsApp 그룹에서 멘션/활성화 게이팅 후) 같은 피어에 대해 **여러 에이전트**를 실행할 수 있습니다.
|
||||
|
||||
구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
broadcast: {
|
||||
strategy: "parallel",
|
||||
"120363403215116621@g.us": ["alfred", "baerbel"],
|
||||
"+15555550123": ["support", "logger"],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참조: [브로드캐스트 그룹](/channels/broadcast-groups).
|
||||
|
||||
## 구성 개요
|
||||
|
||||
- `agents.list`: 이름이 지정된 에이전트 정의(워크스페이스, 모델 등)
|
||||
- `bindings`: 인바운드 채널/계정/피어를 에이전트에 매핑
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [{ id: "support", name: "Support", workspace: "~/.openclaw/workspace-support" }],
|
||||
},
|
||||
bindings: [
|
||||
{ match: { channel: "slack", teamId: "T123" }, agentId: "support" },
|
||||
{ match: { channel: "telegram", peer: { kind: "group", id: "-100123" } }, agentId: "support" },
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## 세션 저장소
|
||||
|
||||
세션 저장소는 상태 디렉터리 아래에 있습니다(기본값 `~/.openclaw`).
|
||||
|
||||
- `~/.openclaw/agents/<agentId>/sessions/sessions.json`
|
||||
- JSONL 트랜스크립트는 저장소와 같은 위치에 있습니다
|
||||
|
||||
`session.store`와 `{agentId}` 템플릿을 통해 저장소 경로를 재정의할 수 있습니다.
|
||||
|
||||
Gateway 및 ACP 세션 검색은 기본 `agents/` 루트 아래와 템플릿이 적용된 `session.store` 루트 아래의 디스크 기반 에이전트 저장소도 검사합니다. 검색된 저장소는 해결된 해당 에이전트 루트 내부에 있어야 하며 일반 `sessions.json` 파일을 사용해야 합니다. 심볼릭 링크와 루트 외부 경로는 무시됩니다.
|
||||
|
||||
## WebChat 동작
|
||||
|
||||
WebChat은 **선택된 에이전트**에 연결되며 기본적으로 해당 에이전트의 메인 세션을 사용합니다. 이 때문에 WebChat에서는 해당 에이전트의 교차 채널 컨텍스트를 한 곳에서 볼 수 있습니다.
|
||||
|
||||
## 응답 컨텍스트
|
||||
|
||||
인바운드 응답에는 다음이 포함됩니다.
|
||||
|
||||
- 가능한 경우 `ReplyToId`, `ReplyToBody`, `ReplyToSender`
|
||||
- 인용된 컨텍스트는 `[Replying to ...]` 블록으로 `Body`에 추가됩니다.
|
||||
|
||||
이 동작은 채널 전반에 걸쳐 일관됩니다.
|
||||
1259
docs/ko/channels/discord.md
Normal file
1259
docs/ko/channels/discord.md
Normal file
File diff suppressed because it is too large
Load Diff
794
docs/ko/channels/feishu.md
Normal file
794
docs/ko/channels/feishu.md
Normal file
@ -0,0 +1,794 @@
|
||||
---
|
||||
read_when:
|
||||
- Feishu/Lark 봇을 연결하려는 경우
|
||||
- Feishu 채널을 구성하는 경우
|
||||
summary: Feishu 봇 개요, 기능 및 구성
|
||||
title: Feishu
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:40Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 4e39b6dfe3a3aa4ebbdb992975e570e4f1b5e79f3b400a555fc373a0d1889952
|
||||
source_path: channels/feishu.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Feishu 봇
|
||||
|
||||
Feishu(Lark)는 기업에서 메시징과 협업에 사용하는 팀 채팅 플랫폼입니다. 이 plugin은 플랫폼의 WebSocket 이벤트 구독을 사용해 OpenClaw를 Feishu/Lark 봇에 연결하므로, 공개 webhook URL을 노출하지 않고도 메시지를 수신할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
Feishu는 현재 OpenClaw 릴리스에 번들로 포함되어 제공되므로 별도의 plugin 설치가 필요하지 않습니다.
|
||||
|
||||
번들된 Feishu가 포함되지 않은 이전 빌드 또는 사용자 지정 설치를 사용 중인 경우 수동으로 설치하세요.
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/feishu
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
Feishu 채널을 추가하는 방법은 두 가지입니다.
|
||||
|
||||
### 방법 1: 온보딩(권장)
|
||||
|
||||
OpenClaw를 방금 설치했다면 온보딩을 실행하세요.
|
||||
|
||||
```bash
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
마법사는 다음 과정을 안내합니다.
|
||||
|
||||
1. Feishu 앱 생성 및 자격 증명 수집
|
||||
2. OpenClaw에서 앱 자격 증명 구성
|
||||
3. Gateway 시작
|
||||
|
||||
✅ **구성 후**, Gateway 상태를 확인하세요.
|
||||
|
||||
- `openclaw gateway status`
|
||||
- `openclaw logs --follow`
|
||||
|
||||
### 방법 2: CLI 설정
|
||||
|
||||
이미 초기 설치를 완료했다면 CLI를 통해 채널을 추가하세요.
|
||||
|
||||
```bash
|
||||
openclaw channels add
|
||||
```
|
||||
|
||||
**Feishu**를 선택한 다음 App ID와 App Secret을 입력하세요.
|
||||
|
||||
✅ **구성 후**, Gateway를 관리하세요.
|
||||
|
||||
- `openclaw gateway status`
|
||||
- `openclaw gateway restart`
|
||||
- `openclaw logs --follow`
|
||||
|
||||
---
|
||||
|
||||
## 1단계: Feishu 앱 만들기
|
||||
|
||||
### 1. Feishu Open Platform 열기
|
||||
|
||||
[Feishu Open Platform](https://open.feishu.cn/app)에 접속해 로그인하세요.
|
||||
|
||||
Lark(글로벌) 테넌트는 [https://open.larksuite.com/app](https://open.larksuite.com/app)을 사용하고 Feishu config에서 `domain: "lark"`를 설정해야 합니다.
|
||||
|
||||
### 2. 앱 만들기
|
||||
|
||||
1. **Create enterprise app**을 클릭합니다.
|
||||
2. 앱 이름과 설명을 입력합니다.
|
||||
3. 앱 아이콘을 선택합니다.
|
||||
|
||||

|
||||
|
||||
### 3. 자격 증명 복사
|
||||
|
||||
**Credentials & Basic Info**에서 다음을 복사하세요.
|
||||
|
||||
- **App ID**(형식: `cli_xxx`)
|
||||
- **App Secret**
|
||||
|
||||
❗ **중요:** App Secret은 비공개로 유지하세요.
|
||||
|
||||

|
||||
|
||||
### 4. 권한 구성
|
||||
|
||||
**Permissions**에서 **Batch import**를 클릭하고 다음을 붙여넣으세요.
|
||||
|
||||
```json
|
||||
{
|
||||
"scopes": {
|
||||
"tenant": [
|
||||
"aily:file:read",
|
||||
"aily:file:write",
|
||||
"application:application.app_message_stats.overview:readonly",
|
||||
"application:application:self_manage",
|
||||
"application:bot.menu:write",
|
||||
"cardkit:card:read",
|
||||
"cardkit:card:write",
|
||||
"contact:user.employee_id:readonly",
|
||||
"corehr:file:download",
|
||||
"event:ip_list",
|
||||
"im:chat.access_event.bot_p2p_chat:read",
|
||||
"im:chat.members:bot_access",
|
||||
"im:message",
|
||||
"im:message.group_at_msg:readonly",
|
||||
"im:message.p2p_msg:readonly",
|
||||
"im:message:readonly",
|
||||
"im:message:send_as_bot",
|
||||
"im:resource"
|
||||
],
|
||||
"user": ["aily:file:read", "aily:file:write", "im:chat.access_event.bot_p2p_chat:read"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 5. 봇 기능 활성화
|
||||
|
||||
**App Capability** > **Bot**에서 다음을 수행하세요.
|
||||
|
||||
1. 봇 기능을 활성화합니다.
|
||||
2. 봇 이름을 설정합니다.
|
||||
|
||||

|
||||
|
||||
### 6. 이벤트 구독 구성
|
||||
|
||||
⚠️ **중요:** 이벤트 구독을 설정하기 전에 다음을 확인하세요.
|
||||
|
||||
1. 이미 Feishu에 대해 `openclaw channels add`를 실행했는지
|
||||
2. Gateway가 실행 중인지(`openclaw gateway status`)
|
||||
|
||||
**Event Subscription**에서:
|
||||
|
||||
1. **Use long connection to receive events**(WebSocket)를 선택합니다.
|
||||
2. 이벤트 `im.message.receive_v1`을 추가합니다.
|
||||
3. (선택 사항) Drive 댓글 워크플로를 위해 `drive.notice.comment_add_v1`도 추가합니다.
|
||||
|
||||
⚠️ Gateway가 실행 중이 아니면 long-connection 설정을 저장하지 못할 수 있습니다.
|
||||
|
||||

|
||||
|
||||
### 7. 앱 게시
|
||||
|
||||
1. **Version Management & Release**에서 버전을 생성합니다.
|
||||
2. 검토를 위해 제출하고 게시합니다.
|
||||
3. 관리자 승인을 기다립니다(기업 앱은 보통 자동 승인됨).
|
||||
|
||||
---
|
||||
|
||||
## 2단계: OpenClaw 구성
|
||||
|
||||
### 마법사로 구성(권장)
|
||||
|
||||
```bash
|
||||
openclaw channels add
|
||||
```
|
||||
|
||||
**Feishu**를 선택하고 App ID와 App Secret을 붙여넣으세요.
|
||||
|
||||
### config 파일로 구성
|
||||
|
||||
`~/.openclaw/openclaw.json`을 편집하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
enabled: true,
|
||||
dmPolicy: "pairing",
|
||||
accounts: {
|
||||
main: {
|
||||
appId: "cli_xxx",
|
||||
appSecret: "xxx",
|
||||
name: "My AI assistant",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`connectionMode: "webhook"`을 사용하는 경우 `verificationToken`과 `encryptKey`를 모두 설정하세요. Feishu webhook 서버는 기본적으로 `127.0.0.1`에 바인딩됩니다. 의도적으로 다른 바인딩 주소가 필요한 경우에만 `webhookHost`를 설정하세요.
|
||||
|
||||
#### Verification Token 및 Encrypt Key(webhook 모드)
|
||||
|
||||
webhook 모드를 사용할 때는 config에서 `channels.feishu.verificationToken`과 `channels.feishu.encryptKey`를 모두 설정하세요. 값을 얻으려면:
|
||||
|
||||
1. Feishu Open Platform에서 앱을 엽니다.
|
||||
2. **Development** → **Events & Callbacks**(开发配置 → 事件与回调)로 이동합니다.
|
||||
3. **Encryption** 탭(加密策略)을 엽니다.
|
||||
4. **Verification Token**과 **Encrypt Key**를 복사합니다.
|
||||
|
||||
아래 스크린샷은 **Verification Token** 위치를 보여줍니다. **Encrypt Key**는 같은 **Encryption** 섹션에 표시됩니다.
|
||||
|
||||

|
||||
|
||||
### 환경 변수로 구성
|
||||
|
||||
```bash
|
||||
export FEISHU_APP_ID="cli_xxx"
|
||||
export FEISHU_APP_SECRET="xxx"
|
||||
```
|
||||
|
||||
### Lark(글로벌) 도메인
|
||||
|
||||
테넌트가 Lark(국제 버전)에 있는 경우 도메인을 `lark`(또는 전체 도메인 문자열)로 설정하세요. `channels.feishu.domain` 또는 계정별(`channels.feishu.accounts.<id>.domain`)로 설정할 수 있습니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
domain: "lark",
|
||||
accounts: {
|
||||
main: {
|
||||
appId: "cli_xxx",
|
||||
appSecret: "xxx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 쿼터 최적화 플래그
|
||||
|
||||
선택적 플래그 두 가지로 Feishu API 사용량을 줄일 수 있습니다.
|
||||
|
||||
- `typingIndicator`(기본값 `true`): `false`이면 입력 중 반응 호출을 건너뜁니다.
|
||||
- `resolveSenderNames`(기본값 `true`): `false`이면 발신자 프로필 조회 호출을 건너뜁니다.
|
||||
|
||||
최상위 또는 계정별로 설정하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
typingIndicator: false,
|
||||
resolveSenderNames: false,
|
||||
accounts: {
|
||||
main: {
|
||||
appId: "cli_xxx",
|
||||
appSecret: "xxx",
|
||||
typingIndicator: true,
|
||||
resolveSenderNames: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3단계: 시작 + 테스트
|
||||
|
||||
### 1. Gateway 시작
|
||||
|
||||
```bash
|
||||
openclaw gateway
|
||||
```
|
||||
|
||||
### 2. 테스트 메시지 보내기
|
||||
|
||||
Feishu에서 봇을 찾아 메시지를 보내세요.
|
||||
|
||||
### 3. 페어링 승인
|
||||
|
||||
기본적으로 봇은 페어링 코드를 응답합니다. 이를 승인하세요.
|
||||
|
||||
```bash
|
||||
openclaw pairing approve feishu <CODE>
|
||||
```
|
||||
|
||||
승인 후에는 정상적으로 대화할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
## 개요
|
||||
|
||||
- **Feishu 봇 채널**: Gateway가 관리하는 Feishu 봇
|
||||
- **결정적 라우팅**: 응답은 항상 Feishu로 돌아감
|
||||
- **세션 격리**: DM은 메인 세션을 공유하고 그룹은 분리됨
|
||||
- **WebSocket 연결**: Feishu SDK를 통한 long connection, 공개 URL 불필요
|
||||
|
||||
---
|
||||
|
||||
## 액세스 제어
|
||||
|
||||
### 다이렉트 메시지
|
||||
|
||||
- **기본값**: `dmPolicy: "pairing"`(알 수 없는 사용자는 페어링 코드를 받음)
|
||||
- **페어링 승인**:
|
||||
|
||||
```bash
|
||||
openclaw pairing list feishu
|
||||
openclaw pairing approve feishu <CODE>
|
||||
```
|
||||
|
||||
- **allowlist 모드**: 허용된 Open ID로 `channels.feishu.allowFrom`을 설정
|
||||
|
||||
### 그룹 채팅
|
||||
|
||||
**1. 그룹 정책**(`channels.feishu.groupPolicy`):
|
||||
|
||||
- `"open"` = 그룹의 모든 사용자 허용
|
||||
- `"allowlist"` = `groupAllowFrom`만 허용
|
||||
- `"disabled"` = 그룹 메시지 비활성화
|
||||
|
||||
기본값: `allowlist`
|
||||
|
||||
**2. 멘션 요구 사항**(`channels.feishu.requireMention`, `channels.feishu.groups.<chat_id>.requireMention`으로 재정의 가능):
|
||||
|
||||
- 명시적 `true` = @mention 필요
|
||||
- 명시적 `false` = 멘션 없이 응답
|
||||
- 설정되지 않았고 `groupPolicy: "open"`인 경우 = 기본값 `false`
|
||||
- 설정되지 않았고 `groupPolicy`가 `"open"`이 아닌 경우 = 기본값 `true`
|
||||
|
||||
---
|
||||
|
||||
## 그룹 구성 예시
|
||||
|
||||
### 모든 그룹 허용, @mention 불필요(open 그룹의 기본값)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
groupPolicy: "open",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 모든 그룹 허용, 하지만 여전히 @mention 필요
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
groupPolicy: "open",
|
||||
requireMention: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 특정 그룹만 허용
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
groupPolicy: "allowlist",
|
||||
// Feishu group IDs (chat_id) look like: oc_xxx
|
||||
groupAllowFrom: ["oc_xxx", "oc_yyy"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 그룹에서 메시지를 보낼 수 있는 발신자 제한(sender allowlist)
|
||||
|
||||
그룹 자체를 허용하는 것 외에도, 해당 그룹의 **모든 메시지**는 발신자 open_id로 제한됩니다. `groups.<chat_id>.allowFrom`에 나열된 사용자만 메시지가 처리되며, 다른 멤버의 메시지는 무시됩니다(이는 `/reset`이나 `/new` 같은 제어 명령에만 적용되는 것이 아니라 전체 발신자 수준 게이팅입니다).
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["oc_xxx"],
|
||||
groups: {
|
||||
oc_xxx: {
|
||||
// Feishu user IDs (open_id) look like: ou_xxx
|
||||
allowFrom: ["ou_user1", "ou_user2"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<a id="get-groupuser-ids"></a>
|
||||
|
||||
## 그룹/사용자 ID 가져오기
|
||||
|
||||
### 그룹 ID(chat_id)
|
||||
|
||||
그룹 ID는 `oc_xxx` 형태입니다.
|
||||
|
||||
**방법 1(권장)**
|
||||
|
||||
1. Gateway를 시작하고 그룹에서 봇을 @mention합니다.
|
||||
2. `openclaw logs --follow`를 실행하고 `chat_id`를 찾습니다.
|
||||
|
||||
**방법 2**
|
||||
|
||||
Feishu API 디버거를 사용해 그룹 채팅을 나열합니다.
|
||||
|
||||
### 사용자 ID(open_id)
|
||||
|
||||
사용자 ID는 `ou_xxx` 형태입니다.
|
||||
|
||||
**방법 1(권장)**
|
||||
|
||||
1. Gateway를 시작하고 봇에 DM을 보냅니다.
|
||||
2. `openclaw logs --follow`를 실행하고 `open_id`를 찾습니다.
|
||||
|
||||
**방법 2**
|
||||
|
||||
사용자 Open ID는 페어링 요청에서 확인합니다.
|
||||
|
||||
```bash
|
||||
openclaw pairing list feishu
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 일반 명령
|
||||
|
||||
| 명령 | 설명 |
|
||||
| --------- | ----------------- |
|
||||
| `/status` | 봇 상태 표시 |
|
||||
| `/reset` | 세션 재설정 |
|
||||
| `/model` | 모델 표시/전환 |
|
||||
|
||||
> 참고: Feishu는 아직 기본 명령 메뉴를 지원하지 않으므로 명령은 텍스트로 보내야 합니다.
|
||||
|
||||
## Gateway 관리 명령
|
||||
|
||||
| 명령 | 설명 |
|
||||
| -------------------------- | ----------------------------- |
|
||||
| `openclaw gateway status` | Gateway 상태 표시 |
|
||||
| `openclaw gateway install` | Gateway 서비스 설치/시작 |
|
||||
| `openclaw gateway stop` | Gateway 서비스 중지 |
|
||||
| `openclaw gateway restart` | Gateway 서비스 재시작 |
|
||||
| `openclaw logs --follow` | Gateway 로그 추적 |
|
||||
|
||||
---
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 그룹 채팅에서 봇이 응답하지 않음
|
||||
|
||||
1. 봇이 그룹에 추가되어 있는지 확인합니다.
|
||||
2. 봇을 @mention했는지 확인합니다(기본 동작).
|
||||
3. `groupPolicy`가 `"disabled"`로 설정되지 않았는지 확인합니다.
|
||||
4. 로그를 확인합니다: `openclaw logs --follow`
|
||||
|
||||
### 봇이 메시지를 수신하지 않음
|
||||
|
||||
1. 앱이 게시되고 승인되었는지 확인합니다.
|
||||
2. 이벤트 구독에 `im.message.receive_v1`이 포함되어 있는지 확인합니다.
|
||||
3. **long connection**이 활성화되어 있는지 확인합니다.
|
||||
4. 앱 권한이 완전한지 확인합니다.
|
||||
5. Gateway가 실행 중인지 확인합니다: `openclaw gateway status`
|
||||
6. 로그를 확인합니다: `openclaw logs --follow`
|
||||
|
||||
### App Secret 유출
|
||||
|
||||
1. Feishu Open Platform에서 App Secret을 재설정합니다.
|
||||
2. config에서 App Secret을 업데이트합니다.
|
||||
3. Gateway를 재시작합니다.
|
||||
|
||||
### 메시지 전송 실패
|
||||
|
||||
1. 앱에 `im:message:send_as_bot` 권한이 있는지 확인합니다.
|
||||
2. 앱이 게시되었는지 확인합니다.
|
||||
3. 자세한 오류는 로그를 확인합니다.
|
||||
|
||||
---
|
||||
|
||||
## 고급 구성
|
||||
|
||||
### 여러 계정
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
defaultAccount: "main",
|
||||
accounts: {
|
||||
main: {
|
||||
appId: "cli_xxx",
|
||||
appSecret: "xxx",
|
||||
name: "Primary bot",
|
||||
},
|
||||
backup: {
|
||||
appId: "cli_yyy",
|
||||
appSecret: "yyy",
|
||||
name: "Backup bot",
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`defaultAccount`는 아웃바운드 API가 `accountId`를 명시적으로 지정하지 않을 때 어떤 Feishu 계정을 사용할지 제어합니다.
|
||||
|
||||
### 메시지 제한
|
||||
|
||||
- `textChunkLimit`: 아웃바운드 텍스트 청크 크기(기본값: 2000자)
|
||||
- `mediaMaxMb`: 미디어 업로드/다운로드 제한(기본값: 30MB)
|
||||
|
||||
### 스트리밍
|
||||
|
||||
Feishu는 인터랙티브 카드를 통한 스트리밍 응답을 지원합니다. 활성화하면 봇은 텍스트를 생성하면서 카드를 업데이트합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
streaming: true, // enable streaming card output (default true)
|
||||
blockStreaming: true, // enable block-level streaming (default true)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
전체 응답이 준비된 후 전송하려면 `streaming: false`로 설정하세요.
|
||||
|
||||
### ACP 세션
|
||||
|
||||
Feishu는 다음에 대해 ACP를 지원합니다.
|
||||
|
||||
- DM
|
||||
- 그룹 주제 대화
|
||||
|
||||
Feishu ACP는 텍스트 명령 기반으로 동작합니다. 기본 slash-command 메뉴는 없으므로 대화에서 `/acp ...` 메시지를 직접 사용하세요.
|
||||
|
||||
#### 영구 ACP 바인딩
|
||||
|
||||
최상위 타입 지정 ACP 바인딩을 사용해 Feishu DM 또는 주제 대화를 영구 ACP 세션에 고정할 수 있습니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: {
|
||||
agent: "codex",
|
||||
backend: "acpx",
|
||||
mode: "persistent",
|
||||
cwd: "/workspace/openclaw",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "feishu",
|
||||
accountId: "default",
|
||||
peer: { kind: "direct", id: "ou_1234567890" },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "feishu",
|
||||
accountId: "default",
|
||||
peer: { kind: "group", id: "oc_group_chat:topic:om_topic_root" },
|
||||
},
|
||||
acp: { label: "codex-feishu-topic" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
#### 채팅에서 스레드 바인딩 ACP 생성
|
||||
|
||||
Feishu DM 또는 주제 대화에서 ACP 세션을 그 자리에서 생성하고 바인딩할 수 있습니다.
|
||||
|
||||
```text
|
||||
/acp spawn codex --thread here
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `--thread here`는 DM과 Feishu 주제에서 작동합니다.
|
||||
- 바인딩된 DM/주제의 후속 메시지는 해당 ACP 세션으로 직접 라우팅됩니다.
|
||||
- v1은 일반 비주제 그룹 채팅을 대상으로 하지 않습니다.
|
||||
|
||||
### 멀티 에이전트 라우팅
|
||||
|
||||
`bindings`를 사용해 Feishu DM 또는 그룹을 서로 다른 agent로 라우팅하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{ id: "main" },
|
||||
{
|
||||
id: "clawd-fan",
|
||||
workspace: "/home/user/clawd-fan",
|
||||
agentDir: "/home/user/.openclaw/agents/clawd-fan/agent",
|
||||
},
|
||||
{
|
||||
id: "clawd-xi",
|
||||
workspace: "/home/user/clawd-xi",
|
||||
agentDir: "/home/user/.openclaw/agents/clawd-xi/agent",
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
agentId: "main",
|
||||
match: {
|
||||
channel: "feishu",
|
||||
peer: { kind: "direct", id: "ou_xxx" },
|
||||
},
|
||||
},
|
||||
{
|
||||
agentId: "clawd-fan",
|
||||
match: {
|
||||
channel: "feishu",
|
||||
peer: { kind: "direct", id: "ou_yyy" },
|
||||
},
|
||||
},
|
||||
{
|
||||
agentId: "clawd-xi",
|
||||
match: {
|
||||
channel: "feishu",
|
||||
peer: { kind: "group", id: "oc_zzz" },
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
라우팅 필드:
|
||||
|
||||
- `match.channel`: `"feishu"`
|
||||
- `match.peer.kind`: `"direct"` 또는 `"group"`
|
||||
- `match.peer.id`: 사용자 Open ID(`ou_xxx`) 또는 그룹 ID(`oc_xxx`)
|
||||
|
||||
조회 팁은 [그룹/사용자 ID 가져오기](#get-groupuser-ids)를 참조하세요.
|
||||
|
||||
---
|
||||
|
||||
## 구성 참조
|
||||
|
||||
전체 구성: [Gateway configuration](/gateway/configuration)
|
||||
|
||||
주요 옵션:
|
||||
|
||||
| 설정 | 설명 | 기본값 |
|
||||
| ------------------------------------------------- | --------------------------------------- | ---------------- |
|
||||
| `channels.feishu.enabled` | 채널 활성화/비활성화 | `true` |
|
||||
| `channels.feishu.domain` | API 도메인(`feishu` 또는 `lark`) | `feishu` |
|
||||
| `channels.feishu.connectionMode` | 이벤트 전송 모드 | `websocket` |
|
||||
| `channels.feishu.defaultAccount` | 아웃바운드 라우팅용 기본 계정 ID | `default` |
|
||||
| `channels.feishu.verificationToken` | webhook 모드에 필요 | - |
|
||||
| `channels.feishu.encryptKey` | webhook 모드에 필요 | - |
|
||||
| `channels.feishu.webhookPath` | webhook 라우트 경로 | `/feishu/events` |
|
||||
| `channels.feishu.webhookHost` | webhook 바인드 호스트 | `127.0.0.1` |
|
||||
| `channels.feishu.webhookPort` | webhook 바인드 포트 | `3000` |
|
||||
| `channels.feishu.accounts.<id>.appId` | App ID | - |
|
||||
| `channels.feishu.accounts.<id>.appSecret` | App Secret | - |
|
||||
| `channels.feishu.accounts.<id>.domain` | 계정별 API 도메인 재정의 | `feishu` |
|
||||
| `channels.feishu.dmPolicy` | DM 정책 | `pairing` |
|
||||
| `channels.feishu.allowFrom` | DM allowlist(open_id 목록) | - |
|
||||
| `channels.feishu.groupPolicy` | 그룹 정책 | `allowlist` |
|
||||
| `channels.feishu.groupAllowFrom` | 그룹 allowlist | - |
|
||||
| `channels.feishu.requireMention` | 기본 @mention 필요 여부 | conditional |
|
||||
| `channels.feishu.groups.<chat_id>.requireMention` | 그룹별 @mention 필요 여부 재정의 | inherited |
|
||||
| `channels.feishu.groups.<chat_id>.enabled` | 그룹 활성화 | `true` |
|
||||
| `channels.feishu.textChunkLimit` | 메시지 청크 크기 | `2000` |
|
||||
| `channels.feishu.mediaMaxMb` | 미디어 크기 제한 | `30` |
|
||||
| `channels.feishu.streaming` | 스트리밍 카드 출력 활성화 | `true` |
|
||||
| `channels.feishu.blockStreaming` | 블록 스트리밍 활성화 | `true` |
|
||||
|
||||
---
|
||||
|
||||
## dmPolicy 참조
|
||||
|
||||
| 값 | 동작 |
|
||||
| ------------- | --------------------------------------------------------------- |
|
||||
| `"pairing"` | **기본값.** 알 수 없는 사용자는 페어링 코드를 받으며, 승인이 필요함 |
|
||||
| `"allowlist"` | `allowFrom`에 있는 사용자만 대화 가능 |
|
||||
| `"open"` | 모든 사용자 허용(`allowFrom`에 `"*"` 필요) |
|
||||
| `"disabled"` | DM 비활성화 |
|
||||
|
||||
---
|
||||
|
||||
## 지원되는 메시지 유형
|
||||
|
||||
### 수신
|
||||
|
||||
- ✅ 텍스트
|
||||
- ✅ 리치 텍스트(post)
|
||||
- ✅ 이미지
|
||||
- ✅ 파일
|
||||
- ✅ 오디오
|
||||
- ✅ 비디오/미디어
|
||||
- ✅ 스티커
|
||||
|
||||
### 전송
|
||||
|
||||
- ✅ 텍스트
|
||||
- ✅ 이미지
|
||||
- ✅ 파일
|
||||
- ✅ 오디오
|
||||
- ✅ 비디오/미디어
|
||||
- ✅ 인터랙티브 카드
|
||||
- ⚠️ 리치 텍스트(post 스타일 서식 및 카드, 임의의 Feishu 작성 기능 전체는 아님)
|
||||
|
||||
### 스레드 및 응답
|
||||
|
||||
- ✅ 인라인 응답
|
||||
- ✅ Feishu가 `reply_in_thread`를 노출하는 경우 주제 스레드 응답
|
||||
- ✅ 스레드/주제 메시지에 응답할 때 미디어 응답도 스레드 인식을 유지함
|
||||
|
||||
## Drive 댓글
|
||||
|
||||
사용자가 Feishu Drive 문서(Docs, Sheets 등)에 댓글을 추가하면 Feishu가 agent를 트리거할 수 있습니다. agent는 댓글 텍스트, 문서 컨텍스트, 댓글 스레드를 받아 스레드 내에서 응답하거나 문서를 수정할 수 있습니다.
|
||||
|
||||
요구 사항:
|
||||
|
||||
- Feishu 앱 이벤트 구독 설정에서 `drive.notice.comment_add_v1`을 구독해야 합니다
|
||||
(기존 `im.message.receive_v1`과 함께)
|
||||
- Drive 도구는 기본적으로 활성화되어 있으며, `channels.feishu.tools.drive: false`로 비활성화할 수 있습니다
|
||||
|
||||
`feishu_drive` 도구는 다음 댓글 작업을 제공합니다.
|
||||
|
||||
| 작업 | 설명 |
|
||||
| ---------------------- | ----------------------------------- |
|
||||
| `list_comments` | 문서의 댓글 목록 표시 |
|
||||
| `list_comment_replies` | 댓글 스레드의 응답 목록 표시 |
|
||||
| `add_comment` | 새 최상위 댓글 추가 |
|
||||
| `reply_comment` | 기존 댓글 스레드에 응답 |
|
||||
|
||||
agent가 Drive 댓글 이벤트를 처리할 때 다음을 받습니다.
|
||||
|
||||
- 댓글 텍스트와 발신자
|
||||
- 문서 메타데이터(제목, 유형, URL)
|
||||
- 스레드 내 응답을 위한 댓글 스레드 컨텍스트
|
||||
|
||||
문서를 수정한 후 agent는 댓글 작성자에게 알리기 위해 `feishu_drive.reply_comment`를 사용하고, 중복 전송을 피하기 위해 정확히 `NO_REPLY` / `no_reply` 무음 토큰을 출력하도록 안내됩니다.
|
||||
|
||||
## 런타임 작업 표면
|
||||
|
||||
현재 Feishu는 다음 런타임 작업을 노출합니다.
|
||||
|
||||
- `send`
|
||||
- `read`
|
||||
- `edit`
|
||||
- `thread-reply`
|
||||
- `pin`
|
||||
- `list-pins`
|
||||
- `unpin`
|
||||
- `member-info`
|
||||
- `channel-info`
|
||||
- `channel-list`
|
||||
- config에서 반응이 활성화된 경우 `react` 및 `reactions`
|
||||
- `feishu_drive` 댓글 작업: `list_comments`, `list_comment_replies`, `add_comment`, `reply_comment`
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지의 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 하드닝
|
||||
277
docs/ko/channels/googlechat.md
Normal file
277
docs/ko/channels/googlechat.md
Normal file
@ -0,0 +1,277 @@
|
||||
---
|
||||
read_when:
|
||||
- Google Chat 채널 기능을 작업할 때
|
||||
summary: Google Chat 앱 지원 상태, 기능 및 구성
|
||||
title: Google Chat
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:34:59Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 570894ed798dd0b9ba42806b050927216379a1228fcd2f96de565bc8a4ac7c2c
|
||||
source_path: channels/googlechat.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Google Chat (Chat API)
|
||||
|
||||
상태: Google Chat API 웹훅을 통한 DM 및 스페이스 지원 준비 완료(HTTP 전용).
|
||||
|
||||
## 빠른 설정(초보자용)
|
||||
|
||||
1. Google Cloud 프로젝트를 만들고 **Google Chat API**를 사용 설정합니다.
|
||||
- 이동: [Google Chat API Credentials](https://console.cloud.google.com/apis/api/chat.googleapis.com/credentials)
|
||||
- 아직 활성화되지 않았다면 API를 활성화합니다.
|
||||
2. **Service Account**를 생성합니다.
|
||||
- **Create Credentials** > **Service Account**를 누릅니다.
|
||||
- 원하는 이름을 지정합니다(예: `openclaw-chat`).
|
||||
- 권한은 비워 둡니다(**Continue** 누름).
|
||||
- 액세스 권한이 있는 주체도 비워 둡니다(**Done** 누름).
|
||||
3. **JSON Key**를 생성하고 다운로드합니다.
|
||||
- 서비스 계정 목록에서 방금 만든 계정을 클릭합니다.
|
||||
- **Keys** 탭으로 이동합니다.
|
||||
- **Add Key** > **Create new key**를 클릭합니다.
|
||||
- **JSON**을 선택하고 **Create**를 누릅니다.
|
||||
4. 다운로드한 JSON 파일을 게이트웨이 호스트에 저장합니다(예: `~/.openclaw/googlechat-service-account.json`).
|
||||
5. [Google Cloud Console Chat Configuration](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat)에서 Google Chat 앱을 생성합니다.
|
||||
- **Application info**를 입력합니다.
|
||||
- **App name**: (예: `OpenClaw`)
|
||||
- **Avatar URL**: (예: `https://openclaw.ai/logo.png`)
|
||||
- **Description**: (예: `개인 AI 비서`)
|
||||
- **Interactive features**를 활성화합니다.
|
||||
- **Functionality**에서 **Join spaces and group conversations**를 선택합니다.
|
||||
- **Connection settings**에서 **HTTP endpoint URL**을 선택합니다.
|
||||
- **Triggers**에서 **Use a common HTTP endpoint URL for all triggers**를 선택하고, 이를 게이트웨이의 공개 URL 뒤에 `/googlechat`를 붙인 값으로 설정합니다.
|
||||
- _팁: 게이트웨이의 공개 URL을 찾으려면 `openclaw status`를 실행하세요._
|
||||
- **Visibility**에서 **Make this Chat app available to specific people and groups in <Your Domain>**를 선택합니다.
|
||||
- 텍스트 상자에 이메일 주소를 입력합니다(예: `user@example.com`).
|
||||
- 하단의 **Save**를 클릭합니다.
|
||||
6. **앱 상태를 활성화합니다**.
|
||||
- 저장 후 **페이지를 새로고침**합니다.
|
||||
- **App status** 섹션을 찾습니다(보통 저장 후 상단 또는 하단에 표시됨).
|
||||
- 상태를 **Live - available to users**로 변경합니다.
|
||||
- 다시 **Save**를 클릭합니다.
|
||||
7. 서비스 계정 경로와 웹훅 audience로 OpenClaw를 구성합니다.
|
||||
- Env: `GOOGLE_CHAT_SERVICE_ACCOUNT_FILE=/path/to/service-account.json`
|
||||
- 또는 config: `channels.googlechat.serviceAccountFile: "/path/to/service-account.json"`.
|
||||
8. 웹훅 audience 유형과 값을 설정합니다(Chat 앱 구성과 일치해야 함).
|
||||
9. 게이트웨이를 시작합니다. 그러면 Google Chat이 웹훅 경로로 POST 요청을 보냅니다.
|
||||
|
||||
## Google Chat에 추가하기
|
||||
|
||||
게이트웨이가 실행 중이고 이메일이 가시성 목록에 추가되어 있다면 다음을 수행합니다.
|
||||
|
||||
1. [Google Chat](https://chat.google.com/)으로 이동합니다.
|
||||
2. **Direct Messages** 옆의 **+**(플러스) 아이콘을 클릭합니다.
|
||||
3. 검색창(평소 사람을 추가하는 위치)에 Google Cloud Console에서 구성한 **App name**을 입력합니다.
|
||||
- **참고**: 이 봇은 비공개 앱이므로 "Marketplace" 탐색 목록에 _표시되지 않습니다_. 반드시 이름으로 검색해야 합니다.
|
||||
4. 결과에서 봇을 선택합니다.
|
||||
5. **Add** 또는 **Chat**을 클릭해 1:1 대화를 시작합니다.
|
||||
6. 비서를 트리거하려면 "Hello"를 보내세요.
|
||||
|
||||
## 공개 URL(웹훅 전용)
|
||||
|
||||
Google Chat 웹훅은 공개 HTTPS 엔드포인트가 필요합니다. 보안을 위해 인터넷에는 **`/googlechat` 경로만 노출**하세요. OpenClaw 대시보드와 기타 민감한 엔드포인트는 사설 네트워크에 유지하세요.
|
||||
|
||||
### 옵션 A: Tailscale Funnel(권장)
|
||||
|
||||
비공개 대시보드에는 Tailscale Serve를 사용하고, 공개 웹훅 경로에는 Funnel을 사용합니다. 이렇게 하면 `/`는 비공개로 유지하면서 `/googlechat`만 노출할 수 있습니다.
|
||||
|
||||
1. **게이트웨이가 어떤 주소에 바인딩되어 있는지 확인합니다.**
|
||||
|
||||
```bash
|
||||
ss -tlnp | grep 18789
|
||||
```
|
||||
|
||||
IP 주소를 확인합니다(예: `127.0.0.1`, `0.0.0.0`, 또는 `100.x.x.x` 같은 Tailscale IP).
|
||||
|
||||
2. **대시보드를 tailnet 전용으로 노출합니다(포트 8443).**
|
||||
|
||||
```bash
|
||||
# localhost(127.0.0.1 또는 0.0.0.0)에 바인딩된 경우:
|
||||
tailscale serve --bg --https 8443 http://127.0.0.1:18789
|
||||
|
||||
# Tailscale IP 전용(예: 100.106.161.80)에 바인딩된 경우:
|
||||
tailscale serve --bg --https 8443 http://100.106.161.80:18789
|
||||
```
|
||||
|
||||
3. **웹훅 경로만 공개적으로 노출합니다.**
|
||||
|
||||
```bash
|
||||
# localhost(127.0.0.1 또는 0.0.0.0)에 바인딩된 경우:
|
||||
tailscale funnel --bg --set-path /googlechat http://127.0.0.1:18789/googlechat
|
||||
|
||||
# Tailscale IP 전용(예: 100.106.161.80)에 바인딩된 경우:
|
||||
tailscale funnel --bg --set-path /googlechat http://100.106.161.80:18789/googlechat
|
||||
```
|
||||
|
||||
4. **노드에 Funnel 액세스를 승인합니다.**
|
||||
프롬프트가 표시되면 출력에 나온 승인 URL을 방문해 tailnet 정책에서 이 노드에 대한 Funnel을 활성화합니다.
|
||||
|
||||
5. **구성을 확인합니다.**
|
||||
|
||||
```bash
|
||||
tailscale serve status
|
||||
tailscale funnel status
|
||||
```
|
||||
|
||||
공개 웹훅 URL은 다음과 같습니다.
|
||||
`https://<node-name>.<tailnet>.ts.net/googlechat`
|
||||
|
||||
비공개 대시보드는 tailnet 전용으로 유지됩니다.
|
||||
`https://<node-name>.<tailnet>.ts.net:8443/`
|
||||
|
||||
Google Chat 앱 구성에는 공개 URL(`:8443` 제외)을 사용하세요.
|
||||
|
||||
> 참고: 이 구성은 재부팅 후에도 유지됩니다. 나중에 제거하려면 `tailscale funnel reset` 및 `tailscale serve reset`을 실행하세요.
|
||||
|
||||
### 옵션 B: 리버스 프록시(Caddy)
|
||||
|
||||
Caddy 같은 리버스 프록시를 사용하는 경우 특정 경로만 프록시하세요.
|
||||
|
||||
```caddy
|
||||
your-domain.com {
|
||||
reverse_proxy /googlechat* localhost:18789
|
||||
}
|
||||
```
|
||||
|
||||
이 구성에서는 `your-domain.com/`에 대한 요청은 무시되거나 404를 반환하고, `your-domain.com/googlechat`만 안전하게 OpenClaw로 라우팅됩니다.
|
||||
|
||||
### 옵션 C: Cloudflare Tunnel
|
||||
|
||||
터널의 ingress 규칙을 구성해 웹훅 경로만 라우팅하세요.
|
||||
|
||||
- **Path**: `/googlechat` -> `http://localhost:18789/googlechat`
|
||||
- **Default Rule**: HTTP 404 (Not Found)
|
||||
|
||||
## 작동 방식
|
||||
|
||||
1. Google Chat이 게이트웨이로 웹훅 POST를 보냅니다. 각 요청에는 `Authorization: Bearer <token>` 헤더가 포함됩니다.
|
||||
- OpenClaw는 헤더가 있을 때 전체 웹훅 본문을 읽고 파싱하기 전에 bearer 인증을 검증합니다.
|
||||
- 본문에 `authorizationEventObject.systemIdToken`이 포함된 Google Workspace Add-on 요청은 더 엄격한 사전 인증 본문 예산을 통해 지원됩니다.
|
||||
2. OpenClaw는 구성된 `audienceType` 및 `audience`에 대해 토큰을 검증합니다.
|
||||
- `audienceType: "app-url"` → audience는 HTTPS 웹훅 URL입니다.
|
||||
- `audienceType: "project-number"` → audience는 Cloud 프로젝트 번호입니다.
|
||||
3. 메시지는 스페이스 기준으로 라우팅됩니다.
|
||||
- DM은 세션 키 `agent:<agentId>:googlechat:direct:<spaceId>`를 사용합니다.
|
||||
- 스페이스는 세션 키 `agent:<agentId>:googlechat:group:<spaceId>`를 사용합니다.
|
||||
4. DM 액세스는 기본적으로 pairing입니다. 알 수 없는 발신자에게는 pairing 코드가 전송되며, 다음으로 승인합니다.
|
||||
- `openclaw pairing approve googlechat <code>`
|
||||
5. 그룹 스페이스는 기본적으로 @멘션이 필요합니다. 멘션 감지에 앱의 사용자 이름이 필요하면 `botUser`를 사용하세요.
|
||||
|
||||
## 대상
|
||||
|
||||
전송 및 허용 목록에는 다음 식별자를 사용하세요.
|
||||
|
||||
- 다이렉트 메시지: `users/<userId>`(권장).
|
||||
- 원시 이메일 `name@example.com`은 변경 가능하며 `channels.googlechat.dangerouslyAllowNameMatching: true`일 때만 다이렉트 허용 목록 일치에 사용됩니다.
|
||||
- 사용 중단 예정: `users/<email>`은 이메일 허용 목록이 아니라 사용자 ID로 처리됩니다.
|
||||
- 스페이스: `spaces/<spaceId>`.
|
||||
|
||||
## 주요 구성
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
googlechat: {
|
||||
enabled: true,
|
||||
serviceAccountFile: "/path/to/service-account.json",
|
||||
// 또는 serviceAccountRef: { source: "file", provider: "filemain", id: "/channels/googlechat/serviceAccount" }
|
||||
audienceType: "app-url",
|
||||
audience: "https://gateway.example.com/googlechat",
|
||||
webhookPath: "/googlechat",
|
||||
botUser: "users/1234567890", // 선택 사항; 멘션 감지에 도움
|
||||
dm: {
|
||||
policy: "pairing",
|
||||
allowFrom: ["users/1234567890"],
|
||||
},
|
||||
groupPolicy: "allowlist",
|
||||
groups: {
|
||||
"spaces/AAAA": {
|
||||
allow: true,
|
||||
requireMention: true,
|
||||
users: ["users/1234567890"],
|
||||
systemPrompt: "짧게만 답변하세요.",
|
||||
},
|
||||
},
|
||||
actions: { reactions: true },
|
||||
typingIndicator: "message",
|
||||
mediaMaxMb: 20,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 서비스 계정 자격 증명은 `serviceAccount`(JSON 문자열)로 인라인 전달할 수도 있습니다.
|
||||
- `serviceAccountRef`도 지원됩니다(env/file SecretRef). `channels.googlechat.accounts.<id>.serviceAccountRef` 아래 계정별 참조도 포함됩니다.
|
||||
- `webhookPath`가 설정되지 않은 경우 기본 웹훅 경로는 `/googlechat`입니다.
|
||||
- `dangerouslyAllowNameMatching`은 허용 목록에 대해 변경 가능한 이메일 주체 일치를 다시 활성화합니다(비상 호환 모드).
|
||||
- `actions.reactions`가 활성화되어 있으면 반응은 `reactions` 도구 및 `channels action`을 통해 사용할 수 있습니다.
|
||||
- 메시지 작업은 텍스트용 `send`와 명시적 첨부파일 전송용 `upload-file`을 노출합니다. `upload-file`은 `media` / `filePath` / `path`와 선택적 `message`, `filename`, 스레드 대상을 받습니다.
|
||||
- `typingIndicator`는 `none`, `message`(기본값), `reaction`을 지원합니다(`reaction`은 사용자 OAuth 필요).
|
||||
- 첨부파일은 Chat API를 통해 다운로드되어 미디어 파이프라인에 저장됩니다(크기는 `mediaMaxMb`로 제한).
|
||||
|
||||
시크릿 참조 세부 정보: [Secrets Management](/gateway/secrets).
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 405 Method Not Allowed
|
||||
|
||||
Google Cloud Logs Explorer에 다음과 같은 오류가 표시되는 경우:
|
||||
|
||||
```
|
||||
status code: 405, reason phrase: HTTP error response: HTTP/1.1 405 Method Not Allowed
|
||||
```
|
||||
|
||||
이는 웹훅 핸들러가 등록되지 않았음을 의미합니다. 일반적인 원인은 다음과 같습니다.
|
||||
|
||||
1. **채널이 구성되지 않음**: config에 `channels.googlechat` 섹션이 없습니다. 다음으로 확인하세요.
|
||||
|
||||
```bash
|
||||
openclaw config get channels.googlechat
|
||||
```
|
||||
|
||||
"Config path not found"가 반환되면 구성을 추가하세요([주요 구성](#config-highlights) 참조).
|
||||
|
||||
2. **플러그인이 활성화되지 않음**: 플러그인 상태를 확인하세요.
|
||||
|
||||
```bash
|
||||
openclaw plugins list | grep googlechat
|
||||
```
|
||||
|
||||
"disabled"로 표시되면 config에 `plugins.entries.googlechat.enabled: true`를 추가하세요.
|
||||
|
||||
3. **게이트웨이를 재시작하지 않음**: config를 추가한 후 게이트웨이를 재시작하세요.
|
||||
|
||||
```bash
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
채널이 실행 중인지 확인합니다.
|
||||
|
||||
```bash
|
||||
openclaw channels status
|
||||
# 다음이 표시되어야 함: Google Chat default: enabled, configured, ...
|
||||
```
|
||||
|
||||
### 기타 문제
|
||||
|
||||
- 인증 오류 또는 누락된 audience 구성을 확인하려면 `openclaw channels status --probe`를 확인하세요.
|
||||
- 메시지가 도착하지 않으면 Chat 앱의 웹훅 URL과 이벤트 구독을 확인하세요.
|
||||
- 멘션 게이팅 때문에 응답이 차단되면 `botUser`를 앱의 사용자 리소스 이름으로 설정하고 `requireMention`을 확인하세요.
|
||||
- 요청이 게이트웨이에 도달하는지 확인하려면 테스트 메시지를 보내면서 `openclaw logs --follow`를 사용하세요.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- [Gateway configuration](/gateway/configuration)
|
||||
- [Security](/gateway/security)
|
||||
- [Reactions](/tools/reactions)
|
||||
|
||||
## 관련
|
||||
|
||||
- [Channels Overview](/channels) — 지원되는 모든 채널
|
||||
- [Pairing](/channels/pairing) — DM 인증 및 pairing 흐름
|
||||
- [Groups](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [Channel Routing](/channels/channel-routing) — 메시지의 세션 라우팅
|
||||
- [Security](/gateway/security) — 액세스 모델 및 보안 강화
|
||||
91
docs/ko/channels/group-messages.md
Normal file
91
docs/ko/channels/group-messages.md
Normal file
@ -0,0 +1,91 @@
|
||||
---
|
||||
read_when:
|
||||
- 그룹 메시지 규칙 또는 멘션을 변경할 때
|
||||
summary: WhatsApp 그룹 메시지 처리의 동작 및 구성(`mentionPatterns`는 여러 표면에서 공유됨)
|
||||
title: 그룹 메시지
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:00Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 2543be5bc4c6f188f955df580a6fef585ecbfc1be36ade5d34b1a9157e021bc5
|
||||
source_path: channels/group-messages.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 그룹 메시지 (WhatsApp web 채널)
|
||||
|
||||
목표: Clawd가 WhatsApp 그룹에 참여하고, 핑을 받았을 때만 활성화되며, 해당 스레드를 개인 DM 세션과 분리해서 유지하도록 합니다.
|
||||
|
||||
참고: `agents.list[].groupChat.mentionPatterns`는 이제 Telegram/Discord/Slack/iMessage에서도 사용됩니다. 이 문서는 WhatsApp 전용 동작에 중점을 둡니다. 다중 에이전트 구성에서는 에이전트별로 `agents.list[].groupChat.mentionPatterns`를 설정하세요(또는 전역 폴백으로 `messages.groupChat.mentionPatterns`를 사용하세요).
|
||||
|
||||
## 현재 구현 (2025-12-03)
|
||||
|
||||
- 활성화 모드: `mention`(기본값) 또는 `always`. `mention`은 핑이 필요합니다(실제 WhatsApp @멘션 via `mentionedJids`, 안전한 정규식 패턴, 또는 텍스트 내 어디에나 있는 봇의 E.164). `always`는 모든 메시지에서 에이전트를 활성화하지만, 의미 있는 가치를 더할 수 있을 때만 응답해야 하며, 그렇지 않으면 정확히 무음 토큰 `NO_REPLY` / `no_reply`를 반환합니다. 기본값은 config의 `channels.whatsapp.groups`에서 설정할 수 있고, 그룹별로 `/activation`으로 재정의할 수 있습니다. `channels.whatsapp.groups`가 설정되면 그룹 허용 목록으로도 작동합니다(모두 허용하려면 `"*"` 포함).
|
||||
- 그룹 정책: `channels.whatsapp.groupPolicy`는 그룹 메시지 수락 여부를 제어합니다(`open|disabled|allowlist`). `allowlist`는 `channels.whatsapp.groupAllowFrom`를 사용합니다(폴백: 명시적 `channels.whatsapp.allowFrom`). 기본값은 `allowlist`입니다(발신자를 추가할 때까지 차단됨).
|
||||
- 그룹별 세션: 세션 키는 `agent:<agentId>:whatsapp:group:<jid>` 형식이므로 `/verbose on` 또는 `/think high` 같은 명령(독립 실행형 메시지로 전송)이 해당 그룹 범위에만 적용됩니다. 개인 DM 상태는 영향을 받지 않습니다. 그룹 스레드에서는 Heartbeat가 건너뛰어집니다.
|
||||
- 컨텍스트 주입: 실행을 트리거하지 않은 **보류 중인 전용** 그룹 메시지(기본값 50개)는 `[Chat messages since your last reply - for context]` 아래에 접두사로 추가되고, 트리거한 줄은 `[Current message - respond to this]` 아래에 들어갑니다. 이미 세션에 있는 메시지는 다시 주입되지 않습니다.
|
||||
- 발신자 표시: 이제 모든 그룹 배치의 끝에는 `[from: Sender Name (+E164)]`가 추가되어 Pi가 누가 말하는지 알 수 있습니다.
|
||||
- 일시적/view-once: 텍스트/멘션을 추출하기 전에 이를 언래핑하므로, 그 안의 핑도 여전히 트리거됩니다.
|
||||
- 그룹 시스템 프롬프트: 그룹 세션의 첫 턴(및 `/activation`이 모드를 변경할 때마다)에 시스템 프롬프트에 다음과 같은 짧은 설명을 주입합니다. `You are replying inside the WhatsApp group "<subject>". Group members: Alice (+44...), Bob (+43...), … Activation: trigger-only … Address the specific sender noted in the message context.` 메타데이터를 사용할 수 없는 경우에도 에이전트에 그룹 채팅이라는 점은 알려줍니다.
|
||||
|
||||
## 구성 예시 (WhatsApp)
|
||||
|
||||
WhatsApp가 텍스트 본문에서 시각적 `@`를 제거하더라도 표시 이름 핑이 작동하도록 `~/.openclaw/openclaw.json`에 `groupChat` 블록을 추가하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groups: {
|
||||
"*": { requireMention: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "main",
|
||||
groupChat: {
|
||||
historyLimit: 50,
|
||||
mentionPatterns: ["@?openclaw", "\\+?15555550123"],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 정규식은 대소문자를 구분하지 않으며, 다른 config 정규식 표면과 동일한 safe-regex 가드레일을 사용합니다. 잘못된 패턴과 안전하지 않은 중첩 반복은 무시됩니다.
|
||||
- 누군가 연락처를 탭하면 WhatsApp는 여전히 `mentionedJids`를 통해 정식 멘션을 보내므로, 번호 폴백은 거의 필요하지 않지만 유용한 안전장치입니다.
|
||||
|
||||
### 활성화 명령(소유자 전용)
|
||||
|
||||
그룹 채팅 명령 사용:
|
||||
|
||||
- `/activation mention`
|
||||
- `/activation always`
|
||||
|
||||
이것은 소유자 번호(`channels.whatsapp.allowFrom`에서 가져오며, 설정되지 않은 경우 봇 자신의 E.164)만 변경할 수 있습니다. 현재 활성화 모드를 보려면 그룹에서 `/status`를 독립 실행형 메시지로 보내세요.
|
||||
|
||||
## 사용 방법
|
||||
|
||||
1. WhatsApp 계정(OpenClaw를 실행 중인 계정)을 그룹에 추가합니다.
|
||||
2. `@openclaw …`라고 말하거나(또는 번호를 포함하거나) 하세요. `groupPolicy: "open"`으로 설정하지 않는 한 허용 목록에 있는 발신자만 이를 트리거할 수 있습니다.
|
||||
3. 에이전트 프롬프트에는 최근 그룹 컨텍스트와 끝의 `[from: …]` 마커가 포함되므로 올바른 사람에게 응답할 수 있습니다.
|
||||
4. 세션 수준 지시문(`/verbose on`, `/think high`, `/new` 또는 `/reset`, `/compact`)은 해당 그룹의 세션에만 적용됩니다. 등록되도록 독립 실행형 메시지로 보내세요. 개인 DM 세션은 독립적으로 유지됩니다.
|
||||
|
||||
## 테스트 / 검증
|
||||
|
||||
- 수동 스모크 테스트:
|
||||
- 그룹에서 `@openclaw` 핑을 보내고 발신자 이름을 참조하는 응답을 확인합니다.
|
||||
- 두 번째 핑을 보내고 기록 블록이 포함되었다가 다음 턴에서 지워지는지 확인합니다.
|
||||
- gateway 로그(`--verbose`로 실행)를 확인하여 `from: <groupJid>` 및 `[from: …]` 접미사를 표시하는 `inbound web message` 항목을 확인합니다.
|
||||
|
||||
## 알려진 고려 사항
|
||||
|
||||
- 그룹에서 불필요하게 시끄러운 브로드캐스트를 방지하기 위해 Heartbeat는 의도적으로 건너뜁니다.
|
||||
- 에코 억제는 결합된 배치 문자열을 사용합니다. 멘션 없이 동일한 텍스트를 두 번 보내면 첫 번째만 응답을 받습니다.
|
||||
- 세션 저장소 항목은 세션 저장소(기본값 `~/.openclaw/agents/<agentId>/sessions/sessions.json`)에 `agent:<agentId>:whatsapp:group:<jid>`로 표시됩니다. 항목이 없다는 것은 해당 그룹이 아직 실행을 트리거하지 않았다는 의미일 뿐입니다.
|
||||
- 그룹의 입력 중 표시기는 `agents.defaults.typingMode`를 따릅니다(기본값: 멘션되지 않은 경우 `message`).
|
||||
417
docs/ko/channels/groups.md
Normal file
417
docs/ko/channels/groups.md
Normal file
@ -0,0 +1,417 @@
|
||||
---
|
||||
read_when:
|
||||
- 그룹 채팅 동작이나 멘션 게이팅을 변경할 때
|
||||
summary: 표면 전반의 그룹 채팅 동작(Discord/iMessage/Matrix/Microsoft Teams/Signal/Slack/Telegram/WhatsApp/Zalo)
|
||||
title: 그룹
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:27Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 39d066e0542b468c6f8b384b463e2316590ea09a00ecb2065053e1e2ce55bd5f
|
||||
source_path: channels/groups.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 그룹
|
||||
|
||||
OpenClaw는 Discord, iMessage, Matrix, Microsoft Teams, Signal, Slack, Telegram, WhatsApp, Zalo 전반에서 그룹 채팅을 일관되게 처리합니다.
|
||||
|
||||
## 초보자용 소개(2분)
|
||||
|
||||
OpenClaw는 사용자의 자체 메시징 계정에서 “동작”합니다. 별도의 WhatsApp 봇 사용자는 없습니다.
|
||||
**당신**이 그룹에 있다면, OpenClaw는 그 그룹을 볼 수 있고 այնտեղ에서 응답할 수 있습니다.
|
||||
|
||||
기본 동작:
|
||||
|
||||
- 그룹은 제한됩니다(`groupPolicy: "allowlist"`).
|
||||
- 멘션 게이팅을 명시적으로 비활성화하지 않는 한 응답에는 멘션이 필요합니다.
|
||||
|
||||
즉, allowlist에 있는 발신자는 OpenClaw를 멘션하여 트리거할 수 있습니다.
|
||||
|
||||
> 요약
|
||||
>
|
||||
> - **DM 접근**은 `*.allowFrom`으로 제어됩니다.
|
||||
> - **그룹 접근**은 `*.groupPolicy` + allowlist(`*.groups`, `*.groupAllowFrom`)로 제어됩니다.
|
||||
> - **응답 트리거링**은 멘션 게이팅(`requireMention`, `/activation`)으로 제어됩니다.
|
||||
|
||||
빠른 흐름(그룹 메시지에 어떤 일이 일어나는지):
|
||||
|
||||
```
|
||||
groupPolicy? disabled -> drop
|
||||
groupPolicy? allowlist -> group allowed? no -> drop
|
||||
requireMention? yes -> mentioned? no -> store for context only
|
||||
otherwise -> reply
|
||||
```
|
||||
|
||||
## 컨텍스트 가시성과 allowlist
|
||||
|
||||
그룹 안전성에는 두 가지 서로 다른 제어가 관련됩니다.
|
||||
|
||||
- **트리거 권한 부여**: 누가 에이전트를 트리거할 수 있는지(`groupPolicy`, `groups`, `groupAllowFrom`, 채널별 allowlist)
|
||||
- **컨텍스트 가시성**: 어떤 보조 컨텍스트가 모델에 주입되는지(답장 텍스트, 인용, 스레드 기록, 전달된 메타데이터)
|
||||
|
||||
기본적으로 OpenClaw는 일반적인 채팅 동작을 우선하며 컨텍스트를 대부분 수신된 그대로 유지합니다. 이는 allowlist가 주로 누가 작업을 트리거할 수 있는지를 결정하며, 인용되거나 기록에 남은 모든 조각에 대한 보편적인 리다크션 경계는 아니라는 뜻입니다.
|
||||
|
||||
현재 동작은 채널별로 다릅니다.
|
||||
|
||||
- 일부 채널은 특정 경로에서 이미 보조 컨텍스트에 발신자 기반 필터링을 적용합니다(예: Slack 스레드 시딩, Matrix 답장/스레드 조회).
|
||||
- 다른 채널은 여전히 인용/답장/전달 컨텍스트를 수신된 그대로 전달합니다.
|
||||
|
||||
하드닝 방향(계획됨):
|
||||
|
||||
- `contextVisibility: "all"`(기본값)은 현재의 수신 그대로 동작을 유지합니다.
|
||||
- `contextVisibility: "allowlist"`는 보조 컨텍스트를 allowlist 발신자로 필터링합니다.
|
||||
- `contextVisibility: "allowlist_quote"`는 `allowlist`에 하나의 명시적인 인용/답장 예외를 추가한 것입니다.
|
||||
|
||||
이 하드닝 모델이 채널 전반에 걸쳐 일관되게 구현되기 전까지는 표면별 차이가 있을 수 있습니다.
|
||||
|
||||

|
||||
|
||||
다음을 원한다면...
|
||||
|
||||
| 목표 | 설정할 값 |
|
||||
| -------------------------------------------- | ---------------------------------------------------------- |
|
||||
| 모든 그룹을 허용하되 @멘션에서만 응답 | `groups: { "*": { requireMention: true } }` |
|
||||
| 모든 그룹 응답 비활성화 | `groupPolicy: "disabled"` |
|
||||
| 특정 그룹만 허용 | `groups: { "<group-id>": { ... } }` (`"*"` 키 없음) |
|
||||
| 그룹에서는 오직 본인만 트리거 가능 | `groupPolicy: "allowlist"`, `groupAllowFrom: ["+1555..."]` |
|
||||
|
||||
## 세션 키
|
||||
|
||||
- 그룹 세션은 `agent:<agentId>:<channel>:group:<id>` 세션 키를 사용합니다(룸/채널은 `agent:<agentId>:<channel>:channel:<id>` 사용).
|
||||
- Telegram 포럼 토픽은 각 토픽이 자체 세션을 갖도록 그룹 ID에 `:topic:<threadId>`를 추가합니다.
|
||||
- 직접 채팅은 메인 세션을 사용합니다(또는 구성된 경우 발신자별 세션).
|
||||
- Heartbeat는 그룹 세션에서 건너뜁니다.
|
||||
|
||||
<a id="pattern-personal-dms-public-groups-single-agent"></a>
|
||||
|
||||
## 패턴: 개인 DM + 공개 그룹(단일 에이전트)
|
||||
|
||||
예, “개인” 트래픽이 **DM**이고 “공개” 트래픽이 **그룹**이라면 이것은 잘 동작합니다.
|
||||
|
||||
이유: 단일 에이전트 모드에서 DM은 일반적으로 **메인** 세션 키(`agent:main:main`)에 도착하는 반면, 그룹은 항상 **비메인** 세션 키(`agent:main:<channel>:group:<id>`)를 사용합니다. `mode: "non-main"`으로 샌드박싱을 활성화하면, 해당 그룹 세션은 Docker에서 실행되고 메인 DM 세션은 호스트에 남습니다.
|
||||
|
||||
이렇게 하면 하나의 에이전트 “브레인”(공유 워크스페이스 + 메모리)을 가지면서도 두 가지 실행 자세를 가질 수 있습니다.
|
||||
|
||||
- **DM**: 전체 도구(호스트)
|
||||
- **그룹**: 샌드박스 + 제한된 도구(Docker)
|
||||
|
||||
> 정말로 분리된 워크스페이스/페르소나(“개인”과 “공개”가 절대 섞이면 안 됨)가 필요하다면 두 번째 에이전트 + 바인딩을 사용하세요. [Multi-Agent Routing](/concepts/multi-agent)을 참조하세요.
|
||||
|
||||
예시(DM은 호스트, 그룹은 샌드박스 + 메시징 전용 도구):
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
sandbox: {
|
||||
mode: "non-main", // groups/channels are non-main -> sandboxed
|
||||
scope: "session", // strongest isolation (one container per group/channel)
|
||||
workspaceAccess: "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
tools: {
|
||||
sandbox: {
|
||||
tools: {
|
||||
// If allow is non-empty, everything else is blocked (deny still wins).
|
||||
allow: ["group:messaging", "group:sessions"],
|
||||
deny: ["group:runtime", "group:fs", "group:ui", "nodes", "cron", "gateway"],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
“호스트 접근 없음” 대신 “그룹은 폴더 X만 볼 수 있음”을 원하나요? `workspaceAccess: "none"`을 유지하고 allowlist된 경로만 샌드박스에 마운트하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
sandbox: {
|
||||
mode: "non-main",
|
||||
scope: "session",
|
||||
workspaceAccess: "none",
|
||||
docker: {
|
||||
binds: [
|
||||
// hostPath:containerPath:mode
|
||||
"/home/user/FriendsShared:/data:ro",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
관련 항목:
|
||||
|
||||
- 구성 키 및 기본값: [Gateway configuration](/gateway/configuration-reference#agentsdefaultssandbox)
|
||||
- 도구가 차단되는 이유 디버깅: [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated)
|
||||
- 바인드 마운트 세부 정보: [Sandboxing](/gateway/sandboxing#custom-bind-mounts)
|
||||
|
||||
## 표시 라벨
|
||||
|
||||
- UI 라벨은 사용 가능할 때 `displayName`을 사용하며 `<channel>:<token>` 형식으로 표시됩니다.
|
||||
- `#room`은 룸/채널용으로 예약되어 있으며, 그룹 채팅은 `g-<slug>`를 사용합니다(소문자, 공백은 `-`로 변환, `#@+._-`는 유지).
|
||||
|
||||
## 그룹 정책
|
||||
|
||||
채널별로 그룹/룸 메시지를 어떻게 처리할지 제어합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groupPolicy: "disabled", // "open" | "disabled" | "allowlist"
|
||||
groupAllowFrom: ["+15551234567"],
|
||||
},
|
||||
telegram: {
|
||||
groupPolicy: "disabled",
|
||||
groupAllowFrom: ["123456789"], // numeric Telegram user id (wizard can resolve @username)
|
||||
},
|
||||
signal: {
|
||||
groupPolicy: "disabled",
|
||||
groupAllowFrom: ["+15551234567"],
|
||||
},
|
||||
imessage: {
|
||||
groupPolicy: "disabled",
|
||||
groupAllowFrom: ["chat_id:123"],
|
||||
},
|
||||
msteams: {
|
||||
groupPolicy: "disabled",
|
||||
groupAllowFrom: ["user@org.com"],
|
||||
},
|
||||
discord: {
|
||||
groupPolicy: "allowlist",
|
||||
guilds: {
|
||||
GUILD_ID: { channels: { help: { allow: true } } },
|
||||
},
|
||||
},
|
||||
slack: {
|
||||
groupPolicy: "allowlist",
|
||||
channels: { "#general": { allow: true } },
|
||||
},
|
||||
matrix: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["@owner:example.org"],
|
||||
groups: {
|
||||
"!roomId:example.org": { allow: true },
|
||||
"#alias:example.org": { allow: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
| 정책 | 동작 |
|
||||
| ------------- | ------------------------------------------------------------ |
|
||||
| `"open"` | 그룹이 allowlist를 우회하지만 멘션 게이팅은 계속 적용됩니다. |
|
||||
| `"disabled"` | 모든 그룹 메시지를 완전히 차단합니다. |
|
||||
| `"allowlist"` | 구성된 allowlist와 일치하는 그룹/룸만 허용합니다. |
|
||||
|
||||
참고:
|
||||
|
||||
- `groupPolicy`는 멘션 게이팅(@멘션 필요)과 별개입니다.
|
||||
- WhatsApp/Telegram/Signal/iMessage/Microsoft Teams/Zalo: `groupAllowFrom`을 사용합니다(대체: 명시적 `allowFrom`).
|
||||
- DM 페어링 승인(`*-allowFrom` 저장소 항목)은 DM 접근에만 적용되며, 그룹 발신자 권한 부여는 그룹 allowlist에 대해 명시적으로 유지됩니다.
|
||||
- Discord: allowlist는 `channels.discord.guilds.<id>.channels`를 사용합니다.
|
||||
- Slack: allowlist는 `channels.slack.channels`를 사용합니다.
|
||||
- Matrix: allowlist는 `channels.matrix.groups`를 사용합니다. 룸 ID 또는 별칭을 권장합니다. 참가한 룸 이름 조회는 best-effort이며, 해석되지 않은 이름은 런타임에서 무시됩니다. 발신자를 제한하려면 `channels.matrix.groupAllowFrom`을 사용하세요. 룸별 `users` allowlist도 지원됩니다.
|
||||
- 그룹 DM은 별도로 제어됩니다(`channels.discord.dm.*`, `channels.slack.dm.*`).
|
||||
- Telegram allowlist는 사용자 ID(`"123456789"`, `"telegram:123456789"`, `"tg:123456789"`) 또는 사용자 이름(`"@alice"` 또는 `"alice"`)과 일치할 수 있습니다. 접두사는 대소문자를 구분하지 않습니다.
|
||||
- 기본값은 `groupPolicy: "allowlist"`이며, 그룹 allowlist가 비어 있으면 그룹 메시지는 차단됩니다.
|
||||
- 런타임 안전성: 제공자 블록이 완전히 누락된 경우(`channels.<provider>` 없음), 그룹 정책은 `channels.defaults.groupPolicy`를 상속하는 대신 실패 시 닫힘 모드(일반적으로 `allowlist`)로 대체됩니다.
|
||||
|
||||
빠른 멘탈 모델(그룹 메시지 평가 순서):
|
||||
|
||||
1. `groupPolicy` (open/disabled/allowlist)
|
||||
2. 그룹 allowlist(`*.groups`, `*.groupAllowFrom`, 채널별 allowlist)
|
||||
3. 멘션 게이팅(`requireMention`, `/activation`)
|
||||
|
||||
## 멘션 게이팅(기본값)
|
||||
|
||||
그룹 메시지는 그룹별로 재정의하지 않는 한 멘션이 필요합니다. 기본값은 각 서브시스템 아래의 `*.groups."*"`에 있습니다.
|
||||
|
||||
봇 메시지에 답장하는 것도 암묵적 멘션으로 계산됩니다(채널이 답장 메타데이터를 지원하는 경우). 이는 Telegram, WhatsApp, Slack, Discord, Microsoft Teams에 적용됩니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groups: {
|
||||
"*": { requireMention: true },
|
||||
"123@g.us": { requireMention: false },
|
||||
},
|
||||
},
|
||||
telegram: {
|
||||
groups: {
|
||||
"*": { requireMention: true },
|
||||
"123456789": { requireMention: false },
|
||||
},
|
||||
},
|
||||
imessage: {
|
||||
groups: {
|
||||
"*": { requireMention: true },
|
||||
"123": { requireMention: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "main",
|
||||
groupChat: {
|
||||
mentionPatterns: ["@openclaw", "openclaw", "\\+15555550123"],
|
||||
historyLimit: 50,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `mentionPatterns`는 대소문자를 구분하지 않는 안전한 정규식 패턴입니다. 잘못된 패턴과 안전하지 않은 중첩 반복 형식은 무시됩니다.
|
||||
- 명시적 멘션을 제공하는 표면은 계속 통과하며, 패턴은 대체 수단입니다.
|
||||
- 에이전트별 재정의: `agents.list[].groupChat.mentionPatterns`(여러 에이전트가 하나의 그룹을 공유할 때 유용).
|
||||
- 멘션 게이팅은 멘션 감지가 가능한 경우에만 적용됩니다(네이티브 멘션 또는 `mentionPatterns`가 구성된 경우).
|
||||
- Discord 기본값은 `channels.discord.guilds."*"`에 있습니다(guild/channel별 재정의 가능).
|
||||
- 그룹 기록 컨텍스트는 채널 전반에서 일관되게 래핑되며 **pending-only**입니다(멘션 게이팅으로 건너뛴 메시지). 전역 기본값에는 `messages.groupChat.historyLimit`을, 재정의에는 `channels.<channel>.historyLimit`(또는 `channels.<channel>.accounts.*.historyLimit`)을 사용하세요. 비활성화하려면 `0`으로 설정하세요.
|
||||
|
||||
## 그룹/채널 도구 제한(선택 사항)
|
||||
|
||||
일부 채널 구성은 **특정 그룹/룸/채널 내부에서** 사용 가능한 도구를 제한하는 기능을 지원합니다.
|
||||
|
||||
- `tools`: 전체 그룹에 대해 도구 허용/거부
|
||||
- `toolsBySender`: 그룹 내 발신자별 재정의
|
||||
명시적 키 접두사를 사용합니다:
|
||||
`id:<senderId>`, `e164:<phone>`, `username:<handle>`, `name:<displayName>`, 그리고 `"*"` 와일드카드.
|
||||
레거시 접두사 없는 키도 여전히 허용되며 `id:` 전용으로 일치합니다.
|
||||
|
||||
해결 순서(가장 구체적인 항목이 우선):
|
||||
|
||||
1. 그룹/채널 `toolsBySender` 일치
|
||||
2. 그룹/채널 `tools`
|
||||
3. 기본값(`"*"`) `toolsBySender` 일치
|
||||
4. 기본값(`"*"`) `tools`
|
||||
|
||||
예시(Telegram):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
telegram: {
|
||||
groups: {
|
||||
"*": { tools: { deny: ["exec"] } },
|
||||
"-1001234567890": {
|
||||
tools: { deny: ["exec", "read", "write"] },
|
||||
toolsBySender: {
|
||||
"id:123456789": { alsoAllow: ["exec"] },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 그룹/채널 도구 제한은 전역/에이전트 도구 정책에 추가로 적용됩니다(deny가 여전히 우선).
|
||||
- 일부 채널은 룸/채널에 다른 중첩 구조를 사용합니다(예: Discord `guilds.*.channels.*`, Slack `channels.*`, Microsoft Teams `teams.*.channels.*`).
|
||||
|
||||
## 그룹 allowlist
|
||||
|
||||
`channels.whatsapp.groups`, `channels.telegram.groups`, 또는 `channels.imessage.groups`가 구성되면 해당 키가 그룹 allowlist 역할을 합니다. 모든 그룹을 허용하면서 기본 멘션 동작을 계속 설정하려면 `"*"`를 사용하세요.
|
||||
|
||||
자주 발생하는 혼동: DM 페어링 승인은 그룹 권한 부여와 동일하지 않습니다.
|
||||
DM 페어링을 지원하는 채널에서 페어링 저장소는 DM만 잠금 해제합니다. 그룹 명령은 여전히 `groupAllowFrom` 또는 해당 채널에 문서화된 구성 대체 항목 같은 구성 allowlist를 통한 명시적인 그룹 발신자 권한 부여가 필요합니다.
|
||||
|
||||
일반적인 의도(복사/붙여넣기):
|
||||
|
||||
1. 모든 그룹 응답 비활성화
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: { whatsapp: { groupPolicy: "disabled" } },
|
||||
}
|
||||
```
|
||||
|
||||
2. 특정 그룹만 허용(WhatsApp)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groups: {
|
||||
"123@g.us": { requireMention: true },
|
||||
"456@g.us": { requireMention: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
3. 모든 그룹을 허용하되 멘션 요구(명시적)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groups: { "*": { requireMention: true } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
4. 그룹에서는 소유자만 트리거 가능(WhatsApp)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15551234567"],
|
||||
groups: { "*": { requireMention: true } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Activation(소유자 전용)
|
||||
|
||||
그룹 소유자는 그룹별 activation을 전환할 수 있습니다.
|
||||
|
||||
- `/activation mention`
|
||||
- `/activation always`
|
||||
|
||||
소유자는 `channels.whatsapp.allowFrom`으로 결정됩니다(설정되지 않은 경우 봇 자신의 E.164). 명령은 독립된 메시지로 보내세요. 현재 다른 표면은 `/activation`을 무시합니다.
|
||||
|
||||
## 컨텍스트 필드
|
||||
|
||||
그룹 인바운드 페이로드는 다음을 설정합니다.
|
||||
|
||||
- `ChatType=group`
|
||||
- `GroupSubject`(알려진 경우)
|
||||
- `GroupMembers`(알려진 경우)
|
||||
- `WasMentioned`(멘션 게이팅 결과)
|
||||
- Telegram 포럼 토픽에는 `MessageThreadId`와 `IsForum`도 포함됩니다.
|
||||
|
||||
채널별 참고 사항:
|
||||
|
||||
- BlueBubbles는 `GroupMembers`를 채우기 전에 로컬 Contacts 데이터베이스에서 이름 없는 macOS 그룹 참가자 정보를 선택적으로 보강할 수 있습니다. 이는 기본적으로 꺼져 있으며 일반적인 그룹 게이팅을 통과한 뒤에만 실행됩니다.
|
||||
|
||||
에이전트 시스템 프롬프트는 새 그룹 세션의 첫 턴에 그룹 소개를 포함합니다. 여기서는 인간처럼 응답하고, Markdown 표를 피하고, 리터럴 `\n` 시퀀스를 입력하지 말 것을 모델에 상기시킵니다.
|
||||
|
||||
## iMessage 세부 사항
|
||||
|
||||
- 라우팅 또는 allowlist에는 `chat_id:<id>` 사용을 권장합니다.
|
||||
- 채팅 나열: `imsg chats --limit 20`
|
||||
- 그룹 응답은 항상 동일한 `chat_id`로 다시 전송됩니다.
|
||||
|
||||
## WhatsApp 세부 사항
|
||||
|
||||
WhatsApp 전용 동작(기록 주입, 멘션 처리 세부 정보)은 [Group messages](/channels/group-messages)를 참조하세요.
|
||||
434
docs/ko/channels/imessage.md
Normal file
434
docs/ko/channels/imessage.md
Normal file
@ -0,0 +1,434 @@
|
||||
---
|
||||
read_when:
|
||||
- iMessage 지원을 설정할 때
|
||||
- iMessage 송수신을 디버깅할 때
|
||||
summary: imsg를 통한 레거시 iMessage 지원(stdio를 통한 JSON-RPC). 새로운 설정에서는 BlueBubbles를 사용해야 합니다.
|
||||
title: iMessage
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:25Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 086d85bead49f75d12ae6b14ac917af52375b6afd28f6af1a0dcbbc7fcb628a0
|
||||
source_path: channels/imessage.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# iMessage (레거시: imsg)
|
||||
|
||||
<Warning>
|
||||
새로운 iMessage 배포에는 <a href="/channels/bluebubbles">BlueBubbles</a>를 사용하세요.
|
||||
|
||||
`imsg` 통합은 레거시이며 향후 릴리스에서 제거될 수 있습니다.
|
||||
</Warning>
|
||||
|
||||
상태: 레거시 외부 CLI 통합. 게이트웨이는 `imsg rpc`를 실행하고 stdio의 JSON-RPC를 통해 통신합니다(별도의 데몬/포트 없음).
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="BlueBubbles (권장)" icon="message-circle" href="/channels/bluebubbles">
|
||||
새로운 설정을 위한 선호되는 iMessage 경로입니다.
|
||||
</Card>
|
||||
<Card title="페어링" icon="link" href="/channels/pairing">
|
||||
iMessage DM은 기본적으로 페어링 모드를 사용합니다.
|
||||
</Card>
|
||||
<Card title="구성 참조" icon="settings" href="/gateway/configuration-reference#imessage">
|
||||
전체 iMessage 필드 참조입니다.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## 빠른 설정
|
||||
|
||||
<Tabs>
|
||||
<Tab title="로컬 Mac (빠른 경로)">
|
||||
<Steps>
|
||||
<Step title="imsg 설치 및 확인">
|
||||
|
||||
```bash
|
||||
brew install steipete/tap/imsg
|
||||
imsg rpc --help
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="OpenClaw 구성">
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
imessage: {
|
||||
enabled: true,
|
||||
cliPath: "/usr/local/bin/imsg",
|
||||
dbPath: "/Users/<you>/Library/Messages/chat.db",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="게이트웨이 시작">
|
||||
|
||||
```bash
|
||||
openclaw gateway
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="첫 번째 DM 페어링 승인(기본 dmPolicy)">
|
||||
|
||||
```bash
|
||||
openclaw pairing list imessage
|
||||
openclaw pairing approve imessage <CODE>
|
||||
```
|
||||
|
||||
페어링 요청은 1시간 후 만료됩니다.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="SSH를 통한 원격 Mac">
|
||||
OpenClaw에는 stdio 호환 `cliPath`만 필요하므로, `cliPath`가 원격 Mac으로 SSH 접속하여 `imsg`를 실행하는 래퍼 스크립트를 가리키도록 설정할 수 있습니다.
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
exec ssh -T gateway-host imsg "$@"
|
||||
```
|
||||
|
||||
첨부 파일이 활성화된 경우의 권장 구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
imessage: {
|
||||
enabled: true,
|
||||
cliPath: "~/.openclaw/scripts/imsg-ssh",
|
||||
remoteHost: "user@gateway-host", // SCP 첨부 파일 가져오기에 사용됨
|
||||
includeAttachments: true,
|
||||
// 선택 사항: 허용된 첨부 파일 루트를 재정의합니다.
|
||||
// 기본값에는 /Users/*/Library/Messages/Attachments가 포함됩니다.
|
||||
attachmentRoots: ["/Users/*/Library/Messages/Attachments"],
|
||||
remoteAttachmentRoots: ["/Users/*/Library/Messages/Attachments"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`remoteHost`가 설정되지 않으면 OpenClaw는 SSH 래퍼 스크립트를 파싱하여 이를 자동 감지하려고 시도합니다.
|
||||
`remoteHost`는 `host` 또는 `user@host`여야 합니다(공백이나 SSH 옵션 없음).
|
||||
OpenClaw는 SCP에 엄격한 호스트 키 검사를 사용하므로 릴레이 호스트 키가 이미 `~/.ssh/known_hosts`에 있어야 합니다.
|
||||
첨부 파일 경로는 허용된 루트(`attachmentRoots` / `remoteAttachmentRoots`)를 기준으로 검증됩니다.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 요구 사항 및 권한(macOS)
|
||||
|
||||
- `imsg`를 실행하는 Mac에서 Messages에 로그인되어 있어야 합니다.
|
||||
- OpenClaw/`imsg`를 실행하는 프로세스 컨텍스트에는 전체 디스크 접근 권한이 필요합니다(Messages DB 접근).
|
||||
- Messages.app을 통해 메시지를 보내려면 자동화 권한이 필요합니다.
|
||||
|
||||
<Tip>
|
||||
권한은 프로세스 컨텍스트별로 부여됩니다. 게이트웨이가 헤드리스(LaunchAgent/SSH)로 실행되는 경우, 프롬프트를 트리거하기 위해 같은 컨텍스트에서 한 번 상호작용 명령을 실행하세요:
|
||||
|
||||
```bash
|
||||
imsg chats --limit 1
|
||||
# 또는
|
||||
imsg send <handle> "test"
|
||||
```
|
||||
|
||||
</Tip>
|
||||
|
||||
## 액세스 제어 및 라우팅
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM 정책">
|
||||
`channels.imessage.dmPolicy`는 다이렉트 메시지를 제어합니다:
|
||||
|
||||
- `pairing` (기본값)
|
||||
- `allowlist`
|
||||
- `open` (`allowFrom`에 `"*"`가 포함되어야 함)
|
||||
- `disabled`
|
||||
|
||||
허용 목록 필드: `channels.imessage.allowFrom`.
|
||||
|
||||
허용 목록 항목은 핸들이나 채팅 대상(`chat_id:*`, `chat_guid:*`, `chat_identifier:*`)일 수 있습니다.
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="그룹 정책 + 멘션">
|
||||
`channels.imessage.groupPolicy`는 그룹 처리를 제어합니다:
|
||||
|
||||
- `allowlist` (구성된 경우 기본값)
|
||||
- `open`
|
||||
- `disabled`
|
||||
|
||||
그룹 발신자 허용 목록: `channels.imessage.groupAllowFrom`.
|
||||
|
||||
런타임 대체 동작: `groupAllowFrom`이 설정되지 않은 경우, iMessage 그룹 발신자 검사는 사용 가능할 때 `allowFrom`으로 대체됩니다.
|
||||
런타임 참고: `channels.imessage`가 완전히 누락되면 런타임은 `groupPolicy="allowlist"`로 대체하고 경고를 기록합니다(`channels.defaults.groupPolicy`가 설정되어 있어도 마찬가지).
|
||||
|
||||
그룹용 멘션 게이팅:
|
||||
|
||||
- iMessage에는 기본 멘션 메타데이터가 없습니다
|
||||
- 멘션 감지는 정규식 패턴(`agents.list[].groupChat.mentionPatterns`, 대체값 `messages.groupChat.mentionPatterns`)을 사용합니다
|
||||
- 구성된 패턴이 없으면 멘션 게이팅을 강제할 수 없습니다
|
||||
|
||||
권한 있는 발신자의 제어 명령은 그룹에서 멘션 게이팅을 우회할 수 있습니다.
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="세션 및 결정적 응답">
|
||||
- DM은 direct routing을 사용하고 그룹은 group routing을 사용합니다.
|
||||
- 기본 `session.dmScope=main`에서는 iMessage DM이 에이전트 메인 세션으로 합쳐집니다.
|
||||
- 그룹 세션은 격리됩니다(`agent:<agentId>:imessage:group:<chat_id>`).
|
||||
- 응답은 원래 채널/대상 메타데이터를 사용해 iMessage로 다시 라우팅됩니다.
|
||||
|
||||
그룹 유사 스레드 동작:
|
||||
|
||||
일부 다중 참여자 iMessage 스레드는 `is_group=false`로 도착할 수 있습니다.
|
||||
해당 `chat_id`가 `channels.imessage.groups` 아래에 명시적으로 구성되어 있으면, OpenClaw는 이를 그룹 트래픽으로 취급합니다(그룹 게이팅 + 그룹 세션 격리).
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## ACP 대화 바인딩
|
||||
|
||||
레거시 iMessage 채팅은 ACP 세션에 바인딩할 수도 있습니다.
|
||||
|
||||
빠른 운영자 흐름:
|
||||
|
||||
- DM 또는 허용된 그룹 채팅 안에서 `/acp spawn codex --bind here`를 실행합니다.
|
||||
- 이후 같은 iMessage 대화의 메시지는 생성된 ACP 세션으로 라우팅됩니다.
|
||||
- `/new`와 `/reset`은 같은 바인딩된 ACP 세션을 제자리에서 재설정합니다.
|
||||
- `/acp close`는 ACP 세션을 닫고 바인딩을 제거합니다.
|
||||
|
||||
구성된 영구 바인딩은 `type: "acp"` 및 `match.channel: "imessage"`가 있는 최상위 `bindings[]` 항목을 통해 지원됩니다.
|
||||
|
||||
`match.peer.id`에는 다음을 사용할 수 있습니다:
|
||||
|
||||
- `+15555550123` 또는 `user@example.com` 같은 정규화된 DM 핸들
|
||||
- `chat_id:<id>` (안정적인 그룹 바인딩에 권장)
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
|
||||
예:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "codex",
|
||||
runtime: {
|
||||
type: "acp",
|
||||
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
type: "acp",
|
||||
agentId: "codex",
|
||||
match: {
|
||||
channel: "imessage",
|
||||
accountId: "default",
|
||||
peer: { kind: "group", id: "chat_id:123" },
|
||||
},
|
||||
acp: { label: "codex-group" },
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
공유 ACP 바인딩 동작은 [ACP 에이전트](/tools/acp-agents)를 참조하세요.
|
||||
|
||||
## 배포 패턴
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="전용 봇 macOS 사용자(별도 iMessage ID)">
|
||||
봇 트래픽이 개인 Messages 프로필과 분리되도록 전용 Apple ID와 macOS 사용자를 사용하세요.
|
||||
|
||||
일반적인 흐름:
|
||||
|
||||
1. 전용 macOS 사용자를 만들고 로그인합니다.
|
||||
2. 해당 사용자에서 봇 Apple ID로 Messages에 로그인합니다.
|
||||
3. 해당 사용자에 `imsg`를 설치합니다.
|
||||
4. OpenClaw가 해당 사용자 컨텍스트에서 `imsg`를 실행할 수 있도록 SSH 래퍼를 만듭니다.
|
||||
5. `channels.imessage.accounts.<id>.cliPath`와 `.dbPath`를 해당 사용자 프로필로 지정합니다.
|
||||
|
||||
첫 실행 시 해당 봇 사용자 세션에서 GUI 승인(자동화 + 전체 디스크 접근 권한)이 필요할 수 있습니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Tailscale을 통한 원격 Mac(예시)">
|
||||
일반적인 토폴로지:
|
||||
|
||||
- 게이트웨이는 Linux/VM에서 실행됨
|
||||
- iMessage + `imsg`는 tailnet의 Mac에서 실행됨
|
||||
- `cliPath` 래퍼는 SSH를 사용해 `imsg`를 실행함
|
||||
- `remoteHost`는 SCP 첨부 파일 가져오기를 활성화함
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
imessage: {
|
||||
enabled: true,
|
||||
cliPath: "~/.openclaw/scripts/imsg-ssh",
|
||||
remoteHost: "bot@mac-mini.tailnet-1234.ts.net",
|
||||
includeAttachments: true,
|
||||
dbPath: "/Users/bot/Library/Messages/chat.db",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
|
||||
```
|
||||
|
||||
SSH와 SCP가 모두 비대화형이 되도록 SSH 키를 사용하세요.
|
||||
먼저 호스트 키가 신뢰되는지 확인하세요(예: `ssh bot@mac-mini.tailnet-1234.ts.net`). 그러면 `known_hosts`가 채워집니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="다중 계정 패턴">
|
||||
iMessage는 `channels.imessage.accounts` 아래에서 계정별 구성을 지원합니다.
|
||||
|
||||
각 계정은 `cliPath`, `dbPath`, `allowFrom`, `groupPolicy`, `mediaMaxMb`, 히스토리 설정, 첨부 파일 루트 허용 목록 등의 필드를 재정의할 수 있습니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 미디어, 청킹 및 전달 대상
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="첨부 파일 및 미디어">
|
||||
- 수신 첨부 파일 수집은 선택 사항입니다: `channels.imessage.includeAttachments`
|
||||
- `remoteHost`가 설정되면 원격 첨부 파일 경로를 SCP로 가져올 수 있습니다
|
||||
- 첨부 파일 경로는 허용된 루트와 일치해야 합니다:
|
||||
- `channels.imessage.attachmentRoots` (로컬)
|
||||
- `channels.imessage.remoteAttachmentRoots` (원격 SCP 모드)
|
||||
- 기본 루트 패턴: `/Users/*/Library/Messages/Attachments`
|
||||
- SCP는 엄격한 호스트 키 검사(`StrictHostKeyChecking=yes`)를 사용합니다
|
||||
- 발신 미디어 크기는 `channels.imessage.mediaMaxMb`를 사용합니다(기본값 16 MB)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="발신 청킹">
|
||||
- 텍스트 청크 제한: `channels.imessage.textChunkLimit` (기본값 4000)
|
||||
- 청크 모드: `channels.imessage.chunkMode`
|
||||
- `length` (기본값)
|
||||
- `newline` (문단 우선 분할)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="주소 지정 형식">
|
||||
선호되는 명시적 대상:
|
||||
|
||||
- `chat_id:123` (안정적인 라우팅에 권장)
|
||||
- `chat_guid:...`
|
||||
- `chat_identifier:...`
|
||||
|
||||
핸들 대상도 지원됩니다:
|
||||
|
||||
- `imessage:+1555...`
|
||||
- `sms:+1555...`
|
||||
- `user@example.com`
|
||||
|
||||
```bash
|
||||
imsg chats --limit 20
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 구성 쓰기
|
||||
|
||||
iMessage는 기본적으로 채널 시작 구성 쓰기를 허용합니다(`commands.config: true`일 때 `/config set|unset`용).
|
||||
|
||||
비활성화:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
imessage: {
|
||||
configWrites: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 문제 해결
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="imsg를 찾을 수 없거나 RPC를 지원하지 않음">
|
||||
바이너리와 RPC 지원을 확인하세요:
|
||||
|
||||
```bash
|
||||
imsg rpc --help
|
||||
openclaw channels status --probe
|
||||
```
|
||||
|
||||
프로브에서 RPC 미지원으로 보고되면 `imsg`를 업데이트하세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="DM이 무시됨">
|
||||
다음을 확인하세요:
|
||||
|
||||
- `channels.imessage.dmPolicy`
|
||||
- `channels.imessage.allowFrom`
|
||||
- 페어링 승인(`openclaw pairing list imessage`)
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="그룹 메시지가 무시됨">
|
||||
다음을 확인하세요:
|
||||
|
||||
- `channels.imessage.groupPolicy`
|
||||
- `channels.imessage.groupAllowFrom`
|
||||
- `channels.imessage.groups` 허용 목록 동작
|
||||
- 멘션 패턴 구성(`agents.list[].groupChat.mentionPatterns`)
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="원격 첨부 파일 실패">
|
||||
다음을 확인하세요:
|
||||
|
||||
- `channels.imessage.remoteHost`
|
||||
- `channels.imessage.remoteAttachmentRoots`
|
||||
- 게이트웨이 호스트에서의 SSH/SCP 키 인증
|
||||
- 게이트웨이 호스트의 `~/.ssh/known_hosts`에 호스트 키가 존재하는지
|
||||
- Messages를 실행하는 Mac에서 원격 경로를 읽을 수 있는지
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="macOS 권한 프롬프트를 놓쳤음">
|
||||
같은 사용자/세션 컨텍스트의 상호작용 GUI 터미널에서 다시 실행하고 프롬프트를 승인하세요:
|
||||
|
||||
```bash
|
||||
imsg chats --limit 1
|
||||
imsg send <handle> "test"
|
||||
```
|
||||
|
||||
OpenClaw/`imsg`를 실행하는 프로세스 컨텍스트에 전체 디스크 접근 권한과 자동화 권한이 부여되었는지 확인하세요.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 구성 참조 포인터
|
||||
|
||||
- [구성 참조 - iMessage](/gateway/configuration-reference#imessage)
|
||||
- [게이트웨이 구성](/gateway/configuration)
|
||||
- [페어링](/channels/pairing)
|
||||
- [BlueBubbles](/channels/bluebubbles)
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 강화
|
||||
56
docs/ko/channels/index.md
Normal file
56
docs/ko/channels/index.md
Normal file
@ -0,0 +1,56 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw용 채팅 채널을 선택하려는 경우
|
||||
- 지원되는 메시징 플랫폼의 빠른 개요가 필요한 경우
|
||||
summary: OpenClaw가 연결할 수 있는 메시징 플랫폼
|
||||
title: 채팅 채널
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:11Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 246ee6f16aebe751241f00102bb435978ed21f6158385aff5d8e222e30567416
|
||||
source_path: channels/index.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 채팅 채널
|
||||
|
||||
OpenClaw는 이미 사용 중인 어떤 채팅 앱에서든 사용자와 대화할 수 있습니다. 각 채널은 Gateway를 통해 연결됩니다.
|
||||
텍스트는 모든 곳에서 지원되며, 미디어와 반응 지원은 채널마다 다릅니다.
|
||||
|
||||
## 지원되는 채널
|
||||
|
||||
- [BlueBubbles](/channels/bluebubbles) — **iMessage에 권장**; 전체 기능 지원이 포함된 BlueBubbles macOS 서버 REST API를 사용합니다(번들 plugin; 수정, 전송 취소, 효과, 반응, 그룹 관리 — 수정은 현재 macOS 26 Tahoe에서 작동하지 않음).
|
||||
- [Discord](/channels/discord) — Discord Bot API + Gateway; 서버, 채널, DM을 지원합니다.
|
||||
- [Feishu](/channels/feishu) — WebSocket을 통한 Feishu/Lark 봇(번들 plugin).
|
||||
- [Google Chat](/channels/googlechat) — HTTP 웹훅을 통한 Google Chat API 앱.
|
||||
- [iMessage (legacy)](/channels/imessage) — imsg CLI를 통한 레거시 macOS 통합(지원 중단 예정, 새 설정에는 BlueBubbles 사용).
|
||||
- [IRC](/channels/irc) — 전통적인 IRC 서버; 페어링/허용 목록 제어가 포함된 채널 + DM.
|
||||
- [LINE](/channels/line) — LINE Messaging API 봇(번들 plugin).
|
||||
- [Matrix](/channels/matrix) — Matrix 프로토콜(번들 plugin).
|
||||
- [Mattermost](/channels/mattermost) — Bot API + WebSocket; 채널, 그룹, DM(번들 plugin).
|
||||
- [Microsoft Teams](/channels/msteams) — Bot Framework; 엔터프라이즈 지원(번들 plugin).
|
||||
- [Nextcloud Talk](/channels/nextcloud-talk) — Nextcloud Talk를 통한 셀프 호스팅 채팅(번들 plugin).
|
||||
- [Nostr](/channels/nostr) — NIP-04를 통한 분산형 DM(번들 plugin).
|
||||
- [QQ Bot](/channels/qqbot) — QQ Bot API; 개인 채팅, 그룹 채팅, 리치 미디어(번들 plugin).
|
||||
- [Signal](/channels/signal) — signal-cli; 개인정보 보호 중심.
|
||||
- [Slack](/channels/slack) — Bolt SDK; 워크스페이스 앱.
|
||||
- [Synology Chat](/channels/synology-chat) — 송신+수신 웹훅을 통한 Synology NAS Chat(번들 plugin).
|
||||
- [Telegram](/channels/telegram) — grammY를 통한 Bot API; 그룹을 지원합니다.
|
||||
- [Tlon](/channels/tlon) — Urbit 기반 메신저(번들 plugin).
|
||||
- [Twitch](/channels/twitch) — IRC 연결을 통한 Twitch 채팅(번들 plugin).
|
||||
- [Voice Call](/plugins/voice-call) — Plivo 또는 Twilio를 통한 전화 통신(plugin, 별도 설치).
|
||||
- [WebChat](/web/webchat) — WebSocket을 통한 Gateway WebChat UI.
|
||||
- [WeChat](https://www.npmjs.com/package/@tencent-weixin/openclaw-weixin) — QR 로그인을 통한 Tencent iLink Bot plugin; 개인 채팅만 지원.
|
||||
- [WhatsApp](/channels/whatsapp) — 가장 대중적임; Baileys를 사용하며 QR 페어링이 필요합니다.
|
||||
- [Zalo](/channels/zalo) — Zalo Bot API; 베트남에서 인기 있는 메신저(번들 plugin).
|
||||
- [Zalo Personal](/channels/zalouser) — QR 로그인을 통한 Zalo 개인 계정(번들 plugin).
|
||||
|
||||
## 참고
|
||||
|
||||
- 채널은 동시에 실행할 수 있습니다. 여러 개를 구성하면 OpenClaw가 채팅별로 라우팅합니다.
|
||||
- 가장 빠른 설정은 보통 **Telegram**입니다(간단한 봇 토큰). WhatsApp는 QR 페어링이 필요하며 디스크에 더 많은 상태를 저장합니다.
|
||||
- 그룹 동작은 채널마다 다릅니다. [Groups](/channels/groups)를 참조하세요.
|
||||
- 안전을 위해 DM 페어링과 허용 목록이 강제 적용됩니다. [Security](/gateway/security)를 참조하세요.
|
||||
- 문제 해결: [Channel troubleshooting](/channels/troubleshooting).
|
||||
- 모델 provider는 별도로 문서화되어 있습니다. [Model Providers](/providers/models)를 참조하세요.
|
||||
259
docs/ko/channels/irc.md
Normal file
259
docs/ko/channels/irc.md
Normal file
@ -0,0 +1,259 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw를 IRC 채널 또는 DM에 연결하려는 경우
|
||||
- IRC 허용 목록, 그룹 정책 또는 멘션 게이팅을 구성하는 경우
|
||||
summary: IRC 플러그인 설정, 액세스 제어 및 문제 해결
|
||||
title: IRC
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:21Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: fceab2979db72116689c6c774d6736a8a2eee3559e3f3cf8969e673d317edd94
|
||||
source_path: channels/irc.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# IRC
|
||||
|
||||
OpenClaw를 전통적인 채널(`#room`) 및 다이렉트 메시지에 연결하려면 IRC를 사용하세요.
|
||||
IRC는 확장 플러그인으로 제공되지만, 구성은 메인 config의 `channels.irc` 아래에서 수행합니다.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
1. `~/.openclaw/openclaw.json`에서 IRC config를 활성화합니다.
|
||||
2. 최소한 다음을 설정합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
enabled: true,
|
||||
host: "irc.example.com",
|
||||
port: 6697,
|
||||
tls: true,
|
||||
nick: "openclaw-bot",
|
||||
channels: ["#openclaw"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
봇 조정을 위해서는 비공개 IRC 서버를 권장합니다. 의도적으로 공개 IRC 네트워크를 사용하는 경우 일반적인 선택지는 Libera.Chat, OFTC, Snoonet입니다. 봇 또는 스웜 백채널 트래픽에는 예측 가능한 공개 채널을 피하세요.
|
||||
|
||||
3. 게이트웨이를 시작하거나 재시작합니다.
|
||||
|
||||
```bash
|
||||
openclaw gateway run
|
||||
```
|
||||
|
||||
## 기본 보안 설정
|
||||
|
||||
- `channels.irc.dmPolicy`의 기본값은 `"pairing"`입니다.
|
||||
- `channels.irc.groupPolicy`의 기본값은 `"allowlist"`입니다.
|
||||
- `groupPolicy="allowlist"`를 사용할 때는 허용된 채널을 정의하기 위해 `channels.irc.groups`를 설정하세요.
|
||||
- 평문 전송을 의도적으로 허용하는 경우가 아니라면 TLS(`channels.irc.tls=true`)를 사용하세요.
|
||||
|
||||
## 액세스 제어
|
||||
|
||||
IRC 채널에는 두 가지 별도의 “게이트”가 있습니다.
|
||||
|
||||
1. **채널 액세스**(`groupPolicy` + `groups`): 봇이 해당 채널의 메시지를 아예 수락할지 여부
|
||||
2. **발신자 액세스**(`groupAllowFrom` / 채널별 `groups["#channel"].allowFrom`): 해당 채널 안에서 누가 봇을 트리거할 수 있는지
|
||||
|
||||
Config 키:
|
||||
|
||||
- DM 허용 목록(DM 발신자 액세스): `channels.irc.allowFrom`
|
||||
- 그룹 발신자 허용 목록(채널 발신자 액세스): `channels.irc.groupAllowFrom`
|
||||
- 채널별 제어(채널 + 발신자 + 멘션 규칙): `channels.irc.groups["#channel"]`
|
||||
- `channels.irc.groupPolicy="open"`은 구성되지 않은 채널도 허용합니다(**그래도 기본적으로 멘션 게이팅은 적용됩니다**)
|
||||
|
||||
허용 목록 항목에는 안정적인 발신자 식별자(`nick!user@host`)를 사용해야 합니다.
|
||||
닉네임만으로 매칭하는 방식은 변경 가능하며, `channels.irc.dangerouslyAllowNameMatching: true`일 때만 활성화됩니다.
|
||||
|
||||
### 흔한 함정: `allowFrom`은 채널용이 아니라 DM용입니다
|
||||
|
||||
다음과 같은 로그가 보인다면:
|
||||
|
||||
- `irc: drop group sender alice!ident@host (policy=allowlist)`
|
||||
|
||||
이는 **그룹/채널** 메시지에 대해 발신자가 허용되지 않았다는 의미입니다. 다음 중 하나로 해결하세요.
|
||||
|
||||
- `channels.irc.groupAllowFrom` 설정(모든 채널에 전역 적용), 또는
|
||||
- 채널별 발신자 허용 목록 설정: `channels.irc.groups["#channel"].allowFrom`
|
||||
|
||||
예시(`#tuirc-dev`에서 누구나 봇과 대화할 수 있도록 허용):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
groupPolicy: "allowlist",
|
||||
groups: {
|
||||
"#tuirc-dev": { allowFrom: ["*"] },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 응답 트리거(멘션)
|
||||
|
||||
채널이 허용되었고(`groupPolicy` + `groups`), 발신자도 허용되었더라도, OpenClaw는 그룹 컨텍스트에서 기본적으로 **멘션 게이팅**을 사용합니다.
|
||||
|
||||
즉, 메시지에 봇과 일치하는 멘션 패턴이 포함되어 있지 않으면 `drop channel … (missing-mention)` 같은 로그가 보일 수 있습니다.
|
||||
|
||||
멘션 없이도 IRC 채널에서 봇이 **응답하게 하려면**, 해당 채널의 멘션 게이팅을 비활성화하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
groupPolicy: "allowlist",
|
||||
groups: {
|
||||
"#tuirc-dev": {
|
||||
requireMention: false,
|
||||
allowFrom: ["*"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
또는 **모든** IRC 채널을 허용하고(채널별 허용 목록 없음), 멘션 없이도 응답하게 하려면:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
groupPolicy: "open",
|
||||
groups: {
|
||||
"*": { requireMention: false, allowFrom: ["*"] },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 보안 참고(공개 채널 권장 설정)
|
||||
|
||||
공개 채널에서 `allowFrom: ["*"]`를 허용하면 누구나 봇에 프롬프트를 보낼 수 있습니다.
|
||||
위험을 줄이려면 해당 채널의 도구를 제한하세요.
|
||||
|
||||
### 채널 내 모든 사용자에게 동일한 도구 적용
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
groups: {
|
||||
"#tuirc-dev": {
|
||||
allowFrom: ["*"],
|
||||
tools: {
|
||||
deny: ["group:runtime", "group:fs", "gateway", "nodes", "cron", "browser"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 발신자별로 다른 도구 적용(소유자에게 더 많은 권한 부여)
|
||||
|
||||
`toolsBySender`를 사용해 `"*"`에는 더 엄격한 정책을, 자신의 닉네임에는 더 느슨한 정책을 적용하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
groups: {
|
||||
"#tuirc-dev": {
|
||||
allowFrom: ["*"],
|
||||
toolsBySender: {
|
||||
"*": {
|
||||
deny: ["group:runtime", "group:fs", "gateway", "nodes", "cron", "browser"],
|
||||
},
|
||||
"id:eigen": {
|
||||
deny: ["gateway", "nodes", "cron"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `toolsBySender` 키는 IRC 발신자 식별자 값에 대해 `id:`를 사용해야 합니다.
|
||||
더 강한 일치를 위해 `id:eigen` 또는 `id:eigen!~eigen@174.127.248.171` 형식을 사용하세요.
|
||||
- 기존의 접두사 없는 키도 계속 허용되며 `id:`로만 매칭됩니다.
|
||||
- 가장 먼저 일치하는 발신자 정책이 우선하며, `"*"`는 와일드카드 대체값입니다.
|
||||
|
||||
그룹 액세스와 멘션 게이팅(그리고 이들이 상호작용하는 방식)에 대한 자세한 내용은 [/channels/groups](/channels/groups)를 참조하세요.
|
||||
|
||||
## NickServ
|
||||
|
||||
연결 후 NickServ로 식별하려면:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
nickserv: {
|
||||
enabled: true,
|
||||
service: "NickServ",
|
||||
password: "your-nickserv-password",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
연결 시 선택적 1회 등록:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
nickserv: {
|
||||
register: true,
|
||||
registerEmail: "bot@example.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
닉네임이 등록된 후에는 반복적인 REGISTER 시도를 피하기 위해 `register`를 비활성화하세요.
|
||||
|
||||
## 환경 변수
|
||||
|
||||
기본 계정은 다음을 지원합니다.
|
||||
|
||||
- `IRC_HOST`
|
||||
- `IRC_PORT`
|
||||
- `IRC_TLS`
|
||||
- `IRC_NICK`
|
||||
- `IRC_USERNAME`
|
||||
- `IRC_REALNAME`
|
||||
- `IRC_PASSWORD`
|
||||
- `IRC_CHANNELS`(쉼표로 구분)
|
||||
- `IRC_NICKSERV_PASSWORD`
|
||||
- `IRC_NICKSERV_REGISTER_EMAIL`
|
||||
|
||||
## 문제 해결
|
||||
|
||||
- 봇이 연결되지만 채널에서 전혀 응답하지 않는다면 `channels.irc.groups`와 멘션 게이팅이 메시지를 드롭하고 있는지(`missing-mention`)를 **모두** 확인하세요. 핑 없이 응답하게 하려면 해당 채널에 `requireMention:false`를 설정하세요.
|
||||
- 로그인이 실패하면 닉네임 사용 가능 여부와 서버 비밀번호를 확인하세요.
|
||||
- 사용자 지정 네트워크에서 TLS가 실패하면 호스트/포트와 인증서 설정을 확인하세요.
|
||||
|
||||
## 관련
|
||||
|
||||
- [Channels Overview](/channels) — 지원되는 모든 채널
|
||||
- [Pairing](/channels/pairing) — DM 인증 및 pairing 흐름
|
||||
- [Groups](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [Channel Routing](/channels/channel-routing) — 메시지의 세션 라우팅
|
||||
- [Security](/gateway/security) — 액세스 모델 및 보안 강화
|
||||
219
docs/ko/channels/line.md
Normal file
219
docs/ko/channels/line.md
Normal file
@ -0,0 +1,219 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw를 LINE에 연결하려는 경우
|
||||
- LINE webhook 및 자격 증명 설정이 필요한 경우
|
||||
- LINE 전용 메시지 옵션을 사용하려는 경우
|
||||
summary: LINE Messaging API plugin 설정, 구성 및 사용법
|
||||
title: LINE
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:24Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: b4782b2aa3e8654505d7f1fd6fc112adf125b5010fc84d655d033688ded37414
|
||||
source_path: channels/line.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# LINE
|
||||
|
||||
LINE는 LINE Messaging API를 통해 OpenClaw에 연결됩니다. 이 plugin은 gateway에서 webhook 수신기로 실행되며 인증에 채널 액세스 토큰과 채널 시크릿을 사용합니다.
|
||||
|
||||
상태: 번들 plugin. 다이렉트 메시지, 그룹 채팅, 미디어, 위치, Flex 메시지, 템플릿 메시지, 빠른 답장이 지원됩니다. 반응과 스레드는 지원되지 않습니다.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
LINE는 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 있으므로 일반 패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
이전 빌드 또는 LINE가 제외된 사용자 지정 설치를 사용하는 경우 수동으로 설치하세요.
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/line
|
||||
```
|
||||
|
||||
로컬 체크아웃(git 리포지토리에서 실행하는 경우):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./path/to/local/line-plugin
|
||||
```
|
||||
|
||||
## 설정
|
||||
|
||||
1. LINE Developers 계정을 만들고 Console을 엽니다:
|
||||
[https://developers.line.biz/console/](https://developers.line.biz/console/)
|
||||
2. Provider를 생성(또는 선택)하고 **Messaging API** 채널을 추가합니다.
|
||||
3. 채널 설정에서 **Channel access token** 및 **Channel secret**을 복사합니다.
|
||||
4. Messaging API 설정에서 **Use webhook**을 활성화합니다.
|
||||
5. webhook URL을 gateway 엔드포인트로 설정합니다(HTTPS 필수).
|
||||
|
||||
```
|
||||
https://gateway-host/line/webhook
|
||||
```
|
||||
|
||||
gateway는 LINE의 webhook 검증(GET)과 인바운드 이벤트(POST)에 응답합니다.
|
||||
사용자 지정 경로가 필요한 경우 `channels.line.webhookPath` 또는
|
||||
`channels.line.accounts.<id>.webhookPath`를 설정하고 그에 맞게 URL을 업데이트하세요.
|
||||
|
||||
보안 참고:
|
||||
|
||||
- LINE 서명 검증은 본문에 의존합니다(원시 본문에 대한 HMAC). 따라서 OpenClaw는 검증 전에 엄격한 사전 인증 본문 제한과 타임아웃을 적용합니다.
|
||||
- OpenClaw는 검증된 원시 요청 바이트에서 webhook 이벤트를 처리합니다. 서명 무결성 보안을 위해 업스트림 미들웨어가 변환한 `req.body` 값은 무시됩니다.
|
||||
|
||||
## 구성
|
||||
|
||||
최소 구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
line: {
|
||||
enabled: true,
|
||||
channelAccessToken: "LINE_CHANNEL_ACCESS_TOKEN",
|
||||
channelSecret: "LINE_CHANNEL_SECRET",
|
||||
dmPolicy: "pairing",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
환경 변수(기본 계정 전용):
|
||||
|
||||
- `LINE_CHANNEL_ACCESS_TOKEN`
|
||||
- `LINE_CHANNEL_SECRET`
|
||||
|
||||
토큰/시크릿 파일:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
line: {
|
||||
tokenFile: "/path/to/line-token.txt",
|
||||
secretFile: "/path/to/line-secret.txt",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`tokenFile`과 `secretFile`은 일반 파일을 가리켜야 합니다. 심볼릭 링크는 거부됩니다.
|
||||
|
||||
여러 계정:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
line: {
|
||||
accounts: {
|
||||
marketing: {
|
||||
channelAccessToken: "...",
|
||||
channelSecret: "...",
|
||||
webhookPath: "/line/marketing",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 액세스 제어
|
||||
|
||||
다이렉트 메시지는 기본적으로 페어링을 사용합니다. 알 수 없는 발신자는 페어링 코드를 받으며 승인될 때까지 메시지가 무시됩니다.
|
||||
|
||||
```bash
|
||||
openclaw pairing list line
|
||||
openclaw pairing approve line <CODE>
|
||||
```
|
||||
|
||||
허용 목록 및 정책:
|
||||
|
||||
- `channels.line.dmPolicy`: `pairing | allowlist | open | disabled`
|
||||
- `channels.line.allowFrom`: DM용 허용 목록 LINE 사용자 ID
|
||||
- `channels.line.groupPolicy`: `allowlist | open | disabled`
|
||||
- `channels.line.groupAllowFrom`: 그룹용 허용 목록 LINE 사용자 ID
|
||||
- 그룹별 재정의: `channels.line.groups.<groupId>.allowFrom`
|
||||
- 런타임 참고: `channels.line`이 완전히 누락된 경우 런타임은 그룹 확인에 대해 `groupPolicy="allowlist"`로 폴백합니다(`channels.defaults.groupPolicy`가 설정되어 있더라도).
|
||||
|
||||
LINE ID는 대소문자를 구분합니다. 유효한 ID 형식은 다음과 같습니다.
|
||||
|
||||
- 사용자: `U` + 32개의 16진수 문자
|
||||
- 그룹: `C` + 32개의 16진수 문자
|
||||
- 룸: `R` + 32개의 16진수 문자
|
||||
|
||||
## 메시지 동작
|
||||
|
||||
- 텍스트는 5000자 단위로 분할됩니다.
|
||||
- Markdown 서식은 제거되며, 코드 블록과 표는 가능한 경우 Flex 카드로 변환됩니다.
|
||||
- 스트리밍 응답은 버퍼링되며, 에이전트가 작업하는 동안 LINE는 로딩 애니메이션과 함께 전체 청크를 받습니다.
|
||||
- 미디어 다운로드는 `channels.line.mediaMaxMb`(기본값 10)로 제한됩니다.
|
||||
|
||||
## 채널 데이터(리치 메시지)
|
||||
|
||||
빠른 답장, 위치, Flex 카드 또는 템플릿 메시지를 보내려면 `channelData.line`을 사용하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
text: "Here you go",
|
||||
channelData: {
|
||||
line: {
|
||||
quickReplies: ["Status", "Help"],
|
||||
location: {
|
||||
title: "Office",
|
||||
address: "123 Main St",
|
||||
latitude: 35.681236,
|
||||
longitude: 139.767125,
|
||||
},
|
||||
flexMessage: {
|
||||
altText: "Status card",
|
||||
contents: {
|
||||
/* Flex payload */
|
||||
},
|
||||
},
|
||||
templateMessage: {
|
||||
type: "confirm",
|
||||
text: "Proceed?",
|
||||
confirmLabel: "Yes",
|
||||
confirmData: "yes",
|
||||
cancelLabel: "No",
|
||||
cancelData: "no",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
LINE plugin에는 Flex 메시지 프리셋용 `/card` 명령도 포함되어 있습니다.
|
||||
|
||||
```
|
||||
/card info "Welcome" "Thanks for joining!"
|
||||
```
|
||||
|
||||
## ACP 지원
|
||||
|
||||
LINE는 ACP(Agent Communication Protocol) 대화 바인딩을 지원합니다.
|
||||
|
||||
- `/acp spawn <agent> --bind here`는 하위 스레드를 만들지 않고 현재 LINE 채팅을 ACP 세션에 바인딩합니다.
|
||||
- 구성된 ACP 바인딩과 활성 대화 바운드 ACP 세션은 다른 대화 채널과 마찬가지로 LINE에서 작동합니다.
|
||||
|
||||
자세한 내용은 [ACP 에이전트](/tools/acp-agents)를 참조하세요.
|
||||
|
||||
## 아웃바운드 미디어
|
||||
|
||||
LINE plugin은 에이전트 메시지 도구를 통해 이미지, 비디오, 오디오 파일 전송을 지원합니다. 미디어는 적절한 미리보기 및 추적 처리를 포함한 LINE 전용 전달 경로를 통해 전송됩니다.
|
||||
|
||||
- **이미지**: 자동 미리보기 생성과 함께 LINE 이미지 메시지로 전송됩니다.
|
||||
- **비디오**: 명시적인 미리보기 및 content-type 처리와 함께 전송됩니다.
|
||||
- **오디오**: LINE 오디오 메시지로 전송됩니다.
|
||||
|
||||
일반 미디어 전송은 LINE 전용 경로를 사용할 수 없을 때 기존 이미지 전용 경로로 폴백합니다.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
- **Webhook 검증 실패:** webhook URL이 HTTPS인지, 그리고 `channelSecret`이 LINE Console과 일치하는지 확인하세요.
|
||||
- **인바운드 이벤트 없음:** webhook 경로가 `channels.line.webhookPath`와 일치하는지, 그리고 gateway가 LINE에서 도달 가능한지 확인하세요.
|
||||
- **미디어 다운로드 오류:** 미디어가 기본 제한을 초과하는 경우 `channels.line.mediaMaxMb`를 늘리세요.
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 강화
|
||||
63
docs/ko/channels/location.md
Normal file
63
docs/ko/channels/location.md
Normal file
@ -0,0 +1,63 @@
|
||||
---
|
||||
read_when:
|
||||
- 채널 위치 파싱을 추가하거나 수정할 때
|
||||
- 에이전트 프롬프트나 도구에서 위치 컨텍스트 필드를 사용할 때
|
||||
summary: 수신 채널 위치 파싱(Telegram/WhatsApp/Matrix) 및 컨텍스트 필드
|
||||
title: 채널 위치 파싱
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:11Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 10061f0c109240a9e0bcab649b17f03b674e8bdf410debf3669b7b6da8189d96
|
||||
source_path: channels/location.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 채널 위치 파싱
|
||||
|
||||
OpenClaw는 채팅 채널에서 공유된 위치를 다음 형식으로 정규화합니다:
|
||||
|
||||
- 수신 본문에 추가되는 사람이 읽기 쉬운 텍스트, 그리고
|
||||
- 자동 응답 컨텍스트 페이로드의 구조화된 필드.
|
||||
|
||||
현재 지원 항목:
|
||||
|
||||
- **Telegram** (위치 핀 + 장소 + 실시간 위치)
|
||||
- **WhatsApp** (`locationMessage` + `liveLocationMessage`)
|
||||
- **Matrix** (`geo_uri`가 있는 `m.location`)
|
||||
|
||||
## 텍스트 형식
|
||||
|
||||
위치는 대괄호 없이 읽기 쉬운 줄로 렌더링됩니다:
|
||||
|
||||
- 핀:
|
||||
- `📍 48.858844, 2.294351 ±12m`
|
||||
- 이름 있는 장소:
|
||||
- `📍 Eiffel Tower — Champ de Mars, Paris (48.858844, 2.294351 ±12m)`
|
||||
- 실시간 공유:
|
||||
- `🛰 실시간 위치: 48.858844, 2.294351 ±12m`
|
||||
|
||||
채널에 캡션/코멘트가 포함되어 있으면 다음 줄에 추가됩니다:
|
||||
|
||||
```
|
||||
📍 48.858844, 2.294351 ±12m
|
||||
여기서 만나요
|
||||
```
|
||||
|
||||
## 컨텍스트 필드
|
||||
|
||||
위치가 있으면 다음 필드가 `ctx`에 추가됩니다:
|
||||
|
||||
- `LocationLat` (숫자)
|
||||
- `LocationLon` (숫자)
|
||||
- `LocationAccuracy` (숫자, 미터; 선택 사항)
|
||||
- `LocationName` (문자열; 선택 사항)
|
||||
- `LocationAddress` (문자열; 선택 사항)
|
||||
- `LocationSource` (`pin | place | live`)
|
||||
- `LocationIsLive` (불리언)
|
||||
|
||||
## 채널 참고 사항
|
||||
|
||||
- **Telegram**: 장소는 `LocationName/LocationAddress`에 매핑되며, 실시간 위치는 `live_period`를 사용합니다.
|
||||
- **WhatsApp**: `locationMessage.comment`와 `liveLocationMessage.caption`은 캡션 줄에 추가됩니다.
|
||||
- **Matrix**: `geo_uri`는 핀 위치로 파싱되며, 고도는 무시되고 `LocationIsLive`는 항상 false입니다.
|
||||
868
docs/ko/channels/matrix.md
Normal file
868
docs/ko/channels/matrix.md
Normal file
@ -0,0 +1,868 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw에서 Matrix를 설정할 때
|
||||
- Matrix E2EE 및 검증을 구성할 때
|
||||
summary: Matrix 지원 상태, 설정 방법 및 구성 예시
|
||||
title: Matrix
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:20Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ba5c49ad2125d97adf66b5517f8409567eff8b86e20224a32fcb940a02cb0659
|
||||
source_path: channels/matrix.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Matrix
|
||||
|
||||
Matrix는 OpenClaw용 Matrix 번들 채널 plugin입니다.
|
||||
공식 `matrix-js-sdk`를 사용하며 DM, room, thread, media, reaction, poll, location, E2EE를 지원합니다.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
Matrix는 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 있으므로, 일반적인
|
||||
패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
이전 빌드 또는 Matrix가 제외된 사용자 지정 설치를 사용 중이라면,
|
||||
수동으로 설치하세요:
|
||||
|
||||
npm에서 설치:
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/matrix
|
||||
```
|
||||
|
||||
로컬 체크아웃에서 설치:
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./path/to/local/matrix-plugin
|
||||
```
|
||||
|
||||
plugin 동작 및 설치 규칙은 [Plugins](/tools/plugin)를 참조하세요.
|
||||
|
||||
## 설정
|
||||
|
||||
1. Matrix plugin을 사용할 수 있는지 확인합니다.
|
||||
- 현재 패키지된 OpenClaw 릴리스에는 이미 포함되어 있습니다.
|
||||
- 이전/사용자 지정 설치에서는 위 명령으로 수동 추가할 수 있습니다.
|
||||
2. homeserver에 Matrix 계정을 만듭니다.
|
||||
3. `channels.matrix`를 다음 중 하나로 구성합니다:
|
||||
- `homeserver` + `accessToken`, 또는
|
||||
- `homeserver` + `userId` + `password`.
|
||||
4. 게이트웨이를 다시 시작합니다.
|
||||
5. 봇과 DM을 시작하거나 room에 초대합니다.
|
||||
|
||||
대화형 설정 경로:
|
||||
|
||||
```bash
|
||||
openclaw channels add
|
||||
openclaw configure --section channels
|
||||
```
|
||||
|
||||
Matrix 마법사가 실제로 묻는 항목:
|
||||
|
||||
- homeserver URL
|
||||
- 인증 방식: 액세스 토큰 또는 비밀번호
|
||||
- 비밀번호 인증을 선택한 경우에만 user ID
|
||||
- 선택적 device 이름
|
||||
- E2EE 활성화 여부
|
||||
- 지금 Matrix room 접근을 구성할지 여부
|
||||
|
||||
알아두어야 할 마법사 동작:
|
||||
|
||||
- 선택한 계정에 대해 Matrix 인증 env var가 이미 존재하고, 해당 계정의 인증이 아직 config에 저장되지 않은 경우, 마법사는 env 바로가기를 제안하고 해당 계정에 `enabled: true`만 기록합니다.
|
||||
- 다른 Matrix 계정을 대화형으로 추가하면, 입력한 계정 이름이 config와 env var에 사용되는 account ID로 정규화됩니다. 예를 들어 `Ops Bot`은 `ops-bot`이 됩니다.
|
||||
- DM 허용 목록 프롬프트는 전체 `@user:server` 값을 즉시 받을 수 있습니다. 표시 이름은 실시간 디렉터리 조회에서 정확히 하나의 일치 항목을 찾은 경우에만 작동하며, 그렇지 않으면 마법사가 전체 Matrix ID로 다시 시도하라고 요청합니다.
|
||||
- Room 허용 목록 프롬프트는 room ID와 alias를 직접 받을 수 있습니다. 참가 중인 room 이름도 실시간으로 확인할 수 있지만, 확인되지 않은 이름은 설정 중 입력된 그대로만 유지되며 이후 런타임 허용 목록 해석에서는 무시됩니다. `!room:server` 또는 `#alias:server`를 권장합니다.
|
||||
- 런타임 room/세션 식별은 안정적인 Matrix room ID를 사용합니다. room에 선언된 alias는 조회 입력으로만 사용되며, 장기 세션 키나 안정적인 그룹 식별자로는 사용되지 않습니다.
|
||||
- 저장 전에 room 이름을 해석하려면 `openclaw channels resolve --channel matrix "Project Room"`를 사용하세요.
|
||||
|
||||
최소 토큰 기반 설정:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_xxx",
|
||||
dm: { policy: "pairing" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
비밀번호 기반 설정(로그인 후 토큰이 캐시됨):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
password: "replace-me", // pragma: allowlist secret
|
||||
deviceName: "OpenClaw Gateway",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Matrix는 캐시된 자격 증명을 `~/.openclaw/credentials/matrix/`에 저장합니다.
|
||||
기본 계정은 `credentials.json`을 사용하고, 이름 있는 계정은 `credentials-<account>.json`을 사용합니다.
|
||||
|
||||
환경 변수 대응 항목(config 키가 설정되지 않은 경우 사용됨):
|
||||
|
||||
- `MATRIX_HOMESERVER`
|
||||
- `MATRIX_ACCESS_TOKEN`
|
||||
- `MATRIX_USER_ID`
|
||||
- `MATRIX_PASSWORD`
|
||||
- `MATRIX_DEVICE_ID`
|
||||
- `MATRIX_DEVICE_NAME`
|
||||
|
||||
기본이 아닌 계정에는 계정 범위 env var를 사용합니다:
|
||||
|
||||
- `MATRIX_<ACCOUNT_ID>_HOMESERVER`
|
||||
- `MATRIX_<ACCOUNT_ID>_ACCESS_TOKEN`
|
||||
- `MATRIX_<ACCOUNT_ID>_USER_ID`
|
||||
- `MATRIX_<ACCOUNT_ID>_PASSWORD`
|
||||
- `MATRIX_<ACCOUNT_ID>_DEVICE_ID`
|
||||
- `MATRIX_<ACCOUNT_ID>_DEVICE_NAME`
|
||||
|
||||
계정 `ops` 예시:
|
||||
|
||||
- `MATRIX_OPS_HOMESERVER`
|
||||
- `MATRIX_OPS_ACCESS_TOKEN`
|
||||
|
||||
정규화된 계정 ID `ops-bot`에는 다음을 사용합니다:
|
||||
|
||||
- `MATRIX_OPS_X2D_BOT_HOMESERVER`
|
||||
- `MATRIX_OPS_X2D_BOT_ACCESS_TOKEN`
|
||||
|
||||
Matrix는 계정 ID의 구두점을 이스케이프하여 범위 지정 env var 충돌을 방지합니다.
|
||||
예를 들어 `-`는 `_X2D_`가 되므로 `ops-prod`는 `MATRIX_OPS_X2D_PROD_*`에 매핑됩니다.
|
||||
|
||||
대화형 마법사는 해당 인증 env var가 이미 존재하고 선택한 계정에 Matrix 인증이 아직 config에 저장되지 않은 경우에만 env-var 바로가기를 제안합니다.
|
||||
|
||||
## 구성 예시
|
||||
|
||||
다음은 DM 페어링, room 허용 목록, E2EE 활성화를 포함한 실용적인 기준 구성입니다:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_xxx",
|
||||
encryption: true,
|
||||
|
||||
dm: {
|
||||
policy: "pairing",
|
||||
threadReplies: "off",
|
||||
},
|
||||
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["@admin:example.org"],
|
||||
groups: {
|
||||
"!roomid:example.org": {
|
||||
requireMention: true,
|
||||
},
|
||||
},
|
||||
|
||||
autoJoin: "allowlist",
|
||||
autoJoinAllowlist: ["!roomid:example.org"],
|
||||
threadReplies: "inbound",
|
||||
replyToMode: "off",
|
||||
streaming: "partial",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 스트리밍 미리보기
|
||||
|
||||
Matrix 답장 스트리밍은 opt-in입니다.
|
||||
|
||||
모델이 텍스트를 생성하는 동안 OpenClaw가 단일 초안 답장을 보내고,
|
||||
그 초안을 제자리에서 수정한 뒤, 답장이
|
||||
완료되면 최종 확정하도록 하려면 `channels.matrix.streaming`을 `"partial"`로 설정하세요:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
streaming: "partial",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
- `streaming: "off"`가 기본값입니다. OpenClaw는 최종 답장을 기다렸다가 한 번만 전송합니다.
|
||||
- `streaming: "partial"`은 여러 개의 부분 메시지를 보내는 대신 현재 assistant 블록에 대해 수정 가능한 미리보기 메시지 하나를 생성합니다.
|
||||
- `blockStreaming: true`는 별도의 Matrix 진행 메시지를 활성화합니다. `streaming: "partial"`과 함께 사용하면 Matrix는 현재 블록의 실시간 초안을 유지하고 완료된 블록은 별도 메시지로 보존합니다.
|
||||
- `streaming: "partial"`이고 `blockStreaming`이 꺼져 있으면, Matrix는 실시간 초안만 수정하고 해당 블록 또는 턴이 끝나면 완료된 답장을 한 번 전송합니다.
|
||||
- 미리보기가 더 이상 하나의 Matrix 이벤트에 맞지 않으면, OpenClaw는 미리보기 스트리밍을 중단하고 일반 최종 전달로 대체합니다.
|
||||
- 미디어 답장은 여전히 첨부파일을 일반 방식으로 전송합니다. 오래된 미리보기를 더 이상 안전하게 재사용할 수 없으면 OpenClaw는 최종 미디어 답장을 보내기 전에 이를 redaction 처리합니다.
|
||||
- 미리보기 수정에는 추가 Matrix API 호출 비용이 듭니다. 가장 보수적인 속도 제한 동작을 원하면 스트리밍을 끄세요.
|
||||
|
||||
`blockStreaming`만으로는 초안 미리보기가 활성화되지 않습니다.
|
||||
미리보기 수정을 위해서는 `streaming: "partial"`을 사용하고, 완료된 assistant 블록도 별도 진행 메시지로 유지하려면 그다음 `blockStreaming: true`를 추가하세요.
|
||||
|
||||
## 암호화 및 검증
|
||||
|
||||
암호화된(E2EE) room에서 발신 이미지 이벤트는 `thumbnail_file`을 사용하므로 이미지 미리보기도 전체 첨부파일과 함께 암호화됩니다. 암호화되지 않은 room은 계속 일반 `thumbnail_url`을 사용합니다. 별도 구성은 필요하지 않습니다. plugin이 E2EE 상태를 자동 감지합니다.
|
||||
|
||||
### 봇 간 room
|
||||
|
||||
기본적으로 다른 구성된 OpenClaw Matrix 계정의 Matrix 메시지는 무시됩니다.
|
||||
|
||||
에이전트 간 Matrix 트래픽을 의도적으로 허용하려면 `allowBots`를 사용하세요:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
allowBots: "mentions", // true | "mentions"
|
||||
groups: {
|
||||
"!roomid:example.org": {
|
||||
requireMention: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
- `allowBots: true`는 허용된 room과 DM에서 다른 구성된 Matrix 봇 계정의 메시지를 허용합니다.
|
||||
- `allowBots: "mentions"`는 room에서 해당 메시지가 이 봇을 명시적으로 멘션할 때만 허용합니다. DM은 여전히 허용됩니다.
|
||||
- `groups.<room>.allowBots`는 하나의 room에 대해 계정 수준 설정을 재정의합니다.
|
||||
- OpenClaw는 자기 자신에게 답장하는 루프를 방지하기 위해 동일한 Matrix user ID의 메시지는 계속 무시합니다.
|
||||
- 여기서 Matrix는 기본적인 bot 플래그를 제공하지 않습니다. OpenClaw는 "봇이 작성한"을 "이 OpenClaw 게이트웨이에서 구성된 다른 Matrix 계정이 보낸" 것으로 간주합니다.
|
||||
|
||||
공유 room에서 봇 간 트래픽을 활성화할 때는 엄격한 room 허용 목록과 멘션 요구 사항을 사용하세요.
|
||||
|
||||
암호화 활성화:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
enabled: true,
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_xxx",
|
||||
encryption: true,
|
||||
dm: { policy: "pairing" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
검증 상태 확인:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify status
|
||||
```
|
||||
|
||||
자세한 상태(전체 진단):
|
||||
|
||||
```bash
|
||||
openclaw matrix verify status --verbose
|
||||
```
|
||||
|
||||
저장된 복구 키를 기계 판독 가능한 출력에 포함:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify status --include-recovery-key --json
|
||||
```
|
||||
|
||||
교차 서명 및 검증 상태 부트스트랩:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify bootstrap
|
||||
```
|
||||
|
||||
다중 계정 지원: 계정별 자격 증명과 선택적 `name`이 포함된 `channels.matrix.accounts`를 사용하세요. 공통 패턴은 [구성 참조](/gateway/configuration-reference#multi-account-all-channels)를 참조하세요.
|
||||
|
||||
자세한 부트스트랩 진단:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify bootstrap --verbose
|
||||
```
|
||||
|
||||
부트스트랩 전에 새 교차 서명 ID 재설정을 강제:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify bootstrap --force-reset-cross-signing
|
||||
```
|
||||
|
||||
복구 키로 이 device 검증:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify device "<your-recovery-key>"
|
||||
```
|
||||
|
||||
자세한 device 검증 정보:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify device "<your-recovery-key>" --verbose
|
||||
```
|
||||
|
||||
room-key 백업 상태 확인:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup status
|
||||
```
|
||||
|
||||
자세한 백업 상태 진단:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup status --verbose
|
||||
```
|
||||
|
||||
서버 백업에서 room key 복원:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup restore
|
||||
```
|
||||
|
||||
자세한 복원 진단:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup restore --verbose
|
||||
```
|
||||
|
||||
현재 서버 백업을 삭제하고 새 백업 기준선을 만듭니다. 저장된
|
||||
백업 키를 정상적으로 로드할 수 없으면, 이 재설정은 이후 콜드 스타트에서
|
||||
새 백업 키를 로드할 수 있도록 secret storage를 다시 생성할 수도 있습니다:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup reset --yes
|
||||
```
|
||||
|
||||
모든 `verify` 명령은 기본적으로 간결하며(내부 SDK의 조용한 로깅 포함), `--verbose`를 사용할 때만 자세한 진단을 표시합니다.
|
||||
스크립트에서는 전체 기계 판독 가능 출력을 위해 `--json`을 사용하세요.
|
||||
|
||||
다중 계정 설정에서 Matrix CLI 명령은 `--account <id>`를 전달하지 않으면 암묵적인 Matrix 기본 계정을 사용합니다.
|
||||
이름 있는 계정을 여러 개 구성한 경우 `channels.matrix.defaultAccount`를 먼저 설정하지 않으면, 이러한 암묵적 CLI 작업은 중단되고 계정을 명시적으로 선택하라고 요청합니다.
|
||||
검증 또는 device 작업이 이름 있는 계정을 명시적으로 대상으로 하도록 하려면 항상 `--account`를 사용하세요:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify status --account assistant
|
||||
openclaw matrix verify backup restore --account assistant
|
||||
openclaw matrix devices list --account assistant
|
||||
```
|
||||
|
||||
이름 있는 계정에서 암호화가 비활성화되었거나 사용할 수 없는 경우, Matrix 경고와 검증 오류는 해당 계정의 config 키를 가리킵니다. 예: `channels.matrix.accounts.assistant.encryption`.
|
||||
|
||||
### "검증됨"의 의미
|
||||
|
||||
OpenClaw는 이 Matrix device가 사용자 자신의 교차 서명 ID에 의해 검증된 경우에만 검증된 것으로 간주합니다.
|
||||
실제로 `openclaw matrix verify status --verbose`는 세 가지 신뢰 신호를 표시합니다:
|
||||
|
||||
- `Locally trusted`: 이 device는 현재 클라이언트에서만 신뢰됨
|
||||
- `Cross-signing verified`: SDK가 이 device를 교차 서명을 통해 검증된 것으로 보고함
|
||||
- `Signed by owner`: 이 device가 자신의 self-signing key로 서명됨
|
||||
|
||||
`Verified by owner`는 교차 서명 검증 또는 소유자 서명이 있을 때만 `yes`가 됩니다.
|
||||
로컬 신뢰만으로는 OpenClaw가 이 device를 완전히 검증된 것으로 취급하기에 충분하지 않습니다.
|
||||
|
||||
### bootstrap이 하는 일
|
||||
|
||||
`openclaw matrix verify bootstrap`은 암호화된 Matrix 계정의 복구 및 설정 명령입니다.
|
||||
다음 작업을 순서대로 수행합니다:
|
||||
|
||||
- 가능하면 기존 복구 키를 재사용하며 secret storage를 bootstrap
|
||||
- 교차 서명을 bootstrap하고 누락된 공개 교차 서명 키를 업로드
|
||||
- 현재 device를 표시하고 교차 서명하려 시도
|
||||
- 기존 서버 측 room-key 백업이 없으면 새로 생성
|
||||
|
||||
homeserver가 교차 서명 키 업로드에 상호작용 인증을 요구하는 경우, OpenClaw는 먼저 인증 없이 업로드를 시도하고, 다음으로 `m.login.dummy`, 마지막으로 `channels.matrix.password`가 구성된 경우 `m.login.password`로 시도합니다.
|
||||
|
||||
현재 교차 서명 ID를 버리고 새로 만들 의도가 있을 때만 `--force-reset-cross-signing`을 사용하세요.
|
||||
|
||||
현재 room-key 백업을 의도적으로 버리고 향후 메시지에 대한 새
|
||||
백업 기준선을 시작하려면 `openclaw matrix verify backup reset --yes`를 사용하세요.
|
||||
복구할 수 없는 이전 암호화 기록이 계속
|
||||
사용 불가능한 상태로 남을 수 있고, 현재 백업 secret을 안전하게 로드할 수 없는 경우 OpenClaw가 secret storage를 다시 만들 수 있다는 점을 받아들일 때만 수행하세요.
|
||||
|
||||
### 새 백업 기준선
|
||||
|
||||
향후 암호화된 메시지는 계속 작동하도록 유지하되 복구 불가능한 이전 기록 손실을 감수할 수 있다면, 다음 명령을 순서대로 실행하세요:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup reset --yes
|
||||
openclaw matrix verify backup status --verbose
|
||||
openclaw matrix verify status
|
||||
```
|
||||
|
||||
이름 있는 Matrix 계정을 명시적으로 대상으로 하려면 각 명령에 `--account <id>`를 추가하세요.
|
||||
|
||||
### 시작 동작
|
||||
|
||||
`encryption: true`일 때 Matrix는 기본적으로 `startupVerification`을 `"if-unverified"`로 설정합니다.
|
||||
시작 시 이 device가 아직 검증되지 않았다면, Matrix는 다른 Matrix 클라이언트에서 self-verification을 요청하고,
|
||||
이미 보류 중인 요청이 있으면 중복 요청을 건너뛰며, 재시작 후 재시도 전에 로컬 쿨다운을 적용합니다.
|
||||
실패한 요청 시도는 기본적으로 성공적으로 요청을 만든 경우보다 더 빨리 재시도합니다.
|
||||
자동 시작 요청을 비활성화하려면 `startupVerification: "off"`로 설정하거나, 더 짧거나 긴 재시도 창이 필요하면 `startupVerificationCooldownHours`를 조정하세요.
|
||||
|
||||
시작 시에는 보수적인 crypto bootstrap 단계도 자동으로 수행됩니다.
|
||||
이 단계는 먼저 현재 secret storage와 교차 서명 ID를 재사용하려고 하며, 명시적인 bootstrap 복구 흐름을 실행하지 않는 한 교차 서명을 재설정하지 않습니다.
|
||||
|
||||
시작 시 손상된 bootstrap 상태를 발견하고 `channels.matrix.password`가 구성되어 있으면, OpenClaw는 더 엄격한 복구 경로를 시도할 수 있습니다.
|
||||
현재 device가 이미 owner-signed 상태라면 OpenClaw는 이를 자동 재설정하지 않고 해당 ID를 보존합니다.
|
||||
|
||||
이전 공개 Matrix plugin에서 업그레이드할 때:
|
||||
|
||||
- OpenClaw는 가능하면 동일한 Matrix 계정, 액세스 토큰, device ID를 자동으로 재사용합니다.
|
||||
- 실행 가능한 Matrix 마이그레이션 변경이 수행되기 전에 OpenClaw는 `~/Backups/openclaw-migrations/` 아래에 복구 스냅샷을 생성하거나 재사용합니다.
|
||||
- 여러 Matrix 계정을 사용하는 경우, 이전 flat-store 레이아웃에서 업그레이드하기 전에 `channels.matrix.defaultAccount`를 설정하여 어떤 계정이 해당 공유 레거시 상태를 받아야 하는지 OpenClaw가 알 수 있게 하세요.
|
||||
- 이전 plugin이 Matrix room-key 백업 복호화 키를 로컬에 저장했다면, 시작 시 또는 `openclaw doctor --fix` 실행 시 이를 새 복구 키 흐름으로 자동 가져옵니다.
|
||||
- 마이그레이션 준비 후 Matrix 액세스 토큰이 변경된 경우, 시작 시 자동 백업 복원을 포기하기 전에 보류 중인 레거시 복원 상태가 있는 형제 토큰 해시 저장소 루트를 검색합니다.
|
||||
- 동일 계정, homeserver, user에 대해 나중에 Matrix 액세스 토큰이 변경되면, OpenClaw는 빈 Matrix 상태 디렉터리에서 시작하는 대신 가장 완전한 기존 토큰 해시 저장소 루트를 우선 재사용합니다.
|
||||
- 다음 게이트웨이 시작 시 백업된 room key가 새 crypto 저장소로 자동 복원됩니다.
|
||||
- 이전 plugin에 백업되지 않은 로컬 전용 room key가 있었다면, OpenClaw는 이를 명확히 경고합니다. 해당 key는 이전 rust crypto 저장소에서 자동 내보내기할 수 없으므로 일부 이전 암호화 기록은 수동 복구 전까지 계속 사용할 수 없을 수 있습니다.
|
||||
- 전체 업그레이드 흐름, 제한 사항, 복구 명령, 일반적인 마이그레이션 메시지는 [Matrix migration](/install/migrating-matrix)을 참조하세요.
|
||||
|
||||
암호화된 런타임 상태는 계정별, 사용자별 토큰 해시 루트 아래의
|
||||
`~/.openclaw/matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/`에 구성됩니다.
|
||||
이 디렉터리에는 sync 저장소(`bot-storage.json`), crypto 저장소(`crypto/`),
|
||||
복구 키 파일(`recovery-key.json`), IndexedDB 스냅샷(`crypto-idb-snapshot.json`),
|
||||
thread 바인딩(`thread-bindings.json`), 시작 검증 상태(`startup-verification.json`)가
|
||||
해당 기능 사용 시 포함됩니다.
|
||||
토큰이 변경되더라도 계정 ID가 같으면 OpenClaw는 해당 계정/homeserver/user 튜플에 대해 가장 적합한 기존
|
||||
루트를 재사용하므로 이전 sync 상태, crypto 상태, thread 바인딩,
|
||||
시작 검증 상태를 계속 확인할 수 있습니다.
|
||||
|
||||
### Node crypto 저장소 모델
|
||||
|
||||
이 plugin의 Matrix E2EE는 Node에서 공식 `matrix-js-sdk` Rust crypto 경로를 사용합니다.
|
||||
이 경로는 crypto 상태를 재시작 후에도 유지하려면 IndexedDB 기반 영속성을 기대합니다.
|
||||
|
||||
OpenClaw는 현재 Node에서 다음 방식으로 이를 제공합니다:
|
||||
|
||||
- SDK가 기대하는 IndexedDB API shim으로 `fake-indexeddb` 사용
|
||||
- `initRustCrypto` 전에 `crypto-idb-snapshot.json`에서 Rust crypto IndexedDB 내용을 복원
|
||||
- 초기화 후와 런타임 중에 업데이트된 IndexedDB 내용을 다시 `crypto-idb-snapshot.json`에 저장
|
||||
- gateway 런타임 영속성과 CLI 유지관리 작업이 같은 스냅샷 파일에서 경쟁하지 않도록 advisory 파일 잠금을 사용해 `crypto-idb-snapshot.json`에 대한 스냅샷 복원과 저장을 직렬화
|
||||
|
||||
이는 사용자 지정 crypto 구현이 아니라 호환성/저장소 플러밍입니다.
|
||||
스냅샷 파일은 민감한 런타임 상태이며 제한적인 파일 권한으로 저장됩니다.
|
||||
OpenClaw의 보안 모델에서 gateway host와 로컬 OpenClaw 상태 디렉터리는 이미 신뢰된 운영자 경계 내부에 있으므로, 이는 별도의 원격 신뢰 경계라기보다 주로 운영상 내구성 문제입니다.
|
||||
|
||||
계획된 개선 사항:
|
||||
|
||||
- 영속적인 Matrix key material에 대한 SecretRef 지원을 추가하여 복구 키와 관련 저장소 암호화 secret을 로컬 파일뿐 아니라 OpenClaw secrets provider에서도 가져올 수 있도록 함
|
||||
|
||||
## 프로필 관리
|
||||
|
||||
선택한 계정의 Matrix self-profile을 다음 명령으로 업데이트합니다:
|
||||
|
||||
```bash
|
||||
openclaw matrix profile set --name "OpenClaw Assistant"
|
||||
openclaw matrix profile set --avatar-url https://cdn.example.org/avatar.png
|
||||
```
|
||||
|
||||
이름 있는 Matrix 계정을 명시적으로 대상으로 하려면 `--account <id>`를 추가하세요.
|
||||
|
||||
Matrix는 `mxc://` 아바타 URL을 직접 받을 수 있습니다. `http://` 또는 `https://` 아바타 URL을 전달하면 OpenClaw는 먼저 이를 Matrix에 업로드하고, 해석된 `mxc://` URL을 다시 `channels.matrix.avatarUrl`(또는 선택한 계정 재정의)에 저장합니다.
|
||||
|
||||
## 자동 검증 알림
|
||||
|
||||
이제 Matrix는 strict DM 검증 room에 검증 수명 주기 알림을 `m.notice` 메시지로 직접 게시합니다.
|
||||
여기에는 다음이 포함됩니다:
|
||||
|
||||
- 검증 요청 알림
|
||||
- 검증 준비 알림(명시적인 "Verify by emoji" 안내 포함)
|
||||
- 검증 시작 및 완료 알림
|
||||
- 사용 가능한 경우 SAS 세부 정보(이모지 및 10진수)
|
||||
|
||||
다른 Matrix 클라이언트에서 들어오는 검증 요청은 OpenClaw가 추적하고 자동 수락합니다.
|
||||
self-verification 흐름에서는 이모지 검증을 사용할 수 있게 되면 OpenClaw도 자동으로 SAS 흐름을 시작하고 자체 측을 확인합니다.
|
||||
다른 Matrix 사용자/device의 검증 요청에 대해서는 OpenClaw가 요청을 자동 수락한 뒤 SAS 흐름이 정상적으로 진행되기를 기다립니다.
|
||||
검증을 완료하려면 여전히 Matrix 클라이언트에서 이모지 또는 10진수 SAS를 비교하고 그곳에서 "They match"를 확인해야 합니다.
|
||||
|
||||
OpenClaw는 self-initiated duplicate flow를 무작정 자동 수락하지 않습니다. 시작 시 self-verification 요청이 이미 보류 중이면 새 요청 생성을 건너뜁니다.
|
||||
|
||||
검증 프로토콜/시스템 알림은 에이전트 채팅 파이프라인으로 전달되지 않으므로 `NO_REPLY`를 생성하지 않습니다.
|
||||
|
||||
### device 위생
|
||||
|
||||
오래된 OpenClaw 관리 Matrix device가 계정에 누적되면 암호화된 room의 신뢰 상태를 파악하기 어려워질 수 있습니다.
|
||||
다음 명령으로 목록을 확인하세요:
|
||||
|
||||
```bash
|
||||
openclaw matrix devices list
|
||||
```
|
||||
|
||||
오래된 OpenClaw 관리 device는 다음 명령으로 제거하세요:
|
||||
|
||||
```bash
|
||||
openclaw matrix devices prune-stale
|
||||
```
|
||||
|
||||
### Direct Room 복구
|
||||
|
||||
direct-message 상태가 어긋나면 OpenClaw는 오래된 단일 room을 가리키는 stale `m.direct` 매핑을 가지게 될 수 있습니다. 피어의 현재 매핑을 확인하려면 다음을 사용하세요:
|
||||
|
||||
```bash
|
||||
openclaw matrix direct inspect --user-id @alice:example.org
|
||||
```
|
||||
|
||||
다음으로 복구할 수 있습니다:
|
||||
|
||||
```bash
|
||||
openclaw matrix direct repair --user-id @alice:example.org
|
||||
```
|
||||
|
||||
복구는 Matrix 전용 로직을 plugin 내부에 유지합니다:
|
||||
|
||||
- 먼저 `m.direct`에 이미 매핑된 엄격한 1:1 DM을 우선 사용
|
||||
- 그렇지 않으면 해당 사용자와 현재 참가 중인 엄격한 1:1 DM으로 대체
|
||||
- 정상적인 DM이 없으면 새 direct room을 생성하고 `m.direct`를 다시 써서 그것을 가리키게 함
|
||||
|
||||
복구 흐름은 오래된 room을 자동 삭제하지 않습니다. 정상적인 DM을 선택하고 매핑만 업데이트하여 이후 Matrix 전송, 검증 알림 및 기타 direct-message 흐름이 다시 올바른 room을 대상으로 하게 합니다.
|
||||
|
||||
## Threads
|
||||
|
||||
Matrix는 자동 답장과 message-tool 전송 모두에 대해 기본 Matrix thread를 지원합니다.
|
||||
|
||||
- `threadReplies: "off"`는 답장을 최상위 수준으로 유지하고 수신 thread 메시지를 부모 세션에 유지합니다.
|
||||
- `threadReplies: "inbound"`는 수신 메시지가 이미 해당 thread에 있을 때만 thread 내부에서 답장합니다.
|
||||
- `threadReplies: "always"`는 room 답장을 트리거 메시지를 루트로 하는 thread에 유지하고, 첫 트리거 메시지부터 일치하는 thread 범위 세션을 통해 해당 대화를 라우팅합니다.
|
||||
- `dm.threadReplies`는 DM에 대해서만 최상위 설정을 재정의합니다. 예를 들어 room thread는 분리하면서 DM은 평면으로 유지할 수 있습니다.
|
||||
- 수신 thread 메시지에는 추가 에이전트 컨텍스트로 thread 루트 메시지가 포함됩니다.
|
||||
- 이제 message-tool 전송은 대상이 같은 room이거나 같은 DM 사용자 대상인 경우, 명시적인 `threadId`가 제공되지 않으면 현재 Matrix thread를 자동 상속합니다.
|
||||
- Matrix는 런타임 thread 바인딩을 지원합니다. 이제 `/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`, thread에 바인딩된 `/acp spawn`이 Matrix room과 DM에서 작동합니다.
|
||||
- `threadBindings.spawnSubagentSessions=true`일 때 최상위 Matrix room/DM의 `/focus`는 새 Matrix thread를 만들고 이를 대상 세션에 바인딩합니다.
|
||||
- 기존 Matrix thread 안에서 `/focus` 또는 `/acp spawn --thread here`를 실행하면 현재 thread가 대신 바인딩됩니다.
|
||||
|
||||
## ACP 대화 바인딩
|
||||
|
||||
Matrix room, DM, 기존 Matrix thread는 채팅 표면을 바꾸지 않고도 영속적인 ACP 워크스페이스로 전환할 수 있습니다.
|
||||
|
||||
빠른 운영자 흐름:
|
||||
|
||||
- 계속 사용할 Matrix DM, room 또는 기존 thread 안에서 `/acp spawn codex --bind here`를 실행합니다.
|
||||
- 최상위 Matrix DM 또는 room에서는 현재 DM/room이 채팅 표면으로 유지되고 이후 메시지는 생성된 ACP 세션으로 라우팅됩니다.
|
||||
- 기존 Matrix thread 안에서는 `--bind here`가 현재 thread를 제자리에서 바인딩합니다.
|
||||
- `/new`와 `/reset`은 동일한 바인딩된 ACP 세션을 제자리에서 재설정합니다.
|
||||
- `/acp close`는 ACP 세션을 닫고 바인딩을 제거합니다.
|
||||
|
||||
참고:
|
||||
|
||||
- `--bind here`는 하위 Matrix thread를 생성하지 않습니다.
|
||||
- `threadBindings.spawnAcpSessions`는 OpenClaw가 하위 Matrix thread를 만들거나 바인딩해야 하는 `/acp spawn --thread auto|here`에만 필요합니다.
|
||||
|
||||
### Thread 바인딩 구성
|
||||
|
||||
Matrix는 `session.threadBindings`의 전역 기본값을 상속하며, 채널별 재정의도 지원합니다:
|
||||
|
||||
- `threadBindings.enabled`
|
||||
- `threadBindings.idleHours`
|
||||
- `threadBindings.maxAgeHours`
|
||||
- `threadBindings.spawnSubagentSessions`
|
||||
- `threadBindings.spawnAcpSessions`
|
||||
|
||||
Matrix thread 바인딩된 spawn 플래그는 opt-in입니다:
|
||||
|
||||
- 최상위 `/focus`가 새 Matrix thread를 만들고 바인딩하도록 허용하려면 `threadBindings.spawnSubagentSessions: true`를 설정하세요.
|
||||
- `/acp spawn --thread auto|here`가 ACP 세션을 Matrix thread에 바인딩하도록 허용하려면 `threadBindings.spawnAcpSessions: true`를 설정하세요.
|
||||
|
||||
## Reactions
|
||||
|
||||
Matrix는 발신 reaction 작업, 수신 reaction 알림, 수신 ack reaction을 지원합니다.
|
||||
|
||||
- 발신 reaction tooling은 `channels["matrix"].actions.reactions`로 게이트됩니다.
|
||||
- `react`는 특정 Matrix 이벤트에 reaction을 추가합니다.
|
||||
- `reactions`는 특정 Matrix 이벤트의 현재 reaction 요약을 나열합니다.
|
||||
- `emoji=""`는 해당 이벤트에 대한 봇 계정 자신의 reaction을 제거합니다.
|
||||
- `remove: true`는 봇 계정의 지정된 이모지 reaction만 제거합니다.
|
||||
|
||||
ack reaction은 표준 OpenClaw 해석 순서를 사용합니다:
|
||||
|
||||
- `channels["matrix"].accounts.<accountId>.ackReaction`
|
||||
- `channels["matrix"].ackReaction`
|
||||
- `messages.ackReaction`
|
||||
- 에이전트 ID 이모지 대체값
|
||||
|
||||
ack reaction 범위는 다음 순서로 해석됩니다:
|
||||
|
||||
- `channels["matrix"].accounts.<accountId>.ackReactionScope`
|
||||
- `channels["matrix"].ackReactionScope`
|
||||
- `messages.ackReactionScope`
|
||||
|
||||
reaction 알림 모드는 다음 순서로 해석됩니다:
|
||||
|
||||
- `channels["matrix"].accounts.<accountId>.reactionNotifications`
|
||||
- `channels["matrix"].reactionNotifications`
|
||||
- 기본값: `own`
|
||||
|
||||
현재 동작:
|
||||
|
||||
- `reactionNotifications: "own"`은 봇이 작성한 Matrix 메시지를 대상으로 하는 추가된 `m.reaction` 이벤트를 전달합니다.
|
||||
- `reactionNotifications: "off"`는 reaction 시스템 이벤트를 비활성화합니다.
|
||||
- Matrix는 제거를 독립적인 `m.reaction` 제거가 아니라 redaction으로 표시하므로, reaction 제거는 아직 시스템 이벤트로 합성되지 않습니다.
|
||||
|
||||
## 기록 컨텍스트
|
||||
|
||||
- `channels.matrix.historyLimit`는 Matrix room 메시지가 에이전트를 트리거할 때 `InboundHistory`로 포함할 최근 room 메시지 수를 제어합니다.
|
||||
- 기본값은 `messages.groupChat.historyLimit`를 따릅니다. 비활성화하려면 `0`으로 설정하세요.
|
||||
- Matrix room 기록은 room 전용입니다. DM은 계속 일반 세션 기록을 사용합니다.
|
||||
- Matrix room 기록은 pending-only입니다. OpenClaw는 아직 답장을 트리거하지 않은 room 메시지를 버퍼링한 뒤, 멘션이나 다른 트리거가 들어오면 그 구간을 스냅샷으로 저장합니다.
|
||||
- 현재 트리거 메시지는 `InboundHistory`에 포함되지 않으며, 해당 턴의 메인 수신 본문에 남아 있습니다.
|
||||
- 동일한 Matrix 이벤트를 재시도할 때는 새 room 메시지로 앞으로 이동하지 않고 원래 기록 스냅샷을 재사용합니다.
|
||||
|
||||
## 컨텍스트 가시성
|
||||
|
||||
Matrix는 가져온 답장 텍스트, thread 루트, pending history 같은 보조 room 컨텍스트에 대해 공통 `contextVisibility` 제어를 지원합니다.
|
||||
|
||||
- `contextVisibility: "all"`이 기본값입니다. 보조 컨텍스트는 받은 그대로 유지됩니다.
|
||||
- `contextVisibility: "allowlist"`는 활성 room/user 허용 목록 검사에서 허용된 발신자만 보조 컨텍스트에 남깁니다.
|
||||
- `contextVisibility: "allowlist_quote"`는 `allowlist`처럼 동작하지만, 명시적으로 인용된 답장 하나는 계속 유지합니다.
|
||||
|
||||
이 설정은 보조 컨텍스트의 가시성에 영향을 주며, 수신 메시지 자체가 답장을 트리거할 수 있는지 여부에는 영향을 주지 않습니다.
|
||||
트리거 권한은 계속 `groupPolicy`, `groups`, `groupAllowFrom`, DM 정책 설정에서 결정됩니다.
|
||||
|
||||
## DM 및 room 정책 예시
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
dm: {
|
||||
policy: "allowlist",
|
||||
allowFrom: ["@admin:example.org"],
|
||||
threadReplies: "off",
|
||||
},
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["@admin:example.org"],
|
||||
groups: {
|
||||
"!roomid:example.org": {
|
||||
requireMention: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
멘션 게이팅 및 허용 목록 동작은 [Groups](/channels/groups)를 참조하세요.
|
||||
|
||||
Matrix DM용 페어링 예시:
|
||||
|
||||
```bash
|
||||
openclaw pairing list matrix
|
||||
openclaw pairing approve matrix <CODE>
|
||||
```
|
||||
|
||||
승인 전의 Matrix 사용자가 계속 메시지를 보내면, OpenClaw는 동일한 보류 중 페어링 코드를 재사용하며 새 코드를 발급하는 대신 짧은 쿨다운 후 다시 리마인더 답장을 보낼 수 있습니다.
|
||||
|
||||
공통 DM 페어링 흐름 및 저장소 레이아웃은 [페어링](/channels/pairing)을 참조하세요.
|
||||
|
||||
## Exec 승인
|
||||
|
||||
Matrix는 Matrix 계정의 exec 승인 클라이언트로 동작할 수 있습니다.
|
||||
|
||||
- `channels.matrix.execApprovals.enabled`
|
||||
- `channels.matrix.execApprovals.approvers` (선택 사항; 기본값은 `channels.matrix.dm.allowFrom`)
|
||||
- `channels.matrix.execApprovals.target` (`dm` | `channel` | `both`, 기본값: `dm`)
|
||||
- `channels.matrix.execApprovals.agentFilter`
|
||||
- `channels.matrix.execApprovals.sessionFilter`
|
||||
|
||||
승인자는 `@owner:example.org` 같은 Matrix user ID여야 합니다. `enabled`가 설정되지 않았거나 `"auto"`이고 `execApprovals.approvers` 또는 `channels.matrix.dm.allowFrom`에서 하나 이상의 승인자를 해석할 수 있으면 Matrix는 기본 exec 승인을 자동 활성화합니다. Matrix를 기본 승인 클라이언트로 명시적으로 비활성화하려면 `enabled: false`로 설정하세요. 그렇지 않으면 승인 요청은 다른 구성된 승인 경로나 exec 승인 대체 정책으로 넘어갑니다.
|
||||
|
||||
현재 Matrix 기본 라우팅은 exec 전용입니다:
|
||||
|
||||
- `channels.matrix.execApprovals.*`는 exec 승인에 대해서만 기본 DM/채널 라우팅을 제어합니다.
|
||||
- plugin 승인은 계속 공통 same-chat `/approve`와 구성된 `approvals.plugin` 전달을 사용합니다.
|
||||
- Matrix는 승인자를 안전하게 추론할 수 있을 때 plugin 승인 권한 부여를 위해 `channels.matrix.dm.allowFrom`을 재사용할 수 있지만, 별도의 기본 plugin 승인 DM/채널 fanout 경로를 제공하지는 않습니다.
|
||||
|
||||
전달 규칙:
|
||||
|
||||
- `target: "dm"`은 승인 프롬프트를 승인자 DM으로 보냅니다
|
||||
- `target: "channel"`은 프롬프트를 원래 Matrix room 또는 DM으로 다시 보냅니다
|
||||
- `target: "both"`는 승인자 DM과 원래 Matrix room 또는 DM 모두로 보냅니다
|
||||
|
||||
현재 Matrix는 텍스트 승인 프롬프트를 사용합니다. 승인자는 `/approve <id> allow-once`, `/approve <id> allow-always`, 또는 `/approve <id> deny`로 이를 처리합니다.
|
||||
|
||||
해석된 승인자만 승인 또는 거부할 수 있습니다. 채널 전달에는 명령 텍스트가 포함되므로 신뢰할 수 있는 room에서만 `channel` 또는 `both`를 활성화하세요.
|
||||
|
||||
Matrix 승인 프롬프트는 공통 코어 승인 planner를 재사용합니다. Matrix 전용 기본 표면은 exec 승인에 대해서만 전송 계층 역할을 합니다: room/DM 라우팅 및 메시지 전송/업데이트/삭제 동작.
|
||||
|
||||
계정별 재정의:
|
||||
|
||||
- `channels.matrix.accounts.<account>.execApprovals`
|
||||
|
||||
관련 문서: [Exec approvals](/tools/exec-approvals)
|
||||
|
||||
## 다중 계정 예시
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
enabled: true,
|
||||
defaultAccount: "assistant",
|
||||
dm: { policy: "pairing" },
|
||||
accounts: {
|
||||
assistant: {
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_assistant_xxx",
|
||||
encryption: true,
|
||||
},
|
||||
alerts: {
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_alerts_xxx",
|
||||
dm: {
|
||||
policy: "allowlist",
|
||||
allowFrom: ["@ops:example.org"],
|
||||
threadReplies: "off",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
최상위 `channels.matrix` 값은 계정이 재정의하지 않는 한 이름 있는 계정의 기본값으로 동작합니다.
|
||||
상속된 room 항목을 특정 Matrix 계정 하나로 제한하려면 `groups.<room>.account`(또는 레거시 `rooms.<room>.account`)를 사용할 수 있습니다.
|
||||
`account`가 없는 항목은 모든 Matrix 계정에 공통으로 유지되며, 기본 계정이 최상위 `channels.matrix.*`에 직접 구성된 경우 `account: "default"` 항목도 계속 작동합니다.
|
||||
부분적인 공통 인증 기본값만으로는 별도의 암묵적 기본 계정이 생성되지 않습니다. OpenClaw는 해당 기본 계정에 새로운 인증(`homeserver` + `accessToken`, 또는 `homeserver` + `userId` + `password`)이 있을 때만 최상위 `default` 계정을 합성합니다. 이름 있는 계정은 이후 캐시된 자격 증명으로 인증을 만족할 수 있다면 `homeserver` + `userId`만으로도 계속 검색 가능할 수 있습니다.
|
||||
Matrix에 이미 정확히 하나의 이름 있는 계정이 있거나 `defaultAccount`가 기존 이름 있는 계정 키를 가리키는 경우, 단일 계정에서 다중 계정으로의 복구/설정 승격은 새 `accounts.default` 항목을 만드는 대신 해당 계정을 보존합니다. Matrix 인증/bootstrap 키만 해당 승격된 계정으로 이동하며, 공통 전달 정책 키는 최상위에 남습니다.
|
||||
암묵적 라우팅, 프로브, CLI 작업에 대해 OpenClaw가 특정 이름 있는 Matrix 계정을 우선 사용하도록 하려면 `defaultAccount`를 설정하세요.
|
||||
여러 이름 있는 계정을 구성하는 경우, 암묵적 계정 선택에 의존하는 CLI 명령에 대해 `defaultAccount`를 설정하거나 `--account <id>`를 전달하세요.
|
||||
한 명령에 대해 이 암묵적 선택을 재정의하려면 `openclaw matrix verify ...` 및 `openclaw matrix devices ...`에 `--account <id>`를 전달하세요.
|
||||
|
||||
## 비공개/LAN homeserver
|
||||
|
||||
기본적으로 OpenClaw는 SSRF 보호를 위해 private/internal Matrix homeserver를 차단하며,
|
||||
계정별로 명시적으로 opt-in해야만 허용합니다.
|
||||
|
||||
homeserver가 localhost, LAN/Tailscale IP 또는 내부 호스트 이름에서 실행되는 경우,
|
||||
해당 Matrix 계정에 대해 `allowPrivateNetwork`를 활성화하세요:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
homeserver: "http://matrix-synapse:8008",
|
||||
allowPrivateNetwork: true,
|
||||
accessToken: "syt_internal_xxx",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
CLI 설정 예시:
|
||||
|
||||
```bash
|
||||
openclaw matrix account add \
|
||||
--account ops \
|
||||
--homeserver http://matrix-synapse:8008 \
|
||||
--allow-private-network \
|
||||
--access-token syt_ops_xxx
|
||||
```
|
||||
|
||||
이 opt-in은 신뢰된 private/internal 대상만 허용합니다. `http://matrix.example.org:8008` 같은
|
||||
공개 평문 homeserver는 계속 차단됩니다. 가능하면 `https://`를 권장합니다.
|
||||
|
||||
## Matrix 트래픽 프록시
|
||||
|
||||
Matrix 배포에 명시적인 아웃바운드 HTTP(S) 프록시가 필요하면 `channels.matrix.proxy`를 설정하세요:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
matrix: {
|
||||
homeserver: "https://matrix.example.org",
|
||||
accessToken: "syt_bot_xxx",
|
||||
proxy: "http://127.0.0.1:7890",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
이름 있는 계정은 `channels.matrix.accounts.<id>.proxy`로 최상위 기본값을 재정의할 수 있습니다.
|
||||
OpenClaw는 런타임 Matrix 트래픽과 계정 상태 프로브 모두에 동일한 프록시 설정을 사용합니다.
|
||||
|
||||
## 대상 해석
|
||||
|
||||
Matrix는 OpenClaw가 room 또는 user 대상을 요청하는 모든 위치에서 다음 대상 형식을 허용합니다:
|
||||
|
||||
- 사용자: `@user:server`, `user:@user:server`, 또는 `matrix:user:@user:server`
|
||||
- Room: `!room:server`, `room:!room:server`, 또는 `matrix:room:!room:server`
|
||||
- Alias: `#alias:server`, `channel:#alias:server`, 또는 `matrix:channel:#alias:server`
|
||||
|
||||
실시간 디렉터리 조회는 로그인된 Matrix 계정을 사용합니다:
|
||||
|
||||
- 사용자 조회는 해당 homeserver의 Matrix 사용자 디렉터리를 조회합니다.
|
||||
- Room 조회는 명시적인 room ID와 alias를 직접 받고, 이후 해당 계정의 참가 중인 room 이름 검색으로 대체합니다.
|
||||
- 참가 중 room 이름 조회는 best-effort입니다. room 이름을 ID나 alias로 해석할 수 없으면 런타임 허용 목록 해석에서 무시됩니다.
|
||||
|
||||
## 구성 참조
|
||||
|
||||
- `enabled`: 채널 활성화 또는 비활성화.
|
||||
- `name`: 계정의 선택적 레이블.
|
||||
- `defaultAccount`: 여러 Matrix 계정이 구성된 경우 선호되는 account ID.
|
||||
- `homeserver`: homeserver URL(예: `https://matrix.example.org`).
|
||||
- `allowPrivateNetwork`: 이 Matrix 계정이 private/internal homeserver에 연결되도록 허용합니다. homeserver가 `localhost`, LAN/Tailscale IP 또는 `matrix-synapse` 같은 내부 호스트로 해석되는 경우 활성화하세요.
|
||||
- `proxy`: Matrix 트래픽용 선택적 HTTP(S) 프록시 URL. 이름 있는 계정은 자체 `proxy`로 최상위 기본값을 재정의할 수 있습니다.
|
||||
- `userId`: 전체 Matrix user ID(예: `@bot:example.org`).
|
||||
- `accessToken`: 토큰 기반 인증용 액세스 토큰. 일반 텍스트 값과 SecretRef 값은 env/file/exec provider 전반에서 `channels.matrix.accessToken`과 `channels.matrix.accounts.<id>.accessToken`에 지원됩니다. [Secrets Management](/gateway/secrets)를 참조하세요.
|
||||
- `password`: 비밀번호 기반 로그인용 비밀번호. 일반 텍스트 값과 SecretRef 값이 지원됩니다.
|
||||
- `deviceId`: 명시적 Matrix device ID.
|
||||
- `deviceName`: 비밀번호 로그인용 device 표시 이름.
|
||||
- `avatarUrl`: 프로필 동기화 및 `set-profile` 업데이트용으로 저장된 self-avatar URL.
|
||||
- `initialSyncLimit`: 시작 시 sync 이벤트 제한.
|
||||
- `encryption`: E2EE 활성화.
|
||||
- `allowlistOnly`: DM과 room에 대해 허용 목록 전용 동작 강제.
|
||||
- `allowBots`: 다른 구성된 OpenClaw Matrix 계정의 메시지를 허용(`true` 또는 `"mentions"`).
|
||||
- `groupPolicy`: `open`, `allowlist`, 또는 `disabled`.
|
||||
- `contextVisibility`: 보조 room 컨텍스트 가시성 모드(`all`, `allowlist`, `allowlist_quote`).
|
||||
- `groupAllowFrom`: room 트래픽용 user ID 허용 목록.
|
||||
- `groupAllowFrom` 항목은 전체 Matrix user ID여야 합니다. 해석되지 않은 이름은 런타임에 무시됩니다.
|
||||
- `historyLimit`: 그룹 기록 컨텍스트로 포함할 최대 room 메시지 수. 기본값은 `messages.groupChat.historyLimit`를 따릅니다. 비활성화하려면 `0`으로 설정하세요.
|
||||
- `replyToMode`: `off`, `first`, 또는 `all`.
|
||||
- `markdown`: 발신 Matrix 텍스트용 선택적 Markdown 렌더링 구성.
|
||||
- `streaming`: `off`(기본값), `partial`, `true`, 또는 `false`. `partial`과 `true`는 제자리 수정 업데이트가 가능한 단일 메시지 초안 미리보기를 활성화합니다.
|
||||
- `blockStreaming`: `true`는 초안 미리보기 스트리밍이 활성화된 동안 완료된 assistant 블록에 대해 별도 진행 메시지를 활성화합니다.
|
||||
- `threadReplies`: `off`, `inbound`, 또는 `always`.
|
||||
- `threadBindings`: thread 바인딩 세션 라우팅 및 수명 주기에 대한 채널별 재정의.
|
||||
- `startupVerification`: 시작 시 자동 self-verification 요청 모드(`if-unverified`, `off`).
|
||||
- `startupVerificationCooldownHours`: 자동 시작 검증 요청을 재시도하기 전 대기 시간.
|
||||
- `textChunkLimit`: 발신 메시지 청크 크기.
|
||||
- `chunkMode`: `length` 또는 `newline`.
|
||||
- `responsePrefix`: 발신 답장용 선택적 메시지 접두사.
|
||||
- `ackReaction`: 이 채널/계정용 선택적 ack reaction 재정의.
|
||||
- `ackReactionScope`: 선택적 ack reaction 범위 재정의(`group-mentions`, `group-all`, `direct`, `all`, `none`, `off`).
|
||||
- `reactionNotifications`: 수신 reaction 알림 모드(`own`, `off`).
|
||||
- `mediaMaxMb`: Matrix 미디어 처리용 미디어 크기 제한(MB). 발신 전송 및 수신 미디어 처리 모두에 적용됩니다.
|
||||
- `autoJoin`: 초대 자동 참가 정책(`always`, `allowlist`, `off`). 기본값: `off`.
|
||||
- `autoJoinAllowlist`: `autoJoin`이 `allowlist`일 때 허용되는 room/alias. alias 항목은 초대 처리 중 room ID로 해석되며, OpenClaw는 초대된 room이 주장하는 alias 상태를 신뢰하지 않습니다.
|
||||
- `dm`: DM 정책 블록(`enabled`, `policy`, `allowFrom`, `threadReplies`).
|
||||
- `dm.allowFrom` 항목은 실시간 디렉터리 조회로 이미 해석한 경우가 아니면 전체 Matrix user ID여야 합니다.
|
||||
- `dm.threadReplies`: DM 전용 thread 정책 재정의(`off`, `inbound`, `always`). DM에서 답장 배치와 세션 분리 모두에 대해 최상위 `threadReplies` 설정을 재정의합니다.
|
||||
- `execApprovals`: Matrix 기본 exec 승인 전달(`enabled`, `approvers`, `target`, `agentFilter`, `sessionFilter`).
|
||||
- `execApprovals.approvers`: exec 요청을 승인할 수 있는 Matrix user ID. `dm.allowFrom`이 이미 승인자를 식별하는 경우 선택 사항입니다.
|
||||
- `execApprovals.target`: `dm | channel | both` (기본값: `dm`).
|
||||
- `accounts`: 이름 있는 계정별 재정의. 최상위 `channels.matrix` 값이 이 항목의 기본값으로 동작합니다.
|
||||
- `groups`: room별 정책 맵. room ID 또는 alias를 권장하며, 해석되지 않은 room 이름은 런타임에 무시됩니다. 세션/그룹 ID는 해석 후 안정적인 room ID를 사용하고, 사람이 읽는 레이블은 계속 room 이름에서 가져옵니다.
|
||||
- `groups.<room>.account`: 다중 계정 설정에서 상속된 room 항목 하나를 특정 Matrix 계정으로 제한.
|
||||
- `groups.<room>.allowBots`: 구성된 봇 발신자에 대한 room 수준 재정의(`true` 또는 `"mentions"`).
|
||||
- `groups.<room>.users`: room별 발신자 허용 목록.
|
||||
- `groups.<room>.tools`: room별 도구 허용/거부 재정의.
|
||||
- `groups.<room>.autoReply`: room 수준 멘션 게이팅 재정의. `true`는 해당 room의 멘션 요구 사항을 비활성화하고, `false`는 다시 강제합니다.
|
||||
- `groups.<room>.skills`: 선택적 room 수준 Skills 필터.
|
||||
- `groups.<room>.systemPrompt`: 선택적 room 수준 시스템 프롬프트 스니펫.
|
||||
- `rooms`: `groups`의 레거시 별칭.
|
||||
- `actions`: 작업별 도구 게이팅(`messages`, `reactions`, `pins`, `profile`, `memberInfo`, `channelInfo`, `verification`).
|
||||
|
||||
## 관련
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 접근 모델 및 보안 강화
|
||||
480
docs/ko/channels/mattermost.md
Normal file
480
docs/ko/channels/mattermost.md
Normal file
@ -0,0 +1,480 @@
|
||||
---
|
||||
read_when:
|
||||
- Mattermost 설정
|
||||
- Mattermost 라우팅 디버깅
|
||||
summary: Mattermost 봇 설정 및 OpenClaw 구성
|
||||
title: Mattermost
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:36:40Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: f21dc7543176fda0b38b00fab60f0daae38dffcf68fa1cf7930a9f14ec57cb5a
|
||||
source_path: channels/mattermost.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Mattermost
|
||||
|
||||
상태: 번들 plugin(봇 토큰 + WebSocket 이벤트). 채널, 그룹, DM이 지원됩니다.
|
||||
Mattermost는 자체 호스팅 가능한 팀 메시징 플랫폼입니다. 제품 세부 정보와 다운로드는 공식 사이트
|
||||
[mattermost.com](https://mattermost.com)에서 확인하세요.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
Mattermost는 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 있으므로, 일반적인
|
||||
패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
구버전 빌드 또는 Mattermost가 제외된 커스텀 설치를 사용하는 경우,
|
||||
수동으로 설치하세요.
|
||||
|
||||
CLI로 설치(npm 레지스트리):
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/mattermost
|
||||
```
|
||||
|
||||
로컬 체크아웃(git 리포지토리에서 실행 중인 경우):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./path/to/local/mattermost-plugin
|
||||
```
|
||||
|
||||
자세한 내용: [Plugins](/tools/plugin)
|
||||
|
||||
## 빠른 설정
|
||||
|
||||
1. Mattermost plugin을 사용할 수 있는지 확인합니다.
|
||||
- 현재 패키지된 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 구버전/커스텀 설치는 위 명령으로 수동 추가할 수 있습니다.
|
||||
2. Mattermost 봇 계정을 만들고 **봇 토큰**을 복사합니다.
|
||||
3. Mattermost **기본 URL**을 복사합니다(예: `https://chat.example.com`).
|
||||
4. OpenClaw를 구성하고 gateway를 시작합니다.
|
||||
|
||||
최소 구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
mattermost: {
|
||||
enabled: true,
|
||||
botToken: "mm-token",
|
||||
baseUrl: "https://chat.example.com",
|
||||
dmPolicy: "pairing",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 네이티브 슬래시 명령
|
||||
|
||||
네이티브 슬래시 명령은 옵트인 방식입니다. 활성화하면 OpenClaw가 Mattermost API를 통해 `oc_*` 슬래시 명령을 등록하고
|
||||
gateway HTTP 서버에서 콜백 POST를 수신합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
mattermost: {
|
||||
commands: {
|
||||
native: true,
|
||||
nativeSkills: true,
|
||||
callbackPath: "/api/channels/mattermost/command",
|
||||
// Mattermost가 gateway에 직접 도달할 수 없을 때 사용합니다(리버스 프록시/공개 URL).
|
||||
callbackUrl: "https://gateway.example.com/api/channels/mattermost/command",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `native: "auto"`는 Mattermost에서 기본적으로 비활성화됩니다. 활성화하려면 `native: true`로 설정하세요.
|
||||
- `callbackUrl`이 생략되면 OpenClaw는 gateway host/port + `callbackPath`에서 이를 파생합니다.
|
||||
- 멀티 계정 설정에서는 `commands`를 최상위에 두거나
|
||||
`channels.mattermost.accounts.<id>.commands` 아래에 둘 수 있습니다(계정 값이 최상위 필드를 재정의함).
|
||||
- 명령 콜백은 OpenClaw가 `oc_*` 명령을 등록할 때 Mattermost가 반환한
|
||||
명령별 토큰으로 검증됩니다.
|
||||
- 슬래시 콜백은 등록 실패, 부분적 시작, 또는
|
||||
콜백 토큰이 등록된 명령 중 어느 것과도 일치하지 않으면 차단된 상태로 실패합니다.
|
||||
- 도달 가능성 요구 사항: 콜백 엔드포인트는 Mattermost 서버에서 도달 가능해야 합니다.
|
||||
- Mattermost가 OpenClaw와 같은 호스트/네트워크 네임스페이스에서 실행되지 않는 한 `callbackUrl`을 `localhost`로 설정하지 마세요.
|
||||
- 해당 URL이 `/api/channels/mattermost/command`를 OpenClaw로 리버스 프록시하지 않는 한 `callbackUrl`을 Mattermost 기본 URL로 설정하지 마세요.
|
||||
- 빠른 확인 방법은 `curl https://<gateway-host>/api/channels/mattermost/command`입니다. GET 요청은 `404`가 아니라 OpenClaw에서 `405 Method Not Allowed`를 반환해야 합니다.
|
||||
- Mattermost 송신 허용 목록 요구 사항:
|
||||
- 콜백 대상이 private/tailnet/internal 주소를 가리키는 경우, Mattermost
|
||||
`ServiceSettings.AllowedUntrustedInternalConnections`에 콜백 호스트/도메인을 포함하도록 설정하세요.
|
||||
- 전체 URL이 아니라 호스트/도메인 항목을 사용하세요.
|
||||
- 올바름: `gateway.tailnet-name.ts.net`
|
||||
- 잘못됨: `https://gateway.tailnet-name.ts.net`
|
||||
|
||||
## 환경 변수(기본 계정)
|
||||
|
||||
환경 변수를 선호한다면 gateway 호스트에 다음을 설정하세요.
|
||||
|
||||
- `MATTERMOST_BOT_TOKEN=...`
|
||||
- `MATTERMOST_URL=https://chat.example.com`
|
||||
|
||||
환경 변수는 **기본** 계정(`default`)에만 적용됩니다. 다른 계정은 반드시 config 값을 사용해야 합니다.
|
||||
|
||||
## 채팅 모드
|
||||
|
||||
Mattermost는 DM에 자동으로 응답합니다. 채널 동작은 `chatmode`로 제어됩니다.
|
||||
|
||||
- `oncall`(기본값): 채널에서 @멘션될 때만 응답합니다.
|
||||
- `onmessage`: 모든 채널 메시지에 응답합니다.
|
||||
- `onchar`: 메시지가 트리거 접두사로 시작할 때 응답합니다.
|
||||
|
||||
구성 예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
mattermost: {
|
||||
chatmode: "onchar",
|
||||
oncharPrefixes: [">", "!"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `onchar`는 명시적인 @멘션에도 계속 응답합니다.
|
||||
- `channels.mattermost.requireMention`은 레거시 구성에서 존중되지만 `chatmode` 사용이 권장됩니다.
|
||||
|
||||
## 스레딩 및 세션
|
||||
|
||||
채널 및 그룹 응답을 메인 채널에 유지할지, 트리거한 게시물 아래 스레드를 시작할지 제어하려면
|
||||
`channels.mattermost.replyToMode`를 사용하세요.
|
||||
|
||||
- `off`(기본값): 수신 게시물이 이미 스레드 안에 있는 경우에만 스레드에서 응답합니다.
|
||||
- `first`: 최상위 채널/그룹 게시물의 경우 해당 게시물 아래에 스레드를 시작하고
|
||||
대화를 스레드 범위 세션으로 라우팅합니다.
|
||||
- `all`: 현재 Mattermost에서는 `first`와 동일하게 동작합니다.
|
||||
- 다이렉트 메시지는 이 설정을 무시하고 비스레드 상태를 유지합니다.
|
||||
|
||||
구성 예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
mattermost: {
|
||||
replyToMode: "all",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 스레드 범위 세션은 트리거한 게시물 ID를 스레드 루트로 사용합니다.
|
||||
- `first`와 `all`은 현재 동일합니다. Mattermost에 스레드 루트가 생기면
|
||||
후속 청크와 미디어가 모두 그 동일한 스레드에서 계속되기 때문입니다.
|
||||
|
||||
## 접근 제어(DM)
|
||||
|
||||
- 기본값: `channels.mattermost.dmPolicy = "pairing"`(알 수 없는 발신자는 페어링 코드를 받음).
|
||||
- 승인 방법:
|
||||
- `openclaw pairing list mattermost`
|
||||
- `openclaw pairing approve mattermost <CODE>`
|
||||
- 공개 DM: `channels.mattermost.dmPolicy="open"`과 `channels.mattermost.allowFrom=["*"]`.
|
||||
|
||||
## 채널(그룹)
|
||||
|
||||
- 기본값: `channels.mattermost.groupPolicy = "allowlist"`(멘션 게이트 방식).
|
||||
- `channels.mattermost.groupAllowFrom`으로 발신자를 허용 목록에 추가합니다(사용자 ID 권장).
|
||||
- 채널별 멘션 재정의는 `channels.mattermost.groups.<channelId>.requireMention`
|
||||
또는 기본값용 `channels.mattermost.groups["*"].requireMention` 아래에 있습니다.
|
||||
- `@username` 일치는 변경 가능하며 `channels.mattermost.dangerouslyAllowNameMatching: true`일 때만 활성화됩니다.
|
||||
- 공개 채널: `channels.mattermost.groupPolicy="open"`(멘션 게이트 방식).
|
||||
- 런타임 참고: `channels.mattermost`가 완전히 없으면, 런타임은 그룹 검사에 `groupPolicy="allowlist"`로 대체됩니다(`channels.defaults.groupPolicy`가 설정되어 있어도 마찬가지임).
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
mattermost: {
|
||||
groupPolicy: "open",
|
||||
groups: {
|
||||
"*": { requireMention: true },
|
||||
"team-channel-id": { requireMention: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 아웃바운드 전달 대상
|
||||
|
||||
`openclaw message send` 또는 cron/웹훅에서 다음 대상 형식을 사용하세요.
|
||||
|
||||
- 채널에는 `channel:<id>`
|
||||
- DM에는 `user:<id>`
|
||||
- DM에는 `@username`(Mattermost API를 통해 확인됨)
|
||||
|
||||
접두사 없는 불투명 ID(예: `64ifufp...`)는 Mattermost에서 **모호**합니다(사용자 ID인지 채널 ID인지 구분 안 됨).
|
||||
|
||||
OpenClaw는 이를 **사용자 우선**으로 해석합니다.
|
||||
|
||||
- ID가 사용자로 존재하면(`GET /api/v4/users/<id>` 성공), OpenClaw는 `/api/v4/channels/direct`를 통해 다이렉트 채널을 확인하여 **DM**을 전송합니다.
|
||||
- 그렇지 않으면 해당 ID는 **채널 ID**로 처리됩니다.
|
||||
|
||||
결정적인 동작이 필요하면 항상 명시적 접두사(`user:<id>` / `channel:<id>`)를 사용하세요.
|
||||
|
||||
## DM 채널 재시도
|
||||
|
||||
OpenClaw가 Mattermost DM 대상으로 전송할 때 먼저 다이렉트 채널을 확인해야 하는 경우,
|
||||
기본적으로 일시적인 다이렉트 채널 생성 실패를 재시도합니다.
|
||||
|
||||
Mattermost plugin 전체에 대해 그 동작을 전역 조정하려면 `channels.mattermost.dmChannelRetry`를 사용하고,
|
||||
특정 계정 하나에 대해서만 조정하려면 `channels.mattermost.accounts.<id>.dmChannelRetry`를 사용하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
mattermost: {
|
||||
dmChannelRetry: {
|
||||
maxRetries: 3,
|
||||
initialDelayMs: 1000,
|
||||
maxDelayMs: 10000,
|
||||
timeoutMs: 30000,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 이는 모든 Mattermost API 호출이 아니라 DM 채널 생성(`/api/v4/channels/direct`)에만 적용됩니다.
|
||||
- 재시도는 rate limit, 5xx 응답, 네트워크 오류 또는 타임아웃 오류 같은 일시적 실패에 적용됩니다.
|
||||
- `429`를 제외한 4xx 클라이언트 오류는 영구 오류로 처리되며 재시도하지 않습니다.
|
||||
|
||||
## 반응(message 도구)
|
||||
|
||||
- `channel=mattermost`와 함께 `message action=react`를 사용하세요.
|
||||
- `messageId`는 Mattermost 게시물 ID입니다.
|
||||
- `emoji`는 `thumbsup` 또는 `:+1:` 같은 이름을 받습니다(콜론은 선택 사항).
|
||||
- 반응을 제거하려면 `remove=true`(boolean)를 설정하세요.
|
||||
- 반응 추가/제거 이벤트는 라우팅된 agent 세션으로 시스템 이벤트로 전달됩니다.
|
||||
|
||||
예시:
|
||||
|
||||
```
|
||||
message action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsup
|
||||
message action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsup remove=true
|
||||
```
|
||||
|
||||
구성:
|
||||
|
||||
- `channels.mattermost.actions.reactions`: 반응 동작 활성화/비활성화(기본값 true).
|
||||
- 계정별 재정의: `channels.mattermost.accounts.<id>.actions.reactions`.
|
||||
|
||||
## 인터랙티브 버튼(message 도구)
|
||||
|
||||
클릭 가능한 버튼이 포함된 메시지를 보냅니다. 사용자가 버튼을 클릭하면 에이전트가
|
||||
선택값을 받아 응답할 수 있습니다.
|
||||
|
||||
채널 기능에 `inlineButtons`를 추가하여 버튼을 활성화하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
mattermost: {
|
||||
capabilities: ["inlineButtons"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`buttons` 파라미터와 함께 `message action=send`를 사용하세요. 버튼은 2차원 배열(버튼 행)입니다.
|
||||
|
||||
```
|
||||
message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]
|
||||
```
|
||||
|
||||
버튼 필드:
|
||||
|
||||
- `text`(필수): 표시 레이블.
|
||||
- `callback_data`(필수): 클릭 시 다시 전송되는 값(action ID로 사용됨).
|
||||
- `style`(선택 사항): `"default"`, `"primary"`, 또는 `"danger"`.
|
||||
|
||||
사용자가 버튼을 클릭하면:
|
||||
|
||||
1. 모든 버튼이 확인 줄로 교체됩니다(예: "✓ **Yes** selected by @user").
|
||||
2. 에이전트는 선택 내용을 수신 메시지로 받아 응답합니다.
|
||||
|
||||
참고:
|
||||
|
||||
- 버튼 콜백은 HMAC-SHA256 검증을 사용합니다(자동, 별도 구성 불필요).
|
||||
- Mattermost는 API 응답에서 callback data를 제거합니다(보안 기능). 따라서 클릭 시 모든 버튼이 제거되며, 일부만 제거하는 것은 불가능합니다.
|
||||
- 하이픈 또는 밑줄이 포함된 action ID는 자동으로 정리됩니다
|
||||
(Mattermost 라우팅 제한).
|
||||
|
||||
구성:
|
||||
|
||||
- `channels.mattermost.capabilities`: 기능 문자열 배열. 에이전트 시스템 프롬프트에서
|
||||
버튼 도구 설명을 활성화하려면 `"inlineButtons"`를 추가하세요.
|
||||
- `channels.mattermost.interactions.callbackBaseUrl`: 버튼 콜백용 선택적 외부 기본 URL
|
||||
(예: `https://gateway.example.com`). Mattermost가 바인드 host의 gateway에 직접
|
||||
도달할 수 없을 때 사용하세요.
|
||||
- 멀티 계정 설정에서는 동일한 필드를
|
||||
`channels.mattermost.accounts.<id>.interactions.callbackBaseUrl` 아래에도 설정할 수 있습니다.
|
||||
- `interactions.callbackBaseUrl`이 생략되면 OpenClaw는
|
||||
`gateway.customBindHost` + `gateway.port`에서 콜백 URL을 파생한 다음, `http://localhost:<port>`로 대체합니다.
|
||||
- 도달 가능성 규칙: 버튼 콜백 URL은 Mattermost 서버에서 도달 가능해야 합니다.
|
||||
Mattermost와 OpenClaw가 같은 호스트/네트워크 네임스페이스에서 실행될 때만 `localhost`가 작동합니다.
|
||||
- 콜백 대상이 private/tailnet/internal인 경우, 해당 host/domain을 Mattermost
|
||||
`ServiceSettings.AllowedUntrustedInternalConnections`에 추가하세요.
|
||||
|
||||
### Direct API 통합(외부 스크립트)
|
||||
|
||||
외부 스크립트와 웹훅은 에이전트의 `message` 도구를 거치지 않고
|
||||
Mattermost REST API를 통해 직접 버튼을 게시할 수 있습니다. 가능하면 extension의 `buildButtonAttachments()`를 사용하세요.
|
||||
원시 JSON을 게시하는 경우 다음 규칙을 따르세요.
|
||||
|
||||
**페이로드 구조:**
|
||||
|
||||
```json5
|
||||
{
|
||||
channel_id: "<channelId>",
|
||||
message: "Choose an option:",
|
||||
props: {
|
||||
attachments: [
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
id: "mybutton01", // 영숫자만 허용 — 아래 참조
|
||||
type: "button", // 필수, 없으면 클릭이 조용히 무시됨
|
||||
name: "Approve", // 표시 레이블
|
||||
style: "primary", // 선택 사항: "default", "primary", "danger"
|
||||
integration: {
|
||||
url: "https://gateway.example.com/mattermost/interactions/default",
|
||||
context: {
|
||||
action_id: "mybutton01", // 버튼 id와 일치해야 함(이름 조회용)
|
||||
action: "approve",
|
||||
// ... 사용자 정의 필드 ...
|
||||
_token: "<hmac>", // 아래 HMAC 섹션 참조
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**중요 규칙:**
|
||||
|
||||
1. attachment는 최상위 `attachments`가 아니라 `props.attachments`에 넣어야 합니다(그렇지 않으면 조용히 무시됨).
|
||||
2. 모든 action에는 `type: "button"`이 필요합니다. 없으면 클릭이 조용히 삼켜집니다.
|
||||
3. 모든 action에는 `id` 필드가 필요합니다. Mattermost는 ID가 없는 action을 무시합니다.
|
||||
4. Action `id`는 **영숫자만** 허용됩니다(`[a-zA-Z0-9]`). 하이픈과 밑줄은
|
||||
Mattermost의 서버 측 action 라우팅을 깨뜨립니다(`404` 반환). 사용 전에 제거하세요.
|
||||
5. 확인 메시지에 원시 ID 대신 버튼 이름(예: "Approve")이 표시되도록
|
||||
`context.action_id`는 버튼의 `id`와 일치해야 합니다.
|
||||
6. `context.action_id`는 필수입니다. 없으면 interaction 핸들러가 `400`을 반환합니다.
|
||||
|
||||
**HMAC 토큰 생성:**
|
||||
|
||||
gateway는 HMAC-SHA256으로 버튼 클릭을 검증합니다. 외부 스크립트는 gateway의 검증 로직과
|
||||
일치하는 토큰을 생성해야 합니다.
|
||||
|
||||
1. 봇 토큰에서 secret을 파생합니다:
|
||||
`HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)`
|
||||
2. `_token`을 제외한 모든 필드로 context 객체를 만듭니다.
|
||||
3. **정렬된 키**와 **공백 없음**으로 직렬화합니다(gateway는 정렬된 키로 `JSON.stringify`를 사용하며,
|
||||
이는 압축된 출력을 생성합니다).
|
||||
4. 서명: `HMAC-SHA256(key=secret, data=serializedContext)`
|
||||
5. 결과 hex digest를 context의 `_token`으로 추가합니다.
|
||||
|
||||
Python 예시:
|
||||
|
||||
```python
|
||||
import hmac, hashlib, json
|
||||
|
||||
secret = hmac.new(
|
||||
b"openclaw-mattermost-interactions",
|
||||
bot_token.encode(), hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
ctx = {"action_id": "mybutton01", "action": "approve"}
|
||||
payload = json.dumps(ctx, sort_keys=True, separators=(",", ":"))
|
||||
token = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest()
|
||||
|
||||
context = {**ctx, "_token": token}
|
||||
```
|
||||
|
||||
일반적인 HMAC 함정:
|
||||
|
||||
- Python의 `json.dumps`는 기본적으로 공백을 추가합니다(`{"key": "val"}`). JavaScript의 압축 출력(`{"key":"val"}`)과 맞추려면
|
||||
`separators=(",", ":")`를 사용하세요.
|
||||
- 항상 **모든** context 필드(`_token` 제외)에 서명하세요. gateway는 `_token`을 제거한 뒤
|
||||
남은 모든 것을 서명합니다. 일부만 서명하면 조용한 검증 실패가 발생합니다.
|
||||
- `sort_keys=True`를 사용하세요. gateway는 서명 전에 키를 정렬하고, Mattermost는
|
||||
페이로드를 저장할 때 context 필드를 재정렬할 수 있습니다.
|
||||
- secret은 랜덤 바이트가 아니라 봇 토큰에서 파생하세요(결정적). secret은
|
||||
버튼을 생성하는 프로세스와 이를 검증하는 gateway에서 동일해야 합니다.
|
||||
|
||||
## 디렉터리 어댑터
|
||||
|
||||
Mattermost plugin에는 Mattermost API를 통해 채널 및 사용자 이름을 확인하는
|
||||
디렉터리 어댑터가 포함되어 있습니다. 이를 통해
|
||||
`openclaw message send` 및 cron/웹훅 전달에서 `#channel-name`과 `@username` 대상을 사용할 수 있습니다.
|
||||
|
||||
별도 구성은 필요하지 않습니다. 어댑터는 계정 config의 봇 토큰을 사용합니다.
|
||||
|
||||
## 멀티 계정
|
||||
|
||||
Mattermost는 `channels.mattermost.accounts` 아래에서 여러 계정을 지원합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
mattermost: {
|
||||
accounts: {
|
||||
default: { name: "Primary", botToken: "mm-token", baseUrl: "https://chat.example.com" },
|
||||
alerts: { name: "Alerts", botToken: "mm-token-2", baseUrl: "https://alerts.example.com" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 문제 해결
|
||||
|
||||
- 채널에서 응답이 없음: 봇이 채널에 들어가 있는지 확인하고 멘션하세요(oncall), 트리거 접두사를 사용하세요(onchar), 또는 `chatmode: "onmessage"`로 설정하세요.
|
||||
- 인증 오류: 봇 토큰, 기본 URL, 계정 활성화 여부를 확인하세요.
|
||||
- 멀티 계정 문제: 환경 변수는 `default` 계정에만 적용됩니다.
|
||||
- 네이티브 슬래시 명령이 `Unauthorized: invalid command token.`을 반환함: OpenClaw가
|
||||
콜백 토큰을 수락하지 않았습니다. 일반적인 원인:
|
||||
- 슬래시 명령 등록이 실패했거나 시작 시 일부만 완료됨
|
||||
- 콜백이 잘못된 gateway/계정으로 도달함
|
||||
- Mattermost에 이전 콜백 대상을 가리키는 오래된 명령이 여전히 남아 있음
|
||||
- gateway가 슬래시 명령을 다시 활성화하지 않고 재시작됨
|
||||
- 네이티브 슬래시 명령이 작동을 멈추면 로그에서
|
||||
`mattermost: failed to register slash commands` 또는
|
||||
`mattermost: native slash commands enabled but no commands could be registered`
|
||||
를 확인하세요.
|
||||
- `callbackUrl`이 생략되었고 로그에서 콜백이
|
||||
`http://127.0.0.1:18789/...`로 확인되었다는 경고가 나오면, 그 URL은
|
||||
Mattermost가 OpenClaw와 같은 호스트/네트워크 네임스페이스에서 실행될 때만
|
||||
도달 가능할 가능성이 높습니다. 대신 명시적으로 외부에서 도달 가능한
|
||||
`commands.callbackUrl`을 설정하세요.
|
||||
- 버튼이 흰색 상자로 보임: 에이전트가 잘못된 버튼 데이터를 보내고 있을 수 있습니다. 각 버튼에 `text`와 `callback_data` 필드가 모두 있는지 확인하세요.
|
||||
- 버튼은 렌더링되지만 클릭해도 아무 일도 일어나지 않음: Mattermost 서버 config의 `AllowedUntrustedInternalConnections`에 `127.0.0.1 localhost`가 포함되어 있는지, 그리고 ServiceSettings에서 `EnablePostActionIntegration`이 `true`인지 확인하세요.
|
||||
- 버튼 클릭 시 404 반환: 버튼 `id`에 하이픈 또는 밑줄이 포함되어 있을 가능성이 높습니다. Mattermost의 action 라우터는 영숫자가 아닌 ID에서 깨집니다. `[a-zA-Z0-9]`만 사용하세요.
|
||||
- Gateway 로그에 `invalid _token`이 표시됨: HMAC 불일치입니다. 모든 context 필드(일부가 아님)에 서명하는지, 키를 정렬하는지, 압축 JSON(공백 없음)을 사용하는지 확인하세요. 위의 HMAC 섹션을 참조하세요.
|
||||
- Gateway 로그에 `missing _token in context`가 표시됨: 버튼 context에 `_token` 필드가 없습니다. integration 페이로드를 만들 때 이를 포함했는지 확인하세요.
|
||||
- 확인 메시지에 버튼 이름 대신 원시 ID가 표시됨: `context.action_id`가 버튼의 `id`와 일치하지 않습니다. 둘 다 동일한 정리된 값으로 설정하세요.
|
||||
- 에이전트가 버튼을 모름: Mattermost 채널 config에 `capabilities: ["inlineButtons"]`를 추가하세요.
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [Channels Overview](/channels) — 지원되는 모든 채널
|
||||
- [Pairing](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [Groups](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [Channel Routing](/channels/channel-routing) — 메시지 세션 라우팅
|
||||
- [Security](/gateway/security) — 접근 모델 및 보안 강화
|
||||
812
docs/ko/channels/msteams.md
Normal file
812
docs/ko/channels/msteams.md
Normal file
@ -0,0 +1,812 @@
|
||||
---
|
||||
read_when:
|
||||
- Microsoft Teams 채널 기능을 작업할 때
|
||||
summary: Microsoft Teams 봇 지원 상태, 기능 및 구성
|
||||
title: Microsoft Teams
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:02Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 99fc6e136893ec65dc85d3bc0c0d92134069a2f3b8cb4fcf66c14674399b3eaf
|
||||
source_path: channels/msteams.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Microsoft Teams
|
||||
|
||||
> "이곳에 들어오는 자여, 모든 희망을 버려라."
|
||||
|
||||
업데이트: 2026-01-21
|
||||
|
||||
상태: 텍스트 + DM 첨부파일이 지원되며, 채널/그룹 파일 전송에는 `sharePointSiteId` + Graph 권한이 필요합니다([그룹 채팅에서 파일 보내기](#sending-files-in-group-chats) 참조). Polls는 Adaptive Cards를 통해 전송됩니다. 메시지 작업은 파일 우선 전송을 위한 명시적 `upload-file`을 노출합니다.
|
||||
|
||||
## 번들 플러그인
|
||||
|
||||
Microsoft Teams는 현재 OpenClaw 릴리스에 번들 플러그인으로 포함되어 있으므로,
|
||||
일반적인 패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
이전 빌드이거나 번들 Teams가 제외된 사용자 지정 설치를 사용하는 경우,
|
||||
수동으로 설치하세요.
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/msteams
|
||||
```
|
||||
|
||||
로컬 체크아웃(깃 리포지토리에서 실행할 때):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./path/to/local/msteams-plugin
|
||||
```
|
||||
|
||||
자세한 내용: [Plugins](/tools/plugin)
|
||||
|
||||
## 빠른 설정(초보자용)
|
||||
|
||||
1. Microsoft Teams 플러그인을 사용할 수 있는지 확인합니다.
|
||||
- 현재 패키지형 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 이전/사용자 지정 설치에서는 위 명령으로 수동 추가할 수 있습니다.
|
||||
2. **Azure Bot**(App ID + client secret + tenant ID)을 생성합니다.
|
||||
3. 해당 자격 증명으로 OpenClaw를 구성합니다.
|
||||
4. 공개 URL 또는 터널을 통해 `/api/messages`(기본 포트 3978)를 노출합니다.
|
||||
5. Teams 앱 패키지를 설치하고 게이트웨이를 시작합니다.
|
||||
|
||||
최소 config:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
msteams: {
|
||||
enabled: true,
|
||||
appId: "<APP_ID>",
|
||||
appPassword: "<APP_PASSWORD>",
|
||||
tenantId: "<TENANT_ID>",
|
||||
webhook: { port: 3978, path: "/api/messages" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고: 그룹 채팅은 기본적으로 차단됩니다(`channels.msteams.groupPolicy: "allowlist"`). 그룹 응답을 허용하려면 `channels.msteams.groupAllowFrom`을 설정하세요(또는 어떤 멤버든 허용하되 기본적으로 멘션 게이팅이 적용되도록 `groupPolicy: "open"`을 사용하세요).
|
||||
|
||||
## 목표
|
||||
|
||||
- Teams DM, 그룹 채팅 또는 채널을 통해 OpenClaw와 대화합니다.
|
||||
- 라우팅을 결정적으로 유지합니다. 응답은 항상 수신된 채널로 돌아갑니다.
|
||||
- 안전한 채널 동작을 기본값으로 사용합니다(별도 구성하지 않으면 멘션 필요).
|
||||
|
||||
## config 쓰기
|
||||
|
||||
기본적으로 Microsoft Teams는 `/config set|unset`에 의해 트리거된 config 업데이트 쓰기를 허용합니다(`commands.config: true` 필요).
|
||||
|
||||
다음으로 비활성화할 수 있습니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: { msteams: { configWrites: false } },
|
||||
}
|
||||
```
|
||||
|
||||
## 액세스 제어(DM + 그룹)
|
||||
|
||||
**DM 액세스**
|
||||
|
||||
- 기본값: `channels.msteams.dmPolicy = "pairing"`입니다. 알 수 없는 발신자는 승인될 때까지 무시됩니다.
|
||||
- `channels.msteams.allowFrom`에는 안정적인 AAD object ID를 사용하는 것이 좋습니다.
|
||||
- UPN/표시 이름은 변경 가능하므로 직접 일치는 기본적으로 비활성화되어 있으며 `channels.msteams.dangerouslyAllowNameMatching: true`일 때만 활성화됩니다.
|
||||
- 자격 증명이 허용되면 마법사가 Microsoft Graph를 통해 이름을 ID로 확인할 수 있습니다.
|
||||
|
||||
**그룹 액세스**
|
||||
|
||||
- 기본값: `channels.msteams.groupPolicy = "allowlist"`입니다(`groupAllowFrom`을 추가하지 않으면 차단됨). 설정되지 않았을 때 기본값을 재정의하려면 `channels.defaults.groupPolicy`를 사용하세요.
|
||||
- `channels.msteams.groupAllowFrom`은 그룹 채팅/채널에서 어떤 발신자가 트리거할 수 있는지 제어합니다(`channels.msteams.allowFrom`으로 대체됨).
|
||||
- 어떤 멤버든 허용하려면 `groupPolicy: "open"`을 설정하세요(그래도 기본적으로 멘션 게이팅 적용).
|
||||
- **어떤 채널도 허용하지 않으려면** `channels.msteams.groupPolicy: "disabled"`를 설정하세요.
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
msteams: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["user@org.com"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**Teams + 채널 허용 목록**
|
||||
|
||||
- `channels.msteams.teams` 아래에 팀과 채널을 나열해 그룹/채널 응답 범위를 지정합니다.
|
||||
- 키에는 안정적인 팀 ID와 채널 conversation ID를 사용해야 합니다.
|
||||
- `groupPolicy="allowlist"`이고 teams 허용 목록이 있으면 나열된 팀/채널만 허용됩니다(멘션 게이팅 적용).
|
||||
- 구성 마법사는 `Team/Channel` 항목을 받아 대신 저장해 줍니다.
|
||||
- 시작 시 OpenClaw는 팀/채널 및 사용자 허용 목록 이름을 ID로 확인하고(Graph 권한이 허용될 때)
|
||||
매핑을 로그에 남깁니다. 확인되지 않은 팀/채널 이름은 입력된 그대로 유지되지만, `channels.msteams.dangerouslyAllowNameMatching: true`가 활성화되지 않는 한 기본적으로 라우팅에서는 무시됩니다.
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
msteams: {
|
||||
groupPolicy: "allowlist",
|
||||
teams: {
|
||||
"My Team": {
|
||||
channels: {
|
||||
General: { requireMention: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 작동 방식
|
||||
|
||||
1. Microsoft Teams 플러그인을 사용할 수 있는지 확인합니다.
|
||||
- 현재 패키지형 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 이전/사용자 지정 설치에서는 위 명령으로 수동 추가할 수 있습니다.
|
||||
2. **Azure Bot**(App ID + secret + tenant ID)을 생성합니다.
|
||||
3. 봇을 참조하고 아래 RSC 권한을 포함하는 **Teams 앱 패키지**를 빌드합니다.
|
||||
4. Teams 앱을 팀에 업로드/설치합니다(DM용 개인 범위도 가능).
|
||||
5. `~/.openclaw/openclaw.json`(또는 env vars)에서 `msteams`를 구성하고 게이트웨이를 시작합니다.
|
||||
6. 게이트웨이는 기본적으로 `/api/messages`에서 Bot Framework 웹훅 트래픽을 수신 대기합니다.
|
||||
|
||||
## Azure Bot 설정(사전 요구 사항)
|
||||
|
||||
OpenClaw를 구성하기 전에 Azure Bot 리소스를 생성해야 합니다.
|
||||
|
||||
### 1단계: Azure Bot 생성
|
||||
|
||||
1. [Create Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot)으로 이동합니다.
|
||||
2. **Basics** 탭을 채웁니다.
|
||||
|
||||
| Field | Value |
|
||||
| ------------------ | -------------------------------------------------------- |
|
||||
| **Bot handle** | 봇 이름(예: `openclaw-msteams`)이며 고유해야 함 |
|
||||
| **Subscription** | Azure 구독 선택 |
|
||||
| **Resource group** | 새로 만들거나 기존 것 사용 |
|
||||
| **Pricing tier** | 개발/테스트용 **Free** |
|
||||
| **Type of App** | **Single Tenant**(권장 - 아래 참고 참조) |
|
||||
| **Creation type** | **Create new Microsoft App ID** |
|
||||
|
||||
> **지원 중단 안내:** 새 멀티 테넌트 봇 생성은 2025-07-31 이후 지원 중단되었습니다. 새 봇에는 **Single Tenant**를 사용하세요.
|
||||
|
||||
3. **Review + create** → **Create**를 클릭합니다(약 1~2분 대기)
|
||||
|
||||
### 2단계: 자격 증명 가져오기
|
||||
|
||||
1. Azure Bot 리소스로 이동 → **Configuration**
|
||||
2. **Microsoft App ID**를 복사 → 이것이 `appId`입니다
|
||||
3. **Manage Password**를 클릭 → App Registration으로 이동
|
||||
4. **Certificates & secrets** → **New client secret** → **Value**를 복사 → 이것이 `appPassword`입니다
|
||||
5. **Overview**로 이동 → **Directory (tenant) ID**를 복사 → 이것이 `tenantId`입니다
|
||||
|
||||
### 3단계: 메시징 엔드포인트 구성
|
||||
|
||||
1. Azure Bot → **Configuration**
|
||||
2. **Messaging endpoint**를 웹훅 URL로 설정합니다.
|
||||
- 프로덕션: `https://your-domain.com/api/messages`
|
||||
- 로컬 개발: 터널 사용([로컬 개발](#local-development-tunneling) 참조)
|
||||
|
||||
### 4단계: Teams 채널 활성화
|
||||
|
||||
1. Azure Bot → **Channels**
|
||||
2. **Microsoft Teams** → Configure → Save를 클릭
|
||||
3. 서비스 약관에 동의합니다
|
||||
|
||||
## 로컬 개발(터널링)
|
||||
|
||||
Teams는 `localhost`에 접근할 수 없습니다. 로컬 개발에는 터널을 사용하세요.
|
||||
|
||||
**옵션 A: ngrok**
|
||||
|
||||
```bash
|
||||
ngrok http 3978
|
||||
# https URL을 복사합니다. 예: https://abc123.ngrok.io
|
||||
# 메시징 엔드포인트를 다음으로 설정: https://abc123.ngrok.io/api/messages
|
||||
```
|
||||
|
||||
**옵션 B: Tailscale Funnel**
|
||||
|
||||
```bash
|
||||
tailscale funnel 3978
|
||||
# Tailscale funnel URL을 메시징 엔드포인트로 사용하세요
|
||||
```
|
||||
|
||||
## Teams Developer Portal(대안)
|
||||
|
||||
manifest ZIP를 수동 생성하는 대신 [Teams Developer Portal](https://dev.teams.microsoft.com/apps)을 사용할 수 있습니다.
|
||||
|
||||
1. **+ New app** 클릭
|
||||
2. 기본 정보(이름, 설명, 개발자 정보) 입력
|
||||
3. **App features** → **Bot**으로 이동
|
||||
4. **Enter a bot ID manually**를 선택하고 Azure Bot App ID를 붙여넣기
|
||||
5. 범위 선택: **Personal**, **Team**, **Group Chat**
|
||||
6. **Distribute** → **Download app package** 클릭
|
||||
7. Teams에서 **Apps** → **Manage your apps** → **Upload a custom app** → ZIP 선택
|
||||
|
||||
이 방식은 JSON manifest를 직접 편집하는 것보다 더 쉬운 경우가 많습니다.
|
||||
|
||||
## 봇 테스트
|
||||
|
||||
**옵션 A: Azure Web Chat(먼저 웹훅 확인)**
|
||||
|
||||
1. Azure Portal → Azure Bot 리소스 → **Test in Web Chat**
|
||||
2. 메시지를 전송하면 응답이 보여야 합니다
|
||||
3. 이를 통해 Teams 설정 전에 웹훅 엔드포인트가 동작하는지 확인할 수 있습니다
|
||||
|
||||
**옵션 B: Teams(앱 설치 후)**
|
||||
|
||||
1. Teams 앱 설치(사이드로드 또는 조직 카탈로그)
|
||||
2. Teams에서 봇을 찾고 DM 전송
|
||||
3. 게이트웨이 로그에서 들어오는 activity 확인
|
||||
|
||||
## 설정(최소 텍스트 전용)
|
||||
|
||||
1. **Microsoft Teams 플러그인을 사용할 수 있는지 확인**
|
||||
- 현재 패키지형 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 이전/사용자 지정 설치에서는 수동으로 추가할 수 있습니다.
|
||||
- npm에서: `openclaw plugins install @openclaw/msteams`
|
||||
- 로컬 체크아웃에서: `openclaw plugins install ./path/to/local/msteams-plugin`
|
||||
|
||||
2. **봇 등록**
|
||||
- Azure Bot을 생성하고(위 참조) 다음을 기록합니다.
|
||||
- App ID
|
||||
- Client secret(App password)
|
||||
- Tenant ID(single-tenant)
|
||||
|
||||
3. **Teams 앱 manifest**
|
||||
- `botId = <App ID>`인 `bot` 항목을 포함합니다.
|
||||
- 범위: `personal`, `team`, `groupChat`.
|
||||
- `supportsFiles: true`(개인 범위 파일 처리에 필요).
|
||||
- RSC 권한(아래)을 추가합니다.
|
||||
- 아이콘 생성: `outline.png` (32x32), `color.png` (192x192).
|
||||
- 세 파일을 함께 zip으로 묶습니다: `manifest.json`, `outline.png`, `color.png`.
|
||||
|
||||
4. **OpenClaw 구성**
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
msteams: {
|
||||
enabled: true,
|
||||
appId: "<APP_ID>",
|
||||
appPassword: "<APP_PASSWORD>",
|
||||
tenantId: "<TENANT_ID>",
|
||||
webhook: { port: 3978, path: "/api/messages" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
config 키 대신 환경 변수를 사용할 수도 있습니다.
|
||||
- `MSTEAMS_APP_ID`
|
||||
- `MSTEAMS_APP_PASSWORD`
|
||||
- `MSTEAMS_TENANT_ID`
|
||||
|
||||
5. **봇 엔드포인트**
|
||||
- Azure Bot Messaging Endpoint를 다음으로 설정합니다.
|
||||
- `https://<host>:3978/api/messages`(또는 선택한 path/port).
|
||||
|
||||
6. **게이트웨이 실행**
|
||||
- 번들 또는 수동 설치된 플러그인을 사용할 수 있고 자격 증명이 포함된 `msteams` config가 존재하면 Teams 채널이 자동으로 시작됩니다.
|
||||
|
||||
## 멤버 정보 작업
|
||||
|
||||
OpenClaw는 Microsoft Teams용 Graph 기반 `member-info` 작업을 노출하므로 에이전트와 자동화가 Microsoft Graph에서 직접 채널 멤버 정보(표시 이름, 이메일, 역할)를 확인할 수 있습니다.
|
||||
|
||||
요구 사항:
|
||||
|
||||
- `Member.Read.Group` RSC 권한(권장 manifest에 이미 포함됨)
|
||||
- 팀 간 조회용: 관리자 동의가 포함된 `User.Read.All` Graph Application 권한
|
||||
|
||||
이 작업은 `channels.msteams.actions.memberInfo`로 제어됩니다(기본값: Graph 자격 증명을 사용할 수 있을 때 활성화).
|
||||
|
||||
## 기록 컨텍스트
|
||||
|
||||
- `channels.msteams.historyLimit`은 프롬프트에 포함할 최근 채널/그룹 메시지 수를 제어합니다.
|
||||
- `messages.groupChat.historyLimit`로 대체됩니다. `0`으로 설정하면 비활성화됩니다(기본값 50).
|
||||
- 가져온 스레드 기록은 발신자 허용 목록(`allowFrom` / `groupAllowFrom`)으로 필터링되므로 스레드 컨텍스트 시드는 허용된 발신자의 메시지만 포함합니다.
|
||||
- 인용된 첨부파일 컨텍스트(`ReplyTo*`에서 파생된 Teams reply HTML)는 현재 수신된 그대로 전달됩니다.
|
||||
- 즉, 허용 목록은 누가 에이전트를 트리거할 수 있는지를 제어하며, 현재는 특정 보조 컨텍스트 경로만 필터링됩니다.
|
||||
- DM 기록은 `channels.msteams.dmHistoryLimit`(사용자 턴 수)로 제한할 수 있습니다. 사용자별 재정의: `channels.msteams.dms["<user_id>"].historyLimit`.
|
||||
|
||||
## 현재 Teams RSC 권한(Manifest)
|
||||
|
||||
다음은 Teams 앱 manifest의 **기존 resourceSpecific 권한**입니다. 이는 앱이 설치된 팀/채팅 내부에서만 적용됩니다.
|
||||
|
||||
**채널(팀 범위)의 경우:**
|
||||
|
||||
- `ChannelMessage.Read.Group` (Application) - @멘션 없이 모든 채널 메시지 수신
|
||||
- `ChannelMessage.Send.Group` (Application)
|
||||
- `Member.Read.Group` (Application)
|
||||
- `Owner.Read.Group` (Application)
|
||||
- `ChannelSettings.Read.Group` (Application)
|
||||
- `TeamMember.Read.Group` (Application)
|
||||
- `TeamSettings.Read.Group` (Application)
|
||||
|
||||
**그룹 채팅의 경우:**
|
||||
|
||||
- `ChatMessage.Read.Chat` (Application) - @멘션 없이 모든 그룹 채팅 메시지 수신
|
||||
|
||||
## 예시 Teams Manifest(일부 가림)
|
||||
|
||||
필수 필드를 포함한 최소한의 유효한 예시입니다. ID와 URL을 바꿔 사용하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
$schema: "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json",
|
||||
manifestVersion: "1.23",
|
||||
version: "1.0.0",
|
||||
id: "00000000-0000-0000-0000-000000000000",
|
||||
name: { short: "OpenClaw" },
|
||||
developer: {
|
||||
name: "Your Org",
|
||||
websiteUrl: "https://example.com",
|
||||
privacyUrl: "https://example.com/privacy",
|
||||
termsOfUseUrl: "https://example.com/terms",
|
||||
},
|
||||
description: { short: "OpenClaw in Teams", full: "OpenClaw in Teams" },
|
||||
icons: { outline: "outline.png", color: "color.png" },
|
||||
accentColor: "#5B6DEF",
|
||||
bots: [
|
||||
{
|
||||
botId: "11111111-1111-1111-1111-111111111111",
|
||||
scopes: ["personal", "team", "groupChat"],
|
||||
isNotificationOnly: false,
|
||||
supportsCalling: false,
|
||||
supportsVideo: false,
|
||||
supportsFiles: true,
|
||||
},
|
||||
],
|
||||
webApplicationInfo: {
|
||||
id: "11111111-1111-1111-1111-111111111111",
|
||||
},
|
||||
authorization: {
|
||||
permissions: {
|
||||
resourceSpecific: [
|
||||
{ name: "ChannelMessage.Read.Group", type: "Application" },
|
||||
{ name: "ChannelMessage.Send.Group", type: "Application" },
|
||||
{ name: "Member.Read.Group", type: "Application" },
|
||||
{ name: "Owner.Read.Group", type: "Application" },
|
||||
{ name: "ChannelSettings.Read.Group", type: "Application" },
|
||||
{ name: "TeamMember.Read.Group", type: "Application" },
|
||||
{ name: "TeamSettings.Read.Group", type: "Application" },
|
||||
{ name: "ChatMessage.Read.Chat", type: "Application" },
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Manifest 주의 사항(필수 필드)
|
||||
|
||||
- `bots[].botId`는 Azure Bot App ID와 **반드시** 일치해야 합니다.
|
||||
- `webApplicationInfo.id`는 Azure Bot App ID와 **반드시** 일치해야 합니다.
|
||||
- `bots[].scopes`에는 사용할 표면(`personal`, `team`, `groupChat`)이 포함되어야 합니다.
|
||||
- `bots[].supportsFiles: true`는 개인 범위 파일 처리에 필요합니다.
|
||||
- 채널 트래픽을 원한다면 `authorization.permissions.resourceSpecific`에 채널 읽기/보내기가 포함되어야 합니다.
|
||||
|
||||
### 기존 앱 업데이트
|
||||
|
||||
이미 설치된 Teams 앱을 업데이트하려면(예: RSC 권한 추가):
|
||||
|
||||
1. 새 설정으로 `manifest.json`을 업데이트합니다
|
||||
2. **`version` 필드를 증가**시킵니다(예: `1.0.0` → `1.1.0`)
|
||||
3. 아이콘과 함께 manifest를 **다시 zip으로 묶습니다**(`manifest.json`, `outline.png`, `color.png`)
|
||||
4. 새 zip을 업로드합니다.
|
||||
- **옵션 A (Teams Admin Center):** Teams Admin Center → Teams apps → Manage apps → 앱 찾기 → Upload new version
|
||||
- **옵션 B (Sideload):** Teams → Apps → Manage your apps → Upload a custom app
|
||||
5. **팀 채널의 경우:** 새 권한이 적용되도록 각 팀에 앱을 다시 설치합니다
|
||||
6. 캐시된 앱 메타데이터를 지우기 위해 Teams를 **완전히 종료 후 다시 실행**합니다(창만 닫지 말 것)
|
||||
|
||||
## 기능: RSC 전용 vs Graph
|
||||
|
||||
### **Teams RSC만 사용**하는 경우(앱 설치됨, Graph API 권한 없음)
|
||||
|
||||
작동함:
|
||||
|
||||
- 채널 메시지 **텍스트** 콘텐츠 읽기.
|
||||
- 채널 메시지 **텍스트** 콘텐츠 보내기.
|
||||
- **개인(DM)** 파일 첨부 수신.
|
||||
|
||||
작동하지 않음:
|
||||
|
||||
- 채널/그룹 **이미지 또는 파일 콘텐츠**(payload에는 HTML stub만 포함됨).
|
||||
- SharePoint/OneDrive에 저장된 첨부파일 다운로드.
|
||||
- 메시지 기록 읽기(실시간 웹훅 이벤트 범위 초과).
|
||||
|
||||
### **Teams RSC + Microsoft Graph Application 권한** 사용 시
|
||||
|
||||
추가됨:
|
||||
|
||||
- 호스팅된 콘텐츠 다운로드(메시지에 붙여넣은 이미지).
|
||||
- SharePoint/OneDrive에 저장된 파일 첨부 다운로드.
|
||||
- Graph를 통한 채널/채팅 메시지 기록 읽기.
|
||||
|
||||
### RSC vs Graph API
|
||||
|
||||
| Capability | RSC Permissions | Graph API |
|
||||
| ----------------------- | -------------------- | ----------------------------------- |
|
||||
| **실시간 메시지** | 예(웹훅을 통해) | 아니요(폴링만 가능) |
|
||||
| **과거 메시지** | 아니요 | 예(기록 조회 가능) |
|
||||
| **설정 복잡도** | 앱 manifest만 필요 | 관리자 동의 + 토큰 흐름 필요 |
|
||||
| **오프라인 동작** | 아니요(실행 중이어야 함) | 예(언제든 조회 가능) |
|
||||
|
||||
**요약:** RSC는 실시간 수신용이고, Graph API는 과거 기록 접근용입니다. 오프라인 동안 놓친 메시지를 따라잡으려면 Graph API와 `ChannelMessage.Read.All`이 필요합니다(관리자 동의 필요).
|
||||
|
||||
## Graph 기반 미디어 + 기록(채널에 필요)
|
||||
|
||||
**채널**에서 이미지/파일이 필요하거나 **메시지 기록**을 가져오려면 Microsoft Graph 권한을 활성화하고 관리자 동의를 받아야 합니다.
|
||||
|
||||
1. Entra ID (Azure AD) **App Registration**에서 Microsoft Graph **Application permissions**를 추가합니다.
|
||||
- `ChannelMessage.Read.All` (채널 첨부파일 + 기록)
|
||||
- `Chat.Read.All` 또는 `ChatMessage.Read.All` (그룹 채팅)
|
||||
2. 테넌트에 대해 **관리자 동의**를 부여합니다.
|
||||
3. Teams 앱 **manifest 버전**을 올리고, 다시 업로드한 뒤, **Teams에 앱을 재설치**합니다.
|
||||
4. 캐시된 앱 메타데이터를 지우기 위해 Teams를 **완전히 종료 후 다시 실행**합니다.
|
||||
|
||||
**사용자 멘션을 위한 추가 권한:** 사용자 @멘션은 대화에 있는 사용자에 대해서는 기본적으로 작동합니다. 하지만 현재 대화에 **없는** 사용자를 동적으로 검색하고 멘션하려면 `User.Read.All` (Application) 권한을 추가하고 관리자 동의를 부여하세요.
|
||||
|
||||
## 알려진 제한 사항
|
||||
|
||||
### 웹훅 시간 초과
|
||||
|
||||
Teams는 HTTP 웹훅을 통해 메시지를 전달합니다. 처리가 너무 오래 걸리면(예: 느린 LLM 응답) 다음이 발생할 수 있습니다.
|
||||
|
||||
- 게이트웨이 시간 초과
|
||||
- Teams가 메시지를 재시도함(중복 발생)
|
||||
- 응답 누락
|
||||
|
||||
OpenClaw는 빠르게 응답을 반환하고 적극적으로 답장을 보내 이 문제를 처리하지만, 응답이 매우 느리면 여전히 문제가 발생할 수 있습니다.
|
||||
|
||||
### 서식
|
||||
|
||||
Teams 마크다운은 Slack이나 Discord보다 제한적입니다.
|
||||
|
||||
- 기본 서식은 작동합니다: **굵게**, _기울임_, `code`, 링크
|
||||
- 복잡한 마크다운(표, 중첩 목록)은 올바르게 렌더링되지 않을 수 있습니다
|
||||
- Polls 및 임의 카드 전송에는 Adaptive Cards가 지원됩니다(아래 참조)
|
||||
|
||||
## 구성
|
||||
|
||||
주요 설정(공유 채널 패턴은 `/gateway/configuration` 참조):
|
||||
|
||||
- `channels.msteams.enabled`: 채널 활성화/비활성화.
|
||||
- `channels.msteams.appId`, `channels.msteams.appPassword`, `channels.msteams.tenantId`: 봇 자격 증명.
|
||||
- `channels.msteams.webhook.port` (기본값 `3978`)
|
||||
- `channels.msteams.webhook.path` (기본값 `/api/messages`)
|
||||
- `channels.msteams.dmPolicy`: `pairing | allowlist | open | disabled` (기본값: pairing)
|
||||
- `channels.msteams.allowFrom`: DM 허용 목록(AAD object ID 권장). Graph 액세스를 사용할 수 있을 때 마법사가 설정 중 이름을 ID로 확인합니다.
|
||||
- `channels.msteams.dangerouslyAllowNameMatching`: 변경 가능한 UPN/표시 이름 일치 및 직접 팀/채널 이름 라우팅을 다시 활성화하는 비상 토글.
|
||||
- `channels.msteams.textChunkLimit`: 아웃바운드 텍스트 청크 크기.
|
||||
- `channels.msteams.chunkMode`: `length`(기본값) 또는 `newline`으로, 길이 기준 청킹 전에 빈 줄(문단 경계)에서 분할합니다.
|
||||
- `channels.msteams.mediaAllowHosts`: 인바운드 첨부파일 호스트 허용 목록(기본값은 Microsoft/Teams 도메인).
|
||||
- `channels.msteams.mediaAuthAllowHosts`: 미디어 재시도 시 Authorization 헤더를 붙일 호스트 허용 목록(기본값은 Graph + Bot Framework 호스트).
|
||||
- `channels.msteams.requireMention`: 채널/그룹에서 @멘션 필요 여부(기본값 true).
|
||||
- `channels.msteams.replyStyle`: `thread | top-level`([응답 스타일](#reply-style-threads-vs-posts) 참조).
|
||||
- `channels.msteams.teams.<teamId>.replyStyle`: 팀별 재정의.
|
||||
- `channels.msteams.teams.<teamId>.requireMention`: 팀별 재정의.
|
||||
- `channels.msteams.teams.<teamId>.tools`: 채널 재정의가 없을 때 사용하는 기본 팀별 도구 정책 재정의(`allow`/`deny`/`alsoAllow`).
|
||||
- `channels.msteams.teams.<teamId>.toolsBySender`: 기본 팀별 발신자별 도구 정책 재정의(`"*"` 와일드카드 지원).
|
||||
- `channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle`: 채널별 재정의.
|
||||
- `channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention`: 채널별 재정의.
|
||||
- `channels.msteams.teams.<teamId>.channels.<conversationId>.tools`: 채널별 도구 정책 재정의(`allow`/`deny`/`alsoAllow`).
|
||||
- `channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender`: 채널별 발신자별 도구 정책 재정의(`"*"` 와일드카드 지원).
|
||||
- `toolsBySender` 키는 명시적 접두사를 사용해야 합니다.
|
||||
`id:`, `e164:`, `username:`, `name:` (기존의 접두사 없는 키는 여전히 `id:`로만 매핑됨).
|
||||
- `channels.msteams.actions.memberInfo`: Graph 기반 멤버 정보 작업 활성화/비활성화(기본값: Graph 자격 증명을 사용할 수 있으면 활성화).
|
||||
- `channels.msteams.sharePointSiteId`: 그룹 채팅/채널의 파일 업로드용 SharePoint site ID([그룹 채팅에서 파일 보내기](#sending-files-in-group-chats) 참조).
|
||||
|
||||
## 라우팅 및 세션
|
||||
|
||||
- 세션 키는 표준 에이전트 형식을 따릅니다([/concepts/session](/concepts/session) 참조).
|
||||
- 다이렉트 메시지는 기본 세션을 공유합니다(`agent:<agentId>:<mainKey>`).
|
||||
- 채널/그룹 메시지는 conversation id를 사용합니다.
|
||||
- `agent:<agentId>:msteams:channel:<conversationId>`
|
||||
- `agent:<agentId>:msteams:group:<conversationId>`
|
||||
|
||||
## 응답 스타일: 스레드 vs 게시물
|
||||
|
||||
Teams는 최근 동일한 기본 데이터 모델 위에서 두 가지 채널 UI 스타일을 도입했습니다.
|
||||
|
||||
| Style | Description | 권장 `replyStyle` |
|
||||
| ------------------------ | --------------------------------------------------------- | ------------------------ |
|
||||
| **Posts** (클래식) | 메시지가 카드로 표시되고 그 아래에 스레드 응답이 달림 | `thread` (기본값) |
|
||||
| **Threads** (Slack 유사) | 메시지가 더 Slack처럼 선형으로 흐름 | `top-level` |
|
||||
|
||||
**문제:** Teams API는 채널이 어떤 UI 스타일을 사용하는지 노출하지 않습니다. 잘못된 `replyStyle`을 사용하면 다음과 같습니다.
|
||||
|
||||
- Threads 스타일 채널에서 `thread` 사용 → 응답이 어색하게 중첩되어 표시됨
|
||||
- Posts 스타일 채널에서 `top-level` 사용 → 응답이 스레드 내부가 아니라 별도 최상위 게시물로 표시됨
|
||||
|
||||
**해결책:** 채널이 어떻게 설정되어 있는지에 따라 채널별로 `replyStyle`을 구성하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
msteams: {
|
||||
replyStyle: "thread",
|
||||
teams: {
|
||||
"19:abc...@thread.tacv2": {
|
||||
channels: {
|
||||
"19:xyz...@thread.tacv2": {
|
||||
replyStyle: "top-level",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 첨부파일 및 이미지
|
||||
|
||||
**현재 제한 사항:**
|
||||
|
||||
- **DM:** Teams 봇 파일 API를 통해 이미지와 파일 첨부가 동작합니다.
|
||||
- **채널/그룹:** 첨부파일은 M365 스토리지(SharePoint/OneDrive)에 저장됩니다. 웹훅 payload에는 실제 파일 바이트가 아닌 HTML stub만 포함됩니다. 채널 첨부파일을 다운로드하려면 **Graph API 권한이 필요합니다**.
|
||||
- 명시적 파일 우선 전송에는 `media` / `filePath` / `path`와 함께 `action=upload-file`을 사용하세요. 선택적 `message`는 함께 전송되는 텍스트/주석이 되며, `filename`은 업로드 이름을 재정의합니다.
|
||||
|
||||
Graph 권한이 없으면 이미지가 포함된 채널 메시지는 텍스트 전용으로 수신됩니다(이미지 콘텐츠에는 봇이 접근할 수 없음).
|
||||
기본적으로 OpenClaw는 Microsoft/Teams 호스트명에서만 미디어를 다운로드합니다. `channels.msteams.mediaAllowHosts`로 재정의하세요(모든 호스트를 허용하려면 `["*"]` 사용).
|
||||
Authorization 헤더는 `channels.msteams.mediaAuthAllowHosts`에 포함된 호스트에만 첨부됩니다(기본값은 Graph + Bot Framework 호스트). 이 목록은 엄격하게 유지하세요(멀티 테넌트 접미사는 피함).
|
||||
|
||||
## 그룹 채팅에서 파일 보내기
|
||||
|
||||
봇은 DM에서 FileConsentCard 흐름(기본 제공)을 사용해 파일을 보낼 수 있습니다. 그러나 **그룹 채팅/채널에서 파일 보내기**에는 추가 설정이 필요합니다.
|
||||
|
||||
| Context | 파일 전송 방식 | 필요한 설정 |
|
||||
| ------------------------ | -------------------------------------------- | ----------------------------------------------- |
|
||||
| **DM** | FileConsentCard → 사용자가 수락 → 봇이 업로드 | 기본적으로 동작 |
|
||||
| **그룹 채팅/채널** | SharePoint에 업로드 → 링크 공유 | `sharePointSiteId` + Graph 권한 필요 |
|
||||
| **이미지(모든 컨텍스트)** | Base64 인라인 인코딩 | 기본적으로 동작 |
|
||||
|
||||
### 그룹 채팅에 SharePoint가 필요한 이유
|
||||
|
||||
봇에는 개인 OneDrive 드라이브가 없습니다(`/me/drive` Graph API 엔드포인트는 애플리케이션 ID에서 동작하지 않음). 그룹 채팅/채널로 파일을 보내려면 봇이 **SharePoint 사이트**에 업로드하고 공유 링크를 생성해야 합니다.
|
||||
|
||||
### 설정
|
||||
|
||||
1. Entra ID (Azure AD) → App Registration에서 **Graph API 권한**을 추가합니다.
|
||||
- `Sites.ReadWrite.All` (Application) - SharePoint에 파일 업로드
|
||||
- `Chat.Read.All` (Application) - 선택 사항, 사용자별 공유 링크 활성화
|
||||
|
||||
2. 테넌트에 대해 **관리자 동의**를 부여합니다.
|
||||
|
||||
3. **SharePoint site ID 가져오기:**
|
||||
|
||||
```bash
|
||||
# Graph Explorer 또는 유효한 토큰이 포함된 curl 사용:
|
||||
curl -H "Authorization: Bearer $TOKEN" \
|
||||
"https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}"
|
||||
|
||||
# 예: "contoso.sharepoint.com/sites/BotFiles" 사이트의 경우
|
||||
curl -H "Authorization: Bearer $TOKEN" \
|
||||
"https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles"
|
||||
|
||||
# 응답에 포함됨: "id": "contoso.sharepoint.com,guid1,guid2"
|
||||
```
|
||||
|
||||
4. **OpenClaw 구성:**
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
msteams: {
|
||||
// ... other config ...
|
||||
sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 공유 동작
|
||||
|
||||
| Permission | 공유 동작 |
|
||||
| --------------------------------------- | --------------------------------------------------------- |
|
||||
| `Sites.ReadWrite.All`만 | 조직 전체 공유 링크(조직 내 누구나 접근 가능) |
|
||||
| `Sites.ReadWrite.All` + `Chat.Read.All` | 사용자별 공유 링크(채팅 멤버만 접근 가능) |
|
||||
|
||||
사용자별 공유는 채팅 참여자만 파일에 접근할 수 있으므로 더 안전합니다. `Chat.Read.All` 권한이 없으면 봇은 조직 전체 공유로 대체합니다.
|
||||
|
||||
### 대체 동작
|
||||
|
||||
| Scenario | 결과 |
|
||||
| ------------------------------------------------- | -------------------------------------------------- |
|
||||
| 그룹 채팅 + 파일 + `sharePointSiteId` 구성됨 | SharePoint에 업로드, 공유 링크 전송 |
|
||||
| 그룹 채팅 + 파일 + `sharePointSiteId` 없음 | OneDrive 업로드 시도(실패 가능), 텍스트만 전송 |
|
||||
| 개인 채팅 + 파일 | FileConsentCard 흐름(SharePoint 없이 동작) |
|
||||
| 모든 컨텍스트 + 이미지 | Base64 인라인 인코딩(SharePoint 없이 동작) |
|
||||
|
||||
### 파일 저장 위치
|
||||
|
||||
업로드된 파일은 구성된 SharePoint 사이트의 기본 문서 라이브러리 내 `/OpenClawShared/` 폴더에 저장됩니다.
|
||||
|
||||
## Polls (Adaptive Cards)
|
||||
|
||||
OpenClaw는 Teams Polls를 Adaptive Cards로 보냅니다(Teams에는 기본 Poll API가 없음).
|
||||
|
||||
- CLI: `openclaw message poll --channel msteams --target conversation:<id> ...`
|
||||
- 투표는 게이트웨이가 `~/.openclaw/msteams-polls.json`에 기록합니다.
|
||||
- 투표 기록을 위해 게이트웨이는 계속 온라인 상태여야 합니다.
|
||||
- Polls는 아직 결과 요약을 자동 게시하지 않습니다(필요하면 저장 파일을 확인하세요).
|
||||
|
||||
## Adaptive Cards(임의)
|
||||
|
||||
`message` 도구 또는 CLI를 사용해 임의의 Adaptive Card JSON을 Teams 사용자나 대화에 보낼 수 있습니다.
|
||||
|
||||
`card` 매개변수는 Adaptive Card JSON 객체를 받습니다. `card`가 제공되면 메시지 텍스트는 선택 사항입니다.
|
||||
|
||||
**에이전트 도구:**
|
||||
|
||||
```json5
|
||||
{
|
||||
action: "send",
|
||||
channel: "msteams",
|
||||
target: "user:<id>",
|
||||
card: {
|
||||
type: "AdaptiveCard",
|
||||
version: "1.5",
|
||||
body: [{ type: "TextBlock", text: "Hello!" }],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**CLI:**
|
||||
|
||||
```bash
|
||||
openclaw message send --channel msteams \
|
||||
--target "conversation:19:abc...@thread.tacv2" \
|
||||
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}'
|
||||
```
|
||||
|
||||
카드 스키마와 예시는 [Adaptive Cards documentation](https://adaptivecards.io/)을 참조하세요. 대상 형식 세부 정보는 아래 [대상 형식](#target-formats)을 참조하세요.
|
||||
|
||||
## 대상 형식
|
||||
|
||||
MSTeams 대상은 사용자와 대화를 구분하기 위해 접두사를 사용합니다.
|
||||
|
||||
| Target type | Format | Example |
|
||||
| ------------------- | -------------------------------- | --------------------------------------------------- |
|
||||
| 사용자(ID 기준) | `user:<aad-object-id>` | `user:40a1a0ed-4ff2-4164-a219-55518990c197` |
|
||||
| 사용자(이름 기준) | `user:<display-name>` | `user:John Smith` (Graph API 필요) |
|
||||
| 그룹/채널 | `conversation:<conversation-id>` | `conversation:19:abc123...@thread.tacv2` |
|
||||
| 그룹/채널(raw) | `<conversation-id>` | `19:abc123...@thread.tacv2` (`@thread`가 포함된 경우) |
|
||||
|
||||
**CLI 예시:**
|
||||
|
||||
```bash
|
||||
# ID로 사용자에게 전송
|
||||
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"
|
||||
|
||||
# 표시 이름으로 사용자에게 전송(Graph API 조회 트리거)
|
||||
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"
|
||||
|
||||
# 그룹 채팅 또는 채널로 전송
|
||||
openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello"
|
||||
|
||||
# 대화에 Adaptive Card 전송
|
||||
openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" \
|
||||
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}'
|
||||
```
|
||||
|
||||
**에이전트 도구 예시:**
|
||||
|
||||
```json5
|
||||
{
|
||||
action: "send",
|
||||
channel: "msteams",
|
||||
target: "user:John Smith",
|
||||
message: "Hello!",
|
||||
}
|
||||
```
|
||||
|
||||
```json5
|
||||
{
|
||||
action: "send",
|
||||
channel: "msteams",
|
||||
target: "conversation:19:abc...@thread.tacv2",
|
||||
card: {
|
||||
type: "AdaptiveCard",
|
||||
version: "1.5",
|
||||
body: [{ type: "TextBlock", text: "Hello" }],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고: `user:` 접두사가 없으면 이름은 기본적으로 그룹/팀 확인으로 처리됩니다. 표시 이름으로 사람을 지정할 때는 항상 `user:`를 사용하세요.
|
||||
|
||||
## Proactive messaging
|
||||
|
||||
- Proactive 메시지는 사용자가 상호작용한 **이후에만** 가능합니다. 그 시점에 대화 참조를 저장하기 때문입니다.
|
||||
- `dmPolicy`와 허용 목록 게이팅은 `/gateway/configuration`을 참조하세요.
|
||||
|
||||
## 팀 및 채널 ID(흔한 함정)
|
||||
|
||||
Teams URL의 `groupId` 쿼리 매개변수는 구성에 사용하는 팀 ID가 **아닙니다**. 대신 URL 경로에서 ID를 추출하세요.
|
||||
|
||||
**팀 URL:**
|
||||
|
||||
```
|
||||
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
|
||||
└────────────────────────────┘
|
||||
팀 ID(URL 디코딩 필요)
|
||||
```
|
||||
|
||||
**채널 URL:**
|
||||
|
||||
```
|
||||
https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
|
||||
└─────────────────────────┘
|
||||
채널 ID(URL 디코딩 필요)
|
||||
```
|
||||
|
||||
**config용:**
|
||||
|
||||
- 팀 ID = `/team/` 뒤의 경로 세그먼트(URL 디코딩됨, 예: `19:Bk4j...@thread.tacv2`)
|
||||
- 채널 ID = `/channel/` 뒤의 경로 세그먼트(URL 디코딩됨)
|
||||
- `groupId` 쿼리 매개변수는 **무시**하세요
|
||||
|
||||
## 비공개 채널
|
||||
|
||||
봇은 비공개 채널에서 제한적으로 지원됩니다.
|
||||
|
||||
| Feature | Standard Channels | Private Channels |
|
||||
| ---------------------------- | ----------------- | ---------------------- |
|
||||
| 봇 설치 | 예 | 제한적 |
|
||||
| 실시간 메시지(웹훅) | 예 | 동작하지 않을 수 있음 |
|
||||
| RSC 권한 | 예 | 다르게 동작할 수 있음 |
|
||||
| @mentions | 예 | 봇에 접근 가능할 경우 |
|
||||
| Graph API 기록 | 예 | 예(권한 필요) |
|
||||
|
||||
**비공개 채널이 동작하지 않을 때의 우회 방법:**
|
||||
|
||||
1. 봇 상호작용에는 표준 채널 사용
|
||||
2. DM 사용 - 사용자는 항상 봇에 직접 메시지를 보낼 수 있음
|
||||
3. 과거 접근에는 Graph API 사용(`ChannelMessage.Read.All` 필요)
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 일반적인 문제
|
||||
|
||||
- **채널에 이미지가 표시되지 않음:** Graph 권한 또는 관리자 동의가 누락되었습니다. Teams 앱을 재설치하고 Teams를 완전히 종료 후 다시 여세요.
|
||||
- **채널에서 응답 없음:** 기본적으로 멘션이 필요합니다. `channels.msteams.requireMention=false`를 설정하거나 팀/채널별로 구성하세요.
|
||||
- **버전 불일치(Teams에 이전 manifest가 계속 표시됨):** 앱을 제거 후 다시 추가하고 Teams를 완전히 종료해 새로고침하세요.
|
||||
- **웹훅에서 401 Unauthorized:** Azure JWT 없이 수동 테스트할 때는 정상입니다. 엔드포인트에 도달했지만 인증에 실패했다는 뜻입니다. 올바른 테스트에는 Azure Web Chat을 사용하세요.
|
||||
|
||||
### Manifest 업로드 오류
|
||||
|
||||
- **"Icon file cannot be empty":** manifest가 참조하는 아이콘 파일이 0바이트입니다. 유효한 PNG 아이콘을 만드세요(`outline.png`는 32x32, `color.png`는 192x192).
|
||||
- **"webApplicationInfo.Id already in use":** 앱이 다른 팀/채팅에 아직 설치되어 있습니다. 먼저 찾아 제거하거나 전파를 위해 5~10분 기다리세요.
|
||||
- **업로드 시 "Something went wrong":** 대신 [https://admin.teams.microsoft.com](https://admin.teams.microsoft.com)을 통해 업로드하고, 브라우저 DevTools(F12) → Network 탭에서 실제 응답 본문 오류를 확인하세요.
|
||||
- **사이드로드 실패:** "Upload a custom app" 대신 "Upload an app to your org's app catalog"를 시도하세요. 이 방식이 사이드로드 제한을 우회하는 경우가 많습니다.
|
||||
|
||||
### RSC 권한이 작동하지 않음
|
||||
|
||||
1. `webApplicationInfo.id`가 봇의 App ID와 정확히 일치하는지 확인하세요
|
||||
2. 앱을 다시 업로드하고 팀/채팅에 재설치하세요
|
||||
3. 조직 관리자가 RSC 권한을 차단했는지 확인하세요
|
||||
4. 올바른 범위를 사용 중인지 확인하세요: 팀에는 `ChannelMessage.Read.Group`, 그룹 채팅에는 `ChatMessage.Read.Chat`
|
||||
|
||||
## 참고 자료
|
||||
|
||||
- [Create Azure Bot](https://learn.microsoft.com/en-us/azure/bot-service/bot-service-quickstart-registration) - Azure Bot 설정 가이드
|
||||
- [Teams Developer Portal](https://dev.teams.microsoft.com/apps) - Teams 앱 생성/관리
|
||||
- [Teams app manifest schema](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema)
|
||||
- [Receive channel messages with RSC](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/channel-messages-with-rsc)
|
||||
- [RSC permissions reference](https://learn.microsoft.com/en-us/microsoftteams/platform/graph-api/rsc/resource-specific-consent)
|
||||
- [Teams bot file handling](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4) (채널/그룹에는 Graph 필요)
|
||||
- [Proactive messaging](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages)
|
||||
|
||||
## 관련
|
||||
|
||||
- [Channels Overview](/channels) — 지원되는 모든 채널
|
||||
- [Pairing](/channels/pairing) — DM 인증 및 pairing 흐름
|
||||
- [Groups](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [Channel Routing](/channels/channel-routing) — 메시지 세션 라우팅
|
||||
- [Security](/gateway/security) — 액세스 모델 및 보안 강화
|
||||
156
docs/ko/channels/nextcloud-talk.md
Normal file
156
docs/ko/channels/nextcloud-talk.md
Normal file
@ -0,0 +1,156 @@
|
||||
---
|
||||
read_when:
|
||||
- Nextcloud Talk 채널 기능을 작업할 때
|
||||
summary: Nextcloud Talk 지원 상태, 기능 및 구성
|
||||
title: Nextcloud Talk
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:42Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 900402afe67cf3ce96103d55158eb28cffb29c9845b77248e70d7653b12ae810
|
||||
source_path: channels/nextcloud-talk.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Nextcloud Talk
|
||||
|
||||
상태: 번들 plugin(webhook bot). 다이렉트 메시지, 룸, 반응, 마크다운 메시지가 지원됩니다.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
Nextcloud Talk는 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 있으므로
|
||||
일반 패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
이전 빌드 또는 Nextcloud Talk가 제외된 사용자 지정 설치를 사용하는 경우
|
||||
수동으로 설치하세요.
|
||||
|
||||
CLI를 통해 설치(npm 레지스트리):
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/nextcloud-talk
|
||||
```
|
||||
|
||||
로컬 체크아웃(git 리포지토리에서 실행하는 경우):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./path/to/local/nextcloud-talk-plugin
|
||||
```
|
||||
|
||||
자세한 내용: [Plugins](/tools/plugin)
|
||||
|
||||
## 빠른 설정(초보자용)
|
||||
|
||||
1. Nextcloud Talk plugin을 사용할 수 있는지 확인합니다.
|
||||
- 현재 패키지된 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 이전/사용자 지정 설치에서는 위 명령으로 수동 추가할 수 있습니다.
|
||||
2. Nextcloud 서버에서 bot을 생성합니다.
|
||||
|
||||
```bash
|
||||
./occ talk:bot:install "OpenClaw" "<shared-secret>" "<webhook-url>" --feature reaction
|
||||
```
|
||||
|
||||
3. 대상 룸 설정에서 bot을 활성화합니다.
|
||||
4. OpenClaw를 구성합니다.
|
||||
- Config: `channels.nextcloud-talk.baseUrl` + `channels.nextcloud-talk.botSecret`
|
||||
- 또는 env: `NEXTCLOUD_TALK_BOT_SECRET` (기본 계정 전용)
|
||||
5. gateway를 다시 시작합니다(또는 설정을 완료합니다).
|
||||
|
||||
최소 구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"nextcloud-talk": {
|
||||
enabled: true,
|
||||
baseUrl: "https://cloud.example.com",
|
||||
botSecret: "shared-secret",
|
||||
dmPolicy: "pairing",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 참고
|
||||
|
||||
- bot은 DM을 시작할 수 없습니다. 사용자가 먼저 bot에 메시지를 보내야 합니다.
|
||||
- webhook URL은 Gateway에서 도달 가능해야 합니다. 프록시 뒤에 있는 경우 `webhookPublicUrl`을 설정하세요.
|
||||
- bot API는 미디어 업로드를 지원하지 않으므로 미디어는 URL로 전송됩니다.
|
||||
- webhook payload는 DM과 룸을 구분하지 않습니다. 룸 유형 조회를 활성화하려면 `apiUser` + `apiPassword`를 설정하세요(그렇지 않으면 DM은 룸으로 처리됩니다).
|
||||
|
||||
## 액세스 제어(DM)
|
||||
|
||||
- 기본값: `channels.nextcloud-talk.dmPolicy = "pairing"`. 알 수 없는 발신자는 페어링 코드를 받습니다.
|
||||
- 승인 방법:
|
||||
- `openclaw pairing list nextcloud-talk`
|
||||
- `openclaw pairing approve nextcloud-talk <CODE>`
|
||||
- 공개 DM: `channels.nextcloud-talk.dmPolicy="open"` 및 `channels.nextcloud-talk.allowFrom=["*"]`.
|
||||
- `allowFrom`은 Nextcloud 사용자 ID에만 일치하며 표시 이름은 무시됩니다.
|
||||
|
||||
## 룸(그룹)
|
||||
|
||||
- 기본값: `channels.nextcloud-talk.groupPolicy = "allowlist"` (멘션 게이트 적용).
|
||||
- `channels.nextcloud-talk.rooms`로 룸을 허용 목록에 추가합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"nextcloud-talk": {
|
||||
rooms: {
|
||||
"room-token": { requireMention: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
- 어떤 룸도 허용하지 않으려면 허용 목록을 비워 두거나 `channels.nextcloud-talk.groupPolicy="disabled"`를 설정하세요.
|
||||
|
||||
## 기능
|
||||
|
||||
| 기능 | 상태 |
|
||||
| --------------- | ------------- |
|
||||
| 다이렉트 메시지 | 지원됨 |
|
||||
| 룸 | 지원됨 |
|
||||
| 스레드 | 지원되지 않음 |
|
||||
| 미디어 | URL 전용 |
|
||||
| 반응 | 지원됨 |
|
||||
| 네이티브 명령 | 지원되지 않음 |
|
||||
|
||||
## 구성 참조(Nextcloud Talk)
|
||||
|
||||
전체 구성: [구성](/gateway/configuration)
|
||||
|
||||
Provider 옵션:
|
||||
|
||||
- `channels.nextcloud-talk.enabled`: 채널 시작 활성화/비활성화
|
||||
- `channels.nextcloud-talk.baseUrl`: Nextcloud 인스턴스 URL
|
||||
- `channels.nextcloud-talk.botSecret`: bot 공유 시크릿
|
||||
- `channels.nextcloud-talk.botSecretFile`: 일반 파일 시크릿 경로. 심볼릭 링크는 거부됩니다.
|
||||
- `channels.nextcloud-talk.apiUser`: 룸 조회(DM 감지)용 API 사용자
|
||||
- `channels.nextcloud-talk.apiPassword`: 룸 조회용 API/앱 비밀번호
|
||||
- `channels.nextcloud-talk.apiPasswordFile`: API 비밀번호 파일 경로
|
||||
- `channels.nextcloud-talk.webhookPort`: webhook 리스너 포트(기본값: 8788)
|
||||
- `channels.nextcloud-talk.webhookHost`: webhook 호스트(기본값: 0.0.0.0)
|
||||
- `channels.nextcloud-talk.webhookPath`: webhook 경로(기본값: /nextcloud-talk-webhook)
|
||||
- `channels.nextcloud-talk.webhookPublicUrl`: 외부에서 도달 가능한 webhook URL
|
||||
- `channels.nextcloud-talk.dmPolicy`: `pairing | allowlist | open | disabled`
|
||||
- `channels.nextcloud-talk.allowFrom`: DM 허용 목록(사용자 ID). `open`에는 `"*"`가 필요합니다.
|
||||
- `channels.nextcloud-talk.groupPolicy`: `allowlist | open | disabled`
|
||||
- `channels.nextcloud-talk.groupAllowFrom`: 그룹 허용 목록(사용자 ID)
|
||||
- `channels.nextcloud-talk.rooms`: 룸별 설정 및 허용 목록
|
||||
- `channels.nextcloud-talk.historyLimit`: 그룹 기록 제한(0이면 비활성화)
|
||||
- `channels.nextcloud-talk.dmHistoryLimit`: DM 기록 제한(0이면 비활성화)
|
||||
- `channels.nextcloud-talk.dms`: DM별 재정의(`historyLimit`)
|
||||
- `channels.nextcloud-talk.textChunkLimit`: 아웃바운드 텍스트 청크 크기(문자 수)
|
||||
- `channels.nextcloud-talk.chunkMode`: 길이 청킹 전에 빈 줄(문단 경계) 기준으로 분할하는 `length`(기본값) 또는 `newline`
|
||||
- `channels.nextcloud-talk.blockStreaming`: 이 채널의 블록 스트리밍 비활성화
|
||||
- `channels.nextcloud-talk.blockStreamingCoalesce`: 블록 스트리밍 병합 조정
|
||||
- `channels.nextcloud-talk.mediaMaxMb`: 인바운드 미디어 제한(MB)
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 강화
|
||||
257
docs/ko/channels/nostr.md
Normal file
257
docs/ko/channels/nostr.md
Normal file
@ -0,0 +1,257 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw가 Nostr를 통해 DM을 수신하도록 하려는 경우
|
||||
- 탈중앙화 메시징을 설정하는 경우
|
||||
summary: NIP-04 암호화 메시지를 통한 Nostr DM 채널
|
||||
title: Nostr
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:49Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: f82829ee66fbeb3367007af343797140049ea49f2e842a695fa56acea0c80728
|
||||
source_path: channels/nostr.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Nostr
|
||||
|
||||
**상태:** 선택적 번들 plugin(구성되기 전까지 기본적으로 비활성화됨).
|
||||
|
||||
Nostr는 소셜 네트워킹을 위한 탈중앙화 프로토콜입니다. 이 채널을 사용하면 OpenClaw가 NIP-04를 통해 암호화된 다이렉트 메시지(DM)를 수신하고 응답할 수 있습니다.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
현재 OpenClaw 릴리스는 Nostr를 번들 plugin으로 포함하므로, 일반적인 패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
### 이전/사용자 지정 설치
|
||||
|
||||
- 온보딩(`openclaw onboard`)과 `openclaw channels add`는 여전히 공유 채널 카탈로그에서 Nostr를 표시합니다.
|
||||
- 빌드에 번들 Nostr가 제외되어 있다면 수동으로 설치하세요.
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/nostr
|
||||
```
|
||||
|
||||
로컬 체크아웃 사용(개발 워크플로):
|
||||
|
||||
```bash
|
||||
openclaw plugins install --link <path-to-local-nostr-plugin>
|
||||
```
|
||||
|
||||
plugin을 설치하거나 활성화한 후 게이트웨이를 재시작하세요.
|
||||
|
||||
### 비대화형 설정
|
||||
|
||||
```bash
|
||||
openclaw channels add --channel nostr --private-key "$NOSTR_PRIVATE_KEY"
|
||||
openclaw channels add --channel nostr --private-key "$NOSTR_PRIVATE_KEY" --relay-urls "wss://relay.damus.io,wss://relay.primal.net"
|
||||
```
|
||||
|
||||
키를 config에 저장하는 대신 환경에 `NOSTR_PRIVATE_KEY`를 유지하려면 `--use-env`를 사용하세요.
|
||||
|
||||
## 빠른 설정
|
||||
|
||||
1. Nostr 키 쌍을 생성합니다(필요한 경우):
|
||||
|
||||
```bash
|
||||
# nak 사용
|
||||
nak key generate
|
||||
```
|
||||
|
||||
2. config에 추가합니다:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
nostr: {
|
||||
privateKey: "${NOSTR_PRIVATE_KEY}",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
3. 키를 export합니다:
|
||||
|
||||
```bash
|
||||
export NOSTR_PRIVATE_KEY="nsec1..."
|
||||
```
|
||||
|
||||
4. 게이트웨이를 재시작합니다.
|
||||
|
||||
## 구성 참조
|
||||
|
||||
| 키 | 유형 | 기본값 | 설명 |
|
||||
| ------------ | -------- | ------------------------------------------- | ----------------------------------- |
|
||||
| `privateKey` | string | 필수 | `nsec` 또는 hex 형식의 비공개 키 |
|
||||
| `relays` | string[] | `['wss://relay.damus.io', 'wss://nos.lol']` | 릴레이 URL(WebSocket) |
|
||||
| `dmPolicy` | string | `pairing` | DM 액세스 정책 |
|
||||
| `allowFrom` | string[] | `[]` | 허용된 발신자 pubkey |
|
||||
| `enabled` | boolean | `true` | 채널 활성화/비활성화 |
|
||||
| `name` | string | - | 표시 이름 |
|
||||
| `profile` | object | - | NIP-01 프로필 메타데이터 |
|
||||
|
||||
## 프로필 메타데이터
|
||||
|
||||
프로필 데이터는 NIP-01 `kind:0` 이벤트로 게시됩니다. Control UI(Channels -> Nostr -> Profile)에서 관리하거나 config에서 직접 설정할 수 있습니다.
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
nostr: {
|
||||
privateKey: "${NOSTR_PRIVATE_KEY}",
|
||||
profile: {
|
||||
name: "openclaw",
|
||||
displayName: "OpenClaw",
|
||||
about: "개인 비서 DM 봇",
|
||||
picture: "https://example.com/avatar.png",
|
||||
banner: "https://example.com/banner.png",
|
||||
website: "https://example.com",
|
||||
nip05: "openclaw@example.com",
|
||||
lud16: "openclaw@example.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 프로필 URL은 `https://`를 사용해야 합니다.
|
||||
- 릴레이에서 가져오면 필드가 병합되며 로컬 재정의는 유지됩니다.
|
||||
|
||||
## 액세스 제어
|
||||
|
||||
### DM 정책
|
||||
|
||||
- **pairing** (기본값): 알 수 없는 발신자에게 페어링 코드가 전송됩니다.
|
||||
- **allowlist**: `allowFrom`의 pubkey만 DM을 보낼 수 있습니다.
|
||||
- **open**: 공개 수신 DM(`allowFrom: ["*"]` 필요).
|
||||
- **disabled**: 수신 DM을 무시합니다.
|
||||
|
||||
강제 적용 참고 사항:
|
||||
|
||||
- 수신 이벤트 서명은 발신자 정책 및 NIP-04 복호화 전에 검증되므로 위조된 이벤트는 조기에 거부됩니다.
|
||||
- 페어링 응답은 원래 DM 본문을 처리하지 않고 전송됩니다.
|
||||
- 수신 DM은 속도 제한이 적용되며 너무 큰 페이로드는 복호화 전에 삭제됩니다.
|
||||
|
||||
### 허용 목록 예시
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
nostr: {
|
||||
privateKey: "${NOSTR_PRIVATE_KEY}",
|
||||
dmPolicy: "allowlist",
|
||||
allowFrom: ["npub1abc...", "npub1xyz..."],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 키 형식
|
||||
|
||||
허용되는 형식:
|
||||
|
||||
- **비공개 키:** `nsec...` 또는 64자 hex
|
||||
- **Pubkey (`allowFrom`):** `npub...` 또는 hex
|
||||
|
||||
## 릴레이
|
||||
|
||||
기본값: `relay.damus.io` 및 `nos.lol`.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
nostr: {
|
||||
privateKey: "${NOSTR_PRIVATE_KEY}",
|
||||
relays: ["wss://relay.damus.io", "wss://relay.primal.net", "wss://nostr.wine"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
팁:
|
||||
|
||||
- 이중화를 위해 2~3개의 릴레이를 사용하세요.
|
||||
- 너무 많은 릴레이는 피하세요(지연 시간, 중복).
|
||||
- 유료 릴레이는 안정성을 높일 수 있습니다.
|
||||
- 테스트에는 로컬 릴레이도 괜찮습니다(`ws://localhost:7777`).
|
||||
|
||||
## 프로토콜 지원
|
||||
|
||||
| NIP | 상태 | 설명 |
|
||||
| ------ | --------- | ----------------------------------- |
|
||||
| NIP-01 | 지원됨 | 기본 이벤트 형식 + 프로필 메타데이터 |
|
||||
| NIP-04 | 지원됨 | 암호화된 DM(`kind:4`) |
|
||||
| NIP-17 | 계획됨 | Gift-wrapped DM |
|
||||
| NIP-44 | 계획됨 | 버전 지정 암호화 |
|
||||
|
||||
## 테스트
|
||||
|
||||
### 로컬 릴레이
|
||||
|
||||
```bash
|
||||
# strfry 시작
|
||||
docker run -p 7777:7777 ghcr.io/hoytech/strfry
|
||||
```
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
nostr: {
|
||||
privateKey: "${NOSTR_PRIVATE_KEY}",
|
||||
relays: ["ws://localhost:7777"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 수동 테스트
|
||||
|
||||
1. 로그에서 봇 pubkey(npub)를 확인합니다.
|
||||
2. Nostr 클라이언트(Damus, Amethyst 등)를 엽니다.
|
||||
3. 봇 pubkey로 DM을 보냅니다.
|
||||
4. 응답을 확인합니다.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 메시지를 수신하지 못함
|
||||
|
||||
- 비공개 키가 유효한지 확인하세요.
|
||||
- 릴레이 URL에 도달할 수 있고 `wss://`를 사용하는지 확인하세요(로컬은 `ws://` 가능).
|
||||
- `enabled`가 `false`가 아닌지 확인하세요.
|
||||
- 게이트웨이 로그에서 릴레이 연결 오류를 확인하세요.
|
||||
|
||||
### 응답을 보내지 못함
|
||||
|
||||
- 릴레이가 쓰기를 허용하는지 확인하세요.
|
||||
- 아웃바운드 연결성을 확인하세요.
|
||||
- 릴레이 속도 제한이 있는지 살펴보세요.
|
||||
|
||||
### 중복 응답
|
||||
|
||||
- 여러 릴레이를 사용할 때는 예상되는 동작입니다.
|
||||
- 메시지는 이벤트 ID로 중복 제거되며, 첫 번째 전달만 응답을 트리거합니다.
|
||||
|
||||
## 보안
|
||||
|
||||
- 비공개 키를 절대 커밋하지 마세요.
|
||||
- 키에는 환경 변수를 사용하세요.
|
||||
- 프로덕션 봇에는 `allowlist`를 고려하세요.
|
||||
- 서명은 발신자 정책 전에 검증되고, 발신자 정책은 복호화 전에 적용되므로 위조된 이벤트는 조기에 거부되며 알 수 없는 발신자가 전체 암호화 작업을 강제할 수 없습니다.
|
||||
|
||||
## 제한 사항 (MVP)
|
||||
|
||||
- 다이렉트 메시지만 지원(그룹 채팅 없음).
|
||||
- 미디어 첨부 파일 없음.
|
||||
- NIP-04만 지원(NIP-17 gift-wrap은 계획됨).
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 강화
|
||||
132
docs/ko/channels/pairing.md
Normal file
132
docs/ko/channels/pairing.md
Normal file
@ -0,0 +1,132 @@
|
||||
---
|
||||
read_when:
|
||||
- DM 접근 제어를 설정할 때
|
||||
- 새 iOS/Android 노드를 페어링할 때
|
||||
- OpenClaw 보안 상태를 검토할 때
|
||||
summary: '페어링 개요: 누가 나에게 DM을 보낼 수 있는지와 어떤 노드가 참여할 수 있는지 승인'
|
||||
title: 페어링
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:35:45Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 2bd99240b3530def23c05a26915d07cf8b730565c2822c6338437f8fb3f285c9
|
||||
source_path: channels/pairing.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 페어링
|
||||
|
||||
“페어링”은 OpenClaw의 명시적인 **소유자 승인** 단계입니다.
|
||||
이는 두 곳에서 사용됩니다.
|
||||
|
||||
1. **DM 페어링**(누가 봇과 대화할 수 있는지)
|
||||
2. **노드 페어링**(어떤 장치/노드가 게이트웨이 네트워크에 참여할 수 있는지)
|
||||
|
||||
보안 맥락: [Security](/gateway/security)
|
||||
|
||||
## 1) DM 페어링(인바운드 채팅 접근)
|
||||
|
||||
채널이 DM 정책 `pairing`으로 구성되면, 알 수 없는 발신자는 짧은 코드를 받게 되며 승인이 이루어질 때까지 해당 메시지는 **처리되지 않습니다**.
|
||||
|
||||
기본 DM 정책은 다음 문서에 설명되어 있습니다: [Security](/gateway/security)
|
||||
|
||||
페어링 코드:
|
||||
|
||||
- 8자, 대문자, 혼동하기 쉬운 문자 없음(`0O1I`).
|
||||
- **1시간 후 만료**됩니다. 봇은 새 요청이 생성될 때만 페어링 메시지를 보냅니다(발신자당 대략 1시간에 한 번).
|
||||
- 대기 중인 DM 페어링 요청은 기본적으로 **채널당 3개**로 제한되며, 하나가 만료되거나 승인될 때까지 추가 요청은 무시됩니다.
|
||||
|
||||
### 발신자 승인
|
||||
|
||||
```bash
|
||||
openclaw pairing list telegram
|
||||
openclaw pairing approve telegram <CODE>
|
||||
```
|
||||
|
||||
지원 채널: `bluebubbles`, `discord`, `feishu`, `googlechat`, `imessage`, `irc`, `line`, `matrix`, `mattermost`, `msteams`, `nextcloud-talk`, `nostr`, `openclaw-weixin`, `signal`, `slack`, `synology-chat`, `telegram`, `twitch`, `whatsapp`, `zalo`, `zalouser`.
|
||||
|
||||
### 상태가 저장되는 위치
|
||||
|
||||
`~/.openclaw/credentials/` 아래에 저장됩니다.
|
||||
|
||||
- 대기 중 요청: `<channel>-pairing.json`
|
||||
- 승인된 allowlist 저장소:
|
||||
- 기본 계정: `<channel>-allowFrom.json`
|
||||
- 비기본 계정: `<channel>-<accountId>-allowFrom.json`
|
||||
|
||||
계정 범위 지정 동작:
|
||||
|
||||
- 비기본 계정은 자신의 범위가 지정된 allowlist 파일만 읽고 씁니다.
|
||||
- 기본 계정은 채널 범위의 범위 미지정 allowlist 파일을 사용합니다.
|
||||
|
||||
이 파일들은 민감한 정보로 취급하세요(assistant에 대한 접근을 제어합니다).
|
||||
|
||||
중요: 이 저장소는 DM 접근용입니다. 그룹 권한 부여는 별개입니다.
|
||||
DM 페어링 코드를 승인한다고 해서 해당 발신자가 자동으로 그룹 명령을 실행하거나 그룹에서 봇을 제어할 수 있게 되는 것은 아닙니다. 그룹 접근의 경우 채널의 명시적인 그룹 allowlist를 구성해야 합니다(예: `groupAllowFrom`, `groups`, 또는 채널에 따라 그룹별/토픽별 재정의).
|
||||
|
||||
## 2) 노드 장치 페어링(iOS/Android/macOS/헤드리스 노드)
|
||||
|
||||
노드는 `role: node`를 가진 **장치**로 게이트웨이에 연결됩니다. 게이트웨이는 승인되어야 하는 장치 페어링 요청을 생성합니다.
|
||||
|
||||
### Telegram으로 페어링(iOS 권장)
|
||||
|
||||
`device-pair` plugin을 사용하면 최초 장치 페어링을 전부 Telegram에서 진행할 수 있습니다.
|
||||
|
||||
1. Telegram에서 봇에게 메시지를 보냅니다: `/pair`
|
||||
2. 봇이 두 개의 메시지로 응답합니다. 하나는 안내 메시지이고, 다른 하나는 Telegram에서 쉽게 복사/붙여넣기할 수 있는 별도의 **설정 코드** 메시지입니다.
|
||||
3. 휴대폰에서 OpenClaw iOS 앱 → Settings → Gateway를 엽니다.
|
||||
4. 설정 코드를 붙여넣고 연결합니다.
|
||||
5. Telegram으로 돌아가 `/pair pending`을 실행한 뒤(요청 ID, 역할, 범위를 검토), 승인합니다.
|
||||
|
||||
설정 코드는 다음을 포함하는 base64 인코딩 JSON 페이로드입니다.
|
||||
|
||||
- `url`: 게이트웨이 WebSocket URL(`ws://...` 또는 `wss://...`)
|
||||
- `bootstrapToken`: 초기 페어링 핸드셰이크에 사용되는, 단일 장치용 단기 bootstrap 토큰
|
||||
|
||||
그 bootstrap 토큰은 내장된 페어링 bootstrap 프로필을 포함합니다.
|
||||
|
||||
- 기본적으로 넘겨지는 `node` 토큰은 `scopes: []`로 유지됩니다
|
||||
- 넘겨지는 `operator` 토큰은 bootstrap allowlist로 계속 제한됩니다:
|
||||
`operator.approvals`, `operator.read`, `operator.talk.secrets`, `operator.write`
|
||||
- bootstrap 범위 검사는 하나의 평면 범위 풀이 아니라 역할 접두사 기반입니다.
|
||||
operator 범위 항목은 operator 요청만 충족하며, 비-operator 역할도 여전히 자신의 역할 접두사 아래에서 범위를 요청해야 합니다
|
||||
|
||||
설정 코드가 유효한 동안에는 비밀번호처럼 취급하세요.
|
||||
|
||||
### 노드 장치 승인
|
||||
|
||||
```bash
|
||||
openclaw devices list
|
||||
openclaw devices approve <requestId>
|
||||
openclaw devices reject <requestId>
|
||||
```
|
||||
|
||||
동일한 장치가 다른 인증 세부 정보(예: 다른 역할/범위/공개 키)로 다시 시도하면, 이전 대기 요청은 대체되고 새 `requestId`가 생성됩니다.
|
||||
|
||||
### 노드 페어링 상태 저장소
|
||||
|
||||
`~/.openclaw/devices/` 아래에 저장됩니다.
|
||||
|
||||
- `pending.json`(단기 보관; 대기 요청은 만료됨)
|
||||
- `paired.json`(페어링된 장치 + 토큰)
|
||||
|
||||
### 참고
|
||||
|
||||
- 레거시 `node.pair.*` API(CLI: `openclaw nodes pending|approve|reject|rename`)는
|
||||
게이트웨이가 소유하는 별도의 페어링 저장소입니다. WS 노드는 여전히 장치 페어링이 필요합니다.
|
||||
- 페어링 기록은 승인된 역할에 대한 내구성 있는 source of truth입니다. 활성
|
||||
장치 토큰은 해당 승인된 역할 집합으로 계속 제한되며, 승인된 역할 밖에 있는
|
||||
우발적인 토큰 항목이 새 접근 권한을 만들지는 않습니다.
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- 보안 모델 + 프롬프트 인젝션: [Security](/gateway/security)
|
||||
- 안전한 업데이트(doctor 실행): [Updating](/install/updating)
|
||||
- 채널 구성:
|
||||
- Telegram: [Telegram](/channels/telegram)
|
||||
- WhatsApp: [WhatsApp](/channels/whatsapp)
|
||||
- Signal: [Signal](/channels/signal)
|
||||
- BlueBubbles(iMessage): [BlueBubbles](/channels/bluebubbles)
|
||||
- iMessage(레거시): [iMessage](/channels/imessage)
|
||||
- Discord: [Discord](/channels/discord)
|
||||
- Slack: [Slack](/channels/slack)
|
||||
187
docs/ko/channels/qqbot.md
Normal file
187
docs/ko/channels/qqbot.md
Normal file
@ -0,0 +1,187 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw를 QQ에 연결하려는 경우
|
||||
- QQ Bot 자격 증명 설정이 필요한 경우
|
||||
- QQ Bot 그룹 또는 개인 채팅 지원을 사용하려는 경우
|
||||
summary: QQ Bot 설정, 구성 및 사용법
|
||||
title: QQ Bot
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:36:00Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 0e58fb7b07c59ecbf80a1276368c4a007b45d84e296ed40cffe9845e0953696c
|
||||
source_path: channels/qqbot.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# QQ Bot
|
||||
|
||||
QQ Bot은 공식 QQ Bot API(WebSocket gateway)를 통해 OpenClaw에 연결됩니다. 이 plugin은 풍부한 미디어(이미지, 음성, 비디오, 파일)와 함께 C2C 개인 채팅, 그룹 @메시지, 길드 채널 메시지를 지원합니다.
|
||||
|
||||
상태: 번들 plugin. 다이렉트 메시지, 그룹 채팅, 길드 채널 및 미디어가 지원됩니다. 반응과 스레드는 지원되지 않습니다.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
현재 OpenClaw 릴리스에는 QQ Bot이 번들로 포함되어 있으므로 일반 패키지형 빌드에서는 별도의 `openclaw plugins install` 단계가 필요하지 않습니다.
|
||||
|
||||
## 설정
|
||||
|
||||
1. [QQ Open Platform](https://q.qq.com/)으로 이동해 휴대폰 QQ로 QR 코드를 스캔하여 등록/로그인합니다.
|
||||
2. **Create Bot**을 클릭해 새 QQ 봇을 만듭니다.
|
||||
3. 봇 설정 페이지에서 **AppID**와 **AppSecret**을 찾아 복사합니다.
|
||||
|
||||
> AppSecret은 평문으로 저장되지 않으므로 저장하지 않고 페이지를 나가면 새로 다시 생성해야 합니다.
|
||||
|
||||
4. 채널을 추가합니다.
|
||||
|
||||
```bash
|
||||
openclaw channels add --channel qqbot --token "AppID:AppSecret"
|
||||
```
|
||||
|
||||
5. Gateway를 재시작합니다.
|
||||
|
||||
대화형 설정 경로:
|
||||
|
||||
```bash
|
||||
openclaw channels add
|
||||
openclaw configure --section channels
|
||||
```
|
||||
|
||||
## 구성
|
||||
|
||||
최소 config:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
qqbot: {
|
||||
enabled: true,
|
||||
appId: "YOUR_APP_ID",
|
||||
clientSecret: "YOUR_APP_SECRET",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
기본 계정 환경 변수:
|
||||
|
||||
- `QQBOT_APP_ID`
|
||||
- `QQBOT_CLIENT_SECRET`
|
||||
|
||||
파일 기반 AppSecret:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
qqbot: {
|
||||
enabled: true,
|
||||
appId: "YOUR_APP_ID",
|
||||
clientSecretFile: "/path/to/qqbot-secret.txt",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 환경 변수 대체는 기본 QQ Bot 계정에만 적용됩니다.
|
||||
- `openclaw channels add --channel qqbot --token-file ...`는 AppSecret만 제공합니다. AppID는 이미 config 또는 `QQBOT_APP_ID`에 설정되어 있어야 합니다.
|
||||
- `clientSecret`은 평문 문자열뿐 아니라 SecretRef 입력도 허용합니다.
|
||||
|
||||
### 다중 계정 설정
|
||||
|
||||
하나의 OpenClaw 인스턴스에서 여러 QQ 봇을 실행합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
qqbot: {
|
||||
enabled: true,
|
||||
appId: "111111111",
|
||||
clientSecret: "secret-of-bot-1",
|
||||
accounts: {
|
||||
bot2: {
|
||||
enabled: true,
|
||||
appId: "222222222",
|
||||
clientSecret: "secret-of-bot-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
각 계정은 자체 WebSocket 연결을 시작하며 독립적인 토큰 캐시를 유지합니다(`appId`별로 격리됨).
|
||||
|
||||
CLI로 두 번째 봇 추가:
|
||||
|
||||
```bash
|
||||
openclaw channels add --channel qqbot --account bot2 --token "222222222:secret-of-bot-2"
|
||||
```
|
||||
|
||||
### 음성(STT / TTS)
|
||||
|
||||
STT와 TTS는 우선순위 대체를 포함한 2단계 구성을 지원합니다.
|
||||
|
||||
| 설정 | plugin별 | 프레임워크 대체 |
|
||||
| ------- | -------------------- | ----------------------------- |
|
||||
| STT | `channels.qqbot.stt` | `tools.media.audio.models[0]` |
|
||||
| TTS | `channels.qqbot.tts` | `messages.tts` |
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
qqbot: {
|
||||
stt: {
|
||||
provider: "your-provider",
|
||||
model: "your-stt-model",
|
||||
},
|
||||
tts: {
|
||||
provider: "your-provider",
|
||||
model: "your-tts-model",
|
||||
voice: "your-voice",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
비활성화하려면 둘 중 하나에 `enabled: false`를 설정하세요.
|
||||
|
||||
아웃바운드 오디오 업로드/트랜스코드 동작은 `channels.qqbot.audioFormatPolicy`로도 조정할 수 있습니다.
|
||||
|
||||
- `sttDirectFormats`
|
||||
- `uploadDirectFormats`
|
||||
- `transcodeEnabled`
|
||||
|
||||
## 대상 형식
|
||||
|
||||
| 형식 | 설명 |
|
||||
| -------------------------- | ------------------ |
|
||||
| `qqbot:c2c:OPENID` | 개인 채팅(C2C) |
|
||||
| `qqbot:group:GROUP_OPENID` | 그룹 채팅 |
|
||||
| `qqbot:channel:CHANNEL_ID` | 길드 채널 |
|
||||
|
||||
> 각 봇은 자체 사용자 OpenID 집합을 가집니다. Bot A가 받은 OpenID는 Bot B를 통해 메시지를 보내는 데 **사용할 수 없습니다**.
|
||||
|
||||
## 슬래시 명령
|
||||
|
||||
AI 큐보다 먼저 가로채는 내장 명령:
|
||||
|
||||
| 명령 | 설명 |
|
||||
| -------------- | ------------------------------------ |
|
||||
| `/bot-ping` | 지연 시간 테스트 |
|
||||
| `/bot-version` | OpenClaw 프레임워크 버전 표시 |
|
||||
| `/bot-help` | 모든 명령 나열 |
|
||||
| `/bot-upgrade` | QQBot 업그레이드 가이드 링크 표시 |
|
||||
| `/bot-logs` | 최근 gateway 로그를 파일로 내보내기 |
|
||||
|
||||
사용법 도움말을 보려면 아무 명령에나 `?`를 추가하세요(예: `/bot-upgrade ?`).
|
||||
|
||||
## 문제 해결
|
||||
|
||||
- **봇이 "gone to Mars"라고 응답함:** 자격 증명이 구성되지 않았거나 Gateway가 시작되지 않았습니다.
|
||||
- **인바운드 메시지가 없음:** `appId`와 `clientSecret`이 올바른지, 그리고 봇이 QQ Open Platform에서 활성화되어 있는지 확인하세요.
|
||||
- **`--token-file`로 설정했는데도 여전히 미구성으로 표시됨:** `--token-file`은 AppSecret만 설정합니다. 여전히 config 또는 `QQBOT_APP_ID`에 `appId`가 필요합니다.
|
||||
- **사전 발송 메시지가 도착하지 않음:** 사용자가 최근 상호작용하지 않았다면 QQ가 봇이 시작한 메시지를 차단할 수 있습니다.
|
||||
- **음성이 전사되지 않음:** STT가 구성되어 있고 공급자에 연결할 수 있는지 확인하세요.
|
||||
344
docs/ko/channels/signal.md
Normal file
344
docs/ko/channels/signal.md
Normal file
@ -0,0 +1,344 @@
|
||||
---
|
||||
read_when:
|
||||
- Signal 지원을 설정할 때
|
||||
- Signal 송수신 문제를 디버깅할 때
|
||||
summary: signal-cli(JSON-RPC + SSE)를 통한 Signal 지원, 설정 경로 및 번호 모델
|
||||
title: Signal
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:36:24Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: cdd855eb353aca6a1c2b04d14af0e3da079349297b54fa8243562c52b29118d9
|
||||
source_path: channels/signal.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Signal (signal-cli)
|
||||
|
||||
상태: 외부 CLI 통합. Gateway는 HTTP JSON-RPC + SSE를 통해 `signal-cli`와 통신합니다.
|
||||
|
||||
## 사전 요구 사항
|
||||
|
||||
- 서버에 OpenClaw가 설치되어 있어야 합니다(아래 Linux 흐름은 Ubuntu 24에서 테스트됨).
|
||||
- gateway가 실행되는 호스트에서 `signal-cli`를 사용할 수 있어야 합니다.
|
||||
- 한 번의 인증 SMS를 수신할 수 있는 전화번호가 필요합니다(SMS 등록 경로용).
|
||||
- 등록 중 Signal captcha(`signalcaptchas.org`)에 접근할 수 있는 브라우저가 필요합니다.
|
||||
|
||||
## 빠른 설정(초보자용)
|
||||
|
||||
1. 봇에 **별도의 Signal 번호**를 사용합니다(권장).
|
||||
2. `signal-cli`를 설치합니다(JVM 빌드를 사용하는 경우 Java 필요).
|
||||
3. 다음 설정 경로 중 하나를 선택합니다.
|
||||
- **경로 A (QR 연결):** `signal-cli link -n "OpenClaw"`를 실행하고 Signal로 스캔합니다.
|
||||
- **경로 B (SMS 등록):** captcha + SMS 인증으로 전용 번호를 등록합니다.
|
||||
4. OpenClaw를 구성하고 gateway를 재시작합니다.
|
||||
5. 첫 번째 DM을 보내고 페어링을 승인합니다(`openclaw pairing approve signal <CODE>`).
|
||||
|
||||
최소 구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
signal: {
|
||||
enabled: true,
|
||||
account: "+15551234567",
|
||||
cliPath: "signal-cli",
|
||||
dmPolicy: "pairing",
|
||||
allowFrom: ["+15557654321"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
필드 참조:
|
||||
|
||||
| 필드 | 설명 |
|
||||
| ----------- | ------------------------------------------------- |
|
||||
| `account` | E.164 형식의 봇 전화번호 (`+15551234567`) |
|
||||
| `cliPath` | `signal-cli` 경로(`PATH`에 있으면 `signal-cli`) |
|
||||
| `dmPolicy` | DM 액세스 정책(`pairing` 권장) |
|
||||
| `allowFrom` | DM을 허용할 전화번호 또는 `uuid:<id>` 값 |
|
||||
|
||||
## 개요
|
||||
|
||||
- Signal 채널은 `signal-cli`를 통해 동작합니다(내장 libsignal 아님).
|
||||
- 결정적 라우팅: 응답은 항상 Signal로 다시 전송됩니다.
|
||||
- DM은 에이전트의 메인 세션을 공유하고, 그룹은 격리됩니다(`agent:<agentId>:signal:group:<groupId>`).
|
||||
|
||||
## Config 쓰기
|
||||
|
||||
기본적으로 Signal은 `/config set|unset`에 의해 트리거되는 config 업데이트 쓰기가 허용됩니다(`commands.config: true` 필요).
|
||||
|
||||
다음으로 비활성화할 수 있습니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: { signal: { configWrites: false } },
|
||||
}
|
||||
```
|
||||
|
||||
## 번호 모델(중요)
|
||||
|
||||
- gateway는 **Signal 디바이스**(`signal-cli` 계정)에 연결됩니다.
|
||||
- 봇을 **개인 Signal 계정**에서 실행하면, 자신의 메시지는 무시합니다(루프 방지).
|
||||
- “내가 봇에 문자를 보내면 답장받는” 구성을 원하면 **별도의 봇 번호**를 사용하세요.
|
||||
|
||||
## 설정 경로 A: 기존 Signal 계정 연결(QR)
|
||||
|
||||
1. `signal-cli`를 설치합니다(JVM 또는 네이티브 빌드).
|
||||
2. 봇 계정을 연결합니다.
|
||||
- `signal-cli link -n "OpenClaw"`를 실행한 다음 Signal에서 QR을 스캔합니다.
|
||||
3. Signal을 구성하고 gateway를 시작합니다.
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
signal: {
|
||||
enabled: true,
|
||||
account: "+15551234567",
|
||||
cliPath: "signal-cli",
|
||||
dmPolicy: "pairing",
|
||||
allowFrom: ["+15557654321"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
다중 계정 지원: 계정별 config와 선택적 `name`을 포함하는 `channels.signal.accounts`를 사용하세요. 공통 패턴은 [`gateway/configuration`](/gateway/configuration-reference#multi-account-all-channels)을 참조하세요.
|
||||
|
||||
## 설정 경로 B: 전용 봇 번호 등록(SMS, Linux)
|
||||
|
||||
기존 Signal 앱 계정을 연결하는 대신 전용 봇 번호를 원할 때 사용합니다.
|
||||
|
||||
1. SMS를 받을 수 있는 번호(또는 유선전화의 경우 음성 인증)를 준비합니다.
|
||||
- 계정/세션 충돌을 피하려면 전용 봇 번호를 사용하세요.
|
||||
2. gateway 호스트에 `signal-cli`를 설치합니다.
|
||||
|
||||
```bash
|
||||
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/AsamK/signal-cli/releases/latest | sed -e 's/^.*\/v//')
|
||||
curl -L -O "https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}-Linux-native.tar.gz"
|
||||
sudo tar xf "signal-cli-${VERSION}-Linux-native.tar.gz" -C /opt
|
||||
sudo ln -sf /opt/signal-cli /usr/local/bin/
|
||||
signal-cli --version
|
||||
```
|
||||
|
||||
JVM 빌드(`signal-cli-${VERSION}.tar.gz`)를 사용하는 경우 먼저 JRE 25+를 설치하세요.
|
||||
`signal-cli`는 최신 상태로 유지하세요. upstream에 따르면 Signal 서버 API가 변경되면 오래된 릴리스가 동작하지 않을 수 있습니다.
|
||||
|
||||
3. 번호를 등록하고 인증합니다.
|
||||
|
||||
```bash
|
||||
signal-cli -a +<BOT_PHONE_NUMBER> register
|
||||
```
|
||||
|
||||
captcha가 필요한 경우:
|
||||
|
||||
1. `https://signalcaptchas.org/registration/generate.html`를 엽니다.
|
||||
2. captcha를 완료하고 “Open Signal”의 `signalcaptcha://...` 링크 대상 값을 복사합니다.
|
||||
3. 가능하면 브라우저 세션과 동일한 외부 IP에서 실행합니다.
|
||||
4. 즉시 다시 등록을 실행합니다(captcha 토큰은 빠르게 만료됨).
|
||||
|
||||
```bash
|
||||
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'
|
||||
signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>
|
||||
```
|
||||
|
||||
4. OpenClaw를 구성하고 gateway를 재시작한 뒤 채널을 확인합니다.
|
||||
|
||||
```bash
|
||||
# gateway를 사용자 systemd 서비스로 실행하는 경우:
|
||||
systemctl --user restart openclaw-gateway.service
|
||||
|
||||
# 그런 다음 확인:
|
||||
openclaw doctor
|
||||
openclaw channels status --probe
|
||||
```
|
||||
|
||||
5. DM 발신자를 페어링합니다.
|
||||
- 봇 번호로 아무 메시지나 보냅니다.
|
||||
- 서버에서 코드를 승인합니다: `openclaw pairing approve signal <PAIRING_CODE>`.
|
||||
- “알 수 없는 연락처”를 피하려면 휴대폰에 봇 번호를 연락처로 저장하세요.
|
||||
|
||||
중요: `signal-cli`로 전화번호 계정을 등록하면 해당 번호의 기본 Signal 앱 세션이 인증 해제될 수 있습니다. 기존 휴대폰 앱 구성을 유지해야 한다면 전용 봇 번호를 사용하거나 QR 연결 모드를 선호하세요.
|
||||
|
||||
upstream 참고 자료:
|
||||
|
||||
- `signal-cli` README: `https://github.com/AsamK/signal-cli`
|
||||
- Captcha 흐름: `https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha`
|
||||
- 연결 흐름: `https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)`
|
||||
|
||||
## 외부 데몬 모드 (`httpUrl`)
|
||||
|
||||
`signal-cli`를 직접 관리하려는 경우(느린 JVM 콜드 스타트, 컨테이너 초기화 또는 공유 CPU) 데몬을 별도로 실행하고 OpenClaw가 이를 가리키도록 설정하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
signal: {
|
||||
httpUrl: "http://127.0.0.1:8080",
|
||||
autoStart: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
이렇게 하면 OpenClaw 내부의 자동 실행과 시작 대기를 건너뜁니다. 자동 실행 시 시작이 느린 경우 `channels.signal.startupTimeoutMs`를 설정하세요.
|
||||
|
||||
## 액세스 제어(DM + 그룹)
|
||||
|
||||
DM:
|
||||
|
||||
- 기본값: `channels.signal.dmPolicy = "pairing"`.
|
||||
- 알 수 없는 발신자는 페어링 코드를 받으며, 승인될 때까지 메시지는 무시됩니다(코드는 1시간 후 만료).
|
||||
- 승인 방법:
|
||||
- `openclaw pairing list signal`
|
||||
- `openclaw pairing approve signal <CODE>`
|
||||
- 페어링은 Signal DM의 기본 토큰 교환 방식입니다. 자세한 내용: [페어링](/channels/pairing)
|
||||
- UUID 전용 발신자(`sourceUuid`에서 옴)는 `channels.signal.allowFrom`에 `uuid:<id>`로 저장됩니다.
|
||||
|
||||
그룹:
|
||||
|
||||
- `channels.signal.groupPolicy = open | allowlist | disabled`.
|
||||
- `channels.signal.groupAllowFrom`는 `allowlist`가 설정된 경우 그룹에서 누가 트리거할 수 있는지 제어합니다.
|
||||
- `channels.signal.groups["<group-id>" | "*"]`는 `requireMention`, `tools`, `toolsBySender`로 그룹 동작을 재정의할 수 있습니다.
|
||||
- 다중 계정 구성에서는 계정별 재정의를 위해 `channels.signal.accounts.<id>.groups`를 사용하세요.
|
||||
- 런타임 참고: `channels.signal`이 완전히 누락된 경우 런타임은 그룹 확인에 대해 `groupPolicy="allowlist"`로 폴백합니다(`channels.defaults.groupPolicy`가 설정되어 있더라도).
|
||||
|
||||
## 동작 방식
|
||||
|
||||
- `signal-cli`는 데몬으로 실행되며 gateway는 SSE를 통해 이벤트를 읽습니다.
|
||||
- 인바운드 메시지는 공유 채널 envelope로 정규화됩니다.
|
||||
- 응답은 항상 동일한 번호 또는 그룹으로 다시 라우팅됩니다.
|
||||
|
||||
## 미디어 및 제한
|
||||
|
||||
- 아웃바운드 텍스트는 `channels.signal.textChunkLimit`(기본값 4000) 기준으로 청킹됩니다.
|
||||
- 선택적 줄바꿈 청킹: 길이 기준 청킹 전에 빈 줄(문단 경계)에서 분할하려면 `channels.signal.chunkMode="newline"`를 설정하세요.
|
||||
- 첨부 파일이 지원됩니다(`signal-cli`에서 가져온 base64 사용).
|
||||
- 기본 미디어 제한: `channels.signal.mediaMaxMb`(기본값 8).
|
||||
- 미디어 다운로드를 건너뛰려면 `channels.signal.ignoreAttachments`를 사용하세요.
|
||||
- 그룹 기록 컨텍스트는 `channels.signal.historyLimit`(또는 `channels.signal.accounts.*.historyLimit`)를 사용하며, 없으면 `messages.groupChat.historyLimit`로 폴백합니다. 비활성화하려면 `0`으로 설정하세요(기본값 50).
|
||||
|
||||
## 입력 중 표시 및 읽음 확인
|
||||
|
||||
- **입력 중 표시**: OpenClaw는 `signal-cli sendTyping`을 통해 입력 중 신호를 보내며 응답이 실행되는 동안 이를 갱신합니다.
|
||||
- **읽음 확인**: `channels.signal.sendReadReceipts`가 true이면 OpenClaw는 허용된 DM에 대한 읽음 확인을 전달합니다.
|
||||
- signal-cli는 그룹에 대한 읽음 확인을 노출하지 않습니다.
|
||||
|
||||
## 반응(메시지 도구)
|
||||
|
||||
- `channel=signal`과 함께 `message action=react`를 사용하세요.
|
||||
- 대상: 발신자의 E.164 또는 UUID(페어링 출력의 `uuid:<id>` 사용, bare UUID도 가능).
|
||||
- `messageId`는 반응할 메시지의 Signal 타임스탬프입니다.
|
||||
- 그룹 반응에는 `targetAuthor` 또는 `targetAuthorUuid`가 필요합니다.
|
||||
|
||||
예시:
|
||||
|
||||
```
|
||||
message action=react channel=signal target=uuid:123e4567-e89b-12d3-a456-426614174000 messageId=1737630212345 emoji=🔥
|
||||
message action=react channel=signal target=+15551234567 messageId=1737630212345 emoji=🔥 remove=true
|
||||
message action=react channel=signal target=signal:group:<groupId> targetAuthor=uuid:<sender-uuid> messageId=1737630212345 emoji=✅
|
||||
```
|
||||
|
||||
Config:
|
||||
|
||||
- `channels.signal.actions.reactions`: 반응 작업 활성화/비활성화(기본값 true)
|
||||
- `channels.signal.reactionLevel`: `off | ack | minimal | extensive`.
|
||||
- `off`/`ack`는 에이전트 반응을 비활성화합니다(메시지 도구 `react`는 오류 발생).
|
||||
- `minimal`/`extensive`는 에이전트 반응을 활성화하고 안내 수준을 설정합니다.
|
||||
- 계정별 재정의: `channels.signal.accounts.<id>.actions.reactions`, `channels.signal.accounts.<id>.reactionLevel`.
|
||||
|
||||
## 전달 대상(CLI/cron)
|
||||
|
||||
- DM: `signal:+15551234567`(또는 일반 E.164)
|
||||
- UUID DM: `uuid:<id>`(또는 bare UUID)
|
||||
- 그룹: `signal:group:<groupId>`.
|
||||
- 사용자 이름: `username:<name>`(Signal 계정에서 지원되는 경우)
|
||||
|
||||
## 문제 해결
|
||||
|
||||
먼저 다음 순서로 실행하세요.
|
||||
|
||||
```bash
|
||||
openclaw status
|
||||
openclaw gateway status
|
||||
openclaw logs --follow
|
||||
openclaw doctor
|
||||
openclaw channels status --probe
|
||||
```
|
||||
|
||||
그런 다음 필요하면 DM 페어링 상태를 확인합니다.
|
||||
|
||||
```bash
|
||||
openclaw pairing list signal
|
||||
```
|
||||
|
||||
일반적인 실패 사례:
|
||||
|
||||
- 데몬에 연결되지만 응답이 없음: 계정/데몬 설정(`httpUrl`, `account`)과 수신 모드를 확인하세요.
|
||||
- DM이 무시됨: 발신자가 페어링 승인 대기 상태입니다.
|
||||
- 그룹 메시지가 무시됨: 그룹 발신자/멘션 게이팅이 전달을 차단합니다.
|
||||
- 편집 후 config 검증 오류: `openclaw doctor --fix`를 실행하세요.
|
||||
- 진단에서 Signal이 보이지 않음: `channels.signal.enabled: true`인지 확인하세요.
|
||||
|
||||
추가 확인:
|
||||
|
||||
```bash
|
||||
openclaw pairing list signal
|
||||
pgrep -af signal-cli
|
||||
grep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20
|
||||
```
|
||||
|
||||
분류 흐름은 [/channels/troubleshooting](/channels/troubleshooting)을 참조하세요.
|
||||
|
||||
## 보안 참고
|
||||
|
||||
- `signal-cli`는 계정 키를 로컬에 저장합니다(일반적으로 `~/.local/share/signal-cli/data/`).
|
||||
- 서버 마이그레이션 또는 재구축 전에 Signal 계정 상태를 백업하세요.
|
||||
- 더 넓은 DM 액세스를 명시적으로 원하지 않는 한 `channels.signal.dmPolicy: "pairing"`을 유지하세요.
|
||||
- SMS 인증은 등록 또는 복구 흐름에만 필요하지만, 번호/계정 제어를 잃으면 재등록이 복잡해질 수 있습니다.
|
||||
|
||||
## 구성 참조(Signal)
|
||||
|
||||
전체 구성: [구성](/gateway/configuration)
|
||||
|
||||
Provider 옵션:
|
||||
|
||||
- `channels.signal.enabled`: 채널 시작 활성화/비활성화
|
||||
- `channels.signal.account`: 봇 계정의 E.164
|
||||
- `channels.signal.cliPath`: `signal-cli` 경로
|
||||
- `channels.signal.httpUrl`: 전체 데몬 URL(host/port보다 우선)
|
||||
- `channels.signal.httpHost`, `channels.signal.httpPort`: 데몬 바인드(기본값 127.0.0.1:8080)
|
||||
- `channels.signal.autoStart`: 데몬 자동 실행(`httpUrl`이 설정되지 않은 경우 기본값 true)
|
||||
- `channels.signal.startupTimeoutMs`: 시작 대기 제한 시간(ms, 최대 120000)
|
||||
- `channels.signal.receiveMode`: `on-start | manual`
|
||||
- `channels.signal.ignoreAttachments`: 첨부 파일 다운로드 건너뛰기
|
||||
- `channels.signal.ignoreStories`: 데몬의 스토리 무시
|
||||
- `channels.signal.sendReadReceipts`: 읽음 확인 전달
|
||||
- `channels.signal.dmPolicy`: `pairing | allowlist | open | disabled`(기본값: pairing)
|
||||
- `channels.signal.allowFrom`: DM 허용 목록(E.164 또는 `uuid:<id>`). `open`에는 `"*"`가 필요합니다. Signal에는 사용자 이름이 없으므로 전화번호/UUID ID를 사용하세요.
|
||||
- `channels.signal.groupPolicy`: `open | allowlist | disabled`(기본값: allowlist)
|
||||
- `channels.signal.groupAllowFrom`: 그룹 발신자 허용 목록
|
||||
- `channels.signal.groups`: Signal 그룹 ID(또는 `"*"`)를 키로 하는 그룹별 재정의. 지원 필드: `requireMention`, `tools`, `toolsBySender`
|
||||
- `channels.signal.accounts.<id>.groups`: 다중 계정 구성용 `channels.signal.groups`의 계정별 버전
|
||||
- `channels.signal.historyLimit`: 컨텍스트로 포함할 최대 그룹 메시지 수(0이면 비활성화)
|
||||
- `channels.signal.dmHistoryLimit`: 사용자 턴 기준 DM 기록 제한. 사용자별 재정의: `channels.signal.dms["<phone_or_uuid>"].historyLimit`
|
||||
- `channels.signal.textChunkLimit`: 아웃바운드 청크 크기(문자 수)
|
||||
- `channels.signal.chunkMode`: 길이 청킹 전에 빈 줄(문단 경계) 기준으로 분할하는 `length`(기본값) 또는 `newline`
|
||||
- `channels.signal.mediaMaxMb`: 인바운드/아웃바운드 미디어 제한(MB)
|
||||
|
||||
관련 전역 옵션:
|
||||
|
||||
- `agents.list[].groupChat.mentionPatterns` (Signal은 네이티브 멘션을 지원하지 않음)
|
||||
- `messages.groupChat.mentionPatterns` (전역 폴백)
|
||||
- `messages.responsePrefix`.
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 강화
|
||||
675
docs/ko/channels/slack.md
Normal file
675
docs/ko/channels/slack.md
Normal file
@ -0,0 +1,675 @@
|
||||
---
|
||||
read_when:
|
||||
- Slack을 설정하거나 Slack 소켓/HTTP 모드를 디버깅할 때
|
||||
summary: Slack 설정 및 런타임 동작(Socket Mode + HTTP Events API)
|
||||
title: Slack
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:36:55Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: efb37e1f04e1ac8ac3786c36ffc20013dacdc654bfa61e7f6e8df89c4902d2ab
|
||||
source_path: channels/slack.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Slack
|
||||
|
||||
상태: Slack 앱 통합을 통한 DM 및 채널용 프로덕션 준비 완료. 기본 모드는 Socket Mode이며, HTTP Events API 모드도 지원됩니다.
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="페어링" icon="link" href="/channels/pairing">
|
||||
Slack DM은 기본적으로 페어링 모드를 사용합니다.
|
||||
</Card>
|
||||
<Card title="슬래시 명령" icon="terminal" href="/tools/slash-commands">
|
||||
네이티브 명령 동작 및 명령 카탈로그.
|
||||
</Card>
|
||||
<Card title="채널 문제 해결" icon="wrench" href="/channels/troubleshooting">
|
||||
채널 전반의 진단 및 복구 플레이북.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## 빠른 설정
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Socket Mode (기본값)">
|
||||
<Steps>
|
||||
<Step title="Slack 앱 및 토큰 생성">
|
||||
Slack 앱 설정에서 다음을 수행합니다.
|
||||
|
||||
- **Socket Mode** 활성화
|
||||
- `connections:write` 권한이 있는 **App Token**(`xapp-...`) 생성
|
||||
- 앱을 설치하고 **Bot Token**(`xoxb-...`) 복사
|
||||
</Step>
|
||||
|
||||
<Step title="OpenClaw 구성">
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
slack: {
|
||||
enabled: true,
|
||||
mode: "socket",
|
||||
appToken: "xapp-...",
|
||||
botToken: "xoxb-...",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
환경 변수 대체(default 계정만 해당):
|
||||
|
||||
```bash
|
||||
SLACK_APP_TOKEN=xapp-...
|
||||
SLACK_BOT_TOKEN=xoxb-...
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="앱 이벤트 구독">
|
||||
다음에 대한 봇 이벤트를 구독합니다.
|
||||
|
||||
- `app_mention`
|
||||
- `message.channels`, `message.groups`, `message.im`, `message.mpim`
|
||||
- `reaction_added`, `reaction_removed`
|
||||
- `member_joined_channel`, `member_left_channel`
|
||||
- `channel_rename`
|
||||
- `pin_added`, `pin_removed`
|
||||
|
||||
DM용으로 App Home **Messages Tab**도 활성화합니다.
|
||||
</Step>
|
||||
|
||||
<Step title="게이트웨이 시작">
|
||||
|
||||
```bash
|
||||
openclaw gateway
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="HTTP Events API 모드">
|
||||
<Steps>
|
||||
<Step title="HTTP용 Slack 앱 구성">
|
||||
|
||||
- 모드를 HTTP로 설정(`channels.slack.mode="http"`)
|
||||
- Slack **Signing Secret** 복사
|
||||
- Event Subscriptions + Interactivity + Slash command Request URL을 모두 동일한 webhook 경로(기본값 `/slack/events`)로 설정
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="OpenClaw HTTP 모드 구성">
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
slack: {
|
||||
enabled: true,
|
||||
mode: "http",
|
||||
botToken: "xoxb-...",
|
||||
signingSecret: "your-signing-secret",
|
||||
webhookPath: "/slack/events",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="멀티 계정 HTTP에 고유 webhook 경로 사용">
|
||||
계정별 HTTP 모드가 지원됩니다.
|
||||
|
||||
등록이 충돌하지 않도록 각 계정에 서로 다른 `webhookPath`를 지정하세요.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 매니페스트 및 범위 체크리스트
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Slack 앱 매니페스트 예시" defaultOpen>
|
||||
|
||||
```json
|
||||
{
|
||||
"display_information": {
|
||||
"name": "OpenClaw",
|
||||
"description": "Slack connector for OpenClaw"
|
||||
},
|
||||
"features": {
|
||||
"bot_user": {
|
||||
"display_name": "OpenClaw",
|
||||
"always_online": true
|
||||
},
|
||||
"app_home": {
|
||||
"messages_tab_enabled": true,
|
||||
"messages_tab_read_only_enabled": false
|
||||
},
|
||||
"slash_commands": [
|
||||
{
|
||||
"command": "/openclaw",
|
||||
"description": "Send a message to OpenClaw",
|
||||
"should_escape": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"oauth_config": {
|
||||
"scopes": {
|
||||
"bot": [
|
||||
"app_mentions:read",
|
||||
"assistant:write",
|
||||
"channels:history",
|
||||
"channels:read",
|
||||
"chat:write",
|
||||
"commands",
|
||||
"emoji:read",
|
||||
"files:read",
|
||||
"files:write",
|
||||
"groups:history",
|
||||
"groups:read",
|
||||
"im:history",
|
||||
"im:read",
|
||||
"im:write",
|
||||
"mpim:history",
|
||||
"mpim:read",
|
||||
"mpim:write",
|
||||
"pins:read",
|
||||
"pins:write",
|
||||
"reactions:read",
|
||||
"reactions:write",
|
||||
"users:read"
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"socket_mode_enabled": true,
|
||||
"event_subscriptions": {
|
||||
"bot_events": [
|
||||
"app_mention",
|
||||
"channel_rename",
|
||||
"member_joined_channel",
|
||||
"member_left_channel",
|
||||
"message.channels",
|
||||
"message.groups",
|
||||
"message.im",
|
||||
"message.mpim",
|
||||
"pin_added",
|
||||
"pin_removed",
|
||||
"reaction_added",
|
||||
"reaction_removed"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="선택적 사용자 토큰 범위(읽기 작업)">
|
||||
`channels.slack.userToken`을 구성한 경우, 일반적인 읽기 범위는 다음과 같습니다.
|
||||
|
||||
- `channels:history`, `groups:history`, `im:history`, `mpim:history`
|
||||
- `channels:read`, `groups:read`, `im:read`, `mpim:read`
|
||||
- `users:read`
|
||||
- `reactions:read`
|
||||
- `pins:read`
|
||||
- `emoji:read`
|
||||
- `search:read`(Slack 검색 읽기에 의존하는 경우)
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 토큰 모델
|
||||
|
||||
- Socket Mode에는 `botToken` + `appToken`이 필요합니다.
|
||||
- HTTP 모드에는 `botToken` + `signingSecret`이 필요합니다.
|
||||
- `botToken`, `appToken`, `signingSecret`, `userToken`은 일반 문자열 또는 SecretRef 객체를 받을 수 있습니다.
|
||||
- 구성의 토큰이 환경 변수 대체보다 우선합니다.
|
||||
- `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` 환경 변수 대체는 default 계정에만 적용됩니다.
|
||||
- `userToken`(`xoxp-...`)은 구성 전용이며(환경 변수 대체 없음), 기본값은 읽기 전용 동작(`userTokenReadOnly: true`)입니다.
|
||||
- 선택 사항: 발신 메시지가 활성 에이전트 신원(사용자 지정 `username` 및 아이콘)을 사용하게 하려면 `chat:write.customize`를 추가하세요. `icon_emoji`는 `:emoji_name:` 문법을 사용합니다.
|
||||
|
||||
상태 스냅샷 동작:
|
||||
|
||||
- Slack 계정 검사는 자격 증명별 `*Source` 및 `*Status` 필드(`botToken`, `appToken`, `signingSecret`, `userToken`)를 추적합니다.
|
||||
- 상태는 `available`, `configured_unavailable`, `missing`입니다.
|
||||
- `configured_unavailable`은 계정이 SecretRef 또는 다른 비인라인 비밀 소스를 통해 구성되었지만, 현재 명령/런타임 경로에서 실제 값을 해석할 수 없었음을 의미합니다.
|
||||
- HTTP 모드에서는 `signingSecretStatus`가 포함되며, Socket Mode에서는 필요한 쌍이 `botTokenStatus` + `appTokenStatus`입니다.
|
||||
|
||||
<Tip>
|
||||
작업/디렉터리 읽기에서는 구성된 경우 사용자 토큰을 우선할 수 있습니다. 쓰기에서는 여전히 봇 토큰이 우선이며, 사용자 토큰 쓰기는 `userTokenReadOnly: false`이고 봇 토큰을 사용할 수 없을 때만 허용됩니다.
|
||||
</Tip>
|
||||
|
||||
## 작업 및 게이트
|
||||
|
||||
Slack 작업은 `channels.slack.actions.*`로 제어됩니다.
|
||||
|
||||
현재 Slack 도구에서 사용할 수 있는 작업 그룹:
|
||||
|
||||
| 그룹 | 기본값 |
|
||||
| ---------- | ------- |
|
||||
| messages | enabled |
|
||||
| reactions | enabled |
|
||||
| pins | enabled |
|
||||
| memberInfo | enabled |
|
||||
| emojiList | enabled |
|
||||
|
||||
현재 Slack 메시지 작업에는 `send`, `upload-file`, `download-file`, `read`, `edit`, `delete`, `pin`, `unpin`, `list-pins`, `member-info`, `emoji-list`가 포함됩니다.
|
||||
|
||||
## 접근 제어 및 라우팅
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM 정책">
|
||||
`channels.slack.dmPolicy`가 DM 접근을 제어합니다(레거시: `channels.slack.dm.policy`).
|
||||
|
||||
- `pairing`(기본값)
|
||||
- `allowlist`
|
||||
- `open`(`channels.slack.allowFrom`에 `"*"`가 포함되어야 함; 레거시: `channels.slack.dm.allowFrom`)
|
||||
- `disabled`
|
||||
|
||||
DM 플래그:
|
||||
|
||||
- `dm.enabled`(기본값 true)
|
||||
- `channels.slack.allowFrom`(권장)
|
||||
- `dm.allowFrom`(레거시)
|
||||
- `dm.groupEnabled`(그룹 DM 기본값 false)
|
||||
- `dm.groupChannels`(선택적 MPIM allowlist)
|
||||
|
||||
멀티 계정 우선순위:
|
||||
|
||||
- `channels.slack.accounts.default.allowFrom`은 `default` 계정에만 적용됩니다.
|
||||
- 이름 있는 계정은 자체 `allowFrom`이 설정되지 않은 경우 `channels.slack.allowFrom`을 상속합니다.
|
||||
- 이름 있는 계정은 `channels.slack.accounts.default.allowFrom`을 상속하지 않습니다.
|
||||
|
||||
DM의 페어링은 `openclaw pairing approve slack <code>`를 사용합니다.
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="채널 정책">
|
||||
`channels.slack.groupPolicy`가 채널 처리를 제어합니다.
|
||||
|
||||
- `open`
|
||||
- `allowlist`
|
||||
- `disabled`
|
||||
|
||||
채널 allowlist는 `channels.slack.channels` 아래에 있으며, 안정적인 채널 ID를 사용해야 합니다.
|
||||
|
||||
런타임 참고: `channels.slack`이 완전히 없는 경우(환경 변수 전용 설정), 런타임은 `channels.defaults.groupPolicy`가 설정되어 있더라도 `groupPolicy="allowlist"`로 대체하고 경고를 기록합니다.
|
||||
|
||||
이름/ID 해석:
|
||||
|
||||
- 채널 allowlist 항목과 DM allowlist 항목은 토큰 접근이 허용되면 시작 시 해석됩니다
|
||||
- 해석되지 않은 채널 이름 항목은 구성된 상태로 유지되지만 기본적으로 라우팅에서는 무시됩니다
|
||||
- 인바운드 권한 부여와 채널 라우팅은 기본적으로 ID 우선이며, 직접 사용자 이름/슬러그 일치를 사용하려면 `channels.slack.dangerouslyAllowNameMatching: true`가 필요합니다
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="멘션 및 채널 사용자">
|
||||
채널 메시지는 기본적으로 멘션 게이팅이 적용됩니다.
|
||||
|
||||
멘션 소스:
|
||||
|
||||
- 명시적 앱 멘션(`<@botId>`)
|
||||
- 멘션 정규식 패턴(`agents.list[].groupChat.mentionPatterns`, 대체값 `messages.groupChat.mentionPatterns`)
|
||||
- 암묵적인 봇 답글 스레드 동작
|
||||
|
||||
채널별 제어(`channels.slack.channels.<id>`; 이름은 시작 시 해석 또는 `dangerouslyAllowNameMatching`을 통해서만 가능):
|
||||
|
||||
- `requireMention`
|
||||
- `users`(allowlist)
|
||||
- `allowBots`
|
||||
- `skills`
|
||||
- `systemPrompt`
|
||||
- `tools`, `toolsBySender`
|
||||
- `toolsBySender` 키 형식: `id:`, `e164:`, `username:`, `name:`, 또는 `"*"` 와일드카드
|
||||
(레거시 접두사 없는 키도 여전히 `id:` 전용으로 매핑됨)
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 스레딩, 세션 및 답글 태그
|
||||
|
||||
- DM은 `direct`로, 채널은 `channel`로, MPIM은 `group`으로 라우팅됩니다.
|
||||
- 기본 `session.dmScope=main`에서는 Slack DM이 에이전트 메인 세션으로 합쳐집니다.
|
||||
- 채널 세션: `agent:<agentId>:slack:channel:<channelId>`.
|
||||
- 스레드 답글은 해당되는 경우 스레드 세션 접미사(`:thread:<threadTs>`)를 만들 수 있습니다.
|
||||
- `channels.slack.thread.historyScope` 기본값은 `thread`이고, `thread.inheritParent` 기본값은 `false`입니다.
|
||||
- `channels.slack.thread.initialHistoryLimit`는 새 스레드 세션이 시작될 때 가져오는 기존 스레드 메시지 수를 제어합니다(기본값 `20`; 비활성화하려면 `0` 설정).
|
||||
|
||||
답글 스레딩 제어:
|
||||
|
||||
- `channels.slack.replyToMode`: `off|first|all`(기본값 `off`)
|
||||
- `channels.slack.replyToModeByChatType`: `direct|group|channel`별
|
||||
- 직접 채팅용 레거시 대체: `channels.slack.dm.replyToMode`
|
||||
|
||||
수동 답글 태그가 지원됩니다.
|
||||
|
||||
- `[[reply_to_current]]`
|
||||
- `[[reply_to:<id>]]`
|
||||
|
||||
참고: `replyToMode="off"`는 Slack의 **모든** 답글 스레딩을 비활성화하며, 명시적인 `[[reply_to_*]]` 태그도 포함됩니다. 이는 명시적 태그가 `"off"` 모드에서도 계속 존중되는 Telegram과 다릅니다. 이 차이는 플랫폼의 스레딩 모델을 반영합니다. Slack 스레드는 채널에서 메시지를 숨기지만, Telegram 답글은 메인 채팅 흐름에서 계속 보입니다.
|
||||
|
||||
## 확인 반응
|
||||
|
||||
`ackReaction`은 OpenClaw가 인바운드 메시지를 처리하는 동안 확인 이모지를 전송합니다.
|
||||
|
||||
해결 순서:
|
||||
|
||||
- `channels.slack.accounts.<accountId>.ackReaction`
|
||||
- `channels.slack.ackReaction`
|
||||
- `messages.ackReaction`
|
||||
- 에이전트 신원 이모지 대체값(`agents.list[].identity.emoji`, 없으면 "👀")
|
||||
|
||||
참고:
|
||||
|
||||
- Slack은 shortcode를 기대합니다(예: `"eyes"`).
|
||||
- Slack 계정 또는 전역에서 반응을 비활성화하려면 `""`를 사용하세요.
|
||||
|
||||
## 텍스트 스트리밍
|
||||
|
||||
`channels.slack.streaming`은 라이브 미리보기 동작을 제어합니다.
|
||||
|
||||
- `off`: 라이브 미리보기 스트리밍 비활성화
|
||||
- `partial`(기본값): 미리보기 텍스트를 최신 부분 출력으로 교체
|
||||
- `block`: 청크 단위 미리보기 업데이트를 추가
|
||||
- `progress`: 생성 중 진행 상태 텍스트를 표시한 다음 최종 텍스트 전송
|
||||
|
||||
`channels.slack.nativeStreaming`은 `streaming`이 `partial`일 때 Slack 네이티브 텍스트 스트리밍을 제어합니다(기본값: `true`).
|
||||
|
||||
- 네이티브 텍스트 스트리밍이 표시되려면 답글 스레드를 사용할 수 있어야 합니다. 스레드 선택은 여전히 `replyToMode`를 따릅니다. 스레드가 없으면 일반 초안 미리보기가 사용됩니다.
|
||||
- 미디어 및 비텍스트 페이로드는 일반 전달로 대체됩니다.
|
||||
- 스트리밍이 답글 도중 실패하면 OpenClaw는 남은 페이로드에 대해 일반 전달로 대체합니다.
|
||||
|
||||
Slack 네이티브 텍스트 스트리밍 대신 초안 미리보기를 사용하려면:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
slack: {
|
||||
streaming: "partial",
|
||||
nativeStreaming: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
레거시 키:
|
||||
|
||||
- `channels.slack.streamMode`(`replace | status_final | append`)는 자동으로 `channels.slack.streaming`으로 마이그레이션됩니다.
|
||||
- 불리언 `channels.slack.streaming`은 자동으로 `channels.slack.nativeStreaming`으로 마이그레이션됩니다.
|
||||
|
||||
## 타이핑 반응 대체
|
||||
|
||||
`typingReaction`은 OpenClaw가 답글을 처리하는 동안 인바운드 Slack 메시지에 임시 반응을 추가하고, 실행이 끝나면 제거합니다. 이는 기본 "is typing..." 상태 표시기를 사용하는 스레드 답글 외부에서 특히 유용합니다.
|
||||
|
||||
해결 순서:
|
||||
|
||||
- `channels.slack.accounts.<accountId>.typingReaction`
|
||||
- `channels.slack.typingReaction`
|
||||
|
||||
참고:
|
||||
|
||||
- Slack은 shortcode를 기대합니다(예: `"hourglass_flowing_sand"`).
|
||||
- 이 반응은 best-effort이며, 답글 또는 실패 경로가 완료된 뒤 정리가 자동으로 시도됩니다.
|
||||
|
||||
## 미디어, 청크 분할 및 전달
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="인바운드 첨부 파일">
|
||||
Slack 파일 첨부는 Slack이 호스팅하는 비공개 URL에서 다운로드되며(토큰 인증 요청 흐름), 가져오기에 성공하고 크기 제한을 충족하면 미디어 저장소에 기록됩니다.
|
||||
|
||||
런타임 인바운드 크기 상한은 `channels.slack.mediaMaxMb`로 재정의하지 않는 한 기본적으로 `20MB`입니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="아웃바운드 텍스트 및 파일">
|
||||
- 텍스트 청크는 `channels.slack.textChunkLimit`을 사용합니다(기본값 4000)
|
||||
- `channels.slack.chunkMode="newline"`은 문단 우선 분할을 활성화합니다
|
||||
- 파일 전송은 Slack 업로드 API를 사용하며 스레드 답글(`thread_ts`)을 포함할 수 있습니다
|
||||
- 아웃바운드 미디어 상한은 구성된 경우 `channels.slack.mediaMaxMb`를 따르며, 그렇지 않으면 채널 전송은 미디어 파이프라인의 MIME 종류 기본값을 사용합니다
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="전달 대상">
|
||||
권장되는 명시적 대상:
|
||||
|
||||
- DM용 `user:<id>`
|
||||
- 채널용 `channel:<id>`
|
||||
|
||||
Slack DM은 사용자 대상에 전송할 때 Slack 대화 API를 통해 열립니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 명령 및 슬래시 동작
|
||||
|
||||
- Slack에서는 네이티브 명령 자동 모드가 **꺼짐**입니다(`commands.native: "auto"`는 Slack 네이티브 명령을 활성화하지 않음).
|
||||
- `channels.slack.commands.native: true`(또는 전역 `commands.native: true`)로 네이티브 Slack 명령 핸들러를 활성화하세요.
|
||||
- 네이티브 명령이 활성화되면, Slack에 일치하는 슬래시 명령(`/<command>` 이름)을 등록하세요. 단, 예외가 하나 있습니다.
|
||||
- 상태 명령에는 `/agentstatus`를 등록하세요(Slack은 `/status`를 예약함)
|
||||
- 네이티브 명령이 활성화되지 않은 경우, `channels.slack.slashCommand`를 통해 하나의 구성된 슬래시 명령을 실행할 수 있습니다.
|
||||
- 네이티브 인수 메뉴는 이제 렌더링 전략을 적응적으로 선택합니다.
|
||||
- 최대 5개 옵션: 버튼 블록
|
||||
- 6-100개 옵션: 정적 선택 메뉴
|
||||
- 100개 초과 옵션: interactivity 옵션 핸들러를 사용할 수 있을 때 비동기 옵션 필터링이 있는 외부 선택
|
||||
- 인코딩된 옵션 값이 Slack 제한을 초과하면 흐름은 버튼으로 대체됩니다
|
||||
- 긴 옵션 페이로드의 경우, Slash command 인수 메뉴는 선택한 값을 디스패치하기 전에 확인 대화상자를 사용합니다.
|
||||
|
||||
기본 슬래시 명령 설정:
|
||||
|
||||
- `enabled: false`
|
||||
- `name: "openclaw"`
|
||||
- `sessionPrefix: "slack:slash"`
|
||||
- `ephemeral: true`
|
||||
|
||||
슬래시 세션은 격리된 키를 사용합니다.
|
||||
|
||||
- `agent:<agentId>:slack:slash:<userId>`
|
||||
|
||||
또한 명령 실행은 대상 대화 세션(`CommandTargetSessionKey`)에 대해 계속 라우팅됩니다.
|
||||
|
||||
## 대화형 답글
|
||||
|
||||
Slack은 에이전트가 작성한 대화형 답글 제어를 렌더링할 수 있지만, 이 기능은 기본적으로 비활성화되어 있습니다.
|
||||
|
||||
전역으로 활성화:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
slack: {
|
||||
capabilities: {
|
||||
interactiveReplies: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
또는 하나의 Slack 계정에 대해서만 활성화:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
slack: {
|
||||
accounts: {
|
||||
ops: {
|
||||
capabilities: {
|
||||
interactiveReplies: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
활성화되면 에이전트는 Slack 전용 답글 지시문을 출력할 수 있습니다.
|
||||
|
||||
- `[[slack_buttons: Approve:approve, Reject:reject]]`
|
||||
- `[[slack_select: Choose a target | Canary:canary, Production:production]]`
|
||||
|
||||
이 지시문은 Slack Block Kit으로 컴파일되며, 클릭 또는 선택은 기존 Slack 상호작용 이벤트 경로를 통해 다시 라우팅됩니다.
|
||||
|
||||
참고:
|
||||
|
||||
- 이것은 Slack 전용 UI입니다. 다른 채널은 Slack Block Kit 지시문을 자체 버튼 시스템으로 번역하지 않습니다.
|
||||
- 대화형 콜백 값은 에이전트가 작성한 원시 값이 아니라 OpenClaw가 생성한 불투명 토큰입니다.
|
||||
- 생성된 대화형 블록이 Slack Block Kit 제한을 초과하면, OpenClaw는 잘못된 blocks 페이로드를 보내는 대신 원래 텍스트 답글로 대체합니다.
|
||||
|
||||
## Slack의 exec 승인
|
||||
|
||||
Slack은 Web UI나 터미널로 대체하는 대신, 대화형 버튼과 상호작용을 갖춘 네이티브 승인 클라이언트로 동작할 수 있습니다.
|
||||
|
||||
- Exec 승인은 네이티브 DM/채널 라우팅을 위해 `channels.slack.execApprovals.*`를 사용합니다.
|
||||
- 플러그인 승인은 요청이 이미 Slack에 도착했고 승인 ID 종류가 `plugin:`일 때 동일한 Slack 네이티브 버튼 표면을 통해 계속 해석될 수 있습니다.
|
||||
- 승인자 권한 부여는 여전히 강제됩니다. 승인자로 식별된 사용자만 Slack을 통해 요청을 승인하거나 거부할 수 있습니다.
|
||||
|
||||
이는 다른 채널과 동일한 공유 승인 버튼 표면을 사용합니다. Slack 앱 설정에서 `interactivity`가 활성화되어 있으면, 승인 프롬프트가 대화에 직접 Block Kit 버튼으로 렌더링됩니다.
|
||||
이 버튼이 있을 때는 그것이 기본 승인 UX가 되며, OpenClaw는 도구 결과에서 채팅 승인을 사용할 수 없거나 수동 승인이 유일한 경로라고 표시하는 경우에만 수동 `/approve` 명령을 포함해야 합니다.
|
||||
|
||||
구성 경로:
|
||||
|
||||
- `channels.slack.execApprovals.enabled`
|
||||
- `channels.slack.execApprovals.approvers`(선택 사항, 가능하면 `commands.ownerAllowFrom`으로 대체)
|
||||
- `channels.slack.execApprovals.target`(`dm` | `channel` | `both`, 기본값: `dm`)
|
||||
- `agentFilter`, `sessionFilter`
|
||||
|
||||
Slack은 `enabled`가 설정되지 않았거나 `"auto"`이고 최소 한 명의 승인자가 해석되면 네이티브 exec 승인을 자동으로 활성화합니다. Slack을 네이티브 승인 클라이언트로 명시적으로 비활성화하려면 `enabled: false`로 설정하세요.
|
||||
승인자가 해석될 때 네이티브 승인을 강제로 켜려면 `enabled: true`로 설정하세요.
|
||||
|
||||
명시적인 Slack exec 승인 구성이 없을 때의 기본 동작:
|
||||
|
||||
```json5
|
||||
{
|
||||
commands: {
|
||||
ownerAllowFrom: ["slack:U12345678"],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
명시적인 Slack 네이티브 구성은 승인자를 재정의하거나, 필터를 추가하거나, origin-chat 전달을 선택하려는 경우에만 필요합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
slack: {
|
||||
execApprovals: {
|
||||
enabled: true,
|
||||
approvers: ["U12345678"],
|
||||
target: "both",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
공유 `approvals.exec` 전달은 별개입니다. exec 승인 프롬프트를 다른 채팅이나 명시적인 대역 외 대상으로도 라우팅해야 할 때만 사용하세요. 공유 `approvals.plugin` 전달도 별개이며, Slack 네이티브 버튼은 해당 요청이 이미 Slack에 도착한 경우 계속 플러그인 승인을 해석할 수 있습니다.
|
||||
|
||||
동일 채팅의 `/approve`도 이미 명령을 지원하는 Slack 채널과 DM에서 동작합니다. 전체 승인 전달 모델은 [Exec approvals](/tools/exec-approvals)를 참조하세요.
|
||||
|
||||
## 이벤트 및 운영 동작
|
||||
|
||||
- 메시지 편집/삭제/스레드 브로드캐스트는 시스템 이벤트로 매핑됩니다.
|
||||
- 반응 추가/제거 이벤트는 시스템 이벤트로 매핑됩니다.
|
||||
- 멤버 참여/퇴장, 채널 생성/이름 변경, 핀 추가/제거 이벤트는 시스템 이벤트로 매핑됩니다.
|
||||
- `channel_id_changed`는 `configWrites`가 활성화된 경우 채널 구성 키를 마이그레이션할 수 있습니다.
|
||||
- 채널 topic/purpose 메타데이터는 신뢰할 수 없는 컨텍스트로 취급되며 라우팅 컨텍스트에 주입될 수 있습니다.
|
||||
- 스레드 시작자와 초기 스레드 기록 컨텍스트 시딩은 해당되는 경우 구성된 발신자 allowlist로 필터링됩니다.
|
||||
- 블록 작업 및 모달 상호작용은 풍부한 페이로드 필드와 함께 구조화된 `Slack interaction: ...` 시스템 이벤트를 발생시킵니다.
|
||||
- 블록 작업: 선택된 값, 라벨, picker 값, `workflow_*` 메타데이터
|
||||
- 라우팅된 채널 메타데이터와 폼 입력이 포함된 모달 `view_submission` 및 `view_closed` 이벤트
|
||||
|
||||
## 구성 참조 포인터
|
||||
|
||||
기본 참조:
|
||||
|
||||
- [구성 참조 - Slack](/gateway/configuration-reference#slack)
|
||||
|
||||
신호가 강한 Slack 필드:
|
||||
- 모드/인증: `mode`, `botToken`, `appToken`, `signingSecret`, `webhookPath`, `accounts.*`
|
||||
- DM 접근: `dm.enabled`, `dmPolicy`, `allowFrom`(레거시: `dm.policy`, `dm.allowFrom`), `dm.groupEnabled`, `dm.groupChannels`
|
||||
- 호환성 토글: `dangerouslyAllowNameMatching`(비상용, 필요하지 않다면 꺼두기)
|
||||
- 채널 접근: `groupPolicy`, `channels.*`, `channels.*.users`, `channels.*.requireMention`
|
||||
- 스레딩/기록: `replyToMode`, `replyToModeByChatType`, `thread.*`, `historyLimit`, `dmHistoryLimit`, `dms.*.historyLimit`
|
||||
- 전달: `textChunkLimit`, `chunkMode`, `mediaMaxMb`, `streaming`, `nativeStreaming`
|
||||
- 운영/기능: `configWrites`, `commands.native`, `slashCommand.*`, `actions.*`, `userToken`, `userTokenReadOnly`
|
||||
|
||||
## 문제 해결
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="채널에서 답글이 없음">
|
||||
다음 순서로 확인하세요.
|
||||
|
||||
- `groupPolicy`
|
||||
- 채널 allowlist(`channels.slack.channels`)
|
||||
- `requireMention`
|
||||
- 채널별 `users` allowlist
|
||||
|
||||
유용한 명령:
|
||||
|
||||
```bash
|
||||
openclaw channels status --probe
|
||||
openclaw logs --follow
|
||||
openclaw doctor
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="DM 메시지가 무시됨">
|
||||
다음을 확인하세요.
|
||||
|
||||
- `channels.slack.dm.enabled`
|
||||
- `channels.slack.dmPolicy`(또는 레거시 `channels.slack.dm.policy`)
|
||||
- 페어링 승인 / allowlist 항목
|
||||
|
||||
```bash
|
||||
openclaw pairing list slack
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Socket mode가 연결되지 않음">
|
||||
봇 토큰 + 앱 토큰, 그리고 Slack 앱 설정의 Socket Mode 활성화를 검증하세요.
|
||||
|
||||
`openclaw channels status --probe --json`에 `botTokenStatus` 또는
|
||||
`appTokenStatus: "configured_unavailable"`가 표시되면, Slack 계정은
|
||||
구성되어 있지만 현재 런타임이 SecretRef 기반 값을 해석할 수 없었다는 뜻입니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="HTTP mode가 이벤트를 수신하지 않음">
|
||||
다음을 검증하세요.
|
||||
|
||||
- signing secret
|
||||
- webhook 경로
|
||||
- Slack Request URL(Events + Interactivity + Slash Commands)
|
||||
- HTTP 계정별 고유 `webhookPath`
|
||||
|
||||
계정 스냅샷에 `signingSecretStatus: "configured_unavailable"`가 나타나면,
|
||||
HTTP 계정은 구성되어 있지만 현재 런타임이 SecretRef 기반 signing secret을
|
||||
해석할 수 없었다는 뜻입니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="네이티브/슬래시 명령이 실행되지 않음">
|
||||
의도한 방식이 다음 중 어느 것인지 확인하세요.
|
||||
|
||||
- Slack에 일치하는 슬래시 명령을 등록한 네이티브 명령 모드(`channels.slack.commands.native: true`)
|
||||
- 또는 단일 슬래시 명령 모드(`channels.slack.slashCommand.enabled: true`)
|
||||
|
||||
또한 `commands.useAccessGroups`와 채널/사용자 allowlist도 확인하세요.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [페어링](/channels/pairing)
|
||||
- [그룹](/channels/groups)
|
||||
- [Security](/gateway/security)
|
||||
- [채널 라우팅](/channels/channel-routing)
|
||||
- [문제 해결](/channels/troubleshooting)
|
||||
- [구성](/gateway/configuration)
|
||||
- [슬래시 명령](/tools/slash-commands)
|
||||
190
docs/ko/channels/synology-chat.md
Normal file
190
docs/ko/channels/synology-chat.md
Normal file
@ -0,0 +1,190 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw와 함께 Synology Chat를 설정할 때
|
||||
- Synology Chat 웹훅 라우팅을 디버깅할 때
|
||||
summary: Synology Chat 웹훅 설정 및 OpenClaw 구성
|
||||
title: Synology Chat
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:36:17Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ddb25fc6b53f896f15f43b4936d69ea071a29a91838a5b662819377271e89d81
|
||||
source_path: channels/synology-chat.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Synology Chat
|
||||
|
||||
상태: Synology Chat 웹훅을 사용하는 번들 plugin 다이렉트 메시지 채널입니다.
|
||||
이 plugin은 Synology Chat 아웃고잉 웹훅에서 수신 메시지를 받아들이고
|
||||
Synology Chat 인커밍 웹훅을 통해 응답을 전송합니다.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
Synology Chat는 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 있으므로, 일반적인
|
||||
패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
이전 빌드 또는 Synology Chat가 제외된 사용자 지정 설치를 사용 중이라면,
|
||||
수동으로 설치하세요:
|
||||
|
||||
로컬 체크아웃에서 설치:
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./path/to/local/synology-chat-plugin
|
||||
```
|
||||
|
||||
자세한 내용: [Plugins](/tools/plugin)
|
||||
|
||||
## 빠른 설정
|
||||
|
||||
1. Synology Chat plugin을 사용할 수 있는지 확인합니다.
|
||||
- 현재 패키지된 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 이전/사용자 지정 설치에서는 위 명령으로 소스 체크아웃에서 수동 추가할 수 있습니다.
|
||||
- 이제 `openclaw onboard`는 `openclaw channels add`와 동일한 채널 설정 목록에 Synology Chat를 표시합니다.
|
||||
- 비대화형 설정: `openclaw channels add --channel synology-chat --token <token> --url <incoming-webhook-url>`
|
||||
2. Synology Chat 통합에서 다음을 수행합니다:
|
||||
- 인커밍 웹훅을 만들고 URL을 복사합니다.
|
||||
- 비밀 토큰으로 아웃고잉 웹훅을 만듭니다.
|
||||
3. 아웃고잉 웹훅 URL이 OpenClaw 게이트웨이를 가리키도록 설정합니다:
|
||||
- 기본값: `https://gateway-host/webhook/synology`
|
||||
- 또는 사용자 지정 `channels.synology-chat.webhookPath`
|
||||
4. OpenClaw에서 설정을 완료합니다.
|
||||
- 가이드 방식: `openclaw onboard`
|
||||
- 직접 방식: `openclaw channels add --channel synology-chat --token <token> --url <incoming-webhook-url>`
|
||||
5. 게이트웨이를 재시작하고 Synology Chat 봇에 DM을 보냅니다.
|
||||
|
||||
웹훅 인증 세부 정보:
|
||||
|
||||
- OpenClaw는 먼저 `body.token`에서, 그다음 `?token=...`에서, 그다음 헤더에서 아웃고잉 웹훅 토큰을 받아들입니다.
|
||||
- 허용되는 헤더 형식:
|
||||
- `x-synology-token`
|
||||
- `x-webhook-token`
|
||||
- `x-openclaw-token`
|
||||
- `Authorization: Bearer <token>`
|
||||
- 비어 있거나 누락된 토큰은 fail-closed 방식으로 거부됩니다.
|
||||
|
||||
최소 구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"synology-chat": {
|
||||
enabled: true,
|
||||
token: "synology-outgoing-token",
|
||||
incomingUrl: "https://nas.example.com/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=...",
|
||||
webhookPath: "/webhook/synology",
|
||||
dmPolicy: "allowlist",
|
||||
allowedUserIds: ["123456"],
|
||||
rateLimitPerMinute: 30,
|
||||
allowInsecureSsl: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 환경 변수
|
||||
|
||||
기본 계정에는 다음 env var를 사용할 수 있습니다:
|
||||
|
||||
- `SYNOLOGY_CHAT_TOKEN`
|
||||
- `SYNOLOGY_CHAT_INCOMING_URL`
|
||||
- `SYNOLOGY_NAS_HOST`
|
||||
- `SYNOLOGY_ALLOWED_USER_IDS` (쉼표로 구분)
|
||||
- `SYNOLOGY_RATE_LIMIT`
|
||||
- `OPENCLAW_BOT_NAME`
|
||||
|
||||
config 값이 env var보다 우선합니다.
|
||||
|
||||
## DM 정책 및 액세스 제어
|
||||
|
||||
- `dmPolicy: "allowlist"`가 권장 기본값입니다.
|
||||
- `allowedUserIds`는 Synology 사용자 ID 목록(또는 쉼표로 구분된 문자열)을 받습니다.
|
||||
- `allowlist` 모드에서 빈 `allowedUserIds` 목록은 잘못된 구성으로 처리되며 웹훅 라우트가 시작되지 않습니다(모두 허용하려면 `dmPolicy: "open"` 사용).
|
||||
- `dmPolicy: "open"`은 모든 발신자를 허용합니다.
|
||||
- `dmPolicy: "disabled"`는 DM을 차단합니다.
|
||||
- 응답 수신자 바인딩은 기본적으로 안정적인 숫자 `user_id`에 유지됩니다. `channels.synology-chat.dangerouslyAllowNameMatching: true`는 변경 가능한 사용자 이름/닉네임 조회를 통한 응답 전달을 다시 활성화하는 비상 호환 모드입니다.
|
||||
- 페어링 승인은 다음과 함께 작동합니다:
|
||||
- `openclaw pairing list synology-chat`
|
||||
- `openclaw pairing approve synology-chat <CODE>`
|
||||
|
||||
## 아웃바운드 전달
|
||||
|
||||
대상으로 숫자 Synology Chat 사용자 ID를 사용하세요.
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw message send --channel synology-chat --target 123456 --text "Hello from OpenClaw"
|
||||
openclaw message send --channel synology-chat --target synology-chat:123456 --text "Hello again"
|
||||
```
|
||||
|
||||
미디어 전송은 URL 기반 파일 전달로 지원됩니다.
|
||||
|
||||
## 다중 계정
|
||||
|
||||
여러 Synology Chat 계정이 `channels.synology-chat.accounts` 아래에서 지원됩니다.
|
||||
각 계정은 토큰, 인커밍 URL, 웹훅 경로, DM 정책 및 제한을 재정의할 수 있습니다.
|
||||
다이렉트 메시지 세션은 계정 및 사용자별로 격리되므로, 서로 다른 두 Synology 계정에서 동일한 숫자 `user_id`를 사용하더라도 대화 기록 상태를 공유하지 않습니다.
|
||||
활성화된 각 계정에는 고유한 `webhookPath`를 지정하세요. 이제 OpenClaw는 중복되는 정확한 경로를 거부하며,
|
||||
다중 계정 설정에서 공유 웹훅 경로만 상속하는 이름 있는 계정은 시작을 거부합니다.
|
||||
이름 있는 계정에 의도적으로 레거시 상속이 필요하다면
|
||||
해당 계정 또는 `channels.synology-chat`에 `dangerouslyAllowInheritedWebhookPath: true`를 설정하세요.
|
||||
단, 중복되는 정확한 경로는 여전히 fail-closed 방식으로 거부됩니다. 계정별 명시적 경로를 권장합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
"synology-chat": {
|
||||
enabled: true,
|
||||
accounts: {
|
||||
default: {
|
||||
token: "token-a",
|
||||
incomingUrl: "https://nas-a.example.com/...token=...",
|
||||
},
|
||||
alerts: {
|
||||
token: "token-b",
|
||||
incomingUrl: "https://nas-b.example.com/...token=...",
|
||||
webhookPath: "/webhook/synology-alerts",
|
||||
dmPolicy: "allowlist",
|
||||
allowedUserIds: ["987654"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 보안 참고 사항
|
||||
|
||||
- `token`은 비밀로 유지하고 유출되면 교체하세요.
|
||||
- 자체 서명된 로컬 NAS 인증서를 명시적으로 신뢰하는 경우가 아니라면 `allowInsecureSsl: false`를 유지하세요.
|
||||
- 수신 웹훅 요청은 토큰 검증 및 발신자별 속도 제한이 적용됩니다.
|
||||
- 잘못된 토큰 검사는 상수 시간 비밀 비교를 사용하며 fail-closed 방식으로 처리됩니다.
|
||||
- 프로덕션에서는 `dmPolicy: "allowlist"`를 권장합니다.
|
||||
- 레거시 사용자 이름 기반 응답 전달이 명시적으로 필요한 경우가 아니라면 `dangerouslyAllowNameMatching`을 끄세요.
|
||||
- 다중 계정 설정에서 공유 경로 라우팅 위험을 명시적으로 수용하는 경우가 아니라면 `dangerouslyAllowInheritedWebhookPath`를 끄세요.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
- `Missing required fields (token, user_id, text)`:
|
||||
- 아웃고잉 웹훅 페이로드에 필수 필드 중 하나가 없습니다
|
||||
- Synology가 헤더로 토큰을 보낸다면 게이트웨이/프록시가 해당 헤더를 보존하는지 확인하세요
|
||||
- `Invalid token`:
|
||||
- 아웃고잉 웹훅 비밀이 `channels.synology-chat.token`과 일치하지 않습니다
|
||||
- 요청이 잘못된 계정/웹훅 경로로 들어오고 있습니다
|
||||
- 요청이 OpenClaw에 도달하기 전에 리버스 프록시가 토큰 헤더를 제거했습니다
|
||||
- `Rate limit exceeded`:
|
||||
- 동일한 소스에서 너무 많은 잘못된 토큰 시도가 있으면 해당 소스가 일시적으로 차단될 수 있습니다
|
||||
- 인증된 발신자에게도 별도의 사용자별 메시지 속도 제한이 적용됩니다
|
||||
- `Allowlist is empty. Configure allowedUserIds or use dmPolicy=open.`:
|
||||
- `dmPolicy="allowlist"`가 활성화되었지만 구성된 사용자가 없습니다
|
||||
- `User not authorized`:
|
||||
- 발신자의 숫자 `user_id`가 `allowedUserIds`에 없습니다
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 강화
|
||||
1065
docs/ko/channels/telegram.md
Normal file
1065
docs/ko/channels/telegram.md
Normal file
File diff suppressed because it is too large
Load Diff
296
docs/ko/channels/tlon.md
Normal file
296
docs/ko/channels/tlon.md
Normal file
@ -0,0 +1,296 @@
|
||||
---
|
||||
read_when:
|
||||
- Tlon/Urbit 채널 기능을 작업할 때
|
||||
summary: Tlon/Urbit 지원 상태, 기능 및 구성
|
||||
title: Tlon
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:36:48Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 289cffb3c1b2d450a5f41e0d67117dfb5c192cec956d82039caac9df9f07496d
|
||||
source_path: channels/tlon.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Tlon
|
||||
|
||||
Tlon은 Urbit 기반의 탈중앙화 메신저입니다. OpenClaw는 사용자의 Urbit ship에 연결하여
|
||||
DM과 그룹 채팅 메시지에 응답할 수 있습니다. 그룹 응답은 기본적으로 @ 멘션이 필요하며
|
||||
허용 목록을 통해 추가로 제한할 수 있습니다.
|
||||
|
||||
상태: 번들 plugin. DM, 그룹 멘션, 스레드 응답, 리치 텍스트 서식, 이미지 업로드를
|
||||
지원합니다. 반응과 Polls는 아직 지원되지 않습니다.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
Tlon은 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 있으므로, 일반적인 패키지
|
||||
빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
이전 빌드 또는 Tlon이 제외된 사용자 지정 설치를 사용 중이라면 수동으로
|
||||
설치하세요:
|
||||
|
||||
CLI를 통한 설치(npm 레지스트리):
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/tlon
|
||||
```
|
||||
|
||||
로컬 체크아웃(깃 저장소에서 실행하는 경우):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./path/to/local/tlon-plugin
|
||||
```
|
||||
|
||||
자세한 내용: [Plugins](/tools/plugin)
|
||||
|
||||
## 설정
|
||||
|
||||
1. Tlon plugin을 사용할 수 있는지 확인합니다.
|
||||
- 현재 패키지된 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 이전/사용자 지정 설치는 위 명령으로 수동 추가할 수 있습니다.
|
||||
2. ship URL과 로그인 코드를 준비합니다.
|
||||
3. `channels.tlon`을 구성합니다.
|
||||
4. 게이트웨이를 재시작합니다.
|
||||
5. 봇에 DM을 보내거나 그룹 채널에서 멘션합니다.
|
||||
|
||||
최소 구성(단일 계정):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
tlon: {
|
||||
enabled: true,
|
||||
ship: "~sampel-palnet",
|
||||
url: "https://your-ship-host",
|
||||
code: "lidlut-tabwed-pillex-ridrup",
|
||||
ownerShip: "~your-main-ship", // 권장: 사용자의 ship, 항상 허용됨
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 비공개/LAN ship
|
||||
|
||||
기본적으로 OpenClaw는 SSRF 보호를 위해 비공개/내부 호스트 이름과 IP 범위를 차단합니다.
|
||||
ship이 비공개 네트워크(localhost, LAN IP 또는 내부 호스트 이름)에서 실행 중인 경우,
|
||||
명시적으로 허용해야 합니다:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
tlon: {
|
||||
url: "http://localhost:8080",
|
||||
allowPrivateNetwork: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
이는 다음과 같은 URL에 적용됩니다:
|
||||
|
||||
- `http://localhost:8080`
|
||||
- `http://192.168.x.x:8080`
|
||||
- `http://my-ship.local:8080`
|
||||
|
||||
⚠️ 로컬 네트워크를 신뢰하는 경우에만 이것을 활성화하세요. 이 설정은 ship URL에 대한 요청의 SSRF 보호를
|
||||
비활성화합니다.
|
||||
|
||||
## 그룹 채널
|
||||
|
||||
자동 검색은 기본적으로 활성화되어 있습니다. 채널을 수동으로 고정할 수도 있습니다:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
tlon: {
|
||||
groupChannels: ["chat/~host-ship/general", "chat/~host-ship/support"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
자동 검색 비활성화:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
tlon: {
|
||||
autoDiscoverChannels: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 액세스 제어
|
||||
|
||||
DM 허용 목록(비어 있으면 DM 허용 안 함, 승인 흐름에는 `ownerShip` 사용):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
tlon: {
|
||||
dmAllowlist: ["~zod", "~nec"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
그룹 권한 부여(기본적으로 제한됨):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
tlon: {
|
||||
defaultAuthorizedShips: ["~zod"],
|
||||
authorization: {
|
||||
channelRules: {
|
||||
"chat/~host-ship/general": {
|
||||
mode: "restricted",
|
||||
allowedShips: ["~zod", "~nec"],
|
||||
},
|
||||
"chat/~host-ship/announcements": {
|
||||
mode: "open",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 소유자 및 승인 시스템
|
||||
|
||||
권한 없는 사용자가 상호작용하려고 할 때 승인 요청을 받을 owner ship을 설정하세요:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
tlon: {
|
||||
ownerShip: "~your-main-ship",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
owner ship은 **모든 곳에서 자동으로 권한이 부여됩니다** — DM 초대는 자동 수락되며
|
||||
채널 메시지는 항상 허용됩니다. 소유자를 `dmAllowlist`나
|
||||
`defaultAuthorizedShips`에 추가할 필요가 없습니다.
|
||||
|
||||
설정되면 소유자는 다음에 대한 DM 알림을 받습니다:
|
||||
|
||||
- 허용 목록에 없는 ship의 DM 요청
|
||||
- 권한 없는 채널에서의 멘션
|
||||
- 그룹 초대 요청
|
||||
|
||||
## 자동 수락 설정
|
||||
|
||||
DM 초대 자동 수락(`dmAllowlist`에 있는 ship 대상):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
tlon: {
|
||||
autoAcceptDmInvites: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
그룹 초대 자동 수락:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
tlon: {
|
||||
autoAcceptGroupInvites: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 전달 대상(CLI/cron)
|
||||
|
||||
`openclaw message send` 또는 cron 전달과 함께 다음을 사용하세요:
|
||||
|
||||
- DM: `~sampel-palnet` 또는 `dm/~sampel-palnet`
|
||||
- 그룹: `chat/~host-ship/channel` 또는 `group:~host-ship/channel`
|
||||
|
||||
## 번들 Skills
|
||||
|
||||
Tlon plugin에는 Tlon 작업에 대한 CLI 액세스를 제공하는 번들 Skills([`@tloncorp/tlon-skill`](https://github.com/tloncorp/tlon-skill))가 포함되어 있습니다:
|
||||
|
||||
- **연락처**: 프로필 가져오기/업데이트, 연락처 목록 보기
|
||||
- **채널**: 목록 보기, 생성, 메시지 게시, 기록 가져오기
|
||||
- **그룹**: 목록 보기, 생성, 구성원 관리
|
||||
- **DM**: 메시지 보내기, 메시지에 반응하기
|
||||
- **반응**: 게시물 및 DM에 이모지 반응 추가/제거
|
||||
- **설정**: 슬래시 명령으로 plugin 권한 관리
|
||||
|
||||
plugin이 설치되면 해당 Skills는 자동으로 사용할 수 있습니다.
|
||||
|
||||
## 기능
|
||||
|
||||
| 기능 | 상태 |
|
||||
| --------------- | ---------------------------------------- |
|
||||
| 다이렉트 메시지 | ✅ 지원됨 |
|
||||
| 그룹/채널 | ✅ 지원됨 (기본적으로 멘션 게이트 적용) |
|
||||
| 스레드 | ✅ 지원됨 (스레드에서 자동 응답) |
|
||||
| 리치 텍스트 | ✅ Markdown이 Tlon 형식으로 변환됨 |
|
||||
| 이미지 | ✅ Tlon 저장소에 업로드됨 |
|
||||
| 반응 | ✅ [번들 Skills](#번들-skills) 통해 지원 |
|
||||
| Polls | ❌ 아직 지원되지 않음 |
|
||||
| 네이티브 명령 | ✅ 지원됨 (기본적으로 owner 전용) |
|
||||
|
||||
## 문제 해결
|
||||
|
||||
먼저 다음 순서대로 실행하세요:
|
||||
|
||||
```bash
|
||||
openclaw status
|
||||
openclaw gateway status
|
||||
openclaw logs --follow
|
||||
openclaw doctor
|
||||
```
|
||||
|
||||
일반적인 실패 사례:
|
||||
|
||||
- **DM이 무시됨**: 발신자가 `dmAllowlist`에 없고 승인 흐름용 `ownerShip`이 구성되지 않았습니다.
|
||||
- **그룹 메시지가 무시됨**: 채널이 검색되지 않았거나 발신자에게 권한이 없습니다.
|
||||
- **연결 오류**: ship URL에 접근 가능한지 확인하세요. 로컬 ship에는 `allowPrivateNetwork`를 활성화하세요.
|
||||
- **인증 오류**: 로그인 코드가 최신인지 확인하세요(코드는 순환 변경됨).
|
||||
|
||||
## 구성 참조
|
||||
|
||||
전체 구성: [Configuration](/gateway/configuration)
|
||||
|
||||
제공자 옵션:
|
||||
|
||||
- `channels.tlon.enabled`: 채널 시작 활성화/비활성화.
|
||||
- `channels.tlon.ship`: 봇의 Urbit ship 이름(예: `~sampel-palnet`).
|
||||
- `channels.tlon.url`: ship URL(예: `https://sampel-palnet.tlon.network`).
|
||||
- `channels.tlon.code`: ship 로그인 코드.
|
||||
- `channels.tlon.allowPrivateNetwork`: localhost/LAN URL 허용(SSRF 우회).
|
||||
- `channels.tlon.ownerShip`: 승인 시스템용 owner ship(항상 권한 있음).
|
||||
- `channels.tlon.dmAllowlist`: DM을 보낼 수 있는 ship(비어 있으면 없음).
|
||||
- `channels.tlon.autoAcceptDmInvites`: 허용 목록에 있는 ship의 DM을 자동 수락.
|
||||
- `channels.tlon.autoAcceptGroupInvites`: 모든 그룹 초대를 자동 수락.
|
||||
- `channels.tlon.autoDiscoverChannels`: 그룹 채널 자동 검색(기본값: true).
|
||||
- `channels.tlon.groupChannels`: 수동으로 고정된 채널 nest.
|
||||
- `channels.tlon.defaultAuthorizedShips`: 모든 채널에 대해 권한이 있는 ship.
|
||||
- `channels.tlon.authorization.channelRules`: 채널별 인증 규칙.
|
||||
- `channels.tlon.showModelSignature`: 메시지에 모델 이름 추가.
|
||||
|
||||
## 참고
|
||||
|
||||
- 그룹 응답은 응답하려면 멘션(예: `~your-bot-ship`)이 필요합니다.
|
||||
- 스레드 응답: 수신 메시지가 스레드에 있으면 OpenClaw는 해당 스레드에서 응답합니다.
|
||||
- 리치 텍스트: Markdown 서식(굵게, 기울임꼴, 코드, 헤더, 목록)은 Tlon의 네이티브 형식으로 변환됩니다.
|
||||
- 이미지: URL은 Tlon 저장소에 업로드되어 이미지 블록으로 삽입됩니다.
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 강화
|
||||
140
docs/ko/channels/troubleshooting.md
Normal file
140
docs/ko/channels/troubleshooting.md
Normal file
@ -0,0 +1,140 @@
|
||||
---
|
||||
read_when:
|
||||
- 채널 전송은 연결되었다고 표시되지만 응답이 실패함
|
||||
- 더 깊은 provider 문서를 보기 전에 채널별 확인이 필요함
|
||||
summary: 채널별 실패 시그니처와 해결 방법으로 빠르게 수행하는 채널 수준 문제 해결
|
||||
title: 채널 문제 해결
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:36:45Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: d45d8220505ea420d970b20bc66e65216c2d7024b5736db1936421ffc0676e1f
|
||||
source_path: channels/troubleshooting.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 채널 문제 해결
|
||||
|
||||
채널은 연결되지만 동작이 잘못될 때 이 페이지를 사용하세요.
|
||||
|
||||
## 명령 단계
|
||||
|
||||
먼저 다음 명령을 순서대로 실행하세요.
|
||||
|
||||
```bash
|
||||
openclaw status
|
||||
openclaw gateway status
|
||||
openclaw logs --follow
|
||||
openclaw doctor
|
||||
openclaw channels status --probe
|
||||
```
|
||||
|
||||
정상 기준선:
|
||||
|
||||
- `Runtime: running`
|
||||
- `RPC probe: ok`
|
||||
- 채널 프로브에 전송 연결 상태가 표시되고, 지원되는 경우 `works` 또는 `audit ok`가 표시됨
|
||||
|
||||
## WhatsApp
|
||||
|
||||
### WhatsApp 실패 시그니처
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ---------------------------- | ------------------------------------------------- | ---------------------------------------------------------- |
|
||||
| 연결되었지만 DM 응답이 없음 | `openclaw pairing list whatsapp` | 발신자를 승인하거나 DM 정책/allowlist를 변경하세요. |
|
||||
| 그룹 메시지가 무시됨 | config에서 `requireMention` + mention 패턴 확인 | 봇을 mention하거나 해당 그룹의 mention 정책을 완화하세요. |
|
||||
| 무작위 연결 해제/재로그인 루프 | `openclaw channels status --probe` + 로그 | 다시 로그인하고 자격 증명 디렉터리가 정상인지 확인하세요. |
|
||||
|
||||
전체 문제 해결: [/channels/whatsapp#troubleshooting](/channels/whatsapp#troubleshooting)
|
||||
|
||||
## Telegram
|
||||
|
||||
### Telegram 실패 시그니처
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ----------------------------------- | --------------------------------------------- | ----------------------------------------------------------------------------- |
|
||||
| `/start`는 되지만 정상적인 응답 흐름이 없음 | `openclaw pairing list telegram` | 페어링을 승인하거나 DM 정책을 변경하세요. |
|
||||
| 봇은 온라인인데 그룹이 조용함 | mention 요구 사항과 봇 privacy mode 확인 | 그룹 가시성을 위해 privacy mode를 비활성화하거나 봇을 mention하세요. |
|
||||
| 네트워크 오류와 함께 전송 실패 | Telegram API 호출 실패 로그 확인 | `api.telegram.org`로의 DNS/IPv6/프록시 라우팅을 수정하세요. |
|
||||
| 시작 시 `setMyCommands`가 거부됨 | `BOT_COMMANDS_TOO_MUCH` 로그 확인 | plugin/skill/custom Telegram 명령을 줄이거나 네이티브 메뉴를 비활성화하세요. |
|
||||
| 업그레이드 후 allowlist가 나를 차단함 | `openclaw security audit` 및 config allowlist | `openclaw doctor --fix`를 실행하거나 `@username`을 숫자 발신자 ID로 바꾸세요. |
|
||||
|
||||
전체 문제 해결: [/channels/telegram#troubleshooting](/channels/telegram#troubleshooting)
|
||||
|
||||
## Discord
|
||||
|
||||
### Discord 실패 시그니처
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ----------------------------- | -------------------------------------- | ------------------------------------------------------------- |
|
||||
| 봇은 온라인인데 길드 응답이 없음 | `openclaw channels status --probe` | 길드/채널을 허용하고 message content intent를 확인하세요. |
|
||||
| 그룹 메시지가 무시됨 | 로그에서 mention 게이팅 드롭 확인 | 봇을 mention하거나 길드/채널 `requireMention: false`를 설정하세요. |
|
||||
| DM 응답이 누락됨 | `openclaw pairing list discord` | DM 페어링을 승인하거나 DM 정책을 조정하세요. |
|
||||
|
||||
전체 문제 해결: [/channels/discord#troubleshooting](/channels/discord#troubleshooting)
|
||||
|
||||
## Slack
|
||||
|
||||
### Slack 실패 시그니처
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| -------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Socket mode는 연결되었지만 응답이 없음 | `openclaw channels status --probe` | 앱 토큰 + 봇 토큰과 필요한 scope를 확인하세요. SecretRef 기반 설정에서는 `botTokenStatus` / `appTokenStatus = configured_unavailable`를 주의 깊게 보세요. |
|
||||
| DM이 차단됨 | `openclaw pairing list slack` | 페어링을 승인하거나 DM 정책을 완화하세요. |
|
||||
| 채널 메시지가 무시됨 | `groupPolicy` 및 채널 allowlist 확인 | 채널을 허용하거나 정책을 `open`으로 변경하세요. |
|
||||
|
||||
전체 문제 해결: [/channels/slack#troubleshooting](/channels/slack#troubleshooting)
|
||||
|
||||
## iMessage 및 BlueBubbles
|
||||
|
||||
### iMessage 및 BlueBubbles 실패 시그니처
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| --------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------- |
|
||||
| 수신 이벤트가 없음 | webhook/server 도달 가능성 및 앱 권한 확인 | webhook URL 또는 BlueBubbles 서버 상태를 수정하세요. |
|
||||
| 보낼 수는 있지만 macOS에서 수신이 안 됨 | Messages 자동화에 대한 macOS 개인정보 보호 권한 확인 | TCC 권한을 다시 부여하고 채널 프로세스를 재시작하세요. |
|
||||
| DM 발신자가 차단됨 | `openclaw pairing list imessage` 또는 `openclaw pairing list bluebubbles` | 페어링을 승인하거나 allowlist를 업데이트하세요. |
|
||||
|
||||
전체 문제 해결:
|
||||
|
||||
- [/channels/imessage#troubleshooting](/channels/imessage#troubleshooting)
|
||||
- [/channels/bluebubbles#troubleshooting](/channels/bluebubbles#troubleshooting)
|
||||
|
||||
## Signal
|
||||
|
||||
### Signal 실패 시그니처
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ----------------------------- | ---------------------------------------- | ------------------------------------------------------------- |
|
||||
| 데몬에 도달 가능하지만 봇이 조용함 | `openclaw channels status --probe` | `signal-cli` 데몬 URL/계정 및 수신 모드를 확인하세요. |
|
||||
| DM이 차단됨 | `openclaw pairing list signal` | 발신자를 승인하거나 DM 정책을 조정하세요. |
|
||||
| 그룹 응답이 트리거되지 않음 | 그룹 allowlist 및 mention 패턴 확인 | 발신자/그룹을 추가하거나 게이팅을 완화하세요. |
|
||||
|
||||
전체 문제 해결: [/channels/signal#troubleshooting](/channels/signal#troubleshooting)
|
||||
|
||||
## QQ Bot
|
||||
|
||||
### QQ Bot 실패 시그니처
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ------------------------------ | -------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| 봇이 "gone to Mars"라고 응답함 | config에서 `appId` 및 `clientSecret` 확인 | 자격 증명을 설정하거나 gateway를 재시작하세요. |
|
||||
| 수신 메시지가 없음 | `openclaw channels status --probe` | QQ Open Platform에서 자격 증명을 확인하세요. |
|
||||
| 음성이 전사되지 않음 | STT provider config 확인 | `channels.qqbot.stt` 또는 `tools.media.audio`를 구성하세요. |
|
||||
| 능동적 메시지가 도착하지 않음 | QQ 플랫폼 상호작용 요구 사항 확인 | QQ는 최근 상호작용이 없으면 봇이 시작한 메시지를 차단할 수 있습니다. |
|
||||
|
||||
전체 문제 해결: [/channels/qqbot#troubleshooting](/channels/qqbot#troubleshooting)
|
||||
|
||||
## Matrix
|
||||
|
||||
### Matrix 실패 시그니처
|
||||
|
||||
| 증상 | 가장 빠른 확인 방법 | 해결 방법 |
|
||||
| ------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------- |
|
||||
| 로그인했지만 룸 메시지를 무시함 | `openclaw channels status --probe` | `groupPolicy`, 룸 allowlist, mention 게이팅을 확인하세요. |
|
||||
| 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`를 실행하거나 복구 키로 다시 실행하세요. |
|
||||
| 교차 서명/bootstrap 상태가 잘못됨 | `openclaw matrix verify bootstrap` | 비밀 저장소, 교차 서명, 백업 상태를 한 번에 복구하세요. |
|
||||
|
||||
전체 설정 및 구성: [Matrix](/channels/matrix)
|
||||
398
docs/ko/channels/twitch.md
Normal file
398
docs/ko/channels/twitch.md
Normal file
@ -0,0 +1,398 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw용 Twitch 채팅 통합을 설정할 때
|
||||
summary: Twitch 채팅 봇 구성 및 설정
|
||||
title: Twitch
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:36:56Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 47af9fb6edb1f462c5919850ee9d05e500a1914ddd0d64a41608fbe960e77cd6
|
||||
source_path: channels/twitch.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Twitch
|
||||
|
||||
IRC 연결을 통한 Twitch 채팅 지원입니다. OpenClaw는 Twitch 사용자(봇 계정)로 연결하여 채널에서 메시지를 수신하고 전송합니다.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
Twitch는 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 있으므로 일반 패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
이전 빌드 또는 Twitch가 제외된 사용자 지정 설치를 사용하는 경우 수동으로 설치하세요.
|
||||
|
||||
CLI를 통해 설치(npm 레지스트리):
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/twitch
|
||||
```
|
||||
|
||||
로컬 체크아웃(git 리포지토리에서 실행하는 경우):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./path/to/local/twitch-plugin
|
||||
```
|
||||
|
||||
자세한 내용: [Plugins](/tools/plugin)
|
||||
|
||||
## 빠른 설정(초보자용)
|
||||
|
||||
1. Twitch plugin을 사용할 수 있는지 확인합니다.
|
||||
- 현재 패키지된 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 이전/사용자 지정 설치에서는 위 명령으로 수동 추가할 수 있습니다.
|
||||
2. 봇용 전용 Twitch 계정을 생성합니다(또는 기존 계정을 사용합니다).
|
||||
3. 자격 증명을 생성합니다: [Twitch Token Generator](https://twitchtokengenerator.com/)
|
||||
- **Bot Token**을 선택합니다
|
||||
- `chat:read` 및 `chat:write` 스코프가 선택되었는지 확인합니다
|
||||
- **Client ID** 및 **Access Token**을 복사합니다
|
||||
4. Twitch 사용자 ID를 찾습니다: [https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/](https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/)
|
||||
5. 토큰을 구성합니다.
|
||||
- Env: `OPENCLAW_TWITCH_ACCESS_TOKEN=...` (기본 계정 전용)
|
||||
- 또는 config: `channels.twitch.accessToken`
|
||||
- 둘 다 설정된 경우 config가 우선합니다(env 폴백은 기본 계정 전용).
|
||||
6. gateway를 시작합니다.
|
||||
|
||||
**⚠️ 중요:** 승인되지 않은 사용자가 봇을 트리거하지 못하도록 액세스 제어(`allowFrom` 또는 `allowedRoles`)를 추가하세요. `requireMention`의 기본값은 `true`입니다.
|
||||
|
||||
최소 구성:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
enabled: true,
|
||||
username: "openclaw", // 봇의 Twitch 계정
|
||||
accessToken: "oauth:abc123...", // OAuth 액세스 토큰(또는 OPENCLAW_TWITCH_ACCESS_TOKEN env var 사용)
|
||||
clientId: "xyz789...", // Token Generator의 Client ID
|
||||
channel: "vevisk", // 참여할 Twitch 채널 채팅(필수)
|
||||
allowFrom: ["123456789"], // (권장) 사용자 본인의 Twitch 사용자 ID만 허용 - https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/ 에서 확인
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 개요
|
||||
|
||||
- Gateway가 소유하는 Twitch 채널입니다.
|
||||
- 결정적 라우팅: 응답은 항상 Twitch로 다시 전송됩니다.
|
||||
- 각 계정은 격리된 세션 키 `agent:<agentId>:twitch:<accountName>`에 매핑됩니다.
|
||||
- `username`은 봇 계정(인증 주체)이고, `channel`은 참여할 채팅방입니다.
|
||||
|
||||
## 설정(상세)
|
||||
|
||||
### 자격 증명 생성
|
||||
|
||||
[Twitch Token Generator](https://twitchtokengenerator.com/)를 사용하세요.
|
||||
|
||||
- **Bot Token**을 선택합니다
|
||||
- `chat:read` 및 `chat:write` 스코프가 선택되었는지 확인합니다
|
||||
- **Client ID** 및 **Access Token**을 복사합니다
|
||||
|
||||
수동 앱 등록은 필요하지 않습니다. 토큰은 몇 시간 후 만료됩니다.
|
||||
|
||||
### 봇 구성
|
||||
|
||||
**Env var(기본 계정 전용):**
|
||||
|
||||
```bash
|
||||
OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
|
||||
```
|
||||
|
||||
**또는 config:**
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
enabled: true,
|
||||
username: "openclaw",
|
||||
accessToken: "oauth:abc123...",
|
||||
clientId: "xyz789...",
|
||||
channel: "vevisk",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
env와 config가 모두 설정된 경우 config가 우선합니다.
|
||||
|
||||
### 액세스 제어(권장)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
allowFrom: ["123456789"], // (권장) 사용자 본인의 Twitch 사용자 ID만 허용
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
강력한 허용 목록에는 `allowFrom`을 우선 사용하세요. 역할 기반 액세스를 원하면 대신 `allowedRoles`를 사용하세요.
|
||||
|
||||
**사용 가능한 역할:** `"moderator"`, `"owner"`, `"vip"`, `"subscriber"`, `"all"`.
|
||||
|
||||
**왜 사용자 ID인가요?** 사용자 이름은 변경될 수 있어 사칭이 가능하지만, 사용자 ID는 영구적입니다.
|
||||
|
||||
Twitch 사용자 ID 찾기: [https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/](https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/) (Twitch 사용자 이름을 ID로 변환)
|
||||
|
||||
## 토큰 갱신(선택 사항)
|
||||
|
||||
[Twitch Token Generator](https://twitchtokengenerator.com/)에서 생성한 토큰은 자동 갱신할 수 없습니다. 만료되면 다시 생성하세요.
|
||||
|
||||
자동 토큰 갱신을 원하면 [Twitch Developer Console](https://dev.twitch.tv/console)에서 직접 Twitch 애플리케이션을 만들고 config에 다음을 추가하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
clientSecret: "your_client_secret",
|
||||
refreshToken: "your_refresh_token",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
봇은 만료 전에 자동으로 토큰을 갱신하고 갱신 이벤트를 로그에 기록합니다.
|
||||
|
||||
## 다중 계정 지원
|
||||
|
||||
계정별 토큰을 사용하려면 `channels.twitch.accounts`를 사용하세요. 공통 패턴은 [`gateway/configuration`](/gateway/configuration)을 참조하세요.
|
||||
|
||||
예시(하나의 봇 계정을 두 채널에서 사용):
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
accounts: {
|
||||
channel1: {
|
||||
username: "openclaw",
|
||||
accessToken: "oauth:abc123...",
|
||||
clientId: "xyz789...",
|
||||
channel: "vevisk",
|
||||
},
|
||||
channel2: {
|
||||
username: "openclaw",
|
||||
accessToken: "oauth:def456...",
|
||||
clientId: "uvw012...",
|
||||
channel: "secondchannel",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**참고:** 각 계정에는 자체 토큰이 필요합니다(채널당 하나의 토큰).
|
||||
|
||||
## 액세스 제어
|
||||
|
||||
### 역할 기반 제한
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
accounts: {
|
||||
default: {
|
||||
allowedRoles: ["moderator", "vip"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 사용자 ID별 허용 목록(가장 안전함)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
accounts: {
|
||||
default: {
|
||||
allowFrom: ["123456789", "987654321"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 역할 기반 액세스(대안)
|
||||
|
||||
`allowFrom`은 강력한 허용 목록입니다. 설정하면 해당 사용자 ID만 허용됩니다.
|
||||
역할 기반 액세스를 원하면 `allowFrom`은 설정하지 말고 대신 `allowedRoles`를 구성하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
accounts: {
|
||||
default: {
|
||||
allowedRoles: ["moderator"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### @mention 요구 사항 비활성화
|
||||
|
||||
기본적으로 `requireMention`은 `true`입니다. 비활성화하고 모든 메시지에 응답하려면 다음과 같이 설정하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
accounts: {
|
||||
default: {
|
||||
requireMention: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 문제 해결
|
||||
|
||||
먼저 진단 명령을 실행하세요.
|
||||
|
||||
```bash
|
||||
openclaw doctor
|
||||
openclaw channels status --probe
|
||||
```
|
||||
|
||||
### 봇이 메시지에 응답하지 않음
|
||||
|
||||
**액세스 제어 확인:** 사용자 ID가 `allowFrom`에 포함되어 있는지 확인하거나, 테스트를 위해 일시적으로 `allowFrom`을 제거하고 `allowedRoles: ["all"]`로 설정하세요.
|
||||
|
||||
**봇이 채널에 있는지 확인:** 봇은 `channel`에 지정된 채널에 참여해야 합니다.
|
||||
|
||||
### 토큰 문제
|
||||
|
||||
**"Failed to connect" 또는 인증 오류:**
|
||||
|
||||
- `accessToken`이 OAuth 액세스 토큰 값인지 확인하세요(일반적으로 `oauth:` 접두사로 시작)
|
||||
- 토큰에 `chat:read` 및 `chat:write` 스코프가 있는지 확인하세요
|
||||
- 토큰 갱신을 사용하는 경우 `clientSecret`과 `refreshToken`이 설정되었는지 확인하세요
|
||||
|
||||
### 토큰 갱신이 작동하지 않음
|
||||
|
||||
**갱신 이벤트 로그 확인:**
|
||||
|
||||
```
|
||||
Using env token source for mybot
|
||||
Access token refreshed for user 123456 (expires in 14400s)
|
||||
```
|
||||
|
||||
"token refresh disabled (no refresh token)"가 표시되면:
|
||||
|
||||
- `clientSecret`이 제공되었는지 확인하세요
|
||||
- `refreshToken`이 제공되었는지 확인하세요
|
||||
|
||||
## Config
|
||||
|
||||
**계정 config:**
|
||||
|
||||
- `username` - 봇 사용자 이름
|
||||
- `accessToken` - `chat:read` 및 `chat:write` 권한이 있는 OAuth 액세스 토큰
|
||||
- `clientId` - Twitch Client ID(Token Generator 또는 자체 앱에서 획득)
|
||||
- `channel` - 참여할 채널(필수)
|
||||
- `enabled` - 이 계정 활성화(기본값: `true`)
|
||||
- `clientSecret` - 선택 사항: 자동 토큰 갱신용
|
||||
- `refreshToken` - 선택 사항: 자동 토큰 갱신용
|
||||
- `expiresIn` - 토큰 만료 시간(초)
|
||||
- `obtainmentTimestamp` - 토큰 획득 타임스탬프
|
||||
- `allowFrom` - 사용자 ID 허용 목록
|
||||
- `allowedRoles` - 역할 기반 액세스 제어(`"moderator" | "owner" | "vip" | "subscriber" | "all"`)
|
||||
- `requireMention` - @mention 필요(기본값: `true`)
|
||||
|
||||
**Provider 옵션:**
|
||||
|
||||
- `channels.twitch.enabled` - 채널 시작 활성화/비활성화
|
||||
- `channels.twitch.username` - 봇 사용자 이름(단순화된 단일 계정 config)
|
||||
- `channels.twitch.accessToken` - OAuth 액세스 토큰(단순화된 단일 계정 config)
|
||||
- `channels.twitch.clientId` - Twitch Client ID(단순화된 단일 계정 config)
|
||||
- `channels.twitch.channel` - 참여할 채널(단순화된 단일 계정 config)
|
||||
- `channels.twitch.accounts.<accountName>` - 다중 계정 config(위의 모든 계정 필드)
|
||||
|
||||
전체 예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
twitch: {
|
||||
enabled: true,
|
||||
username: "openclaw",
|
||||
accessToken: "oauth:abc123...",
|
||||
clientId: "xyz789...",
|
||||
channel: "vevisk",
|
||||
clientSecret: "secret123...",
|
||||
refreshToken: "refresh456...",
|
||||
allowFrom: ["123456789"],
|
||||
allowedRoles: ["moderator", "vip"],
|
||||
accounts: {
|
||||
default: {
|
||||
username: "mybot",
|
||||
accessToken: "oauth:abc123...",
|
||||
clientId: "xyz789...",
|
||||
channel: "your_channel",
|
||||
enabled: true,
|
||||
clientSecret: "secret123...",
|
||||
refreshToken: "refresh456...",
|
||||
expiresIn: 14400,
|
||||
obtainmentTimestamp: 1706092800000,
|
||||
allowFrom: ["123456789", "987654321"],
|
||||
allowedRoles: ["moderator"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 도구 작업
|
||||
|
||||
에이전트는 다음 작업으로 `twitch`를 호출할 수 있습니다.
|
||||
|
||||
- `send` - 채널에 메시지 보내기
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
action: "twitch",
|
||||
params: {
|
||||
message: "Hello Twitch!",
|
||||
to: "#mychannel",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 안전 및 운영
|
||||
|
||||
- **토큰을 비밀번호처럼 취급하세요** - 토큰을 git에 커밋하지 마세요
|
||||
- **장기 실행 봇에는 자동 토큰 갱신을 사용하세요**
|
||||
- 액세스 제어에는 사용자 이름 대신 **사용자 ID 허용 목록**을 사용하세요
|
||||
- 토큰 갱신 이벤트와 연결 상태를 위해 **로그를 모니터링하세요**
|
||||
- **토큰 스코프를 최소화하세요** - `chat:read` 및 `chat:write`만 요청하세요
|
||||
- **문제가 해결되지 않으면**: 다른 프로세스가 세션을 소유하고 있지 않은지 확인한 후 gateway를 재시작하세요
|
||||
|
||||
## 제한
|
||||
|
||||
- 메시지당 **500자**(단어 경계 기준 자동 청킹)
|
||||
- 청킹 전에 Markdown이 제거됩니다
|
||||
- 속도 제한 없음(Twitch의 내장 rate limit 사용)
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 강화
|
||||
495
docs/ko/channels/whatsapp.md
Normal file
495
docs/ko/channels/whatsapp.md
Normal file
@ -0,0 +1,495 @@
|
||||
---
|
||||
read_when:
|
||||
- WhatsApp/웹 채널 동작 또는 받은편지함 라우팅 작업
|
||||
summary: WhatsApp 채널 지원, 접근 제어, 전달 동작 및 운영
|
||||
title: WhatsApp
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:36Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: c16a468b3f47fdf7e4fc3fd745b5c49c7ccebb7af0e8c87c632b78b04c583e49
|
||||
source_path: channels/whatsapp.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# WhatsApp (웹 채널)
|
||||
|
||||
상태: WhatsApp Web(Baileys)을 통한 프로덕션 준비 완료. Gateway가 연결된 세션을 소유합니다.
|
||||
|
||||
## 설치(필요 시)
|
||||
|
||||
- `openclaw onboard`와 `openclaw channels add --channel whatsapp`는
|
||||
WhatsApp plugin을 처음 선택할 때 설치를 안내합니다.
|
||||
- `openclaw channels login --channel whatsapp`도
|
||||
plugin이 아직 없으면 설치 흐름을 제공합니다.
|
||||
- 개발 채널 + git 체크아웃: 기본값은 로컬 plugin 경로입니다.
|
||||
- Stable/Beta: 기본값은 npm 패키지 `@openclaw/whatsapp`입니다.
|
||||
|
||||
수동 설치도 계속 사용할 수 있습니다.
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/whatsapp
|
||||
```
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="페어링" icon="link" href="/channels/pairing">
|
||||
알 수 없는 발신자에 대한 기본 DM 정책은 페어링입니다.
|
||||
</Card>
|
||||
<Card title="채널 문제 해결" icon="wrench" href="/channels/troubleshooting">
|
||||
채널 전반의 진단 및 복구 플레이북.
|
||||
</Card>
|
||||
<Card title="Gateway 구성" icon="settings" href="/gateway/configuration">
|
||||
전체 채널 config 패턴 및 예시.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## 빠른 설정
|
||||
|
||||
<Steps>
|
||||
<Step title="WhatsApp 접근 정책 구성">
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
dmPolicy: "pairing",
|
||||
allowFrom: ["+15551234567"],
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15551234567"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="WhatsApp 연결(QR)">
|
||||
|
||||
```bash
|
||||
openclaw channels login --channel whatsapp
|
||||
```
|
||||
|
||||
특정 계정의 경우:
|
||||
|
||||
```bash
|
||||
openclaw channels login --channel whatsapp --account work
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="gateway 시작">
|
||||
|
||||
```bash
|
||||
openclaw gateway
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="첫 번째 페어링 요청 승인(페어링 모드 사용 시)">
|
||||
|
||||
```bash
|
||||
openclaw pairing list whatsapp
|
||||
openclaw pairing approve whatsapp <CODE>
|
||||
```
|
||||
|
||||
페어링 요청은 1시간 후 만료됩니다. 대기 중 요청은 채널당 최대 3개까지 허용됩니다.
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
가능하면 OpenClaw는 WhatsApp를 별도 번호로 운영하는 것을 권장합니다. (채널 메타데이터와 설정 흐름은 그 구성을 기준으로 최적화되어 있지만, 개인 번호 설정도 지원합니다.)
|
||||
</Note>
|
||||
|
||||
## 배포 패턴
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="전용 번호(권장)">
|
||||
가장 깔끔한 운영 모드입니다.
|
||||
|
||||
- OpenClaw용 별도 WhatsApp 신원
|
||||
- 더 명확한 DM 허용 목록 및 라우팅 경계
|
||||
- 자기 자신과의 채팅 혼동 가능성 감소
|
||||
|
||||
최소 정책 패턴:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
dmPolicy: "allowlist",
|
||||
allowFrom: ["+15551234567"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="개인 번호 대체 사용">
|
||||
온보딩은 개인 번호 모드를 지원하며 self-chat 친화적인 기본 구성을 기록합니다.
|
||||
|
||||
- `dmPolicy: "allowlist"`
|
||||
- `allowFrom`에 개인 번호 포함
|
||||
- `selfChatMode: true`
|
||||
|
||||
런타임에서는 self-chat 보호가 연결된 자기 번호와 `allowFrom`을 기준으로 동작합니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="WhatsApp Web 전용 채널 범위">
|
||||
현재 OpenClaw 채널 아키텍처에서 메시징 플랫폼 채널은 WhatsApp Web 기반(`Baileys`)입니다.
|
||||
|
||||
내장 채팅 채널 레지스트리에는 별도의 Twilio WhatsApp 메시징 채널이 없습니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 런타임 모델
|
||||
|
||||
- Gateway가 WhatsApp 소켓과 재연결 루프를 소유합니다.
|
||||
- 아웃바운드 전송은 대상 계정에 대해 활성 WhatsApp 리스너가 있어야 합니다.
|
||||
- 상태 및 브로드캐스트 채팅은 무시됩니다(`@status`, `@broadcast`).
|
||||
- 다이렉트 채팅은 DM 세션 규칙을 사용합니다(`session.dmScope`; 기본값 `main`은 DM을 agent 메인 세션으로 병합함).
|
||||
- 그룹 세션은 격리됩니다(`agent:<agentId>:whatsapp:group:<jid>`).
|
||||
|
||||
## 접근 제어 및 활성화
|
||||
|
||||
<Tabs>
|
||||
<Tab title="DM 정책">
|
||||
`channels.whatsapp.dmPolicy`는 다이렉트 채팅 접근을 제어합니다.
|
||||
|
||||
- `pairing`(기본값)
|
||||
- `allowlist`
|
||||
- `open`(`allowFrom`에 `"*"` 포함 필요)
|
||||
- `disabled`
|
||||
|
||||
`allowFrom`은 E.164 형식 번호를 받으며(내부적으로 정규화됨).
|
||||
|
||||
멀티 계정 재정의: 해당 계정에서는 `channels.whatsapp.accounts.<id>.dmPolicy`(및 `allowFrom`)가 채널 수준 기본값보다 우선합니다.
|
||||
|
||||
런타임 동작 세부 사항:
|
||||
|
||||
- 페어링은 채널 allow-store에 영속 저장되며 구성된 `allowFrom`과 병합됩니다
|
||||
- 허용 목록이 구성되지 않았으면 연결된 자기 번호가 기본적으로 허용됩니다
|
||||
- 아웃바운드 `fromMe` DM은 자동 페어링되지 않습니다
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="그룹 정책 + 허용 목록">
|
||||
그룹 접근은 두 계층으로 구성됩니다.
|
||||
|
||||
1. **그룹 멤버십 허용 목록**(`channels.whatsapp.groups`)
|
||||
- `groups`가 생략되면 모든 그룹이 대상이 됩니다
|
||||
- `groups`가 있으면 그룹 허용 목록으로 동작합니다(`"*"` 허용 가능)
|
||||
|
||||
2. **그룹 발신자 정책**(`channels.whatsapp.groupPolicy` + `groupAllowFrom`)
|
||||
- `open`: 발신자 허용 목록 우회
|
||||
- `allowlist`: 발신자가 `groupAllowFrom`(또는 `*`)과 일치해야 함
|
||||
- `disabled`: 모든 그룹 수신 차단
|
||||
|
||||
발신자 허용 목록 대체 동작:
|
||||
|
||||
- `groupAllowFrom`이 설정되지 않으면, 런타임은 가능할 때 `allowFrom`으로 대체합니다
|
||||
- 발신자 허용 목록은 멘션/답글 활성화보다 먼저 평가됩니다
|
||||
|
||||
참고: `channels.whatsapp` 블록이 아예 없으면, `channels.defaults.groupPolicy`가 설정되어 있어도 런타임 그룹 정책 대체값은 `allowlist`입니다(경고 로그와 함께).
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="멘션 + /activation">
|
||||
그룹 응답은 기본적으로 멘션이 필요합니다.
|
||||
|
||||
멘션 감지에는 다음이 포함됩니다.
|
||||
|
||||
- 봇 신원에 대한 명시적 WhatsApp 멘션
|
||||
- 구성된 멘션 정규식 패턴(`agents.list[].groupChat.mentionPatterns`, 대체값 `messages.groupChat.mentionPatterns`)
|
||||
- 암묵적인 reply-to-bot 감지(답글 발신자가 봇 신원과 일치)
|
||||
|
||||
보안 참고:
|
||||
|
||||
- 인용/답글은 멘션 게이팅만 충족하며, 발신자 권한을 부여하지는 않습니다
|
||||
- `groupPolicy: "allowlist"`에서는 허용 목록에 없는 발신자가 허용 목록 사용자의 메시지에 답글을 달더라도 여전히 차단됩니다
|
||||
|
||||
세션 수준 활성화 명령:
|
||||
|
||||
- `/activation mention`
|
||||
- `/activation always`
|
||||
|
||||
`activation`은 세션 상태를 업데이트하며(전역 config 아님), 소유자 게이트가 적용됩니다.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 개인 번호 및 self-chat 동작
|
||||
|
||||
연결된 자기 번호가 `allowFrom`에도 포함되어 있으면 WhatsApp self-chat 보호가 활성화됩니다.
|
||||
|
||||
- self-chat 턴에서는 읽음 확인 생략
|
||||
- 그렇지 않으면 자신에게 핑을 보낼 수 있는 mention-JID 자동 트리거 동작 무시
|
||||
- `messages.responsePrefix`가 설정되지 않은 경우, self-chat 응답의 기본값은 `[{identity.name}]` 또는 `[openclaw]`
|
||||
|
||||
## 메시지 정규화 및 컨텍스트
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="수신 엔벌로프 + 답글 컨텍스트">
|
||||
들어오는 WhatsApp 메시지는 공용 수신 엔벌로프로 감싸집니다.
|
||||
|
||||
인용된 답글이 있으면 다음 형식으로 컨텍스트가 추가됩니다.
|
||||
|
||||
```text
|
||||
[Replying to <sender> id:<stanzaId>]
|
||||
<quoted body or media placeholder>
|
||||
[/Replying]
|
||||
```
|
||||
|
||||
답글 메타데이터 필드도 가능하면 채워집니다(`ReplyToId`, `ReplyToBody`, `ReplyToSender`, sender JID/E.164).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="미디어 플레이스홀더 및 위치/연락처 추출">
|
||||
미디어만 있는 수신 메시지는 다음과 같은 플레이스홀더로 정규화됩니다.
|
||||
|
||||
- `<media:image>`
|
||||
- `<media:video>`
|
||||
- `<media:audio>`
|
||||
- `<media:document>`
|
||||
- `<media:sticker>`
|
||||
|
||||
위치 및 연락처 페이로드는 라우팅 전에 텍스트 컨텍스트로 정규화됩니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="보류 중인 그룹 기록 주입">
|
||||
그룹에서는 아직 처리되지 않은 메시지를 버퍼링했다가 봇이 최종적으로 트리거될 때 컨텍스트로 주입할 수 있습니다.
|
||||
|
||||
- 기본 한도: `50`
|
||||
- config: `channels.whatsapp.historyLimit`
|
||||
- 대체값: `messages.groupChat.historyLimit`
|
||||
- `0`은 비활성화
|
||||
|
||||
주입 마커:
|
||||
|
||||
- `[Chat messages since your last reply - for context]`
|
||||
- `[Current message - respond to this]`
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="읽음 확인">
|
||||
읽음 확인은 허용된 수신 WhatsApp 메시지에 대해 기본적으로 활성화됩니다.
|
||||
|
||||
전역 비활성화:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
sendReadReceipts: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
계정별 재정의:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
accounts: {
|
||||
work: {
|
||||
sendReadReceipts: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
self-chat 턴에서는 전역적으로 활성화되어 있어도 읽음 확인을 보내지 않습니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 전달, 분할, 미디어
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="텍스트 분할">
|
||||
- 기본 분할 한도: `channels.whatsapp.textChunkLimit = 4000`
|
||||
- `channels.whatsapp.chunkMode = "length" | "newline"`
|
||||
- `newline` 모드는 단락 경계(빈 줄)를 우선하며, 이후 길이 안전 분할로 대체합니다
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="아웃바운드 미디어 동작">
|
||||
- 이미지, 비디오, 오디오(PTT 음성 메모), 문서 페이로드 지원
|
||||
- 음성 메모 호환성을 위해 `audio/ogg`는 `audio/ogg; codecs=opus`로 다시 작성됩니다
|
||||
- 비디오 전송 시 `gifPlayback: true`를 통해 애니메이션 GIF 재생 지원
|
||||
- 다중 미디어 응답 페이로드 전송 시 캡션은 첫 번째 미디어 항목에 적용됩니다
|
||||
- 미디어 소스는 HTTP(S), `file://`, 또는 로컬 경로일 수 있습니다
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="미디어 크기 제한 및 대체 동작">
|
||||
- 수신 미디어 저장 한도: `channels.whatsapp.mediaMaxMb`(기본값 `50`)
|
||||
- 아웃바운드 미디어 전송 한도: `channels.whatsapp.mediaMaxMb`(기본값 `50`)
|
||||
- 계정별 재정의는 `channels.whatsapp.accounts.<accountId>.mediaMaxMb` 사용
|
||||
- 이미지는 제한에 맞도록 자동 최적화됩니다(크기 조정/품질 스윕)
|
||||
- 미디어 전송 실패 시, 첫 번째 항목 대체 동작으로 응답을 조용히 버리지 않고 텍스트 경고를 전송합니다
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 반응 수준
|
||||
|
||||
`channels.whatsapp.reactionLevel`은 WhatsApp에서 에이전트가 이모지 반응을 얼마나 넓게 사용할지 제어합니다.
|
||||
|
||||
| 수준 | Ack 반응 | 에이전트 시작 반응 | 설명 |
|
||||
| ------------- | -------- | ------------------ | ------------------------------------------------- |
|
||||
| `"off"` | 아니요 | 아니요 | 반응을 전혀 사용하지 않음 |
|
||||
| `"ack"` | 예 | 아니요 | Ack 반응만 사용(응답 전 수신 확인) |
|
||||
| `"minimal"` | 예 | 예(보수적) | Ack + 보수적 가이드의 agent 반응 |
|
||||
| `"extensive"` | 예 | 예(권장) | Ack + 권장 가이드의 agent 반응 |
|
||||
|
||||
기본값: `"minimal"`.
|
||||
|
||||
계정별 재정의는 `channels.whatsapp.accounts.<id>.reactionLevel`을 사용합니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
reactionLevel: "ack",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 확인 반응
|
||||
|
||||
WhatsApp는 `channels.whatsapp.ackReaction`을 통해 수신 즉시 Ack 반응을 지원합니다.
|
||||
Ack 반응은 `reactionLevel`에 의해 제어되며, `reactionLevel`이 `"off"`이면 억제됩니다.
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
ackReaction: {
|
||||
emoji: "👀",
|
||||
direct: true,
|
||||
group: "mentions", // always | mentions | never
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
동작 참고:
|
||||
|
||||
- 수신이 허용된 직후 즉시 전송됨(응답 전)
|
||||
- 실패는 로그에 기록되지만 일반 응답 전달을 막지 않음
|
||||
- 그룹 모드 `mentions`는 멘션으로 트리거된 턴에 반응하며, 그룹 활성화 `always`는 이 검사를 우회하는 역할을 함
|
||||
- WhatsApp는 `channels.whatsapp.ackReaction`을 사용합니다(레거시 `messages.ackReaction`은 여기서 사용되지 않음)
|
||||
|
||||
## 멀티 계정 및 자격 증명
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="계정 선택 및 기본값">
|
||||
- 계정 ID는 `channels.whatsapp.accounts`에서 가져옵니다
|
||||
- 기본 계정 선택: `default`가 있으면 그것을, 없으면 첫 번째로 구성된 계정 ID(정렬 기준)
|
||||
- 조회를 위해 계정 ID는 내부적으로 정규화됩니다
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="자격 증명 경로 및 레거시 호환성">
|
||||
- 현재 auth 경로: `~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
|
||||
- 백업 파일: `creds.json.bak`
|
||||
- `~/.openclaw/credentials/`의 레거시 기본 auth도 기본 계정 흐름에서 계속 인식/마이그레이션됩니다
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="로그아웃 동작">
|
||||
`openclaw channels logout --channel whatsapp [--account <id>]`는 해당 계정의 WhatsApp auth 상태를 지웁니다.
|
||||
|
||||
레거시 auth 디렉터리에서는 `oauth.json`은 보존되고 Baileys auth 파일만 제거됩니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 도구, 작업, config 쓰기
|
||||
|
||||
- agent 도구 지원에는 WhatsApp 반응 작업(`react`)이 포함됩니다.
|
||||
- 작업 게이트:
|
||||
- `channels.whatsapp.actions.reactions`
|
||||
- `channels.whatsapp.actions.polls`
|
||||
- 채널 시작 config 쓰기는 기본적으로 활성화되어 있습니다(`channels.whatsapp.configWrites=false`로 비활성화).
|
||||
|
||||
## 문제 해결
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="연결되지 않음(QR 필요)">
|
||||
증상: 채널 상태에 연결되지 않음으로 표시됨.
|
||||
|
||||
해결 방법:
|
||||
|
||||
```bash
|
||||
openclaw channels login --channel whatsapp
|
||||
openclaw channels status
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="연결되었지만 연결 해제됨 / 재연결 루프">
|
||||
증상: 계정은 연결되었지만 연결 해제 또는 재연결 시도가 반복됨.
|
||||
|
||||
해결 방법:
|
||||
|
||||
```bash
|
||||
openclaw doctor
|
||||
openclaw logs --follow
|
||||
```
|
||||
|
||||
필요하면 `channels login`으로 다시 연결하세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="전송 시 활성 리스너 없음">
|
||||
대상 계정에 활성 gateway 리스너가 없으면 아웃바운드 전송은 즉시 실패합니다.
|
||||
|
||||
gateway가 실행 중이고 계정이 연결되어 있는지 확인하세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="그룹 메시지가 예상과 다르게 무시됨">
|
||||
다음 순서로 확인하세요.
|
||||
|
||||
- `groupPolicy`
|
||||
- `groupAllowFrom` / `allowFrom`
|
||||
- `groups` 허용 목록 항목
|
||||
- 멘션 게이팅(`requireMention` + mention 패턴)
|
||||
- `openclaw.json`(JSON5)의 중복 키: 나중 항목이 앞선 항목을 덮어쓰므로 범위별로 `groupPolicy`는 하나만 유지하세요
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Bun 런타임 경고">
|
||||
WhatsApp gateway 런타임은 Node를 사용해야 합니다. Bun은 안정적인 WhatsApp/Telegram gateway 운영과 호환되지 않는 것으로 표시됩니다.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 구성 참조 포인터
|
||||
|
||||
기본 참조:
|
||||
|
||||
- [구성 참조 - WhatsApp](/gateway/configuration-reference#whatsapp)
|
||||
|
||||
신호가 높은 WhatsApp 필드:
|
||||
|
||||
- 접근: `dmPolicy`, `allowFrom`, `groupPolicy`, `groupAllowFrom`, `groups`
|
||||
- 전달: `textChunkLimit`, `chunkMode`, `mediaMaxMb`, `sendReadReceipts`, `ackReaction`, `reactionLevel`
|
||||
- 멀티 계정: `accounts.<id>.enabled`, `accounts.<id>.authDir`, 계정 수준 재정의
|
||||
- 운영: `configWrites`, `debounceMs`, `web.enabled`, `web.heartbeatSeconds`, `web.reconnect.*`
|
||||
- 세션 동작: `session.dmScope`, `historyLimit`, `dmHistoryLimit`, `dms.<id>.historyLimit`
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [페어링](/channels/pairing)
|
||||
- [그룹](/channels/groups)
|
||||
- [보안](/gateway/security)
|
||||
- [채널 라우팅](/channels/channel-routing)
|
||||
- [멀티 agent 라우팅](/concepts/multi-agent)
|
||||
- [문제 해결](/channels/troubleshooting)
|
||||
259
docs/ko/channels/zalo.md
Normal file
259
docs/ko/channels/zalo.md
Normal file
@ -0,0 +1,259 @@
|
||||
---
|
||||
read_when:
|
||||
- Zalo 기능 또는 웹훅 작업 중
|
||||
summary: Zalo 봇 지원 상태, 기능 및 구성
|
||||
title: Zalo
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:21Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ab94642ba28e79605b67586af8f71c18bc10e0af60343a7df508e6823b6f4119
|
||||
source_path: channels/zalo.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Zalo (Bot API)
|
||||
|
||||
상태: 실험적입니다. DM이 지원됩니다. 아래 [Capabilities](#capabilities) 섹션은 현재 Marketplace 봇 동작을 반영합니다.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
Zalo는 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 있으므로, 일반적인 패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
이전 빌드 또는 Zalo가 제외된 커스텀 설치를 사용 중이라면 수동으로 설치하세요.
|
||||
|
||||
- CLI로 설치: `openclaw plugins install @openclaw/zalo`
|
||||
- 또는 소스 체크아웃에서 설치: `openclaw plugins install ./path/to/local/zalo-plugin`
|
||||
- 자세한 내용: [Plugins](/tools/plugin)
|
||||
|
||||
## 빠른 설정(초보자용)
|
||||
|
||||
1. Zalo plugin을 사용할 수 있는지 확인하세요.
|
||||
- 현재 패키지된 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 이전/커스텀 설치에서는 위 명령으로 수동 추가할 수 있습니다.
|
||||
2. 토큰을 설정하세요.
|
||||
- Env: `ZALO_BOT_TOKEN=...`
|
||||
- 또는 config: `channels.zalo.accounts.default.botToken: "..."`.
|
||||
3. gateway를 재시작하세요(또는 설정을 완료하세요).
|
||||
4. DM 액세스는 기본적으로 페어링이며, 첫 접촉 시 페어링 코드를 승인해야 합니다.
|
||||
|
||||
최소 config:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
zalo: {
|
||||
enabled: true,
|
||||
accounts: {
|
||||
default: {
|
||||
botToken: "12345689:abc-xyz",
|
||||
dmPolicy: "pairing",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 개요
|
||||
|
||||
Zalo는 베트남 중심의 메시징 앱이며, Bot API를 통해 Gateway가 1:1 대화용 봇을 실행할 수 있습니다.
|
||||
Zalo로의 결정적 라우팅이 필요한 지원 또는 알림에 적합합니다.
|
||||
|
||||
이 페이지는 **Zalo Bot Creator / Marketplace bots**에 대한 현재 OpenClaw 동작을 반영합니다.
|
||||
**Zalo Official Account (OA) bots**는 다른 Zalo 제품 표면이며 동작이 다를 수 있습니다.
|
||||
|
||||
- Gateway가 소유하는 Zalo Bot API 채널입니다.
|
||||
- 결정적 라우팅: 응답은 다시 Zalo로 돌아가며, 모델이 채널을 선택하지 않습니다.
|
||||
- DM은 에이전트의 메인 세션을 공유합니다.
|
||||
- 아래 [Capabilities](#capabilities) 섹션은 현재 Marketplace 봇 지원 범위를 보여줍니다.
|
||||
|
||||
## 설정(빠른 경로)
|
||||
|
||||
### 1) 봇 토큰 만들기(Zalo Bot Platform)
|
||||
|
||||
1. [https://bot.zaloplatforms.com](https://bot.zaloplatforms.com)으로 이동해 로그인합니다.
|
||||
2. 새 봇을 만들고 설정을 구성합니다.
|
||||
3. 전체 봇 토큰(보통 `numeric_id:secret`)을 복사합니다. Marketplace 봇의 경우, 실제 런타임에서 사용할 수 있는 토큰은 생성 후 봇 환영 메시지에 표시될 수 있습니다.
|
||||
|
||||
### 2) 토큰 구성(env 또는 config)
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
zalo: {
|
||||
enabled: true,
|
||||
accounts: {
|
||||
default: {
|
||||
botToken: "12345689:abc-xyz",
|
||||
dmPolicy: "pairing",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
나중에 그룹을 사용할 수 있는 Zalo 봇 표면으로 이동하면 `groupPolicy` 및 `groupAllowFrom` 같은 그룹별 config를 명시적으로 추가할 수 있습니다. 현재 Marketplace 봇 동작은 [Capabilities](#capabilities)를 참조하세요.
|
||||
|
||||
Env 옵션: `ZALO_BOT_TOKEN=...` (기본 계정에서만 작동).
|
||||
|
||||
다중 계정 지원: `channels.zalo.accounts`를 사용해 계정별 토큰과 선택적 `name`을 설정합니다.
|
||||
|
||||
3. gateway를 재시작하세요. 토큰이 확인되면(env 또는 config) Zalo가 시작됩니다.
|
||||
4. DM 액세스의 기본값은 페어링입니다. 봇에 처음 연락할 때 코드를 승인하세요.
|
||||
|
||||
## 작동 방식(동작)
|
||||
|
||||
- 수신 메시지는 미디어 플레이스홀더가 포함된 공유 채널 엔벌로프로 정규화됩니다.
|
||||
- 응답은 항상 동일한 Zalo 채팅으로 다시 라우팅됩니다.
|
||||
- 기본값은 long-polling이며, `channels.zalo.webhookUrl`을 사용하면 webhook 모드를 사용할 수 있습니다.
|
||||
|
||||
## 제한 사항
|
||||
|
||||
- 발신 텍스트는 2000자로 분할됩니다(Zalo API 제한).
|
||||
- 미디어 다운로드/업로드는 `channels.zalo.mediaMaxMb`(기본값 5)로 제한됩니다.
|
||||
- 2000자 제한으로 인해 스트리밍의 유용성이 낮아서 기본적으로 스트리밍은 차단됩니다.
|
||||
|
||||
## 액세스 제어(DM)
|
||||
|
||||
### DM 액세스
|
||||
|
||||
- 기본값: `channels.zalo.dmPolicy = "pairing"`. 알 수 없는 발신자는 페어링 코드를 받으며, 승인되기 전까지 메시지는 무시됩니다(코드는 1시간 후 만료).
|
||||
- 승인 방법:
|
||||
- `openclaw pairing list zalo`
|
||||
- `openclaw pairing approve zalo <CODE>`
|
||||
- 페어링은 기본 토큰 교환 방식입니다. 자세한 내용: [Pairing](/channels/pairing)
|
||||
- `channels.zalo.allowFrom`은 숫자 사용자 ID를 받습니다(사용자 이름 조회는 제공되지 않음).
|
||||
|
||||
## 액세스 제어(Groups)
|
||||
|
||||
**Zalo Bot Creator / Marketplace bots**의 경우, 실제로는 봇을 그룹에 아예 추가할 수 없었기 때문에 그룹 지원을 사용할 수 없었습니다.
|
||||
|
||||
즉, 아래 그룹 관련 config 키는 스키마에 존재하지만 Marketplace 봇에서는 사용할 수 없었습니다.
|
||||
|
||||
- `channels.zalo.groupPolicy`는 그룹 수신 처리를 제어합니다: `open | allowlist | disabled`.
|
||||
- `channels.zalo.groupAllowFrom`은 그룹에서 어떤 발신자 ID가 봇을 트리거할 수 있는지 제한합니다.
|
||||
- `groupAllowFrom`이 설정되지 않으면, Zalo는 발신자 검사에 `allowFrom`으로 폴백합니다.
|
||||
- 런타임 참고: `channels.zalo`가 완전히 누락된 경우에도 안전을 위해 런타임은 여전히 `groupPolicy="allowlist"`로 폴백합니다.
|
||||
|
||||
그룹 액세스를 봇 표면에서 사용할 수 있을 때의 그룹 정책 값은 다음과 같습니다.
|
||||
|
||||
- `groupPolicy: "disabled"` — 모든 그룹 메시지를 차단합니다.
|
||||
- `groupPolicy: "open"` — 모든 그룹 멤버를 허용합니다(mention 게이트 적용).
|
||||
- `groupPolicy: "allowlist"` — fail-closed 기본값이며, 허용된 발신자만 수락합니다.
|
||||
|
||||
다른 Zalo 봇 제품 표면을 사용 중이고 실제로 작동하는 그룹 동작을 확인했다면, Marketplace 봇 흐름과 같다고 가정하지 말고 별도로 문서화하세요.
|
||||
|
||||
## Long-polling vs webhook
|
||||
|
||||
- 기본값: long-polling(공개 URL 불필요).
|
||||
- Webhook 모드: `channels.zalo.webhookUrl` 및 `channels.zalo.webhookSecret`를 설정하세요.
|
||||
- webhook secret은 8~256자여야 합니다.
|
||||
- webhook URL은 HTTPS를 사용해야 합니다.
|
||||
- Zalo는 검증을 위해 `X-Bot-Api-Secret-Token` 헤더와 함께 이벤트를 보냅니다.
|
||||
- Gateway HTTP는 `channels.zalo.webhookPath`에서 webhook 요청을 처리합니다(기본값: webhook URL 경로).
|
||||
- 요청은 `Content-Type: application/json`(또는 `+json` 미디어 타입)을 사용해야 합니다.
|
||||
- 중복 이벤트(`event_name + message_id`)는 짧은 재생 방지 창 동안 무시됩니다.
|
||||
- 버스트 트래픽은 경로/소스별로 속도 제한되며 HTTP 429를 반환할 수 있습니다.
|
||||
|
||||
**참고:** Zalo API 문서에 따라 getUpdates(polling)와 webhook은 동시에 사용할 수 없습니다.
|
||||
|
||||
## 지원되는 메시지 유형
|
||||
|
||||
빠른 지원 현황은 [Capabilities](#capabilities)를 참조하세요. 아래 참고 사항은 동작에 추가 컨텍스트가 필요한 부분을 보완합니다.
|
||||
|
||||
- **텍스트 메시지**: 2000자 분할과 함께 완전 지원.
|
||||
- **텍스트 내 일반 URL**: 일반 텍스트 입력처럼 동작합니다.
|
||||
- **링크 미리보기 / 리치 링크 카드**: [Capabilities](#capabilities)의 Marketplace 봇 상태를 참조하세요. 안정적으로 응답을 트리거하지 못했습니다.
|
||||
- **이미지 메시지**: [Capabilities](#capabilities)의 Marketplace 봇 상태를 참조하세요. 수신 이미지 처리는 신뢰할 수 없었습니다(최종 응답 없이 타이핑 표시만 나타남).
|
||||
- **스티커**: [Capabilities](#capabilities)의 Marketplace 봇 상태를 참조하세요.
|
||||
- **음성 메모 / 오디오 파일 / 비디오 / 일반 파일 첨부**: [Capabilities](#capabilities)의 Marketplace 봇 상태를 참조하세요.
|
||||
- **지원되지 않는 유형**: 기록됩니다(예: 보호된 사용자의 메시지).
|
||||
|
||||
## Capabilities
|
||||
|
||||
이 표는 OpenClaw에서의 현재 **Zalo Bot Creator / Marketplace bot** 동작을 요약합니다.
|
||||
|
||||
| 기능 | 상태 |
|
||||
| --------------------------- | --------------------------------------- |
|
||||
| 다이렉트 메시지 | ✅ 지원됨 |
|
||||
| Groups | ❌ Marketplace 봇에서는 사용 불가 |
|
||||
| 미디어(수신 이미지) | ⚠️ 제한적 / 환경에서 확인 필요 |
|
||||
| 미디어(발신 이미지) | ⚠️ Marketplace 봇에서 재테스트 안 됨 |
|
||||
| 텍스트 내 일반 URL | ✅ 지원됨 |
|
||||
| 링크 미리보기 | ⚠️ Marketplace 봇에서는 신뢰하기 어려움 |
|
||||
| Reactions | ❌ 지원되지 않음 |
|
||||
| 스티커 | ⚠️ Marketplace 봇에서는 에이전트 응답 없음 |
|
||||
| 음성 메모 / 오디오 / 비디오 | ⚠️ Marketplace 봇에서는 에이전트 응답 없음 |
|
||||
| 파일 첨부 | ⚠️ Marketplace 봇에서는 에이전트 응답 없음 |
|
||||
| Threads | ❌ 지원되지 않음 |
|
||||
| Polls | ❌ 지원되지 않음 |
|
||||
| Native commands | ❌ 지원되지 않음 |
|
||||
| Streaming | ⚠️ 차단됨(2000자 제한) |
|
||||
|
||||
## 전달 대상(CLI/cron)
|
||||
|
||||
- 대화 ID를 대상으로 사용하세요.
|
||||
- 예시: `openclaw message send --channel zalo --target 123456789 --message "hi"`.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
**봇이 응답하지 않음:**
|
||||
|
||||
- 토큰이 유효한지 확인하세요: `openclaw channels status --probe`
|
||||
- 발신자가 승인되었는지 확인하세요(페어링 또는 allowFrom)
|
||||
- gateway 로그를 확인하세요: `openclaw logs --follow`
|
||||
|
||||
**Webhook이 이벤트를 수신하지 않음:**
|
||||
|
||||
- webhook URL이 HTTPS를 사용하는지 확인하세요
|
||||
- secret token이 8~256자인지 확인하세요
|
||||
- 구성된 경로에서 gateway HTTP 엔드포인트에 도달할 수 있는지 확인하세요
|
||||
- getUpdates polling이 실행 중이 아닌지 확인하세요(둘은 동시에 사용할 수 없음)
|
||||
|
||||
## 구성 참조(Zalo)
|
||||
|
||||
전체 구성: [Configuration](/gateway/configuration)
|
||||
|
||||
평면 최상위 키(`channels.zalo.botToken`, `channels.zalo.dmPolicy` 등)는 레거시 단일 계정 축약형입니다. 새 config에는 `channels.zalo.accounts.<id>.*`를 권장합니다. 두 형식 모두 스키마에 존재하므로 여기서 계속 문서화합니다.
|
||||
|
||||
Provider 옵션:
|
||||
|
||||
- `channels.zalo.enabled`: 채널 시작 활성화/비활성화.
|
||||
- `channels.zalo.botToken`: Zalo Bot Platform의 봇 토큰.
|
||||
- `channels.zalo.tokenFile`: 일반 파일 경로에서 토큰을 읽습니다. 심볼릭 링크는 거부됩니다.
|
||||
- `channels.zalo.dmPolicy`: `pairing | allowlist | open | disabled` (기본값: pairing).
|
||||
- `channels.zalo.allowFrom`: DM allowlist(사용자 ID). `open`에는 `"*"`가 필요합니다. 마법사는 숫자 ID를 요청합니다.
|
||||
- `channels.zalo.groupPolicy`: `open | allowlist | disabled` (기본값: allowlist). config에는 존재하며, 현재 Marketplace 봇 동작은 [Capabilities](#capabilities) 및 [Access control (Groups)](#access-control-groups)를 참조하세요.
|
||||
- `channels.zalo.groupAllowFrom`: 그룹 발신자 allowlist(사용자 ID). 설정되지 않으면 `allowFrom`으로 폴백합니다.
|
||||
- `channels.zalo.mediaMaxMb`: 수신/발신 미디어 상한(MB, 기본값 5).
|
||||
- `channels.zalo.webhookUrl`: webhook 모드 활성화(HTTPS 필수).
|
||||
- `channels.zalo.webhookSecret`: webhook secret(8~256자).
|
||||
- `channels.zalo.webhookPath`: gateway HTTP 서버의 webhook 경로.
|
||||
- `channels.zalo.proxy`: API 요청용 프록시 URL.
|
||||
|
||||
다중 계정 옵션:
|
||||
|
||||
- `channels.zalo.accounts.<id>.botToken`: 계정별 토큰.
|
||||
- `channels.zalo.accounts.<id>.tokenFile`: 계정별 일반 토큰 파일. 심볼릭 링크는 거부됩니다.
|
||||
- `channels.zalo.accounts.<id>.name`: 표시 이름.
|
||||
- `channels.zalo.accounts.<id>.enabled`: 계정 활성화/비활성화.
|
||||
- `channels.zalo.accounts.<id>.dmPolicy`: 계정별 DM 정책.
|
||||
- `channels.zalo.accounts.<id>.allowFrom`: 계정별 allowlist.
|
||||
- `channels.zalo.accounts.<id>.groupPolicy`: 계정별 그룹 정책. config에는 존재하며, 현재 Marketplace 봇 동작은 [Capabilities](#capabilities) 및 [Access control (Groups)](#access-control-groups)를 참조하세요.
|
||||
- `channels.zalo.accounts.<id>.groupAllowFrom`: 계정별 그룹 발신자 allowlist.
|
||||
- `channels.zalo.accounts.<id>.webhookUrl`: 계정별 webhook URL.
|
||||
- `channels.zalo.accounts.<id>.webhookSecret`: 계정별 webhook secret.
|
||||
- `channels.zalo.accounts.<id>.webhookPath`: 계정별 webhook 경로.
|
||||
- `channels.zalo.accounts.<id>.proxy`: 계정별 프록시 URL.
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [Channels Overview](/channels) — 지원되는 모든 채널
|
||||
- [Pairing](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [Groups](/channels/groups) — 그룹 채팅 동작 및 mention 게이팅
|
||||
- [Channel Routing](/channels/channel-routing) — 메시지의 세션 라우팅
|
||||
- [Security](/gateway/security) — 액세스 모델 및 강화
|
||||
202
docs/ko/channels/zalouser.md
Normal file
202
docs/ko/channels/zalouser.md
Normal file
@ -0,0 +1,202 @@
|
||||
---
|
||||
read_when:
|
||||
- OpenClaw용 Zalo Personal을 설정할 때
|
||||
- Zalo Personal 로그인 또는 메시지 흐름을 디버깅할 때
|
||||
summary: native `zca-js`(QR 로그인)를 통한 Zalo 개인 계정 지원, 기능 및 구성
|
||||
title: Zalo Personal
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:17Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 331b95041463185472d242cb0a944972f0a8e99df8120bda6350eca86ad5963f
|
||||
source_path: channels/zalouser.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Zalo Personal (비공식)
|
||||
|
||||
상태: 실험적. 이 통합은 OpenClaw 내부에서 native `zca-js`를 통해 **개인 Zalo 계정**을 자동화합니다.
|
||||
|
||||
> **경고:** 이는 비공식 통합이며 계정 정지/차단으로 이어질 수 있습니다. 본인 책임하에 사용하세요.
|
||||
|
||||
## 번들 plugin
|
||||
|
||||
Zalo Personal은 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 있으므로, 일반적인
|
||||
패키지 빌드에서는 별도 설치가 필요하지 않습니다.
|
||||
|
||||
이전 빌드 또는 Zalo Personal이 제외된 사용자 지정 설치를 사용 중이라면
|
||||
수동으로 설치하세요:
|
||||
|
||||
- CLI로 설치: `openclaw plugins install @openclaw/zalouser`
|
||||
- 또는 소스 체크아웃에서 설치: `openclaw plugins install ./path/to/local/zalouser-plugin`
|
||||
- 자세한 내용: [Plugins](/tools/plugin)
|
||||
|
||||
외부 `zca`/`openzca` CLI 바이너리는 필요하지 않습니다.
|
||||
|
||||
## 빠른 설정(초보자용)
|
||||
|
||||
1. Zalo Personal plugin을 사용할 수 있는지 확인합니다.
|
||||
- 현재 패키지된 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다.
|
||||
- 이전/사용자 지정 설치는 위 명령으로 수동 추가할 수 있습니다.
|
||||
2. 로그인합니다(QR, 게이트웨이 머신에서):
|
||||
- `openclaw channels login --channel zalouser`
|
||||
- Zalo 모바일 앱으로 QR 코드를 스캔합니다.
|
||||
3. 채널을 활성화합니다:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
zalouser: {
|
||||
enabled: true,
|
||||
dmPolicy: "pairing",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
4. 게이트웨이를 재시작합니다(또는 설정을 완료합니다).
|
||||
5. DM 액세스는 기본적으로 pairing이며, 첫 연락 시 페어링 코드를 승인합니다.
|
||||
|
||||
## 개요
|
||||
|
||||
- 전부 `zca-js`를 통해 인프로세스로 실행됩니다.
|
||||
- native 이벤트 리스너를 사용해 수신 메시지를 받습니다.
|
||||
- JS API를 통해 직접 응답을 전송합니다(텍스트/미디어/링크).
|
||||
- Zalo Bot API를 사용할 수 없는 “개인 계정” 사용 사례를 위해 설계되었습니다.
|
||||
|
||||
## 이름 지정
|
||||
|
||||
채널 id는 **비공식적인 개인 Zalo 사용자 계정**을 자동화한다는 점을 명확히 하기 위해 `zalouser`입니다. `zalo`는 향후 공식 Zalo API 통합 가능성을 위해 예약해 둡니다.
|
||||
|
||||
## ID 찾기(디렉터리)
|
||||
|
||||
디렉터리 CLI를 사용해 피어/그룹과 해당 ID를 찾으세요:
|
||||
|
||||
```bash
|
||||
openclaw directory self --channel zalouser
|
||||
openclaw directory peers list --channel zalouser --query "name"
|
||||
openclaw directory groups list --channel zalouser --query "work"
|
||||
```
|
||||
|
||||
## 제한 사항
|
||||
|
||||
- 발신 텍스트는 ~2000자로 청크 처리됩니다(Zalo 클라이언트 제한).
|
||||
- 스트리밍은 기본적으로 차단됩니다.
|
||||
|
||||
## 액세스 제어(DM)
|
||||
|
||||
`channels.zalouser.dmPolicy`는 다음을 지원합니다: `pairing | allowlist | open | disabled` (기본값: `pairing`).
|
||||
|
||||
`channels.zalouser.allowFrom`은 사용자 ID 또는 이름을 받습니다. 설정 중에는 plugin의 인프로세스 연락처 조회를 사용해 이름을 ID로 확인합니다.
|
||||
|
||||
다음을 통해 승인합니다:
|
||||
|
||||
- `openclaw pairing list zalouser`
|
||||
- `openclaw pairing approve zalouser <code>`
|
||||
|
||||
## 그룹 액세스(선택 사항)
|
||||
|
||||
- 기본값: `channels.zalouser.groupPolicy = "open"` (그룹 허용). 설정되지 않은 경우 기본값을 재정의하려면 `channels.defaults.groupPolicy`를 사용하세요.
|
||||
- 허용 목록으로 제한하려면:
|
||||
- `channels.zalouser.groupPolicy = "allowlist"`
|
||||
- `channels.zalouser.groups` (키는 안정적인 그룹 ID여야 하며, 가능하면 시작 시 이름이 ID로 확인됩니다)
|
||||
- `channels.zalouser.groupAllowFrom` (허용된 그룹에서 어떤 발신자가 봇을 트리거할 수 있는지 제어)
|
||||
- 모든 그룹 차단: `channels.zalouser.groupPolicy = "disabled"`.
|
||||
- 구성 마법사는 그룹 허용 목록을 물어볼 수 있습니다.
|
||||
- 시작 시 OpenClaw는 허용 목록의 그룹/사용자 이름을 ID로 확인하고 그 매핑을 로그에 남깁니다.
|
||||
- 그룹 허용 목록 일치는 기본적으로 ID 전용입니다. `channels.zalouser.dangerouslyAllowNameMatching: true`가 활성화되지 않으면 확인되지 않은 이름은 인증에서 무시됩니다.
|
||||
- `channels.zalouser.dangerouslyAllowNameMatching: true`는 변경 가능한 그룹 이름 일치를 다시 활성화하는 비상 호환 모드입니다.
|
||||
- `groupAllowFrom`이 설정되지 않은 경우 런타임은 그룹 발신자 검사에 `allowFrom`으로 대체합니다.
|
||||
- 발신자 검사는 일반 그룹 메시지와 제어 명령(예: `/new`, `/reset`) 모두에 적용됩니다.
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
zalouser: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["1471383327500481391"],
|
||||
groups: {
|
||||
"123456789": { allow: true },
|
||||
"Work Chat": { allow: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 그룹 멘션 게이팅
|
||||
|
||||
- `channels.zalouser.groups.<group>.requireMention`은 그룹 응답에 멘션이 필요한지 제어합니다.
|
||||
- 확인 순서: 정확한 그룹 id/이름 -> 정규화된 그룹 slug -> `*` -> 기본값 (`true`).
|
||||
- 이는 허용 목록 그룹과 open 그룹 모드 모두에 적용됩니다.
|
||||
- 권한 있는 제어 명령(예: `/new`)은 멘션 게이팅을 우회할 수 있습니다.
|
||||
- 그룹 메시지가 멘션 필요 때문에 건너뛰어지면 OpenClaw는 이를 보류 중인 그룹 기록으로 저장하고 다음에 처리되는 그룹 메시지에 포함합니다.
|
||||
- 그룹 기록 제한은 기본적으로 `messages.groupChat.historyLimit`(대체값 `50`)입니다. 계정별로 `channels.zalouser.historyLimit`로 재정의할 수 있습니다.
|
||||
|
||||
예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
zalouser: {
|
||||
groupPolicy: "allowlist",
|
||||
groups: {
|
||||
"*": { allow: true, requireMention: true },
|
||||
"Work Chat": { allow: true, requireMention: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 다중 계정
|
||||
|
||||
계정은 OpenClaw 상태의 `zalouser` 프로필에 매핑됩니다. 예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
zalouser: {
|
||||
enabled: true,
|
||||
defaultAccount: "default",
|
||||
accounts: {
|
||||
work: { enabled: true, profile: "work" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 입력 중, 반응 및 전달 확인
|
||||
|
||||
- OpenClaw는 응답을 전송하기 전에 입력 중 이벤트를 보냅니다(best-effort).
|
||||
- 메시지 반응 액션 `react`는 채널 액션에서 `zalouser`에 대해 지원됩니다.
|
||||
- 메시지에서 특정 반응 이모지를 제거하려면 `remove: true`를 사용하세요.
|
||||
- 반응 의미 체계: [Reactions](/tools/reactions)
|
||||
- 이벤트 메타데이터가 포함된 수신 메시지에 대해서는 OpenClaw가 전달됨 + 확인함 확인 응답을 보냅니다(best-effort).
|
||||
|
||||
## 문제 해결
|
||||
|
||||
**로그인이 유지되지 않음:**
|
||||
|
||||
- `openclaw channels status --probe`
|
||||
- 다시 로그인: `openclaw channels logout --channel zalouser && openclaw channels login --channel zalouser`
|
||||
|
||||
**허용 목록/그룹 이름이 확인되지 않음:**
|
||||
|
||||
- `allowFrom`/`groupAllowFrom`/`groups`에 숫자 ID를 사용하거나, 정확한 친구/그룹 이름을 사용하세요.
|
||||
|
||||
**이전 CLI 기반 설정에서 업그레이드함:**
|
||||
|
||||
- 기존 외부 `zca` 프로세스 가정을 제거하세요.
|
||||
- 이제 이 채널은 외부 CLI 바이너리 없이 OpenClaw 내부에서 완전히 실행됩니다.
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [채널 개요](/channels) — 지원되는 모든 채널
|
||||
- [페어링](/channels/pairing) — DM 인증 및 페어링 흐름
|
||||
- [그룹](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅
|
||||
- [채널 라우팅](/channels/channel-routing) — 메시지용 세션 라우팅
|
||||
- [보안](/gateway/security) — 액세스 모델 및 강화
|
||||
73
docs/ko/ci.md
Normal file
73
docs/ko/ci.md
Normal file
@ -0,0 +1,73 @@
|
||||
---
|
||||
read_when:
|
||||
- CI 작업이 실행되었거나 실행되지 않은 이유를 이해해야 할 때
|
||||
- 실패한 GitHub Actions 검사를 디버깅할 때
|
||||
summary: CI 작업 그래프, 범위 게이트, 그리고 로컬 명령 대응 항목
|
||||
title: CI 파이프라인
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:09Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 5a95b6e584b4309bc249866ea436b4dfe30e0298ab8916eadbc344edae3d1194
|
||||
source_path: ci.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# CI 파이프라인
|
||||
|
||||
CI는 `main`에 대한 모든 push와 모든 pull request에서 실행됩니다. 관련 없는 영역만 변경되었을 때 비용이 큰 작업을 건너뛰도록 스마트 범위 지정을 사용합니다.
|
||||
|
||||
## 작업 개요
|
||||
|
||||
| 작업 | 목적 | 실행 시점 |
|
||||
| ------------------------ | ---------------------------------------------------------------------------------------- | ----------------------------------- |
|
||||
| `preflight` | 문서 전용 변경, 변경된 범위, 변경된 확장, 그리고 CI 매니페스트 빌드를 감지 | 초안이 아닌 모든 push 및 PR에서 항상 실행 |
|
||||
| `security-fast` | 비공개 키 감지, `zizmor`를 통한 워크플로 감사, 프로덕션 의존성 감사 | 초안이 아닌 모든 push 및 PR에서 항상 실행 |
|
||||
| `build-artifacts` | `dist/`와 Control UI를 한 번 빌드하고, 후속 작업을 위한 재사용 가능한 아티팩트를 업로드 | Node 관련 변경 |
|
||||
| `checks-fast-core` | 번들/플러그인 계약/프로토콜 검사 같은 빠른 Linux 정확성 레인 | Node 관련 변경 |
|
||||
| `checks-fast-extensions` | `checks-fast-extensions-shard` 완료 후 확장 샤드 레인 집계 | Node 관련 변경 |
|
||||
| `extension-fast` | 변경된 번들 plugin에 대해서만 집중 테스트 실행 | 확장 변경이 감지될 때 |
|
||||
| `check` | CI의 기본 로컬 게이트: `pnpm check` + `pnpm build:strict-smoke` | Node 관련 변경 |
|
||||
| `check-additional` | 아키텍처 및 경계 가드와 게이트웨이 watch 회귀 하네스 | Node 관련 변경 |
|
||||
| `build-smoke` | 빌드된 CLI 스모크 테스트 및 시작 메모리 스모크 | Node 관련 변경 |
|
||||
| `checks` | 더 무거운 Linux Node 레인: 전체 테스트, 채널 테스트, 그리고 push 전용 Node 22 호환성 | Node 관련 변경 |
|
||||
| `check-docs` | 문서 포맷팅, lint, 깨진 링크 검사 | 문서가 변경되었을 때 |
|
||||
| `skills-python` | Python 기반 Skills에 대한 Ruff + pytest | Python Skills 관련 변경 |
|
||||
| `checks-windows` | Windows 전용 테스트 레인 | Windows 관련 변경 |
|
||||
| `macos-node` | 공유 빌드 아티팩트를 사용하는 macOS TypeScript 테스트 레인 | macOS 관련 변경 |
|
||||
| `macos-swift` | macOS 앱용 Swift lint, 빌드, 테스트 | macOS 관련 변경 |
|
||||
| `android` | Android 빌드 및 테스트 매트릭스 | Android 관련 변경 |
|
||||
|
||||
## Fail-Fast 순서
|
||||
|
||||
작업은 비용이 큰 작업이 실행되기 전에 저렴한 검사가 먼저 실패하도록 순서가 정해져 있습니다.
|
||||
|
||||
1. `preflight`가 어떤 레인이 아예 존재하는지를 결정합니다. `docs-scope`와 `changed-scope` 로직은 독립 작업이 아니라 이 작업 내부의 단계입니다.
|
||||
2. `security-fast`, `check`, `check-additional`, `check-docs`, `skills-python`은 더 무거운 아티팩트 및 플랫폼 매트릭스 작업을 기다리지 않고 빠르게 실패합니다.
|
||||
3. `build-artifacts`는 빠른 Linux 레인과 겹쳐 실행되므로, 후속 소비자는 공유 빌드가 준비되는 즉시 시작할 수 있습니다.
|
||||
4. 그다음 더 무거운 플랫폼 및 런타임 레인이 분기됩니다: `checks-fast-core`, `checks-fast-extensions`, `extension-fast`, `checks`, `checks-windows`, `macos-node`, `macos-swift`, `android`.
|
||||
|
||||
범위 로직은 `scripts/ci-changed-scope.mjs`에 있으며 `src/scripts/ci-changed-scope.test.ts`의 단위 테스트로 검증됩니다.
|
||||
별도의 `install-smoke` 워크플로는 자체 `preflight` 작업을 통해 동일한 범위 스크립트를 재사용합니다. 이는 더 좁은 changed-smoke 신호에서 `run_install_smoke`를 계산하므로, Docker/install smoke는 설치, 패키징, 컨테이너 관련 변경에 대해서만 실행됩니다.
|
||||
|
||||
push에서는 `checks` 매트릭스에 push 전용 `compat-node22` 레인이 추가됩니다. pull request에서는 이 레인이 건너뛰어지고, 매트릭스는 일반 테스트/채널 레인에 집중된 상태를 유지합니다.
|
||||
|
||||
## 러너
|
||||
|
||||
| 러너 | 작업 |
|
||||
| -------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| `blacksmith-16vcpu-ubuntu-2404` | `preflight`, `security-fast`, `build-artifacts`, Linux 검사, 문서 검사, Python Skills, `android` |
|
||||
| `blacksmith-32vcpu-windows-2025` | `checks-windows` |
|
||||
| `macos-latest` | `macos-node`, `macos-swift` |
|
||||
|
||||
## 로컬 대응 명령
|
||||
|
||||
```bash
|
||||
pnpm check # types + lint + format
|
||||
pnpm build:strict-smoke
|
||||
pnpm test:gateway:watch-regression
|
||||
pnpm test # vitest tests
|
||||
pnpm test:channels
|
||||
pnpm check:docs # docs format + lint + broken links
|
||||
pnpm build # CI artifact/build-smoke 레인이 중요할 때 dist 빌드
|
||||
```
|
||||
292
docs/ko/cli/acp.md
Normal file
292
docs/ko/cli/acp.md
Normal file
@ -0,0 +1,292 @@
|
||||
---
|
||||
read_when:
|
||||
- ACP 기반 IDE 통합을 설정할 때
|
||||
- Gateway로의 ACP 세션 라우팅을 디버깅할 때
|
||||
summary: IDE 통합용 ACP 브리지 실행
|
||||
title: acp
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:39Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 2461b181e4a97dd84580581e9436ca1947a224decce8044132dbcf7fb2b7502c
|
||||
source_path: cli/acp.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# acp
|
||||
|
||||
OpenClaw Gateway와 통신하는 [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) 브리지를 실행합니다.
|
||||
|
||||
이 명령은 IDE를 위해 stdio를 통해 ACP를 사용하고 프롬프트를 WebSocket을 통해 Gateway로 전달합니다. ACP 세션이 Gateway 세션 키에 매핑되도록 유지합니다.
|
||||
|
||||
`openclaw acp`는 Gateway 기반 ACP 브리지이며, 완전한 ACP 네이티브 편집기 런타임은 아닙니다. 세션 라우팅, 프롬프트 전달, 기본 스트리밍 업데이트에 중점을 둡니다.
|
||||
|
||||
외부 MCP 클라이언트가 ACP 하니스 세션을 호스팅하는 대신 OpenClaw 채널 대화에 직접 연결되게 하려면 [`openclaw mcp serve`](/cli/mcp)를 대신 사용하세요.
|
||||
|
||||
## 이것이 아닌 것
|
||||
|
||||
이 페이지는 종종 ACP 하니스 세션과 혼동됩니다.
|
||||
|
||||
`openclaw acp`의 의미는 다음과 같습니다.
|
||||
|
||||
- OpenClaw가 ACP 서버로 동작함
|
||||
- IDE 또는 ACP 클라이언트가 OpenClaw에 연결함
|
||||
- OpenClaw가 해당 작업을 Gateway 세션으로 전달함
|
||||
|
||||
이는 OpenClaw가 `acpx`를 통해 Codex 또는 Claude Code 같은 외부 하니스를 실행하는 [ACP 에이전트](/tools/acp-agents)와는 다릅니다.
|
||||
|
||||
간단한 기준:
|
||||
|
||||
- 편집기/클라이언트가 ACP로 OpenClaw와 통신하려는 경우: `openclaw acp` 사용
|
||||
- OpenClaw가 Codex/Claude/Gemini를 ACP 하니스로 실행해야 하는 경우: `/acp spawn` 및 [ACP 에이전트](/tools/acp-agents) 사용
|
||||
|
||||
## 호환성 매트릭스
|
||||
|
||||
| ACP 영역 | 상태 | 참고 |
|
||||
| --------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `initialize`, `newSession`, `prompt`, `cancel` | 구현됨 | stdio에서 Gateway chat/send + abort로 이어지는 핵심 브리지 흐름입니다. |
|
||||
| `listSessions`, 슬래시 명령 | 구현됨 | 세션 목록은 Gateway 세션 상태를 기준으로 동작하며, 명령은 `available_commands_update`를 통해 광고됩니다. |
|
||||
| `loadSession` | 부분 지원 | ACP 세션을 Gateway 세션 키에 다시 바인딩하고 저장된 사용자/assistant 텍스트 기록을 재생합니다. 도구/시스템 기록은 아직 재구성되지 않습니다. |
|
||||
| 프롬프트 콘텐츠(`text`, 내장 `resource`, 이미지) | 부분 지원 | 텍스트/리소스는 채팅 입력으로 평탄화되고, 이미지는 Gateway 첨부 파일이 됩니다. |
|
||||
| 세션 모드 | 부분 지원 | `session/set_mode`가 지원되며 브리지는 thought level, tool verbosity, reasoning, usage detail, elevated actions에 대한 초기 Gateway 기반 세션 제어를 노출합니다. 더 광범위한 ACP 네이티브 모드/config 표면은 아직 범위 밖입니다. |
|
||||
| 세션 정보 및 사용량 업데이트 | 부분 지원 | 브리지는 캐시된 Gateway 세션 스냅샷에서 `session_info_update` 및 최선의 노력 방식의 `usage_update` 알림을 내보냅니다. 사용량은 근사치이며 Gateway 토큰 총계가 최신으로 표시될 때만 전송됩니다. |
|
||||
| 도구 스트리밍 | 부분 지원 | `tool_call` / `tool_call_update` 이벤트에는 원시 I/O, 텍스트 콘텐츠, 그리고 Gateway 도구 인자/결과가 이를 노출할 경우 최선의 노력 방식의 파일 위치가 포함됩니다. 내장 터미널과 더 풍부한 diff 네이티브 출력은 아직 노출되지 않습니다. |
|
||||
| 세션별 MCP 서버(`mcpServers`) | 지원되지 않음 | 브리지 모드는 세션별 MCP 서버 요청을 거부합니다. 대신 OpenClaw gateway 또는 agent에서 MCP를 구성하세요. |
|
||||
| 클라이언트 파일시스템 메서드(`fs/read_text_file`, `fs/write_text_file`) | 지원되지 않음 | 브리지는 ACP 클라이언트 파일시스템 메서드를 호출하지 않습니다. |
|
||||
| 클라이언트 터미널 메서드(`terminal/*`) | 지원되지 않음 | 브리지는 ACP 클라이언트 터미널을 생성하거나 tool call을 통해 터미널 ID를 스트리밍하지 않습니다. |
|
||||
| 세션 계획 / thought 스트리밍 | 지원되지 않음 | 브리지는 현재 ACP 계획 또는 thought 업데이트가 아니라 출력 텍스트와 도구 상태를 내보냅니다. |
|
||||
|
||||
## 알려진 제한 사항
|
||||
|
||||
- `loadSession`은 저장된 사용자 및 assistant 텍스트 기록을 재생하지만, 과거 도구 호출, 시스템 알림 또는 더 풍부한 ACP 네이티브 이벤트 유형은 재구성하지 않습니다.
|
||||
- 여러 ACP 클라이언트가 동일한 Gateway 세션 키를 공유하는 경우, 이벤트 및 취소 라우팅은 클라이언트별로 엄격히 격리되지 않고 최선의 노력 방식으로 동작합니다. 편집기 로컬 턴을 깔끔하게 유지해야 한다면 기본 격리된 `acp:<uuid>` 세션을 사용하는 것이 좋습니다.
|
||||
- Gateway 중지 상태는 ACP 중지 사유로 변환되지만, 이 매핑은 완전한 ACP 네이티브 런타임보다 표현력이 떨어집니다.
|
||||
- 초기 세션 제어는 현재 Gateway 노브의 일부에만 집중해 노출합니다: thought level, tool verbosity, reasoning, usage detail, elevated actions. 모델 선택과 exec-host 제어는 아직 ACP config 옵션으로 노출되지 않습니다.
|
||||
- `session_info_update`와 `usage_update`는 실시간 ACP 네이티브 런타임 계정이 아니라 Gateway 세션 스냅샷에서 파생됩니다. 사용량은 근사치이며 비용 데이터는 포함하지 않고, Gateway가 총 토큰 데이터를 최신으로 표시할 때만 전송됩니다.
|
||||
- 도구 추적 데이터는 최선의 노력 방식입니다. 브리지는 알려진 도구 인자/결과에 나타나는 파일 경로를 노출할 수 있지만, ACP 터미널이나 구조화된 파일 diff는 아직 내보내지 않습니다.
|
||||
|
||||
## 사용법
|
||||
|
||||
```bash
|
||||
openclaw acp
|
||||
|
||||
# 원격 Gateway
|
||||
openclaw acp --url wss://gateway-host:18789 --token <token>
|
||||
|
||||
# 원격 Gateway (파일에서 토큰 읽기)
|
||||
openclaw acp --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.token
|
||||
|
||||
# 기존 세션 키에 연결
|
||||
openclaw acp --session agent:main:main
|
||||
|
||||
# 라벨로 연결(이미 존재해야 함)
|
||||
openclaw acp --session-label "support inbox"
|
||||
|
||||
# 첫 번째 프롬프트 전에 세션 키 재설정
|
||||
openclaw acp --session agent:main:main --reset-session
|
||||
```
|
||||
|
||||
## ACP 클라이언트(디버그)
|
||||
|
||||
내장 ACP 클라이언트를 사용하면 IDE 없이 브리지를 기본 점검할 수 있습니다.
|
||||
이 클라이언트는 ACP 브리지를 실행하고 프롬프트를 대화형으로 입력할 수 있게 합니다.
|
||||
|
||||
```bash
|
||||
openclaw acp client
|
||||
|
||||
# 실행된 브리지를 원격 Gateway로 연결
|
||||
openclaw acp client --server-args --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.token
|
||||
|
||||
# 서버 명령 재정의(기본값: openclaw)
|
||||
openclaw acp client --server "node" --server-args openclaw.mjs acp --url ws://127.0.0.1:19001
|
||||
```
|
||||
|
||||
권한 모델(클라이언트 디버그 모드):
|
||||
|
||||
- 자동 승인은 허용 목록 기반이며 신뢰된 핵심 도구 ID에만 적용됩니다.
|
||||
- `read` 자동 승인은 현재 작업 디렉터리(`--cwd`가 설정된 경우) 범위로 제한됩니다.
|
||||
- ACP는 현재 작업 디렉터리 아래의 범위 제한 `read` 호출과 읽기 전용 검색 도구(`search`, `web_search`, `memory_search`) 같은 좁은 읽기 전용 범주만 자동 승인합니다. 알 수 없거나 비핵심 도구, 범위 밖 읽기, 실행 가능한 도구, 컨트롤 플레인 도구, 변경 도구, 대화형 흐름은 항상 명시적인 프롬프트 승인이 필요합니다.
|
||||
- 서버가 제공하는 `toolCall.kind`는 신뢰할 수 없는 메타데이터로 취급되며(권한 부여의 근거가 아님).
|
||||
- 이 ACP 브리지 정책은 ACPX 하니스 권한과 별개입니다. OpenClaw를 `acpx` 백엔드를 통해 실행하는 경우, `plugins.entries.acpx.config.permissionMode=approve-all`이 해당 하니스 세션의 비상 시 “yolo” 스위치입니다.
|
||||
|
||||
## 사용 방법
|
||||
|
||||
IDE(또는 다른 클라이언트)가 Agent Client Protocol을 사용하고, 이를 통해 OpenClaw Gateway 세션을 구동하고 싶을 때 ACP를 사용합니다.
|
||||
|
||||
1. Gateway가 실행 중인지 확인합니다(로컬 또는 원격).
|
||||
2. Gateway 대상(config 또는 플래그)을 구성합니다.
|
||||
3. IDE가 stdio를 통해 `openclaw acp`를 실행하도록 지정합니다.
|
||||
|
||||
예시 config(영구 저장):
|
||||
|
||||
```bash
|
||||
openclaw config set gateway.remote.url wss://gateway-host:18789
|
||||
openclaw config set gateway.remote.token <token>
|
||||
```
|
||||
|
||||
예시 직접 실행(config 쓰기 없음):
|
||||
|
||||
```bash
|
||||
openclaw acp --url wss://gateway-host:18789 --token <token>
|
||||
# 로컬 프로세스 안전 측면에서 권장
|
||||
openclaw acp --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.token
|
||||
```
|
||||
|
||||
## 에이전트 선택
|
||||
|
||||
ACP는 에이전트를 직접 선택하지 않습니다. Gateway 세션 키를 기준으로 라우팅합니다.
|
||||
|
||||
특정 에이전트를 대상으로 하려면 에이전트 범위 세션 키를 사용하세요.
|
||||
|
||||
```bash
|
||||
openclaw acp --session agent:main:main
|
||||
openclaw acp --session agent:design:main
|
||||
openclaw acp --session agent:qa:bug-123
|
||||
```
|
||||
|
||||
각 ACP 세션은 하나의 Gateway 세션 키에 매핑됩니다. 하나의 에이전트는 여러 세션을 가질 수 있으며, ACP는 키나 라벨을 재정의하지 않으면 기본적으로 격리된 `acp:<uuid>` 세션을 사용합니다.
|
||||
|
||||
세션별 `mcpServers`는 브리지 모드에서 지원되지 않습니다. ACP 클라이언트가 `newSession` 또는 `loadSession` 중 이를 보내면, 브리지는 조용히 무시하는 대신 명확한 오류를 반환합니다.
|
||||
|
||||
ACPX 기반 세션이 OpenClaw plugin 도구를 보도록 하려면, 세션별 `mcpServers`를 전달하려 하지 말고 gateway 측 ACPX plugin 브리지를 활성화하세요. 자세한 내용은 [ACP 에이전트](/tools/acp-agents#plugin-tools-mcp-bridge)를 참조하세요.
|
||||
|
||||
## `acpx`에서 사용하기(Codex, Claude, 기타 ACP 클라이언트)
|
||||
|
||||
Codex 또는 Claude Code 같은 코딩 에이전트가 ACP를 통해 OpenClaw bot과 통신하게 하려면, 내장 `openclaw` 대상을 갖춘 `acpx`를 사용하세요.
|
||||
|
||||
일반적인 흐름:
|
||||
|
||||
1. Gateway를 실행하고 ACP 브리지가 여기에 도달할 수 있는지 확인합니다.
|
||||
2. `acpx openclaw`가 `openclaw acp`를 가리키도록 설정합니다.
|
||||
3. 코딩 에이전트가 사용할 OpenClaw 세션 키를 대상으로 지정합니다.
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
# 기본 OpenClaw ACP 세션으로 단발성 요청 보내기
|
||||
acpx openclaw exec "활성 OpenClaw 세션 상태를 요약해 줘."
|
||||
|
||||
# 후속 턴을 위한 지속적 이름 세션
|
||||
acpx openclaw sessions ensure --name codex-bridge
|
||||
acpx openclaw -s codex-bridge --cwd /path/to/repo \
|
||||
"이 리포지토리와 관련된 최근 컨텍스트를 내 OpenClaw 작업 에이전트에 물어봐."
|
||||
```
|
||||
|
||||
`acpx openclaw`가 항상 특정 Gateway와 세션 키를 대상으로 하도록 하려면, `~/.acpx/config.json`에서 `openclaw` agent 명령을 재정의하세요.
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"openclaw": {
|
||||
"command": "env OPENCLAW_HIDE_BANNER=1 OPENCLAW_SUPPRESS_NOTES=1 openclaw acp --url ws://127.0.0.1:18789 --token-file ~/.openclaw/gateway.token --session agent:main:main"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
리포지토리 로컬 OpenClaw 체크아웃의 경우, ACP 스트림을 깨끗하게 유지하기 위해 dev runner 대신 직접 CLI 엔트리포인트를 사용하세요. 예:
|
||||
|
||||
```bash
|
||||
env OPENCLAW_HIDE_BANNER=1 OPENCLAW_SUPPRESS_NOTES=1 node openclaw.mjs acp ...
|
||||
```
|
||||
|
||||
이것이 Codex, Claude Code 또는 다른 ACP 지원 클라이언트가 터미널을 스크래핑하지 않고 OpenClaw 에이전트에서 컨텍스트 정보를 가져오게 하는 가장 쉬운 방법입니다.
|
||||
|
||||
## Zed 편집기 설정
|
||||
|
||||
`~/.config/zed/settings.json`에 사용자 지정 ACP 에이전트를 추가하세요(또는 Zed의 Settings UI 사용):
|
||||
|
||||
```json
|
||||
{
|
||||
"agent_servers": {
|
||||
"OpenClaw ACP": {
|
||||
"type": "custom",
|
||||
"command": "openclaw",
|
||||
"args": ["acp"],
|
||||
"env": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
특정 Gateway 또는 에이전트를 대상으로 지정하려면:
|
||||
|
||||
```json
|
||||
{
|
||||
"agent_servers": {
|
||||
"OpenClaw ACP": {
|
||||
"type": "custom",
|
||||
"command": "openclaw",
|
||||
"args": [
|
||||
"acp",
|
||||
"--url",
|
||||
"wss://gateway-host:18789",
|
||||
"--token",
|
||||
"<token>",
|
||||
"--session",
|
||||
"agent:design:main"
|
||||
],
|
||||
"env": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Zed에서 Agent 패널을 열고 “OpenClaw ACP”를 선택해 스레드를 시작하세요.
|
||||
|
||||
## 세션 매핑
|
||||
|
||||
기본적으로 ACP 세션은 `acp:` 접두사가 있는 격리된 Gateway 세션 키를 받습니다.
|
||||
알려진 세션을 재사용하려면 세션 키 또는 라벨을 전달하세요.
|
||||
|
||||
- `--session <key>`: 특정 Gateway 세션 키 사용
|
||||
- `--session-label <label>`: 기존 세션을 라벨로 해석
|
||||
- `--reset-session`: 해당 키에 대해 새 세션 ID 발급(같은 키, 새 트랜스크립트)
|
||||
|
||||
ACP 클라이언트가 메타데이터를 지원하면 세션별로 재정의할 수 있습니다.
|
||||
|
||||
```json
|
||||
{
|
||||
"_meta": {
|
||||
"sessionKey": "agent:main:main",
|
||||
"sessionLabel": "support inbox",
|
||||
"resetSession": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
세션 키에 대한 자세한 내용은 [/concepts/session](/concepts/session)을 참조하세요.
|
||||
|
||||
## 옵션
|
||||
|
||||
- `--url <url>`: Gateway WebSocket URL(configured 시 기본값은 gateway.remote.url)
|
||||
- `--token <token>`: Gateway 인증 토큰
|
||||
- `--token-file <path>`: 파일에서 Gateway 인증 토큰 읽기
|
||||
- `--password <password>`: Gateway 인증 비밀번호
|
||||
- `--password-file <path>`: 파일에서 Gateway 인증 비밀번호 읽기
|
||||
- `--session <key>`: 기본 세션 키
|
||||
- `--session-label <label>`: 해석할 기본 세션 라벨
|
||||
- `--require-existing`: 세션 키/라벨이 존재하지 않으면 실패
|
||||
- `--reset-session`: 첫 사용 전에 세션 키 재설정
|
||||
- `--no-prefix-cwd`: 프롬프트 앞에 작업 디렉터리를 접두사로 붙이지 않음
|
||||
- `--provenance <off|meta|meta+receipt>`: ACP provenance 메타데이터 또는 영수증 포함
|
||||
- `--verbose, -v`: stderr에 상세 로그 출력
|
||||
|
||||
보안 참고:
|
||||
|
||||
- 일부 시스템에서는 `--token`과 `--password`가 로컬 프로세스 목록에 표시될 수 있습니다.
|
||||
- `--token-file`/`--password-file` 또는 환경 변수(`OPENCLAW_GATEWAY_TOKEN`, `OPENCLAW_GATEWAY_PASSWORD`) 사용을 권장합니다.
|
||||
- Gateway 인증 해석은 다른 Gateway 클라이언트가 사용하는 공통 계약을 따릅니다.
|
||||
- 로컬 모드: env (`OPENCLAW_GATEWAY_*`) -> `gateway.auth.*` -> `gateway.remote.*` 폴백은 `gateway.auth.*`가 설정되지 않은 경우에만 적용(설정되었지만 해석되지 않은 로컬 SecretRef는 fail closed)
|
||||
- 원격 모드: 원격 우선순위 규칙에 따른 env/config 폴백과 함께 `gateway.remote.*`
|
||||
- `--url`은 override-safe이며 암시적 config/env 자격 증명을 재사용하지 않습니다. 명시적인 `--token`/`--password`(또는 파일 변형)를 전달하세요.
|
||||
- ACP 런타임 백엔드 자식 프로세스는 `OPENCLAW_SHELL=acp`를 받으며, 이는 컨텍스트별 셸/프로필 규칙에 사용할 수 있습니다.
|
||||
- `openclaw acp client`는 실행된 브리지 프로세스에 `OPENCLAW_SHELL=acp-client`를 설정합니다.
|
||||
|
||||
### `acp client` 옵션
|
||||
|
||||
- `--cwd <dir>`: ACP 세션의 작업 디렉터리
|
||||
- `--server <command>`: ACP 서버 명령(기본값: `openclaw`)
|
||||
- `--server-args <args...>`: ACP 서버에 전달할 추가 인수
|
||||
- `--server-verbose`: ACP 서버에서 상세 로그 활성화
|
||||
- `--verbose, -v`: 상세 클라이언트 로그
|
||||
64
docs/ko/cli/agent.md
Normal file
64
docs/ko/cli/agent.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
read_when:
|
||||
- 스크립트에서 하나의 에이전트 턴을 실행하려는 경우(선택적으로 응답 전달)
|
||||
summary: Gateway를 통해 하나의 에이전트 턴을 보내는 `openclaw agent`용 CLI 참조
|
||||
title: agent
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:12Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 0627f943bc7f3556318008f76dc6150788cf06927dccdc7d2681acb98f257d56
|
||||
source_path: cli/agent.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw agent`
|
||||
|
||||
Gateway를 통해 에이전트 턴을 실행합니다(임베디드 실행에는 `--local` 사용).
|
||||
구성된 에이전트를 직접 대상으로 지정하려면 `--agent <id>`를 사용하세요.
|
||||
|
||||
다음 세션 선택자 중 하나 이상을 전달해야 합니다.
|
||||
|
||||
- `--to <dest>`
|
||||
- `--session-id <id>`
|
||||
- `--agent <id>`
|
||||
|
||||
관련 항목:
|
||||
|
||||
- 에이전트 전송 도구: [Agent send](/tools/agent-send)
|
||||
|
||||
## 옵션
|
||||
|
||||
- `-m, --message <text>`: 필수 메시지 본문
|
||||
- `-t, --to <dest>`: 세션 키를 도출하는 데 사용되는 수신자
|
||||
- `--session-id <id>`: 명시적 세션 ID
|
||||
- `--agent <id>`: 에이전트 ID, 라우팅 바인딩을 재정의함
|
||||
- `--thinking <off|minimal|low|medium|high|xhigh>`: 에이전트 사고 수준
|
||||
- `--verbose <on|off>`: 세션에 대해 verbose 수준을 유지
|
||||
- `--channel <channel>`: 전달 채널, 생략하면 기본 세션 채널 사용
|
||||
- `--reply-to <target>`: 전달 대상 재정의
|
||||
- `--reply-channel <channel>`: 전달 채널 재정의
|
||||
- `--reply-account <id>`: 전달 계정 재정의
|
||||
- `--local`: 임베디드 에이전트를 직접 실행(플러그인 레지스트리 사전 로드 후)
|
||||
- `--deliver`: 선택한 채널/대상으로 응답 다시 전송
|
||||
- `--timeout <seconds>`: 에이전트 시간 제한 재정의(기본값 600 또는 config 값)
|
||||
- `--json`: JSON 출력
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw agent --to +15555550123 --message "status update" --deliver
|
||||
openclaw agent --agent ops --message "Summarize logs"
|
||||
openclaw agent --session-id 1234 --message "Summarize inbox" --thinking medium
|
||||
openclaw agent --to +15555550123 --message "Trace logs" --verbose on --json
|
||||
openclaw agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"
|
||||
openclaw agent --agent ops --message "Run locally" --local
|
||||
```
|
||||
|
||||
## 참고
|
||||
|
||||
- Gateway 모드는 Gateway 요청이 실패하면 임베디드 에이전트로 대체됩니다. 처음부터 임베디드 실행을 강제하려면 `--local`을 사용하세요.
|
||||
- `--local`은 여전히 먼저 플러그인 레지스트리를 사전 로드하므로, 플러그인이 제공하는 provider, 도구, 채널을 임베디드 실행 중에도 계속 사용할 수 있습니다.
|
||||
- `--channel`, `--reply-channel`, `--reply-account`는 세션 라우팅이 아니라 응답 전달에 영향을 줍니다.
|
||||
- 이 명령이 `models.json` 재생성을 트리거하면, SecretRef로 관리되는 provider 자격 증명은 해석된 시크릿 평문이 아니라 비시크릿 마커(예: env var 이름, `secretref-env:ENV_VAR_NAME`, 또는 `secretref-managed`)로 유지됩니다.
|
||||
- 마커 쓰기는 소스 권위적입니다. OpenClaw는 해석된 런타임 시크릿 값이 아니라 활성 소스 config 스냅샷의 마커를 유지합니다.
|
||||
227
docs/ko/cli/agents.md
Normal file
227
docs/ko/cli/agents.md
Normal file
@ -0,0 +1,227 @@
|
||||
---
|
||||
read_when:
|
||||
- 여러 개의 격리된 에이전트(워크스페이스 + 라우팅 + 인증)가 필요할 때
|
||||
summary: '`openclaw agents`용 CLI 참조(list/add/delete/bindings/bind/unbind/set identity)'
|
||||
title: agents
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:28Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 90b90c4915993bd8af322c0590d4cb59baabb8940598ce741315f8f95ef43179
|
||||
source_path: cli/agents.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw agents`
|
||||
|
||||
격리된 에이전트(워크스페이스 + 인증 + 라우팅)를 관리합니다.
|
||||
|
||||
관련 항목:
|
||||
|
||||
- 멀티 에이전트 라우팅: [Multi-Agent Routing](/concepts/multi-agent)
|
||||
- 에이전트 워크스페이스: [Agent workspace](/concepts/agent-workspace)
|
||||
- Skills 가시성 구성: [Skills config](/tools/skills-config)
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw agents list
|
||||
openclaw agents list --bindings
|
||||
openclaw agents add work --workspace ~/.openclaw/workspace-work
|
||||
openclaw agents add ops --workspace ~/.openclaw/workspace-ops --bind telegram:ops --non-interactive
|
||||
openclaw agents bindings
|
||||
openclaw agents bind --agent work --bind telegram:ops
|
||||
openclaw agents unbind --agent work --bind telegram:ops
|
||||
openclaw agents set-identity --workspace ~/.openclaw/workspace --from-identity
|
||||
openclaw agents set-identity --agent main --avatar avatars/openclaw.png
|
||||
openclaw agents delete work
|
||||
```
|
||||
|
||||
## 라우팅 바인딩
|
||||
|
||||
인바운드 채널 트래픽을 특정 에이전트에 고정하려면 라우팅 바인딩을 사용하세요.
|
||||
|
||||
에이전트별로 서로 다른 표시 Skills도 원한다면,
|
||||
`openclaw.json`에서 `agents.defaults.skills`와 `agents.list[].skills`를 구성하세요. 자세한 내용은
|
||||
[Skills config](/tools/skills-config) 및
|
||||
[Configuration Reference](/gateway/configuration-reference#agentsdefaultsskills)를 참조하세요.
|
||||
|
||||
바인딩 나열:
|
||||
|
||||
```bash
|
||||
openclaw agents bindings
|
||||
openclaw agents bindings --agent work
|
||||
openclaw agents bindings --json
|
||||
```
|
||||
|
||||
바인딩 추가:
|
||||
|
||||
```bash
|
||||
openclaw agents bind --agent work --bind telegram:ops --bind discord:guild-a
|
||||
```
|
||||
|
||||
`accountId`를 생략하면(`--bind <channel>`), OpenClaw는 가능할 때 채널 기본값과 plugin 설정 훅에서 이를 해석합니다.
|
||||
|
||||
`bind` 또는 `unbind`에서 `--agent`를 생략하면 OpenClaw는 현재 기본 에이전트를 대상으로 합니다.
|
||||
|
||||
### 바인딩 범위 동작
|
||||
|
||||
- `accountId`가 없는 바인딩은 채널 기본 계정에만 일치합니다.
|
||||
- `accountId: "*"`는 채널 전체 대체값(모든 계정)이며, 명시적 계정 바인딩보다 덜 구체적입니다.
|
||||
- 동일한 에이전트에 이미 `accountId` 없는 일치하는 채널 바인딩이 있고, 나중에 명시적이거나 해석된 `accountId`로 바인딩하면, OpenClaw는 중복을 추가하는 대신 기존 바인딩을 제자리에서 업그레이드합니다.
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
# initial channel-only binding
|
||||
openclaw agents bind --agent work --bind telegram
|
||||
|
||||
# later upgrade to account-scoped binding
|
||||
openclaw agents bind --agent work --bind telegram:ops
|
||||
```
|
||||
|
||||
업그레이드 후 해당 바인딩의 라우팅은 `telegram:ops` 범위로 제한됩니다. 기본 계정 라우팅도 원한다면 명시적으로 추가하세요(예: `--bind telegram:default`).
|
||||
|
||||
바인딩 제거:
|
||||
|
||||
```bash
|
||||
openclaw agents unbind --agent work --bind telegram:ops
|
||||
openclaw agents unbind --agent work --all
|
||||
```
|
||||
|
||||
`unbind`는 `--all` 또는 하나 이상의 `--bind` 값 중 하나만 받을 수 있으며, 둘 다 함께 사용할 수는 없습니다.
|
||||
|
||||
## 명령 표면
|
||||
|
||||
### `agents`
|
||||
|
||||
하위 명령 없이 `openclaw agents`를 실행하는 것은 `openclaw agents list`와 같습니다.
|
||||
|
||||
### `agents list`
|
||||
|
||||
옵션:
|
||||
|
||||
- `--json`
|
||||
- `--bindings`: 에이전트별 개수/요약만이 아니라 전체 라우팅 규칙 포함
|
||||
|
||||
### `agents add [name]`
|
||||
|
||||
옵션:
|
||||
|
||||
- `--workspace <dir>`
|
||||
- `--model <id>`
|
||||
- `--agent-dir <dir>`
|
||||
- `--bind <channel[:accountId]>`(반복 가능)
|
||||
- `--non-interactive`
|
||||
- `--json`
|
||||
|
||||
참고:
|
||||
|
||||
- 명시적인 add 플래그를 하나라도 전달하면 명령은 non-interactive 경로로 전환됩니다.
|
||||
- Non-interactive 모드에서는 에이전트 이름과 `--workspace`가 모두 필요합니다.
|
||||
- `main`은 예약되어 있으며 새 에이전트 ID로 사용할 수 없습니다.
|
||||
|
||||
### `agents bindings`
|
||||
|
||||
옵션:
|
||||
|
||||
- `--agent <id>`
|
||||
- `--json`
|
||||
|
||||
### `agents bind`
|
||||
|
||||
옵션:
|
||||
|
||||
- `--agent <id>`(기본값은 현재 기본 에이전트)
|
||||
- `--bind <channel[:accountId]>`(반복 가능)
|
||||
- `--json`
|
||||
|
||||
### `agents unbind`
|
||||
|
||||
옵션:
|
||||
|
||||
- `--agent <id>`(기본값은 현재 기본 에이전트)
|
||||
- `--bind <channel[:accountId]>`(반복 가능)
|
||||
- `--all`
|
||||
- `--json`
|
||||
|
||||
### `agents delete <id>`
|
||||
|
||||
옵션:
|
||||
|
||||
- `--force`
|
||||
- `--json`
|
||||
|
||||
참고:
|
||||
|
||||
- `main`은 삭제할 수 없습니다.
|
||||
- `--force`가 없으면 대화형 확인이 필요합니다.
|
||||
- 워크스페이스, 에이전트 상태, 세션 transcript 디렉터리는 영구 삭제되지 않고 휴지통으로 이동됩니다.
|
||||
|
||||
## identity 파일
|
||||
|
||||
각 에이전트 워크스페이스는 워크스페이스 루트에 `IDENTITY.md`를 포함할 수 있습니다.
|
||||
|
||||
- 예시 경로: `~/.openclaw/workspace/IDENTITY.md`
|
||||
- `set-identity --from-identity`는 워크스페이스 루트(또는 명시적인 `--identity-file`)에서 읽습니다
|
||||
|
||||
아바타 경로는 워크스페이스 루트를 기준으로 해석됩니다.
|
||||
|
||||
## identity 설정
|
||||
|
||||
`set-identity`는 필드를 `agents.list[].identity`에 기록합니다.
|
||||
|
||||
- `name`
|
||||
- `theme`
|
||||
- `emoji`
|
||||
- `avatar`(워크스페이스 상대 경로, http(s) URL, 또는 data URI)
|
||||
|
||||
옵션:
|
||||
|
||||
- `--agent <id>`
|
||||
- `--workspace <dir>`
|
||||
- `--identity-file <path>`
|
||||
- `--from-identity`
|
||||
- `--name <name>`
|
||||
- `--theme <theme>`
|
||||
- `--emoji <emoji>`
|
||||
- `--avatar <value>`
|
||||
- `--json`
|
||||
|
||||
참고:
|
||||
|
||||
- 대상 에이전트를 선택하려면 `--agent` 또는 `--workspace`를 사용할 수 있습니다.
|
||||
- `--workspace`에 의존하는데 여러 에이전트가 해당 워크스페이스를 공유하면, 명령은 실패하고 `--agent`를 전달하라고 안내합니다.
|
||||
- 명시적인 identity 필드가 제공되지 않으면, 명령은 `IDENTITY.md`에서 identity 데이터를 읽습니다.
|
||||
|
||||
`IDENTITY.md`에서 로드:
|
||||
|
||||
```bash
|
||||
openclaw agents set-identity --workspace ~/.openclaw/workspace --from-identity
|
||||
```
|
||||
|
||||
필드를 명시적으로 재정의:
|
||||
|
||||
```bash
|
||||
openclaw agents set-identity --agent main --name "OpenClaw" --emoji "🦞" --avatar avatars/openclaw.png
|
||||
```
|
||||
|
||||
구성 예시:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "main",
|
||||
identity: {
|
||||
name: "OpenClaw",
|
||||
theme: "space lobster",
|
||||
emoji: "🦞",
|
||||
avatar: "avatars/openclaw.png",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
143
docs/ko/cli/approvals.md
Normal file
143
docs/ko/cli/approvals.md
Normal file
@ -0,0 +1,143 @@
|
||||
---
|
||||
read_when:
|
||||
- CLI에서 exec 승인을 편집하려는 경우
|
||||
- 게이트웨이 또는 노드 호스트의 허용 목록을 관리해야 하는 경우
|
||||
summary: 게이트웨이 또는 노드 호스트의 exec 승인을 위한 `openclaw approvals` CLI 참조
|
||||
title: approvals
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:26Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 7b2532bfd3e6e6ce43c96a2807df2dd00cb7b4320b77a7dfd09bee0531da610e
|
||||
source_path: cli/approvals.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw approvals`
|
||||
|
||||
**로컬 호스트**, **게이트웨이 호스트**, 또는 **노드 호스트**의 exec 승인을 관리합니다.
|
||||
기본적으로 명령은 디스크의 로컬 approvals 파일을 대상으로 합니다. 게이트웨이를 대상으로 하려면 `--gateway`를, 특정 노드를 대상으로 하려면 `--node`를 사용하세요.
|
||||
|
||||
별칭: `openclaw exec-approvals`
|
||||
|
||||
관련 항목:
|
||||
|
||||
- Exec approvals: [Exec approvals](/tools/exec-approvals)
|
||||
- Nodes: [Nodes](/nodes)
|
||||
|
||||
## 일반 명령
|
||||
|
||||
```bash
|
||||
openclaw approvals get
|
||||
openclaw approvals get --node <id|name|ip>
|
||||
openclaw approvals get --gateway
|
||||
```
|
||||
|
||||
이제 `openclaw approvals get`은 로컬, 게이트웨이, 노드 대상에 대한 유효한 exec 정책을 표시합니다.
|
||||
|
||||
- 요청된 `tools.exec` 정책
|
||||
- 호스트 approvals-file 정책
|
||||
- 우선순위 규칙 적용 후의 유효 결과
|
||||
|
||||
우선순위는 의도된 동작입니다.
|
||||
|
||||
- 호스트 approvals 파일은 강제 가능한 기준 정보입니다
|
||||
- 요청된 `tools.exec` 정책은 의도를 더 좁히거나 넓힐 수 있지만, 유효 결과는 여전히 호스트 규칙에서 파생됩니다
|
||||
- `--node`는 노드 호스트 approvals 파일과 게이트웨이 `tools.exec` 정책을 결합합니다. 둘 다 런타임에 계속 적용되기 때문입니다
|
||||
- 게이트웨이 config를 사용할 수 없으면 CLI는 노드 approvals 스냅샷으로 대체하고 최종 런타임 정책을 계산할 수 없었다고 표시합니다
|
||||
|
||||
## 파일에서 approvals 교체
|
||||
|
||||
```bash
|
||||
openclaw approvals set --file ./exec-approvals.json
|
||||
openclaw approvals set --stdin <<'EOF'
|
||||
{ version: 1, defaults: { security: "full", ask: "off" } }
|
||||
EOF
|
||||
openclaw approvals set --node <id|name|ip> --file ./exec-approvals.json
|
||||
openclaw approvals set --gateway --file ./exec-approvals.json
|
||||
```
|
||||
|
||||
`set`은 엄격한 JSON만이 아니라 JSON5를 허용합니다. `--file` 또는 `--stdin` 중 하나만 사용하고, 둘 다 함께 사용하지는 마세요.
|
||||
|
||||
## "절대 프롬프트하지 않음" / YOLO 예시
|
||||
|
||||
호스트가 exec 승인에서 절대 멈추지 않아야 한다면, 호스트 approvals 기본값을 `full` + `off`로 설정하세요.
|
||||
|
||||
```bash
|
||||
openclaw approvals set --stdin <<'EOF'
|
||||
{
|
||||
version: 1,
|
||||
defaults: {
|
||||
security: "full",
|
||||
ask: "off",
|
||||
askFallback: "full"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
노드 버전:
|
||||
|
||||
```bash
|
||||
openclaw approvals set --node <id|name|ip> --stdin <<'EOF'
|
||||
{
|
||||
version: 1,
|
||||
defaults: {
|
||||
security: "full",
|
||||
ask: "off",
|
||||
askFallback: "full"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
이것은 **호스트 approvals 파일**만 변경합니다. 요청된 OpenClaw 정책도 일치시키려면 다음도 설정하세요.
|
||||
|
||||
```bash
|
||||
openclaw config set tools.exec.host gateway
|
||||
openclaw config set tools.exec.security full
|
||||
openclaw config set tools.exec.ask off
|
||||
```
|
||||
|
||||
이 예시에서 `tools.exec.host=gateway`인 이유:
|
||||
|
||||
- `host=auto`는 여전히 "가능하면 샌드박스, 그렇지 않으면 게이트웨이"를 의미합니다.
|
||||
- YOLO는 라우팅이 아니라 승인에 관한 것입니다.
|
||||
- 샌드박스가 구성되어 있어도 호스트 exec를 사용하려면 `gateway` 또는 `/exec host=gateway`로 호스트 선택을 명시적으로 지정하세요.
|
||||
|
||||
이것은 현재 호스트 기본 YOLO 동작과 일치합니다. 승인이 필요하다면 더 엄격하게 조이세요.
|
||||
|
||||
## 허용 목록 도우미
|
||||
|
||||
```bash
|
||||
openclaw approvals allowlist add "~/Projects/**/bin/rg"
|
||||
openclaw approvals allowlist add --agent main --node <id|name|ip> "/usr/bin/uptime"
|
||||
openclaw approvals allowlist add --agent "*" "/usr/bin/uname"
|
||||
|
||||
openclaw approvals allowlist remove "~/Projects/**/bin/rg"
|
||||
```
|
||||
|
||||
## 공통 옵션
|
||||
|
||||
`get`, `set`, `allowlist add|remove`는 모두 다음을 지원합니다.
|
||||
|
||||
- `--node <id|name|ip>`
|
||||
- `--gateway`
|
||||
- 공유 노드 RPC 옵션: `--url`, `--token`, `--timeout`, `--json`
|
||||
|
||||
대상 지정 참고 사항:
|
||||
|
||||
- 대상 플래그가 없으면 디스크의 로컬 approvals 파일을 의미합니다
|
||||
- `--gateway`는 게이트웨이 호스트 approvals 파일을 대상으로 합니다
|
||||
- `--node`는 ID, 이름, IP 또는 ID 접두사를 확인한 후 하나의 노드 호스트를 대상으로 합니다
|
||||
|
||||
`allowlist add|remove`는 다음도 지원합니다.
|
||||
|
||||
- `--agent <id>`(기본값은 `*`)
|
||||
|
||||
## 참고
|
||||
|
||||
- `--node`는 `openclaw nodes`와 동일한 리졸버를 사용합니다(ID, 이름, IP 또는 ID 접두사).
|
||||
- `--agent`의 기본값은 `"*"`이며, 이는 모든 에이전트에 적용됩니다.
|
||||
- 노드 호스트는 `system.execApprovals.get/set`을 광고해야 합니다(macOS 앱 또는 헤드리스 노드 호스트).
|
||||
- Approvals 파일은 호스트별로 `~/.openclaw/exec-approvals.json`에 저장됩니다.
|
||||
88
docs/ko/cli/backup.md
Normal file
88
docs/ko/cli/backup.md
Normal file
@ -0,0 +1,88 @@
|
||||
---
|
||||
read_when:
|
||||
- 로컬 OpenClaw 상태를 위한 일급 백업 아카이브가 필요할 때
|
||||
- 재설정 또는 제거 전에 어떤 경로가 포함될지 미리 보고 싶을 때
|
||||
summary: '`openclaw backup`용 CLI 참조(로컬 백업 아카이브 생성)'
|
||||
title: backup
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:34Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 700eda8f9eac1cc93a854fa579f128e5e97d4e6dfc0da75b437c0fb2a898a37d
|
||||
source_path: cli/backup.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw backup`
|
||||
|
||||
OpenClaw 상태, config, 인증 프로필, 채널/제공자 자격 증명, 세션, 그리고 선택적으로 워크스페이스에 대한 로컬 백업 아카이브를 생성합니다.
|
||||
|
||||
```bash
|
||||
openclaw backup create
|
||||
openclaw backup create --output ~/Backups
|
||||
openclaw backup create --dry-run --json
|
||||
openclaw backup create --verify
|
||||
openclaw backup create --no-include-workspace
|
||||
openclaw backup create --only-config
|
||||
openclaw backup verify ./2026-03-09T00-00-00.000Z-openclaw-backup.tar.gz
|
||||
```
|
||||
|
||||
## 참고
|
||||
|
||||
- 아카이브에는 확인된 소스 경로와 아카이브 레이아웃이 포함된 `manifest.json` 파일이 포함됩니다.
|
||||
- 기본 출력은 현재 작업 디렉터리에 타임스탬프가 포함된 `.tar.gz` 아카이브입니다.
|
||||
- 현재 작업 디렉터리가 백업 대상 소스 트리 내부에 있으면, OpenClaw는 기본 아카이브 위치로 홈 디렉터리를 대신 사용합니다.
|
||||
- 기존 아카이브 파일은 절대 덮어쓰지 않습니다.
|
||||
- 소스 상태/워크스페이스 트리 내부의 출력 경로는 자체 포함을 방지하기 위해 거부됩니다.
|
||||
- `openclaw backup verify <archive>`는 아카이브에 루트 manifest가 정확히 하나 포함되어 있는지 검증하고, traversal 스타일 아카이브 경로를 거부하며, manifest에 선언된 모든 페이로드가 tarball에 존재하는지 확인합니다.
|
||||
- `openclaw backup create --verify`는 아카이브를 쓴 직후 해당 검증을 즉시 실행합니다.
|
||||
- `openclaw backup create --only-config`는 활성 JSON config 파일만 백업합니다.
|
||||
|
||||
## 백업되는 항목
|
||||
|
||||
`openclaw backup create`는 로컬 OpenClaw 설치에서 백업 소스를 계획합니다:
|
||||
|
||||
- OpenClaw의 로컬 상태 확인자가 반환하는 상태 디렉터리(보통 `~/.openclaw`)
|
||||
- 활성 config 파일 경로
|
||||
- 상태 디렉터리 밖에 존재하는 경우 확인된 `credentials/` 디렉터리
|
||||
- `--no-include-workspace`를 전달하지 않는 한 현재 config에서 발견된 워크스페이스 디렉터리
|
||||
|
||||
모델 인증 프로필은 이미 상태 디렉터리 아래
|
||||
`agents/<agentId>/agent/auth-profiles.json`에 포함되어 있으므로, 일반적으로
|
||||
상태 백업 항목으로 포함됩니다.
|
||||
|
||||
`--only-config`를 사용하면 OpenClaw는 상태, 자격 증명 디렉터리, 워크스페이스 검색을 건너뛰고 활성 config 파일 경로만 아카이브합니다.
|
||||
|
||||
OpenClaw는 아카이브를 만들기 전에 경로를 정규화합니다. config, 자격 증명 디렉터리 또는 워크스페이스가 이미 상태 디렉터리 내부에 있으면, 별도의 최상위 백업 소스로 중복되지 않습니다. 누락된 경로는 건너뜁니다.
|
||||
|
||||
아카이브 페이로드는 해당 소스 트리의 파일 내용을 저장하며, 포함된 `manifest.json`은 확인된 절대 소스 경로와 각 자산에 사용된 아카이브 레이아웃을 기록합니다.
|
||||
|
||||
## 잘못된 config 동작
|
||||
|
||||
`openclaw backup`은 복구 중에도 도움을 줄 수 있도록 의도적으로 일반 config 사전 점검을 우회합니다. 하지만 워크스페이스 검색은 유효한 config에 의존하므로, 이제 `openclaw backup create`는 config 파일이 존재하지만 잘못되었고 워크스페이스 백업이 여전히 활성화되어 있으면 즉시 실패합니다.
|
||||
|
||||
그런 상황에서도 부분 백업을 원한다면 다음과 같이 다시 실행하세요:
|
||||
|
||||
```bash
|
||||
openclaw backup create --no-include-workspace
|
||||
```
|
||||
|
||||
이렇게 하면 상태, config, 외부 자격 증명 디렉터리는 범위에 유지하면서
|
||||
워크스페이스 검색은 완전히 건너뜁니다.
|
||||
|
||||
config 파일 자체의 복사본만 필요하다면, `--only-config`도 config가 잘못된 경우에 작동합니다. 워크스페이스 검색을 위해 config 파싱에 의존하지 않기 때문입니다.
|
||||
|
||||
## 크기 및 성능
|
||||
|
||||
OpenClaw는 기본 제공 최대 백업 크기 또는 파일별 크기 제한을 강제하지 않습니다.
|
||||
|
||||
실질적인 제한은 로컬 머신과 대상 파일 시스템에서 결정됩니다:
|
||||
|
||||
- 임시 아카이브 쓰기와 최종 아카이브를 위한 사용 가능한 공간
|
||||
- 큰 워크스페이스 트리를 순회하고 `.tar.gz`로 압축하는 데 걸리는 시간
|
||||
- `openclaw backup create --verify`를 사용하거나 `openclaw backup verify`를 실행할 때 아카이브를 다시 검사하는 시간
|
||||
- 대상 경로에서의 파일 시스템 동작. OpenClaw는 덮어쓰지 않는 하드 링크 게시 단계를 우선 사용하고, 하드 링크를 지원하지 않으면 배타적 복사로 대체합니다
|
||||
|
||||
큰 워크스페이스는 보통 아카이브 크기의 주요 원인입니다. 더 작거나 더 빠른 백업을 원하면 `--no-include-workspace`를 사용하세요.
|
||||
|
||||
가장 작은 아카이브가 필요하면 `--only-config`를 사용하세요.
|
||||
240
docs/ko/cli/browser.md
Normal file
240
docs/ko/cli/browser.md
Normal file
@ -0,0 +1,240 @@
|
||||
---
|
||||
read_when:
|
||||
- 일반적인 작업 예시를 위해 `openclaw browser`를 사용할 때
|
||||
- 노드 호스트를 통해 다른 머신에서 실행 중인 브라우저를 제어하려고 할 때
|
||||
- Chrome MCP를 통해 로컬의 로그인된 Chrome에 연결하려고 할 때
|
||||
summary: '`openclaw browser`용 CLI 참조(수명 주기, 프로필, 탭, 작업, 상태, 디버깅)'
|
||||
title: browser
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:43Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: c89a7483dd733863dd8ebd47a14fbb411808ad07daaed515c1270978de9157e7
|
||||
source_path: cli/browser.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw browser`
|
||||
|
||||
OpenClaw의 브라우저 제어 표면을 관리하고 브라우저 작업(수명 주기, 프로필, 탭, 스냅샷, 스크린샷, 탐색, 입력, 상태 에뮬레이션, 디버깅)을 실행합니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- 브라우저 도구 + API: [Browser tool](/tools/browser)
|
||||
|
||||
## 공통 플래그
|
||||
|
||||
- `--url <gatewayWsUrl>`: 게이트웨이 WebSocket URL(config 기본값 사용).
|
||||
- `--token <token>`: 게이트웨이 토큰(필요한 경우).
|
||||
- `--timeout <ms>`: 요청 타임아웃(ms).
|
||||
- `--expect-final`: 최종 게이트웨이 응답을 기다립니다.
|
||||
- `--browser-profile <name>`: 브라우저 프로필 선택(config의 기본값 사용).
|
||||
- `--json`: 기계 판독 가능 출력(지원되는 경우).
|
||||
|
||||
## 빠른 시작(로컬)
|
||||
|
||||
```bash
|
||||
openclaw browser profiles
|
||||
openclaw browser --browser-profile openclaw start
|
||||
openclaw browser --browser-profile openclaw open https://example.com
|
||||
openclaw browser --browser-profile openclaw snapshot
|
||||
```
|
||||
|
||||
## 수명 주기
|
||||
|
||||
```bash
|
||||
openclaw browser status
|
||||
openclaw browser start
|
||||
openclaw browser stop
|
||||
openclaw browser --browser-profile openclaw reset-profile
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `attachOnly` 및 원격 CDP 프로필의 경우, `openclaw browser stop`은
|
||||
OpenClaw가 브라우저 프로세스를 직접 시작하지 않았더라도 활성 제어 세션을 닫고
|
||||
임시 에뮬레이션 재정의를 지웁니다.
|
||||
- 로컬 관리형 프로필의 경우, `openclaw browser stop`은 생성된 브라우저
|
||||
프로세스를 중지합니다.
|
||||
|
||||
## 명령이 없는 경우
|
||||
|
||||
`openclaw browser`가 알 수 없는 명령이라면
|
||||
`~/.openclaw/openclaw.json`의 `plugins.allow`를 확인하세요.
|
||||
|
||||
`plugins.allow`가 있으면 번들 브라우저 plugin이
|
||||
명시적으로 나열되어 있어야 합니다:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
allow: ["telegram", "browser"],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
plugin 허용 목록에서 `browser`가 제외되어 있으면
|
||||
`browser.enabled=true`만으로는 CLI 하위 명령이 복구되지 않습니다.
|
||||
|
||||
관련 문서: [Browser tool](/tools/browser#missing-browser-command-or-tool)
|
||||
|
||||
## 프로필
|
||||
|
||||
프로필은 이름 있는 브라우저 라우팅 구성입니다. 실제로는 다음과 같습니다:
|
||||
|
||||
- `openclaw`: 전용 OpenClaw 관리 Chrome 인스턴스를 시작하거나 연결합니다(격리된 사용자 데이터 디렉터리).
|
||||
- `user`: Chrome DevTools MCP를 통해 기존의 로그인된 Chrome 세션을 제어합니다.
|
||||
- 사용자 지정 CDP 프로필: 로컬 또는 원격 CDP 엔드포인트를 가리킵니다.
|
||||
|
||||
```bash
|
||||
openclaw browser profiles
|
||||
openclaw browser create-profile --name work --color "#FF5A36"
|
||||
openclaw browser create-profile --name chrome-live --driver existing-session
|
||||
openclaw browser create-profile --name remote --cdp-url https://browser-host.example.com
|
||||
openclaw browser delete-profile --name work
|
||||
```
|
||||
|
||||
특정 프로필 사용:
|
||||
|
||||
```bash
|
||||
openclaw browser --browser-profile work tabs
|
||||
```
|
||||
|
||||
## 탭
|
||||
|
||||
```bash
|
||||
openclaw browser tabs
|
||||
openclaw browser tab new
|
||||
openclaw browser tab select 2
|
||||
openclaw browser tab close 2
|
||||
openclaw browser open https://docs.openclaw.ai
|
||||
openclaw browser focus <targetId>
|
||||
openclaw browser close <targetId>
|
||||
```
|
||||
|
||||
## 스냅샷 / 스크린샷 / 작업
|
||||
|
||||
스냅샷:
|
||||
|
||||
```bash
|
||||
openclaw browser snapshot
|
||||
```
|
||||
|
||||
스크린샷:
|
||||
|
||||
```bash
|
||||
openclaw browser screenshot
|
||||
openclaw browser screenshot --full-page
|
||||
openclaw browser screenshot --ref e12
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `--full-page`는 페이지 캡처 전용이며 `--ref`
|
||||
또는 `--element`와 함께 사용할 수 없습니다.
|
||||
- `existing-session` / `user` 프로필은 페이지 스크린샷과 스냅샷 출력의 `--ref`
|
||||
스크린샷은 지원하지만 CSS `--element` 스크린샷은 지원하지 않습니다.
|
||||
|
||||
탐색/클릭/입력(ref 기반 UI 자동화):
|
||||
|
||||
```bash
|
||||
openclaw browser navigate https://example.com
|
||||
openclaw browser click <ref>
|
||||
openclaw browser type <ref> "hello"
|
||||
openclaw browser press Enter
|
||||
openclaw browser hover <ref>
|
||||
openclaw browser scrollintoview <ref>
|
||||
openclaw browser drag <startRef> <endRef>
|
||||
openclaw browser select <ref> OptionA OptionB
|
||||
openclaw browser fill --fields '[{"ref":"1","value":"Ada"}]'
|
||||
openclaw browser wait --text "Done"
|
||||
openclaw browser evaluate --fn '(el) => el.textContent' --ref <ref>
|
||||
```
|
||||
|
||||
파일 + 대화상자 헬퍼:
|
||||
|
||||
```bash
|
||||
openclaw browser upload /tmp/openclaw/uploads/file.pdf --ref <ref>
|
||||
openclaw browser waitfordownload
|
||||
openclaw browser download <ref> report.pdf
|
||||
openclaw browser dialog --accept
|
||||
```
|
||||
|
||||
## 상태 및 저장소
|
||||
|
||||
뷰포트 + 에뮬레이션:
|
||||
|
||||
```bash
|
||||
openclaw browser resize 1280 720
|
||||
openclaw browser set viewport 1280 720
|
||||
openclaw browser set offline on
|
||||
openclaw browser set media dark
|
||||
openclaw browser set timezone Europe/London
|
||||
openclaw browser set locale en-GB
|
||||
openclaw browser set geo 51.5074 -0.1278 --accuracy 25
|
||||
openclaw browser set device "iPhone 14"
|
||||
openclaw browser set headers '{"x-test":"1"}'
|
||||
openclaw browser set credentials myuser mypass
|
||||
```
|
||||
|
||||
쿠키 + 저장소:
|
||||
|
||||
```bash
|
||||
openclaw browser cookies
|
||||
openclaw browser cookies set session abc123 --url https://example.com
|
||||
openclaw browser cookies clear
|
||||
openclaw browser storage local get
|
||||
openclaw browser storage local set token abc123
|
||||
openclaw browser storage session clear
|
||||
```
|
||||
|
||||
## 디버깅
|
||||
|
||||
```bash
|
||||
openclaw browser console --level error
|
||||
openclaw browser pdf
|
||||
openclaw browser responsebody "**/api"
|
||||
openclaw browser highlight <ref>
|
||||
openclaw browser errors --clear
|
||||
openclaw browser requests --filter api
|
||||
openclaw browser trace start
|
||||
openclaw browser trace stop --out trace.zip
|
||||
```
|
||||
|
||||
## MCP를 통한 기존 Chrome
|
||||
|
||||
기본 제공 `user` 프로필을 사용하거나, 직접 `existing-session` 프로필을 만드세요:
|
||||
|
||||
```bash
|
||||
openclaw browser --browser-profile user tabs
|
||||
openclaw browser create-profile --name chrome-live --driver existing-session
|
||||
openclaw browser create-profile --name brave-live --driver existing-session --user-data-dir "~/Library/Application Support/BraveSoftware/Brave-Browser"
|
||||
openclaw browser --browser-profile chrome-live tabs
|
||||
```
|
||||
|
||||
이 경로는 호스트 전용입니다. Docker, 헤드리스 서버, Browserless 또는 기타 원격 설정에서는 대신 CDP 프로필을 사용하세요.
|
||||
|
||||
현재 existing-session 제한 사항:
|
||||
|
||||
- 스냅샷 기반 작업은 CSS 선택자가 아니라 ref를 사용합니다
|
||||
- `click`은 왼쪽 클릭만 지원합니다
|
||||
- `type`은 `slowly=true`를 지원하지 않습니다
|
||||
- `press`는 `delayMs`를 지원하지 않습니다
|
||||
- `hover`, `scrollintoview`, `drag`, `select`, `fill`, `evaluate`는
|
||||
호출별 타임아웃 재정의를 거부합니다
|
||||
- `select`는 값 하나만 지원합니다
|
||||
- `wait --load networkidle`은 지원되지 않습니다
|
||||
- 파일 업로드는 `--ref` / `--input-ref`가 필요하며 CSS
|
||||
`--element`를 지원하지 않고, 현재 한 번에 파일 하나만 지원합니다
|
||||
- 대화상자 훅은 `--timeout`을 지원하지 않습니다
|
||||
- 스크린샷은 페이지 캡처와 `--ref`는 지원하지만 CSS `--element`는 지원하지 않습니다
|
||||
- `responsebody`, 다운로드 가로채기, PDF 내보내기, 일괄 작업은 여전히
|
||||
관리형 브라우저 또는 원시 CDP 프로필이 필요합니다
|
||||
|
||||
## 원격 브라우저 제어(노드 호스트 프록시)
|
||||
|
||||
게이트웨이가 브라우저와 다른 머신에서 실행되는 경우, Chrome/Brave/Edge/Chromium이 있는 머신에서 **노드 호스트**를 실행하세요. 게이트웨이는 브라우저 작업을 해당 노드로 프록시합니다(별도의 브라우저 제어 서버는 필요하지 않음).
|
||||
|
||||
자동 라우팅은 `gateway.nodes.browser.mode`로 제어하고, 여러 노드가 연결되어 있을 경우 특정 노드를 고정하려면 `gateway.nodes.browser.node`를 사용하세요.
|
||||
|
||||
보안 + 원격 설정: [Browser tool](/tools/browser), [Remote access](/gateway/remote), [Tailscale](/gateway/tailscale), [Security](/gateway/security)
|
||||
138
docs/ko/cli/channels.md
Normal file
138
docs/ko/cli/channels.md
Normal file
@ -0,0 +1,138 @@
|
||||
---
|
||||
read_when:
|
||||
- 채널 account(WhatsApp/Telegram/Discord/Google Chat/Slack/Mattermost (plugin)/Signal/iMessage/Matrix)를 추가/제거하려고 함
|
||||
- 채널 상태를 확인하거나 채널 로그를 실시간으로 보려고 함
|
||||
summary: '`openclaw channels`용 CLI 참조(accounts, status, login/logout, logs)'
|
||||
title: channels
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:42Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: d0f558fdb5f6ec54e7fdb7a88e5c24c9d2567174341bd3ea87848bce4cba5d29
|
||||
source_path: cli/channels.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw channels`
|
||||
|
||||
Gateway에서 채팅 채널 accounts와 해당 런타임 상태를 관리합니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- 채널 가이드: [Channels](/channels/index)
|
||||
- Gateway 구성: [Configuration](/gateway/configuration)
|
||||
|
||||
## 일반적인 명령
|
||||
|
||||
```bash
|
||||
openclaw channels list
|
||||
openclaw channels status
|
||||
openclaw channels capabilities
|
||||
openclaw channels capabilities --channel discord --target channel:123
|
||||
openclaw channels resolve --channel slack "#general" "@jane"
|
||||
openclaw channels logs --channel all
|
||||
```
|
||||
|
||||
## 상태 / capabilities / resolve / logs
|
||||
|
||||
- `channels status`: `--probe`, `--timeout <ms>`, `--json`
|
||||
- `channels capabilities`: `--channel <name>`, `--account <id>` (`--channel`과 함께만 사용), `--target <dest>`, `--timeout <ms>`, `--json`
|
||||
- `channels resolve`: `<entries...>`, `--channel <name>`, `--account <id>`, `--kind <auto|user|group>`, `--json`
|
||||
- `channels logs`: `--channel <name|all>`, `--lines <n>`, `--json`
|
||||
|
||||
`channels status --probe`는 라이브 경로입니다. gateway에 연결할 수 있으면 account별
|
||||
`probeAccount` 및 선택적 `auditAccount` 검사를 실행하므로 출력에 전송
|
||||
상태와 함께 `works`, `probe failed`, `audit ok`, `audit failed` 같은 프로브 결과가 포함될 수 있습니다.
|
||||
gateway에 연결할 수 없으면 `channels status`는 라이브 프로브 출력 대신
|
||||
config 전용 요약으로 폴백합니다.
|
||||
|
||||
## accounts 추가 / 제거
|
||||
|
||||
```bash
|
||||
openclaw channels add --channel telegram --token <bot-token>
|
||||
openclaw channels add --channel nostr --private-key "$NOSTR_PRIVATE_KEY"
|
||||
openclaw channels remove --channel telegram --delete
|
||||
```
|
||||
|
||||
팁: `openclaw channels add --help`는 채널별 플래그(token, private key, app token, signal-cli 경로 등)를 표시합니다.
|
||||
|
||||
일반적인 비대화형 add 표면은 다음과 같습니다.
|
||||
|
||||
- bot-token 채널: `--token`, `--bot-token`, `--app-token`, `--token-file`
|
||||
- Signal/iMessage 전송 필드: `--signal-number`, `--cli-path`, `--http-url`, `--http-host`, `--http-port`, `--db-path`, `--service`, `--region`
|
||||
- Google Chat 필드: `--webhook-path`, `--webhook-url`, `--audience-type`, `--audience`
|
||||
- Matrix 필드: `--homeserver`, `--user-id`, `--access-token`, `--password`, `--device-name`, `--initial-sync-limit`
|
||||
- Nostr 필드: `--private-key`, `--relay-urls`
|
||||
- Tlon 필드: `--ship`, `--url`, `--code`, `--group-channels`, `--dm-allowlist`, `--auto-discover-channels`
|
||||
- 지원되는 경우 기본 account의 env 기반 인증에 사용하는 `--use-env`
|
||||
|
||||
플래그 없이 `openclaw channels add`를 실행하면 대화형 마법사가 다음을 물을 수 있습니다.
|
||||
|
||||
- 선택한 채널별 account ID
|
||||
- 해당 accounts의 선택적 표시 이름
|
||||
- `Bind configured channel accounts to agents now?`
|
||||
|
||||
지금 bind를 확인하면, 마법사는 구성된 각 채널 account를 어떤 에이전트가 소유할지 묻고 account 범위 라우팅 바인딩을 기록합니다.
|
||||
|
||||
동일한 라우팅 규칙은 나중에 `openclaw agents bindings`, `openclaw agents bind`, `openclaw agents unbind`로도 관리할 수 있습니다([agents](/cli/agents) 참조).
|
||||
|
||||
여전히 단일 account 최상위 설정을 사용하는 채널에 비기본 account를 추가하면, OpenClaw는 새 account를 기록하기 전에 account 범위 최상위 값을 해당 채널의 account 맵으로 승격합니다. 대부분의 채널은 이 값을 `channels.<channel>.accounts.default`에 배치하지만, 번들 채널은 대신 기존에 일치하는 승격 account를 유지할 수 있습니다. Matrix가 현재 예시입니다. 이미 하나의 이름 있는 account가 존재하거나 `defaultAccount`가 기존 이름 있는 account를 가리키는 경우, 승격은 새 `accounts.default`를 만드는 대신 해당 account를 유지합니다.
|
||||
|
||||
라우팅 동작은 일관되게 유지됩니다.
|
||||
|
||||
- 기존 채널 전용 바인딩(`accountId` 없음)은 계속 기본 account와 일치합니다.
|
||||
- `channels add`는 비대화형 모드에서 바인딩을 자동 생성하거나 재작성하지 않습니다.
|
||||
- 대화형 설정은 선택적으로 account 범위 바인딩을 추가할 수 있습니다.
|
||||
|
||||
config가 이미 혼합 상태(이름 있는 accounts가 있고 최상위 단일 account 값도 여전히 설정됨)였다면, `openclaw doctor --fix`를 실행해 account 범위 값을 해당 채널에 대해 선택된 승격 account로 이동하세요. 대부분의 채널은 `accounts.default`로 승격하며, Matrix는 기존 이름 있는/default 대상을 유지할 수 있습니다.
|
||||
|
||||
## login / logout (대화형)
|
||||
|
||||
```bash
|
||||
openclaw channels login --channel whatsapp
|
||||
openclaw channels logout --channel whatsapp
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `channels login`은 `--verbose`를 지원합니다.
|
||||
- 지원되는 login 대상이 하나만 구성된 경우 `channels login` / `logout`은 채널을 추론할 수 있습니다.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
- 광범위한 프로브에는 `openclaw status --deep`를 실행하세요.
|
||||
- 가이드형 수정에는 `openclaw doctor`를 사용하세요.
|
||||
- `openclaw channels list`에 `Claude: HTTP 403 ... user:profile`이 출력되면 사용량 스냅샷에 `user:profile` scope가 필요하다는 뜻입니다. `--no-usage`를 사용하거나, claude.ai 세션 키(`CLAUDE_WEB_SESSION_KEY` / `CLAUDE_WEB_COOKIE`)를 제공하거나, Claude CLI를 통해 다시 인증하세요.
|
||||
- gateway에 연결할 수 없으면 `openclaw channels status`는 config 전용 요약으로 폴백합니다. 지원되는 채널 자격 증명이 SecretRef를 통해 구성되었지만 현재 명령 경로에서 사용할 수 없는 경우, 해당 account를 미구성으로 표시하는 대신 저하된 상태 메모와 함께 구성됨으로 보고합니다.
|
||||
|
||||
## Capabilities 프로브
|
||||
|
||||
사용 가능한 경우 provider capability 힌트(intents/scopes)와 정적 기능 지원을 가져옵니다.
|
||||
|
||||
```bash
|
||||
openclaw channels capabilities
|
||||
openclaw channels capabilities --channel discord --target channel:123
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `--channel`은 선택 사항입니다. 생략하면 모든 채널(extensions 포함)을 나열합니다.
|
||||
- `--account`는 `--channel`과 함께 사용할 때만 유효합니다.
|
||||
- `--target`은 `channel:<id>` 또는 순수 숫자 채널 ID를 받으며 Discord에만 적용됩니다.
|
||||
- 프로브는 provider별입니다. Discord intents + 선택적 채널 권한, Slack bot + user scopes, Telegram bot 플래그 + webhook, Signal 데몬 버전, Microsoft Teams 앱 토큰 + Graph roles/scopes(알려진 경우 주석 포함)를 포함합니다. 프로브가 없는 채널은 `Probe: unavailable`을 보고합니다.
|
||||
|
||||
## 이름을 ID로 resolve
|
||||
|
||||
provider 디렉터리를 사용해 채널/사용자 이름을 ID로 resolve합니다.
|
||||
|
||||
```bash
|
||||
openclaw channels resolve --channel slack "#general" "@jane"
|
||||
openclaw channels resolve --channel discord "My Server/#support" "@someone"
|
||||
openclaw channels resolve --channel matrix "Project Room"
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 대상 유형을 강제하려면 `--kind user|group|auto`를 사용하세요.
|
||||
- 여러 항목이 같은 이름을 공유하는 경우 resolve는 활성 항목을 우선합니다.
|
||||
- `channels resolve`는 읽기 전용입니다. 선택한 account가 SecretRef를 통해 구성되었지만 현재 명령 경로에서 해당 자격 증명을 사용할 수 없는 경우, 명령은 전체 실행을 중단하는 대신 메모가 포함된 저하된 미해결 결과를 반환합니다.
|
||||
28
docs/ko/cli/clawbot.md
Normal file
28
docs/ko/cli/clawbot.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
read_when:
|
||||
- '`openclaw clawbot ...`를 사용하는 기존 스크립트를 유지 관리하는 경우'
|
||||
- 현재 명령으로의 마이그레이션 가이드가 필요한 경우
|
||||
summary: '`openclaw clawbot`용 CLI 참조(레거시 별칭 네임스페이스)'
|
||||
title: clawbot
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:30Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 1db82065ecb0107d1ab1a2c6ddaee9df1dd02b983ca1f759974c9d73f0ee3bde
|
||||
source_path: cli/clawbot.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw clawbot`
|
||||
|
||||
하위 호환성을 위해 유지되는 레거시 별칭 네임스페이스입니다.
|
||||
|
||||
현재 지원되는 별칭:
|
||||
|
||||
- `openclaw clawbot qr` (`openclaw qr`와 동일한 동작, [`openclaw qr`](/cli/qr) 참조)
|
||||
|
||||
## 마이그레이션
|
||||
|
||||
최신 최상위 명령을 직접 사용하는 것을 권장합니다.
|
||||
|
||||
- `openclaw clawbot qr` -> `openclaw qr`
|
||||
42
docs/ko/cli/completion.md
Normal file
42
docs/ko/cli/completion.md
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
read_when:
|
||||
- zsh/bash/fish/PowerShell용 셸 자동 완성이 필요할 때
|
||||
- OpenClaw 상태 아래에 자동 완성 스크립트를 캐시해야 할 때
|
||||
summary: '`openclaw completion`용 CLI 참조(셸 자동 완성 스크립트 생성/설치)'
|
||||
title: completion
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:33Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 7bbf140a880bafdb7140149f85465d66d0d46e5a3da6a1e41fb78be2fd2bd4d0
|
||||
source_path: cli/completion.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw completion`
|
||||
|
||||
셸 자동 완성 스크립트를 생성하고, 선택적으로 셸 프로필에 설치합니다.
|
||||
|
||||
## 사용법
|
||||
|
||||
```bash
|
||||
openclaw completion
|
||||
openclaw completion --shell zsh
|
||||
openclaw completion --install
|
||||
openclaw completion --shell fish --install
|
||||
openclaw completion --write-state
|
||||
openclaw completion --shell bash --write-state
|
||||
```
|
||||
|
||||
## 옵션
|
||||
|
||||
- `-s, --shell <shell>`: 셸 대상(`zsh`, `bash`, `powershell`, `fish`; 기본값: `zsh`)
|
||||
- `-i, --install`: 셸 프로필에 source 줄을 추가하여 자동 완성 설치
|
||||
- `--write-state`: 스크립트를 stdout에 출력하지 않고 `$OPENCLAW_STATE_DIR/completions`에 자동 완성 스크립트를 작성
|
||||
- `-y, --yes`: 설치 확인 프롬프트 건너뛰기
|
||||
|
||||
## 참고
|
||||
|
||||
- `--install`은 셸 프로필에 작은 "OpenClaw Completion" 블록을 작성하고 이를 캐시된 스크립트에 연결합니다.
|
||||
- `--install`이나 `--write-state`가 없으면 명령은 스크립트를 stdout에 출력합니다.
|
||||
- 자동 완성 생성은 중첩된 하위 명령이 포함되도록 명령 트리를 eager 로드합니다.
|
||||
359
docs/ko/cli/config.md
Normal file
359
docs/ko/cli/config.md
Normal file
@ -0,0 +1,359 @@
|
||||
---
|
||||
read_when:
|
||||
- 비대화형으로 config를 읽거나 편집하려는 경우
|
||||
summary: '`openclaw config`용 CLI 참조(get/set/unset/file/schema/validate)'
|
||||
title: config
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:01Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: e4de30f41e15297019151ad1a5b306cb331fd5c2beefd5ce5b98fcc51e95f0de
|
||||
source_path: cli/config.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw config`
|
||||
|
||||
`openclaw.json`에서 비대화형 편집을 위한 config 도우미입니다: get/set/unset/file/schema/validate
|
||||
경로 기준 값 처리 및 활성 config 파일 출력. 하위 명령 없이 실행하면
|
||||
구성 마법사(`openclaw configure`와 동일)가 열립니다.
|
||||
|
||||
루트 옵션:
|
||||
|
||||
- `--section <section>`: 하위 명령 없이 `openclaw config`를 실행할 때 반복 가능한 guided-setup 섹션 필터
|
||||
|
||||
지원되는 guided 섹션:
|
||||
|
||||
- `workspace`
|
||||
- `model`
|
||||
- `web`
|
||||
- `gateway`
|
||||
- `daemon`
|
||||
- `channels`
|
||||
- `plugins`
|
||||
- `skills`
|
||||
- `health`
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw config file
|
||||
openclaw config --section model
|
||||
openclaw config --section gateway --section daemon
|
||||
openclaw config schema
|
||||
openclaw config get browser.executablePath
|
||||
openclaw config set browser.executablePath "/usr/bin/google-chrome"
|
||||
openclaw config set agents.defaults.heartbeat.every "2h"
|
||||
openclaw config set agents.list[0].tools.exec.node "node-id-or-name"
|
||||
openclaw config set channels.discord.token --ref-provider default --ref-source env --ref-id DISCORD_BOT_TOKEN
|
||||
openclaw config set secrets.providers.vaultfile --provider-source file --provider-path /etc/openclaw/secrets.json --provider-mode json
|
||||
openclaw config unset plugins.entries.brave.config.webSearch.apiKey
|
||||
openclaw config set channels.discord.token --ref-provider default --ref-source env --ref-id DISCORD_BOT_TOKEN --dry-run
|
||||
openclaw config validate
|
||||
openclaw config validate --json
|
||||
```
|
||||
|
||||
### `config schema`
|
||||
|
||||
생성된 `openclaw.json`용 JSON 스키마를 JSON으로 stdout에 출력합니다.
|
||||
|
||||
포함 내용:
|
||||
|
||||
- 현재 루트 config 스키마와 에디터 도구용 루트 `$schema` 문자열 필드
|
||||
- Control UI에서 사용하는 필드 `title` 및 `description` 문서 메타데이터
|
||||
- 일치하는 필드 문서가 있으면 중첩 객체, 와일드카드(`*`), 배열 항목(`[]`) 노드도 동일한 `title` / `description` 메타데이터를 상속
|
||||
- 일치하는 필드 문서가 있으면 `anyOf` / `oneOf` / `allOf` 분기도 동일한 문서 메타데이터를 상속
|
||||
- 런타임 manifest를 로드할 수 있을 때 최선의 방식으로 제공되는 라이브 플러그인 + 채널 스키마 메타데이터
|
||||
- 현재 config가 유효하지 않아도 깔끔한 대체 스키마
|
||||
|
||||
관련 런타임 RPC:
|
||||
|
||||
- `config.schema.lookup`은 정규화된 config 경로 하나와 얕은
|
||||
스키마 노드(`title`, `description`, `type`, `enum`, `const`, 일반 경계값),
|
||||
일치된 UI 힌트 메타데이터, 즉시 자식 요약을 반환합니다. 이를 사용해
|
||||
Control UI 또는 사용자 지정 클라이언트에서 경로 범위 드릴다운을 수행하세요.
|
||||
|
||||
```bash
|
||||
openclaw config schema
|
||||
```
|
||||
|
||||
다른 도구로 검사하거나 검증하려면 파일로 파이프하세요.
|
||||
|
||||
```bash
|
||||
openclaw config schema > openclaw.schema.json
|
||||
```
|
||||
|
||||
### 경로
|
||||
|
||||
경로는 점 표기법 또는 대괄호 표기법을 사용합니다.
|
||||
|
||||
```bash
|
||||
openclaw config get agents.defaults.workspace
|
||||
openclaw config get agents.list[0].id
|
||||
```
|
||||
|
||||
특정 에이전트를 대상으로 지정하려면 에이전트 목록 인덱스를 사용하세요.
|
||||
|
||||
```bash
|
||||
openclaw config get agents.list
|
||||
openclaw config set agents.list[1].tools.exec.node "node-id-or-name"
|
||||
```
|
||||
|
||||
## 값
|
||||
|
||||
값은 가능하면 JSON5로 파싱되고, 그렇지 않으면 문자열로 처리됩니다.
|
||||
JSON5 파싱을 강제하려면 `--strict-json`을 사용하세요. `--json`도 기존 별칭으로 계속 지원됩니다.
|
||||
|
||||
```bash
|
||||
openclaw config set agents.defaults.heartbeat.every "0m"
|
||||
openclaw config set gateway.port 19001 --strict-json
|
||||
openclaw config set channels.whatsapp.groups '["*"]' --strict-json
|
||||
```
|
||||
|
||||
`config get <path> --json`은 터미널 형식 텍스트 대신 원시 값을 JSON으로 출력합니다.
|
||||
|
||||
## `config set` 모드
|
||||
|
||||
`openclaw config set`은 네 가지 할당 스타일을 지원합니다.
|
||||
|
||||
1. 값 모드: `openclaw config set <path> <value>`
|
||||
2. SecretRef 빌더 모드:
|
||||
|
||||
```bash
|
||||
openclaw config set channels.discord.token \
|
||||
--ref-provider default \
|
||||
--ref-source env \
|
||||
--ref-id DISCORD_BOT_TOKEN
|
||||
```
|
||||
|
||||
3. Provider 빌더 모드(`secrets.providers.<alias>` 경로에서만):
|
||||
|
||||
```bash
|
||||
openclaw config set secrets.providers.vault \
|
||||
--provider-source exec \
|
||||
--provider-command /usr/local/bin/openclaw-vault \
|
||||
--provider-arg read \
|
||||
--provider-arg openai/api-key \
|
||||
--provider-timeout-ms 5000
|
||||
```
|
||||
|
||||
4. 배치 모드(`--batch-json` 또는 `--batch-file`):
|
||||
|
||||
```bash
|
||||
openclaw config set --batch-json '[
|
||||
{
|
||||
"path": "secrets.providers.default",
|
||||
"provider": { "source": "env" }
|
||||
},
|
||||
{
|
||||
"path": "channels.discord.token",
|
||||
"ref": { "source": "env", "provider": "default", "id": "DISCORD_BOT_TOKEN" }
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
```bash
|
||||
openclaw config set --batch-file ./config-set.batch.json --dry-run
|
||||
```
|
||||
|
||||
정책 참고:
|
||||
|
||||
- 지원되지 않는 런타임 변경 가능 표면(예: `hooks.token`, `commands.ownerDisplaySecret`, Discord thread-binding webhook token, WhatsApp creds JSON)에서는 SecretRef 할당이 거부됩니다. [SecretRef Credential Surface](/reference/secretref-credential-surface)를 참조하세요.
|
||||
|
||||
배치 파싱은 항상 배치 페이로드(`--batch-json`/`--batch-file`)를 기준 정보로 사용합니다.
|
||||
`--strict-json` / `--json`은 배치 파싱 동작을 바꾸지 않습니다.
|
||||
|
||||
JSON 경로/값 모드는 SecretRef와 provider 모두에 대해 계속 지원됩니다.
|
||||
|
||||
```bash
|
||||
openclaw config set channels.discord.token \
|
||||
'{"source":"env","provider":"default","id":"DISCORD_BOT_TOKEN"}' \
|
||||
--strict-json
|
||||
|
||||
openclaw config set secrets.providers.vaultfile \
|
||||
'{"source":"file","path":"/etc/openclaw/secrets.json","mode":"json"}' \
|
||||
--strict-json
|
||||
```
|
||||
|
||||
## Provider Builder 플래그
|
||||
|
||||
Provider 빌더 대상은 경로로 `secrets.providers.<alias>`를 사용해야 합니다.
|
||||
|
||||
공통 플래그:
|
||||
|
||||
- `--provider-source <env|file|exec>`
|
||||
- `--provider-timeout-ms <ms>` (`file`, `exec`)
|
||||
|
||||
Env provider (`--provider-source env`):
|
||||
|
||||
- `--provider-allowlist <ENV_VAR>` (반복 가능)
|
||||
|
||||
File provider (`--provider-source file`):
|
||||
|
||||
- `--provider-path <path>` (필수)
|
||||
- `--provider-mode <singleValue|json>`
|
||||
- `--provider-max-bytes <bytes>`
|
||||
|
||||
Exec provider (`--provider-source exec`):
|
||||
|
||||
- `--provider-command <path>` (필수)
|
||||
- `--provider-arg <arg>` (반복 가능)
|
||||
- `--provider-no-output-timeout-ms <ms>`
|
||||
- `--provider-max-output-bytes <bytes>`
|
||||
- `--provider-json-only`
|
||||
- `--provider-env <KEY=VALUE>` (반복 가능)
|
||||
- `--provider-pass-env <ENV_VAR>` (반복 가능)
|
||||
- `--provider-trusted-dir <path>` (반복 가능)
|
||||
- `--provider-allow-insecure-path`
|
||||
- `--provider-allow-symlink-command`
|
||||
|
||||
강화된 exec provider 예시:
|
||||
|
||||
```bash
|
||||
openclaw config set secrets.providers.vault \
|
||||
--provider-source exec \
|
||||
--provider-command /usr/local/bin/openclaw-vault \
|
||||
--provider-arg read \
|
||||
--provider-arg openai/api-key \
|
||||
--provider-json-only \
|
||||
--provider-pass-env VAULT_TOKEN \
|
||||
--provider-trusted-dir /usr/local/bin \
|
||||
--provider-timeout-ms 5000
|
||||
```
|
||||
|
||||
## 드라이 런
|
||||
|
||||
`openclaw.json`에 쓰지 않고 변경 사항을 검증하려면 `--dry-run`을 사용하세요.
|
||||
|
||||
```bash
|
||||
openclaw config set channels.discord.token \
|
||||
--ref-provider default \
|
||||
--ref-source env \
|
||||
--ref-id DISCORD_BOT_TOKEN \
|
||||
--dry-run
|
||||
|
||||
openclaw config set channels.discord.token \
|
||||
--ref-provider default \
|
||||
--ref-source env \
|
||||
--ref-id DISCORD_BOT_TOKEN \
|
||||
--dry-run \
|
||||
--json
|
||||
|
||||
openclaw config set channels.discord.token \
|
||||
--ref-provider vault \
|
||||
--ref-source exec \
|
||||
--ref-id discord/token \
|
||||
--dry-run \
|
||||
--allow-exec
|
||||
```
|
||||
|
||||
드라이 런 동작:
|
||||
|
||||
- 빌더 모드: 변경된 ref/provider에 대해 SecretRef 해석 가능성 검사를 실행합니다.
|
||||
- JSON 모드(`--strict-json`, `--json`, 또는 배치 모드): 스키마 검증과 SecretRef 해석 가능성 검사를 실행합니다.
|
||||
- 알려진 지원되지 않는 SecretRef 대상 표면에 대한 정책 검증도 실행됩니다.
|
||||
- 정책 검사는 변경 후 전체 config를 평가하므로, 상위 객체 쓰기(예: `hooks`를 객체로 설정)로 지원되지 않는 표면 검증을 우회할 수 없습니다.
|
||||
- exec SecretRef 검사는 명령 부작용을 피하기 위해 드라이 런 중 기본적으로 건너뜁니다.
|
||||
- exec SecretRef 검사를 선택적으로 수행하려면 `--dry-run`과 함께 `--allow-exec`를 사용하세요(이 경우 provider 명령이 실행될 수 있음).
|
||||
- `--allow-exec`는 드라이 런 전용이며 `--dry-run` 없이 사용하면 오류가 발생합니다.
|
||||
|
||||
`--dry-run --json`은 기계 판독 가능한 보고서를 출력합니다.
|
||||
|
||||
- `ok`: 드라이 런 통과 여부
|
||||
- `operations`: 평가된 할당 수
|
||||
- `checks`: 스키마/해석 가능성 검사가 실행되었는지 여부
|
||||
- `checks.resolvabilityComplete`: 해석 가능성 검사가 끝까지 실행되었는지 여부(exec ref를 건너뛴 경우 false)
|
||||
- `refsChecked`: 드라이 런 중 실제로 확인된 ref 수
|
||||
- `skippedExecRefs`: `--allow-exec`가 설정되지 않아 건너뛴 exec ref 수
|
||||
- `errors`: `ok=false`일 때 구조화된 스키마/해석 가능성 실패
|
||||
|
||||
### JSON 출력 형태
|
||||
|
||||
```json5
|
||||
{
|
||||
ok: boolean,
|
||||
operations: number,
|
||||
configPath: string,
|
||||
inputModes: ["value" | "json" | "builder", ...],
|
||||
checks: {
|
||||
schema: boolean,
|
||||
resolvability: boolean,
|
||||
resolvabilityComplete: boolean,
|
||||
},
|
||||
refsChecked: number,
|
||||
skippedExecRefs: number,
|
||||
errors?: [
|
||||
{
|
||||
kind: "schema" | "resolvability",
|
||||
message: string,
|
||||
ref?: string, // 해석 가능성 오류에 대해 존재
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
성공 예시:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"operations": 1,
|
||||
"configPath": "~/.openclaw/openclaw.json",
|
||||
"inputModes": ["builder"],
|
||||
"checks": {
|
||||
"schema": false,
|
||||
"resolvability": true,
|
||||
"resolvabilityComplete": true
|
||||
},
|
||||
"refsChecked": 1,
|
||||
"skippedExecRefs": 0
|
||||
}
|
||||
```
|
||||
|
||||
실패 예시:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": false,
|
||||
"operations": 1,
|
||||
"configPath": "~/.openclaw/openclaw.json",
|
||||
"inputModes": ["builder"],
|
||||
"checks": {
|
||||
"schema": false,
|
||||
"resolvability": true,
|
||||
"resolvabilityComplete": true
|
||||
},
|
||||
"refsChecked": 1,
|
||||
"skippedExecRefs": 0,
|
||||
"errors": [
|
||||
{
|
||||
"kind": "resolvability",
|
||||
"message": "Error: Environment variable \"MISSING_TEST_SECRET\" is not set.",
|
||||
"ref": "env:default:MISSING_TEST_SECRET"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
드라이 런이 실패하는 경우:
|
||||
|
||||
- `config schema validation failed`: 변경 후 config 형태가 유효하지 않습니다. 경로/값 또는 provider/ref 객체 형태를 수정하세요.
|
||||
- `Config policy validation failed: unsupported SecretRef usage`: 해당 자격 증명은 평문/문자열 입력으로 되돌리고, 지원되는 표면에서만 SecretRef를 유지하세요.
|
||||
- `SecretRef assignment(s) could not be resolved`: 참조된 provider/ref가 현재 해석될 수 없습니다(누락된 env var, 잘못된 파일 포인터, exec provider 실패, 또는 provider/source 불일치).
|
||||
- `Dry run note: skipped <n> exec SecretRef resolvability check(s)`: 드라이 런에서 exec ref를 건너뛰었습니다. exec 해석 가능성 검증이 필요하면 `--allow-exec`와 함께 다시 실행하세요.
|
||||
- 배치 모드에서는 실패한 항목을 수정하고 쓰기 전에 `--dry-run`을 다시 실행하세요.
|
||||
|
||||
## 하위 명령
|
||||
|
||||
- `config file`: 활성 config 파일 경로를 출력합니다(`OPENCLAW_CONFIG_PATH` 또는 기본 위치에서 확인됨).
|
||||
|
||||
편집 후에는 게이트웨이를 재시작하세요.
|
||||
|
||||
## 검증
|
||||
|
||||
게이트웨이를 시작하지 않고 현재 config를 활성 스키마에 대해 검증합니다.
|
||||
|
||||
```bash
|
||||
openclaw config validate
|
||||
openclaw config validate --json
|
||||
```
|
||||
77
docs/ko/cli/configure.md
Normal file
77
docs/ko/cli/configure.md
Normal file
@ -0,0 +1,77 @@
|
||||
---
|
||||
read_when:
|
||||
- 자격 증명, 장치 또는 기본 에이전트 설정을 대화형으로 조정하려고 할 때
|
||||
summary: '`openclaw configure`용 CLI 참조(대화형 구성 프롬프트)'
|
||||
title: configure
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:43Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 989569fdb8e1b31ce3438756b3ed9bf18e0c8baf611c5981643ba5925459c98f
|
||||
source_path: cli/configure.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw configure`
|
||||
|
||||
자격 증명, 장치, 기본 에이전트 설정을 위한 대화형 프롬프트입니다.
|
||||
|
||||
참고: **Model** 섹션에는 이제
|
||||
`agents.defaults.models` allowlist(`/model`과 모델 선택기에 표시되는 항목)에 대한 다중 선택이 포함됩니다.
|
||||
|
||||
구성이 provider 인증 선택에서 시작되면 기본 모델 및
|
||||
allowlist 선택기는 해당 provider를 자동으로 우선합니다. Volcengine/BytePlus 같은
|
||||
페어링된 provider의 경우, 동일한 우선순위는 해당 coding-plan
|
||||
변형(`volcengine-plan/*`, `byteplus-plan/*`)에도 일치합니다. preferred-provider
|
||||
필터로 인해 빈 목록이 생성될 경우, configure는 빈 선택기를 표시하는 대신
|
||||
필터링되지 않은 카탈로그로 대체합니다.
|
||||
|
||||
팁: 하위 명령 없이 `openclaw config`를 실행하면 같은 마법사가 열립니다.
|
||||
비대화형 편집에는 `openclaw config get|set|unset`을 사용하세요.
|
||||
|
||||
웹 검색의 경우 `openclaw configure --section web`을 사용하면 provider를 선택하고
|
||||
그 자격 증명을 구성할 수 있습니다. 일부 provider는 provider별
|
||||
후속 프롬프트도 표시합니다.
|
||||
|
||||
- **Grok**는 동일한 `XAI_API_KEY`를 사용하는 선택적 `x_search` 설정을 제공할 수 있으며
|
||||
`x_search` 모델을 선택하도록 할 수 있습니다.
|
||||
- **Kimi**는 Moonshot API 리전(`api.moonshot.ai` vs
|
||||
`api.moonshot.cn`)과 기본 Kimi 웹 검색 모델을 물을 수 있습니다.
|
||||
|
||||
관련 항목:
|
||||
|
||||
- 게이트웨이 구성 참조: [Configuration](/gateway/configuration)
|
||||
- Config CLI: [Config](/cli/config)
|
||||
|
||||
## 옵션
|
||||
|
||||
- `--section <section>`: 반복 가능한 섹션 필터
|
||||
|
||||
사용 가능한 섹션:
|
||||
|
||||
- `workspace`
|
||||
- `model`
|
||||
- `web`
|
||||
- `gateway`
|
||||
- `daemon`
|
||||
- `channels`
|
||||
- `plugins`
|
||||
- `skills`
|
||||
- `health`
|
||||
|
||||
참고:
|
||||
|
||||
- Gateway가 실행되는 위치를 선택하면 항상 `gateway.mode`가 업데이트됩니다. 그것만 필요하다면 다른 섹션 없이 "Continue"를 선택할 수 있습니다.
|
||||
- 채널 지향 서비스(Slack/Discord/Matrix/Microsoft Teams)는 설정 중 채널/룸 allowlist를 묻습니다. 이름 또는 ID를 입력할 수 있으며, 가능하면 마법사가 이름을 ID로 해석합니다.
|
||||
- daemon 설치 단계를 실행하는 경우, 토큰 인증에는 토큰이 필요하고 `gateway.auth.token`이 SecretRef로 관리되면, configure는 SecretRef를 검증하지만 해석된 일반 텍스트 토큰 값을 supervisor 서비스 환경 메타데이터에 유지하지 않습니다.
|
||||
- 토큰 인증에 토큰이 필요하고 구성된 토큰 SecretRef가 해석되지 않으면, configure는 실행 가능한 해결 지침과 함께 daemon 설치를 차단합니다.
|
||||
- `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있고 `gateway.auth.mode`가 설정되지 않은 경우, configure는 mode가 명시적으로 설정될 때까지 daemon 설치를 차단합니다.
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw configure
|
||||
openclaw configure --section web
|
||||
openclaw configure --section model --section channels
|
||||
openclaw configure --section gateway --section daemon
|
||||
```
|
||||
140
docs/ko/cli/cron.md
Normal file
140
docs/ko/cli/cron.md
Normal file
@ -0,0 +1,140 @@
|
||||
---
|
||||
read_when:
|
||||
- 예약된 작업과 웨이크업이 필요할 때
|
||||
- cron 실행 및 로그를 디버깅할 때
|
||||
summary: '`openclaw cron`용 CLI 참조(백그라운드 작업 예약 및 실행)'
|
||||
title: cron
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:59Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: f74ec8847835f24b3970f1b260feeb69c7ab6c6ec7e41615cbb73f37f14a8112
|
||||
source_path: cli/cron.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw cron`
|
||||
|
||||
게이트웨이 스케줄러의 cron 작업을 관리합니다.
|
||||
|
||||
관련 항목:
|
||||
|
||||
- Cron Jobs: [Cron Jobs](/automation/cron-jobs)
|
||||
|
||||
팁: 전체 명령 표면을 보려면 `openclaw cron --help`를 실행하세요.
|
||||
|
||||
참고: 격리된 `cron add` 작업은 기본적으로 `--announce` 전달을 사용합니다. 출력을 내부 전용으로 유지하려면 `--no-deliver`를 사용하세요. `--deliver`는 `--announce`의 더 이상 권장되지 않는 별칭으로 유지됩니다.
|
||||
|
||||
참고: cron이 소유하는 격리 실행은 일반 텍스트 요약을 기대하며, 최종 전송 경로는 실행기가 소유합니다. `--no-deliver`는 실행을 내부 전용으로 유지합니다. 이 옵션은 전달을 에이전트의 메시지 도구로 다시 넘기지 않습니다.
|
||||
|
||||
참고: 원샷(`--at`) 작업은 기본적으로 성공 후 삭제됩니다. 유지하려면 `--keep-after-run`을 사용하세요.
|
||||
|
||||
참고: `--session`은 `main`, `isolated`, `current`, `session:<id>`를 지원합니다. 생성 시 활성 세션에 바인딩하려면 `current`를 사용하고, 명시적인 영구 세션 키를 사용하려면 `session:<id>`를 사용하세요.
|
||||
|
||||
참고: 원샷 CLI 작업의 경우, 오프셋이 없는 `--at` 날짜/시간은 `--tz <iana>`를 함께 전달하지 않는 한 UTC로 처리됩니다. `--tz <iana>`를 함께 전달하면 해당 로컬 벽시계 시간을 지정한 시간대에서 해석합니다.
|
||||
|
||||
참고: 반복 작업은 이제 연속 오류 후 지수적 재시도 백오프(30초 → 1분 → 5분 → 15분 → 60분)를 사용하며, 다음 성공 실행 후 정상 일정으로 돌아갑니다.
|
||||
|
||||
참고: `openclaw cron run`은 이제 수동 실행이 실행 대기열에 들어가자마자 반환됩니다. 성공 응답에는 `{ ok: true, enqueued: true, runId }`가 포함됩니다. 최종 결과를 추적하려면 `openclaw cron runs --id <job-id>`를 사용하세요.
|
||||
|
||||
참고: `openclaw cron run <job-id>`는 기본적으로 강제 실행합니다. 이전의 "기한이 되었을 때만 실행" 동작을 유지하려면 `--due`를 사용하세요.
|
||||
|
||||
참고: 격리된 cron 턴은 오래된 확인 전용 응답을 억제합니다. 첫 번째 결과가 단지 중간 상태 업데이트일 뿐이고, 최종 답변을 담당하는 하위 에이전트 실행이 없다면 cron은 전달 전에 실제 결과를 위해 한 번 더 다시 프롬프트합니다.
|
||||
|
||||
참고: 격리된 cron 실행이 무음 토큰만 반환하는 경우(`NO_REPLY` / `no_reply`), cron은 직접 아웃바운드 전달과 대체 대기열 요약 경로도 함께 억제하므로 채팅에 아무것도 게시되지 않습니다.
|
||||
|
||||
참고: `cron add|edit --model ...`은 해당 작업에 그 선택된 허용 모델을 사용합니다. 모델이 허용되지 않으면 cron은 경고를 출력하고 대신 작업의 에이전트/기본 모델 선택으로 대체합니다. 구성된 대체 체인은 계속 적용되지만, 명시적인 작업별 대체 목록이 없는 일반 모델 재정의는 더 이상 에이전트 기본 모델을 숨겨진 추가 재시도 대상으로 붙이지 않습니다.
|
||||
|
||||
참고: 격리된 cron 모델 우선순위는 Gmail-hook 재정의가 먼저이고, 그다음 작업별 `--model`, 그다음 저장된 cron 세션 모델 재정의, 마지막으로 일반 에이전트/기본 선택입니다.
|
||||
|
||||
참고: 격리된 cron fast mode는 확인된 라이브 모델 선택을 따릅니다. 모델 config `params.fastMode`는 기본적으로 적용되지만, 저장된 세션 `fastMode` 재정의는 여전히 config보다 우선합니다.
|
||||
|
||||
참고: 격리된 실행에서 `LiveSessionModelSwitchError`가 발생하면 cron은 재시도 전에 전환된 provider/model(존재하는 경우 전환된 auth profile 재정의 포함)을 유지합니다. 바깥쪽 재시도 루프는 초기 시도 후 최대 2번의 전환 재시도로 제한되며, 이후에는 무한 루프 대신 중단합니다.
|
||||
|
||||
참고: 실패 알림은 먼저 `delivery.failureDestination`을 사용하고, 그다음 전역 `cron.failureDestination`, 마지막으로 명시적 실패 대상이 구성되지 않은 경우 작업의 기본 announce 대상으로 대체됩니다.
|
||||
|
||||
참고: 보존/정리는 config에서 제어됩니다:
|
||||
|
||||
- `cron.sessionRetention`(기본값 `24h`)은 완료된 격리 실행 세션을 정리합니다.
|
||||
- `cron.runLog.maxBytes` + `cron.runLog.keepLines`는 `~/.openclaw/cron/runs/<jobId>.jsonl`을 정리합니다.
|
||||
|
||||
업그레이드 참고: 현재 전달/저장 형식 이전의 오래된 cron 작업이 있다면 `openclaw doctor --fix`를 실행하세요. 이제 doctor는 레거시 cron 필드(`jobId`, `schedule.cron`, 레거시 `threadId`를 포함한 최상위 전달 필드, payload `provider` 전달 별칭)를 정규화하고, `cron.webhook`이 구성된 경우 단순한 `notify: true` 웹훅 대체 작업을 명시적 웹훅 전달로 마이그레이션합니다.
|
||||
|
||||
## 일반적인 편집
|
||||
|
||||
메시지를 변경하지 않고 전달 설정만 업데이트:
|
||||
|
||||
```bash
|
||||
openclaw cron edit <job-id> --announce --channel telegram --to "123456789"
|
||||
```
|
||||
|
||||
격리된 작업의 전달 비활성화:
|
||||
|
||||
```bash
|
||||
openclaw cron edit <job-id> --no-deliver
|
||||
```
|
||||
|
||||
격리된 작업에 경량 부트스트랩 컨텍스트 활성화:
|
||||
|
||||
```bash
|
||||
openclaw cron edit <job-id> --light-context
|
||||
```
|
||||
|
||||
특정 채널로 announce:
|
||||
|
||||
```bash
|
||||
openclaw cron edit <job-id> --announce --channel slack --to "channel:C1234567890"
|
||||
```
|
||||
|
||||
경량 부트스트랩 컨텍스트로 격리된 작업 생성:
|
||||
|
||||
```bash
|
||||
openclaw cron add \
|
||||
--name "경량 아침 브리프" \
|
||||
--cron "0 7 * * *" \
|
||||
--session isolated \
|
||||
--message "밤사이 업데이트를 요약하세요." \
|
||||
--light-context \
|
||||
--no-deliver
|
||||
```
|
||||
|
||||
`--light-context`는 격리된 agent-turn 작업에만 적용됩니다. cron 실행에서는 경량 모드가 전체 워크스페이스 부트스트랩 세트를 주입하는 대신 부트스트랩 컨텍스트를 비워 둡니다.
|
||||
|
||||
전달 소유권 참고:
|
||||
|
||||
- cron이 소유하는 격리 작업은 항상 최종 사용자 표시 전달을 cron 실행기(`announce`, `webhook`, 또는 내부 전용 `none`)를 통해 라우팅합니다.
|
||||
- 작업이 어떤 외부 수신자에게 메시지를 보내는 것을 언급하는 경우, 에이전트는 직접 보내려고 하지 말고 결과에 의도된 대상을 설명해야 합니다.
|
||||
|
||||
## 일반적인 관리자 명령
|
||||
|
||||
수동 실행:
|
||||
|
||||
```bash
|
||||
openclaw cron run <job-id>
|
||||
openclaw cron run <job-id> --due
|
||||
openclaw cron runs --id <job-id> --limit 50
|
||||
```
|
||||
|
||||
에이전트/세션 재지정:
|
||||
|
||||
```bash
|
||||
openclaw cron edit <job-id> --agent ops
|
||||
openclaw cron edit <job-id> --clear-agent
|
||||
openclaw cron edit <job-id> --session current
|
||||
openclaw cron edit <job-id> --session "session:daily-brief"
|
||||
```
|
||||
|
||||
전달 조정:
|
||||
|
||||
```bash
|
||||
openclaw cron edit <job-id> --announce --channel slack --to "channel:C1234567890"
|
||||
openclaw cron edit <job-id> --best-effort-deliver
|
||||
openclaw cron edit <job-id> --no-best-effort-deliver
|
||||
openclaw cron edit <job-id> --no-deliver
|
||||
```
|
||||
|
||||
실패 전달 참고:
|
||||
|
||||
- `delivery.failureDestination`은 격리된 작업에 지원됩니다.
|
||||
- 메인 세션 작업은 기본 전달 모드가 `webhook`일 때만 `delivery.failureDestination`을 사용할 수 있습니다.
|
||||
- 실패 대상을 별도로 설정하지 않았고 작업이 이미 채널에 announce하고 있다면, 실패 알림은 동일한 announce 대상을 재사용합니다.
|
||||
64
docs/ko/cli/daemon.md
Normal file
64
docs/ko/cli/daemon.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
read_when:
|
||||
- 여전히 스크립트에서 `openclaw daemon ...`을 사용하는 경우
|
||||
- 서비스 수명 주기 명령(install/start/stop/restart/status)이 필요한 경우
|
||||
summary: '`openclaw daemon`용 CLI 참조(Gateway 서비스 관리의 레거시 별칭)'
|
||||
title: daemon
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:51Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 91fdaf3c4f3e7dd4dff86f9b74a653dcba2674573698cf51efc4890077994169
|
||||
source_path: cli/daemon.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw daemon`
|
||||
|
||||
Gateway 서비스 관리 명령의 레거시 별칭입니다.
|
||||
|
||||
`openclaw daemon ...`은 `openclaw gateway ...` 서비스 명령과 동일한 서비스 제어 표면에 매핑됩니다.
|
||||
|
||||
## 사용법
|
||||
|
||||
```bash
|
||||
openclaw daemon status
|
||||
openclaw daemon install
|
||||
openclaw daemon start
|
||||
openclaw daemon stop
|
||||
openclaw daemon restart
|
||||
openclaw daemon uninstall
|
||||
```
|
||||
|
||||
## 하위 명령
|
||||
|
||||
- `status`: 서비스 설치 상태를 표시하고 Gateway 상태를 프로브합니다
|
||||
- `install`: 서비스 설치(`launchd`/`systemd`/`schtasks`)
|
||||
- `uninstall`: 서비스 제거
|
||||
- `start`: 서비스 시작
|
||||
- `stop`: 서비스 중지
|
||||
- `restart`: 서비스 재시작
|
||||
|
||||
## 공통 옵션
|
||||
|
||||
- `status`: `--url`, `--token`, `--password`, `--timeout`, `--no-probe`, `--require-rpc`, `--deep`, `--json`
|
||||
- `install`: `--port`, `--runtime <node|bun>`, `--token`, `--force`, `--json`
|
||||
- 수명 주기(`uninstall|start|stop|restart`): `--json`
|
||||
|
||||
참고:
|
||||
|
||||
- `status`는 가능할 때 프로브 인증을 위해 구성된 auth SecretRef를 확인합니다.
|
||||
- 이 명령 경로에서 필요한 auth SecretRef를 확인할 수 없으면, 프로브 연결/인증이 실패할 때 `daemon status --json`은 `rpc.authWarning`을 보고합니다. `--token`/`--password`를 명시적으로 전달하거나 먼저 secret 소스를 확인하세요.
|
||||
- 프로브가 성공하면, 거짓 양성을 피하기 위해 확인되지 않은 auth-ref 경고는 억제됩니다.
|
||||
- `status --deep`는 최선의 노력 기반 시스템 수준 서비스 스캔을 추가합니다. 다른 gateway 유사 서비스를 찾으면, 사람이 읽는 출력에 정리 힌트를 표시하고 머신당 gateway 하나가 여전히 일반적인 권장 사항임을 경고합니다.
|
||||
- Linux systemd 설치에서는 `status` 토큰 드리프트 검사가 `Environment=`와 `EnvironmentFile=` 유닛 소스를 모두 포함합니다.
|
||||
- 드리프트 검사는 병합된 런타임 env(서비스 명령 env 우선, 이후 프로세스 env 대체)를 사용해 `gateway.auth.token` SecretRef를 확인합니다.
|
||||
- 토큰 인증이 실질적으로 활성 상태가 아니면(명시적 `gateway.auth.mode`가 `password`/`none`/`trusted-proxy`이거나, 모드가 설정되지 않아 password가 우선할 수 있고 어떤 토큰 후보도 우선할 수 없는 경우), 토큰 드리프트 검사는 config 토큰 확인을 건너뜁니다.
|
||||
- 토큰 인증에 토큰이 필요하고 `gateway.auth.token`이 SecretRef로 관리되는 경우, `install`은 SecretRef를 확인할 수 있는지 검증하지만 확인된 토큰을 서비스 환경 메타데이터에 저장하지는 않습니다.
|
||||
- 토큰 인증에 토큰이 필요하고 구성된 토큰 SecretRef를 확인할 수 없으면 설치는 안전하게 실패합니다.
|
||||
- `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있고 `gateway.auth.mode`가 설정되지 않은 경우, 모드를 명시적으로 설정할 때까지 설치가 차단됩니다.
|
||||
- 의도적으로 한 호스트에서 여러 gateway를 실행하는 경우, 포트, config/상태, 워크스페이스를 분리하세요. [/gateway#multiple-gateways-same-host](/gateway#multiple-gateways-same-host)를 참조하세요.
|
||||
|
||||
## 권장
|
||||
|
||||
현재 문서와 예시는 [`openclaw gateway`](/cli/gateway)를 사용하세요.
|
||||
29
docs/ko/cli/dashboard.md
Normal file
29
docs/ko/cli/dashboard.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
read_when:
|
||||
- 현재 토큰으로 Control UI를 열려는 경우
|
||||
- 브라우저를 실행하지 않고 URL을 출력하려는 경우
|
||||
summary: '`openclaw dashboard`용 CLI 참조(Control UI 열기)'
|
||||
title: dashboard
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:43Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: a34cd109a3803e2910fcb4d32f2588aa205a4933819829ef5598f0780f586c94
|
||||
source_path: cli/dashboard.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw dashboard`
|
||||
|
||||
현재 인증을 사용해 Control UI를 엽니다.
|
||||
|
||||
```bash
|
||||
openclaw dashboard
|
||||
openclaw dashboard --no-open
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `dashboard`는 가능할 경우 구성된 `gateway.auth.token` SecretRef를 해석합니다.
|
||||
- SecretRef로 관리되는 토큰(해석되었거나 해석되지 않았거나)의 경우, `dashboard`는 외부 시크릿이 터미널 출력, 클립보드 기록 또는 브라우저 실행 인수에 노출되지 않도록 토큰이 포함되지 않은 URL을 출력/복사/엽니다.
|
||||
- `gateway.auth.token`이 SecretRef로 관리되지만 이 명령 경로에서 해석되지 않은 경우, 이 명령은 잘못된 토큰 플레이스홀더를 포함하는 대신 토큰이 없는 URL과 명시적인 해결 지침을 출력합니다.
|
||||
177
docs/ko/cli/devices.md
Normal file
177
docs/ko/cli/devices.md
Normal file
@ -0,0 +1,177 @@
|
||||
---
|
||||
read_when:
|
||||
- 기기 페어링 요청을 승인하는 중
|
||||
- 기기 토큰을 교체하거나 폐기해야 함
|
||||
summary: '`openclaw devices`용 CLI 참조(기기 페어링 + 토큰 교체/폐기)'
|
||||
title: devices
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:00Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: e2f9fcb8e3508a703590f87caaafd953a5d3557e11c958cbb2be1d67bb8720f4
|
||||
source_path: cli/devices.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw devices`
|
||||
|
||||
기기 페어링 요청과 기기 범위 토큰을 관리합니다.
|
||||
|
||||
## 명령
|
||||
|
||||
### `openclaw devices list`
|
||||
|
||||
대기 중인 페어링 요청과 페어링된 기기를 나열합니다.
|
||||
|
||||
```
|
||||
openclaw devices list
|
||||
openclaw devices list --json
|
||||
```
|
||||
|
||||
대기 요청 출력에는 요청된 역할과 scopes가 포함되므로 승인 전에
|
||||
검토할 수 있습니다.
|
||||
|
||||
### `openclaw devices remove <deviceId>`
|
||||
|
||||
페어링된 기기 항목 하나를 제거합니다.
|
||||
|
||||
페어링된 기기 토큰으로 인증된 경우, 비관리자 호출자는
|
||||
**자신의** 기기 항목만 제거할 수 있습니다. 다른 기기를 제거하려면
|
||||
`operator.admin`이 필요합니다.
|
||||
|
||||
```
|
||||
openclaw devices remove <deviceId>
|
||||
openclaw devices remove <deviceId> --json
|
||||
```
|
||||
|
||||
### `openclaw devices clear --yes [--pending]`
|
||||
|
||||
페어링된 기기를 일괄 제거합니다.
|
||||
|
||||
```
|
||||
openclaw devices clear --yes
|
||||
openclaw devices clear --yes --pending
|
||||
openclaw devices clear --yes --pending --json
|
||||
```
|
||||
|
||||
### `openclaw devices approve [requestId] [--latest]`
|
||||
|
||||
대기 중인 기기 페어링 요청을 승인합니다. `requestId`를 생략하면 OpenClaw가
|
||||
가장 최근의 대기 요청을 자동으로 승인합니다.
|
||||
|
||||
참고: 기기가 변경된 인증 세부 정보(역할/scopes/public
|
||||
key)로 페어링을 다시 시도하면, OpenClaw는 이전 대기 항목을 대체하고 새
|
||||
`requestId`를 발급합니다. 현재 ID를 사용하려면 승인 직전에
|
||||
`openclaw devices list`를 실행하세요.
|
||||
|
||||
```
|
||||
openclaw devices approve
|
||||
openclaw devices approve <requestId>
|
||||
openclaw devices approve --latest
|
||||
```
|
||||
|
||||
### `openclaw devices reject <requestId>`
|
||||
|
||||
대기 중인 기기 페어링 요청을 거부합니다.
|
||||
|
||||
```
|
||||
openclaw devices reject <requestId>
|
||||
```
|
||||
|
||||
### `openclaw devices rotate --device <id> --role <role> [--scope <scope...>]`
|
||||
|
||||
특정 역할의 기기 토큰을 교체합니다(선택적으로 scopes도 업데이트).
|
||||
대상 역할은 해당 기기의 승인된 페어링 계약에 이미 존재해야 하며,
|
||||
교체로 새 미승인 역할을 발급할 수는 없습니다.
|
||||
`--scope`를 생략하면, 저장된 교체 토큰으로 나중에 다시 연결할 때 그
|
||||
토큰의 캐시된 승인 scopes를 재사용합니다. 명시적인 `--scope` 값을 전달하면,
|
||||
그 값이 이후 캐시 토큰 재연결을 위한 저장된 scope 집합이 됩니다.
|
||||
비관리자 페어링 기기 호출자는 **자신의** 기기 토큰만 교체할 수 있습니다.
|
||||
또한 명시적인 `--scope` 값은 호출자 세션 자체의
|
||||
operator scopes 범위 내에 있어야 하며, 교체로 호출자가 이미 가진 것보다 더 넓은 operator 토큰을 발급할 수는 없습니다.
|
||||
|
||||
```
|
||||
openclaw devices rotate --device <deviceId> --role operator --scope operator.read --scope operator.write
|
||||
```
|
||||
|
||||
새 토큰 페이로드를 JSON으로 반환합니다.
|
||||
|
||||
### `openclaw devices revoke --device <id> --role <role>`
|
||||
|
||||
특정 역할의 기기 토큰을 폐기합니다.
|
||||
|
||||
비관리자 페어링 기기 호출자는 **자신의** 기기 토큰만 폐기할 수 있습니다.
|
||||
다른 기기의 토큰을 폐기하려면 `operator.admin`이 필요합니다.
|
||||
|
||||
```
|
||||
openclaw devices revoke --device <deviceId> --role node
|
||||
```
|
||||
|
||||
폐기 결과를 JSON으로 반환합니다.
|
||||
|
||||
## 공통 옵션
|
||||
|
||||
- `--url <url>`: Gateway WebSocket URL (`gateway.remote.url`이 구성된 경우 기본값으로 사용).
|
||||
- `--token <token>`: Gateway 토큰(필요한 경우).
|
||||
- `--password <password>`: Gateway 비밀번호(비밀번호 인증).
|
||||
- `--timeout <ms>`: RPC 타임아웃.
|
||||
- `--json`: JSON 출력(스크립팅에 권장).
|
||||
|
||||
참고: `--url`을 설정하면 CLI는 config 또는 환경 자격 증명으로 폴백하지 않습니다.
|
||||
`--token` 또는 `--password`를 명시적으로 전달하세요. 명시적 자격 증명이 없으면 오류입니다.
|
||||
|
||||
## 참고
|
||||
|
||||
- 토큰 교체는 새 토큰을 반환합니다(민감 정보). 비밀처럼 취급하세요.
|
||||
- 이 명령들은 `operator.pairing`(또는 `operator.admin`) scope가 필요합니다.
|
||||
- 토큰 교체는 해당 기기의 승인된 페어링 역할 집합과 승인된 scope
|
||||
기준선 내에서만 이루어집니다. 잘못된 캐시 토큰 항목이 새
|
||||
교체 대상을 부여하지는 않습니다.
|
||||
- 페어링 기기 토큰 세션에서는 기기 간 관리가 관리자 전용입니다.
|
||||
`remove`, `rotate`, `revoke`는 호출자에게
|
||||
`operator.admin`이 없는 한 자기 자신만 가능합니다.
|
||||
- `devices clear`는 의도적으로 `--yes`로 보호됩니다.
|
||||
- local loopback에서 페어링 scope를 사용할 수 없는 경우(`--url`을 명시적으로 전달하지 않았을 때), list/approve는 로컬 페어링 폴백을 사용할 수 있습니다.
|
||||
- `devices approve`는 `requestId`를 생략하거나 `--latest`를 전달하면 가장 최근의 대기 요청을 자동으로 선택합니다.
|
||||
|
||||
## 토큰 드리프트 복구 체크리스트
|
||||
|
||||
Control UI 또는 다른 클라이언트에서 `AUTH_TOKEN_MISMATCH` 또는 `AUTH_DEVICE_TOKEN_MISMATCH`로 계속 실패할 때 사용하세요.
|
||||
|
||||
1. 현재 gateway 토큰 소스를 확인합니다.
|
||||
|
||||
```bash
|
||||
openclaw config get gateway.auth.token
|
||||
```
|
||||
|
||||
2. 페어링된 기기를 나열하고 영향을 받은 기기 ID를 식별합니다.
|
||||
|
||||
```bash
|
||||
openclaw devices list
|
||||
```
|
||||
|
||||
3. 영향을 받은 기기의 operator 토큰을 교체합니다.
|
||||
|
||||
```bash
|
||||
openclaw devices rotate --device <deviceId> --role operator
|
||||
```
|
||||
|
||||
4. 교체만으로 충분하지 않다면 오래된 페어링을 제거하고 다시 승인합니다.
|
||||
|
||||
```bash
|
||||
openclaw devices remove <deviceId>
|
||||
openclaw devices list
|
||||
openclaw devices approve <requestId>
|
||||
```
|
||||
|
||||
5. 현재 공유 토큰/비밀번호로 클라이언트 연결을 다시 시도합니다.
|
||||
|
||||
참고:
|
||||
|
||||
- 일반 재연결 인증 우선순위는 명시적 공유 토큰/비밀번호 우선, 그다음 명시적 `deviceToken`, 그다음 저장된 기기 토큰, 마지막으로 bootstrap 토큰입니다.
|
||||
- 신뢰된 `AUTH_TOKEN_MISMATCH` 복구에서는 제한된 한 번의 재시도를 위해 공유 토큰과 저장된 기기 토큰을 함께 임시 전송할 수 있습니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- [Dashboard auth troubleshooting](/web/dashboard#if-you-see-unauthorized-1008)
|
||||
- [Gateway troubleshooting](/gateway/troubleshooting#dashboard-control-ui-connectivity)
|
||||
70
docs/ko/cli/directory.md
Normal file
70
docs/ko/cli/directory.md
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
read_when:
|
||||
- 채널의 연락처/그룹/자기 ID를 조회하려고 할 때
|
||||
- 채널 디렉터리 어댑터를 개발하고 있을 때
|
||||
summary: '`openclaw directory`용 CLI 참조(self, peers, groups)'
|
||||
title: directory
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:51Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6a81a037e0a33f77c24b1adabbc4be16ed4d03c419873f3cbdd63f2ce84a1064
|
||||
source_path: cli/directory.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw directory`
|
||||
|
||||
이를 지원하는 채널에 대한 디렉터리 조회입니다(연락처/peer, 그룹, 그리고 “나”).
|
||||
|
||||
## 공통 플래그
|
||||
|
||||
- `--channel <name>`: 채널 ID/별칭(여러 채널이 구성된 경우 필수, 하나만 구성된 경우 자동 선택)
|
||||
- `--account <id>`: 계정 ID(기본값: 채널 기본 계정)
|
||||
- `--json`: JSON 출력
|
||||
|
||||
## 참고
|
||||
|
||||
- `directory`는 다른 명령에 붙여 넣을 수 있는 ID를 찾는 데 도움을 주기 위한 것입니다(특히 `openclaw message send --target ...`).
|
||||
- 많은 채널에서 결과는 라이브 provider 디렉터리가 아니라 구성 기반(allowlist / 구성된 그룹)입니다.
|
||||
- 기본 출력은 탭으로 구분된 `id`(그리고 경우에 따라 `name`)이며, 스크립트에서는 `--json`을 사용하세요.
|
||||
|
||||
## `message send`와 함께 결과 사용하기
|
||||
|
||||
```bash
|
||||
openclaw directory peers list --channel slack --query "U0"
|
||||
openclaw message send --channel slack --target user:U012ABCDEF --message "hello"
|
||||
```
|
||||
|
||||
## ID 형식(채널별)
|
||||
|
||||
- WhatsApp: `+15551234567`(DM), `1234567890-1234567890@g.us`(그룹)
|
||||
- Telegram: `@username` 또는 숫자 채팅 ID, 그룹은 숫자 ID
|
||||
- Slack: `user:U…`, `channel:C…`
|
||||
- Discord: `user:<id>`, `channel:<id>`
|
||||
- Matrix(plugin): `user:@user:server`, `room:!roomId:server`, 또는 `#alias:server`
|
||||
- Microsoft Teams(plugin): `user:<id>`, `conversation:<id>`
|
||||
- Zalo(plugin): 사용자 ID(Bot API)
|
||||
- Zalo Personal / `zalouser`(plugin): `zca`의 스레드 ID(DM/그룹) (`me`, `friend list`, `group list`)
|
||||
|
||||
## 자기 자신("me")
|
||||
|
||||
```bash
|
||||
openclaw directory self --channel zalouser
|
||||
```
|
||||
|
||||
## peers(연락처/사용자)
|
||||
|
||||
```bash
|
||||
openclaw directory peers list --channel zalouser
|
||||
openclaw directory peers list --channel zalouser --query "name"
|
||||
openclaw directory peers list --channel zalouser --limit 50
|
||||
```
|
||||
|
||||
## 그룹
|
||||
|
||||
```bash
|
||||
openclaw directory groups list --channel zalouser
|
||||
openclaw directory groups list --channel zalouser --query "work"
|
||||
openclaw directory groups members --channel zalouser --group-id <id>
|
||||
```
|
||||
55
docs/ko/cli/dns.md
Normal file
55
docs/ko/cli/dns.md
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
read_when:
|
||||
- Tailscale + CoreDNS를 통한 광역 검색(DNS-SD)을 원할 때
|
||||
- You’re setting up split DNS for a custom discovery domain (example: openclaw.internal)
|
||||
summary: '`openclaw dns`용 CLI 참조(광역 검색 도우미)'
|
||||
title: dns
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:50Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 4831fbb7791adfed5195bc4ba36bb248d2bc8830958334211d3c96f824617927
|
||||
source_path: cli/dns.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw dns`
|
||||
|
||||
광역 검색(Tailscale + CoreDNS)을 위한 DNS 도우미입니다. 현재는 macOS + Homebrew CoreDNS에 중점을 두고 있습니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- Gateway 검색: [검색](/gateway/discovery)
|
||||
- 광역 검색 구성: [구성](/gateway/configuration)
|
||||
|
||||
## 설정
|
||||
|
||||
```bash
|
||||
openclaw dns setup
|
||||
openclaw dns setup --domain openclaw.internal
|
||||
openclaw dns setup --apply
|
||||
```
|
||||
|
||||
## `dns setup`
|
||||
|
||||
유니캐스트 DNS-SD 검색을 위한 CoreDNS 설정을 계획하거나 적용합니다.
|
||||
|
||||
옵션:
|
||||
|
||||
- `--domain <domain>`: 광역 검색 도메인(예: `openclaw.internal`)
|
||||
- `--apply`: CoreDNS 구성을 설치하거나 업데이트하고 서비스를 재시작합니다(`sudo` 필요, macOS 전용)
|
||||
|
||||
표시 내용:
|
||||
|
||||
- 확인된 검색 도메인
|
||||
- 존 파일 경로
|
||||
- 현재 tailnet IP
|
||||
- 권장 `openclaw.json` 검색 구성
|
||||
- 설정할 Tailscale Split DNS 네임서버/도메인 값
|
||||
|
||||
참고:
|
||||
|
||||
- `--apply` 없이 실행하면 이 명령은 계획 도우미로만 동작하며 권장 설정을 출력합니다.
|
||||
- `--domain`을 생략하면 OpenClaw는 config의 `discovery.wideArea.domain`을 사용합니다.
|
||||
- `--apply`는 현재 macOS에서만 지원되며 Homebrew CoreDNS를 전제로 합니다.
|
||||
- `--apply`는 필요 시 존 파일을 부트스트랩하고, CoreDNS import stanza가 존재하도록 보장하며, `coredns` brew 서비스를 재시작합니다.
|
||||
35
docs/ko/cli/docs.md
Normal file
35
docs/ko/cli/docs.md
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
read_when:
|
||||
- 터미널에서 실시간 OpenClaw 문서를 검색하려는 경우
|
||||
summary: '`openclaw docs`용 CLI 참조(실시간 문서 인덱스 검색)'
|
||||
title: docs
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:46Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: cfcceed872d7509b9843af3fae733a136bc5e26ded55c2ac47a16489a1636989
|
||||
source_path: cli/docs.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw docs`
|
||||
|
||||
실시간 문서 인덱스를 검색합니다.
|
||||
|
||||
인수:
|
||||
|
||||
- `[query...]`: 실시간 문서 인덱스로 보낼 검색어
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw docs
|
||||
openclaw docs browser existing-session
|
||||
openclaw docs sandbox allowHostControl
|
||||
openclaw docs gateway token secretref
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 쿼리가 없으면 `openclaw docs`는 실시간 문서 검색 진입점을 엽니다.
|
||||
- 여러 단어 쿼리는 하나의 검색 요청으로 그대로 전달됩니다.
|
||||
70
docs/ko/cli/doctor.md
Normal file
70
docs/ko/cli/doctor.md
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
read_when:
|
||||
- 연결/인증 문제가 있어 안내형 수정이 필요할 때
|
||||
- 업데이트 후 정상 여부를 점검하려고 할 때
|
||||
summary: '`openclaw doctor`용 CLI 참조(상태 점검 + 안내형 복구)'
|
||||
title: doctor
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:59Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: d257a9e2797b4b0b50c1020165c8a1cd6a2342381bf9c351645ca37494c881e1
|
||||
source_path: cli/doctor.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw doctor`
|
||||
|
||||
게이트웨이와 채널을 위한 상태 점검 + 빠른 수정 도구입니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- 문제 해결: [문제 해결](/gateway/troubleshooting)
|
||||
- 보안 감사: [보안](/gateway/security)
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw doctor
|
||||
openclaw doctor --repair
|
||||
openclaw doctor --deep
|
||||
openclaw doctor --repair --non-interactive
|
||||
openclaw doctor --generate-gateway-token
|
||||
```
|
||||
|
||||
## 옵션
|
||||
|
||||
- `--no-workspace-suggestions`: 워크스페이스 메모리/검색 제안을 비활성화
|
||||
- `--yes`: 프롬프트 없이 기본값 수락
|
||||
- `--repair`: 프롬프트 없이 권장 복구 적용
|
||||
- `--fix`: `--repair`의 별칭
|
||||
- `--force`: 필요 시 사용자 지정 서비스 구성을 덮어쓰는 것을 포함한 적극적인 복구 적용
|
||||
- `--non-interactive`: 프롬프트 없이 실행, 안전한 마이그레이션만 수행
|
||||
- `--generate-gateway-token`: 게이트웨이 토큰 생성 및 구성
|
||||
- `--deep`: 추가 게이트웨이 설치를 찾기 위해 시스템 서비스를 스캔
|
||||
|
||||
참고:
|
||||
|
||||
- 대화형 프롬프트(키체인/OAuth 수정 등)는 stdin이 TTY이고 `--non-interactive`가 **설정되지 않은 경우에만** 실행됩니다. 헤드리스 실행(cron, Telegram, 터미널 없음)에서는 프롬프트를 건너뜁니다.
|
||||
- `--fix`(`--repair`의 별칭)는 백업을 `~/.openclaw/openclaw.json.bak`에 기록하고 알 수 없는 config 키를 제거하며, 제거된 각 항목을 나열합니다.
|
||||
- 이제 상태 무결성 검사는 세션 디렉터리의 고아 transcript 파일을 감지하며, 공간을 안전하게 회수하기 위해 이를 `.deleted.<timestamp>`로 보관할 수 있습니다.
|
||||
- Doctor는 또한 `~/.openclaw/cron/jobs.json`(또는 `cron.store`)에서 레거시 cron 작업 형식을 스캔하며, 스케줄러가 런타임에 자동 정규화하기 전에 이를 제자리에서 다시 쓸 수 있습니다.
|
||||
- Doctor는 레거시 평면 Talk config(`talk.voiceId`, `talk.modelId` 등)를 `talk.provider` + `talk.providers.<provider>`로 자동 마이그레이션합니다.
|
||||
- 이제 `doctor --fix`를 반복 실행해도 차이가 객체 키 순서뿐인 경우 Talk 정규화를 보고하거나 적용하지 않습니다.
|
||||
- Doctor에는 메모리 검색 준비 상태 점검이 포함되어 있으며, 임베딩 자격 증명이 없을 경우 `openclaw configure --section model`을 권장할 수 있습니다.
|
||||
- sandbox 모드가 활성화되어 있지만 Docker를 사용할 수 없는 경우, doctor는 해결 방법(`install Docker` 또는 `openclaw config set agents.defaults.sandbox.mode off`)과 함께 신호가 강한 경고를 보고합니다.
|
||||
- `gateway.auth.token`/`gateway.auth.password`가 SecretRef로 관리되고 현재 명령 경로에서 사용할 수 없는 경우, doctor는 읽기 전용 경고를 보고하며 일반 텍스트 대체 자격 증명을 쓰지 않습니다.
|
||||
- 수정 경로에서 채널 SecretRef 검사가 실패하더라도, doctor는 조기 종료하지 않고 계속 진행하며 경고를 보고합니다.
|
||||
- Telegram `allowFrom` 사용자 이름 자동 해석(`doctor --fix`)에는 현재 명령 경로에서 해석 가능한 Telegram 토큰이 필요합니다. 토큰 검사를 사용할 수 없으면 doctor는 경고를 보고하고 해당 실행에서는 자동 해석을 건너뜁니다.
|
||||
|
||||
## macOS: `launchctl` env 재정의
|
||||
|
||||
이전에 `launchctl setenv OPENCLAW_GATEWAY_TOKEN ...`(또는 `...PASSWORD`)를 실행한 적이 있다면, 그 값이 config 파일을 재정의하여 지속적인 “unauthorized” 오류를 일으킬 수 있습니다.
|
||||
|
||||
```bash
|
||||
launchctl getenv OPENCLAW_GATEWAY_TOKEN
|
||||
launchctl getenv OPENCLAW_GATEWAY_PASSWORD
|
||||
|
||||
launchctl unsetenv OPENCLAW_GATEWAY_TOKEN
|
||||
launchctl unsetenv OPENCLAW_GATEWAY_PASSWORD
|
||||
```
|
||||
25
docs/ko/cli/flows.md
Normal file
25
docs/ko/cli/flows.md
Normal file
@ -0,0 +1,25 @@
|
||||
---
|
||||
read_when:
|
||||
- 이전 문서나 릴리스 노트에서 openclaw flows를 보게 될 때
|
||||
summary: '리디렉션: flow 명령은 `openclaw tasks flow` 아래에 있습니다'
|
||||
title: flows (리디렉션)
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:53Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: f4b9acefdb4e8dedde08d96986fe9b1ca7f91293281850b68ff9fa28f0516a61
|
||||
source_path: cli/flows.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw tasks flow`
|
||||
|
||||
flow 명령은 독립적인 `flows` 명령이 아니라 `openclaw tasks`의 하위 명령입니다.
|
||||
|
||||
```bash
|
||||
openclaw tasks flow list [--json]
|
||||
openclaw tasks flow show <lookup>
|
||||
openclaw tasks flow cancel <lookup>
|
||||
```
|
||||
|
||||
전체 문서는 [Task Flow](/automation/taskflow) 및 [tasks CLI 참조](/cli/index#tasks)를 참조하세요.
|
||||
309
docs/ko/cli/gateway.md
Normal file
309
docs/ko/cli/gateway.md
Normal file
@ -0,0 +1,309 @@
|
||||
---
|
||||
read_when:
|
||||
- CLI에서 Gateway를 실행할 때(개발 또는 서버)
|
||||
- Gateway 인증, 바인드 모드, 연결성을 디버깅할 때
|
||||
- Bonjour를 통해 Gateway를 발견할 때(local + wide-area DNS-SD)
|
||||
summary: OpenClaw Gateway CLI(`openclaw gateway`) — Gateway 실행, 조회, 발견
|
||||
title: gateway
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:38Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: e311ded0dbad84b8212f0968f3563998d49c5e0eb292a0dc4b3bd3c22d4fa7f2
|
||||
source_path: cli/gateway.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Gateway CLI
|
||||
|
||||
Gateway는 OpenClaw의 WebSocket 서버입니다(채널, 노드, 세션, 훅).
|
||||
|
||||
이 페이지의 하위 명령은 `openclaw gateway …` 아래에 있습니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- [/gateway/bonjour](/gateway/bonjour)
|
||||
- [/gateway/discovery](/gateway/discovery)
|
||||
- [/gateway/configuration](/gateway/configuration)
|
||||
|
||||
## Gateway 실행
|
||||
|
||||
로컬 Gateway 프로세스를 실행합니다:
|
||||
|
||||
```bash
|
||||
openclaw gateway
|
||||
```
|
||||
|
||||
포그라운드 별칭:
|
||||
|
||||
```bash
|
||||
openclaw gateway run
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 기본적으로 Gateway는 `~/.openclaw/openclaw.json`에 `gateway.mode=local`이 설정되어 있지 않으면 시작을 거부합니다. 임시/개발 실행에는 `--allow-unconfigured`를 사용하세요.
|
||||
- `openclaw onboard --mode local`과 `openclaw setup`은 `gateway.mode=local`을 기록해야 합니다. 파일은 존재하지만 `gateway.mode`가 없으면 이를 암묵적으로 local 모드로 가정하지 말고, 손상되었거나 덮어써진 구성으로 보고 복구해야 합니다.
|
||||
- 파일이 존재하고 `gateway.mode`가 없으면, Gateway는 이를 의심스러운 구성 손상으로 간주하고 사용자를 위해 “local로 추측”하지 않습니다.
|
||||
- 인증 없이 loopback을 넘어 바인딩하는 것은 차단됩니다(안전 가드레일).
|
||||
- `SIGUSR1`은 권한이 있으면 프로세스 내부 재시작을 트리거합니다(`commands.restart`는 기본적으로 활성화되어 있으며, 수동 재시작을 막으려면 `commands.restart: false`로 설정하세요. 단, gateway tool/config apply/update는 계속 허용됩니다).
|
||||
- `SIGINT`/`SIGTERM` 핸들러는 gateway 프로세스를 중지하지만, 사용자 지정 터미널 상태를 복원하지는 않습니다. CLI를 TUI 또는 raw-mode 입력으로 감싸는 경우 종료 전에 터미널을 복원하세요.
|
||||
|
||||
### 옵션
|
||||
|
||||
- `--port <port>`: WebSocket 포트(기본값은 config/env에서 오며, 일반적으로 `18789`)
|
||||
- `--bind <loopback|lan|tailnet|auto|custom>`: 리스너 바인드 모드
|
||||
- `--auth <token|password>`: 인증 모드 재정의
|
||||
- `--token <token>`: 토큰 재정의(프로세스에 대해 `OPENCLAW_GATEWAY_TOKEN`도 설정)
|
||||
- `--password <password>`: 비밀번호 재정의. 경고: 인라인 비밀번호는 로컬 프로세스 목록에 노출될 수 있습니다.
|
||||
- `--password-file <path>`: 파일에서 gateway 비밀번호 읽기
|
||||
- `--tailscale <off|serve|funnel>`: Tailscale을 통해 Gateway 노출
|
||||
- `--tailscale-reset-on-exit`: 종료 시 Tailscale serve/funnel 구성 재설정
|
||||
- `--allow-unconfigured`: config에 `gateway.mode=local`이 없어도 gateway 시작 허용. 이는 임시/개발 부트스트랩용 시작 가드를 우회할 뿐이며, config 파일을 기록하거나 복구하지는 않습니다.
|
||||
- `--dev`: 없으면 개발용 config + workspace 생성(`BOOTSTRAP.md` 건너뜀)
|
||||
- `--reset`: 개발용 config + 자격 증명 + 세션 + workspace 재설정(`--dev` 필요)
|
||||
- `--force`: 시작 전에 선택한 포트의 기존 리스너 강제 종료
|
||||
- `--verbose`: 자세한 로그
|
||||
- `--cli-backend-logs`: 콘솔에 CLI 백엔드 로그만 표시(stdout/stderr도 활성화)
|
||||
- `--claude-cli-logs`: `--cli-backend-logs`의 deprecated 별칭
|
||||
- `--ws-log <auto|full|compact>`: websocket 로그 스타일(기본값 `auto`)
|
||||
- `--compact`: `--ws-log compact`의 별칭
|
||||
- `--raw-stream`: 원시 모델 스트림 이벤트를 jsonl로 기록
|
||||
- `--raw-stream-path <path>`: 원시 스트림 jsonl 경로
|
||||
|
||||
## 실행 중인 Gateway 조회
|
||||
|
||||
모든 조회 명령은 WebSocket RPC를 사용합니다.
|
||||
|
||||
출력 모드:
|
||||
|
||||
- 기본값: 사람이 읽기 쉬운 형식(TTY에서는 색상 포함)
|
||||
- `--json`: 기계가 읽기 쉬운 JSON(스타일/스피너 없음)
|
||||
- `--no-color`(또는 `NO_COLOR=1`): 사람용 레이아웃은 유지하면서 ANSI 비활성화
|
||||
|
||||
공통 옵션(지원되는 경우):
|
||||
|
||||
- `--url <url>`: Gateway WebSocket URL
|
||||
- `--token <token>`: Gateway 토큰
|
||||
- `--password <password>`: Gateway 비밀번호
|
||||
- `--timeout <ms>`: 타임아웃/예산(명령마다 다름)
|
||||
- `--expect-final`: “final” 응답을 기다림(에이전트 호출)
|
||||
|
||||
참고: `--url`을 설정하면 CLI는 config 또는 환경 자격 증명으로 대체하지 않습니다.
|
||||
`--token` 또는 `--password`를 명시적으로 전달하세요. 명시적 자격 증명이 없으면 오류입니다.
|
||||
|
||||
### `gateway health`
|
||||
|
||||
```bash
|
||||
openclaw gateway health --url ws://127.0.0.1:18789
|
||||
```
|
||||
|
||||
### `gateway usage-cost`
|
||||
|
||||
세션 로그에서 usage-cost 요약을 가져옵니다.
|
||||
|
||||
```bash
|
||||
openclaw gateway usage-cost
|
||||
openclaw gateway usage-cost --days 7
|
||||
openclaw gateway usage-cost --json
|
||||
```
|
||||
|
||||
옵션:
|
||||
|
||||
- `--days <days>`: 포함할 일 수(기본값 `30`)
|
||||
|
||||
### `gateway status`
|
||||
|
||||
`gateway status`는 Gateway 서비스(launchd/systemd/schtasks)와 선택적 RPC 프로브를 표시합니다.
|
||||
|
||||
```bash
|
||||
openclaw gateway status
|
||||
openclaw gateway status --json
|
||||
openclaw gateway status --require-rpc
|
||||
```
|
||||
|
||||
옵션:
|
||||
|
||||
- `--url <url>`: 명시적 프로브 대상을 추가합니다. 구성된 원격 + localhost도 계속 프로브됩니다.
|
||||
- `--token <token>`: 프로브용 토큰 인증
|
||||
- `--password <password>`: 프로브용 비밀번호 인증
|
||||
- `--timeout <ms>`: 프로브 타임아웃(기본값 `10000`)
|
||||
- `--no-probe`: RPC 프로브 건너뜀(서비스 전용 보기)
|
||||
- `--deep`: 시스템 수준 서비스도 스캔
|
||||
- `--require-rpc`: RPC 프로브가 실패하면 0이 아닌 값으로 종료. `--no-probe`와 함께 사용할 수 없습니다.
|
||||
|
||||
참고:
|
||||
|
||||
- `gateway status`는 로컬 CLI config가 없거나 잘못되어도 진단용으로 계속 사용할 수 있습니다.
|
||||
- `gateway status`는 가능할 때 프로브 인증을 위해 구성된 인증 SecretRef를 해석합니다.
|
||||
- 필요한 인증 SecretRef가 이 명령 경로에서 해석되지 않으면, `gateway status --json`은 프로브 연결/인증이 실패할 때 `rpc.authWarning`을 보고합니다. `--token`/`--password`를 명시적으로 전달하거나 먼저 비밀 소스를 해석하세요.
|
||||
- 프로브가 성공하면 unresolved auth-ref 경고는 거짓 양성을 피하기 위해 억제됩니다.
|
||||
- 단순히 리스닝 서비스만으로는 충분하지 않고 Gateway RPC 자체가 정상이어야 하는 스크립트 및 자동화에서는 `--require-rpc`를 사용하세요.
|
||||
- `--deep`는 추가 launchd/systemd/schtasks 설치를 best-effort로 스캔합니다. 여러 gateway 유사 서비스가 감지되면, 사람용 출력은 정리 힌트를 출력하고 대부분의 설정에서는 머신당 하나의 gateway만 실행해야 한다고 경고합니다.
|
||||
- 사람용 출력에는 해석된 파일 로그 경로와 CLI 대 서비스 config 경로/유효성 스냅샷이 포함되어 profile 또는 state-dir 드리프트 진단에 도움이 됩니다.
|
||||
- Linux systemd 설치에서 서비스 인증 드리프트 검사는 유닛의 `Environment=`와 `EnvironmentFile=` 값을 모두 읽습니다(`%h`, 인용된 경로, 여러 파일, 선택적 `-` 파일 포함).
|
||||
- 드리프트 검사는 병합된 런타임 env를 사용해 `gateway.auth.token` SecretRef를 해석합니다(우선 서비스 명령 env, 그다음 프로세스 env 대체).
|
||||
- 토큰 인증이 실질적으로 활성 상태가 아니면(명시적 `gateway.auth.mode`가 `password`/`none`/`trusted-proxy`이거나, mode가 설정되지 않아 비밀번호가 우선될 수 있고 어떤 토큰 후보도 우선될 수 없는 경우), 토큰 드리프트 검사는 config 토큰 해석을 건너뜁니다.
|
||||
|
||||
### `gateway probe`
|
||||
|
||||
`gateway probe`는 “모든 것을 디버깅”하는 명령입니다. 항상 다음을 프로브합니다:
|
||||
|
||||
- 구성된 원격 gateway(설정된 경우)
|
||||
- local loopback(원격이 구성되어 있어도)
|
||||
|
||||
`--url`을 전달하면 해당 명시적 대상이 둘보다 앞에 추가됩니다. 사람용 출력에서는
|
||||
대상을 다음과 같이 라벨링합니다:
|
||||
|
||||
- `URL (explicit)`
|
||||
- `Remote (configured)` 또는 `Remote (configured, inactive)`
|
||||
- `Local loopback`
|
||||
|
||||
여러 Gateway에 연결할 수 있으면 모두 출력합니다. 격리된 profile/port(예: 구조 봇)를 사용할 때는 여러 Gateway를 지원하지만, 대부분의 설치는 여전히 단일 gateway를 실행합니다.
|
||||
|
||||
```bash
|
||||
openclaw gateway probe
|
||||
openclaw gateway probe --json
|
||||
```
|
||||
|
||||
해석:
|
||||
|
||||
- `Reachable: yes`는 최소 하나의 대상이 WebSocket 연결을 수락했음을 의미합니다.
|
||||
- `RPC: ok`는 상세 RPC 호출(`health`/`status`/`system-presence`/`config.get`)도 성공했음을 의미합니다.
|
||||
- `RPC: limited - missing scope: operator.read`는 연결은 성공했지만 상세 RPC가 범위 제한을 받았음을 의미합니다. 이는 완전한 실패가 아니라 **성능 저하된** 연결 가능성으로 보고됩니다.
|
||||
- 종료 코드는 프로브한 대상 중 어느 것도 연결할 수 없을 때만 0이 아닙니다.
|
||||
|
||||
JSON 참고(`--json`):
|
||||
|
||||
- 최상위:
|
||||
- `ok`: 최소 하나의 대상에 연결 가능
|
||||
- `degraded`: 최소 하나의 대상에서 상세 RPC가 범위 제한을 받음
|
||||
- `primaryTargetId`: 다음 순서로 활성 승자로 취급할 최적 대상: 명시적 URL, SSH 터널, 구성된 원격, 그다음 local loopback
|
||||
- `warnings[]`: `code`, `message`, 선택적 `targetIds`가 포함된 best-effort 경고 기록
|
||||
- `network`: 현재 config와 호스트 네트워킹에서 파생된 local loopback/tailnet URL 힌트
|
||||
- `discovery.timeoutMs`와 `discovery.count`: 이 프로브 패스에 실제로 사용된 발견 예산/결과 수
|
||||
- 대상별(`targets[].connect`):
|
||||
- `ok`: 연결 + degraded 분류 이후의 연결 가능성
|
||||
- `rpcOk`: 전체 상세 RPC 성공
|
||||
- `scopeLimited`: `operator.read` 범위가 없어 상세 RPC 실패
|
||||
|
||||
일반적인 경고 코드:
|
||||
|
||||
- `ssh_tunnel_failed`: SSH 터널 설정 실패, 명령이 직접 프로브로 대체됨
|
||||
- `multiple_gateways`: 둘 이상의 대상에 연결할 수 있었음. 구조 봇 같은 격리 profile을 의도적으로 실행하지 않는 한 흔치 않습니다.
|
||||
- `auth_secretref_unresolved`: 실패한 대상에 대해 구성된 인증 SecretRef를 해석할 수 없었음
|
||||
- `probe_scope_limited`: WebSocket 연결은 성공했지만 상세 RPC가 `operator.read` 누락으로 제한됨
|
||||
|
||||
#### SSH를 통한 원격(Mac 앱 동등 기능)
|
||||
|
||||
macOS 앱의 “Remote over SSH” 모드는 로컬 포트 포워딩을 사용하므로, 원격 gateway(오직 loopback에만 바인딩되어 있을 수 있음)가 `ws://127.0.0.1:<port>`에서 연결 가능해집니다.
|
||||
|
||||
CLI 동등 명령:
|
||||
|
||||
```bash
|
||||
openclaw gateway probe --ssh user@gateway-host
|
||||
```
|
||||
|
||||
옵션:
|
||||
|
||||
- `--ssh <target>`: `user@host` 또는 `user@host:port`(포트 기본값 `22`)
|
||||
- `--ssh-identity <path>`: identity 파일
|
||||
- `--ssh-auto`: 해석된 discovery 엔드포인트(`local.`와 설정된 wide-area 도메인, 있는 경우)에서 발견된 첫 번째 gateway 호스트를 SSH 대상으로 선택. TXT 전용 힌트는 무시됩니다.
|
||||
|
||||
Config(선택 사항, 기본값으로 사용됨):
|
||||
|
||||
- `gateway.remote.sshTarget`
|
||||
- `gateway.remote.sshIdentity`
|
||||
|
||||
### `gateway call <method>`
|
||||
|
||||
저수준 RPC 도우미입니다.
|
||||
|
||||
```bash
|
||||
openclaw gateway call status
|
||||
openclaw gateway call logs.tail --params '{"sinceMs": 60000}'
|
||||
```
|
||||
|
||||
옵션:
|
||||
|
||||
- `--params <json>`: params용 JSON 객체 문자열(기본값 `{}`)
|
||||
- `--url <url>`
|
||||
- `--token <token>`
|
||||
- `--password <password>`
|
||||
- `--timeout <ms>`
|
||||
- `--expect-final`
|
||||
- `--json`
|
||||
|
||||
참고:
|
||||
|
||||
- `--params`는 유효한 JSON이어야 합니다.
|
||||
- `--expect-final`은 중간 이벤트를 스트리밍한 뒤 최종 페이로드를 보내는 에이전트 스타일 RPC에 주로 사용됩니다.
|
||||
|
||||
## Gateway 서비스 관리
|
||||
|
||||
```bash
|
||||
openclaw gateway install
|
||||
openclaw gateway start
|
||||
openclaw gateway stop
|
||||
openclaw gateway restart
|
||||
openclaw gateway uninstall
|
||||
```
|
||||
|
||||
명령 옵션:
|
||||
|
||||
- `gateway status`: `--url`, `--token`, `--password`, `--timeout`, `--no-probe`, `--require-rpc`, `--deep`, `--json`
|
||||
- `gateway install`: `--port`, `--runtime <node|bun>`, `--token`, `--force`, `--json`
|
||||
- `gateway uninstall|start|stop|restart`: `--json`
|
||||
|
||||
참고:
|
||||
|
||||
- `gateway install`은 `--port`, `--runtime`, `--token`, `--force`, `--json`을 지원합니다.
|
||||
- 토큰 인증에 토큰이 필요하고 `gateway.auth.token`이 SecretRef로 관리되면, `gateway install`은 SecretRef를 해석 가능한지 검증하지만 해석된 토큰을 서비스 환경 메타데이터에 저장하지는 않습니다.
|
||||
- 토큰 인증에 토큰이 필요하고 구성된 토큰 SecretRef가 해석되지 않으면, 설치는 대체 일반 텍스트를 저장하는 대신 fail closed합니다.
|
||||
- `gateway run`에서 비밀번호 인증을 사용할 때는 인라인 `--password`보다 `OPENCLAW_GATEWAY_PASSWORD`, `--password-file`, 또는 SecretRef 기반 `gateway.auth.password`를 권장합니다.
|
||||
- inferred auth 모드에서는 셸 전용 `OPENCLAW_GATEWAY_PASSWORD`가 install 토큰 요구 사항을 완화하지 않습니다. 관리형 서비스를 설치할 때는 내구성 있는 config(`gateway.auth.password` 또는 config `env`)를 사용하세요.
|
||||
- `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있고 `gateway.auth.mode`가 설정되지 않으면, mode가 명시적으로 설정될 때까지 install이 차단됩니다.
|
||||
- 수명 주기 명령은 스크립팅용으로 `--json`을 허용합니다.
|
||||
|
||||
## Gateway 발견(Bonjour)
|
||||
|
||||
`gateway discover`는 Gateway 비콘(`_openclaw-gw._tcp`)을 스캔합니다.
|
||||
|
||||
- 멀티캐스트 DNS-SD: `local.`
|
||||
- 유니캐스트 DNS-SD(Wide-Area Bonjour): 도메인 선택(예: `openclaw.internal.`) 후 split DNS + DNS 서버 설정, 자세한 내용은 [/gateway/bonjour](/gateway/bonjour)
|
||||
|
||||
Bonjour discovery가 활성화된 Gateway만(기본값) 비콘을 광고합니다.
|
||||
|
||||
Wide-Area discovery 레코드에는 다음이 포함됩니다(TXT):
|
||||
|
||||
- `role`(gateway 역할 힌트)
|
||||
- `transport`(전송 힌트, 예: `gateway`)
|
||||
- `gatewayPort`(WebSocket 포트, 일반적으로 `18789`)
|
||||
- `sshPort`(선택 사항; 없으면 클라이언트는 SSH 대상 포트를 기본값 `22`로 사용)
|
||||
- `tailnetDns`(사용 가능한 경우 MagicDNS 호스트명)
|
||||
- `gatewayTls` / `gatewayTlsSha256`(TLS 활성화 + 인증서 지문)
|
||||
- `cliPath`(wide-area 영역에 기록되는 원격 설치 힌트)
|
||||
|
||||
### `gateway discover`
|
||||
|
||||
```bash
|
||||
openclaw gateway discover
|
||||
```
|
||||
|
||||
옵션:
|
||||
|
||||
- `--timeout <ms>`: 명령별 타임아웃(browse/resolve), 기본값 `2000`
|
||||
- `--json`: 기계가 읽기 쉬운 출력(스타일/스피너도 비활성화)
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw gateway discover --timeout 4000
|
||||
openclaw gateway discover --json | jq '.beacons[].wsUrl'
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- CLI는 `local.`과 활성화된 경우 구성된 wide-area 도메인을 함께 스캔합니다.
|
||||
- JSON 출력의 `wsUrl`은 `lanHost`나 `tailnetDns` 같은 TXT 전용 힌트가 아니라 해석된 서비스 엔드포인트에서 파생됩니다.
|
||||
- `local.` mDNS에서는 `discovery.mdns.mode`가 `full`일 때만 `sshPort`와 `cliPath`가 브로드캐스트됩니다. Wide-area DNS-SD는 여전히 `cliPath`를 기록하며, `sshPort`도 সেখানে 선택 사항으로 유지됩니다.
|
||||
40
docs/ko/cli/health.md
Normal file
40
docs/ko/cli/health.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
read_when:
|
||||
- 실행 중인 Gateway의 상태를 빠르게 확인하려는 경우
|
||||
summary: '`openclaw health`용 CLI 참조(RPC를 통한 gateway 상태 스냅샷)'
|
||||
title: health
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:37:57Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 4ed2b9ceefee6159cabaae9172d2d88174626456e7503d5d2bcd142634188ff0
|
||||
source_path: cli/health.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw health`
|
||||
|
||||
실행 중인 Gateway에서 상태 정보를 가져옵니다.
|
||||
|
||||
옵션:
|
||||
|
||||
- `--json`: 기계가 읽을 수 있는 출력
|
||||
- `--timeout <ms>`: 밀리초 단위 연결 타임아웃(기본값 `10000`)
|
||||
- `--verbose`: 자세한 로깅
|
||||
- `--debug`: `--verbose`의 별칭
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw health
|
||||
openclaw health --json
|
||||
openclaw health --timeout 2500
|
||||
openclaw health --verbose
|
||||
openclaw health --debug
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 기본 `openclaw health`는 실행 중인 gateway에 상태 스냅샷을 요청합니다. gateway에 이미 최신 캐시 스냅샷이 있으면, 해당 캐시된 페이로드를 반환하고 백그라운드에서 새로 고칠 수 있습니다.
|
||||
- `--verbose`는 라이브 프로브를 강제하고, gateway 연결 세부 정보를 출력하며, 사람이 읽을 수 있는 출력을 구성된 모든 계정과 agent에 걸쳐 확장합니다.
|
||||
- 여러 agent가 구성된 경우 출력에는 agent별 세션 저장소가 포함됩니다.
|
||||
337
docs/ko/cli/hooks.md
Normal file
337
docs/ko/cli/hooks.md
Normal file
@ -0,0 +1,337 @@
|
||||
---
|
||||
read_when:
|
||||
- 에이전트 hooks를 관리하려는 경우
|
||||
- hook 사용 가능 여부를 확인하거나 workspace hooks를 활성화하려는 경우
|
||||
summary: '`openclaw hooks`용 CLI 참조(에이전트 hooks)'
|
||||
title: hooks
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:19Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 8dc9144e9844e9c3cdef2514098eb170543746fcc55ca5a1cc746c12d80209e7
|
||||
source_path: cli/hooks.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw hooks`
|
||||
|
||||
에이전트 hooks를 관리합니다(`/new`, `/reset`, gateway 시작과 같은 명령을 위한 이벤트 기반 자동화).
|
||||
|
||||
하위 명령 없이 `openclaw hooks`를 실행하면 `openclaw hooks list`와 동일합니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- Hooks: [Hooks](/automation/hooks)
|
||||
- Plugin hooks: [Plugin hooks](/plugins/architecture#provider-runtime-hooks)
|
||||
|
||||
## 모든 hooks 나열
|
||||
|
||||
```bash
|
||||
openclaw hooks list
|
||||
```
|
||||
|
||||
workspace, managed, extra, bundled 디렉터리에서 검색된 모든 hooks를 나열합니다.
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `--eligible`: 적격한 hook만 표시(요구 사항 충족)
|
||||
- `--json`: JSON으로 출력
|
||||
- `-v, --verbose`: 누락된 요구 사항을 포함한 자세한 정보 표시
|
||||
|
||||
**출력 예시:**
|
||||
|
||||
```
|
||||
Hooks (4/4 ready)
|
||||
|
||||
Ready:
|
||||
🚀 boot-md ✓ - gateway 시작 시 BOOT.md 실행
|
||||
📎 bootstrap-extra-files ✓ - 에이전트 bootstrap 중 추가 workspace bootstrap 파일 주입
|
||||
📝 command-logger ✓ - 모든 명령 이벤트를 중앙 감사 파일에 기록
|
||||
💾 session-memory ✓ - /new 또는 /reset 명령이 실행되면 세션 컨텍스트를 메모리에 저장
|
||||
```
|
||||
|
||||
**예시(상세):**
|
||||
|
||||
```bash
|
||||
openclaw hooks list --verbose
|
||||
```
|
||||
|
||||
적격하지 않은 hooks에 대해 누락된 요구 사항을 표시합니다.
|
||||
|
||||
**예시(JSON):**
|
||||
|
||||
```bash
|
||||
openclaw hooks list --json
|
||||
```
|
||||
|
||||
프로그래밍 방식으로 사용할 수 있도록 구조화된 JSON을 반환합니다.
|
||||
|
||||
## Hook 정보 가져오기
|
||||
|
||||
```bash
|
||||
openclaw hooks info <name>
|
||||
```
|
||||
|
||||
특정 hook에 대한 자세한 정보를 표시합니다.
|
||||
|
||||
**인수:**
|
||||
|
||||
- `<name>`: hook 이름 또는 hook 키(예: `session-memory`)
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `--json`: JSON으로 출력
|
||||
|
||||
**예시:**
|
||||
|
||||
```bash
|
||||
openclaw hooks info session-memory
|
||||
```
|
||||
|
||||
**출력:**
|
||||
|
||||
```
|
||||
💾 session-memory ✓ Ready
|
||||
|
||||
/new 또는 /reset 명령이 실행되면 세션 컨텍스트를 메모리에 저장
|
||||
|
||||
Details:
|
||||
Source: openclaw-bundled
|
||||
Path: /path/to/openclaw/hooks/bundled/session-memory/HOOK.md
|
||||
Handler: /path/to/openclaw/hooks/bundled/session-memory/handler.ts
|
||||
Homepage: https://docs.openclaw.ai/automation/hooks#session-memory
|
||||
Events: command:new, command:reset
|
||||
|
||||
Requirements:
|
||||
Config: ✓ workspace.dir
|
||||
```
|
||||
|
||||
## Hooks 적격성 확인
|
||||
|
||||
```bash
|
||||
openclaw hooks check
|
||||
```
|
||||
|
||||
hook 적격성 상태 요약(준비 완료 개수와 미준비 개수)을 표시합니다.
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `--json`: JSON으로 출력
|
||||
|
||||
**출력 예시:**
|
||||
|
||||
```
|
||||
Hooks Status
|
||||
|
||||
Total hooks: 4
|
||||
Ready: 4
|
||||
Not ready: 0
|
||||
```
|
||||
|
||||
## Hook 활성화
|
||||
|
||||
```bash
|
||||
openclaw hooks enable <name>
|
||||
```
|
||||
|
||||
config(기본값: `~/.openclaw/openclaw.json`)에 추가하여 특정 hook을 활성화합니다.
|
||||
|
||||
**참고:** workspace hooks는 여기서 또는 config에서 활성화하기 전까지 기본적으로 비활성화됩니다. plugins가 관리하는 hooks는 `openclaw hooks list`에서 `plugin:<id>`로 표시되며 여기서 활성화/비활성화할 수 없습니다. 대신 plugin 자체를 활성화/비활성화하세요.
|
||||
|
||||
**인수:**
|
||||
|
||||
- `<name>`: hook 이름(예: `session-memory`)
|
||||
|
||||
**예시:**
|
||||
|
||||
```bash
|
||||
openclaw hooks enable session-memory
|
||||
```
|
||||
|
||||
**출력:**
|
||||
|
||||
```
|
||||
✓ Enabled hook: 💾 session-memory
|
||||
```
|
||||
|
||||
**수행 내용:**
|
||||
|
||||
- hook이 존재하고 적격한지 확인
|
||||
- config의 `hooks.internal.entries.<name>.enabled = true`를 업데이트
|
||||
- config를 디스크에 저장
|
||||
|
||||
hook이 `<workspace>/hooks/`에서 온 경우, Gateway가 이를 로드하기 전에
|
||||
이 옵트인 단계가 필요합니다.
|
||||
|
||||
**활성화 후:**
|
||||
|
||||
- hooks가 다시 로드되도록 gateway를 재시작하세요(macOS에서는 메뉴 바 앱 재시작, 개발 환경에서는 gateway 프로세스 재시작).
|
||||
|
||||
## Hook 비활성화
|
||||
|
||||
```bash
|
||||
openclaw hooks disable <name>
|
||||
```
|
||||
|
||||
config를 업데이트하여 특정 hook을 비활성화합니다.
|
||||
|
||||
**인수:**
|
||||
|
||||
- `<name>`: hook 이름(예: `command-logger`)
|
||||
|
||||
**예시:**
|
||||
|
||||
```bash
|
||||
openclaw hooks disable command-logger
|
||||
```
|
||||
|
||||
**출력:**
|
||||
|
||||
```
|
||||
⏸ Disabled hook: 📝 command-logger
|
||||
```
|
||||
|
||||
**비활성화 후:**
|
||||
|
||||
- hooks가 다시 로드되도록 gateway를 재시작하세요
|
||||
|
||||
## 참고
|
||||
|
||||
- `openclaw hooks list --json`, `info --json`, `check --json`은 구조화된 JSON을 stdout에 직접 씁니다.
|
||||
- plugin이 관리하는 hooks는 여기서 활성화하거나 비활성화할 수 없습니다. 대신 소유 plugin을 활성화하거나 비활성화하세요.
|
||||
|
||||
## Hook 팩 설치
|
||||
|
||||
```bash
|
||||
openclaw plugins install <package> # 먼저 ClawHub, 그다음 npm
|
||||
openclaw plugins install <package> --pin # 버전 고정
|
||||
openclaw plugins install <path> # 로컬 경로
|
||||
```
|
||||
|
||||
통합 plugins 설치 프로그램을 통해 hook 팩을 설치합니다.
|
||||
|
||||
`openclaw hooks install`도 호환성 별칭으로 계속 작동하지만, 지원 중단 경고를 출력하고 `openclaw plugins install`로 전달합니다.
|
||||
|
||||
npm 스펙은 **레지스트리 전용**입니다(패키지 이름 + 선택적 **정확한 버전** 또는 **dist-tag**). Git/URL/파일 스펙과 semver 범위는 거부됩니다. 안전을 위해 종속성 설치는 `--ignore-scripts`로 실행됩니다.
|
||||
|
||||
bare 스펙과 `@latest`는 stable 트랙을 유지합니다. npm이 이들 중 하나를 prerelease로 해석하면, OpenClaw는 중지하고 `@beta`/`@rc` 같은 prerelease 태그 또는 정확한 prerelease 버전으로 명시적으로 옵트인하라고 요청합니다.
|
||||
|
||||
**수행 내용:**
|
||||
|
||||
- hook 팩을 `~/.openclaw/hooks/<id>`로 복사
|
||||
- 설치된 hooks를 `hooks.internal.entries.*`에서 활성화
|
||||
- 설치 정보를 `hooks.internal.installs`에 기록
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `-l, --link`: 로컬 디렉터리를 복사하는 대신 링크합니다(`hooks.internal.load.extraDirs`에 추가)
|
||||
- `--pin`: npm 설치를 `hooks.internal.installs`에 정확한 해석 결과 `name@version`으로 기록
|
||||
|
||||
**지원되는 아카이브:** `.zip`, `.tgz`, `.tar.gz`, `.tar`
|
||||
|
||||
**예시:**
|
||||
|
||||
```bash
|
||||
# 로컬 디렉터리
|
||||
openclaw plugins install ./my-hook-pack
|
||||
|
||||
# 로컬 아카이브
|
||||
openclaw plugins install ./my-hook-pack.zip
|
||||
|
||||
# NPM 패키지
|
||||
openclaw plugins install @openclaw/my-hook-pack
|
||||
|
||||
# 복사하지 않고 로컬 디렉터리 링크
|
||||
openclaw plugins install -l ./my-hook-pack
|
||||
```
|
||||
|
||||
링크된 hook 팩은 workspace hooks가 아니라 운영자가 구성한
|
||||
디렉터리의 managed hooks로 취급됩니다.
|
||||
|
||||
## Hook 팩 업데이트
|
||||
|
||||
```bash
|
||||
openclaw plugins update <id>
|
||||
openclaw plugins update --all
|
||||
```
|
||||
|
||||
통합 plugins 업데이터를 통해 추적 중인 npm 기반 hook 팩을 업데이트합니다.
|
||||
|
||||
`openclaw hooks update`도 호환성 별칭으로 계속 작동하지만, 지원 중단 경고를 출력하고 `openclaw plugins update`로 전달합니다.
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `--all`: 추적 중인 모든 hook 팩 업데이트
|
||||
- `--dry-run`: 쓰기 없이 변경 사항만 표시
|
||||
|
||||
저장된 무결성 해시가 존재하고 가져온 아티팩트 해시가 변경된 경우,
|
||||
OpenClaw는 경고를 출력하고 진행 전에 확인을 요청합니다. CI/비대화형 실행에서 프롬프트를 우회하려면 전역 `--yes`를 사용하세요.
|
||||
|
||||
## 번들 hooks
|
||||
|
||||
### session-memory
|
||||
|
||||
`/new` 또는 `/reset`을 실행할 때 세션 컨텍스트를 메모리에 저장합니다.
|
||||
|
||||
**활성화:**
|
||||
|
||||
```bash
|
||||
openclaw hooks enable session-memory
|
||||
```
|
||||
|
||||
**출력:** `~/.openclaw/workspace/memory/YYYY-MM-DD-slug.md`
|
||||
|
||||
**참조:** [session-memory 문서](/automation/hooks#session-memory)
|
||||
|
||||
### bootstrap-extra-files
|
||||
|
||||
`agent:bootstrap` 동안 추가 bootstrap 파일(예: monorepo 로컬 `AGENTS.md` / `TOOLS.md`)을 주입합니다.
|
||||
|
||||
**활성화:**
|
||||
|
||||
```bash
|
||||
openclaw hooks enable bootstrap-extra-files
|
||||
```
|
||||
|
||||
**참조:** [bootstrap-extra-files 문서](/automation/hooks#bootstrap-extra-files)
|
||||
|
||||
### command-logger
|
||||
|
||||
모든 명령 이벤트를 중앙 감사 파일에 기록합니다.
|
||||
|
||||
**활성화:**
|
||||
|
||||
```bash
|
||||
openclaw hooks enable command-logger
|
||||
```
|
||||
|
||||
**출력:** `~/.openclaw/logs/commands.log`
|
||||
|
||||
**로그 보기:**
|
||||
|
||||
```bash
|
||||
# 최근 명령
|
||||
tail -n 20 ~/.openclaw/logs/commands.log
|
||||
|
||||
# 보기 좋게 출력
|
||||
cat ~/.openclaw/logs/commands.log | jq .
|
||||
|
||||
# 작업별 필터링
|
||||
grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
|
||||
```
|
||||
|
||||
**참조:** [command-logger 문서](/automation/hooks#command-logger)
|
||||
|
||||
### boot-md
|
||||
|
||||
gateway가 시작될 때(채널 시작 후) `BOOT.md`를 실행합니다.
|
||||
|
||||
**이벤트**: `gateway:startup`
|
||||
|
||||
**활성화**:
|
||||
|
||||
```bash
|
||||
openclaw hooks enable boot-md
|
||||
```
|
||||
|
||||
**참조:** [boot-md 문서](/automation/hooks#boot-md)
|
||||
1841
docs/ko/cli/index.md
Normal file
1841
docs/ko/cli/index.md
Normal file
File diff suppressed because it is too large
Load Diff
66
docs/ko/cli/logs.md
Normal file
66
docs/ko/cli/logs.md
Normal file
@ -0,0 +1,66 @@
|
||||
---
|
||||
read_when:
|
||||
- 원격으로(SSH 없이) 게이트웨이 로그를 tail해야 할 때
|
||||
- 도구용 JSON 로그 줄이 필요할 때
|
||||
summary: '`openclaw logs`용 CLI 참조(RPC를 통한 게이트웨이 로그 tail)'
|
||||
title: logs
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:07Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 238a52e31a9a332cab513ced049e92d032b03c50376895ce57dffa2ee7d1e4b4
|
||||
source_path: cli/logs.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw logs`
|
||||
|
||||
RPC를 통해 게이트웨이 파일 로그를 tail합니다(원격 모드에서 동작).
|
||||
|
||||
관련 문서:
|
||||
|
||||
- 로깅 개요: [로깅](/logging)
|
||||
- 게이트웨이 CLI: [gateway](/cli/gateway)
|
||||
|
||||
## 옵션
|
||||
|
||||
- `--limit <n>`: 반환할 최대 로그 줄 수(기본값 `200`)
|
||||
- `--max-bytes <n>`: 로그 파일에서 읽을 최대 바이트 수(기본값 `250000`)
|
||||
- `--follow`: 로그 스트림을 계속 따라감
|
||||
- `--interval <ms>`: follow 중 폴링 간격(기본값 `1000`)
|
||||
- `--json`: 줄 단위 JSON 이벤트 출력
|
||||
- `--plain`: 스타일 서식 없는 일반 텍스트 출력
|
||||
- `--no-color`: ANSI 색상 비활성화
|
||||
- `--local-time`: 타임스탬프를 로컬 시간대로 렌더링
|
||||
|
||||
## 공통 게이트웨이 RPC 옵션
|
||||
|
||||
`openclaw logs`는 표준 게이트웨이 클라이언트 플래그도 지원합니다:
|
||||
|
||||
- `--url <url>`: 게이트웨이 WebSocket URL
|
||||
- `--token <token>`: 게이트웨이 토큰
|
||||
- `--timeout <ms>`: 타임아웃(ms, 기본값 `30000`)
|
||||
- `--expect-final`: 게이트웨이 호출이 agent 기반일 때 최종 응답 대기
|
||||
|
||||
`--url`을 전달하면 CLI는 config 또는 환경 자격 증명을 자동 적용하지 않습니다. 대상 게이트웨이에 인증이 필요하면 `--token`을 명시적으로 포함하세요.
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw logs
|
||||
openclaw logs --follow
|
||||
openclaw logs --follow --interval 2000
|
||||
openclaw logs --limit 500 --max-bytes 500000
|
||||
openclaw logs --json
|
||||
openclaw logs --plain
|
||||
openclaw logs --no-color
|
||||
openclaw logs --limit 500
|
||||
openclaw logs --local-time
|
||||
openclaw logs --follow --local-time
|
||||
openclaw logs --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"
|
||||
```
|
||||
|
||||
## 참고
|
||||
|
||||
- 타임스탬프를 로컬 시간대로 렌더링하려면 `--local-time`을 사용하세요.
|
||||
- local loopback 게이트웨이가 페어링을 요청하면 `openclaw logs`는 자동으로 구성된 로컬 로그 파일로 대체합니다. 명시적인 `--url` 대상은 이 대체 동작을 사용하지 않습니다.
|
||||
499
docs/ko/cli/mcp.md
Normal file
499
docs/ko/cli/mcp.md
Normal file
@ -0,0 +1,499 @@
|
||||
---
|
||||
read_when:
|
||||
- Codex, Claude Code 또는 다른 MCP 클라이언트를 OpenClaw 기반 채널에 연결할 때
|
||||
- '`openclaw mcp serve`를 실행할 때'
|
||||
- OpenClaw에 저장된 MCP 서버 정의를 관리할 때
|
||||
summary: MCP를 통해 OpenClaw 채널 대화를 노출하고 저장된 MCP 서버 정의를 관리합니다
|
||||
title: mcp
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:59Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: b35de9e14f96666eeca2f93c06cb214e691152f911d45ee778efe9cf5bf96cc2
|
||||
source_path: cli/mcp.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# mcp
|
||||
|
||||
`openclaw mcp`에는 두 가지 역할이 있습니다:
|
||||
|
||||
- `openclaw mcp serve`로 OpenClaw를 MCP 서버로 실행
|
||||
- `list`, `show`,
|
||||
`set`, `unset`으로 OpenClaw 소유의 아웃바운드 MCP 서버 정의 관리
|
||||
|
||||
즉:
|
||||
|
||||
- `serve`는 OpenClaw가 MCP 서버로 동작하는 경우입니다
|
||||
- `list` / `show` / `set` / `unset`은 OpenClaw가 나중에 자체 런타임에서 소비할 수 있는 다른 MCP 서버들을 위한 클라이언트 측 레지스트리로 동작하는 경우입니다
|
||||
|
||||
OpenClaw가 직접 코딩 하네스
|
||||
세션을 호스팅하고 그 런타임을 ACP를 통해 라우팅해야 한다면 [`openclaw acp`](/cli/acp)를 사용하세요.
|
||||
|
||||
## OpenClaw를 MCP 서버로 사용
|
||||
|
||||
이것은 `openclaw mcp serve` 경로입니다.
|
||||
|
||||
## `serve`를 사용해야 하는 경우
|
||||
|
||||
다음과 같은 경우 `openclaw mcp serve`를 사용하세요:
|
||||
|
||||
- Codex, Claude Code 또는 다른 MCP 클라이언트가
|
||||
OpenClaw 기반 채널 대화와 직접 통신해야 하는 경우
|
||||
- 이미 라우팅된 세션이 있는 로컬 또는 원격 OpenClaw Gateway가 있는 경우
|
||||
- 채널별로 별도의 브리지를 실행하는 대신, OpenClaw의 채널 백엔드 전반에서 동작하는 단일 MCP 서버를 원할 경우
|
||||
|
||||
OpenClaw가 코딩
|
||||
런타임 자체를 호스팅하고 에이전트 세션을 OpenClaw 내부에 유지해야 한다면 대신 [`openclaw acp`](/cli/acp)를 사용하세요.
|
||||
|
||||
## 작동 방식
|
||||
|
||||
`openclaw mcp serve`는 stdio MCP 서버를 시작합니다. MCP 클라이언트가 해당
|
||||
프로세스를 소유합니다. 클라이언트가 stdio 세션을 열어 두는 동안 브리지는
|
||||
로컬 또는 원격 OpenClaw Gateway에 WebSocket으로 연결하고, 라우팅된 채널
|
||||
대화를 MCP를 통해 노출합니다.
|
||||
|
||||
수명 주기:
|
||||
|
||||
1. MCP 클라이언트가 `openclaw mcp serve`를 실행합니다
|
||||
2. 브리지가 Gateway에 연결합니다
|
||||
3. 라우팅된 세션이 MCP 대화와 transcript/history 도구가 됩니다
|
||||
4. 브리지가 연결되어 있는 동안 라이브 이벤트가 메모리에 대기열로 저장됩니다
|
||||
5. Claude 채널 모드가 활성화되어 있으면 동일한 세션이
|
||||
Claude 전용 푸시 알림도 받을 수 있습니다
|
||||
|
||||
중요한 동작:
|
||||
|
||||
- 라이브 큐 상태는 브리지가 연결될 때 시작됩니다
|
||||
- 이전 transcript 기록은 `messages_read`로 읽습니다
|
||||
- Claude 푸시 알림은 MCP 세션이 살아 있는 동안에만 존재합니다
|
||||
- 클라이언트가 연결을 끊으면 브리지가 종료되고 라이브 큐도 사라집니다
|
||||
|
||||
## 클라이언트 모드 선택
|
||||
|
||||
같은 브리지를 두 가지 방식으로 사용할 수 있습니다:
|
||||
|
||||
- 일반 MCP 클라이언트: 표준 MCP 도구만 사용합니다. `conversations_list`,
|
||||
`messages_read`, `events_poll`, `events_wait`, `messages_send` 및
|
||||
승인 도구를 사용하세요.
|
||||
- Claude Code: 표준 MCP 도구와 Claude 전용 채널 어댑터를 함께 사용합니다.
|
||||
`--claude-channel-mode on`을 활성화하거나 기본값 `auto`를 그대로 두세요.
|
||||
|
||||
현재 `auto`는 `on`과 동일하게 동작합니다. 아직 클라이언트 기능 감지는 없습니다.
|
||||
|
||||
## `serve`가 노출하는 항목
|
||||
|
||||
브리지는 기존 Gateway 세션 경로 메타데이터를 사용하여 채널 기반
|
||||
대화를 노출합니다. OpenClaw가 이미 다음과 같은 알려진 경로를 가진 세션 상태를 보유하고 있으면
|
||||
대화가 나타납니다:
|
||||
|
||||
- `channel`
|
||||
- 수신자 또는 대상 메타데이터
|
||||
- 선택적 `accountId`
|
||||
- 선택적 `threadId`
|
||||
|
||||
이를 통해 MCP 클라이언트는 한 곳에서 다음을 할 수 있습니다:
|
||||
|
||||
- 최근 라우팅된 대화 나열
|
||||
- 최근 transcript 기록 읽기
|
||||
- 새 수신 이벤트 대기
|
||||
- 같은 경로를 통해 응답 다시 보내기
|
||||
- 브리지가 연결된 동안 도착한 승인 요청 보기
|
||||
|
||||
## 사용법
|
||||
|
||||
```bash
|
||||
# 로컬 Gateway
|
||||
openclaw mcp serve
|
||||
|
||||
# 원격 Gateway
|
||||
openclaw mcp serve --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.token
|
||||
|
||||
# 비밀번호 인증을 사용하는 원격 Gateway
|
||||
openclaw mcp serve --url wss://gateway-host:18789 --password-file ~/.openclaw/gateway.password
|
||||
|
||||
# 자세한 브리지 로그 활성화
|
||||
openclaw mcp serve --verbose
|
||||
|
||||
# Claude 전용 푸시 알림 비활성화
|
||||
openclaw mcp serve --claude-channel-mode off
|
||||
```
|
||||
|
||||
## 브리지 도구
|
||||
|
||||
현재 브리지는 다음 MCP 도구를 노출합니다:
|
||||
|
||||
- `conversations_list`
|
||||
- `conversation_get`
|
||||
- `messages_read`
|
||||
- `attachments_fetch`
|
||||
- `events_poll`
|
||||
- `events_wait`
|
||||
- `messages_send`
|
||||
- `permissions_list_open`
|
||||
- `permissions_respond`
|
||||
|
||||
### `conversations_list`
|
||||
|
||||
Gateway 세션 상태에 이미 경로 메타데이터가 있는 최근 세션 기반 대화를 나열합니다.
|
||||
|
||||
유용한 필터:
|
||||
|
||||
- `limit`
|
||||
- `search`
|
||||
- `channel`
|
||||
- `includeDerivedTitles`
|
||||
- `includeLastMessage`
|
||||
|
||||
### `conversation_get`
|
||||
|
||||
`session_key`로 하나의 대화를 반환합니다.
|
||||
|
||||
### `messages_read`
|
||||
|
||||
하나의 세션 기반 대화에 대한 최근 transcript 메시지를 읽습니다.
|
||||
|
||||
### `attachments_fetch`
|
||||
|
||||
하나의 transcript 메시지에서 비텍스트 메시지 콘텐츠 블록을 추출합니다. 이것은
|
||||
독립적인 영구 첨부 파일 blob 저장소가 아니라 transcript 콘텐츠에 대한 메타데이터 뷰입니다.
|
||||
|
||||
### `events_poll`
|
||||
|
||||
숫자 커서 이후의 대기 중인 라이브 이벤트를 읽습니다.
|
||||
|
||||
### `events_wait`
|
||||
|
||||
다음으로 일치하는 대기 중 이벤트가 도착하거나 시간 초과가 만료될 때까지 롱 폴링합니다.
|
||||
|
||||
일반 MCP 클라이언트가 Claude 전용 푸시 프로토콜 없이
|
||||
준실시간 전달이 필요할 때 이것을 사용하세요.
|
||||
|
||||
### `messages_send`
|
||||
|
||||
이미 세션에 기록된 같은 경로를 통해 텍스트를 다시 보냅니다.
|
||||
|
||||
현재 동작:
|
||||
|
||||
- 기존 대화 경로가 필요합니다
|
||||
- 세션의 채널, 수신자, 계정 id, 스레드 id를 사용합니다
|
||||
- 텍스트만 전송합니다
|
||||
|
||||
### `permissions_list_open`
|
||||
|
||||
브리지가 Gateway에 연결된 이후 관찰한 대기 중인 exec/plugin 승인 요청을 나열합니다.
|
||||
|
||||
### `permissions_respond`
|
||||
|
||||
다음 중 하나로 대기 중인 exec/plugin 승인 요청 하나를 해결합니다:
|
||||
|
||||
- `allow-once`
|
||||
- `allow-always`
|
||||
- `deny`
|
||||
|
||||
## 이벤트 모델
|
||||
|
||||
브리지는 연결되어 있는 동안 메모리 내 이벤트 큐를 유지합니다.
|
||||
|
||||
현재 이벤트 유형:
|
||||
|
||||
- `message`
|
||||
- `exec_approval_requested`
|
||||
- `exec_approval_resolved`
|
||||
- `plugin_approval_requested`
|
||||
- `plugin_approval_resolved`
|
||||
- `claude_permission_request`
|
||||
|
||||
중요한 제한 사항:
|
||||
|
||||
- 큐는 라이브 전용이며, MCP 브리지가 시작될 때 시작됩니다
|
||||
- `events_poll` 및 `events_wait`는 그 자체로는 이전 Gateway 기록을 재생하지 않습니다
|
||||
- 영구 backlog는 `messages_read`로 읽어야 합니다
|
||||
|
||||
## Claude 채널 알림
|
||||
|
||||
브리지는 Claude 전용 채널 알림도 노출할 수 있습니다. 이것은
|
||||
Claude Code 채널 어댑터에 해당하는 OpenClaw 버전입니다. 표준 MCP 도구는 계속 사용할 수 있지만,
|
||||
라이브 수신 메시지는 Claude 전용 MCP 알림으로도 도착할 수 있습니다.
|
||||
|
||||
플래그:
|
||||
|
||||
- `--claude-channel-mode off`: 표준 MCP 도구만
|
||||
- `--claude-channel-mode on`: Claude 채널 알림 활성화
|
||||
- `--claude-channel-mode auto`: 현재 기본값이며 `on`과 동일한 브리지 동작
|
||||
|
||||
Claude 채널 모드가 활성화되면 서버는 Claude 실험적
|
||||
기능을 광고하고 다음을 내보낼 수 있습니다:
|
||||
|
||||
- `notifications/claude/channel`
|
||||
- `notifications/claude/channel/permission`
|
||||
|
||||
현재 브리지 동작:
|
||||
|
||||
- 수신 `user` transcript 메시지는
|
||||
`notifications/claude/channel`로 전달됩니다
|
||||
- MCP를 통해 수신된 Claude 권한 요청은 메모리 내에서 추적됩니다
|
||||
- 연결된 대화가 나중에 `yes abcde` 또는 `no abcde`를 보내면 브리지는
|
||||
이를 `notifications/claude/channel/permission`으로 변환합니다
|
||||
- 이 알림은 라이브 세션 전용이며, MCP 클라이언트가 연결을 끊으면
|
||||
푸시 대상이 없습니다
|
||||
|
||||
이것은 의도적으로 클라이언트 전용입니다. 일반 MCP 클라이언트는
|
||||
표준 폴링 도구에 의존해야 합니다.
|
||||
|
||||
## MCP 클라이언트 config
|
||||
|
||||
예시 stdio 클라이언트 config:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"openclaw": {
|
||||
"command": "openclaw",
|
||||
"args": [
|
||||
"mcp",
|
||||
"serve",
|
||||
"--url",
|
||||
"wss://gateway-host:18789",
|
||||
"--token-file",
|
||||
"/path/to/gateway.token"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
대부분의 일반 MCP 클라이언트에서는 표준 도구 표면으로 시작하고
|
||||
Claude 모드는 무시하세요. 실제로
|
||||
Claude 전용 알림 메서드를 이해하는 클라이언트에만 Claude 모드를 켜세요.
|
||||
|
||||
## 옵션
|
||||
|
||||
`openclaw mcp serve`는 다음을 지원합니다:
|
||||
|
||||
- `--url <url>`: Gateway WebSocket URL
|
||||
- `--token <token>`: Gateway 토큰
|
||||
- `--token-file <path>`: 파일에서 토큰 읽기
|
||||
- `--password <password>`: Gateway 비밀번호
|
||||
- `--password-file <path>`: 파일에서 비밀번호 읽기
|
||||
- `--claude-channel-mode <auto|on|off>`: Claude 알림 모드
|
||||
- `-v`, `--verbose`: stderr에 자세한 로그 출력
|
||||
|
||||
가능하면 인라인 비밀보다 `--token-file` 또는 `--password-file`을 선호하세요.
|
||||
|
||||
## 보안 및 신뢰 경계
|
||||
|
||||
브리지는 라우팅을 새로 만들지 않습니다. Gateway가
|
||||
이미 라우팅 방법을 알고 있는 대화만 노출합니다.
|
||||
|
||||
즉:
|
||||
|
||||
- 발신자 허용 목록, 페어링 및 채널 수준 신뢰는 여전히
|
||||
기본 OpenClaw 채널 config에 속합니다
|
||||
- `messages_send`는 기존에 저장된 경로를 통해서만 응답할 수 있습니다
|
||||
- 승인 상태는 현재 브리지 세션에 한해 라이브/메모리 내에만 존재합니다
|
||||
- 브리지 인증은 다른 원격 Gateway 클라이언트에 대해 신뢰할 것과 동일한 Gateway 토큰 또는 비밀번호 제어를 사용해야 합니다
|
||||
|
||||
대화가 `conversations_list`에 나타나지 않는다면 일반적인 원인은
|
||||
MCP config가 아닙니다. 기본 Gateway 세션에
|
||||
경로 메타데이터가 없거나 불완전하기 때문입니다.
|
||||
|
||||
## 테스트
|
||||
|
||||
OpenClaw는 이 브리지를 위한 결정적 Docker 스모크 테스트를 제공합니다:
|
||||
|
||||
```bash
|
||||
pnpm test:docker:mcp-channels
|
||||
```
|
||||
|
||||
이 스모크 테스트는 다음을 수행합니다:
|
||||
|
||||
- 시드된 Gateway 컨테이너 시작
|
||||
- `openclaw mcp serve`를 실행하는 두 번째 컨테이너 시작
|
||||
- 대화 검색, transcript 읽기, 첨부 파일 메타데이터 읽기,
|
||||
라이브 이벤트 큐 동작 및 아웃바운드 전송 라우팅 검증
|
||||
- 실제 stdio MCP 브리지를 통한 Claude 스타일 채널 및 권한 알림 검증
|
||||
|
||||
이것은 실제
|
||||
Telegram, Discord 또는 iMessage 계정을 테스트 실행에 연결하지 않고 브리지가 동작함을 입증하는 가장 빠른 방법입니다.
|
||||
|
||||
더 넓은 테스트 맥락은 [Testing](/help/testing)을 참조하세요.
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 반환되는 대화가 없음
|
||||
|
||||
보통 Gateway 세션이 아직 라우팅 가능하지 않다는 뜻입니다. 기본 세션에 저장된 채널/provider, 수신자 및 선택적
|
||||
계정/스레드 경로 메타데이터가 있는지 확인하세요.
|
||||
|
||||
### `events_poll` 또는 `events_wait`가 이전 메시지를 놓침
|
||||
|
||||
예상된 동작입니다. 라이브 큐는 브리지가 연결될 때 시작됩니다. 이전 transcript
|
||||
기록은 `messages_read`로 읽으세요.
|
||||
|
||||
### Claude 알림이 표시되지 않음
|
||||
|
||||
다음을 모두 확인하세요:
|
||||
|
||||
- 클라이언트가 stdio MCP 세션을 계속 열어 두고 있는지
|
||||
- `--claude-channel-mode`가 `on` 또는 `auto`인지
|
||||
- 클라이언트가 실제로 Claude 전용 알림 메서드를 이해하는지
|
||||
- 수신 메시지가 브리지가 연결된 이후에 발생했는지
|
||||
|
||||
### 승인이 표시되지 않음
|
||||
|
||||
`permissions_list_open`은 브리지가
|
||||
연결되어 있는 동안 관찰한 승인 요청만 표시합니다. 영구 승인 기록 API가 아닙니다.
|
||||
|
||||
## OpenClaw를 MCP 클라이언트 레지스트리로 사용
|
||||
|
||||
이것은 `openclaw mcp list`, `show`, `set`, `unset` 경로입니다.
|
||||
|
||||
이 명령들은 OpenClaw를 MCP를 통해 노출하지 않습니다. OpenClaw config의 `mcp.servers` 아래에 있는
|
||||
OpenClaw 소유 MCP 서버 정의를 관리합니다.
|
||||
|
||||
이 저장된 정의는 내장 Pi 및 기타 런타임 어댑터처럼 OpenClaw가 나중에 실행하거나 구성하는 런타임을 위한 것입니다. OpenClaw는 정의를 중앙에 저장하여,
|
||||
해당 런타임이 각자 중복된 MCP 서버 목록을 따로 유지하지 않도록 합니다.
|
||||
|
||||
중요한 동작:
|
||||
|
||||
- 이 명령들은 OpenClaw config만 읽거나 씁니다
|
||||
- 대상 MCP 서버에 연결하지 않습니다
|
||||
- 명령, URL 또는 원격 전송이
|
||||
현재 실제로 도달 가능한지 검증하지 않습니다
|
||||
- 런타임 어댑터는 실행 시점에
|
||||
실제로 지원하는 전송 형태를 결정합니다
|
||||
|
||||
## 저장된 MCP 서버 정의
|
||||
|
||||
OpenClaw는 또한 OpenClaw가 관리하는 MCP 정의가 필요한 표면을 위해
|
||||
config에 경량 MCP 서버 레지스트리를 저장합니다.
|
||||
|
||||
명령:
|
||||
|
||||
- `openclaw mcp list`
|
||||
- `openclaw mcp show [name]`
|
||||
- `openclaw mcp set <name> <json>`
|
||||
- `openclaw mcp unset <name>`
|
||||
|
||||
참고:
|
||||
|
||||
- `list`는 서버 이름을 정렬합니다.
|
||||
- 이름 없이 `show`를 실행하면 구성된 전체 MCP 서버 객체를 출력합니다.
|
||||
- `set`은 명령줄에서 하나의 JSON 객체 값을 기대합니다.
|
||||
- `unset`은 지정한 서버가 존재하지 않으면 실패합니다.
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw mcp list
|
||||
openclaw mcp show context7 --json
|
||||
openclaw mcp set context7 '{"command":"uvx","args":["context7-mcp"]}'
|
||||
openclaw mcp set docs '{"url":"https://mcp.example.com"}'
|
||||
openclaw mcp unset context7
|
||||
```
|
||||
|
||||
예시 config 형태:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"context7": {
|
||||
"command": "uvx",
|
||||
"args": ["context7-mcp"]
|
||||
},
|
||||
"docs": {
|
||||
"url": "https://mcp.example.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Stdio 전송
|
||||
|
||||
로컬 자식 프로세스를 실행하고 stdin/stdout을 통해 통신합니다.
|
||||
|
||||
| 필드 | 설명 |
|
||||
| -------------------------- | ---------------------------- |
|
||||
| `command` | 실행할 실행 파일(필수) |
|
||||
| `args` | 명령줄 인수 배열 |
|
||||
| `env` | 추가 환경 변수 |
|
||||
| `cwd` / `workingDirectory` | 프로세스의 작업 디렉터리 |
|
||||
|
||||
### SSE / HTTP 전송
|
||||
|
||||
HTTP Server-Sent Events를 통해 원격 MCP 서버에 연결합니다.
|
||||
|
||||
| 필드 | 설명 |
|
||||
| --------------------- | -------------------------------------------------------- |
|
||||
| `url` | 원격 서버의 HTTP 또는 HTTPS URL(필수) |
|
||||
| `headers` | 선택적 HTTP 헤더 키-값 맵(예: 인증 토큰) |
|
||||
| `connectionTimeoutMs` | 서버별 연결 시간 초과(ms, 선택 사항) |
|
||||
|
||||
예시:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"remote-tools": {
|
||||
"url": "https://mcp.example.com",
|
||||
"headers": {
|
||||
"Authorization": "Bearer <token>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`url`의 민감한 값(userinfo)과 `headers`는 로그 및
|
||||
상태 출력에서 마스킹됩니다.
|
||||
|
||||
### Streamable HTTP 전송
|
||||
|
||||
`streamable-http`는 `sse`, `stdio`와 함께 제공되는 추가 전송 옵션입니다. 원격 MCP 서버와의 양방향 통신에 HTTP 스트리밍을 사용합니다.
|
||||
|
||||
| 필드 | 설명 |
|
||||
| --------------------- | -------------------------------------------------------------------------------------- |
|
||||
| `url` | 원격 서버의 HTTP 또는 HTTPS URL(필수) |
|
||||
| `transport` | 이 전송을 선택하려면 `"streamable-http"`로 설정합니다. 생략하면 OpenClaw는 `sse`를 사용합니다 |
|
||||
| `headers` | 선택적 HTTP 헤더 키-값 맵(예: 인증 토큰) |
|
||||
| `connectionTimeoutMs` | 서버별 연결 시간 초과(ms, 선택 사항) |
|
||||
|
||||
예시:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"streaming-tools": {
|
||||
"url": "https://mcp.example.com/stream",
|
||||
"transport": "streamable-http",
|
||||
"connectionTimeoutMs": 10000,
|
||||
"headers": {
|
||||
"Authorization": "Bearer <token>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
이 명령들은 저장된 config만 관리합니다. 채널 브리지를 시작하지 않고,
|
||||
라이브 MCP 클라이언트 세션을 열지 않으며, 대상 서버가 도달 가능한지 입증하지도 않습니다.
|
||||
|
||||
## 현재 제한 사항
|
||||
|
||||
이 페이지는 오늘 배포된 브리지를 설명합니다.
|
||||
|
||||
현재 제한 사항:
|
||||
|
||||
- 대화 검색은 기존 Gateway 세션 경로 메타데이터에 의존합니다
|
||||
- Claude 전용 어댑터 외의 일반 푸시 프로토콜은 아직 없습니다
|
||||
- 메시지 편집 또는 반응 도구는 아직 없습니다
|
||||
- HTTP/SSE/streamable-http 전송은 단일 원격 서버에 연결하며, 아직 다중화된 업스트림은 없습니다
|
||||
- `permissions_list_open`에는 브리지가
|
||||
연결되어 있는 동안 관찰한 승인만 포함됩니다
|
||||
142
docs/ko/cli/memory.md
Normal file
142
docs/ko/cli/memory.md
Normal file
@ -0,0 +1,142 @@
|
||||
---
|
||||
read_when:
|
||||
- 시맨틱 메모리를 인덱싱하거나 검색하려고 함
|
||||
- 메모리 가용성 또는 인덱싱을 디버그하는 중
|
||||
- 회상된 단기 메모리를 `MEMORY.md`로 승격하려고 함
|
||||
summary: '`openclaw memory`용 CLI 참조(status/index/search/promote)'
|
||||
title: memory
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:23Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: a89e3a819737bb63521128ae63d9e25b5cd9db35c3ea4606d087a8ad48b41eab
|
||||
source_path: cli/memory.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw memory`
|
||||
|
||||
시맨틱 메모리 인덱싱 및 검색을 관리합니다.
|
||||
활성 메모리 plugin이 제공합니다(기본값: `memory-core`; 비활성화하려면 `plugins.slots.memory = "none"` 설정).
|
||||
|
||||
관련 문서:
|
||||
|
||||
- 메모리 개념: [Memory](/concepts/memory)
|
||||
- Plugins: [Plugins](/tools/plugin)
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw memory status
|
||||
openclaw memory status --deep
|
||||
openclaw memory status --fix
|
||||
openclaw memory index --force
|
||||
openclaw memory search "meeting notes"
|
||||
openclaw memory search --query "deployment" --max-results 20
|
||||
openclaw memory promote --limit 10 --min-score 0.75
|
||||
openclaw memory promote --apply
|
||||
openclaw memory promote --json --min-recall-count 0 --min-unique-queries 0
|
||||
openclaw memory status --json
|
||||
openclaw memory status --deep --index
|
||||
openclaw memory status --deep --index --verbose
|
||||
openclaw memory status --agent main
|
||||
openclaw memory index --agent main --verbose
|
||||
```
|
||||
|
||||
## 옵션
|
||||
|
||||
`memory status` 및 `memory index`:
|
||||
|
||||
- `--agent <id>`: 단일 에이전트로 범위를 제한합니다. 이 옵션이 없으면 이 명령들은 구성된 각 에이전트에 대해 실행되며, 구성된 에이전트 목록이 없으면 기본 에이전트로 폴백합니다.
|
||||
- `--verbose`: 프로브 및 인덱싱 중 상세 로그를 출력합니다.
|
||||
|
||||
`memory status`:
|
||||
|
||||
- `--deep`: 벡터 + 임베딩 가용성을 프로브합니다.
|
||||
- `--index`: 저장소가 dirty 상태이면 재인덱싱을 실행합니다(`--deep` 포함).
|
||||
- `--fix`: 오래된 recall lock을 복구하고 promotion 메타데이터를 정규화합니다.
|
||||
- `--json`: JSON 출력을 표시합니다.
|
||||
|
||||
`memory index`:
|
||||
|
||||
- `--force`: 전체 재인덱싱을 강제로 수행합니다.
|
||||
|
||||
`memory search`:
|
||||
|
||||
- 쿼리 입력: 위치 인자 `[query]` 또는 `--query <text>` 중 하나를 전달합니다.
|
||||
- 둘 다 제공되면 `--query`가 우선합니다.
|
||||
- 둘 다 없으면 명령은 오류와 함께 종료됩니다.
|
||||
- `--agent <id>`: 단일 에이전트로 범위를 제한합니다(기본값: 기본 에이전트).
|
||||
- `--max-results <n>`: 반환할 결과 수를 제한합니다.
|
||||
- `--min-score <n>`: 점수가 낮은 일치 항목을 필터링합니다.
|
||||
- `--json`: JSON 결과를 출력합니다.
|
||||
|
||||
`memory promote`:
|
||||
|
||||
단기 메모리 promotion을 미리 보고 적용합니다.
|
||||
|
||||
```bash
|
||||
openclaw memory promote [--apply] [--limit <n>] [--include-promoted]
|
||||
```
|
||||
|
||||
- `--apply` -- promotion을 `MEMORY.md`에 기록합니다(기본값: 미리보기만).
|
||||
- `--limit <n>` -- 표시할 후보 수를 제한합니다.
|
||||
- `--include-promoted` -- 이전 주기에서 이미 승격된 항목도 포함합니다.
|
||||
|
||||
전체 옵션:
|
||||
|
||||
- 가중 recall 신호(`frequency`, `relevance`, `query diversity`, `recency`)를 사용해 `memory/YYYY-MM-DD.md`의 단기 후보를 순위화합니다.
|
||||
- `memory_search`가 일일 메모리 히트를 반환할 때 캡처된 recall 이벤트를 사용합니다.
|
||||
- 선택적 자동 dreaming 모드: `plugins.entries.memory-core.config.dreaming.mode`가 `core`, `deep`, 또는 `rem`이면 `memory-core`가 백그라운드에서 promotion을 트리거하는 cron 작업을 자동으로 관리합니다(수동 `openclaw cron add` 불필요).
|
||||
- `--agent <id>`: 단일 에이전트로 범위를 제한합니다(기본값: 기본 에이전트).
|
||||
- `--limit <n>`: 반환/적용할 최대 후보 수입니다.
|
||||
- `--min-score <n>`: 최소 가중 promotion 점수입니다.
|
||||
- `--min-recall-count <n>`: 후보에 필요한 최소 recall 횟수입니다.
|
||||
- `--min-unique-queries <n>`: 후보에 필요한 최소 고유 쿼리 수입니다.
|
||||
- `--apply`: 선택된 후보를 `MEMORY.md`에 추가하고 승격된 것으로 표시합니다.
|
||||
- `--include-promoted`: 출력에 이미 승격된 후보를 포함합니다.
|
||||
- `--json`: JSON 출력을 표시합니다.
|
||||
|
||||
## Dreaming (실험적)
|
||||
|
||||
Dreaming은 메모리를 위한 야간 반영 패스입니다. 시스템이 낮 동안 회상된 내용을 다시 살펴보고 무엇을 장기적으로 유지할 가치가 있는지 판단하기 때문에 "dreaming"이라고 부릅니다.
|
||||
|
||||
- 옵트인 기능이며 기본적으로 비활성화되어 있습니다.
|
||||
- `plugins.entries.memory-core.config.dreaming.mode`로 활성화합니다.
|
||||
- 채팅에서 `/dreaming off|core|rem|deep`로 모드를 전환할 수 있습니다. 각 모드의 동작을 보려면 `/dreaming`(또는 `/dreaming options`)을 실행하세요.
|
||||
- 활성화되면 `memory-core`가 관리형 cron 작업을 자동으로 생성하고 유지합니다.
|
||||
- dreaming은 활성화하되 자동 promotion을 사실상 일시 정지하려면 `dreaming.limit`를 `0`으로 설정하세요.
|
||||
- 순위화는 가중 신호를 사용합니다: recall 빈도, 검색 관련성, 쿼리 다양성, 시간적 최신성(최근 recall은 시간이 지나며 감쇠함).
|
||||
- `MEMORY.md`로의 promotion은 품질 임계값을 충족할 때만 일어나므로 장기 메모리는 일회성 세부 정보가 쌓이지 않고 높은 신호를 유지합니다.
|
||||
|
||||
기본 모드 프리셋:
|
||||
|
||||
- `core`: 매일 `0 3 * * *`, `minScore=0.75`, `minRecallCount=3`, `minUniqueQueries=2`
|
||||
- `deep`: 12시간마다(`0 */12 * * *`), `minScore=0.8`, `minRecallCount=3`, `minUniqueQueries=3`
|
||||
- `rem`: 6시간마다(`0 */6 * * *`), `minScore=0.85`, `minRecallCount=4`, `minUniqueQueries=3`
|
||||
|
||||
예시:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugins": {
|
||||
"entries": {
|
||||
"memory-core": {
|
||||
"config": {
|
||||
"dreaming": {
|
||||
"mode": "core"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `memory index --verbose`는 단계별 세부 정보(provider, 모델, 소스, 배치 활동)를 출력합니다.
|
||||
- `memory status`에는 `memorySearch.extraPaths`를 통해 구성된 추가 경로가 모두 포함됩니다.
|
||||
- 실질적으로 활성인 메모리 원격 API 키 필드가 SecretRef로 구성되어 있으면, 이 명령은 활성 gateway 스냅샷에서 해당 값을 확인합니다. gateway를 사용할 수 없으면 명령은 즉시 실패합니다.
|
||||
- Gateway 버전 불일치 참고: 이 명령 경로에는 `secrets.resolve`를 지원하는 gateway가 필요합니다. 오래된 gateway는 unknown-method 오류를 반환합니다.
|
||||
- dreaming 주기는 기본적으로 각 모드의 프리셋 일정입니다. `plugins.entries.memory-core.config.dreaming.frequency`를 cron 표현식(예: `0 3 * * *`)으로 설정해 주기를 재정의하고, `timezone`, `limit`, `minScore`, `minRecallCount`, `minUniqueQueries`로 세부 조정할 수 있습니다.
|
||||
307
docs/ko/cli/message.md
Normal file
307
docs/ko/cli/message.md
Normal file
@ -0,0 +1,307 @@
|
||||
---
|
||||
read_when:
|
||||
- 메시지 CLI 작업을 추가하거나 수정하는 경우
|
||||
- 아웃바운드 채널 동작을 변경하는 경우
|
||||
summary: '`openclaw message`용 CLI 참조(전송 + 채널 작업)'
|
||||
title: message
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:31Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: b70f36189d028d59db25cd8b39d7c67883eaea71bea2358ee6314eec6cd2fa51
|
||||
source_path: cli/message.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw message`
|
||||
|
||||
메시지 전송 및 채널 작업을 위한 단일 아웃바운드 명령입니다
|
||||
(Discord/Google Chat/iMessage/Matrix/Mattermost (plugin)/Microsoft Teams/Signal/Slack/Telegram/WhatsApp).
|
||||
|
||||
## 사용법
|
||||
|
||||
```
|
||||
openclaw message <subcommand> [flags]
|
||||
```
|
||||
|
||||
채널 선택:
|
||||
|
||||
- 둘 이상의 채널이 구성된 경우 `--channel`이 필요합니다.
|
||||
- 정확히 하나의 채널만 구성된 경우 해당 채널이 기본값이 됩니다.
|
||||
- 값: `discord|googlechat|imessage|matrix|mattermost|msteams|signal|slack|telegram|whatsapp` (Mattermost는 plugin 필요)
|
||||
|
||||
대상 형식(`--target`):
|
||||
|
||||
- WhatsApp: E.164 또는 그룹 JID
|
||||
- Telegram: chat id 또는 `@username`
|
||||
- Discord: `channel:<id>` 또는 `user:<id>` (또는 `<@id>` 멘션; 원시 숫자 id는 채널로 처리됨)
|
||||
- Google Chat: `spaces/<spaceId>` 또는 `users/<userId>`
|
||||
- Slack: `channel:<id>` 또는 `user:<id>` (원시 channel id 허용)
|
||||
- Mattermost (plugin): `channel:<id>`, `user:<id>`, 또는 `@username` (접두사 없는 id는 채널로 처리됨)
|
||||
- Signal: `+E.164`, `group:<id>`, `signal:+E.164`, `signal:group:<id>`, 또는 `username:<name>`/`u:<name>`
|
||||
- iMessage: handle, `chat_id:<id>`, `chat_guid:<guid>`, 또는 `chat_identifier:<id>`
|
||||
- Matrix: `@user:server`, `!room:server`, 또는 `#alias:server`
|
||||
- Microsoft Teams: conversation id (`19:...@thread.tacv2`) 또는 `conversation:<id>` 또는 `user:<aad-object-id>`
|
||||
|
||||
이름 조회:
|
||||
|
||||
- 지원되는 provider(Discord/Slack 등)의 경우 `Help` 또는 `#help` 같은 채널 이름은 디렉터리 캐시를 통해 확인됩니다.
|
||||
- 캐시 미스가 발생하면 provider가 지원하는 경우 OpenClaw가 실시간 디렉터리 조회를 시도합니다.
|
||||
|
||||
## 공통 플래그
|
||||
|
||||
- `--channel <name>`
|
||||
- `--account <id>`
|
||||
- `--target <dest>` (send/poll/read 등용 대상 채널 또는 사용자)
|
||||
- `--targets <name>` (반복 가능, broadcast 전용)
|
||||
- `--json`
|
||||
- `--dry-run`
|
||||
- `--verbose`
|
||||
|
||||
## SecretRef 동작
|
||||
|
||||
- `openclaw message`는 선택한 작업을 실행하기 전에 지원되는 채널 SecretRef를 해석합니다.
|
||||
- 가능할 때 해석 범위는 활성 작업 대상에 맞춰 제한됩니다.
|
||||
- `--channel`이 설정된 경우(또는 `discord:...` 같은 접두사 대상에서 추론된 경우) 채널 범위
|
||||
- `--account`가 설정된 경우 계정 범위(채널 전역 + 선택한 계정 표면)
|
||||
- `--account`를 생략하면 OpenClaw는 `default` 계정 SecretRef 범위를 강제하지 않습니다
|
||||
- 관련 없는 채널의 미해결 SecretRef는 대상 지정된 메시지 작업을 차단하지 않습니다.
|
||||
- 선택한 채널/계정 SecretRef가 해석되지 않으면 해당 작업에 대해 명령은 실패 시 닫힘 방식으로 처리됩니다.
|
||||
|
||||
## 작업
|
||||
|
||||
### 코어
|
||||
|
||||
- `send`
|
||||
- 채널: WhatsApp/Telegram/Discord/Google Chat/Slack/Mattermost (plugin)/Signal/iMessage/Matrix/Microsoft Teams
|
||||
- 필수: `--target`, 그리고 `--message` 또는 `--media`
|
||||
- 선택 사항: `--media`, `--interactive`, `--buttons`, `--components`, `--card`, `--reply-to`, `--thread-id`, `--gif-playback`, `--force-document`, `--silent`
|
||||
- 공유 interactive payload: 지원되는 경우 `--interactive`는 채널 네이티브 interactive JSON payload를 전송합니다
|
||||
- Telegram 전용: `--buttons` (`channels.telegram.capabilities.inlineButtons`가 이를 허용해야 함)
|
||||
- Telegram 전용: `--force-document` (Telegram 압축을 피하기 위해 이미지와 GIF를 document로 전송)
|
||||
- Telegram 전용: `--thread-id` (포럼 topic id)
|
||||
- Slack 전용: `--thread-id` (thread timestamp, `--reply-to`는 동일한 필드 사용)
|
||||
- Discord 전용: `--components` JSON payload
|
||||
- Adaptive-card 채널: 지원되는 경우 `--card` JSON payload
|
||||
- Telegram + Discord: `--silent`
|
||||
- WhatsApp 전용: `--gif-playback`
|
||||
|
||||
- `poll`
|
||||
- 채널: WhatsApp/Telegram/Discord/Matrix/Microsoft Teams
|
||||
- 필수: `--target`, `--poll-question`, `--poll-option` (반복)
|
||||
- 선택 사항: `--poll-multi`
|
||||
- Discord 전용: `--poll-duration-hours`, `--silent`, `--message`
|
||||
- Telegram 전용: `--poll-duration-seconds` (5-600), `--silent`, `--poll-anonymous` / `--poll-public`, `--thread-id`
|
||||
|
||||
- `react`
|
||||
- 채널: Discord/Google Chat/Slack/Telegram/WhatsApp/Signal/Matrix
|
||||
- 필수: `--message-id`, `--target`
|
||||
- 선택 사항: `--emoji`, `--remove`, `--participant`, `--from-me`, `--target-author`, `--target-author-uuid`
|
||||
- 참고: `--remove`에는 `--emoji`가 필요합니다(지원되는 경우 자신의 반응을 지우려면 `--emoji`를 생략, /tools/reactions 참조)
|
||||
- WhatsApp 전용: `--participant`, `--from-me`
|
||||
- Signal 그룹 반응: `--target-author` 또는 `--target-author-uuid` 필요
|
||||
|
||||
- `reactions`
|
||||
- 채널: Discord/Google Chat/Slack/Matrix
|
||||
- 필수: `--message-id`, `--target`
|
||||
- 선택 사항: `--limit`
|
||||
|
||||
- `read`
|
||||
- 채널: Discord/Slack/Matrix
|
||||
- 필수: `--target`
|
||||
- 선택 사항: `--limit`, `--before`, `--after`
|
||||
- Discord 전용: `--around`
|
||||
|
||||
- `edit`
|
||||
- 채널: Discord/Slack/Matrix
|
||||
- 필수: `--message-id`, `--message`, `--target`
|
||||
|
||||
- `delete`
|
||||
- 채널: Discord/Slack/Telegram/Matrix
|
||||
- 필수: `--message-id`, `--target`
|
||||
|
||||
- `pin` / `unpin`
|
||||
- 채널: Discord/Slack/Matrix
|
||||
- 필수: `--message-id`, `--target`
|
||||
|
||||
- `pins` (목록)
|
||||
- 채널: Discord/Slack/Matrix
|
||||
- 필수: `--target`
|
||||
|
||||
- `permissions`
|
||||
- 채널: Discord/Matrix
|
||||
- 필수: `--target`
|
||||
- Matrix 전용: Matrix 암호화가 활성화되고 verification 작업이 허용된 경우 사용 가능
|
||||
|
||||
- `search`
|
||||
- 채널: Discord
|
||||
- 필수: `--guild-id`, `--query`
|
||||
- 선택 사항: `--channel-id`, `--channel-ids` (반복), `--author-id`, `--author-ids` (반복), `--limit`
|
||||
|
||||
### 스레드
|
||||
|
||||
- `thread create`
|
||||
- 채널: Discord
|
||||
- 필수: `--thread-name`, `--target` (channel id)
|
||||
- 선택 사항: `--message-id`, `--message`, `--auto-archive-min`
|
||||
|
||||
- `thread list`
|
||||
- 채널: Discord
|
||||
- 필수: `--guild-id`
|
||||
- 선택 사항: `--channel-id`, `--include-archived`, `--before`, `--limit`
|
||||
|
||||
- `thread reply`
|
||||
- 채널: Discord
|
||||
- 필수: `--target` (thread id), `--message`
|
||||
- 선택 사항: `--media`, `--reply-to`
|
||||
|
||||
### 이모지
|
||||
|
||||
- `emoji list`
|
||||
- Discord: `--guild-id`
|
||||
- Slack: 추가 플래그 없음
|
||||
|
||||
- `emoji upload`
|
||||
- 채널: Discord
|
||||
- 필수: `--guild-id`, `--emoji-name`, `--media`
|
||||
- 선택 사항: `--role-ids` (반복)
|
||||
|
||||
### 스티커
|
||||
|
||||
- `sticker send`
|
||||
- 채널: Discord
|
||||
- 필수: `--target`, `--sticker-id` (반복)
|
||||
- 선택 사항: `--message`
|
||||
|
||||
- `sticker upload`
|
||||
- 채널: Discord
|
||||
- 필수: `--guild-id`, `--sticker-name`, `--sticker-desc`, `--sticker-tags`, `--media`
|
||||
|
||||
### 역할 / 채널 / 멤버 / 음성
|
||||
|
||||
- `role info` (Discord): `--guild-id`
|
||||
- `role add` / `role remove` (Discord): `--guild-id`, `--user-id`, `--role-id`
|
||||
- `channel info` (Discord): `--target`
|
||||
- `channel list` (Discord): `--guild-id`
|
||||
- `member info` (Discord/Slack): `--user-id` (+ Discord의 경우 `--guild-id`)
|
||||
- `voice status` (Discord): `--guild-id`, `--user-id`
|
||||
|
||||
### 이벤트
|
||||
|
||||
- `event list` (Discord): `--guild-id`
|
||||
- `event create` (Discord): `--guild-id`, `--event-name`, `--start-time`
|
||||
- 선택 사항: `--end-time`, `--desc`, `--channel-id`, `--location`, `--event-type`
|
||||
|
||||
### moderation (Discord)
|
||||
|
||||
- `timeout`: `--guild-id`, `--user-id` (선택 사항 `--duration-min` 또는 `--until`, 둘 다 생략하면 timeout 해제)
|
||||
- `kick`: `--guild-id`, `--user-id` (+ `--reason`)
|
||||
- `ban`: `--guild-id`, `--user-id` (+ `--delete-days`, `--reason`)
|
||||
- `timeout`도 `--reason`을 지원합니다
|
||||
|
||||
### broadcast
|
||||
|
||||
- `broadcast`
|
||||
- 채널: 구성된 모든 채널, 모든 provider를 대상으로 하려면 `--channel all` 사용
|
||||
- 필수: `--targets <target...>`
|
||||
- 선택 사항: `--message`, `--media`, `--dry-run`
|
||||
|
||||
## 예시
|
||||
|
||||
Discord 응답 전송:
|
||||
|
||||
```
|
||||
openclaw message send --channel discord \
|
||||
--target channel:123 --message "hi" --reply-to 456
|
||||
```
|
||||
|
||||
components가 포함된 Discord 메시지 전송:
|
||||
|
||||
```
|
||||
openclaw message send --channel discord \
|
||||
--target channel:123 --message "Choose:" \
|
||||
--components '{"text":"Choose a path","blocks":[{"type":"actions","buttons":[{"label":"Approve","style":"success"},{"label":"Decline","style":"danger"}]}]}'
|
||||
```
|
||||
|
||||
전체 스키마는 [Discord components](/channels/discord#interactive-components)를 참조하세요.
|
||||
|
||||
공유 interactive payload 전송:
|
||||
|
||||
```bash
|
||||
openclaw message send --channel googlechat --target spaces/AAA... \
|
||||
--message "Choose:" \
|
||||
--interactive '{"text":"Choose a path","blocks":[{"type":"actions","buttons":[{"label":"Approve"},{"label":"Decline"}]}]}'
|
||||
```
|
||||
|
||||
Discord Poll 생성:
|
||||
|
||||
```
|
||||
openclaw message poll --channel discord \
|
||||
--target channel:123 \
|
||||
--poll-question "Snack?" \
|
||||
--poll-option Pizza --poll-option Sushi \
|
||||
--poll-multi --poll-duration-hours 48
|
||||
```
|
||||
|
||||
Telegram Poll 생성(2분 후 자동 종료):
|
||||
|
||||
```
|
||||
openclaw message poll --channel telegram \
|
||||
--target @mychat \
|
||||
--poll-question "Lunch?" \
|
||||
--poll-option Pizza --poll-option Sushi \
|
||||
--poll-duration-seconds 120 --silent
|
||||
```
|
||||
|
||||
Teams proactive 메시지 전송:
|
||||
|
||||
```
|
||||
openclaw message send --channel msteams \
|
||||
--target conversation:19:abc@thread.tacv2 --message "hi"
|
||||
```
|
||||
|
||||
Teams Poll 생성:
|
||||
|
||||
```
|
||||
openclaw message poll --channel msteams \
|
||||
--target conversation:19:abc@thread.tacv2 \
|
||||
--poll-question "Lunch?" \
|
||||
--poll-option Pizza --poll-option Sushi
|
||||
```
|
||||
|
||||
Slack에서 반응 추가:
|
||||
|
||||
```
|
||||
openclaw message react --channel slack \
|
||||
--target C123 --message-id 456 --emoji "✅"
|
||||
```
|
||||
|
||||
Signal 그룹에서 반응 추가:
|
||||
|
||||
```
|
||||
openclaw message react --channel signal \
|
||||
--target signal:group:abc123 --message-id 1737630212345 \
|
||||
--emoji "✅" --target-author-uuid 123e4567-e89b-12d3-a456-426614174000
|
||||
```
|
||||
|
||||
Telegram inline button 전송:
|
||||
|
||||
```
|
||||
openclaw message send --channel telegram --target @mychat --message "Choose:" \
|
||||
--buttons '[ [{"text":"Yes","callback_data":"cmd:yes"}], [{"text":"No","callback_data":"cmd:no"}] ]'
|
||||
```
|
||||
|
||||
Teams Adaptive Card 전송:
|
||||
|
||||
```bash
|
||||
openclaw message send --channel msteams \
|
||||
--target conversation:19:abc@thread.tacv2 \
|
||||
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Status update"}]}'
|
||||
```
|
||||
|
||||
압축을 피하기 위해 Telegram 이미지를 document로 전송:
|
||||
|
||||
```bash
|
||||
openclaw message send --channel telegram --target @mychat \
|
||||
--media ./diagram.png --force-document
|
||||
```
|
||||
140
docs/ko/cli/models.md
Normal file
140
docs/ko/cli/models.md
Normal file
@ -0,0 +1,140 @@
|
||||
---
|
||||
read_when:
|
||||
- 기본 모델을 변경하거나 provider 인증 상태를 확인하려는 경우
|
||||
- 사용 가능한 모델/provider를 스캔하고 인증 프로필을 디버그하려는 경우
|
||||
summary: '`openclaw models`용 CLI 참조(상태/목록/설정/스캔, 별칭, 대체 모델, 인증)'
|
||||
title: models
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:29Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 04ba33181d49b6bbf3b5d5fa413aa6b388c9f29fb9d4952055d68c79f7bcfea0
|
||||
source_path: cli/models.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw models`
|
||||
|
||||
모델 검색, 스캔 및 구성(기본 모델, 대체 모델, 인증 프로필).
|
||||
|
||||
관련 문서:
|
||||
|
||||
- Provider + 모델: [Models](/providers/models)
|
||||
- Provider 인증 설정: [시작하기](/ko/start/getting-started)
|
||||
|
||||
## 공통 명령
|
||||
|
||||
```bash
|
||||
openclaw models status
|
||||
openclaw models list
|
||||
openclaw models set <model-or-alias>
|
||||
openclaw models scan
|
||||
```
|
||||
|
||||
`openclaw models status`는 해석된 기본값/대체 모델과 인증 개요를 표시합니다.
|
||||
provider 사용량 스냅샷을 사용할 수 있는 경우 OAuth/API 키 상태 섹션에는
|
||||
provider 사용 기간과 할당량 스냅샷이 포함됩니다.
|
||||
현재 사용 기간 provider: Anthropic, GitHub Copilot, Gemini CLI, OpenAI
|
||||
Codex, MiniMax, Xiaomi, z.ai. 사용량 인증은 가능한 경우 provider별 훅에서
|
||||
가져오며, 그렇지 않으면 OpenClaw는 인증 프로필, env 또는 config의
|
||||
일치하는 OAuth/API 키 자격 증명으로 대체합니다.
|
||||
구성된 각 provider 프로필에 대해 실시간 인증 프로브를 실행하려면 `--probe`를 추가하세요.
|
||||
프로브는 실제 요청입니다(토큰을 소비하고 속도 제한을 유발할 수 있음).
|
||||
구성된 에이전트의 모델/인증 상태를 검사하려면 `--agent <id>`를 사용하세요. 생략하면
|
||||
명령은 설정된 경우 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR`를 사용하고, 그렇지 않으면
|
||||
구성된 기본 에이전트를 사용합니다.
|
||||
프로브 행은 인증 프로필, env 자격 증명 또는 `models.json`에서 가져올 수 있습니다.
|
||||
|
||||
참고:
|
||||
|
||||
- `models set <model-or-alias>`는 `provider/model` 또는 별칭을 받습니다.
|
||||
- 모델 ref는 **첫 번째** `/`를 기준으로 분할하여 파싱합니다. 모델 ID에 `/`가 포함된 경우(OpenRouter 스타일), provider 접두사를 포함하세요(예: `openrouter/moonshotai/kimi-k2`).
|
||||
- provider를 생략하면 OpenClaw는 먼저 입력을 별칭으로 해석하고, 그다음
|
||||
정확한 모델 ID에 대한 고유한 구성 provider 일치 항목으로 해석하며, 그 이후에만
|
||||
더 이상 사용되지 않음을 알리는 경고와 함께 구성된 기본 provider로 대체합니다.
|
||||
해당 provider가 더 이상 구성된 기본 모델을 제공하지 않는 경우, OpenClaw는
|
||||
오래되어 제거된 provider 기본값을 표시하는 대신 첫 번째 구성된 provider/모델로 대체합니다.
|
||||
- `models status`는 비밀이 아닌 플레이스홀더에 대해 인증 출력에서 비밀처럼 마스킹하지 않고 `marker(<value>)`를 표시할 수 있습니다(예: `OPENAI_API_KEY`, `secretref-managed`, `minimax-oauth`, `oauth:chutes`, `ollama-local`).
|
||||
|
||||
### `models status`
|
||||
|
||||
옵션:
|
||||
|
||||
- `--json`
|
||||
- `--plain`
|
||||
- `--check` (종료 코드 1=만료/누락, 2=만료 임박)
|
||||
- `--probe` (구성된 인증 프로필의 실시간 프로브)
|
||||
- `--probe-provider <name>` (하나의 provider 프로브)
|
||||
- `--probe-profile <id>` (반복 또는 쉼표로 구분된 프로필 ID)
|
||||
- `--probe-timeout <ms>`
|
||||
- `--probe-concurrency <n>`
|
||||
- `--probe-max-tokens <n>`
|
||||
- `--agent <id>` (구성된 에이전트 ID, `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR` 재정의)
|
||||
|
||||
프로브 상태 버킷:
|
||||
|
||||
- `ok`
|
||||
- `auth`
|
||||
- `rate_limit`
|
||||
- `billing`
|
||||
- `timeout`
|
||||
- `format`
|
||||
- `unknown`
|
||||
- `no_model`
|
||||
|
||||
예상되는 프로브 상세/이유 코드 사례:
|
||||
|
||||
- `excluded_by_auth_order`: 저장된 프로필은 존재하지만 명시적인
|
||||
`auth.order.<provider>`에 포함되지 않아, 프로브는 시도하는 대신
|
||||
제외 사실을 보고합니다.
|
||||
- `missing_credential`, `invalid_expires`, `expired`, `unresolved_ref`:
|
||||
프로필은 존재하지만 적격하지 않거나 해석할 수 없습니다.
|
||||
- `no_model`: provider 인증은 존재하지만, OpenClaw가 해당 provider에 대해
|
||||
프로브 가능한 모델 후보를 해석할 수 없었습니다.
|
||||
|
||||
## 별칭 + 대체 모델
|
||||
|
||||
```bash
|
||||
openclaw models aliases list
|
||||
openclaw models fallbacks list
|
||||
```
|
||||
|
||||
## 인증 프로필
|
||||
|
||||
```bash
|
||||
openclaw models auth add
|
||||
openclaw models auth login --provider <id>
|
||||
openclaw models auth setup-token --provider <id>
|
||||
openclaw models auth paste-token
|
||||
```
|
||||
|
||||
`models auth add`는 대화형 인증 도우미입니다. 선택한 provider에 따라
|
||||
provider 인증 흐름(OAuth/API 키)을 시작하거나 수동 토큰 붙여넣기로 안내할 수 있습니다.
|
||||
|
||||
`models auth login`은 provider plugin의 인증 흐름(OAuth/API 키)을 실행합니다.
|
||||
설치된 provider를 보려면 `openclaw plugins list`를 사용하세요.
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw models auth login --provider anthropic --method cli --set-default
|
||||
openclaw models auth login --provider openai-codex --set-default
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `login --provider anthropic --method cli --set-default`는 로컬 Claude
|
||||
CLI 로그인을 재사용하고 메인 Anthropic 기본 모델 경로를 정식
|
||||
`claude-cli/claude-*` ref로 다시 씁니다.
|
||||
- `setup-token`과 `paste-token`은 토큰 인증 방법을 노출하는 provider를 위한
|
||||
일반적인 토큰 명령으로 유지됩니다.
|
||||
- `setup-token`은 대화형 TTY가 필요하며 provider의 토큰 인증
|
||||
메서드를 실행합니다(해당 provider가 노출하는 경우 기본적으로 그 provider의 `setup-token`
|
||||
메서드를 사용).
|
||||
- `paste-token`은 다른 곳이나 자동화에서 생성된 토큰 문자열을 받습니다.
|
||||
- `paste-token`은 `--provider`가 필요하고, 토큰 값을 묻는 프롬프트를 표시하며,
|
||||
`--profile-id`를 전달하지 않으면 기본 프로필 ID `<provider>:manual`에 기록합니다.
|
||||
- `paste-token --expires-in <duration>`은 `365d` 또는 `12h` 같은
|
||||
상대 기간으로부터 절대 토큰 만료 시점을 저장합니다.
|
||||
- Anthropic 과금 참고: Anthropic의 공개 CLI 문서를 기준으로 보면 Claude Code CLI 대체 경로는 로컬의 사용자 관리 자동화에는 허용될 가능성이 높다고 판단합니다. 다만, 외부 제품에서 구독 기반 사용에 대한 Anthropic의 서드파티 하니스 정책에는 충분한 모호성이 있어 프로덕션에서는 권장하지 않습니다. 또한 Anthropic은 **2026년 4월 4일 오후 12:00 PT / 오후 8:00 BST**에 OpenClaw 사용자에게 **OpenClaw** Claude 로그인 경로가 서드파티 하니스 사용으로 간주되며, 구독과 별도로 청구되는 **Extra Usage**가 필요하다고 알렸습니다.
|
||||
- Anthropic `setup-token` / `paste-token`은 레거시/수동 OpenClaw 경로로 다시 사용할 수 있습니다. 이 경로는 Anthropic이 OpenClaw 사용자에게 **Extra Usage**가 필요하다고 안내한 점을 전제로 사용하세요.
|
||||
139
docs/ko/cli/node.md
Normal file
139
docs/ko/cli/node.md
Normal file
@ -0,0 +1,139 @@
|
||||
---
|
||||
read_when:
|
||||
- 헤드리스 노드 호스트를 실행할 때
|
||||
- system.run용 비 macOS 노드를 페어링할 때
|
||||
summary: '`openclaw node`용 CLI 참조(헤드리스 노드 호스트)'
|
||||
title: node
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:39Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6123b33ec46f2b85f2c815947435ac91bbe84456165ff0e504453356da55b46d
|
||||
source_path: cli/node.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw node`
|
||||
|
||||
Gateway WebSocket에 연결하고 이 머신에서
|
||||
`system.run` / `system.which`를 노출하는 **헤드리스 노드 호스트**를 실행합니다.
|
||||
|
||||
## 왜 노드 호스트를 사용하나요?
|
||||
|
||||
네트워크의 다른 머신에서 **전체 macOS 컴패니언 앱을 설치하지 않고도**
|
||||
에이전트가 **명령을 실행**하게 하려면 노드 호스트를 사용하세요.
|
||||
|
||||
일반적인 사용 사례:
|
||||
|
||||
- 원격 Linux/Windows 머신(빌드 서버, 실험실 머신, NAS)에서 명령 실행
|
||||
- exec는 gateway에서 **샌드박싱된 상태**로 유지하면서, 승인된 실행은 다른 호스트에 위임
|
||||
- 자동화 또는 CI 노드용 경량 헤드리스 실행 대상 제공
|
||||
|
||||
실행은 여전히 노드 호스트의 **exec 승인** 및 에이전트별 허용 목록으로 보호되므로,
|
||||
명령 액세스 범위를 명확하고 제한적으로 유지할 수 있습니다.
|
||||
|
||||
## 브라우저 프록시(무구성)
|
||||
|
||||
노드에서 `browser.enabled`가 비활성화되지 않은 경우 노드 호스트는 자동으로 브라우저 프록시를 광고합니다. 이를 통해 추가 구성 없이 에이전트가 해당 노드에서 브라우저 자동화를 사용할 수 있습니다.
|
||||
|
||||
기본적으로 프록시는 노드의 일반 브라우저 프로필 표면을 노출합니다. `nodeHost.browserProxy.allowProfiles`를 설정하면 프록시는 제한적으로 동작합니다. 허용 목록에 없는 프로필 대상 지정은 거부되며, 영구 프로필 생성/삭제 라우트는 프록시를 통해 차단됩니다.
|
||||
|
||||
필요하면 노드에서 비활성화하세요.
|
||||
|
||||
```json5
|
||||
{
|
||||
nodeHost: {
|
||||
browserProxy: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 실행(포그라운드)
|
||||
|
||||
```bash
|
||||
openclaw node run --host <gateway-host> --port 18789
|
||||
```
|
||||
|
||||
옵션:
|
||||
|
||||
- `--host <host>`: Gateway WebSocket 호스트(기본값: `127.0.0.1`)
|
||||
- `--port <port>`: Gateway WebSocket 포트(기본값: `18789`)
|
||||
- `--tls`: gateway 연결에 TLS 사용
|
||||
- `--tls-fingerprint <sha256>`: 예상 TLS 인증서 지문(sha256)
|
||||
- `--node-id <id>`: 노드 ID 재정의(페어링 토큰 지움)
|
||||
- `--display-name <name>`: 노드 표시 이름 재정의
|
||||
|
||||
## 노드 호스트용 Gateway 인증
|
||||
|
||||
`openclaw node run` 및 `openclaw node install`은 config/env에서 gateway 인증을 해석합니다(노드 명령에는 `--token`/`--password` 플래그 없음).
|
||||
|
||||
- 먼저 `OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`를 확인합니다.
|
||||
- 그다음 로컬 config 폴백: `gateway.auth.token` / `gateway.auth.password`.
|
||||
- 로컬 모드에서 노드 호스트는 의도적으로 `gateway.remote.token` / `gateway.remote.password`를 상속하지 않습니다.
|
||||
- `gateway.auth.token` / `gateway.auth.password`가 SecretRef를 통해 명시적으로 구성되었지만 해석되지 않으면, 노드 인증 해석은 fail closed로 동작합니다(원격 폴백에 의해 가려지지 않음).
|
||||
- `gateway.mode=remote`에서는 원격 우선순위 규칙에 따라 원격 클라이언트 필드(`gateway.remote.token` / `gateway.remote.password`)도 사용할 수 있습니다.
|
||||
- 노드 호스트 인증 해석은 `OPENCLAW_GATEWAY_*` 환경 변수만 존중합니다.
|
||||
|
||||
## 서비스(백그라운드)
|
||||
|
||||
헤드리스 노드 호스트를 사용자 서비스로 설치합니다.
|
||||
|
||||
```bash
|
||||
openclaw node install --host <gateway-host> --port 18789
|
||||
```
|
||||
|
||||
옵션:
|
||||
|
||||
- `--host <host>`: Gateway WebSocket 호스트(기본값: `127.0.0.1`)
|
||||
- `--port <port>`: Gateway WebSocket 포트(기본값: `18789`)
|
||||
- `--tls`: gateway 연결에 TLS 사용
|
||||
- `--tls-fingerprint <sha256>`: 예상 TLS 인증서 지문(sha256)
|
||||
- `--node-id <id>`: 노드 ID 재정의(페어링 토큰 지움)
|
||||
- `--display-name <name>`: 노드 표시 이름 재정의
|
||||
- `--runtime <runtime>`: 서비스 런타임(`node` 또는 `bun`)
|
||||
- `--force`: 이미 설치된 경우 재설치/덮어쓰기
|
||||
|
||||
서비스 관리:
|
||||
|
||||
```bash
|
||||
openclaw node status
|
||||
openclaw node stop
|
||||
openclaw node restart
|
||||
openclaw node uninstall
|
||||
```
|
||||
|
||||
포그라운드 노드 호스트(서비스 없음)에는 `openclaw node run`을 사용하세요.
|
||||
|
||||
서비스 명령은 기계 판독 가능한 출력을 위해 `--json`을 지원합니다.
|
||||
|
||||
## 페어링
|
||||
|
||||
첫 번째 연결은 Gateway에 보류 중인 디바이스 페어링 요청(`role: node`)을 생성합니다.
|
||||
다음으로 승인하세요.
|
||||
|
||||
```bash
|
||||
openclaw devices list
|
||||
openclaw devices approve <requestId>
|
||||
```
|
||||
|
||||
노드가 변경된 인증 세부 정보(role/scopes/public key)로 페어링을 다시 시도하면,
|
||||
이전 보류 요청은 대체되고 새 `requestId`가 생성됩니다.
|
||||
승인 전에 `openclaw devices list`를 다시 실행하세요.
|
||||
|
||||
노드 호스트는 노드 ID, 토큰, 표시 이름, gateway 연결 정보를
|
||||
`~/.openclaw/node.json`에 저장합니다.
|
||||
|
||||
## Exec 승인
|
||||
|
||||
`system.run`은 로컬 exec 승인에 의해 제어됩니다.
|
||||
|
||||
- `~/.openclaw/exec-approvals.json`
|
||||
- [Exec 승인](/tools/exec-approvals)
|
||||
- `openclaw approvals --node <id|name|ip>` (Gateway에서 편집)
|
||||
|
||||
승인된 비동기 노드 exec의 경우, OpenClaw는 프롬프트 전에 정규 `systemRunPlan`을 준비합니다.
|
||||
이후 승인된 `system.run` 전달은 저장된 해당
|
||||
plan을 재사용하므로, 승인 요청이 생성된 뒤 명령/cwd/세션 필드를 편집해도
|
||||
노드가 실행하는 내용이 바뀌는 대신 거부됩니다.
|
||||
73
docs/ko/cli/nodes.md
Normal file
73
docs/ko/cli/nodes.md
Normal file
@ -0,0 +1,73 @@
|
||||
---
|
||||
read_when:
|
||||
- 페어링된 노드(카메라, screen, canvas)를 관리하는 중
|
||||
- 요청을 승인하거나 노드 명령을 호출해야 함
|
||||
summary: '`openclaw nodes`용 CLI 참조(status, pairing, invoke, camera/canvas/screen)'
|
||||
title: nodes
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:32Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 1ce3095591c4623ad18e3eca8d8083e5c10266fbf94afea2d025f0ba8093a175
|
||||
source_path: cli/nodes.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw nodes`
|
||||
|
||||
페어링된 노드(기기)를 관리하고 노드 기능을 호출합니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- 노드 개요: [Nodes](/nodes)
|
||||
- 카메라: [Camera nodes](/nodes/camera)
|
||||
- 이미지: [Image nodes](/nodes/images)
|
||||
|
||||
공통 옵션:
|
||||
|
||||
- `--url`, `--token`, `--timeout`, `--json`
|
||||
|
||||
## 일반적인 명령
|
||||
|
||||
```bash
|
||||
openclaw nodes list
|
||||
openclaw nodes list --connected
|
||||
openclaw nodes list --last-connected 24h
|
||||
openclaw nodes pending
|
||||
openclaw nodes approve <requestId>
|
||||
openclaw nodes reject <requestId>
|
||||
openclaw nodes rename --node <id|name|ip> --name <displayName>
|
||||
openclaw nodes status
|
||||
openclaw nodes status --connected
|
||||
openclaw nodes status --last-connected 24h
|
||||
```
|
||||
|
||||
`nodes list`는 대기 중/페어링된 표를 출력합니다. 페어링된 행에는 가장 최근 연결 경과 시간(Last Connect)이 포함됩니다.
|
||||
현재 연결된 노드만 표시하려면 `--connected`를 사용하세요. `--last-connected <duration>`을 사용하면
|
||||
지정한 기간 내에 연결된 노드로 필터링할 수 있습니다(예: `24h`, `7d`).
|
||||
|
||||
승인 참고:
|
||||
|
||||
- `openclaw nodes pending`은 pairing scope만 필요합니다.
|
||||
- `openclaw nodes approve <requestId>`는 대기 요청의
|
||||
추가 scope 요구 사항을 상속합니다.
|
||||
- 명령 없는 요청: pairing만
|
||||
- exec가 아닌 노드 명령: pairing + write
|
||||
- `system.run` / `system.run.prepare` / `system.which`: pairing + admin
|
||||
|
||||
## 호출
|
||||
|
||||
```bash
|
||||
openclaw nodes invoke --node <id|name|ip> --command <command> --params <json>
|
||||
```
|
||||
|
||||
호출 플래그:
|
||||
|
||||
- `--params <json>`: JSON 객체 문자열(기본값 `{}`).
|
||||
- `--invoke-timeout <ms>`: 노드 호출 타임아웃(기본값 `15000`).
|
||||
- `--idempotency-key <key>`: 선택적 멱등성 키.
|
||||
- `system.run` 및 `system.run.prepare`는 여기서 차단됩니다. 셸 실행에는 `host=node`와 함께 `exec` 도구를 사용하세요.
|
||||
|
||||
노드에서 셸을 실행하려면 `openclaw nodes run` 대신 `host=node`와 함께 `exec` 도구를 사용하세요.
|
||||
이제 `nodes` CLI는 기능 중심입니다. 직접 RPC는 `nodes invoke`로 수행하며, 그 외 pairing, camera,
|
||||
screen, location, canvas, notifications를 지원합니다.
|
||||
177
docs/ko/cli/onboard.md
Normal file
177
docs/ko/cli/onboard.md
Normal file
@ -0,0 +1,177 @@
|
||||
---
|
||||
read_when:
|
||||
- 게이트웨이, 워크스페이스, 인증, 채널, Skills에 대한 안내형 설정이 필요할 때
|
||||
summary: '`openclaw onboard`용 CLI 참조(대화형 온보딩)'
|
||||
title: onboard
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:52Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6db61c8002c9e82e48ff44f72e176b58ad85fad5cb8434687455ed40add8cc2a
|
||||
source_path: cli/onboard.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw onboard`
|
||||
|
||||
로컬 또는 원격 게이트웨이 설정을 위한 대화형 온보딩입니다.
|
||||
|
||||
## 관련 가이드
|
||||
|
||||
- CLI 온보딩 허브: [온보딩(CLI)](/ko/start/wizard)
|
||||
- 온보딩 개요: [온보딩 개요](/start/onboarding-overview)
|
||||
- CLI 온보딩 참조: [CLI 설정 참조](/start/wizard-cli-reference)
|
||||
- CLI 자동화: [CLI 자동화](/start/wizard-cli-automation)
|
||||
- macOS 온보딩: [온보딩(macOS 앱)](/start/onboarding)
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw onboard
|
||||
openclaw onboard --flow quickstart
|
||||
openclaw onboard --flow manual
|
||||
openclaw onboard --mode remote --remote-url wss://gateway-host:18789
|
||||
```
|
||||
|
||||
평문 private-network `ws://` 대상(신뢰된 네트워크 전용)의 경우,
|
||||
온보딩 프로세스 환경에서 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`을 설정하세요.
|
||||
|
||||
비대화형 사용자 지정 provider:
|
||||
|
||||
```bash
|
||||
openclaw onboard --non-interactive \
|
||||
--auth-choice custom-api-key \
|
||||
--custom-base-url "https://llm.example.com/v1" \
|
||||
--custom-model-id "foo-large" \
|
||||
--custom-api-key "$CUSTOM_API_KEY" \
|
||||
--secret-input-mode plaintext \
|
||||
--custom-compatibility openai
|
||||
```
|
||||
|
||||
비대화형 모드에서는 `--custom-api-key`가 선택 사항입니다. 생략하면 온보딩은 `CUSTOM_API_KEY`를 확인합니다.
|
||||
|
||||
비대화형 Ollama:
|
||||
|
||||
```bash
|
||||
openclaw onboard --non-interactive \
|
||||
--auth-choice ollama \
|
||||
--custom-base-url "http://ollama-host:11434" \
|
||||
--custom-model-id "qwen3.5:27b" \
|
||||
--accept-risk
|
||||
```
|
||||
|
||||
`--custom-base-url`의 기본값은 `http://127.0.0.1:11434`입니다. `--custom-model-id`는 선택 사항이며, 생략하면 온보딩은 Ollama의 권장 기본값을 사용합니다. `kimi-k2.5:cloud` 같은 클라우드 모델 ID도 여기서 사용할 수 있습니다.
|
||||
|
||||
provider 키를 일반 텍스트 대신 ref로 저장:
|
||||
|
||||
```bash
|
||||
openclaw onboard --non-interactive \
|
||||
--auth-choice openai-api-key \
|
||||
--secret-input-mode ref \
|
||||
--accept-risk
|
||||
```
|
||||
|
||||
`--secret-input-mode ref`를 사용하면 온보딩은 일반 텍스트 키 값 대신 env 기반 ref를 기록합니다.
|
||||
auth-profile 기반 provider의 경우 `keyRef` 항목을 기록하고, 사용자 지정 provider의 경우 `models.providers.<id>.apiKey`를 env ref로 기록합니다(예: `{ source: "env", provider: "default", id: "CUSTOM_API_KEY" }`).
|
||||
|
||||
비대화형 `ref` 모드 계약:
|
||||
|
||||
- 온보딩 프로세스 환경에서 provider env var를 설정하세요(예: `OPENAI_API_KEY`).
|
||||
- 해당 env var도 설정되어 있지 않다면 인라인 키 플래그(예: `--openai-api-key`)를 전달하지 마세요.
|
||||
- 필요한 env var 없이 인라인 키 플래그가 전달되면, 온보딩은 안내 메시지와 함께 즉시 실패합니다.
|
||||
|
||||
비대화형 모드의 게이트웨이 토큰 옵션:
|
||||
|
||||
- `--gateway-auth token --gateway-token <token>`은 일반 텍스트 토큰을 저장합니다.
|
||||
- `--gateway-auth token --gateway-token-ref-env <name>`은 `gateway.auth.token`을 env SecretRef로 저장합니다.
|
||||
- `--gateway-token`과 `--gateway-token-ref-env`는 서로 함께 사용할 수 없습니다.
|
||||
- `--gateway-token-ref-env`는 온보딩 프로세스 환경에 비어 있지 않은 env var가 필요합니다.
|
||||
- `--install-daemon` 사용 시 토큰 인증에 토큰이 필요한 경우, SecretRef로 관리되는 게이트웨이 토큰은 검증되지만 supervisor 서비스 환경 메타데이터에 해석된 일반 텍스트로 저장되지는 않습니다.
|
||||
- `--install-daemon` 사용 시 토큰 모드에 토큰이 필요하고 구성된 토큰 SecretRef가 해석되지 않으면, 온보딩은 해결 방법 안내와 함께 실패 종료합니다.
|
||||
- `--install-daemon` 사용 시 `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있는데 `gateway.auth.mode`가 설정되지 않은 경우, 온보딩은 모드를 명시적으로 설정할 때까지 설치를 차단합니다.
|
||||
- 로컬 온보딩은 config에 `gateway.mode="local"`을 기록합니다. 이후 config 파일에 `gateway.mode`가 없다면, 이는 유효한 로컬 모드 단축 경로가 아니라 config 손상 또는 불완전한 수동 편집으로 간주해야 합니다.
|
||||
- `--allow-unconfigured`는 별도의 게이트웨이 런타임 이스케이프 해치입니다. 온보딩에서 `gateway.mode`를 생략해도 된다는 뜻은 아닙니다.
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
export OPENCLAW_GATEWAY_TOKEN="your-token"
|
||||
openclaw onboard --non-interactive \
|
||||
--mode local \
|
||||
--auth-choice skip \
|
||||
--gateway-auth token \
|
||||
--gateway-token-ref-env OPENCLAW_GATEWAY_TOKEN \
|
||||
--accept-risk
|
||||
```
|
||||
|
||||
비대화형 로컬 게이트웨이 상태 확인:
|
||||
|
||||
- `--skip-health`를 전달하지 않으면, 온보딩은 도달 가능한 로컬 게이트웨이를 확인한 뒤에만 성공적으로 종료합니다.
|
||||
- `--install-daemon`은 먼저 관리형 게이트웨이 설치 경로를 시작합니다. 이를 사용하지 않으면 `openclaw gateway run`처럼 로컬 게이트웨이가 이미 실행 중이어야 합니다.
|
||||
- 자동화에서 config/workspace/bootstrap 기록만 원한다면 `--skip-health`를 사용하세요.
|
||||
- 네이티브 Windows에서 `--install-daemon`은 먼저 Scheduled Tasks를 시도하고, 작업 생성이 거부되면 사용자별 Startup 폴더 로그인 항목으로 대체합니다.
|
||||
|
||||
ref 모드의 대화형 온보딩 동작:
|
||||
|
||||
- 프롬프트가 나타나면 **Use secret reference**를 선택하세요.
|
||||
- 그다음 다음 중 하나를 선택하세요:
|
||||
- 환경 변수
|
||||
- 구성된 secret provider(`file` 또는 `exec`)
|
||||
- 온보딩은 ref를 저장하기 전에 빠른 사전 검증을 수행합니다.
|
||||
- 검증에 실패하면, 온보딩은 오류를 표시하고 다시 시도할 수 있게 합니다.
|
||||
|
||||
비대화형 Z.AI 엔드포인트 선택:
|
||||
|
||||
참고: `--auth-choice zai-api-key`는 이제 키에 가장 적합한 Z.AI 엔드포인트를 자동 감지합니다(`zai/glm-5`가 있는 일반 API를 우선).
|
||||
특별히 GLM Coding Plan 엔드포인트를 원하면 `zai-coding-global` 또는 `zai-coding-cn`을 선택하세요.
|
||||
|
||||
```bash
|
||||
# 프롬프트 없는 엔드포인트 선택
|
||||
openclaw onboard --non-interactive \
|
||||
--auth-choice zai-coding-global \
|
||||
--zai-api-key "$ZAI_API_KEY"
|
||||
|
||||
# 다른 Z.AI 엔드포인트 선택:
|
||||
# --auth-choice zai-coding-cn
|
||||
# --auth-choice zai-global
|
||||
# --auth-choice zai-cn
|
||||
```
|
||||
|
||||
비대화형 Mistral 예시:
|
||||
|
||||
```bash
|
||||
openclaw onboard --non-interactive \
|
||||
--auth-choice mistral-api-key \
|
||||
--mistral-api-key "$MISTRAL_API_KEY"
|
||||
```
|
||||
|
||||
흐름 참고:
|
||||
|
||||
- `quickstart`: 최소 프롬프트, 게이트웨이 토큰 자동 생성.
|
||||
- `manual`: 포트/바인드/인증에 대한 전체 프롬프트(`advanced`의 별칭).
|
||||
- 인증 선택이 선호 provider를 암시하는 경우, 온보딩은
|
||||
기본 모델 및 허용 목록 선택기를 해당 provider로 미리 필터링합니다. Volcengine과
|
||||
BytePlus의 경우 coding-plan 변형도 함께 일치시킵니다
|
||||
(`volcengine-plan/*`, `byteplus-plan/*`).
|
||||
- 선호 provider 필터에서 아직 로드된 모델이 하나도 없으면, 온보딩은
|
||||
선택기를 비워 두는 대신 필터링되지 않은 카탈로그로 대체합니다.
|
||||
- 웹 검색 단계에서 일부 provider는 provider별
|
||||
후속 프롬프트를 트리거할 수 있습니다:
|
||||
- **Grok**은 동일한 `XAI_API_KEY`와
|
||||
`x_search` 모델 선택으로 선택적 `x_search` 설정을 제안할 수 있습니다.
|
||||
- **Kimi**는 Moonshot API 리전(`api.moonshot.ai` vs
|
||||
`api.moonshot.cn`)과 기본 Kimi 웹 검색 모델을 물을 수 있습니다.
|
||||
- 로컬 온보딩 DM 범위 동작: [CLI 설정 참조](/start/wizard-cli-reference#outputs-and-internals).
|
||||
- 가장 빠른 첫 채팅: `openclaw dashboard`(제어 UI, 채널 설정 불필요).
|
||||
- 사용자 지정 Provider: 목록에 없는 호스팅 provider를 포함해 OpenAI 또는 Anthropic 호환 엔드포인트에 연결합니다. 자동 감지에는 Unknown을 사용하세요.
|
||||
|
||||
## 일반적인 후속 명령
|
||||
|
||||
```bash
|
||||
openclaw configure
|
||||
openclaw agents add <name>
|
||||
```
|
||||
|
||||
<Note>
|
||||
`--json`은 비대화형 모드를 의미하지 않습니다. 스크립트에서는 `--non-interactive`를 사용하세요.
|
||||
</Note>
|
||||
72
docs/ko/cli/pairing.md
Normal file
72
docs/ko/cli/pairing.md
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
read_when:
|
||||
- pairing 모드 DM을 사용 중이고 발신자를 승인해야 하는 경우
|
||||
summary: '`openclaw pairing`용 CLI 참조(페어링 요청 승인/목록)'
|
||||
title: pairing
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:43Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 122a608ef83ec2b1011fdfd1b59b94950a4dcc8b598335b0956e2eedece4958f
|
||||
source_path: cli/pairing.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw pairing`
|
||||
|
||||
DM 페어링 요청을 승인하거나 검사합니다(페어링을 지원하는 채널용).
|
||||
|
||||
관련 문서:
|
||||
|
||||
- 페어링 흐름: [페어링](/channels/pairing)
|
||||
|
||||
## 명령
|
||||
|
||||
```bash
|
||||
openclaw pairing list telegram
|
||||
openclaw pairing list --channel telegram --account work
|
||||
openclaw pairing list telegram --json
|
||||
|
||||
openclaw pairing approve <code>
|
||||
openclaw pairing approve telegram <code>
|
||||
openclaw pairing approve --channel telegram --account work <code> --notify
|
||||
```
|
||||
|
||||
## `pairing list`
|
||||
|
||||
하나의 채널에 대한 대기 중인 페어링 요청을 나열합니다.
|
||||
|
||||
옵션:
|
||||
|
||||
- `[channel]`: 위치 기반 채널 ID
|
||||
- `--channel <channel>`: 명시적 채널 ID
|
||||
- `--account <accountId>`: 다중 계정 채널용 계정 ID
|
||||
- `--json`: 기계 판독 가능 출력
|
||||
|
||||
참고:
|
||||
|
||||
- 여러 페어링 지원 채널이 구성된 경우, 위치 인수 또는 `--channel`을 사용해 채널을 제공해야 합니다.
|
||||
- 채널 ID가 유효한 한 extension 채널도 허용됩니다.
|
||||
|
||||
## `pairing approve`
|
||||
|
||||
대기 중인 페어링 코드를 승인하고 해당 발신자를 허용합니다.
|
||||
|
||||
사용법:
|
||||
|
||||
- `openclaw pairing approve <channel> <code>`
|
||||
- `openclaw pairing approve --channel <channel> <code>`
|
||||
- 정확히 하나의 페어링 지원 채널만 구성된 경우 `openclaw pairing approve <code>`
|
||||
|
||||
옵션:
|
||||
|
||||
- `--channel <channel>`: 명시적 채널 ID
|
||||
- `--account <accountId>`: 다중 계정 채널용 계정 ID
|
||||
- `--notify`: 동일한 채널에서 요청자에게 확인 메시지 전송
|
||||
|
||||
## 참고
|
||||
|
||||
- 채널 입력: 위치 인수로 전달하거나(`pairing list telegram`) `--channel <channel>`을 사용하세요.
|
||||
- `pairing list`는 다중 계정 채널에 대해 `--account <accountId>`를 지원합니다.
|
||||
- `pairing approve`는 `--account <accountId>` 및 `--notify`를 지원합니다.
|
||||
- 하나의 페어링 지원 채널만 구성된 경우 `pairing approve <code>`를 사용할 수 있습니다.
|
||||
305
docs/ko/cli/plugins.md
Normal file
305
docs/ko/cli/plugins.md
Normal file
@ -0,0 +1,305 @@
|
||||
---
|
||||
read_when:
|
||||
- Gateway 플러그인 또는 호환 번들을 설치하거나 관리하려는 경우
|
||||
- 플러그인 로드 실패를 디버그하려는 경우
|
||||
summary: '`openclaw plugins`용 CLI 참조(list, install, marketplace, uninstall, enable/disable, doctor)'
|
||||
title: plugins
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:10Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 8c35ccf68cd7be1af5fee175bd1ce7de88b81c625a05a23887e5780e790df925
|
||||
source_path: cli/plugins.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw plugins`
|
||||
|
||||
Gateway 플러그인/확장, hook pack, 호환 번들을 관리합니다.
|
||||
|
||||
관련 항목:
|
||||
|
||||
- 플러그인 시스템: [Plugins](/tools/plugin)
|
||||
- 번들 호환성: [Plugin bundles](/plugins/bundles)
|
||||
- 플러그인 manifest + schema: [Plugin manifest](/plugins/manifest)
|
||||
- 보안 강화: [Security](/gateway/security)
|
||||
|
||||
## 명령
|
||||
|
||||
```bash
|
||||
openclaw plugins list
|
||||
openclaw plugins list --enabled
|
||||
openclaw plugins list --verbose
|
||||
openclaw plugins list --json
|
||||
openclaw plugins install <path-or-spec>
|
||||
openclaw plugins inspect <id>
|
||||
openclaw plugins inspect <id> --json
|
||||
openclaw plugins inspect --all
|
||||
openclaw plugins info <id>
|
||||
openclaw plugins enable <id>
|
||||
openclaw plugins disable <id>
|
||||
openclaw plugins uninstall <id>
|
||||
openclaw plugins doctor
|
||||
openclaw plugins update <id>
|
||||
openclaw plugins update --all
|
||||
openclaw plugins marketplace list <marketplace>
|
||||
openclaw plugins marketplace list <marketplace> --json
|
||||
```
|
||||
|
||||
번들 플러그인은 OpenClaw와 함께 제공됩니다. 일부는 기본적으로 활성화되어 있으며(예:
|
||||
번들 모델 provider, 번들 음성 provider, 번들 browser
|
||||
plugin), 다른 것들은 `plugins enable`이 필요합니다.
|
||||
|
||||
네이티브 OpenClaw 플러그인은 인라인 JSON
|
||||
Schema(`configSchema`, 비어 있어도 포함)와 함께 `openclaw.plugin.json`을 제공해야 합니다. 호환 번들은 대신 자체 번들
|
||||
manifest를 사용합니다.
|
||||
|
||||
`plugins list`는 `Format: openclaw` 또는 `Format: bundle`을 표시합니다. 자세한 list/info
|
||||
출력에는 번들 하위 유형(`codex`, `claude`, 또는 `cursor`)과 감지된 번들
|
||||
기능도 표시됩니다.
|
||||
|
||||
### 설치
|
||||
|
||||
```bash
|
||||
openclaw plugins install <package> # 먼저 ClawHub, 그다음 npm
|
||||
openclaw plugins install clawhub:<package> # ClawHub만
|
||||
openclaw plugins install <package> --force # 기존 설치 덮어쓰기
|
||||
openclaw plugins install <package> --pin # 버전 고정
|
||||
openclaw plugins install <package> --dangerously-force-unsafe-install
|
||||
openclaw plugins install <path> # 로컬 경로
|
||||
openclaw plugins install <plugin>@<marketplace> # marketplace
|
||||
openclaw plugins install <plugin> --marketplace <name> # marketplace (명시적)
|
||||
openclaw plugins install <plugin> --marketplace https://github.com/<owner>/<repo>
|
||||
```
|
||||
|
||||
접두사 없는 패키지 이름은 먼저 ClawHub에서 확인한 다음 npm을 확인합니다. 보안 참고:
|
||||
플러그인 설치는 코드 실행처럼 취급하세요. 고정된 버전을 권장합니다.
|
||||
|
||||
config가 유효하지 않으면 `plugins install`은 일반적으로 실패 시 닫힘 방식으로 동작하며 먼저
|
||||
`openclaw doctor --fix`를 실행하라고 안내합니다. 문서화된 유일한 예외는
|
||||
명시적으로
|
||||
`openclaw.install.allowInvalidConfigRecovery`를 opt-in한 플러그인을 위한 제한적인 번들 플러그인 복구 경로입니다.
|
||||
|
||||
`--force`는 기존 설치 대상을 재사용하고 이미 설치된
|
||||
플러그인 또는 hook pack을 제자리에서 덮어씁니다. 새 로컬 경로, archive, ClawHub 패키지 또는 npm artifact에서
|
||||
동일한 ID를 의도적으로 다시 설치할 때 사용하세요.
|
||||
|
||||
`--pin`은 npm 설치에만 적용됩니다. `--marketplace`와는 함께 사용할 수 없습니다.
|
||||
marketplace 설치는 npm spec 대신 marketplace 소스 메타데이터를 유지하기 때문입니다.
|
||||
|
||||
`--dangerously-force-unsafe-install`은 내장된 dangerous-code scanner의 오탐을 위한 비상용 옵션입니다.
|
||||
내장 scanner가 `critical` 결과를 보고해도 설치를 계속 진행할 수 있게 하지만,
|
||||
플러그인 `before_install` hook 정책 차단은 **우회하지 않으며**,
|
||||
scan 실패도 우회하지 않습니다.
|
||||
|
||||
이 CLI 플래그는 플러그인 설치/업데이트 흐름에 적용됩니다. Gateway 기반 Skills
|
||||
종속성 설치는 대응되는 `dangerouslyForceUnsafeInstall` 요청
|
||||
재정의를 사용하며, `openclaw skills install`은 별도의 ClawHub Skills
|
||||
다운로드/설치 흐름으로 유지됩니다.
|
||||
|
||||
`plugins install`은 `package.json`에
|
||||
`openclaw.hooks`를 노출하는 hook pack의 설치 표면이기도 합니다. 필터링된 hook
|
||||
가시성과 hook별 활성화에는 패키지 설치가 아니라 `openclaw hooks`를 사용하세요.
|
||||
|
||||
npm spec은 **registry 전용**입니다(패키지 이름 + 선택적 **정확한 버전** 또는
|
||||
**dist-tag**). Git/URL/file spec과 semver 범위는 거부됩니다. 종속성 설치는 안전을 위해
|
||||
`--ignore-scripts`와 함께 실행됩니다.
|
||||
|
||||
접두사 없는 spec과 `@latest`는 stable 트랙을 유지합니다. npm이 이 둘 중 하나를 prerelease로 해석하면
|
||||
OpenClaw는 중단하고
|
||||
`@beta`/`@rc` 같은 prerelease 태그나 `@1.2.3-beta.4` 같은 정확한 prerelease 버전으로
|
||||
명시적으로 opt-in하라고 요청합니다.
|
||||
|
||||
접두사 없는 설치 spec이 번들 플러그인 ID(예: `diffs`)와 일치하면 OpenClaw는
|
||||
번들 플러그인을 직접 설치합니다. 같은 이름의 npm 패키지를 설치하려면 명시적인 scoped spec을
|
||||
사용하세요(예: `@scope/diffs`).
|
||||
|
||||
지원되는 archive: `.zip`, `.tgz`, `.tar.gz`, `.tar`.
|
||||
|
||||
Claude marketplace 설치도 지원됩니다.
|
||||
|
||||
ClawHub 설치는 명시적인 `clawhub:<package>` locator를 사용합니다.
|
||||
|
||||
```bash
|
||||
openclaw plugins install clawhub:openclaw-codex-app-server
|
||||
openclaw plugins install clawhub:openclaw-codex-app-server@1.2.3
|
||||
```
|
||||
|
||||
이제 OpenClaw는 접두사 없는 npm-safe 플러그인 spec에 대해서도 ClawHub를 우선 사용합니다. 해당 패키지나 버전이
|
||||
ClawHub에 없을 때만 npm으로 대체합니다.
|
||||
|
||||
```bash
|
||||
openclaw plugins install openclaw-codex-app-server
|
||||
```
|
||||
|
||||
OpenClaw는 ClawHub에서 패키지 archive를 다운로드하고, 광고된
|
||||
플러그인 API / 최소 gateway 호환성을 확인한 뒤, 일반 archive 경로를 통해 설치합니다. 기록된 설치는 나중 업데이트를 위해
|
||||
ClawHub 소스 메타데이터를 유지합니다.
|
||||
|
||||
marketplace 이름이 Claude의 로컬 레지스트리 캐시 `~/.claude/plugins/known_marketplaces.json`에 있을 때는
|
||||
`plugin@marketplace` 축약형을 사용하세요.
|
||||
|
||||
```bash
|
||||
openclaw plugins marketplace list <marketplace-name>
|
||||
openclaw plugins install <plugin-name>@<marketplace-name>
|
||||
```
|
||||
|
||||
marketplace 소스를 명시적으로 전달하려면 `--marketplace`를 사용하세요.
|
||||
|
||||
```bash
|
||||
openclaw plugins install <plugin-name> --marketplace <marketplace-name>
|
||||
openclaw plugins install <plugin-name> --marketplace <owner/repo>
|
||||
openclaw plugins install <plugin-name> --marketplace https://github.com/<owner>/<repo>
|
||||
openclaw plugins install <plugin-name> --marketplace ./my-marketplace
|
||||
```
|
||||
|
||||
Marketplace 소스는 다음 중 하나일 수 있습니다.
|
||||
|
||||
- `~/.claude/plugins/known_marketplaces.json`의 Claude known-marketplace 이름
|
||||
- 로컬 marketplace 루트 또는 `marketplace.json` 경로
|
||||
- `owner/repo` 같은 GitHub repo 축약형
|
||||
- `https://github.com/owner/repo` 같은 GitHub repo URL
|
||||
- git URL
|
||||
|
||||
GitHub 또는 git에서 로드한 원격 marketplace의 경우 플러그인 항목은
|
||||
복제된 marketplace repo 내부에 남아 있어야 합니다. OpenClaw는 해당
|
||||
repo의 상대 경로 소스를 허용하고, 원격 manifest의 HTTP(S), 절대 경로, git, GitHub 및 기타 비경로
|
||||
플러그인 소스는 거부합니다.
|
||||
|
||||
로컬 경로와 archive의 경우 OpenClaw는 다음을 자동 감지합니다.
|
||||
|
||||
- 네이티브 OpenClaw 플러그인 (`openclaw.plugin.json`)
|
||||
- Codex 호환 번들 (`.codex-plugin/plugin.json`)
|
||||
- Claude 호환 번들 (`.claude-plugin/plugin.json` 또는 기본 Claude
|
||||
component 레이아웃)
|
||||
- Cursor 호환 번들 (`.cursor-plugin/plugin.json`)
|
||||
|
||||
호환 번들은 일반 extensions 루트에 설치되고 동일한 list/info/enable/disable 흐름에 참여합니다. 현재는 번들 Skills, Claude
|
||||
command-skills, Claude `settings.json` 기본값, Claude `.lsp.json` /
|
||||
manifest에 선언된 `lspServers` 기본값, Cursor command-skills, 호환
|
||||
Codex hook 디렉터리가 지원됩니다. 다른 감지된 번들 기능은 diagnostics/info에는 표시되지만 아직 런타임 실행에 연결되지는 않았습니다.
|
||||
|
||||
### 목록
|
||||
|
||||
```bash
|
||||
openclaw plugins list
|
||||
openclaw plugins list --enabled
|
||||
openclaw plugins list --verbose
|
||||
openclaw plugins list --json
|
||||
```
|
||||
|
||||
로드된 플러그인만 보려면 `--enabled`를 사용하세요. 테이블 보기에서 플러그인별 세부 줄 보기로 전환하려면
|
||||
`--verbose`를 사용하세요. 소스/출처/버전/활성화
|
||||
메타데이터가 표시됩니다. 기계 판독 가능한 인벤토리와 레지스트리
|
||||
diagnostics에는 `--json`을 사용하세요.
|
||||
|
||||
로컬 디렉터리를 복사하지 않으려면 `--link`를 사용하세요(`plugins.load.paths`에 추가됨).
|
||||
|
||||
```bash
|
||||
openclaw plugins install -l ./my-plugin
|
||||
```
|
||||
|
||||
링크 설치는 관리되는 설치 대상을 복사해 덮어쓰는 대신 소스 경로를 재사용하므로,
|
||||
`--force`는 `--link`와 함께 지원되지 않습니다.
|
||||
|
||||
npm 설치에서 확인된 정확한 spec(`name@version`)을
|
||||
`plugins.installs`에 저장하려면 `--pin`을 사용하세요. 기본 동작은 고정되지 않은 상태로 유지됩니다.
|
||||
|
||||
### 제거
|
||||
|
||||
```bash
|
||||
openclaw plugins uninstall <id>
|
||||
openclaw plugins uninstall <id> --dry-run
|
||||
openclaw plugins uninstall <id> --keep-files
|
||||
```
|
||||
|
||||
`uninstall`은 `plugins.entries`, `plugins.installs`,
|
||||
플러그인 허용 목록, 그리고 해당되는 경우 링크된 `plugins.load.paths` 항목에서 플러그인 기록을 제거합니다.
|
||||
활성 메모리 플러그인의 경우 메모리 슬롯은 `memory-core`로 재설정됩니다.
|
||||
|
||||
기본적으로 제거는 활성
|
||||
state-dir plugin 루트 아래의 플러그인 설치 디렉터리도 삭제합니다. 디스크의 파일을 유지하려면
|
||||
`--keep-files`를 사용하세요.
|
||||
|
||||
`--keep-config`는 `--keep-files`의 deprecated 별칭으로 지원됩니다.
|
||||
|
||||
### 업데이트
|
||||
|
||||
```bash
|
||||
openclaw plugins update <id-or-npm-spec>
|
||||
openclaw plugins update --all
|
||||
openclaw plugins update <id-or-npm-spec> --dry-run
|
||||
openclaw plugins update @openclaw/voice-call@beta
|
||||
openclaw plugins update openclaw-codex-app-server --dangerously-force-unsafe-install
|
||||
```
|
||||
|
||||
업데이트는 `plugins.installs`의 추적된 설치와 `hooks.internal.installs`의 추적된 hook-pack
|
||||
설치에 적용됩니다.
|
||||
|
||||
플러그인 ID를 전달하면 OpenClaw는 해당
|
||||
플러그인에 대해 기록된 설치 spec을 재사용합니다. 즉, 이전에 저장된 `@beta` 같은 dist-tag와 정확히 고정된 버전이 이후 `update <id>` 실행에서도 계속 사용됩니다.
|
||||
|
||||
npm 설치의 경우 dist-tag
|
||||
또는 정확한 버전이 포함된 명시적 npm 패키지 spec도 전달할 수 있습니다. OpenClaw는 해당 패키지 이름을 추적된 플러그인
|
||||
기록에 다시 매핑하고, 설치된 플러그인을 업데이트한 뒤, 이후
|
||||
ID 기반 업데이트를 위해 새 npm spec을 기록합니다.
|
||||
|
||||
저장된 integrity hash가 존재하고 가져온 artifact hash가 변경되면,
|
||||
OpenClaw는 경고를 출력하고 진행 전에 확인을 요청합니다. CI/비대화형 실행에서 프롬프트를 우회하려면
|
||||
전역 `--yes`를 사용하세요.
|
||||
|
||||
`--dangerously-force-unsafe-install`은 `plugins update`에서도
|
||||
플러그인 업데이트 중 내장 dangerous-code scan 오탐을 위한 비상 재정의로 사용할 수 있습니다.
|
||||
여전히 플러그인 `before_install` 정책 차단이나
|
||||
scan-failure 차단은 우회하지 않으며, hook-pack 업데이트가 아니라 플러그인 업데이트에만 적용됩니다.
|
||||
|
||||
### 검사
|
||||
|
||||
```bash
|
||||
openclaw plugins inspect <id>
|
||||
openclaw plugins inspect <id> --json
|
||||
```
|
||||
|
||||
단일 플러그인에 대한 심층 검사입니다. 식별, 로드 상태, 소스,
|
||||
등록된 기능, hook, 도구, 명령, 서비스, gateway 메서드,
|
||||
HTTP 경로, 정책 플래그, diagnostics, 설치 메타데이터, 번들 기능,
|
||||
그리고 감지된 MCP 또는 LSP 서버 지원을 표시합니다.
|
||||
|
||||
각 플러그인은 런타임에 실제로 등록한 항목에 따라 분류됩니다.
|
||||
|
||||
- **plain-capability** — 하나의 기능 유형(예: provider 전용 플러그인)
|
||||
- **hybrid-capability** — 여러 기능 유형(예: 텍스트 + 음성 + 이미지)
|
||||
- **hook-only** — 기능이나 표면 없이 hook만 존재
|
||||
- **non-capability** — 기능은 없지만 도구/명령/서비스가 있음
|
||||
|
||||
기능 모델에 대한 자세한 내용은 [Plugin shapes](/plugins/architecture#plugin-shapes)를 참조하세요.
|
||||
|
||||
`--json` 플래그는 스크립팅과
|
||||
감사에 적합한 기계 판독 가능한 보고서를 출력합니다.
|
||||
|
||||
`inspect --all`은 shape, capability 종류,
|
||||
호환성 공지, 번들 기능, hook 요약 열이 포함된 전체 플릿 테이블을 렌더링합니다.
|
||||
|
||||
`info`는 `inspect`의 별칭입니다.
|
||||
|
||||
### Doctor
|
||||
|
||||
```bash
|
||||
openclaw plugins doctor
|
||||
```
|
||||
|
||||
`doctor`는 플러그인 로드 오류, manifest/discovery diagnostics, 그리고
|
||||
호환성 공지를 보고합니다. 모든 것이 정상이면 `No plugin issues
|
||||
detected.`를 출력합니다.
|
||||
|
||||
### Marketplace
|
||||
|
||||
```bash
|
||||
openclaw plugins marketplace list <source>
|
||||
openclaw plugins marketplace list <source> --json
|
||||
```
|
||||
|
||||
Marketplace 목록은 로컬 marketplace 경로, `marketplace.json` 경로,
|
||||
`owner/repo` 같은 GitHub 축약형, GitHub repo URL, 또는 git URL을 받을 수 있습니다. `--json`은
|
||||
확인된 소스 레이블과 파싱된 marketplace manifest 및
|
||||
플러그인 항목을 출력합니다.
|
||||
59
docs/ko/cli/qr.md
Normal file
59
docs/ko/cli/qr.md
Normal file
@ -0,0 +1,59 @@
|
||||
---
|
||||
read_when:
|
||||
- 모바일 노드 앱을 gateway와 빠르게 페어링하려고 함
|
||||
- 원격/수동 공유를 위한 설정 코드 출력이 필요함
|
||||
summary: '`openclaw qr`용 CLI 참조(모바일 페어링 QR + 설정 코드 생성)'
|
||||
title: qr
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:43Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ee6469334ad09037318f938c7ac609b7d5e3385c0988562501bb02a1bfa411ff
|
||||
source_path: cli/qr.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw qr`
|
||||
|
||||
현재 Gateway 구성에서 모바일 페어링 QR과 설정 코드를 생성합니다.
|
||||
|
||||
## 사용법
|
||||
|
||||
```bash
|
||||
openclaw qr
|
||||
openclaw qr --setup-code-only
|
||||
openclaw qr --json
|
||||
openclaw qr --remote
|
||||
openclaw qr --url wss://gateway.example/ws
|
||||
```
|
||||
|
||||
## 옵션
|
||||
|
||||
- `--remote`: `gateway.remote.url`을 우선 사용합니다. 이 값이 설정되지 않은 경우에도 `gateway.tailscale.mode=serve|funnel`이 원격 공개 URL을 제공할 수 있습니다
|
||||
- `--url <url>`: 페이로드에 사용되는 gateway URL 재정의
|
||||
- `--public-url <url>`: 페이로드에 사용되는 공개 URL 재정의
|
||||
- `--token <token>`: bootstrap 흐름이 인증에 사용할 gateway 토큰 재정의
|
||||
- `--password <password>`: bootstrap 흐름이 인증에 사용할 gateway 비밀번호 재정의
|
||||
- `--setup-code-only`: 설정 코드만 출력
|
||||
- `--no-ascii`: ASCII QR 렌더링 건너뛰기
|
||||
- `--json`: JSON 출력(`setupCode`, `gatewayUrl`, `auth`, `urlSource`)
|
||||
|
||||
## 참고
|
||||
|
||||
- `--token`과 `--password`는 함께 사용할 수 없습니다.
|
||||
- 이제 설정 코드 자체에는 공유 gateway 토큰/비밀번호가 아니라 불투명한 단기 `bootstrapToken`이 포함됩니다.
|
||||
- 내장된 node/operator bootstrap 흐름에서 기본 노드 토큰은 여전히 `scopes: []`로 설정됩니다.
|
||||
- bootstrap 핸드오프가 operator 토큰도 발급하는 경우, 그것은 bootstrap allowlist인 `operator.approvals`, `operator.read`, `operator.talk.secrets`, `operator.write` 범위 내로 제한됩니다.
|
||||
- Bootstrap scope 검사는 역할 접두사 기반입니다. 해당 operator allowlist는 operator 요청에만 적용되며, operator가 아닌 역할은 여전히 자기 역할 접두사 아래의 scopes가 필요합니다.
|
||||
- Tailscale/공개 `ws://` gateway URL에서는 모바일 페어링이 fail closed 처리됩니다. 비공개 LAN `ws://`는 계속 지원되지만, Tailscale/공개 모바일 경로에는 Tailscale Serve/Funnel 또는 `wss://` gateway URL을 사용해야 합니다.
|
||||
- `--remote`를 사용할 때 OpenClaw는 `gateway.remote.url` 또는
|
||||
`gateway.tailscale.mode=serve|funnel` 중 하나를 요구합니다.
|
||||
- `--remote`를 사용할 때, 실질적으로 활성화된 원격 자격 증명이 SecretRef로 구성되어 있고 `--token` 또는 `--password`를 전달하지 않으면, 명령은 활성 gateway 스냅샷에서 해당 값을 확인합니다. gateway를 사용할 수 없으면 명령은 즉시 실패합니다.
|
||||
- `--remote` 없이 실행할 때는 CLI 인증 재정의를 전달하지 않은 경우 로컬 gateway 인증 SecretRef가 확인됩니다.
|
||||
- 토큰 인증이 우선될 수 있을 때 `gateway.auth.token`이 확인됩니다(명시적 `gateway.auth.mode="token"` 또는 비밀번호 소스가 우선하지 않는 추론 모드).
|
||||
- 비밀번호 인증이 우선될 수 있을 때 `gateway.auth.password`가 확인됩니다(명시적 `gateway.auth.mode="password"` 또는 auth/env에서 우선 토큰이 없는 추론 모드).
|
||||
- `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있고(SecretRef 포함) `gateway.auth.mode`가 설정되지 않은 경우, 명시적으로 모드를 설정할 때까지 설정 코드 확인은 실패합니다.
|
||||
- Gateway 버전 불일치 참고: 이 명령 경로에는 `secrets.resolve`를 지원하는 gateway가 필요합니다. 오래된 gateway는 unknown-method 오류를 반환합니다.
|
||||
- 스캔 후에는 다음 명령으로 기기 페어링을 승인하세요.
|
||||
- `openclaw devices list`
|
||||
- `openclaw devices approve <requestId>`
|
||||
42
docs/ko/cli/reset.md
Normal file
42
docs/ko/cli/reset.md
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
read_when:
|
||||
- CLI 설치는 유지한 채 로컬 상태를 지우고 싶을 때
|
||||
- 무엇이 제거될지 dry-run으로 확인하고 싶을 때
|
||||
summary: '`openclaw reset`용 CLI 참조(로컬 상태/구성 재설정)'
|
||||
title: reset
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:44Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ad464700f948bebe741ec309f25150714f0b280834084d4f531327418a42c79b
|
||||
source_path: cli/reset.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw reset`
|
||||
|
||||
로컬 구성/상태를 재설정합니다(CLI 설치는 유지됨).
|
||||
|
||||
옵션:
|
||||
|
||||
- `--scope <scope>`: `config`, `config+creds+sessions`, 또는 `full`
|
||||
- `--yes`: 확인 프롬프트 건너뛰기
|
||||
- `--non-interactive`: 프롬프트 비활성화, `--scope`와 `--yes` 필요
|
||||
- `--dry-run`: 파일을 제거하지 않고 수행할 작업 출력
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw backup create
|
||||
openclaw reset
|
||||
openclaw reset --dry-run
|
||||
openclaw reset --scope config --yes --non-interactive
|
||||
openclaw reset --scope config+creds+sessions --yes --non-interactive
|
||||
openclaw reset --scope full --yes --non-interactive
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 로컬 상태를 제거하기 전에 복원 가능한 스냅샷이 필요하다면 먼저 `openclaw backup create`를 실행하세요.
|
||||
- `--scope`를 생략하면, `openclaw reset`은 무엇을 제거할지 선택하는 대화형 프롬프트를 사용합니다.
|
||||
- `--non-interactive`는 `--scope`와 `--yes`가 모두 설정된 경우에만 유효합니다.
|
||||
202
docs/ko/cli/sandbox.md
Normal file
202
docs/ko/cli/sandbox.md
Normal file
@ -0,0 +1,202 @@
|
||||
---
|
||||
read_when: You are managing sandbox runtimes or debugging sandbox/tool-policy behavior.
|
||||
status: active
|
||||
summary: 격리된 에이전트 실행을 위한 sandbox 런타임을 관리하고 유효 sandbox 정책을 검사합니다
|
||||
title: Sandbox CLI
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:58Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: fa2783037da2901316108d35e04bb319d5d57963c2764b9146786b3c6474b48a
|
||||
source_path: cli/sandbox.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Sandbox CLI
|
||||
|
||||
격리된 에이전트 실행을 위한 sandbox 런타임을 관리합니다.
|
||||
|
||||
## 개요
|
||||
|
||||
OpenClaw는 보안을 위해 에이전트를 격리된 sandbox 런타임에서 실행할 수 있습니다. `sandbox` 명령은 업데이트나 구성 변경 후 해당 런타임을 검사하고 다시 만드는 데 도움을 줍니다.
|
||||
|
||||
현재 이는 일반적으로 다음을 의미합니다.
|
||||
|
||||
- Docker sandbox 컨테이너
|
||||
- `agents.defaults.sandbox.backend = "ssh"`일 때의 SSH sandbox 런타임
|
||||
- `agents.defaults.sandbox.backend = "openshell"`일 때의 OpenShell sandbox 런타임
|
||||
|
||||
`ssh` 및 OpenShell `remote`의 경우, 다시 만들기는 Docker보다 더 중요합니다.
|
||||
|
||||
- 원격 workspace는 초기 시드 이후 정본입니다
|
||||
- `openclaw sandbox recreate`는 선택한 범위의 해당 정본 원격 workspace를 삭제합니다
|
||||
- 다음 사용 시 현재 로컬 workspace에서 다시 시드합니다
|
||||
|
||||
## 명령
|
||||
|
||||
### `openclaw sandbox explain`
|
||||
|
||||
**유효한** sandbox 모드/범위/workspace 액세스, sandbox 도구 정책, 상승 권한 게이트를 검사합니다(fix-it config 키 경로 포함).
|
||||
|
||||
```bash
|
||||
openclaw sandbox explain
|
||||
openclaw sandbox explain --session agent:main:main
|
||||
openclaw sandbox explain --agent work
|
||||
openclaw sandbox explain --json
|
||||
```
|
||||
|
||||
### `openclaw sandbox list`
|
||||
|
||||
모든 sandbox 런타임을 상태 및 구성과 함께 나열합니다.
|
||||
|
||||
```bash
|
||||
openclaw sandbox list
|
||||
openclaw sandbox list --browser # 브라우저 컨테이너만 나열
|
||||
openclaw sandbox list --json # JSON 출력
|
||||
```
|
||||
|
||||
**출력에는 다음이 포함됩니다.**
|
||||
|
||||
- 런타임 이름 및 상태
|
||||
- 백엔드 (`docker`, `openshell` 등)
|
||||
- config 레이블 및 현재 config와 일치하는지 여부
|
||||
- 생성 후 경과 시간
|
||||
- 유휴 시간(마지막 사용 이후 경과 시간)
|
||||
- 연결된 세션/에이전트
|
||||
|
||||
### `openclaw sandbox recreate`
|
||||
|
||||
업데이트된 config로 다시 생성되도록 sandbox 런타임을 제거합니다.
|
||||
|
||||
```bash
|
||||
openclaw sandbox recreate --all # 모든 컨테이너 다시 만들기
|
||||
openclaw sandbox recreate --session main # 특정 세션
|
||||
openclaw sandbox recreate --agent mybot # 특정 에이전트
|
||||
openclaw sandbox recreate --browser # 브라우저 컨테이너만
|
||||
openclaw sandbox recreate --all --force # 확인 건너뛰기
|
||||
```
|
||||
|
||||
**옵션:**
|
||||
|
||||
- `--all`: 모든 sandbox 컨테이너 다시 만들기
|
||||
- `--session <key>`: 특정 세션의 컨테이너 다시 만들기
|
||||
- `--agent <id>`: 특정 에이전트의 컨테이너 다시 만들기
|
||||
- `--browser`: 브라우저 컨테이너만 다시 만들기
|
||||
- `--force`: 확인 프롬프트 건너뛰기
|
||||
|
||||
**중요:** 런타임은 에이전트가 다음에 사용될 때 자동으로 다시 생성됩니다.
|
||||
|
||||
## 사용 사례
|
||||
|
||||
### Docker 이미지 업데이트 후
|
||||
|
||||
```bash
|
||||
# 새 이미지 가져오기
|
||||
docker pull openclaw-sandbox:latest
|
||||
docker tag openclaw-sandbox:latest openclaw-sandbox:bookworm-slim
|
||||
|
||||
# 새 이미지를 사용하도록 config 업데이트
|
||||
# config 편집: agents.defaults.sandbox.docker.image (또는 agents.list[].sandbox.docker.image)
|
||||
|
||||
# 컨테이너 다시 만들기
|
||||
openclaw sandbox recreate --all
|
||||
```
|
||||
|
||||
### sandbox 구성 변경 후
|
||||
|
||||
```bash
|
||||
# config 편집: agents.defaults.sandbox.* (또는 agents.list[].sandbox.*)
|
||||
|
||||
# 새 config 적용을 위해 다시 만들기
|
||||
openclaw sandbox recreate --all
|
||||
```
|
||||
|
||||
### SSH 대상 또는 SSH 인증 자료 변경 후
|
||||
|
||||
```bash
|
||||
# config 편집:
|
||||
# - agents.defaults.sandbox.backend
|
||||
# - agents.defaults.sandbox.ssh.target
|
||||
# - agents.defaults.sandbox.ssh.workspaceRoot
|
||||
# - agents.defaults.sandbox.ssh.identityFile / certificateFile / knownHostsFile
|
||||
# - agents.defaults.sandbox.ssh.identityData / certificateData / knownHostsData
|
||||
|
||||
openclaw sandbox recreate --all
|
||||
```
|
||||
|
||||
핵심 `ssh` 백엔드의 경우, 다시 만들기는 SSH 대상의 범위별 원격 workspace 루트를 삭제합니다. 다음 실행 시 로컬 workspace에서 다시 시드합니다.
|
||||
|
||||
### OpenShell 소스, 정책 또는 모드 변경 후
|
||||
|
||||
```bash
|
||||
# config 편집:
|
||||
# - agents.defaults.sandbox.backend
|
||||
# - plugins.entries.openshell.config.from
|
||||
# - plugins.entries.openshell.config.mode
|
||||
# - plugins.entries.openshell.config.policy
|
||||
|
||||
openclaw sandbox recreate --all
|
||||
```
|
||||
|
||||
OpenShell `remote` 모드의 경우, 다시 만들기는 해당 범위의 정본 원격 workspace를 삭제합니다. 다음 실행 시 로컬 workspace에서 다시 시드합니다.
|
||||
|
||||
### setupCommand 변경 후
|
||||
|
||||
```bash
|
||||
openclaw sandbox recreate --all
|
||||
# 또는 에이전트 하나만:
|
||||
openclaw sandbox recreate --agent family
|
||||
```
|
||||
|
||||
### 특정 에이전트에만 적용
|
||||
|
||||
```bash
|
||||
# 한 에이전트의 컨테이너만 업데이트
|
||||
openclaw sandbox recreate --agent alfred
|
||||
```
|
||||
|
||||
## 왜 이것이 필요한가요?
|
||||
|
||||
**문제:** sandbox 구성을 업데이트하면 다음과 같은 일이 발생합니다.
|
||||
|
||||
- 기존 런타임은 이전 설정으로 계속 실행됩니다
|
||||
- 런타임은 24시간 비활성 상태가 되어야만 정리됩니다
|
||||
- 자주 사용되는 에이전트는 이전 런타임을 무기한 유지합니다
|
||||
|
||||
**해결책:** `openclaw sandbox recreate`를 사용해 이전 런타임을 강제로 제거하세요. 이후 필요할 때 현재 설정으로 자동 재생성됩니다.
|
||||
|
||||
팁: 백엔드별 수동 정리보다 `openclaw sandbox recreate`를 우선 사용하세요.
|
||||
이 명령은 Gateway의 런타임 레지스트리를 사용하므로 범위/세션 키가 바뀔 때 불일치를 방지합니다.
|
||||
|
||||
## 구성
|
||||
|
||||
sandbox 설정은 `~/.openclaw/openclaw.json`의 `agents.defaults.sandbox` 아래에 있습니다(에이전트별 재정의는 `agents.list[].sandbox`에 둡니다).
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"sandbox": {
|
||||
"mode": "all", // off, non-main, all
|
||||
"backend": "docker", // docker, ssh, openshell
|
||||
"scope": "agent", // session, agent, shared
|
||||
"docker": {
|
||||
"image": "openclaw-sandbox:bookworm-slim",
|
||||
"containerPrefix": "openclaw-sbx-",
|
||||
// ... more Docker options
|
||||
},
|
||||
"prune": {
|
||||
"idleHours": 24, // 24시간 유휴 후 자동 정리
|
||||
"maxAgeDays": 7, // 7일 후 자동 정리
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 함께 보기
|
||||
|
||||
- [Sandbox 문서](/gateway/sandboxing)
|
||||
- [에이전트 구성](/concepts/agent-workspace)
|
||||
- [Doctor 명령](/gateway/doctor) - sandbox 설정 확인
|
||||
204
docs/ko/cli/secrets.md
Normal file
204
docs/ko/cli/secrets.md
Normal file
@ -0,0 +1,204 @@
|
||||
---
|
||||
read_when:
|
||||
- 런타임에서 secret ref를 다시 해석하는 경우
|
||||
- 평문 잔여물과 해석되지 않은 ref를 감사하는 경우
|
||||
- SecretRef를 구성하고 단방향 스크럽 변경 사항을 적용하는 경우
|
||||
summary: '`openclaw secrets`용 CLI 참조(reload, audit, configure, apply)'
|
||||
title: secrets
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:11Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: f436ba089d752edb766c0a3ce746ee6bca1097b22c9b30e3d9715cb0bb50bf47
|
||||
source_path: cli/secrets.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw secrets`
|
||||
|
||||
`openclaw secrets`를 사용해 SecretRef를 관리하고 활성 런타임 스냅샷을 정상 상태로 유지하세요.
|
||||
|
||||
명령 역할:
|
||||
|
||||
- `reload`: ref를 다시 해석하고 전체 성공 시에만 런타임 스냅샷을 교체하는 gateway RPC(`secrets.reload`)입니다(config 쓰기 없음).
|
||||
- `audit`: 평문, 해석되지 않은 ref, 우선순위 드리프트를 대상으로 구성/auth/생성된 모델 저장소와 레거시 잔여물을 읽기 전용으로 검사합니다(`--allow-exec`가 설정되지 않으면 exec ref는 건너뜀).
|
||||
- `configure`: 공급자 설정, 대상 매핑, 사전 점검을 위한 대화형 플래너입니다(TTY 필요).
|
||||
- `apply`: 저장된 계획을 실행합니다(검증 전용은 `--dry-run`; dry-run은 기본적으로 exec 검사를 건너뛰고, 쓰기 모드는 `--allow-exec`가 설정되지 않으면 exec가 포함된 계획을 거부함). 이후 대상 평문 잔여물을 스크럽합니다.
|
||||
|
||||
권장 운영자 루프:
|
||||
|
||||
```bash
|
||||
openclaw secrets audit --check
|
||||
openclaw secrets configure
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
|
||||
openclaw secrets audit --check
|
||||
openclaw secrets reload
|
||||
```
|
||||
|
||||
계획에 `exec` SecretRef/공급자가 포함되어 있다면 dry-run과 실제 쓰기 apply 명령 모두에 `--allow-exec`를 전달하세요.
|
||||
|
||||
CI/게이트용 종료 코드 참고:
|
||||
|
||||
- `audit --check`는 항목이 발견되면 `1`을 반환합니다.
|
||||
- 해석되지 않은 ref는 `2`를 반환합니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- Secrets 가이드: [Secrets Management](/gateway/secrets)
|
||||
- 자격 증명 표면: [SecretRef Credential Surface](/reference/secretref-credential-surface)
|
||||
- 보안 가이드: [Security](/gateway/security)
|
||||
|
||||
## 런타임 스냅샷 다시 로드
|
||||
|
||||
secret ref를 다시 해석하고 런타임 스냅샷을 원자적으로 교체합니다.
|
||||
|
||||
```bash
|
||||
openclaw secrets reload
|
||||
openclaw secrets reload --json
|
||||
openclaw secrets reload --url ws://127.0.0.1:18789 --token <token>
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- gateway RPC 메서드 `secrets.reload`를 사용합니다.
|
||||
- 해석에 실패하면 gateway는 마지막으로 알려진 정상 스냅샷을 유지하고 오류를 반환합니다(부분 활성화 없음).
|
||||
- JSON 응답에는 `warningCount`가 포함됩니다.
|
||||
|
||||
옵션:
|
||||
|
||||
- `--url <url>`
|
||||
- `--token <token>`
|
||||
- `--timeout <ms>`
|
||||
- `--json`
|
||||
|
||||
## 감사
|
||||
|
||||
OpenClaw 상태에서 다음을 검사합니다:
|
||||
|
||||
- 평문 secret 저장소
|
||||
- 해석되지 않은 ref
|
||||
- 우선순위 드리프트(`auth-profiles.json` 자격 증명이 `openclaw.json` ref를 가림)
|
||||
- 생성된 `agents/*/agent/models.json` 잔여물(공급자 `apiKey` 값 및 민감한 공급자 헤더)
|
||||
- 레거시 잔여물(레거시 auth 저장소 항목, OAuth 알림)
|
||||
|
||||
헤더 잔여물 참고:
|
||||
|
||||
- 민감한 공급자 헤더 감지는 이름 휴리스틱 기반입니다(일반적인 auth/자격 증명 헤더 이름과 `authorization`, `x-api-key`, `token`, `secret`, `password`, `credential` 같은 조각).
|
||||
|
||||
```bash
|
||||
openclaw secrets audit
|
||||
openclaw secrets audit --check
|
||||
openclaw secrets audit --json
|
||||
openclaw secrets audit --allow-exec
|
||||
```
|
||||
|
||||
종료 동작:
|
||||
|
||||
- `--check`는 항목이 발견되면 0이 아닌 값으로 종료합니다.
|
||||
- 해석되지 않은 ref는 더 높은 우선순위의 0이 아닌 종료 코드를 사용합니다.
|
||||
|
||||
보고서 형태의 주요 항목:
|
||||
|
||||
- `status`: `clean | findings | unresolved`
|
||||
- `resolution`: `refsChecked`, `skippedExecRefs`, `resolvabilityComplete`
|
||||
- `summary`: `plaintextCount`, `unresolvedRefCount`, `shadowedRefCount`, `legacyResidueCount`
|
||||
- finding 코드:
|
||||
- `PLAINTEXT_FOUND`
|
||||
- `REF_UNRESOLVED`
|
||||
- `REF_SHADOWED`
|
||||
- `LEGACY_RESIDUE`
|
||||
|
||||
## 구성(대화형 도우미)
|
||||
|
||||
공급자 및 SecretRef 변경 사항을 대화형으로 빌드하고, 사전 점검을 실행한 뒤, 선택적으로 적용합니다:
|
||||
|
||||
```bash
|
||||
openclaw secrets configure
|
||||
openclaw secrets configure --plan-out /tmp/openclaw-secrets-plan.json
|
||||
openclaw secrets configure --apply --yes
|
||||
openclaw secrets configure --providers-only
|
||||
openclaw secrets configure --skip-provider-setup
|
||||
openclaw secrets configure --agent ops
|
||||
openclaw secrets configure --json
|
||||
```
|
||||
|
||||
흐름:
|
||||
|
||||
- 먼저 공급자 설정(`secrets.providers` 별칭에 대해 `add/edit/remove`)
|
||||
- 다음으로 자격 증명 매핑(필드 선택 후 `{source, provider, id}` ref 할당)
|
||||
- 마지막으로 사전 점검 및 선택적 적용
|
||||
|
||||
플래그:
|
||||
|
||||
- `--providers-only`: `secrets.providers`만 구성하고 자격 증명 매핑은 건너뜁니다.
|
||||
- `--skip-provider-setup`: 공급자 설정을 건너뛰고 자격 증명을 기존 공급자에 매핑합니다.
|
||||
- `--agent <id>`: `auth-profiles.json` 대상 검색 및 쓰기를 하나의 agent 저장소 범위로 제한합니다.
|
||||
- `--allow-exec`: 사전 점검/apply 중 exec SecretRef 검사를 허용합니다(공급자 명령을 실행할 수 있음).
|
||||
|
||||
참고:
|
||||
|
||||
- 대화형 TTY가 필요합니다.
|
||||
- `--providers-only`와 `--skip-provider-setup`은 함께 사용할 수 없습니다.
|
||||
- `configure`는 `openclaw.json`의 secret 보유 필드와 선택한 agent 범위의 `auth-profiles.json`을 대상으로 합니다.
|
||||
- `configure`는 picker 흐름에서 새 `auth-profiles.json` 매핑을 직접 생성하는 것을 지원합니다.
|
||||
- 정식 지원 표면: [SecretRef Credential Surface](/reference/secretref-credential-surface).
|
||||
- 적용 전에 사전 점검 해석을 수행합니다.
|
||||
- 사전 점검/apply에 exec ref가 포함되면 두 단계 모두에서 `--allow-exec`를 유지하세요.
|
||||
- 생성된 계획은 기본적으로 스크럽 옵션(`scrubEnv`, `scrubAuthProfilesForProviderTargets`, `scrubLegacyAuthJson` 모두 활성화됨)을 사용합니다.
|
||||
- 스크럽된 평문 값에 대한 apply 경로는 단방향입니다.
|
||||
- `--apply` 없이도 CLI는 사전 점검 후 `Apply this plan now?`를 계속 묻습니다.
|
||||
- `--apply`를 사용할 때(`--yes` 없음) CLI는 되돌릴 수 없는 추가 확인을 요청합니다.
|
||||
- `--json`은 계획 + 사전 점검 보고서를 출력하지만, 이 명령은 여전히 대화형 TTY가 필요합니다.
|
||||
|
||||
Exec 공급자 안전 참고:
|
||||
|
||||
- Homebrew 설치는 종종 `/opt/homebrew/bin/*` 아래의 심볼릭 링크 바이너리를 노출합니다.
|
||||
- 신뢰된 패키지 관리자 경로에 필요할 때만 `allowSymlinkCommand: true`를 설정하고, `trustedDirs`(예: `["/opt/homebrew"]`)와 함께 사용하세요.
|
||||
- Windows에서 공급자 경로에 대한 ACL 검증을 사용할 수 없으면 OpenClaw는 fail-closed로 동작합니다. 신뢰된 경로에 한해, 해당 공급자에 `allowInsecurePath: true`를 설정해 경로 보안 검사를 우회할 수 있습니다.
|
||||
|
||||
## 저장된 계획 적용
|
||||
|
||||
이전에 생성한 계획을 적용하거나 사전 점검합니다:
|
||||
|
||||
```bash
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --allow-exec
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run --allow-exec
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --json
|
||||
```
|
||||
|
||||
Exec 동작:
|
||||
|
||||
- `--dry-run`은 파일을 쓰지 않고 사전 점검을 검증합니다.
|
||||
- exec SecretRef 검사는 dry-run에서 기본적으로 건너뜁니다.
|
||||
- 쓰기 모드는 `--allow-exec`가 설정되지 않으면 exec SecretRef/공급자가 포함된 계획을 거부합니다.
|
||||
- 어느 모드에서든 exec 공급자 검사/실행을 허용하려면 `--allow-exec`를 사용하세요.
|
||||
|
||||
계획 계약 세부 사항(허용되는 대상 경로, 유효성 검사 규칙, 실패 의미 체계):
|
||||
|
||||
- [Secrets Apply Plan Contract](/gateway/secrets-plan-contract)
|
||||
|
||||
`apply`가 업데이트할 수 있는 항목:
|
||||
|
||||
- `openclaw.json`(SecretRef 대상 + 공급자 upsert/delete)
|
||||
- `auth-profiles.json`(공급자 대상 스크럽)
|
||||
- 레거시 `auth.json` 잔여물
|
||||
- 값이 마이그레이션된 `~/.openclaw/.env`의 알려진 secret 키
|
||||
|
||||
## 롤백 백업이 없는 이유
|
||||
|
||||
`secrets apply`는 이전 평문 값을 포함하는 롤백 백업을 의도적으로 작성하지 않습니다.
|
||||
|
||||
안전성은 엄격한 사전 점검 + 실패 시 최선 시도의 메모리 내 복원을 포함한 거의 원자적인 apply에서 나옵니다.
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw secrets audit --check
|
||||
openclaw secrets configure
|
||||
openclaw secrets audit --check
|
||||
```
|
||||
|
||||
`audit --check`가 여전히 평문 항목을 보고하면, 보고된 나머지 대상 경로를 업데이트한 뒤 감사를 다시 실행하세요.
|
||||
91
docs/ko/cli/security.md
Normal file
91
docs/ko/cli/security.md
Normal file
@ -0,0 +1,91 @@
|
||||
---
|
||||
read_when:
|
||||
- config/state에 대해 빠른 보안 감사를 실행하려고 함
|
||||
- 안전한 “fix” 제안(권한, 기본값 강화)을 적용하려고 함
|
||||
summary: '`openclaw security`용 CLI 참조(일반적인 보안 실수 감사 및 수정)'
|
||||
title: security
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:03Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: e5a3e4ab8e0dfb6c10763097cb4483be2431985f16de877523eb53e2122239ae
|
||||
source_path: cli/security.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw security`
|
||||
|
||||
보안 도구(audit + 선택적 수정).
|
||||
|
||||
관련 문서:
|
||||
|
||||
- 보안 가이드: [Security](/gateway/security)
|
||||
|
||||
## Audit
|
||||
|
||||
```bash
|
||||
openclaw security audit
|
||||
openclaw security audit --deep
|
||||
openclaw security audit --deep --password <password>
|
||||
openclaw security audit --deep --token <token>
|
||||
openclaw security audit --fix
|
||||
openclaw security audit --json
|
||||
```
|
||||
|
||||
이 audit는 여러 DM 발신자가 메인 세션을 공유할 때 경고를 표시하며, 공유 받은편지함을 위한 **보안 DM 모드**인 `session.dmScope="per-channel-peer"`(다중 account 채널에서는 `per-account-channel-peer`)를 권장합니다.
|
||||
이 설정은 협업형/공유 받은편지함 강화를 위한 것입니다. 상호 신뢰하지 않거나 적대적인 운영자들이 하나의 Gateway를 공유하는 구성은 권장되지 않으며, 별도의 gateways(또는 별도의 OS 사용자/호스트)로 신뢰 경계를 분리해야 합니다.
|
||||
또한 config가 공유 사용자 유입 가능성을 시사할 때(예: 열린 DM/group 정책, 구성된 그룹 대상, 와일드카드 발신자 규칙) `security.trust_model.multi_user_heuristic`를 출력하고, OpenClaw의 기본 신뢰 모델은 개인 비서 모델이라는 점을 상기시킵니다.
|
||||
의도적인 공유 사용자 설정의 경우, audit 가이드는 모든 세션을 샌드박스 처리하고, 파일 시스템 접근을 workspace 범위로 제한하며, 개인/비공개 identity 또는 자격 증명을 해당 런타임에서 분리해 둘 것을 권장합니다.
|
||||
또한 작은 모델(`<=300B`)이 샌드박싱 없이 사용되며 web/browser 도구가 활성화된 경우에도 경고합니다.
|
||||
webhook 유입에 대해서는 `hooks.token`이 Gateway 토큰을 재사용하는 경우, `hooks.token`이 짧은 경우, `hooks.path="/"`인 경우, `hooks.defaultSessionKey`가 설정되지 않은 경우, `hooks.allowedAgentIds`가 제한되지 않은 경우, 요청 `sessionKey` 재정의가 활성화된 경우, 그리고 `hooks.allowedSessionKeyPrefixes` 없이 재정의가 활성화된 경우를 경고합니다.
|
||||
또한 샌드박스 모드가 꺼져 있는데 sandbox Docker 설정이 구성된 경우, `gateway.nodes.denyCommands`가 효과 없는 패턴형/알 수 없는 항목을 사용하는 경우(정확한 노드 command-name 매칭만 지원하며 셸 텍스트 필터링은 아님), `gateway.nodes.allowCommands`가 위험한 노드 명령을 명시적으로 활성화하는 경우, 전역 `tools.profile="minimal"`이 에이전트 도구 프로필에 의해 재정의되는 경우, 열린 그룹이 샌드박스/workspace 보호 없이 런타임/파일 시스템 도구를 노출하는 경우, 설치된 extension plugin 도구가 느슨한 도구 정책 아래에서 접근 가능할 수 있는 경우도 경고합니다.
|
||||
또한 `gateway.allowRealIpFallback=true`(프록시가 잘못 구성된 경우 헤더 스푸핑 위험)와 `discovery.mdns.mode="full"`(mDNS TXT 레코드를 통한 메타데이터 노출)도 표시합니다.
|
||||
또한 sandbox browser가 `sandbox.browser.cdpSourceRange` 없이 Docker `bridge` 네트워크를 사용할 때도 경고합니다.
|
||||
또한 위험한 sandbox Docker 네트워크 모드(`host`, `container:*` 네임스페이스 조인 포함)도 표시합니다.
|
||||
또한 기존 sandbox browser Docker 컨테이너에 해시 라벨이 없거나 오래된 경우(예: 마이그레이션 이전 컨테이너에 `openclaw.browserConfigEpoch`가 없는 경우)도 경고하며 `openclaw sandbox recreate --browser --all`을 권장합니다.
|
||||
또한 npm 기반 plugin/hook 설치 기록이 pin되지 않았거나, 무결성 메타데이터가 없거나, 현재 설치된 패키지 버전과 드리프트가 있을 때도 경고합니다.
|
||||
또한 채널 allowlist가 안정적인 ID 대신 변경 가능한 이름/이메일/태그에 의존하는 경우(해당하는 Discord, Slack, Google Chat, Microsoft Teams, Mattermost, IRC scopes)도 경고합니다.
|
||||
또한 `gateway.auth.mode="none"`으로 인해 Gateway HTTP API가 공유 비밀 없이 접근 가능한 상태(`/tools/invoke`와 활성화된 모든 `/v1/*` 엔드포인트 포함)일 때도 경고합니다.
|
||||
`dangerous`/`dangerously` 접두사가 붙은 설정은 명시적인 긴급 우회 운영자 재정의이며, 그 자체만으로는 보안 취약점 보고 대상이 아닙니다.
|
||||
전체 위험 파라미터 목록은 [Security](/gateway/security)의 "Insecure or dangerous flags summary" 섹션을 참조하세요.
|
||||
|
||||
SecretRef 동작:
|
||||
|
||||
- `security audit`는 대상 경로에 대해 지원되는 SecretRefs를 읽기 전용 모드로 확인합니다.
|
||||
- 현재 명령 경로에서 SecretRef를 사용할 수 없으면 audit는 중단되지 않고 `secretDiagnostics`를 보고합니다.
|
||||
- `--token`과 `--password`는 해당 명령 호출의 deep-probe 인증만 재정의하며, config나 SecretRef 매핑은 다시 쓰지 않습니다.
|
||||
|
||||
## JSON 출력
|
||||
|
||||
CI/정책 검사에는 `--json`을 사용하세요.
|
||||
|
||||
```bash
|
||||
openclaw security audit --json | jq '.summary'
|
||||
openclaw security audit --deep --json | jq '.findings[] | select(.severity=="critical") | .checkId'
|
||||
```
|
||||
|
||||
`--fix`와 `--json`을 함께 사용하면 출력에는 수정 작업과 최종 보고서가 모두 포함됩니다.
|
||||
|
||||
```bash
|
||||
openclaw security audit --fix --json | jq '{fix: .fix.ok, summary: .report.summary}'
|
||||
```
|
||||
|
||||
## `--fix`가 변경하는 항목
|
||||
|
||||
`--fix`는 안전하고 결정적인 수정만 적용합니다.
|
||||
|
||||
- 일반적인 `groupPolicy="open"`을 `groupPolicy="allowlist"`로 전환합니다(지원되는 채널의 account 변형 포함)
|
||||
- WhatsApp group 정책이 `allowlist`로 전환될 때, 저장된 `allowFrom` 파일 목록이 존재하고 config에 아직 `allowFrom`이 정의되지 않은 경우 해당 목록으로 `groupAllowFrom`을 초기화합니다
|
||||
- `logging.redactSensitive`를 `"off"`에서 `"tools"`로 설정합니다
|
||||
- 상태/config 및 일반적인 민감 파일에 대한 권한을 강화합니다
|
||||
(`credentials/*.json`, `auth-profiles.json`, `sessions.json`, 세션
|
||||
`*.jsonl`)
|
||||
- 또한 `openclaw.json`에서 참조되는 config include 파일의 권한도 강화합니다
|
||||
- POSIX 호스트에서는 `chmod`, Windows에서는 `icacls` 재설정을 사용합니다
|
||||
|
||||
`--fix`가 **하지 않는 것**:
|
||||
|
||||
- 토큰/비밀번호/API 키 교체
|
||||
- 도구 비활성화(`gateway`, `cron`, `exec` 등)
|
||||
- gateway bind/auth/network 노출 선택 변경
|
||||
- plugins/Skills 제거 또는 재작성
|
||||
120
docs/ko/cli/sessions.md
Normal file
120
docs/ko/cli/sessions.md
Normal file
@ -0,0 +1,120 @@
|
||||
---
|
||||
read_when:
|
||||
- 저장된 세션을 나열하고 최근 활동을 확인하려고 할 때
|
||||
summary: '`openclaw sessions`용 CLI 참조(저장된 세션 + 사용량 나열)'
|
||||
title: sessions
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:57Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 47eb55d90bd0681676283310cfa50dcacc95dff7d9a39bf2bb188788c6e5e5ba
|
||||
source_path: cli/sessions.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw sessions`
|
||||
|
||||
저장된 대화 세션을 나열합니다.
|
||||
|
||||
```bash
|
||||
openclaw sessions
|
||||
openclaw sessions --agent work
|
||||
openclaw sessions --all-agents
|
||||
openclaw sessions --active 120
|
||||
openclaw sessions --verbose
|
||||
openclaw sessions --json
|
||||
```
|
||||
|
||||
범위 선택:
|
||||
|
||||
- 기본값: 구성된 기본 에이전트 저장소
|
||||
- `--verbose`: 자세한 로깅
|
||||
- `--agent <id>`: 하나의 구성된 에이전트 저장소
|
||||
- `--all-agents`: 모든 구성된 에이전트 저장소 집계
|
||||
- `--store <path>`: 명시적 저장소 경로(`--agent` 또는 `--all-agents`와 함께 사용할 수 없음)
|
||||
|
||||
`openclaw sessions --all-agents`는 구성된 에이전트 저장소를 읽습니다. Gateway 및 ACP
|
||||
세션 검색은 더 넓은 범위를 다룹니다. 기본 `agents/` 루트 또는 템플릿화된
|
||||
`session.store` 루트 아래에서 디스크에만 있는 저장소도 포함합니다. 이렇게
|
||||
발견된 저장소는 에이전트 루트 내부의 일반 `sessions.json` 파일로 해석되어야 하며,
|
||||
심볼릭 링크와 루트 외부 경로는 건너뜁니다.
|
||||
|
||||
JSON 예시:
|
||||
|
||||
`openclaw sessions --all-agents --json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"path": null,
|
||||
"stores": [
|
||||
{ "agentId": "main", "path": "/home/user/.openclaw/agents/main/sessions/sessions.json" },
|
||||
{ "agentId": "work", "path": "/home/user/.openclaw/agents/work/sessions/sessions.json" }
|
||||
],
|
||||
"allAgents": true,
|
||||
"count": 2,
|
||||
"activeMinutes": null,
|
||||
"sessions": [
|
||||
{ "agentId": "main", "key": "agent:main:main", "model": "gpt-5" },
|
||||
{ "agentId": "work", "key": "agent:work:main", "model": "claude-opus-4-6" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 정리 유지 관리
|
||||
|
||||
다음 쓰기 주기를 기다리지 않고 지금 유지 관리를 실행합니다:
|
||||
|
||||
```bash
|
||||
openclaw sessions cleanup --dry-run
|
||||
openclaw sessions cleanup --agent work --dry-run
|
||||
openclaw sessions cleanup --all-agents --dry-run
|
||||
openclaw sessions cleanup --enforce
|
||||
openclaw sessions cleanup --enforce --active-key "agent:main:telegram:direct:123"
|
||||
openclaw sessions cleanup --json
|
||||
```
|
||||
|
||||
`openclaw sessions cleanup`은 config의 `session.maintenance` 설정을 사용합니다.
|
||||
|
||||
- 범위 참고: `openclaw sessions cleanup`은 세션 저장소/transcript만 유지 관리합니다. `cron/runs/<jobId>.jsonl`의 cron 실행 로그는 정리하지 않습니다. 이러한 로그는 [Cron configuration](/automation/cron-jobs#configuration)에 있는 `cron.runLog.maxBytes`와 `cron.runLog.keepLines`로 관리되며, [Cron maintenance](/automation/cron-jobs#maintenance)에 설명되어 있습니다.
|
||||
|
||||
- `--dry-run`: 쓰지 않고 얼마나 많은 항목이 정리/상한 적용될지 미리 봅니다.
|
||||
- 텍스트 모드에서 dry-run은 세션별 작업 표(`Action`, `Key`, `Age`, `Model`, `Flags`)를 출력하므로 무엇이 유지되고 제거될지 확인할 수 있습니다.
|
||||
- `--enforce`: `session.maintenance.mode`가 `warn`이어도 유지 관리를 적용합니다.
|
||||
- `--fix-missing`: transcript 파일이 없는 항목을 제거합니다. 일반적으로 아직 연령/개수 기준으로 정리 대상이 아니더라도 제거합니다.
|
||||
- `--active-key <key>`: 특정 활성 키가 디스크 예산으로 인해 제거되지 않도록 보호합니다.
|
||||
- `--agent <id>`: 하나의 구성된 에이전트 저장소에 대해 정리 실행
|
||||
- `--all-agents`: 모든 구성된 에이전트 저장소에 대해 정리 실행
|
||||
- `--store <path>`: 특정 `sessions.json` 파일을 대상으로 실행
|
||||
- `--json`: JSON 요약 출력. `--all-agents`와 함께 사용하면 저장소별 요약 하나씩이 출력에 포함됩니다.
|
||||
|
||||
`openclaw sessions cleanup --all-agents --dry-run --json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"allAgents": true,
|
||||
"mode": "warn",
|
||||
"dryRun": true,
|
||||
"stores": [
|
||||
{
|
||||
"agentId": "main",
|
||||
"storePath": "/home/user/.openclaw/agents/main/sessions/sessions.json",
|
||||
"beforeCount": 120,
|
||||
"afterCount": 80,
|
||||
"pruned": 40,
|
||||
"capped": 0
|
||||
},
|
||||
{
|
||||
"agentId": "work",
|
||||
"storePath": "/home/user/.openclaw/agents/work/sessions/sessions.json",
|
||||
"beforeCount": 18,
|
||||
"afterCount": 18,
|
||||
"pruned": 0,
|
||||
"capped": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
관련 항목:
|
||||
|
||||
- 세션 구성: [Configuration reference](/gateway/configuration-reference#session)
|
||||
52
docs/ko/cli/setup.md
Normal file
52
docs/ko/cli/setup.md
Normal file
@ -0,0 +1,52 @@
|
||||
---
|
||||
read_when:
|
||||
- 전체 CLI 온보딩 없이 첫 실행 설정을 진행할 때
|
||||
- 기본 워크스페이스 경로를 설정하려고 할 때
|
||||
summary: '`openclaw setup`용 CLI 참조(config + 워크스페이스 초기화)'
|
||||
title: setup
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:38:58Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: f538aac341c749043ad959e35f2ed99c844ab8c3500ff59aa159d940bd301792
|
||||
source_path: cli/setup.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw setup`
|
||||
|
||||
`~/.openclaw/openclaw.json`과 에이전트 워크스페이스를 초기화합니다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- 시작하기: [시작하기](/ko/start/getting-started)
|
||||
- CLI 온보딩: [온보딩(CLI)](/ko/start/wizard)
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw setup
|
||||
openclaw setup --workspace ~/.openclaw/workspace
|
||||
openclaw setup --wizard
|
||||
openclaw setup --non-interactive --mode remote --remote-url wss://gateway-host:18789 --remote-token <token>
|
||||
```
|
||||
|
||||
## 옵션
|
||||
|
||||
- `--workspace <dir>`: 에이전트 워크스페이스 디렉터리(`agents.defaults.workspace`로 저장)
|
||||
- `--wizard`: 온보딩 실행
|
||||
- `--non-interactive`: 프롬프트 없이 온보딩 실행
|
||||
- `--mode <local|remote>`: 온보딩 모드
|
||||
- `--remote-url <url>`: 원격 게이트웨이 WebSocket URL
|
||||
- `--remote-token <token>`: 원격 게이트웨이 토큰
|
||||
|
||||
setup을 통해 온보딩 실행:
|
||||
|
||||
```bash
|
||||
openclaw setup --wizard
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 일반 `openclaw setup`은 전체 온보딩 흐름 없이 config + 워크스페이스를 초기화합니다.
|
||||
- 온보딩 플래그가 하나라도 있으면(`--wizard`, `--non-interactive`, `--mode`, `--remote-url`, `--remote-token`) 온보딩이 자동 실행됩니다.
|
||||
65
docs/ko/cli/skills.md
Normal file
65
docs/ko/cli/skills.md
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
read_when:
|
||||
- 어떤 Skills를 사용할 수 있고 실행 준비가 되었는지 확인하려고 할 때
|
||||
- ClawHub에서 Skills를 검색, 설치 또는 업데이트하려고 할 때
|
||||
- Skills에 필요한 바이너리/env/config 누락을 디버깅하려고 할 때
|
||||
summary: '`openclaw skills`용 CLI 참조(search/install/update/list/info/check)'
|
||||
title: Skills
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:05Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 11af59b1b6bff19cc043acd8d67bdd4303201d3f75f23c948b83bf14882c7bb1
|
||||
source_path: cli/skills.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw skills`
|
||||
|
||||
로컬 Skills를 검사하고 ClawHub에서 Skills를 설치/업데이트합니다.
|
||||
|
||||
관련 항목:
|
||||
|
||||
- Skills 시스템: [Skills](/tools/skills)
|
||||
- Skills 구성: [Skills config](/tools/skills-config)
|
||||
- ClawHub 설치: [ClawHub](/tools/clawhub)
|
||||
|
||||
## 명령
|
||||
|
||||
```bash
|
||||
openclaw skills search "calendar"
|
||||
openclaw skills search --limit 20 --json
|
||||
openclaw skills install <slug>
|
||||
openclaw skills install <slug> --version <version>
|
||||
openclaw skills install <slug> --force
|
||||
openclaw skills update <slug>
|
||||
openclaw skills update --all
|
||||
openclaw skills list
|
||||
openclaw skills list --eligible
|
||||
openclaw skills list --json
|
||||
openclaw skills list --verbose
|
||||
openclaw skills info <name>
|
||||
openclaw skills info <name> --json
|
||||
openclaw skills check
|
||||
openclaw skills check --json
|
||||
```
|
||||
|
||||
`search`/`install`/`update`는 ClawHub를 직접 사용하며 활성
|
||||
워크스페이스의 `skills/` 디렉터리에 설치됩니다. `list`/`info`/`check`는 여전히 현재
|
||||
워크스페이스와 구성에서 볼 수 있는 로컬 Skills를 검사합니다.
|
||||
|
||||
이 CLI `install` 명령은 ClawHub에서 Skill 폴더를 다운로드합니다. 온보딩 또는 Skills 설정에서
|
||||
트리거되는 Gateway 기반 Skill 의존성 설치는 대신 별도의
|
||||
`skills.install` 요청 경로를 사용합니다.
|
||||
|
||||
참고:
|
||||
|
||||
- `search [query...]`는 선택적 쿼리를 받습니다. 이를 생략하면 기본
|
||||
ClawHub 검색 피드를 탐색합니다.
|
||||
- `search --limit <n>`은 반환되는 결과 수를 제한합니다.
|
||||
- `install --force`는 동일한
|
||||
slug에 대해 기존 워크스페이스 Skill 폴더를 덮어씁니다.
|
||||
- `update --all`은 활성 워크스페이스에서 추적되는 ClawHub 설치만 업데이트합니다.
|
||||
- 하위 명령이 제공되지 않으면 `list`가 기본 동작입니다.
|
||||
- `list`, `info`, `check`는 렌더링된 출력을 stdout에 씁니다.
|
||||
`--json`과 함께 사용하면 기계가 읽을 수 있는 페이로드가 파이프와 스크립트를 위해 stdout에 유지됩니다.
|
||||
42
docs/ko/cli/status.md
Normal file
42
docs/ko/cli/status.md
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
read_when:
|
||||
- 채널 상태와 최근 세션 수신자에 대한 빠른 진단이 필요할 때
|
||||
- 디버깅용으로 붙여넣기 쉬운 “all” 상태 출력이 필요할 때
|
||||
summary: '`openclaw status`용 CLI 참조(진단, 프로브, 사용량 스냅샷)'
|
||||
title: status
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:08Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: fbe9d94fbe9938cd946ee6f293b5bd3b464b75e1ade2eacdd851788c3bffe94e
|
||||
source_path: cli/status.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw status`
|
||||
|
||||
채널 + 세션 진단.
|
||||
|
||||
```bash
|
||||
openclaw status
|
||||
openclaw status --all
|
||||
openclaw status --deep
|
||||
openclaw status --usage
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- `--deep`는 실시간 프로브를 실행합니다(WhatsApp Web + Telegram + Discord + Slack + Signal).
|
||||
- `--usage`는 정규화된 provider 사용량 기간을 `X% 남음` 형식으로 출력합니다.
|
||||
- MiniMax의 원시 `usage_percent` / `usagePercent` 필드는 남은 할당량이므로, OpenClaw는 표시 전에 이를 반전합니다. 개수 기반 필드가 있으면 그것이 우선합니다. `model_remains` 응답은 채팅 모델 항목을 우선 사용하고, 필요 시 타임스탬프에서 기간 레이블을 도출하며, 플랜 레이블에 모델 이름을 포함합니다.
|
||||
- 현재 세션 스냅샷이 희소한 경우, `/status`는 가장 최근 transcript 사용량 로그에서 토큰 및 캐시 카운터를 보완할 수 있습니다. 기존의 0이 아닌 실시간 값은 transcript 대체값보다 계속 우선합니다.
|
||||
- transcript 대체값은 실시간 세션 항목에 활성 런타임 모델 레이블이 없을 때 이를 복구할 수도 있습니다. 해당 transcript 모델이 선택된 모델과 다르면, status는 선택된 모델 대신 복구된 런타임 모델을 기준으로 컨텍스트 윈도우를 해석합니다.
|
||||
- 프롬프트 크기 계산에서 session 메타데이터가 없거나 더 작으면 transcript 대체값은 더 큰 프롬프트 지향 합계를 우선 사용하므로, custom provider 세션이 `0` 토큰 표시로 축소되지 않습니다.
|
||||
- 여러 에이전트가 구성된 경우 출력에는 에이전트별 세션 저장소가 포함됩니다.
|
||||
- 개요에는 사용 가능한 경우 게이트웨이 + 노드 호스트 서비스 설치/런타임 상태가 포함됩니다.
|
||||
- 개요에는 업데이트 채널 + git SHA(소스 체크아웃의 경우)가 포함됩니다.
|
||||
- 업데이트 정보는 개요에 표시되며, 업데이트가 가능하면 status는 `openclaw update`를 실행하라는 힌트를 출력합니다([업데이트](/install/updating) 참조).
|
||||
- 읽기 전용 status 표면(`status`, `status --json`, `status --all`)은 가능한 경우 대상 config 경로에 대해 지원되는 SecretRef를 해석합니다.
|
||||
- 지원되는 채널 SecretRef가 구성되어 있지만 현재 명령 경로에서 사용할 수 없는 경우, status는 충돌하지 않고 읽기 전용 상태를 유지하며 저하된 출력을 보고합니다. 사람이 읽는 출력에는 “현재 명령 경로에서 구성된 토큰을 사용할 수 없음” 같은 경고가 표시되고, JSON 출력에는 `secretDiagnostics`가 포함됩니다.
|
||||
- 명령 로컬 SecretRef 해석이 성공하면 status는 해석된 스냅샷을 우선 사용하고 최종 출력에서 일시적인 “secret unavailable” 채널 마커를 제거합니다.
|
||||
- `status --all`에는 Secrets 개요 행과, 보고서 생성을 중단하지 않고 secret 진단을 요약하는 진단 섹션(가독성을 위해 잘림)이 포함됩니다.
|
||||
74
docs/ko/cli/system.md
Normal file
74
docs/ko/cli/system.md
Normal file
@ -0,0 +1,74 @@
|
||||
---
|
||||
read_when:
|
||||
- cron 작업을 만들지 않고 시스템 이벤트를 대기열에 넣으려는 경우
|
||||
- heartbeat를 활성화하거나 비활성화해야 하는 경우
|
||||
- 시스템 presence 항목을 검사하려는 경우
|
||||
summary: '`openclaw system`용 CLI 참조(시스템 이벤트, heartbeat, presence)'
|
||||
title: system
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:07Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: a7d19afde9d9cde8a79b0bb8cec6e5673466f4cb9b575fb40111fc32f4eee5d7
|
||||
source_path: cli/system.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw system`
|
||||
|
||||
Gateway를 위한 시스템 수준 도우미입니다. 시스템 이벤트를 대기열에 넣고, heartbeat를 제어하며, presence를 확인할 수 있습니다.
|
||||
|
||||
모든 `system` 하위 명령은 Gateway RPC를 사용하며 공통 클라이언트 플래그를 지원합니다.
|
||||
|
||||
- `--url <url>`
|
||||
- `--token <token>`
|
||||
- `--timeout <ms>`
|
||||
- `--expect-final`
|
||||
|
||||
## 일반 명령
|
||||
|
||||
```bash
|
||||
openclaw system event --text "긴급한 후속 조치가 있는지 확인해 줘" --mode now
|
||||
openclaw system event --text "긴급한 후속 조치가 있는지 확인해 줘" --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"
|
||||
openclaw system heartbeat enable
|
||||
openclaw system heartbeat last
|
||||
openclaw system presence
|
||||
```
|
||||
|
||||
## `system event`
|
||||
|
||||
**메인** 세션에 시스템 이벤트를 대기열에 넣습니다. 다음 heartbeat가 이를 프롬프트의 `System:` 줄로 주입합니다. 즉시 heartbeat를 트리거하려면 `--mode now`를 사용하세요. `next-heartbeat`는 다음 예약 틱까지 기다립니다.
|
||||
|
||||
플래그:
|
||||
|
||||
- `--text <text>`: 필수 시스템 이벤트 텍스트
|
||||
- `--mode <mode>`: `now` 또는 `next-heartbeat`(기본값)
|
||||
- `--json`: 기계 판독 가능한 출력
|
||||
- `--url`, `--token`, `--timeout`, `--expect-final`: 공통 Gateway RPC 플래그
|
||||
|
||||
## `system heartbeat last|enable|disable`
|
||||
|
||||
heartbeat 제어:
|
||||
|
||||
- `last`: 마지막 heartbeat 이벤트 표시
|
||||
- `enable`: heartbeat를 다시 켭니다(비활성화된 경우 사용)
|
||||
- `disable`: heartbeat 일시 중지
|
||||
|
||||
플래그:
|
||||
|
||||
- `--json`: 기계 판독 가능한 출력
|
||||
- `--url`, `--token`, `--timeout`, `--expect-final`: 공통 Gateway RPC 플래그
|
||||
|
||||
## `system presence`
|
||||
|
||||
Gateway가 알고 있는 현재 시스템 presence 항목(노드, 인스턴스 및 유사한 상태 줄)을 나열합니다.
|
||||
|
||||
플래그:
|
||||
|
||||
- `--json`: 기계 판독 가능한 출력
|
||||
- `--url`, `--token`, `--timeout`, `--expect-final`: 공통 Gateway RPC 플래그
|
||||
|
||||
## 참고
|
||||
|
||||
- 현재 config(로컬 또는 원격)를 통해 접근 가능한 실행 중인 Gateway가 필요합니다.
|
||||
- 시스템 이벤트는 일시적이며 재시작 후에는 유지되지 않습니다.
|
||||
37
docs/ko/cli/tui.md
Normal file
37
docs/ko/cli/tui.md
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
read_when:
|
||||
- Gateway용 터미널 UI가 필요할 때(원격 친화적)
|
||||
- 스크립트에서 url/token/session을 전달하고 싶을 때
|
||||
summary: Gateway에 연결된 `openclaw tui`용 CLI 참조(터미널 UI)
|
||||
title: tui
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:04Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 60e35062c0551f85ce0da604a915b3e1ca2514d00d840afe3b94c529304c2c1a
|
||||
source_path: cli/tui.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw tui`
|
||||
|
||||
Gateway에 연결된 터미널 UI를 엽니다.
|
||||
|
||||
관련 항목:
|
||||
|
||||
- TUI 가이드: [TUI](/web/tui)
|
||||
|
||||
참고:
|
||||
|
||||
- `tui`는 가능할 때 token/password 인증을 위해 구성된 gateway auth SecretRef를 확인합니다(`env`/`file`/`exec` 제공자).
|
||||
- 구성된 에이전트 워크스페이스 디렉터리 내부에서 실행되면, TUI는 세션 키 기본값으로 해당 에이전트를 자동 선택합니다(`--session`이 명시적으로 `agent:<id>:...`인 경우 제외).
|
||||
|
||||
## 예시
|
||||
|
||||
```bash
|
||||
openclaw tui
|
||||
openclaw tui --url ws://127.0.0.1:18789 --token <token>
|
||||
openclaw tui --session main --deliver
|
||||
# 에이전트 워크스페이스 내부에서 실행하면 해당 에이전트를 자동으로 추론
|
||||
openclaw tui --session bugfix
|
||||
```
|
||||
46
docs/ko/cli/uninstall.md
Normal file
46
docs/ko/cli/uninstall.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
read_when:
|
||||
- gateway 서비스 및/또는 로컬 상태를 제거하려고 함
|
||||
- 먼저 dry-run을 하려고 함
|
||||
summary: '`openclaw uninstall`용 CLI 참조(gateway 서비스 + 로컬 데이터 제거)'
|
||||
title: uninstall
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:08Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 2123a4f9c7a070ef7e13c60dafc189053ef61ce189fa4f29449dd50987c1894c
|
||||
source_path: cli/uninstall.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw uninstall`
|
||||
|
||||
gateway 서비스 + 로컬 데이터를 제거합니다(CLI는 유지됨).
|
||||
|
||||
옵션:
|
||||
|
||||
- `--service`: gateway 서비스 제거
|
||||
- `--state`: 상태 및 config 제거
|
||||
- `--workspace`: workspace 디렉터리 제거
|
||||
- `--app`: macOS 앱 제거
|
||||
- `--all`: 서비스, 상태, workspace, 앱 제거
|
||||
- `--yes`: 확인 프롬프트 건너뛰기
|
||||
- `--non-interactive`: 프롬프트 비활성화, `--yes` 필요
|
||||
- `--dry-run`: 파일을 제거하지 않고 수행 작업 출력
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw backup create
|
||||
openclaw uninstall
|
||||
openclaw uninstall --service --yes --non-interactive
|
||||
openclaw uninstall --state --workspace --yes --non-interactive
|
||||
openclaw uninstall --all --yes
|
||||
openclaw uninstall --dry-run
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- 상태 또는 workspaces를 제거하기 전에 복원 가능한 스냅샷을 원한다면 먼저 `openclaw backup create`를 실행하세요.
|
||||
- `--all`은 서비스, 상태, workspace, 앱을 함께 제거하는 축약형입니다.
|
||||
- `--non-interactive`에는 `--yes`가 필요합니다.
|
||||
118
docs/ko/cli/update.md
Normal file
118
docs/ko/cli/update.md
Normal file
@ -0,0 +1,118 @@
|
||||
---
|
||||
read_when:
|
||||
- 소스 체크아웃을 안전하게 업데이트하고 싶을 때
|
||||
- '`--update` 단축 동작을 이해해야 할 때'
|
||||
summary: '`openclaw update`용 CLI 참조(비교적 안전한 소스 업데이트 + gateway 자동 재시작)'
|
||||
title: update
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:20Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 12c8098654b644c3666981d379f6c018e84fde56a5420f295d78052f9001bdad
|
||||
source_path: cli/update.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw update`
|
||||
|
||||
OpenClaw를 안전하게 업데이트하고 stable/beta/dev 채널 간에 전환합니다.
|
||||
|
||||
**npm/pnpm/bun**으로 설치한 경우(전역 설치, git 메타데이터 없음),
|
||||
업데이트는 [Updating](/install/updating)의 패키지 관리자 흐름을 통해 수행됩니다.
|
||||
|
||||
## 사용법
|
||||
|
||||
```bash
|
||||
openclaw update
|
||||
openclaw update status
|
||||
openclaw update wizard
|
||||
openclaw update --channel beta
|
||||
openclaw update --channel dev
|
||||
openclaw update --tag beta
|
||||
openclaw update --tag main
|
||||
openclaw update --dry-run
|
||||
openclaw update --no-restart
|
||||
openclaw update --yes
|
||||
openclaw update --json
|
||||
openclaw --update
|
||||
```
|
||||
|
||||
## 옵션
|
||||
|
||||
- `--no-restart`: 업데이트가 성공한 후 Gateway 서비스를 재시작하지 않습니다.
|
||||
- `--channel <stable|beta|dev>`: 업데이트 채널 설정(git + npm, config에 유지됨).
|
||||
- `--tag <dist-tag|version|spec>`: 이번 업데이트에만 패키지 대상을 재정의합니다. 패키지 설치의 경우 `main`은 `github:openclaw/openclaw#main`에 매핑됩니다.
|
||||
- `--dry-run`: config 쓰기, 설치, plugin 동기화, 재시작 없이 계획된 업데이트 작업(채널/태그/대상/재시작 흐름)을 미리 봅니다.
|
||||
- `--json`: 기계가 읽을 수 있는 `UpdateRunResult` JSON을 출력합니다.
|
||||
- `--timeout <seconds>`: 단계별 시간 초과(기본값 1200초).
|
||||
- `--yes`: 확인 프롬프트를 건너뜁니다(예: 다운그레이드 확인)
|
||||
|
||||
참고: 이전 버전은 구성을 손상시킬 수 있으므로 다운그레이드에는 확인이 필요합니다.
|
||||
|
||||
## `update status`
|
||||
|
||||
활성 업데이트 채널 + git 태그/브랜치/SHA(소스 체크아웃의 경우)와 업데이트 가능 여부를 표시합니다.
|
||||
|
||||
```bash
|
||||
openclaw update status
|
||||
openclaw update status --json
|
||||
openclaw update status --timeout 10
|
||||
```
|
||||
|
||||
옵션:
|
||||
|
||||
- `--json`: 기계가 읽을 수 있는 상태 JSON을 출력합니다.
|
||||
- `--timeout <seconds>`: 확인 시간 초과(기본값 3초).
|
||||
|
||||
## `update wizard`
|
||||
|
||||
업데이트 채널을 선택하고 업데이트 후 Gateway를 재시작할지 확인하는
|
||||
대화형 흐름입니다(기본값은 재시작). git 체크아웃 없이 `dev`를 선택하면
|
||||
체크아웃을 생성할지 제안합니다.
|
||||
|
||||
옵션:
|
||||
|
||||
- `--timeout <seconds>`: 각 업데이트 단계의 시간 초과(기본값 `1200`)
|
||||
|
||||
## 수행 작업
|
||||
|
||||
채널을 명시적으로 전환할 때(`--channel ...`), OpenClaw는
|
||||
설치 방식도 함께 맞춥니다:
|
||||
|
||||
- `dev` → git 체크아웃을 보장합니다(기본값: `~/openclaw`, `OPENCLAW_GIT_DIR`로 재정의 가능),
|
||||
이를 업데이트하고 해당 체크아웃에서 전역 CLI를 설치합니다.
|
||||
- `stable` → `latest`를 사용해 npm에서 설치합니다.
|
||||
- `beta` → npm dist-tag `beta`를 우선 사용하지만, beta가 없거나 현재 stable 릴리스보다 오래된 경우 `latest`로 대체합니다.
|
||||
|
||||
Gateway 코어 자동 업데이터(config에서 활성화된 경우)는 동일한 업데이트 경로를 재사용합니다.
|
||||
|
||||
## Git 체크아웃 흐름
|
||||
|
||||
채널:
|
||||
|
||||
- `stable`: 최신 비-beta 태그를 체크아웃한 다음 build + doctor를 실행합니다.
|
||||
- `beta`: 최신 `-beta` 태그를 우선 사용하지만, beta가 없거나 더 오래된 경우 최신 stable 태그로 대체합니다.
|
||||
- `dev`: `main`을 체크아웃한 다음 fetch + rebase를 수행합니다.
|
||||
|
||||
상위 수준 흐름:
|
||||
|
||||
1. 깨끗한 worktree가 필요합니다(커밋되지 않은 변경 사항 없음).
|
||||
2. 선택한 채널(태그 또는 브랜치)로 전환합니다.
|
||||
3. 업스트림을 fetch합니다(dev 전용).
|
||||
4. dev 전용: 임시 worktree에서 사전 점검 lint + TypeScript build를 실행합니다. 최신 팁이 실패하면 최대 10개 커밋까지 되돌아가며 가장 최신의 정상 빌드를 찾습니다.
|
||||
5. 선택한 커밋으로 rebase합니다(dev 전용).
|
||||
6. 의존성을 설치합니다(pnpm 우선, npm 대체, bun은 보조 호환성 대체 수단으로 유지).
|
||||
7. build 및 Control UI build를 실행합니다.
|
||||
8. 최종 “안전 업데이트” 확인으로 `openclaw doctor`를 실행합니다.
|
||||
9. 활성 채널에 맞게 plugin을 동기화하고(dev는 번들 extension 사용, stable/beta는 npm 사용) npm으로 설치된 plugin을 업데이트합니다.
|
||||
|
||||
## `--update` 단축
|
||||
|
||||
`openclaw --update`는 `openclaw update`로 다시 작성됩니다(셸 및 런처 스크립트에 유용).
|
||||
|
||||
## 함께 보기
|
||||
|
||||
- `openclaw doctor` (git 체크아웃에서 먼저 update 실행을 제안함)
|
||||
- [개발 채널](/install/development-channels)
|
||||
- [업데이트](/install/updating)
|
||||
- [CLI 참조](/cli)
|
||||
41
docs/ko/cli/voicecall.md
Normal file
41
docs/ko/cli/voicecall.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
read_when:
|
||||
- voice-call plugin을 사용하며 CLI 진입점을 알고 싶을 때
|
||||
- '`voicecall call|continue|status|tail|expose`의 빠른 예시가 필요할 때'
|
||||
summary: '`openclaw voicecall`용 CLI 참조(voice-call plugin 명령 표면)'
|
||||
title: voicecall
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:10Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 2c99e7a3d256e1c74a0f07faba9675cc5a88b1eb2fc6e22993caf3874d4f340a
|
||||
source_path: cli/voicecall.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw voicecall`
|
||||
|
||||
`voicecall`은 plugin이 제공하는 명령입니다. voice-call plugin이 설치되고 활성화된 경우에만 표시됩니다.
|
||||
|
||||
기본 문서:
|
||||
|
||||
- voice-call plugin: [Voice Call](/plugins/voice-call)
|
||||
|
||||
## 일반적인 명령
|
||||
|
||||
```bash
|
||||
openclaw voicecall status --call-id <id>
|
||||
openclaw voicecall call --to "+15555550123" --message "Hello" --mode notify
|
||||
openclaw voicecall continue --call-id <id> --message "Any questions?"
|
||||
openclaw voicecall end --call-id <id>
|
||||
```
|
||||
|
||||
## 웹훅 노출(Tailscale)
|
||||
|
||||
```bash
|
||||
openclaw voicecall expose --mode serve
|
||||
openclaw voicecall expose --mode funnel
|
||||
openclaw voicecall expose --mode off
|
||||
```
|
||||
|
||||
보안 참고: 웹훅 엔드포인트는 신뢰하는 네트워크에만 노출하세요. 가능하면 Funnel보다 Tailscale Serve를 우선하세요.
|
||||
98
docs/ko/cli/webhooks.md
Normal file
98
docs/ko/cli/webhooks.md
Normal file
@ -0,0 +1,98 @@
|
||||
---
|
||||
read_when:
|
||||
- Gmail Pub/Sub 이벤트를 OpenClaw에 연결하려는 경우
|
||||
- webhook 도우미 명령을 사용하려는 경우
|
||||
summary: '`openclaw webhooks`용 CLI 참조(webhook 도우미 + Gmail Pub/Sub)'
|
||||
title: webhooks
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:15Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 2b22ce879c3a94557be57919b4d2b3e92ff4d41fbae7bc88d2ab07cd4bbeac83
|
||||
source_path: cli/webhooks.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw webhooks`
|
||||
|
||||
webhook 도우미 및 통합(Gmail Pub/Sub, webhook 도우미).
|
||||
|
||||
관련 문서:
|
||||
|
||||
- Webhooks: [Webhooks](/automation/cron-jobs#webhooks)
|
||||
- Gmail Pub/Sub: [Gmail Pub/Sub](/automation/cron-jobs#gmail-pubsub-integration)
|
||||
|
||||
## Gmail
|
||||
|
||||
```bash
|
||||
openclaw webhooks gmail setup --account you@example.com
|
||||
openclaw webhooks gmail run
|
||||
```
|
||||
|
||||
### `webhooks gmail setup`
|
||||
|
||||
Gmail watch, Pub/Sub, OpenClaw webhook 전달을 구성합니다.
|
||||
|
||||
필수:
|
||||
|
||||
- `--account <email>`
|
||||
|
||||
옵션:
|
||||
|
||||
- `--project <id>`
|
||||
- `--topic <name>`
|
||||
- `--subscription <name>`
|
||||
- `--label <label>`
|
||||
- `--hook-url <url>`
|
||||
- `--hook-token <token>`
|
||||
- `--push-token <token>`
|
||||
- `--bind <host>`
|
||||
- `--port <port>`
|
||||
- `--path <path>`
|
||||
- `--include-body`
|
||||
- `--max-bytes <n>`
|
||||
- `--renew-minutes <n>`
|
||||
- `--tailscale <funnel|serve|off>`
|
||||
- `--tailscale-path <path>`
|
||||
- `--tailscale-target <target>`
|
||||
- `--push-endpoint <url>`
|
||||
- `--json`
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw webhooks gmail setup --account you@example.com
|
||||
openclaw webhooks gmail setup --account you@example.com --project my-gcp-project --json
|
||||
openclaw webhooks gmail setup --account you@example.com --hook-url https://gateway.example.com/hooks/gmail
|
||||
```
|
||||
|
||||
### `webhooks gmail run`
|
||||
|
||||
`gog watch serve`와 watch 자동 갱신 루프를 실행합니다.
|
||||
|
||||
옵션:
|
||||
|
||||
- `--account <email>`
|
||||
- `--topic <topic>`
|
||||
- `--subscription <name>`
|
||||
- `--label <label>`
|
||||
- `--hook-url <url>`
|
||||
- `--hook-token <token>`
|
||||
- `--push-token <token>`
|
||||
- `--bind <host>`
|
||||
- `--port <port>`
|
||||
- `--path <path>`
|
||||
- `--include-body`
|
||||
- `--max-bytes <n>`
|
||||
- `--renew-minutes <n>`
|
||||
- `--tailscale <funnel|serve|off>`
|
||||
- `--tailscale-path <path>`
|
||||
- `--tailscale-target <target>`
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
openclaw webhooks gmail run --account you@example.com
|
||||
```
|
||||
|
||||
전체 설정 흐름과 운영 세부 정보는 [Gmail Pub/Sub 문서](/automation/cron-jobs#gmail-pubsub-integration)를 참조하세요.
|
||||
176
docs/ko/concepts/agent-loop.md
Normal file
176
docs/ko/concepts/agent-loop.md
Normal file
@ -0,0 +1,176 @@
|
||||
---
|
||||
read_when:
|
||||
- 에이전트 루프 또는 수명 주기 이벤트에 대한 정확한 단계별 설명이 필요함
|
||||
summary: 에이전트 루프 수명 주기, 스트림 및 wait 의미론
|
||||
title: Agent Loop
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:36Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 8e562e63c494881e9c345efcb93c5f972d69aaec61445afc3d4ad026b2d26883
|
||||
source_path: concepts/agent-loop.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Agent Loop (OpenClaw)
|
||||
|
||||
에이전트 루프는 에이전트의 전체 “실제” 실행입니다: 입력 수집 → 컨텍스트 조립 → 모델 추론 →
|
||||
도구 실행 → 응답 스트리밍 → 영속화. 이는 메시지를 동작과 최종 응답으로
|
||||
변환하면서 세션 상태의 일관성을 유지하는 권위 있는 경로입니다.
|
||||
|
||||
OpenClaw에서 루프는 세션당 하나의 직렬화된 실행이며, 모델이 생각하고, 도구를 호출하고, 출력을 스트리밍할 때
|
||||
수명 주기 및 스트림 이벤트를 발생시킵니다. 이 문서는 그 실제 루프가
|
||||
엔드 투 엔드로 어떻게 연결되어 있는지 설명합니다.
|
||||
|
||||
## 진입점
|
||||
|
||||
- Gateway RPC: `agent` 및 `agent.wait`.
|
||||
- CLI: `agent` 명령.
|
||||
|
||||
## 작동 방식(상위 수준)
|
||||
|
||||
1. `agent` RPC가 매개변수를 검증하고, 세션(sessionKey/sessionId)을 확인하고, 세션 메타데이터를 저장한 다음, 즉시 `{ runId, acceptedAt }`를 반환합니다.
|
||||
2. `agentCommand`가 에이전트를 실행합니다:
|
||||
- 모델 + thinking/verbose 기본값 확인
|
||||
- Skills 스냅샷 로드
|
||||
- `runEmbeddedPiAgent` 호출(pi-agent-core 런타임)
|
||||
- 임베디드 루프가 수명 주기 종료/오류를 발생시키지 않으면 **lifecycle end/error** 발생
|
||||
3. `runEmbeddedPiAgent`:
|
||||
- 세션별 + 전역 큐를 통해 실행을 직렬화
|
||||
- 모델 + 인증 프로필을 확인하고 pi 세션 빌드
|
||||
- pi 이벤트를 구독하고 assistant/tool 델타 스트리밍
|
||||
- 타임아웃 강제 적용 -> 초과 시 실행 중단
|
||||
- 페이로드 + 사용량 메타데이터 반환
|
||||
4. `subscribeEmbeddedPiSession`이 pi-agent-core 이벤트를 OpenClaw `agent` 스트림으로 브리지합니다:
|
||||
- 도구 이벤트 => `stream: "tool"`
|
||||
- assistant 델타 => `stream: "assistant"`
|
||||
- 수명 주기 이벤트 => `stream: "lifecycle"` (`phase: "start" | "end" | "error"`)
|
||||
5. `agent.wait`는 `waitForAgentRun`을 사용합니다:
|
||||
- `runId`에 대한 **lifecycle end/error** 대기
|
||||
- `{ status: ok|error|timeout, startedAt, endedAt, error? }` 반환
|
||||
|
||||
## 큐잉 + 동시성
|
||||
|
||||
- 실행은 세션 키(세션 레인)별로 직렬화되며 선택적으로 전역 레인을 통과합니다.
|
||||
- 이를 통해 도구/세션 경쟁 상태를 방지하고 세션 기록의 일관성을 유지합니다.
|
||||
- 메시징 채널은 이 레인 시스템에 연결되는 큐 모드(collect/steer/followup)를 선택할 수 있습니다.
|
||||
자세한 내용은 [Command Queue](/concepts/queue)를 참조하세요.
|
||||
|
||||
## 세션 + workspace 준비
|
||||
|
||||
- workspace가 확인 및 생성되며, 샌드박스 실행은 샌드박스 workspace 루트로 리디렉션될 수 있습니다.
|
||||
- Skills가 로드되거나(또는 스냅샷에서 재사용되며) env와 프롬프트에 주입됩니다.
|
||||
- bootstrap/context 파일이 확인되어 시스템 프롬프트 보고서에 주입됩니다.
|
||||
- 세션 쓰기 잠금이 획득되며, 스트리밍 전에 `SessionManager`가 열리고 준비됩니다.
|
||||
|
||||
## 프롬프트 조립 + 시스템 프롬프트
|
||||
|
||||
- 시스템 프롬프트는 OpenClaw의 기본 프롬프트, skills 프롬프트, bootstrap 컨텍스트, 실행별 재정의로 구성됩니다.
|
||||
- 모델별 제한과 compaction reserve 토큰이 강제 적용됩니다.
|
||||
- 모델이 실제로 보는 내용은 [System prompt](/concepts/system-prompt)를 참조하세요.
|
||||
|
||||
## Hook 지점(가로챌 수 있는 위치)
|
||||
|
||||
OpenClaw에는 두 가지 hook 시스템이 있습니다.
|
||||
|
||||
- **내부 hooks**(Gateway hooks): 명령 및 수명 주기 이벤트를 위한 이벤트 기반 스크립트.
|
||||
- **Plugin hooks**: 에이전트/도구 수명 주기와 gateway 파이프라인 내부의 확장 지점.
|
||||
|
||||
### 내부 hooks (Gateway hooks)
|
||||
|
||||
- **`agent:bootstrap`**: 시스템 프롬프트가 최종 확정되기 전에 bootstrap 파일을 빌드하는 동안 실행됩니다.
|
||||
bootstrap 컨텍스트 파일을 추가/제거할 때 사용합니다.
|
||||
- **명령 hooks**: `/new`, `/reset`, `/stop` 및 기타 명령 이벤트(Hooks 문서 참조).
|
||||
|
||||
설정 및 예시는 [Hooks](/automation/hooks)를 참조하세요.
|
||||
|
||||
### Plugin hooks (에이전트 + gateway 수명 주기)
|
||||
|
||||
이들은 에이전트 루프 또는 gateway 파이프라인 내부에서 실행됩니다.
|
||||
|
||||
- **`before_model_resolve`**: 모델 확인 전에 세션 사전 단계(`messages` 없음)에서 실행되어 provider/model을 결정적으로 재정의합니다.
|
||||
- **`before_prompt_build`**: 세션 로드 후(`messages` 포함) 실행되어 프롬프트 제출 전에 `prependContext`, `systemPrompt`, `prependSystemContext`, 또는 `appendSystemContext`를 주입합니다. 턴별 동적 텍스트에는 `prependContext`를 사용하고, 시스템 프롬프트 공간에 들어가야 하는 안정적인 안내에는 system-context 필드를 사용하세요.
|
||||
- **`before_agent_start`**: 레거시 호환성 hook으로 어느 단계에서든 실행될 수 있습니다. 위의 명시적 hooks를 우선 사용하세요.
|
||||
- **`before_agent_reply`**: 인라인 동작 후 및 LLM 호출 전에 실행되며, plugin이 해당 턴을 점유하고 합성 응답을 반환하거나 턴 전체를 완전히 무음 처리할 수 있게 합니다.
|
||||
- **`agent_end`**: 완료 후 최종 메시지 목록과 실행 메타데이터를 검사합니다.
|
||||
- **`before_compaction` / `after_compaction`**: compaction 주기를 관찰하거나 주석을 추가합니다.
|
||||
- **`before_tool_call` / `after_tool_call`**: 도구 매개변수/결과를 가로챕니다.
|
||||
- **`before_install`**: 내장 스캔 결과를 검사하고 skill 또는 plugin 설치를 선택적으로 차단합니다.
|
||||
- **`tool_result_persist`**: 도구 결과가 세션 기록에 기록되기 전에 동기적으로 변환합니다.
|
||||
- **`message_received` / `message_sending` / `message_sent`**: 수신 + 발신 메시지 hooks.
|
||||
- **`session_start` / `session_end`**: 세션 수명 주기 경계.
|
||||
- **`gateway_start` / `gateway_stop`**: gateway 수명 주기 이벤트.
|
||||
|
||||
발신/도구 가드에 대한 hook 결정 규칙:
|
||||
|
||||
- `before_tool_call`: `{ block: true }`는 최종 결정이며 더 낮은 우선순위 핸들러를 중단합니다.
|
||||
- `before_tool_call`: `{ block: false }`는 no-op이며 이전 block을 해제하지 않습니다.
|
||||
- `before_install`: `{ block: true }`는 최종 결정이며 더 낮은 우선순위 핸들러를 중단합니다.
|
||||
- `before_install`: `{ block: false }`는 no-op이며 이전 block을 해제하지 않습니다.
|
||||
- `message_sending`: `{ cancel: true }`는 최종 결정이며 더 낮은 우선순위 핸들러를 중단합니다.
|
||||
- `message_sending`: `{ cancel: false }`는 no-op이며 이전 cancel을 해제하지 않습니다.
|
||||
|
||||
hook API 및 등록 세부 사항은 [Plugin hooks](/plugins/architecture#provider-runtime-hooks)를 참조하세요.
|
||||
|
||||
## 스트리밍 + 부분 응답
|
||||
|
||||
- Assistant 델타는 pi-agent-core에서 스트리밍되며 `assistant` 이벤트로 발생합니다.
|
||||
- Block streaming은 `text_end` 또는 `message_end`에서 부분 응답을 발생시킬 수 있습니다.
|
||||
- Reasoning streaming은 별도 스트림 또는 block reply로 발생할 수 있습니다.
|
||||
- 청크 분할 및 block reply 동작은 [Streaming](/concepts/streaming)을 참조하세요.
|
||||
|
||||
## 도구 실행 + 메시징 도구
|
||||
|
||||
- 도구 시작/업데이트/종료 이벤트는 `tool` 스트림에서 발생합니다.
|
||||
- 도구 결과는 기록/발생 전에 크기와 이미지 페이로드 기준으로 정리됩니다.
|
||||
- 메시징 도구 전송은 중복 assistant 확인 메시지를 억제하기 위해 추적됩니다.
|
||||
|
||||
## 응답 형태 조정 + 억제
|
||||
|
||||
- 최종 페이로드는 다음으로 조립됩니다:
|
||||
- assistant 텍스트(및 선택적 reasoning)
|
||||
- 인라인 도구 요약(verbose + 허용 시)
|
||||
- 모델 오류 시 assistant 오류 텍스트
|
||||
- 정확히 `NO_REPLY` / `no_reply`인 무응답 토큰은 발신
|
||||
페이로드에서 필터링됩니다.
|
||||
- 메시징 도구 중복은 최종 페이로드 목록에서 제거됩니다.
|
||||
- 렌더링 가능한 페이로드가 남지 않았고 도구 오류가 발생한 경우,
|
||||
폴백 도구 오류 응답이 발생합니다
|
||||
(단, 메시징 도구가 이미 사용자에게 보이는 응답을 보낸 경우는 제외).
|
||||
|
||||
## Compaction + 재시도
|
||||
|
||||
- 자동 compaction은 `compaction` 스트림 이벤트를 발생시키고 재시도를 트리거할 수 있습니다.
|
||||
- 재시도 시 중복 출력을 피하기 위해 메모리 내 버퍼와 도구 요약이 재설정됩니다.
|
||||
- compaction 파이프라인은 [Compaction](/concepts/compaction)을 참조하세요.
|
||||
|
||||
## 이벤트 스트림(현재)
|
||||
|
||||
- `lifecycle`: `subscribeEmbeddedPiSession`에서 발생(그리고 폴백으로 `agentCommand`에서도 발생)
|
||||
- `assistant`: pi-agent-core의 스트리밍 델타
|
||||
- `tool`: pi-agent-core의 스트리밍 도구 이벤트
|
||||
|
||||
## 채팅 채널 처리
|
||||
|
||||
- Assistant 델타는 채팅 `delta` 메시지로 버퍼링됩니다.
|
||||
- 채팅 `final`은 **lifecycle end/error**에서 발생합니다.
|
||||
|
||||
## 타임아웃
|
||||
|
||||
- `agent.wait` 기본값: 30초(wait만 해당). `timeoutMs` 매개변수로 재정의 가능.
|
||||
- 에이전트 런타임: `agents.defaults.timeoutSeconds` 기본값 172800초(48시간); `runEmbeddedPiAgent`의 중단 타이머에서 강제 적용.
|
||||
|
||||
## 조기 종료될 수 있는 위치
|
||||
|
||||
- 에이전트 타임아웃(중단)
|
||||
- AbortSignal(취소)
|
||||
- Gateway 연결 해제 또는 RPC 타임아웃
|
||||
- `agent.wait` 타임아웃(wait만 해당, 에이전트를 중지하지는 않음)
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [Tools](/tools) — 사용 가능한 에이전트 도구
|
||||
- [Hooks](/automation/hooks) — 에이전트 수명 주기 이벤트에 의해 트리거되는 이벤트 기반 스크립트
|
||||
- [Compaction](/concepts/compaction) — 긴 대화가 요약되는 방식
|
||||
- [Exec Approvals](/tools/exec-approvals) — 셸 명령에 대한 승인 게이트
|
||||
- [Thinking](/tools/thinking) — thinking/reasoning 수준 구성
|
||||
238
docs/ko/concepts/agent-workspace.md
Normal file
238
docs/ko/concepts/agent-workspace.md
Normal file
@ -0,0 +1,238 @@
|
||||
---
|
||||
read_when:
|
||||
- 에이전트 워크스페이스 또는 해당 파일 레이아웃을 설명해야 할 때
|
||||
- 에이전트 워크스페이스를 백업하거나 마이그레이션하려고 할 때
|
||||
summary: '에이전트 워크스페이스: 위치, 레이아웃 및 백업 전략'
|
||||
title: 에이전트 워크스페이스
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:37Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 3735633f1098c733415369f9836fdbbc0bf869636a24ed42e95e6784610d964a
|
||||
source_path: concepts/agent-workspace.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 에이전트 워크스페이스
|
||||
|
||||
워크스페이스는 에이전트의 집입니다. 파일 도구와 워크스페이스 컨텍스트에 사용되는 유일한 작업 디렉터리입니다. 이를 비공개로 유지하고 메모리처럼 취급하세요.
|
||||
|
||||
이는 config, 자격 증명, 세션을 저장하는 `~/.openclaw/`와는 별개입니다.
|
||||
|
||||
**중요:** 워크스페이스는 하드 샌드박스가 아니라 **기본 cwd**입니다. 도구는 상대 경로를 워크스페이스 기준으로 해석하지만, 샌드박싱이 활성화되지 않은 경우 절대 경로는 여전히 호스트의 다른 위치에 접근할 수 있습니다. 격리가 필요하면 [`agents.defaults.sandbox`](/gateway/sandboxing)(및/또는 에이전트별 sandbox config)를 사용하세요. 샌드박싱이 활성화되어 있고 `workspaceAccess`가 `"rw"`가 아니면, 도구는 호스트 워크스페이스가 아니라 `~/.openclaw/sandboxes` 아래의 sandbox 워크스페이스 내부에서 동작합니다.
|
||||
|
||||
## 기본 위치
|
||||
|
||||
- 기본값: `~/.openclaw/workspace`
|
||||
- `OPENCLAW_PROFILE`이 설정되어 있고 `"default"`가 아니면 기본값은
|
||||
`~/.openclaw/workspace-<profile>`이 됩니다.
|
||||
- `~/.openclaw/openclaw.json`에서 재정의:
|
||||
|
||||
```json5
|
||||
{
|
||||
agent: {
|
||||
workspace: "~/.openclaw/workspace",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`openclaw onboard`, `openclaw configure`, 또는 `openclaw setup`은 워크스페이스를 생성하고 누락된 경우 bootstrap 파일을 시드합니다.
|
||||
Sandbox 시드 복사는 워크스페이스 내부의 일반 파일만 허용하며, 원본 워크스페이스 외부로 해석되는 symlink/hardlink 별칭은 무시됩니다.
|
||||
|
||||
이미 워크스페이스 파일을 직접 관리하고 있다면 bootstrap
|
||||
파일 생성을 비활성화할 수 있습니다:
|
||||
|
||||
```json5
|
||||
{ agent: { skipBootstrap: true } }
|
||||
```
|
||||
|
||||
## 추가 워크스페이스 폴더
|
||||
|
||||
이전 설치에서는 `~/openclaw`가 생성되었을 수 있습니다. 여러 워크스페이스
|
||||
디렉터리를 유지하면 혼란스러운 인증 또는 상태 드리프트가 발생할 수 있습니다. 한 번에 활성화되는 워크스페이스는 하나뿐이기 때문입니다.
|
||||
|
||||
**권장 사항:** 활성 워크스페이스는 하나만 유지하세요. 더 이상 추가
|
||||
폴더를 사용하지 않는다면 보관하거나 휴지통으로 이동하세요(예: `trash ~/openclaw`).
|
||||
의도적으로 여러 워크스페이스를 유지하는 경우,
|
||||
`agents.defaults.workspace`가 활성 워크스페이스를 가리키는지 확인하세요.
|
||||
|
||||
`openclaw doctor`는 추가 워크스페이스 디렉터리를 감지하면 경고합니다.
|
||||
|
||||
## 워크스페이스 파일 맵(각 파일의 의미)
|
||||
|
||||
다음은 OpenClaw가 워크스페이스 내부에서 기대하는 표준 파일입니다:
|
||||
|
||||
- `AGENTS.md`
|
||||
- 에이전트의 운영 지침과 메모리 사용 방법.
|
||||
- 모든 세션 시작 시 로드됩니다.
|
||||
- 규칙, 우선순위, "어떻게 행동할지" 세부 사항을 두기 좋은 위치입니다.
|
||||
|
||||
- `SOUL.md`
|
||||
- 페르소나, 어조 및 경계.
|
||||
- 모든 세션에서 로드됩니다.
|
||||
- 가이드: [SOUL.md Personality Guide](/concepts/soul)
|
||||
|
||||
- `USER.md`
|
||||
- 사용자가 누구인지와 어떻게 호칭할지.
|
||||
- 모든 세션에서 로드됩니다.
|
||||
|
||||
- `IDENTITY.md`
|
||||
- 에이전트의 이름, 분위기, 이모지.
|
||||
- bootstrap 의식 중 생성/업데이트됩니다.
|
||||
|
||||
- `TOOLS.md`
|
||||
- 로컬 도구와 규칙에 대한 메모.
|
||||
- 도구 사용 가능 여부를 제어하지는 않으며, 안내용일 뿐입니다.
|
||||
|
||||
- `HEARTBEAT.md`
|
||||
- heartbeat 실행용 선택적 소형 체크리스트.
|
||||
- 토큰 낭비를 피하기 위해 짧게 유지하세요.
|
||||
|
||||
- `BOOT.md`
|
||||
- internal hooks가 활성화되어 있을 때 게이트웨이 재시작 시 실행되는 선택적 시작 체크리스트.
|
||||
- 짧게 유지하고, 발신 전송에는 message 도구를 사용하세요.
|
||||
|
||||
- `BOOTSTRAP.md`
|
||||
- 일회성 최초 실행 의식.
|
||||
- 완전히 새로운 워크스페이스에만 생성됩니다.
|
||||
- 의식이 완료되면 삭제하세요.
|
||||
|
||||
- `memory/YYYY-MM-DD.md`
|
||||
- 일일 메모리 로그(하루당 파일 하나).
|
||||
- 세션 시작 시 오늘 + 어제 파일을 읽는 것을 권장합니다.
|
||||
|
||||
- `MEMORY.md` (선택 사항)
|
||||
- 선별된 장기 메모리.
|
||||
- 메인 비공개 세션에서만 로드합니다(공유/그룹 컨텍스트 제외).
|
||||
|
||||
워크플로와 자동 메모리 플러시는 [Memory](/concepts/memory)를 참조하세요.
|
||||
|
||||
- `skills/` (선택 사항)
|
||||
- 워크스페이스 전용 Skills.
|
||||
- 해당 워크스페이스에서 가장 높은 우선순위의 Skills 위치입니다.
|
||||
- 이름이 충돌하면 프로젝트 에이전트 Skills, 개인 에이전트 Skills, 관리형 Skills, 번들 Skills, `skills.load.extraDirs`를 재정의합니다.
|
||||
|
||||
- `canvas/` (선택 사항)
|
||||
- 노드 디스플레이용 Canvas UI 파일(예: `canvas/index.html`).
|
||||
|
||||
bootstrap 파일이 하나라도 누락되면 OpenClaw는 세션에 "missing file" 마커를 삽입하고 계속 진행합니다. 큰 bootstrap 파일은 삽입 시 잘립니다. 제한은 `agents.defaults.bootstrapMaxChars`(기본값: 20000)와 `agents.defaults.bootstrapTotalMaxChars`(기본값: 150000)로 조정하세요.
|
||||
`openclaw setup`은 기존 파일을 덮어쓰지 않고 누락된 기본 파일을 다시 만들 수 있습니다.
|
||||
|
||||
## 워크스페이스에 없는 것
|
||||
|
||||
다음 항목은 `~/.openclaw/` 아래에 있으며 워크스페이스 리포지토리에 커밋하면 안 됩니다:
|
||||
|
||||
- `~/.openclaw/openclaw.json` (config)
|
||||
- `~/.openclaw/agents/<agentId>/agent/auth-profiles.json` (모델 인증 프로필: OAuth + API 키)
|
||||
- `~/.openclaw/credentials/` (채널/provider 상태 및 레거시 OAuth 가져오기 데이터)
|
||||
- `~/.openclaw/agents/<agentId>/sessions/` (세션 transcript + 메타데이터)
|
||||
- `~/.openclaw/skills/` (관리형 Skills)
|
||||
|
||||
세션 또는 config를 마이그레이션해야 하는 경우, 따로 복사하고
|
||||
버전 제어에는 포함하지 마세요.
|
||||
|
||||
## Git 백업(권장, 비공개)
|
||||
|
||||
워크스페이스를 비공개 메모리처럼 취급하세요. **비공개** git 리포지토리에 넣어 백업되고 복구 가능하도록 하세요.
|
||||
|
||||
다음 단계는 게이트웨이가 실행되는 머신에서 실행하세요(워크스페이스가 그곳에 있습니다).
|
||||
|
||||
### 1) 리포지토리 초기화
|
||||
|
||||
git이 설치되어 있으면 완전히 새로운 워크스페이스는 자동으로 초기화됩니다. 이
|
||||
워크스페이스가 아직 리포지토리가 아니라면 다음을 실행하세요:
|
||||
|
||||
```bash
|
||||
cd ~/.openclaw/workspace
|
||||
git init
|
||||
git add AGENTS.md SOUL.md TOOLS.md IDENTITY.md USER.md HEARTBEAT.md memory/
|
||||
git commit -m "Add agent workspace"
|
||||
```
|
||||
|
||||
### 2) 비공개 원격 저장소 추가(초보자 친화적 옵션)
|
||||
|
||||
옵션 A: GitHub 웹 UI
|
||||
|
||||
1. GitHub에서 새 **비공개** 리포지토리를 생성합니다.
|
||||
2. README로 초기화하지 마세요(병합 충돌 방지).
|
||||
3. HTTPS 원격 URL을 복사합니다.
|
||||
4. 원격을 추가하고 푸시합니다:
|
||||
|
||||
```bash
|
||||
git branch -M main
|
||||
git remote add origin <https-url>
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
옵션 B: GitHub CLI (`gh`)
|
||||
|
||||
```bash
|
||||
gh auth login
|
||||
gh repo create openclaw-workspace --private --source . --remote origin --push
|
||||
```
|
||||
|
||||
옵션 C: GitLab 웹 UI
|
||||
|
||||
1. GitLab에서 새 **비공개** 리포지토리를 생성합니다.
|
||||
2. README로 초기화하지 마세요(병합 충돌 방지).
|
||||
3. HTTPS 원격 URL을 복사합니다.
|
||||
4. 원격을 추가하고 푸시합니다:
|
||||
|
||||
```bash
|
||||
git branch -M main
|
||||
git remote add origin <https-url>
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
### 3) 지속적인 업데이트
|
||||
|
||||
```bash
|
||||
git status
|
||||
git add .
|
||||
git commit -m "Update memory"
|
||||
git push
|
||||
```
|
||||
|
||||
## 비밀 정보는 커밋하지 마세요
|
||||
|
||||
비공개 리포지토리에서도 워크스페이스에 비밀 정보를 저장하지 않는 것이 좋습니다:
|
||||
|
||||
- API 키, OAuth 토큰, 비밀번호 또는 비공개 자격 증명.
|
||||
- `~/.openclaw/` 아래의 모든 항목.
|
||||
- 채팅 또는 민감한 첨부파일의 원시 덤프.
|
||||
|
||||
민감한 참조를 저장해야 한다면 플레이스홀더를 사용하고 실제
|
||||
비밀 정보는 다른 곳(비밀번호 관리자, 환경 변수 또는 `~/.openclaw/`)에 보관하세요.
|
||||
|
||||
권장 `.gitignore` 시작 예시:
|
||||
|
||||
```gitignore
|
||||
.DS_Store
|
||||
.env
|
||||
**/*.key
|
||||
**/*.pem
|
||||
**/secrets*
|
||||
```
|
||||
|
||||
## 워크스페이스를 새 머신으로 이동하기
|
||||
|
||||
1. 원하는 경로(기본값 `~/.openclaw/workspace`)에 리포지토리를 클론합니다.
|
||||
2. `~/.openclaw/openclaw.json`에서 `agents.defaults.workspace`를 해당 경로로 설정합니다.
|
||||
3. 누락된 파일을 시드하려면 `openclaw setup --workspace <path>`를 실행합니다.
|
||||
4. 세션이 필요하면 이전 머신의 `~/.openclaw/agents/<agentId>/sessions/`를
|
||||
별도로 복사합니다.
|
||||
|
||||
## 고급 참고 사항
|
||||
|
||||
- 다중 에이전트 라우팅에서는 에이전트별로 서로 다른 워크스페이스를 사용할 수 있습니다. 라우팅 구성은
|
||||
[채널 라우팅](/channels/channel-routing)을 참조하세요.
|
||||
- `agents.defaults.sandbox`가 활성화되어 있으면, 메인 세션이 아닌 세션은
|
||||
`agents.defaults.sandbox.workspaceRoot` 아래의 세션별 sandbox
|
||||
워크스페이스를 사용할 수 있습니다.
|
||||
|
||||
## 관련
|
||||
|
||||
- [Standing Orders](/automation/standing-orders) — 워크스페이스 파일의 영구 지침
|
||||
- [Heartbeat](/gateway/heartbeat) — HEARTBEAT.md 워크스페이스 파일
|
||||
- [Session](/concepts/session) — 세션 저장 경로
|
||||
- [Sandboxing](/gateway/sandboxing) — 샌드박스 환경에서의 워크스페이스 접근
|
||||
130
docs/ko/concepts/agent.md
Normal file
130
docs/ko/concepts/agent.md
Normal file
@ -0,0 +1,130 @@
|
||||
---
|
||||
read_when:
|
||||
- 에이전트 런타임, 워크스페이스 부트스트랩, 또는 세션 동작을 변경할 때
|
||||
summary: 에이전트 런타임, 워크스페이스 계약, 세션 부트스트랩
|
||||
title: 에이전트 런타임
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:32Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: e2ff39f4114f009e5b1f86894ea4bb29b1c9512563b70d063f09ca7cde5e8948
|
||||
source_path: concepts/agent.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# 에이전트 런타임
|
||||
|
||||
OpenClaw는 단일 임베디드 에이전트 런타임을 실행합니다.
|
||||
|
||||
## 워크스페이스(필수)
|
||||
|
||||
OpenClaw는 단일 에이전트 워크스페이스 디렉터리(`agents.defaults.workspace`)를 도구와 컨텍스트를 위한 에이전트의 **유일한** 작업 디렉터리(`cwd`)로 사용합니다.
|
||||
|
||||
권장 사항: `openclaw setup`을 사용해 `~/.openclaw/openclaw.json`이 없으면 생성하고 워크스페이스 파일을 초기화하세요.
|
||||
|
||||
전체 워크스페이스 레이아웃 + 백업 가이드: [Agent workspace](/concepts/agent-workspace)
|
||||
|
||||
`agents.defaults.sandbox`가 활성화되어 있으면, 비메인 세션은
|
||||
`agents.defaults.sandbox.workspaceRoot` 아래의 세션별 워크스페이스로 이를 재정의할 수 있습니다(
|
||||
[Gateway configuration](/gateway/configuration) 참조).
|
||||
|
||||
## 부트스트랩 파일(주입됨)
|
||||
|
||||
`agents.defaults.workspace` 내부에서 OpenClaw는 다음 사용자 편집 가능 파일을 예상합니다.
|
||||
|
||||
- `AGENTS.md` — 운영 지침 + “메모리”
|
||||
- `SOUL.md` — 페르소나, 경계, 톤
|
||||
- `TOOLS.md` — 사용자가 유지 관리하는 도구 메모(예: `imsg`, `sag`, 규칙)
|
||||
- `BOOTSTRAP.md` — 일회성 첫 실행 의식(완료 후 삭제됨)
|
||||
- `IDENTITY.md` — 에이전트 이름/분위기/이모지
|
||||
- `USER.md` — 사용자 프로필 + 선호하는 호칭
|
||||
|
||||
새 세션의 첫 턴에서 OpenClaw는 이 파일들의 내용을 에이전트 컨텍스트에 직접 주입합니다.
|
||||
|
||||
비어 있는 파일은 건너뜁니다. 큰 파일은 프롬프트를 가볍게 유지하기 위해 표시자와 함께 잘리고 축약됩니다(전체 내용은 파일을 읽으세요).
|
||||
|
||||
파일이 없으면 OpenClaw는 단일 “파일 없음” 표시 줄을 주입합니다(그리고 `openclaw setup`이 안전한 기본 템플릿을 생성합니다).
|
||||
|
||||
`BOOTSTRAP.md`는 **완전히 새로운 워크스페이스**에서만 생성됩니다(다른 부트스트랩 파일이 없는 경우). 의식을 완료한 뒤 삭제하면 이후 재시작에서 다시 생성되지 않아야 합니다.
|
||||
|
||||
부트스트랩 파일 생성을 완전히 비활성화하려면(사전 시드된 워크스페이스용) 다음을 설정하세요:
|
||||
|
||||
```json5
|
||||
{ agent: { skipBootstrap: true } }
|
||||
```
|
||||
|
||||
## 내장 도구
|
||||
|
||||
핵심 도구(read/exec/edit/write 및 관련 시스템 도구)는 도구 정책의 적용을 받으면서 항상 사용할 수 있습니다. `apply_patch`는 선택 사항이며 `tools.exec.applyPatch`로 제어됩니다. `TOOLS.md`는 어떤 도구가 존재하는지를 제어하지 않으며, _어떻게_ 사용되기를 원하는지에 대한 지침입니다.
|
||||
|
||||
## Skills
|
||||
|
||||
OpenClaw는 다음 위치에서 Skills를 로드합니다(우선순위 높은 순):
|
||||
|
||||
- 워크스페이스: `<workspace>/skills`
|
||||
- 프로젝트 에이전트 Skills: `<workspace>/.agents/skills`
|
||||
- 개인 에이전트 Skills: `~/.agents/skills`
|
||||
- 관리형/로컬: `~/.openclaw/skills`
|
||||
- 번들됨(설치와 함께 제공)
|
||||
- 추가 Skill 폴더: `skills.load.extraDirs`
|
||||
|
||||
Skills는 config/env로 제어될 수 있습니다([Gateway configuration](/gateway/configuration)의 `skills` 참조).
|
||||
|
||||
## 런타임 경계
|
||||
|
||||
임베디드 에이전트 런타임은 Pi 에이전트 코어(모델, 도구, 프롬프트 파이프라인)를 기반으로 구축됩니다. 세션 관리, discovery, 도구 연결, 채널 전달은 그 코어 위의 OpenClaw 소유 계층입니다.
|
||||
|
||||
## 세션
|
||||
|
||||
세션 transcript는 다음 위치에 JSONL로 저장됩니다.
|
||||
|
||||
- `~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl`
|
||||
|
||||
세션 ID는 안정적이며 OpenClaw가 선택합니다.
|
||||
다른 도구의 레거시 세션 폴더는 읽지 않습니다.
|
||||
|
||||
## 스트리밍 중 조정
|
||||
|
||||
큐 모드가 `steer`이면 인바운드 메시지가 현재 실행에 주입됩니다.
|
||||
대기된 조정은 **현재 assistant 턴이 도구 호출 실행을 마친 뒤**,
|
||||
다음 LLM 호출 전에 전달됩니다. 이제 조정은 현재 assistant 메시지의
|
||||
남은 도구 호출을 건너뛰지 않으며, 대신 다음 모델 경계에서 대기된
|
||||
메시지를 주입합니다.
|
||||
|
||||
큐 모드가 `followup` 또는 `collect`이면 인바운드 메시지는 현재 턴이 끝날 때까지
|
||||
보류되며, 그다음 대기된 페이로드로 새 에이전트 턴이 시작됩니다. 모드 + 디바운스/상한 동작은
|
||||
[Queue](/concepts/queue)를 참조하세요.
|
||||
|
||||
블록 스트리밍은 완료된 assistant 블록을 끝나는 즉시 전송합니다. 이는
|
||||
**기본적으로 꺼져 있습니다**(`agents.defaults.blockStreamingDefault: "off"`).
|
||||
경계는 `agents.defaults.blockStreamingBreak`로 조정합니다(`text_end` 또는 `message_end`, 기본값은 text_end).
|
||||
소프트 블록 청크 분할은 `agents.defaults.blockStreamingChunk`로 제어합니다(기본값
|
||||
800–1200자, 문단 구분 우선, 그다음 줄바꿈, 문장은 마지막).
|
||||
스트리밍된 청크는 `agents.defaults.blockStreamingCoalesce`로 병합해
|
||||
한 줄짜리 스팸을 줄일 수 있습니다(전송 전 idle 기반 병합). Telegram이 아닌 채널은
|
||||
블록 답글을 활성화하려면 명시적으로 `*.blockStreaming: true`가 필요합니다.
|
||||
상세한 도구 요약은 도구 시작 시 출력되며(디바운스 없음), Control UI는
|
||||
가능할 때 에이전트 이벤트를 통해 도구 출력을 스트리밍합니다.
|
||||
자세한 내용: [Streaming + chunking](/concepts/streaming).
|
||||
|
||||
## 모델 ref
|
||||
|
||||
config의 모델 ref(예: `agents.defaults.model` 및 `agents.defaults.models`)는 **첫 번째** `/`를 기준으로 분리하여 파싱됩니다.
|
||||
|
||||
- 모델을 구성할 때는 `provider/model`을 사용하세요.
|
||||
- 모델 ID 자체에 `/`가 포함되는 경우(OpenRouter 스타일), provider 접두사를 포함하세요(예: `openrouter/moonshotai/kimi-k2`).
|
||||
- provider를 생략하면 OpenClaw는 먼저 별칭을 시도하고, 그다음 정확한 모델 ID에 대한 고유한
|
||||
구성 provider 일치를 시도한 후, 마지막으로 구성된 기본 provider로 대체합니다. 해당 provider가 더 이상
|
||||
구성된 기본 모델을 제공하지 않으면, OpenClaw는 오래되어 제거된 provider 기본값을 표시하는 대신
|
||||
첫 번째 구성된 provider/model로 대체합니다.
|
||||
|
||||
## 구성(최소)
|
||||
|
||||
최소한 다음을 설정하세요:
|
||||
|
||||
- `agents.defaults.workspace`
|
||||
- `channels.whatsapp.allowFrom`(강력 권장)
|
||||
|
||||
---
|
||||
|
||||
_다음: [Group Chats](/channels/group-messages)_ 🦞
|
||||
161
docs/ko/concepts/architecture.md
Normal file
161
docs/ko/concepts/architecture.md
Normal file
@ -0,0 +1,161 @@
|
||||
---
|
||||
read_when:
|
||||
- 게이트웨이 프로토콜, 클라이언트 또는 전송 계층을 작업할 때
|
||||
summary: WebSocket 게이트웨이 아키텍처, 구성 요소 및 클라이언트 흐름
|
||||
title: Gateway 아키텍처
|
||||
x-i18n:
|
||||
generated_at: "2026-04-05T12:39:32Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 2b12a2a29e94334c6d10787ac85c34b5b046f9a14f3dd53be453368ca4a7547d
|
||||
source_path: concepts/architecture.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Gateway 아키텍처
|
||||
|
||||
## 개요
|
||||
|
||||
- 하나의 장기 실행 **Gateway**가 모든 메시징 표면을 소유합니다(WhatsApp via
|
||||
Baileys, Telegram via grammY, Slack, Discord, Signal, iMessage, WebChat).
|
||||
- 제어 평면 클라이언트(macOS 앱, CLI, 웹 UI, 자동화)는 구성된 바인드 호스트(기본값
|
||||
`127.0.0.1:18789`)에서 **WebSocket**을 통해
|
||||
Gateway에 연결합니다.
|
||||
- **Nodes**(macOS/iOS/Android/headless)도 **WebSocket**을 통해 연결하지만,
|
||||
명시적인 caps/commands와 함께 `role: node`를 선언합니다.
|
||||
- 호스트당 하나의 Gateway만 존재하며, WhatsApp 세션을 여는 유일한 위치입니다.
|
||||
- **canvas host**는 Gateway HTTP 서버에서 다음 경로로 제공됩니다.
|
||||
- `/__openclaw__/canvas/` (에이전트가 편집 가능한 HTML/CSS/JS)
|
||||
- `/__openclaw__/a2ui/` (A2UI 호스트)
|
||||
이는 Gateway와 같은 포트(기본값 `18789`)를 사용합니다.
|
||||
|
||||
## 구성 요소 및 흐름
|
||||
|
||||
### Gateway (daemon)
|
||||
|
||||
- provider 연결을 유지합니다.
|
||||
- 타입이 지정된 WS API(요청, 응답, 서버 푸시 이벤트)를 노출합니다.
|
||||
- 들어오는 프레임을 JSON Schema에 따라 검증합니다.
|
||||
- `agent`, `chat`, `presence`, `health`, `heartbeat`, `cron` 같은 이벤트를 내보냅니다.
|
||||
|
||||
### Clients (mac app / CLI / web admin)
|
||||
|
||||
- 클라이언트당 하나의 WS 연결을 사용합니다.
|
||||
- 요청(`health`, `status`, `send`, `agent`, `system-presence`)을 보냅니다.
|
||||
- 이벤트(`tick`, `agent`, `presence`, `shutdown`)를 구독합니다.
|
||||
|
||||
### Nodes (macOS / iOS / Android / headless)
|
||||
|
||||
- `role: node`와 함께 **같은 WS 서버**에 연결합니다.
|
||||
- `connect`에서 장치 ID를 제공하며, pairing은 **장치 기반**(role `node`)이고
|
||||
승인은 장치 pairing 저장소에 유지됩니다.
|
||||
- `canvas.*`, `camera.*`, `screen.record`, `location.get` 같은 명령을 노출합니다.
|
||||
|
||||
프로토콜 세부 사항:
|
||||
|
||||
- [Gateway protocol](/gateway/protocol)
|
||||
|
||||
### WebChat
|
||||
|
||||
- 채팅 기록과 전송을 위해 Gateway WS API를 사용하는 정적 UI입니다.
|
||||
- 원격 설정에서는 다른
|
||||
클라이언트와 동일한 SSH/Tailscale 터널을 통해 연결됩니다.
|
||||
|
||||
## 연결 수명 주기(단일 클라이언트)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant Gateway
|
||||
|
||||
Client->>Gateway: req:connect
|
||||
Gateway-->>Client: res (ok)
|
||||
Note right of Gateway: 또는 res error + close
|
||||
Note left of Client: payload=hello-ok<br>snapshot: presence + health
|
||||
|
||||
Gateway-->>Client: event:presence
|
||||
Gateway-->>Client: event:tick
|
||||
|
||||
Client->>Gateway: req:agent
|
||||
Gateway-->>Client: res:agent<br>ack {runId, status:"accepted"}
|
||||
Gateway-->>Client: event:agent<br>(streaming)
|
||||
Gateway-->>Client: res:agent<br>final {runId, status, summary}
|
||||
```
|
||||
|
||||
## 와이어 프로토콜(요약)
|
||||
|
||||
- 전송 계층: WebSocket, JSON payload를 포함한 텍스트 프레임.
|
||||
- 첫 번째 프레임은 **반드시** `connect`여야 합니다.
|
||||
- 핸드셰이크 이후:
|
||||
- 요청: `{type:"req", id, method, params}` → `{type:"res", id, ok, payload|error}`
|
||||
- 이벤트: `{type:"event", event, payload, seq?, stateVersion?}`
|
||||
- `hello-ok.features.methods` / `events`는
|
||||
검색 메타데이터이며, 호출 가능한 모든 helper route의 생성된 덤프가 아닙니다.
|
||||
- 공유 시크릿 인증은 구성된 gateway 인증 모드에 따라
|
||||
`connect.params.auth.token` 또는
|
||||
`connect.params.auth.password`를 사용합니다.
|
||||
- Tailscale Serve
|
||||
(`gateway.auth.allowTailscale: true`) 같은 ID 기반 모드나 non-loopback
|
||||
`gateway.auth.mode: "trusted-proxy"`는 `connect.params.auth.*` 대신
|
||||
요청 헤더에서 인증을 충족합니다.
|
||||
- private-ingress `gateway.auth.mode: "none"`은 공유 시크릿 인증을
|
||||
완전히 비활성화합니다. 이 모드는 공개/비신뢰 ingress에서는 사용하지 마세요.
|
||||
- 부작용이 있는 메서드(`send`, `agent`)에는
|
||||
안전한 재시도를 위해 idempotency key가 필요합니다. 서버는 짧은 수명의 dedupe 캐시를 유지합니다.
|
||||
- Nodes는 `connect`에 `role: "node"`와 caps/commands/permissions를 포함해야 합니다.
|
||||
|
||||
## pairing + 로컬 신뢰
|
||||
|
||||
- 모든 WS 클라이언트(운영자 + node)는 `connect`에 **장치 ID**를 포함합니다.
|
||||
- 새 장치 ID는 pairing 승인이 필요하며, Gateway는 이후 연결을 위해 **device token**을 발급합니다.
|
||||
- 직접적인 로컬 loopback 연결은 동일 호스트 UX를 부드럽게 유지하기 위해 자동 승인될 수 있습니다.
|
||||
- OpenClaw에는 신뢰된 공유 시크릿 helper 흐름을 위한
|
||||
좁은 범위의 backend/container-local self-connect 경로도 있습니다.
|
||||
- same-host tailnet 바인드를 포함한 tailnet 및 LAN 연결은 여전히
|
||||
명시적인 pairing 승인이 필요합니다.
|
||||
- 모든 연결은 `connect.challenge` nonce에 서명해야 합니다.
|
||||
- 서명 payload `v3`는 `platform` + `deviceFamily`도 바인딩하며, gateway는 재연결 시 pairing된 메타데이터를 고정하고
|
||||
메타데이터 변경 시 복구 pairing을 요구합니다.
|
||||
- **비로컬** 연결은 여전히 명시적인 승인이 필요합니다.
|
||||
- Gateway 인증(`gateway.auth.*`)은 로컬이든
|
||||
원격이든 **모든** 연결에 계속 적용됩니다.
|
||||
|
||||
세부 사항: [Gateway protocol](/gateway/protocol), [Pairing](/channels/pairing),
|
||||
[Security](/gateway/security).
|
||||
|
||||
## 프로토콜 타이핑 및 코드 생성
|
||||
|
||||
- TypeBox 스키마가 프로토콜을 정의합니다.
|
||||
- JSON Schema는 이러한 스키마에서 생성됩니다.
|
||||
- Swift 모델은 JSON Schema에서 생성됩니다.
|
||||
|
||||
## 원격 액세스
|
||||
|
||||
- 권장: Tailscale 또는 VPN.
|
||||
- 대안: SSH 터널
|
||||
|
||||
```bash
|
||||
ssh -N -L 18789:127.0.0.1:18789 user@host
|
||||
```
|
||||
|
||||
- 같은 핸드셰이크 + 인증 토큰이 터널 위에서도 적용됩니다.
|
||||
- 원격 설정의 WS에는 TLS + 선택적 pinning을 활성화할 수 있습니다.
|
||||
|
||||
## 운영 스냅샷
|
||||
|
||||
- 시작: `openclaw gateway` (포그라운드, 로그는 stdout으로 출력).
|
||||
- 상태 확인: WS를 통한 `health` (`hello-ok`에도 포함됨).
|
||||
- 감독: 자동 재시작을 위한 launchd/systemd.
|
||||
|
||||
## 불변 조건
|
||||
|
||||
- 정확히 하나의 Gateway가 호스트당 하나의 Baileys 세션을 제어합니다.
|
||||
- 핸드셰이크는 필수이며, JSON이 아니거나 `connect`가 아닌 첫 프레임은 즉시 연결 종료됩니다.
|
||||
- 이벤트는 재생되지 않으므로, 클라이언트는 누락이 있으면 새로고침해야 합니다.
|
||||
|
||||
## 관련
|
||||
|
||||
- [Agent Loop](/concepts/agent-loop) — 자세한 에이전트 실행 주기
|
||||
- [Gateway Protocol](/gateway/protocol) — WebSocket 프로토콜 계약
|
||||
- [Queue](/concepts/queue) — 명령 큐 및 동시성
|
||||
- [Security](/gateway/security) — 신뢰 모델 및 보안 강화
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user