From 37f6599b1cfb2e82b4594d3cb32516f47f006f84 Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Fri, 10 Apr 2026 06:07:26 +0000 Subject: [PATCH] chore(i18n): refresh ko translations --- docs/ko/automation/tasks.md | 224 +-- docs/ko/concepts/active-memory.md | 580 ++++++ docs/ko/concepts/memory-search.md | 75 +- docs/ko/concepts/qa-e2e-automation.md | 119 +- docs/ko/gateway/configuration-reference.md | 2006 ++++++++++++++------ docs/ko/help/testing.md | 777 ++++---- docs/ko/reference/memory-config.md | 351 ++-- docs/ko/tools/browser.md | 519 ++--- 8 files changed, 3086 insertions(+), 1565 deletions(-) create mode 100644 docs/ko/concepts/active-memory.md diff --git a/docs/ko/automation/tasks.md b/docs/ko/automation/tasks.md index a964e7c80..6c882cb18 100644 --- a/docs/ko/automation/tasks.md +++ b/docs/ko/automation/tasks.md @@ -1,44 +1,44 @@ --- read_when: - - 진행 중이거나 최근 완료된 백그라운드 작업을 확인할 때 - - 분리된 에이전트 실행의 전달 실패를 디버깅할 때 - - 백그라운드 실행이 세션, cron, heartbeat와 어떻게 연결되는지 이해할 때 -summary: ACP 실행, 하위 에이전트, 격리된 cron 작업, CLI 작업에 대한 백그라운드 작업 추적 + - 진행 중이거나 최근 완료된 백그라운드 작업 검사 + - 분리된 에이전트 실행의 전달 실패 디버깅 + - 백그라운드 실행이 세션, cron, 그리고 하트비트와 어떻게 연결되는지 이해하기 +summary: ACP 실행, 하위 에이전트, 격리된 cron 작업, 그리고 CLI 작업을 위한 백그라운드 작업 추적 title: 백그라운드 작업 x-i18n: - generated_at: "2026-04-06T03:06:46Z" + generated_at: "2026-04-10T05:59:51Z" model: gpt-5.4 provider: openai - source_hash: 2f56c1ac23237907a090c69c920c09578a2f56f5d8bf750c7f2136c603c8a8ff + source_hash: d7b5ba41f1025e0089986342ce85698bc62f676439c3ccf03f3ed146beb1b1ac source_path: automation/tasks.md workflow: 15 --- # 백그라운드 작업 -> **예약을 찾고 있나요?** 적절한 메커니즘을 선택하려면 [Automation & Tasks](/ko/automation)를 참고하세요. 이 페이지는 백그라운드 작업의 **추적**을 다루며, 예약 자체를 설명하지 않습니다. +> **일정을 찾고 있나요?** 적절한 메커니즘을 선택하려면 [Automation & Tasks](/ko/automation)를 참조하세요. 이 페이지는 백그라운드 작업의 **추적**을 다루며, 예약을 다루지 않습니다. -백그라운드 작업은 **주 대화 세션 외부**에서 실행되는 작업을 추적합니다: +백그라운드 작업은 **기본 대화 세션 외부에서** 실행되는 작업을 추적합니다: ACP 실행, 하위 에이전트 생성, 격리된 cron 작업 실행, 그리고 CLI로 시작된 작업입니다. -작업은 세션, cron 작업, heartbeat를 **대체하지 않습니다**. 대신 어떤 분리된 작업이 발생했고, 언제 발생했으며, 성공했는지를 기록하는 **활동 원장**입니다. +작업은 세션, cron 작업, 또는 하트비트를 대체하지 않습니다 — 이것들은 분리된 작업이 무엇이었는지, 언제 발생했는지, 그리고 성공했는지를 기록하는 **활동 원장**입니다. -모든 에이전트 실행이 작업을 생성하는 것은 아닙니다. Heartbeat 턴과 일반적인 대화형 채팅은 생성하지 않습니다. 모든 cron 실행, ACP 생성, 하위 에이전트 생성, CLI 에이전트 명령은 작업을 생성합니다. +모든 에이전트 실행이 작업을 생성하는 것은 아닙니다. 하트비트 턴과 일반 대화형 채팅은 생성하지 않습니다. 모든 cron 실행, ACP 생성, 하위 에이전트 생성, 그리고 CLI 에이전트 명령은 생성합니다. -## 요약 +## TL;DR -- 작업은 스케줄러가 아니라 **기록**입니다. cron과 heartbeat는 작업이 _언제_ 실행될지 결정하고, 작업은 _무슨 일이 있었는지_ 추적합니다. -- ACP, 하위 에이전트, 모든 cron 작업, CLI 작업은 작업을 생성합니다. Heartbeat 턴은 생성하지 않습니다. -- 각 작업은 `queued → running → terminal`(succeeded, failed, timed_out, cancelled 또는 lost) 단계를 거칩니다. -- Cron 작업은 cron 런타임이 여전히 해당 작업을 소유하는 동안 활성 상태를 유지하며, 채팅 기반 CLI 작업은 소유한 실행 컨텍스트가 아직 활성 상태일 때만 활성 상태를 유지합니다. -- 완료는 푸시 기반입니다. 분리된 작업은 완료되면 직접 알리거나 요청자 세션/heartbeat를 깨울 수 있으므로, 상태를 폴링하는 루프는 대개 적절한 형태가 아닙니다. -- 격리된 cron 실행과 하위 에이전트 완료는 최종 정리 bookkeeping 전에 해당 하위 세션의 추적된 브라우저 탭/프로세스를 가능한 범위에서 정리합니다. -- 격리된 cron 전달은 하위 하위 에이전트 작업이 아직 마무리 중일 때 오래된 중간 부모 응답을 억제하며, 전달 전에 최종 하위 출력이 도착하면 이를 우선합니다. -- 완료 알림은 채널로 직접 전달되거나 다음 heartbeat를 위해 대기열에 들어갑니다. +- 작업은 스케줄러가 아니라 **기록**입니다 — cron과 하트비트는 작업이 _언제_ 실행될지 결정하고, 작업은 _무슨 일이 일어났는지_ 추적합니다. +- ACP, 하위 에이전트, 모든 cron 작업, 그리고 CLI 작업은 작업을 생성합니다. 하트비트 턴은 생성하지 않습니다. +- 각 작업은 `queued → running → terminal`(succeeded, failed, timed_out, cancelled, 또는 lost)을 거칩니다. +- cron 작업은 cron 런타임이 여전히 해당 작업을 소유하는 동안 활성 상태를 유지합니다. 채팅 기반 CLI 작업은 소유한 실행 컨텍스트가 여전히 활성 상태인 동안에만 활성 상태를 유지합니다. +- 완료는 푸시 기반입니다: 분리된 작업은 완료 시 직접 알리거나 요청자 세션/하트비트를 깨울 수 있으므로, 상태를 폴링하는 루프는 보통 적절한 방식이 아닙니다. +- 격리된 cron 실행과 하위 에이전트 완료는 최종 정리 기록을 남기기 전에 자식 세션의 추적된 브라우저 탭/프로세스를 최선의 노력으로 정리합니다. +- 격리된 cron 전달은 하위 하위 에이전트 작업이 아직 마무리 중일 때 오래된 중간 부모 응답을 억제하고, 전달 전에 최종 하위 결과가 도착하면 그것을 우선합니다. +- 완료 알림은 채널로 직접 전달되거나 다음 하트비트를 위해 대기열에 들어갑니다. - `openclaw tasks list`는 모든 작업을 표시하고, `openclaw tasks audit`는 문제를 표시합니다. -- 종료된 기록은 7일 동안 보관된 후 자동으로 정리됩니다. +- 종료된 기록은 7일간 보관된 뒤 자동으로 정리됩니다. ## 빠른 시작 @@ -50,48 +50,48 @@ openclaw tasks list openclaw tasks list --runtime acp openclaw tasks list --status running -# 특정 작업의 세부 정보 표시(ID, run ID 또는 session key로 조회) +# 특정 작업의 세부 정보 표시(ID, run ID, 또는 session key로) openclaw tasks show -# 실행 중인 작업 취소(하위 세션 종료) +# 실행 중인 작업 취소(자식 세션 종료) openclaw tasks cancel # 작업의 알림 정책 변경 openclaw tasks notify state_changes -# 상태 점검 실행 +# 상태 점검 감사 실행 openclaw tasks audit -# 유지 관리 미리보기 또는 적용 +# 유지 관리 미리 보기 또는 적용 openclaw tasks maintenance openclaw tasks maintenance --apply -# TaskFlow 상태 확인 +# TaskFlow 상태 검사 openclaw tasks flow list openclaw tasks flow show openclaw tasks flow cancel ``` -## 작업을 생성하는 것 +## 작업을 생성하는 항목 -| 소스 | 런타임 유형 | 작업 레코드가 생성되는 시점 | 기본 알림 정책 | -| ---------------------- | ----------- | ---------------------------------------------------- | -------------- | -| ACP 백그라운드 실행 | `acp` | 하위 ACP 세션 생성 시 | `done_only` | -| 하위 에이전트 오케스트레이션 | `subagent` | `sessions_spawn`를 통해 하위 에이전트 생성 시 | `done_only` | -| Cron 작업(모든 유형) | `cron` | 모든 cron 실행(주 세션 및 격리 실행) | `silent` | -| CLI 작업 | `cli` | 게이트웨이를 통해 실행되는 `openclaw agent` 명령 | `silent` | -| 에이전트 미디어 작업 | `cli` | 세션 기반 `video_generate` 실행 | `silent` | +| 소스 | 런타임 유형 | 작업 기록이 생성되는 시점 | 기본 알림 정책 | +| ---------------------- | ------------ | ------------------------------------------------------ | --------------------- | +| ACP 백그라운드 실행 | `acp` | 자식 ACP 세션 생성 시 | `done_only` | +| 하위 에이전트 오케스트레이션 | `subagent` | `sessions_spawn`를 통해 하위 에이전트 생성 시 | `done_only` | +| cron 작업(모든 유형) | `cron` | 모든 cron 실행(기본 세션 및 격리 실행) | `silent` | +| CLI 작업 | `cli` | 게이트웨이를 통해 실행되는 `openclaw agent` 명령 | `silent` | +| 에이전트 미디어 작업 | `cli` | 세션 기반 `video_generate` 실행 | `silent` | -주 세션 cron 작업은 기본적으로 `silent` 알림 정책을 사용합니다. 즉, 추적용 레코드는 만들지만 알림은 생성하지 않습니다. 격리된 cron 작업도 기본적으로 `silent`이지만 자체 세션에서 실행되므로 더 눈에 띕니다. +기본 세션 cron 작업은 기본적으로 `silent` 알림 정책을 사용합니다 — 추적을 위한 기록은 생성하지만 알림은 만들지 않습니다. 격리된 cron 작업도 기본값은 `silent`이지만 자체 세션에서 실행되므로 더 눈에 띕니다. -세션 기반 `video_generate` 실행도 `silent` 알림 정책을 사용합니다. 여전히 작업 레코드는 생성되지만, 완료는 내부 깨우기 형태로 원래 에이전트 세션에 되돌아가므로 에이전트가 후속 메시지를 작성하고 완성된 비디오를 직접 첨부할 수 있습니다. `tools.media.asyncCompletion.directSend`를 활성화하면, 비동기 `music_generate` 및 `video_generate` 완료는 먼저 채널에 직접 전달을 시도한 뒤, 실패하면 요청자 세션 깨우기 경로로 대체됩니다. +세션 기반 `video_generate` 실행도 `silent` 알림 정책을 사용합니다. 여전히 작업 기록은 생성하지만, 완료는 원래 에이전트 세션으로 내부 웨이크 형태로 되돌아가므로 에이전트가 직접 후속 메시지를 작성하고 완성된 비디오를 첨부할 수 있습니다. `tools.media.asyncCompletion.directSend`를 활성화하면 비동기 `music_generate` 및 `video_generate` 완료는 요청자 세션 웨이크 경로로 돌아가기 전에 먼저 채널 직접 전달을 시도합니다. -세션 기반 `video_generate` 작업이 아직 활성 상태인 동안에는 이 도구가 가드레일 역할도 수행합니다. 같은 세션에서 `video_generate`를 반복 호출하면 두 번째 동시 생성을 시작하는 대신 활성 작업 상태를 반환합니다. 에이전트 측에서 명시적인 진행 상황/상태 조회가 필요할 때는 `action: "status"`를 사용하세요. +세션 기반 `video_generate` 작업이 아직 활성 상태일 때 이 도구는 가드레일 역할도 합니다: 같은 세션에서 `video_generate`를 반복 호출하면 두 번째 동시 생성을 시작하는 대신 활성 작업 상태를 반환합니다. 에이전트 측에서 명시적인 진행 상황/상태 조회를 원할 때는 `action: "status"`를 사용하세요. -**작업을 생성하지 않는 것:** +**작업을 생성하지 않는 항목:** -- Heartbeat 턴 — 주 세션, [Heartbeat](/ko/gateway/heartbeat) 참고 -- 일반적인 대화형 채팅 턴 +- 하트비트 턴 — 기본 세션; [Heartbeat](/ko/gateway/heartbeat) 참조 +- 일반 대화형 채팅 턴 - 직접 `/command` 응답 ## 작업 수명 주기 @@ -102,56 +102,56 @@ stateDiagram-v2 queued --> running : 에이전트 시작 running --> succeeded : 정상 완료 running --> failed : 오류 - running --> timed_out : 시간 제한 초과 + running --> timed_out : 제한 시간 초과 running --> cancelled : 운영자가 취소 queued --> lost : 세션 사라짐 > 5분 running --> lost : 세션 사라짐 > 5분 ``` -| 상태 | 의미 | +| 상태 | 의미 | | ----------- | -------------------------------------------------------------------------- | -| `queued` | 생성되었으며 에이전트 시작 대기 중 | -| `running` | 에이전트 턴이 현재 실행 중 | -| `succeeded` | 성공적으로 완료됨 | -| `failed` | 오류와 함께 완료됨 | -| `timed_out` | 구성된 시간 제한을 초과함 | -| `cancelled` | 운영자가 `openclaw tasks cancel`을 통해 중지함 | -| `lost` | 5분 유예 기간 후 런타임이 권위 있는 백업 상태를 잃음 | +| `queued` | 생성되었으며, 에이전트 시작 대기 중 | +| `running` | 에이전트 턴이 현재 실행 중 | +| `succeeded` | 성공적으로 완료됨 | +| `failed` | 오류와 함께 완료됨 | +| `timed_out` | 구성된 제한 시간을 초과함 | +| `cancelled` | 운영자가 `openclaw tasks cancel`을 통해 중지함 | +| `lost` | 런타임이 5분 유예 기간 후 권위 있는 백킹 상태를 잃음 | -전환은 자동으로 발생합니다. 연결된 에이전트 실행이 끝나면 작업 상태도 그에 맞게 업데이트됩니다. +전환은 자동으로 발생합니다 — 연결된 에이전트 실행이 끝나면 작업 상태가 그에 맞게 업데이트됩니다. -`lost`는 런타임 인지형입니다. +`lost`는 런타임 인지형입니다: -- ACP 작업: 기반 ACP 하위 세션 메타데이터가 사라졌습니다. -- 하위 에이전트 작업: 대상 에이전트 저장소에서 기반 하위 세션이 사라졌습니다. -- Cron 작업: cron 런타임이 더 이상 해당 작업을 활성 상태로 추적하지 않습니다. -- CLI 작업: 격리된 하위 세션 작업은 하위 세션을 사용하고, 채팅 기반 CLI 작업은 대신 활성 실행 컨텍스트를 사용하므로 남아 있는 채널/그룹/직접 세션 행이 이들을 활성 상태로 유지하지는 않습니다. +- ACP 작업: 백킹 ACP 자식 세션 메타데이터가 사라졌습니다. +- 하위 에이전트 작업: 백킹 자식 세션이 대상 에이전트 저장소에서 사라졌습니다. +- cron 작업: cron 런타임이 더 이상 해당 작업을 활성 상태로 추적하지 않습니다. +- CLI 작업: 격리된 자식 세션 작업은 자식 세션을 사용하고, 채팅 기반 CLI 작업은 그 대신 활성 실행 컨텍스트를 사용하므로, 채널/그룹/다이렉트 세션 행이 남아 있어도 활성 상태로 유지되지 않습니다. ## 전달 및 알림 -작업이 종료 상태에 도달하면 OpenClaw가 알립니다. 전달 경로는 두 가지입니다. +작업이 종료 상태에 도달하면 OpenClaw가 알립니다. 전달 경로는 두 가지입니다: -**직접 전달** — 작업에 채널 대상(`requesterOrigin`)이 있으면 완료 메시지가 해당 채널(Telegram, Discord, Slack 등)로 바로 전송됩니다. 하위 에이전트 완료의 경우, OpenClaw는 가능한 경우 연결된 스레드/토픽 라우팅도 유지하며, 직접 전달을 포기하기 전에 요청자 세션의 저장된 경로(`lastChannel` / `lastTo` / `lastAccountId`)에서 누락된 `to` / 계정을 보완할 수 있습니다. +**직접 전달** — 작업에 채널 대상(`requesterOrigin`)이 있으면 완료 메시지가 해당 채널(Telegram, Discord, Slack 등)로 바로 전달됩니다. 하위 에이전트 완료의 경우, OpenClaw는 가능할 때 바인딩된 스레드/토픽 라우팅도 유지하며, 직접 전달을 포기하기 전에 요청자 세션에 저장된 라우트(`lastChannel` / `lastTo` / `lastAccountId`)에서 누락된 `to` / 계정을 채울 수 있습니다. -**세션 대기열 전달** — 직접 전달에 실패했거나 origin이 설정되지 않았으면, 업데이트는 요청자 세션의 시스템 이벤트로 대기열에 들어가며 다음 heartbeat에 표시됩니다. +**세션 대기열 전달** — 직접 전달에 실패했거나 origin이 설정되지 않았으면, 업데이트가 요청자 세션의 시스템 이벤트로 대기열에 들어가고 다음 하트비트에서 표시됩니다. -작업 완료는 즉시 heartbeat 깨우기를 트리거하므로 결과를 빠르게 확인할 수 있습니다. 다음 예약 heartbeat tick까지 기다릴 필요가 없습니다. +작업 완료는 즉시 하트비트 웨이크를 트리거하므로 결과를 빠르게 볼 수 있습니다 — 다음 예약된 하트비트 틱까지 기다릴 필요가 없습니다. -즉, 일반적인 워크플로는 푸시 기반입니다. 분리된 작업을 한 번 시작한 다음, 런타임이 완료 시 깨우거나 알리도록 두면 됩니다. 디버깅, 개입 또는 명시적 감사가 필요할 때만 작업 상태를 폴링하세요. +즉, 일반적인 워크플로는 푸시 기반입니다: 분리된 작업을 한 번 시작한 뒤 런타임이 완료 시 깨우거나 알리도록 두세요. 디버깅, 개입, 또는 명시적인 감사를 위해 필요할 때만 작업 상태를 폴링하세요. ### 알림 정책 -각 작업에 대해 어느 정도까지 알림을 받을지 제어합니다. +각 작업에 대해 얼마나 많은 알림을 받을지 제어합니다: -| 정책 | 전달되는 내용 | +| 정책 | 전달되는 내용 | | --------------------- | ----------------------------------------------------------------------- | -| `done_only` (기본값) | 종료 상태(succeeded, failed 등)만 전달 — **이것이 기본값입니다** | -| `state_changes` | 모든 상태 전환 및 진행 상황 업데이트 | -| `silent` | 아무것도 전달하지 않음 | +| `done_only` (기본값) | 종료 상태(succeeded, failed 등)만 — **이것이 기본값입니다** | +| `state_changes` | 모든 상태 전환 및 진행 상황 업데이트 | +| `silent` | 아무것도 없음 | -작업 실행 중에도 정책을 변경할 수 있습니다. +작업이 실행 중일 때 정책을 변경할 수 있습니다: ```bash openclaw tasks notify state_changes @@ -165,7 +165,7 @@ openclaw tasks notify state_changes openclaw tasks list [--runtime ] [--status ] [--json] ``` -출력 열: Task ID, Kind, Status, Delivery, Run ID, Child Session, Summary. +출력 열: 작업 ID, 종류, 상태, 전달, 실행 ID, 자식 세션, 요약. ### `tasks show` @@ -173,7 +173,7 @@ openclaw tasks list [--runtime ] [--status ] [--j openclaw tasks show ``` -조회 토큰은 task ID, run ID 또는 session key를 받을 수 있습니다. 타이밍, 전달 상태, 오류, 종료 요약을 포함한 전체 레코드를 표시합니다. +조회 토큰은 작업 ID, 실행 ID, 또는 세션 키를 받을 수 있습니다. 시간 정보, 전달 상태, 오류, 종료 요약을 포함한 전체 기록을 표시합니다. ### `tasks cancel` @@ -181,7 +181,7 @@ openclaw tasks show openclaw tasks cancel ``` -ACP 및 하위 에이전트 작업의 경우 하위 세션을 종료합니다. 상태는 `cancelled`로 전환되고 전달 알림이 전송됩니다. +ACP 및 하위 에이전트 작업의 경우 자식 세션을 종료합니다. CLI 추적 작업의 경우, 취소는 작업 레지스트리에 기록됩니다(별도의 자식 런타임 핸들은 없습니다). 상태는 `cancelled`로 전환되며, 해당하는 경우 전달 알림이 전송됩니다. ### `tasks notify` @@ -197,14 +197,14 @@ openclaw tasks audit [--json] 운영상 문제를 표시합니다. 문제가 감지되면 결과는 `openclaw status`에도 표시됩니다. -| 항목 | 심각도 | 트리거 | -| ------------------------- | ------ | --------------------------------------------------- | -| `stale_queued` | warn | 10분 이상 대기 상태 | -| `stale_running` | error | 30분 이상 실행 상태 | -| `lost` | error | 런타임 기반 작업 소유 상태가 사라짐 | -| `delivery_failed` | warn | 전달에 실패했고 알림 정책이 `silent`가 아님 | -| `missing_cleanup` | warn | 종료된 작업에 cleanup 타임스탬프가 없음 | -| `inconsistent_timestamps` | warn | 타임라인 위반(예: 시작 전에 종료됨) | +| 항목 | 심각도 | 트리거 | +| ------------------------- | -------- | ----------------------------------------------------- | +| `stale_queued` | warn | 10분 이상 queued 상태 | +| `stale_running` | error | 30분 이상 running 상태 | +| `lost` | error | 런타임 기반 작업 소유 상태가 사라짐 | +| `delivery_failed` | warn | 전달에 실패했고 알림 정책이 `silent`가 아님 | +| `missing_cleanup` | warn | 정리 타임스탬프가 없는 종료 작업 | +| `inconsistent_timestamps` | warn | 타임라인 위반(예: 시작 전에 종료됨) | ### `tasks maintenance` @@ -213,20 +213,20 @@ openclaw tasks maintenance [--json] openclaw tasks maintenance --apply [--json] ``` -이 명령은 작업 및 Task Flow 상태에 대한 조정, cleanup stamping, 정리를 미리 보거나 적용할 때 사용합니다. +이를 사용해 작업 및 Task Flow 상태에 대한 조정, 정리 타임스탬프 기록, 그리고 정리 작업을 미리 보거나 적용할 수 있습니다. -조정은 런타임 인지형입니다. +조정은 런타임 인지형입니다: -- ACP/하위 에이전트 작업은 기반 하위 세션을 확인합니다. -- Cron 작업은 cron 런타임이 여전히 해당 작업을 소유하는지 확인합니다. -- 채팅 기반 CLI 작업은 채팅 세션 행만이 아니라 소유한 활성 실행 컨텍스트를 확인합니다. +- ACP/하위 에이전트 작업은 백킹 자식 세션을 확인합니다. +- cron 작업은 cron 런타임이 여전히 해당 작업을 소유하는지 확인합니다. +- 채팅 기반 CLI 작업은 단순히 채팅 세션 행이 아니라 소유한 활성 실행 컨텍스트를 확인합니다. -완료 정리도 런타임 인지형입니다. +완료 정리도 런타임 인지형입니다: -- 하위 에이전트 완료 시 알림 정리가 계속되기 전에 하위 세션의 추적된 브라우저 탭/프로세스를 가능한 범위에서 닫습니다. -- 격리된 cron 완료 시 실행이 완전히 종료되기 전에 cron 세션의 추적된 브라우저 탭/프로세스를 가능한 범위에서 닫습니다. -- 격리된 cron 전달은 필요할 경우 하위 하위 에이전트 후속 작업이 끝날 때까지 기다리며, 이를 알리는 대신 오래된 부모 확인 텍스트를 억제합니다. -- 하위 에이전트 완료 전달은 최신의 표시 가능한 assistant 텍스트를 우선하며, 이것이 비어 있으면 정제된 최신 tool/toolResult 텍스트로 대체하고, 시간 초과만 발생한 tool-call 실행은 짧은 부분 진행 요약으로 축약될 수 있습니다. +- 하위 에이전트 완료는 알림 정리가 계속되기 전에 자식 세션의 추적된 브라우저 탭/프로세스를 최선의 노력으로 닫습니다. +- 격리된 cron 완료는 실행이 완전히 종료되기 전에 cron 세션의 추적된 브라우저 탭/프로세스를 최선의 노력으로 닫습니다. +- 격리된 cron 전달은 필요할 경우 하위 하위 에이전트 후속 작업이 마무리될 때까지 기다리고, 이를 알리는 대신 오래된 부모 확인 텍스트를 억제합니다. +- 하위 에이전트 완료 전달은 가장 최근의 표시 가능한 assistant 텍스트를 우선하며, 그것이 비어 있으면 정제된 최신 tool/toolResult 텍스트로 대체하고, 시간 초과만 발생한 도구 호출 실행은 짧은 부분 진행 요약으로 축약될 수 있습니다. - 정리 실패가 실제 작업 결과를 가리지는 않습니다. ### `tasks flow list|show|cancel` @@ -237,86 +237,86 @@ openclaw tasks flow show [--json] openclaw tasks flow cancel ``` -개별 백그라운드 작업 레코드 하나보다 오케스트레이션하는 Task Flow 자체가 더 중요할 때 이 명령을 사용하세요. +개별 백그라운드 작업 기록 하나보다 이를 오케스트레이션하는 Task Flow 자체가 더 중요할 때 사용하세요. ## 채팅 작업 보드(`/tasks`) -어떤 채팅 세션에서든 `/tasks`를 사용해 해당 세션에 연결된 백그라운드 작업을 볼 수 있습니다. 보드는 런타임, 상태, 타이밍, 진행 상황 또는 오류 세부 정보를 포함해 활성 및 최근 완료된 작업을 표시합니다. +아무 채팅 세션에서나 `/tasks`를 사용해 해당 세션에 연결된 백그라운드 작업을 볼 수 있습니다. 보드는 런타임, 상태, 시간 정보, 그리고 진행 상황 또는 오류 세부 정보와 함께 활성 작업 및 최근 완료된 작업을 표시합니다. -현재 세션에 표시 가능한 연결 작업이 없으면, `/tasks`는 에이전트 로컬 작업 수로 대체되어 다른 세션 세부 정보를 노출하지 않으면서도 개요를 확인할 수 있습니다. +현재 세션에 표시 가능한 연결 작업이 없으면, `/tasks`는 에이전트 로컬 작업 수로 대체되어 다른 세션의 세부 정보를 노출하지 않고도 개요를 계속 볼 수 있습니다. -전체 운영자 원장은 CLI `openclaw tasks list`를 사용하세요. +전체 운영자 원장을 보려면 CLI를 사용하세요: `openclaw tasks list`. ## 상태 통합(작업 압력) -`openclaw status`에는 한눈에 보는 작업 요약이 포함됩니다. +`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 인지형 작업 스냅샷을 사용합니다. 활성 작업이 우선되며, 오래된 완료 행은 숨겨지고, 최근 실패는 활성 작업이 없을 때만 표시됩니다. 이렇게 하면 상태 카드가 현재 중요한 사항에 집중됩니다. +`/status`와 `session_status` 도구는 모두 정리 상태를 인지하는 작업 스냅샷을 사용합니다: 활성 작업이 우선되며, 오래된 완료 행은 숨겨지고, 최근 실패는 활성 작업이 남아 있지 않을 때만 표시됩니다. 이렇게 하면 상태 카드가 지금 중요한 내용에 집중할 수 있습니다. ## 저장소 및 유지 관리 -### 작업 저장 위치 +### 작업이 저장되는 위치 -작업 레코드는 다음 SQLite에 영구 저장됩니다. +작업 기록은 다음 위치의 SQLite에 영속 저장됩니다: ``` $OPENCLAW_STATE_DIR/tasks/runs.sqlite ``` -레지스트리는 게이트웨이 시작 시 메모리에 로드되고, 재시작 후에도 내구성을 유지할 수 있도록 쓰기를 SQLite와 동기화합니다. +레지스트리는 게이트웨이 시작 시 메모리로 로드되며, 재시작 후에도 내구성을 보장하기 위해 쓰기 작업을 SQLite와 동기화합니다. ### 자동 유지 관리 -스위퍼가 **60초**마다 실행되며 세 가지를 처리합니다. +스위퍼가 **60초**마다 실행되며 세 가지를 처리합니다: -1. **조정** — 활성 작업에 여전히 권위 있는 런타임 백업이 있는지 확인합니다. ACP/하위 에이전트 작업은 하위 세션 상태를, cron 작업은 활성 작업 소유권을, 채팅 기반 CLI 작업은 소유한 실행 컨텍스트를 사용합니다. 이 백업 상태가 5분 이상 사라져 있으면 작업은 `lost`로 표시됩니다. -2. **Cleanup stamping** — 종료된 작업에 `cleanupAfter` 타임스탬프를 설정합니다(`endedAt + 7일`). -3. **정리** — `cleanupAfter` 날짜가 지난 레코드를 삭제합니다. +1. **조정** — 활성 작업이 여전히 권위 있는 런타임 백킹을 갖고 있는지 확인합니다. ACP/하위 에이전트 작업은 자식 세션 상태를 사용하고, cron 작업은 활성 작업 소유 상태를 사용하며, 채팅 기반 CLI 작업은 소유한 실행 컨텍스트를 사용합니다. 이 백킹 상태가 5분 이상 사라져 있으면 작업은 `lost`로 표시됩니다. +2. **정리 타임스탬프 기록** — 종료된 작업에 `cleanupAfter` 타임스탬프를 설정합니다(`endedAt + 7일`). +3. **정리** — `cleanupAfter` 날짜가 지난 기록을 삭제합니다. -**보관 기간**: 종료된 작업 레코드는 **7일** 동안 보관된 후 자동으로 정리됩니다. 별도의 설정은 필요하지 않습니다. +**보존 기간**: 종료된 작업 기록은 **7일** 동안 유지된 뒤 자동으로 정리됩니다. 별도 구성은 필요하지 않습니다. ## 작업이 다른 시스템과 연결되는 방식 ### 작업과 Task Flow -[Task Flow](/ko/automation/taskflow)는 백그라운드 작업 위에 있는 흐름 오케스트레이션 계층입니다. 하나의 flow는 수명 주기 동안 관리형 또는 미러링된 동기화 모드를 사용해 여러 작업을 조정할 수 있습니다. 개별 작업 레코드를 확인하려면 `openclaw tasks`를, 오케스트레이션 흐름을 확인하려면 `openclaw tasks flow`를 사용하세요. +[Task Flow](/ko/automation/taskflow)는 백그라운드 작업 위에 있는 플로우 오케스트레이션 계층입니다. 하나의 플로우는 수명 주기 동안 관리형 또는 미러링 동기화 모드를 사용해 여러 작업을 조정할 수 있습니다. 개별 작업 기록을 확인하려면 `openclaw tasks`를 사용하고, 오케스트레이션하는 플로우를 확인하려면 `openclaw tasks flow`를 사용하세요. -자세한 내용은 [Task Flow](/ko/automation/taskflow)를 참고하세요. +자세한 내용은 [Task Flow](/ko/automation/taskflow)를 참조하세요. ### 작업과 cron -cron 작업 **정의**는 `~/.openclaw/cron/jobs.json`에 있습니다. **모든** cron 실행은 작업 레코드를 생성합니다. 주 세션과 격리 실행 모두 해당됩니다. 주 세션 cron 작업은 기본적으로 `silent` 알림 정책을 사용하므로 알림을 생성하지 않고도 추적됩니다. +cron 작업 **정의**는 `~/.openclaw/cron/jobs.json`에 저장됩니다. **모든** cron 실행은 작업 기록을 생성합니다 — 기본 세션과 격리 실행 모두 해당됩니다. 기본 세션 cron 작업은 기본적으로 `silent` 알림 정책을 사용하므로 알림을 생성하지 않고 추적만 수행합니다. -[크론 작업](/ko/automation/cron-jobs)을 참고하세요. +[Cron Jobs](/ko/automation/cron-jobs)를 참조하세요. -### 작업과 heartbeat +### 작업과 하트비트 -Heartbeat 실행은 주 세션 턴이며 작업 레코드를 생성하지 않습니다. 작업이 완료되면 heartbeat 깨우기를 트리거해 결과를 신속히 확인할 수 있습니다. +하트비트 실행은 기본 세션 턴입니다 — 작업 기록을 생성하지 않습니다. 작업이 완료되면 결과를 빠르게 볼 수 있도록 하트비트 웨이크를 트리거할 수 있습니다. -[Heartbeat](/ko/gateway/heartbeat)를 참고하세요. +[Heartbeat](/ko/gateway/heartbeat)를 참조하세요. ### 작업과 세션 -작업은 `childSessionKey`(작업이 실행되는 위치)와 `requesterSessionKey`(작업을 시작한 주체)를 참조할 수 있습니다. 세션은 대화 컨텍스트이고, 작업은 그 위에서 동작 추적을 담당합니다. +작업은 `childSessionKey`(작업이 실행되는 위치)와 `requesterSessionKey`(작업을 시작한 주체)를 참조할 수 있습니다. 세션은 대화 컨텍스트이고, 작업은 그 위에서 이루어지는 활동 추적입니다. ### 작업과 에이전트 실행 -작업의 `runId`는 실제 작업을 수행하는 에이전트 실행과 연결됩니다. 에이전트 수명 주기 이벤트(시작, 종료, 오류)는 작업 상태를 자동으로 업데이트하므로, 수명 주기를 수동으로 관리할 필요가 없습니다. +작업의 `runId`는 작업을 수행하는 에이전트 실행에 연결됩니다. 에이전트 수명 주기 이벤트(시작, 종료, 오류)는 작업 상태를 자동으로 업데이트하므로 수명 주기를 수동으로 관리할 필요가 없습니다. ## 관련 문서 - [Automation & Tasks](/ko/automation) — 모든 자동화 메커니즘 한눈에 보기 -- [Task Flow](/ko/automation/taskflow) — 작업 위의 흐름 오케스트레이션 +- [Task Flow](/ko/automation/taskflow) — 작업 위의 플로우 오케스트레이션 - [Scheduled Tasks](/ko/automation/cron-jobs) — 백그라운드 작업 예약 -- [Heartbeat](/ko/gateway/heartbeat) — 주기적인 주 세션 턴 +- [Heartbeat](/ko/gateway/heartbeat) — 주기적인 기본 세션 턴 - [CLI: Tasks](/cli/index#tasks) — CLI 명령 참조 diff --git a/docs/ko/concepts/active-memory.md b/docs/ko/concepts/active-memory.md new file mode 100644 index 000000000..ade03b9a2 --- /dev/null +++ b/docs/ko/concepts/active-memory.md @@ -0,0 +1,580 @@ +--- +read_when: + - 활성 메모리가 무엇을 위한 것인지 이해하고 싶습니다 + - 대화형 에이전트에 활성 메모리를 켜고 싶습니다 + - 어디에서나 활성화하지 않고 활성 메모리 동작을 조정하고 싶습니다 +summary: 대화형 채팅 세션에 관련 메모리를 주입하는 plugin 소유 차단 메모리 하위 에이전트 +title: 활성 메모리 +x-i18n: + generated_at: "2026-04-10T05:59:51Z" + model: gpt-5.4 + provider: openai + source_hash: 6a51437df4ae4d9d57764601dfcfcdadb269e2895bf49dc82b9f496c1b3cb341 + source_path: concepts/active-memory.md + workflow: 15 +--- + +# 활성 메모리 + +활성 메모리는 적격한 대화형 세션에서 메인 응답 전에 실행되는 선택적 plugin 소유 차단 메모리 하위 에이전트입니다. + +이 기능이 존재하는 이유는 대부분의 메모리 시스템이 유능하지만 반응형이기 때문입니다. 메인 에이전트가 언제 메모리를 검색할지 결정하거나, 사용자가 "이걸 기억해" 또는 "메모리 검색해" 같은 말을 하길 기다립니다. 그 시점에는 메모리가 응답을 자연스럽게 느끼게 만들 수 있었던 순간이 이미 지나가 버립니다. + +활성 메모리는 메인 응답이 생성되기 전에 시스템이 관련 메모리를 노출할 수 있는 제한된 한 번의 기회를 제공합니다. + +## 이를 에이전트에 붙여 넣으세요 + +자체 포함형의 안전한 기본 설정으로 Active Memory를 활성화하려면 이것을 에이전트에 붙여 넣으세요: + +```json5 +{ + plugins: { + entries: { + "active-memory": { + enabled: true, + config: { + enabled: true, + agents: ["main"], + allowedChatTypes: ["direct"], + modelFallbackPolicy: "default-remote", + queryMode: "recent", + promptStyle: "balanced", + timeoutMs: 15000, + maxSummaryChars: 220, + persistTranscripts: false, + logging: true, + }, + }, + }, + }, +} +``` + +이 설정은 `main` 에이전트에 대해 plugin을 켜고, 기본적으로 direct-message 스타일 세션으로 제한하며, 먼저 현재 세션 모델을 상속하도록 하고, 명시적이거나 상속된 모델을 사용할 수 없는 경우에도 내장 원격 폴백을 허용합니다. + +그다음 게이트웨이를 다시 시작하세요: + +```bash +node scripts/run-node.mjs gateway --profile dev +``` + +대화에서 실시간으로 확인하려면: + +```text +/verbose on +``` + +## 활성 메모리 켜기 + +가장 안전한 설정은 다음과 같습니다: + +1. plugin 활성화 +2. 하나의 대화형 에이전트를 대상으로 지정 +3. 조정하는 동안에만 로깅 유지 + +`openclaw.json`에서 다음으로 시작하세요: + +```json5 +{ + plugins: { + entries: { + "active-memory": { + enabled: true, + config: { + agents: ["main"], + allowedChatTypes: ["direct"], + modelFallbackPolicy: "default-remote", + queryMode: "recent", + promptStyle: "balanced", + timeoutMs: 15000, + maxSummaryChars: 220, + persistTranscripts: false, + logging: true, + }, + }, + }, + }, +} +``` + +그런 다음 게이트웨이를 다시 시작하세요: + +```bash +node scripts/run-node.mjs gateway --profile dev +``` + +이 의미는 다음과 같습니다: + +- `plugins.entries.active-memory.enabled: true`는 plugin을 켭니다 +- `config.agents: ["main"]`는 `main` 에이전트만 활성 메모리에 옵트인합니다 +- `config.allowedChatTypes: ["direct"]`는 기본적으로 direct-message 스타일 세션에서만 활성 메모리를 유지합니다 +- `config.model`이 설정되지 않은 경우, 활성 메모리는 먼저 현재 세션 모델을 상속합니다 +- `config.modelFallbackPolicy: "default-remote"`는 명시적이거나 상속된 모델을 사용할 수 없을 때 기본값으로 내장 원격 폴백을 유지합니다 +- `config.promptStyle: "balanced"`는 `recent` 모드에 대해 기본 범용 프롬프트 스타일을 사용합니다 +- 활성 메모리는 여전히 적격한 대화형 지속 채팅 세션에서만 실행됩니다 + +## 확인하는 방법 + +활성 메모리는 모델에 숨겨진 시스템 컨텍스트를 주입합니다. 클라이언트에 원시 `...` 태그를 노출하지 않습니다. + +## 세션 토글 + +설정을 수정하지 않고 현재 채팅 세션에 대해 활성 메모리를 일시 중지하거나 다시 시작하려면 plugin 명령을 사용하세요: + +```text +/active-memory status +/active-memory off +/active-memory on +``` + +이것은 세션 범위입니다. +`plugins.entries.active-memory.enabled`, 에이전트 대상 지정 또는 기타 전역 설정은 변경하지 않습니다. + +명령이 설정을 기록하고 모든 세션에 대해 활성 메모리를 일시 중지하거나 다시 시작하게 하려면 명시적인 전역 형식을 사용하세요: + +```text +/active-memory status --global +/active-memory off --global +/active-memory on --global +``` + +전역 형식은 `plugins.entries.active-memory.config.enabled`를 기록합니다. 나중에 명령으로 활성 메모리를 다시 켤 수 있도록 `plugins.entries.active-memory.enabled`는 켜 둡니다. + +라이브 세션에서 활성 메모리가 무엇을 하는지 보고 싶다면 해당 세션에 대해 상세 모드를 켜세요: + +```text +/verbose on +``` + +상세 모드가 활성화되면 OpenClaw는 다음을 표시할 수 있습니다: + +- `Active Memory: ok 842ms recent 34 chars`와 같은 활성 메모리 상태 줄 +- `Active Memory Debug: Lemon pepper wings with blue cheese.`와 같은 읽기 쉬운 디버그 요약 + +이 줄들은 숨겨진 시스템 컨텍스트를 공급하는 동일한 활성 메모리 패스에서 파생되지만, 원시 프롬프트 마크업을 노출하는 대신 사람이 읽을 수 있도록 형식화됩니다. + +기본적으로 차단 메모리 하위 에이전트 전사는 임시이며 실행이 완료되면 삭제됩니다. + +예시 흐름: + +```text +/verbose on +어떤 윙을 주문해야 할까? +``` + +예상되는 표시 응답 형태: + +```text +...일반적인 어시스턴트 응답... + +🧩 Active Memory: ok 842ms recent 34 chars +🔎 Active Memory Debug: 블루치즈를 곁들인 레몬 페퍼 윙. +``` + +## 실행 시점 + +활성 메모리는 두 개의 게이트를 사용합니다: + +1. **설정 옵트인** + plugin이 활성화되어 있어야 하며, 현재 에이전트 ID가 + `plugins.entries.active-memory.config.agents`에 있어야 합니다. +2. **엄격한 런타임 적격성** + 활성화되고 대상이 지정된 경우에도 활성 메모리는 적격한 + 대화형 지속 채팅 세션에서만 실행됩니다. + +실제 규칙은 다음과 같습니다: + +```text +plugin 활성화 ++ +에이전트 ID 대상 지정 ++ +허용된 채팅 유형 ++ +적격한 대화형 지속 채팅 세션 += +활성 메모리 실행 +``` + +이 중 하나라도 실패하면 활성 메모리는 실행되지 않습니다. + +## 세션 유형 + +`config.allowedChatTypes`는 어떤 종류의 대화에서 Active Memory를 실행할 수 있는지 전체적으로 제어합니다. + +기본값은 다음과 같습니다: + +```json5 +allowedChatTypes: ["direct"] +``` + +즉, Active Memory는 기본적으로 direct-message 스타일 세션에서 실행되지만, group 또는 channel 세션에서는 명시적으로 옵트인하지 않는 한 실행되지 않습니다. + +예시: + +```json5 +allowedChatTypes: ["direct"] +``` + +```json5 +allowedChatTypes: ["direct", "group"] +``` + +```json5 +allowedChatTypes: ["direct", "group", "channel"] +``` + +## 실행 위치 + +활성 메모리는 플랫폼 전체 추론 기능이 아니라 대화 강화 기능입니다. + +| Surface | 활성 메모리 실행 여부 | +| ------------------------------------------------------------------- | ----------------------------------------------------- | +| Control UI / 웹 채팅 지속 세션 | 예, plugin이 활성화되어 있고 에이전트가 대상이면 실행 | +| 같은 지속 채팅 경로의 다른 대화형 채널 세션 | 예, plugin이 활성화되어 있고 에이전트가 대상이면 실행 | +| 헤드리스 원샷 실행 | 아니요 | +| 하트비트/백그라운드 실행 | 아니요 | +| 일반 내부 `agent-command` 경로 | 아니요 | +| 하위 에이전트/내부 헬퍼 실행 | 아니요 | + +## 사용해야 하는 이유 + +다음과 같은 경우 활성 메모리를 사용하세요: + +- 세션이 지속적이고 사용자 대상일 때 +- 에이전트가 검색할 만한 의미 있는 장기 메모리를 가지고 있을 때 +- 연속성과 개인화가 원시 프롬프트 결정성보다 더 중요할 때 + +특히 다음에 잘 맞습니다: + +- 안정적인 선호 +- 반복되는 습관 +- 자연스럽게 드러나야 하는 장기 사용자 컨텍스트 + +다음에는 적합하지 않습니다: + +- 자동화 +- 내부 워커 +- 원샷 API 작업 +- 숨겨진 개인화가 놀랍게 느껴질 수 있는 곳 + +## 동작 방식 + +런타임 형태는 다음과 같습니다: + +```mermaid +flowchart LR + U["사용자 메시지"] --> Q["메모리 쿼리 빌드"] + Q --> R["Active Memory 차단 메모리 하위 에이전트"] + R -->|NONE 또는 비어 있음| M["메인 응답"] + R -->|관련 요약| I["숨겨진 active_memory_plugin 시스템 컨텍스트 추가"] + I --> M["메인 응답"] +``` + +차단 메모리 하위 에이전트가 사용할 수 있는 것은 다음뿐입니다: + +- `memory_search` +- `memory_get` + +연결 상태가 약하면 `NONE`을 반환해야 합니다. + +## 쿼리 모드 + +`config.queryMode`는 차단 메모리 하위 에이전트가 얼마나 많은 대화를 볼지 제어합니다. + +## 프롬프트 스타일 + +`config.promptStyle`는 차단 메모리 하위 에이전트가 메모리를 반환할지 결정할 때 얼마나 적극적이거나 엄격할지 제어합니다. + +사용 가능한 스타일: + +- `balanced`: `recent` 모드용 범용 기본값 +- `strict`: 가장 덜 적극적임; 인접한 컨텍스트의 영향이 매우 적기를 원할 때 가장 적합 +- `contextual`: 연속성 친화성이 가장 높음; 대화 기록이 더 중요해야 할 때 가장 적합 +- `recall-heavy`: 더 약하지만 여전히 그럴듯한 일치에도 메모리를 더 기꺼이 노출함 +- `precision-heavy`: 일치가 명확하지 않으면 적극적으로 `NONE`을 선호함 +- `preference-only`: 즐겨찾기, 습관, 루틴, 취향, 반복되는 개인 사실에 최적화됨 + +`config.promptStyle`이 설정되지 않았을 때의 기본 매핑: + +```text +message -> strict +recent -> balanced +full -> contextual +``` + +`config.promptStyle`을 명시적으로 설정하면 그 재정의가 우선합니다. + +예시: + +```json5 +promptStyle: "preference-only" +``` + +## 모델 폴백 정책 + +`config.model`이 설정되지 않은 경우, Active Memory는 다음 순서로 모델을 확인하려고 합니다: + +```text +명시적 plugin 모델 +-> 현재 세션 모델 +-> 에이전트 기본 모델 +-> 선택적 내장 원격 폴백 +``` + +`config.modelFallbackPolicy`는 마지막 단계를 제어합니다. + +기본값: + +```json5 +modelFallbackPolicy: "default-remote" +``` + +다른 옵션: + +```json5 +modelFallbackPolicy: "resolved-only" +``` + +명시적이거나 상속된 모델을 사용할 수 없을 때 내장 원격 기본값으로 폴백하는 대신 Active Memory가 회상을 건너뛰게 하려면 `resolved-only`를 사용하세요. + +## 고급 이스케이프 해치 + +이 옵션들은 의도적으로 권장 설정에 포함되지 않았습니다. + +`config.thinking`은 차단 메모리 하위 에이전트의 사고 수준을 재정의할 수 있습니다: + +```json5 +thinking: "medium" +``` + +기본값: + +```json5 +thinking: "off" +``` + +이것을 기본으로 활성화하지 마세요. Active Memory는 응답 경로에서 실행되므로 추가 사고 시간은 사용자에게 보이는 지연 시간을 직접 증가시킵니다. + +`config.promptAppend`는 기본 Active Memory 프롬프트 뒤와 대화 컨텍스트 앞에 추가 운영자 지침을 더합니다: + +```json5 +promptAppend: "일회성 이벤트보다 안정적인 장기 선호를 우선하세요." +``` + +`config.promptOverride`는 기본 Active Memory 프롬프트를 대체합니다. OpenClaw는 그 뒤에 대화 컨텍스트를 계속 추가합니다: + +```json5 +promptOverride: "당신은 메모리 검색 에이전트입니다. NONE 또는 하나의 간결한 사용자 사실을 반환하세요." +``` + +프롬프트 커스터마이징은 의도적으로 다른 회상 계약을 테스트하는 경우가 아니라면 권장되지 않습니다. 기본 프롬프트는 메인 모델에 대해 `NONE` 또는 간결한 사용자 사실 컨텍스트를 반환하도록 조정되어 있습니다. + +### `message` + +최신 사용자 메시지만 전송됩니다. + +```text +최신 사용자 메시지만 +``` + +다음과 같은 경우 사용하세요: + +- 가장 빠른 동작을 원할 때 +- 안정적인 선호 회상에 가장 강한 편향을 원할 때 +- 후속 턴에 대화 컨텍스트가 필요 없을 때 + +권장 타임아웃: + +- `3000`~`5000`ms 정도에서 시작 + +### `recent` + +최신 사용자 메시지와 소량의 최근 대화 꼬리가 전송됩니다. + +```text +최근 대화 꼬리: +user: ... +assistant: ... +user: ... + +최신 사용자 메시지: +... +``` + +다음과 같은 경우 사용하세요: + +- 속도와 대화 맥락화 사이에서 더 나은 균형을 원할 때 +- 후속 질문이 종종 마지막 몇 턴에 의존할 때 + +권장 타임아웃: + +- `15000`ms 정도에서 시작 + +### `full` + +전체 대화가 차단 메모리 하위 에이전트로 전송됩니다. + +```text +전체 대화 컨텍스트: +user: ... +assistant: ... +user: ... +... +``` + +다음과 같은 경우 사용하세요: + +- 지연 시간보다 가장 강한 회상 품질이 더 중요할 때 +- 대화에 스레드 앞부분의 중요한 설정이 포함되어 있을 때 + +권장 타임아웃: + +- `message` 또는 `recent`보다 상당히 늘리세요 +- 스레드 크기에 따라 `15000`ms 이상에서 시작 + +일반적으로 타임아웃은 컨텍스트 크기에 따라 증가해야 합니다: + +```text +message < recent < full +``` + +## 전사 지속성 + +활성 메모리 차단 메모리 하위 에이전트 실행은 차단 메모리 하위 에이전트 호출 중 실제 `session.jsonl` 전사를 생성합니다. + +기본적으로 그 전사는 임시입니다: + +- 임시 디렉터리에 기록됩니다 +- 차단 메모리 하위 에이전트 실행에만 사용됩니다 +- 실행이 끝나면 즉시 삭제됩니다 + +디버깅이나 검토를 위해 이러한 차단 메모리 하위 에이전트 전사를 디스크에 유지하려면 지속성을 명시적으로 켜세요: + +```json5 +{ + plugins: { + entries: { + "active-memory": { + enabled: true, + config: { + agents: ["main"], + persistTranscripts: true, + transcriptDir: "active-memory", + }, + }, + }, + }, +} +``` + +활성화되면 활성 메모리는 메인 사용자 대화 전사 경로가 아니라 대상 에이전트의 세션 폴더 아래 별도 디렉터리에 전사를 저장합니다. + +기본 레이아웃의 개념은 다음과 같습니다: + +```text +agents//sessions/active-memory/.jsonl +``` + +상대 하위 디렉터리는 `config.transcriptDir`로 변경할 수 있습니다. + +이 기능은 주의해서 사용하세요: + +- 바쁜 세션에서는 차단 메모리 하위 에이전트 전사가 빠르게 누적될 수 있습니다 +- `full` 쿼리 모드는 많은 대화 컨텍스트를 중복할 수 있습니다 +- 이러한 전사에는 숨겨진 프롬프트 컨텍스트와 회상된 메모리가 포함됩니다 + +## 구성 + +모든 활성 메모리 구성은 다음 아래에 있습니다: + +```text +plugins.entries.active-memory +``` + +가장 중요한 필드는 다음과 같습니다: + +| Key | Type | 의미 | +| --------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | +| `enabled` | `boolean` | plugin 자체를 활성화합니다 | +| `config.agents` | `string[]` | 활성 메모리를 사용할 수 있는 에이전트 ID | +| `config.model` | `string` | 선택적 차단 메모리 하위 에이전트 모델 참조; 설정되지 않으면 활성 메모리는 현재 세션 모델을 사용합니다 | +| `config.queryMode` | `"message" \| "recent" \| "full"` | 차단 메모리 하위 에이전트가 얼마나 많은 대화를 볼지 제어합니다 | +| `config.promptStyle` | `"balanced" \| "strict" \| "contextual" \| "recall-heavy" \| "precision-heavy" \| "preference-only"` | 차단 메모리 하위 에이전트가 메모리를 반환할지 결정할 때 얼마나 적극적이거나 엄격할지 제어합니다 | +| `config.thinking` | `"off" \| "minimal" \| "low" \| "medium" \| "high" \| "xhigh" \| "adaptive"` | 차단 메모리 하위 에이전트용 고급 사고 재정의; 속도를 위해 기본값은 `off` | +| `config.promptOverride` | `string` | 고급 전체 프롬프트 대체; 일반적인 사용에는 권장되지 않음 | +| `config.promptAppend` | `string` | 기본 또는 재정의된 프롬프트에 추가되는 고급 추가 지침 | +| `config.timeoutMs` | `number` | 차단 메모리 하위 에이전트의 하드 타임아웃 | +| `config.maxSummaryChars` | `number` | active-memory 요약에 허용되는 총 최대 문자 수 | +| `config.logging` | `boolean` | 조정 중에 활성 메모리 로그를 출력합니다 | +| `config.persistTranscripts` | `boolean` | 임시 파일을 삭제하는 대신 차단 메모리 하위 에이전트 전사를 디스크에 유지합니다 | +| `config.transcriptDir` | `string` | 에이전트 세션 폴더 아래의 상대 차단 메모리 하위 에이전트 전사 디렉터리 | + +유용한 조정 필드: + +| Key | Type | 의미 | +| ----------------------------- | -------- | ------------------------------------------------------------- | +| `config.maxSummaryChars` | `number` | active-memory 요약에 허용되는 총 최대 문자 수 | +| `config.recentUserTurns` | `number` | `queryMode`가 `recent`일 때 포함할 이전 사용자 턴 수 | +| `config.recentAssistantTurns` | `number` | `queryMode`가 `recent`일 때 포함할 이전 어시스턴트 턴 수 | +| `config.recentUserChars` | `number` | 최근 사용자 턴당 최대 문자 수 | +| `config.recentAssistantChars` | `number` | 최근 어시스턴트 턴당 최대 문자 수 | +| `config.cacheTtlMs` | `number` | 반복되는 동일 쿼리에 대한 캐시 재사용 | + +## 권장 설정 + +`recent`로 시작하세요. + +```json5 +{ + plugins: { + entries: { + "active-memory": { + enabled: true, + config: { + agents: ["main"], + queryMode: "recent", + promptStyle: "balanced", + timeoutMs: 15000, + maxSummaryChars: 220, + logging: true, + }, + }, + }, + }, +} +``` + +조정하는 동안 라이브 동작을 확인하고 싶다면 별도의 active-memory 디버그 명령을 찾는 대신 세션에서 `/verbose on`을 사용하세요. + +그런 다음 다음으로 이동하세요: + +- 더 낮은 지연 시간을 원하면 `message` +- 추가 컨텍스트가 더 느린 차단 메모리 하위 에이전트의 가치가 있다고 판단되면 `full` + +## 디버깅 + +활성 메모리가 예상한 위치에 표시되지 않는다면: + +1. `plugins.entries.active-memory.enabled` 아래에서 plugin이 활성화되어 있는지 확인합니다. +2. 현재 에이전트 ID가 `config.agents`에 나열되어 있는지 확인합니다. +3. 대화형 지속 채팅 세션을 통해 테스트하고 있는지 확인합니다. +4. `config.logging: true`를 켜고 게이트웨이 로그를 확인합니다. +5. `openclaw memory status --deep`로 메모리 검색 자체가 작동하는지 검증합니다. + +메모리 적중이 너무 시끄럽다면 다음을 더 엄격하게 하세요: + +- `maxSummaryChars` + +활성 메모리가 너무 느리다면: + +- `queryMode`를 낮추기 +- `timeoutMs`를 낮추기 +- 최근 턴 수 줄이기 +- 턴당 문자 제한 줄이기 + +## 관련 페이지 + +- [메모리 검색](/ko/concepts/memory-search) +- [메모리 구성 참조](/ko/reference/memory-config) +- [Plugin SDK 설정](/ko/plugins/sdk-setup) diff --git a/docs/ko/concepts/memory-search.md b/docs/ko/concepts/memory-search.md index 6165e3950..c48bd52ec 100644 --- a/docs/ko/concepts/memory-search.md +++ b/docs/ko/concepts/memory-search.md @@ -1,26 +1,26 @@ --- read_when: - - '`memory_search`가 어떻게 작동하는지 이해하려는 경우' - - 임베딩 provider를 선택하려는 경우 - - 검색 품질을 조정하려는 경우 -summary: 메모리 검색이 임베딩과 하이브리드 검색을 사용해 관련 메모를 찾는 방법 + - memory_search가 어떻게 작동하는지 이해하고 싶습니다. + - 임베딩 공급자를 선택하고 싶습니다. + - 검색 품질을 조정하고 싶습니다. +summary: 메모리 검색은 임베딩과 하이브리드 검색을 사용해 관련 메모를 찾는 방식입니다. title: 메모리 검색 x-i18n: - generated_at: "2026-04-06T03:06:42Z" + generated_at: "2026-04-10T06:00:19Z" model: gpt-5.4 provider: openai - source_hash: b6541cd702bff41f9a468dad75ea438b70c44db7c65a4b793cbacaf9e583c7e9 + source_hash: ca0237f4f1ee69dcbfb12e6e9527a53e368c0bf9b429e506831d4af2f3a3ac6f source_path: concepts/memory-search.md workflow: 15 --- # 메모리 검색 -`memory_search`는 표현이 원문과 다르더라도 메모리 파일에서 관련 메모를 찾아냅니다. 이 기능은 메모리를 작은 청크로 인덱싱한 뒤, 임베딩, 키워드 또는 둘 다를 사용해 검색하는 방식으로 작동합니다. +`memory_search`는 원래 텍스트와 표현이 다르더라도 메모리 파일에서 관련 메모를 찾습니다. 이 기능은 메모리를 작은 청크로 인덱싱한 뒤, 임베딩, 키워드 또는 둘 다를 사용해 검색하는 방식으로 동작합니다. ## 빠른 시작 -OpenAI, Gemini, Voyage 또는 Mistral API 키가 구성되어 있으면 메모리 검색은 자동으로 작동합니다. provider를 명시적으로 설정하려면 다음을 사용하세요. +OpenAI, Gemini, Voyage 또는 Mistral API 키가 구성되어 있으면 메모리 검색은 자동으로 작동합니다. 공급자를 명시적으로 설정하려면 다음과 같이 하세요. ```json5 { @@ -36,21 +36,21 @@ OpenAI, Gemini, Voyage 또는 Mistral API 키가 구성되어 있으면 메모 API 키 없이 로컬 임베딩을 사용하려면 `provider: "local"`을 사용하세요(`node-llama-cpp` 필요). -## 지원되는 provider +## 지원되는 공급자 -| Provider | ID | API 키 필요 | 참고 | -| -------- | --------- | ----------- | ---- | -| OpenAI | `openai` | 예 | 자동 감지됨, 빠름 | -| Gemini | `gemini` | 예 | 이미지/오디오 인덱싱 지원 | -| Voyage | `voyage` | 예 | 자동 감지됨 | -| Mistral | `mistral` | 예 | 자동 감지됨 | -| Bedrock | `bedrock` | 아니요 | AWS 자격 증명 체인이 확인되면 자동 감지됨 | -| Ollama | `ollama` | 아니요 | 로컬, 명시적으로 설정해야 함 | -| Local | `local` | 아니요 | GGUF 모델, 약 0.6 GB 다운로드 | +| 공급자 | ID | API 키 필요 | 참고 | +| ------ | --------- | ----------- | ---------------------------------------------------- | +| OpenAI | `openai` | 예 | 자동 감지, 빠름 | +| Gemini | `gemini` | 예 | 이미지/오디오 인덱싱 지원 | +| Voyage | `voyage` | 예 | 자동 감지 | +| Mistral| `mistral` | 예 | 자동 감지 | +| Bedrock| `bedrock` | 아니요 | AWS 자격 증명 체인이 해석되면 자동 감지 | +| Ollama | `ollama` | 아니요 | 로컬, 명시적으로 설정해야 함 | +| Local | `local` | 아니요 | GGUF 모델, 약 0.6 GB 다운로드 필요 | ## 검색 작동 방식 -OpenClaw는 두 개의 검색 경로를 병렬로 실행하고 결과를 병합합니다. +OpenClaw는 두 개의 검색 경로를 병렬로 실행한 뒤 결과를 병합합니다. ```mermaid flowchart LR @@ -63,31 +63,31 @@ flowchart LR M --> R["Top Results"] ``` -- **벡터 검색**은 의미가 비슷한 메모를 찾습니다("gateway host"는 "OpenClaw를 실행하는 머신"과 일치). -- **BM25 키워드 검색**은 정확히 일치하는 항목을 찾습니다(ID, 오류 문자열, 구성 키). +- **벡터 검색**은 의미가 비슷한 메모를 찾습니다("gateway host"는 "the machine running OpenClaw"와 일치할 수 있습니다). +- **BM25 키워드 검색**은 정확히 일치하는 항목을 찾습니다(ID, 오류 문자열, 설정 키 등). 한 경로만 사용할 수 있는 경우(임베딩 없음 또는 FTS 없음), 다른 경로만 단독으로 실행됩니다. ## 검색 품질 개선 -메모 기록이 많은 경우, 두 가지 선택적 기능이 도움이 됩니다. +메모 기록이 많을 때 도움이 되는 선택적 기능 두 가지가 있습니다. ### 시간 감쇠 -오래된 메모는 순위 가중치가 점차 낮아져 최근 정보가 먼저 표시됩니다. -기본 반감기 30일에서는 지난달의 메모 점수가 원래 가중치의 50%가 됩니다. -`MEMORY.md` 같은 상시 유지 파일에는 감쇠가 적용되지 않습니다. +오래된 메모는 순위 가중치가 점차 낮아져 최근 정보가 먼저 노출됩니다. +기본 반감기 30일 기준으로 지난달의 메모는 원래 가중치의 50% 점수를 받습니다. +`MEMORY.md` 같은 상시 유효 파일에는 감쇠가 적용되지 않습니다. -에이전트에 수개월치 일일 메모가 있고 오래된 정보가 최근 컨텍스트보다 계속 더 높은 순위에 오른다면 시간 감쇠를 활성화하세요. +에이전트에 수개월치 일일 메모가 있고 오래된 정보가 최신 컨텍스트보다 계속 더 높은 순위에 오르면 시간 감쇠를 활성화하세요. ### MMR(다양성) -중복 결과를 줄입니다. 다섯 개의 메모가 모두 같은 라우터 구성을 언급하더라도, MMR은 상위 결과가 반복되지 않고 서로 다른 주제를 다루도록 보장합니다. +중복되는 결과를 줄입니다. 다섯 개의 메모가 모두 동일한 라우터 설정을 언급하더라도, MMR은 같은 내용이 반복되지 않도록 상위 결과가 서로 다른 주제를 다루게 합니다. -`memory_search`가 서로 다른 일일 메모에서 거의 중복된 스니펫을 계속 반환한다면 MMR을 활성화하세요. +`memory_search`가 서로 다른 일일 메모에서 거의 중복되는 스니펫을 계속 반환한다면 MMR을 활성화하세요. ### 둘 다 활성화 @@ -112,24 +112,23 @@ flowchart LR ## 멀티모달 메모리 Gemini Embedding 2를 사용하면 Markdown과 함께 이미지 및 오디오 파일도 인덱싱할 수 있습니다. -검색 쿼리는 여전히 텍스트이지만, 시각 및 오디오 콘텐츠와 일치합니다. +검색 질의는 여전히 텍스트이지만, 시각 및 오디오 콘텐츠와 매칭됩니다. 설정 방법은 [메모리 구성 참조](/ko/reference/memory-config)를 확인하세요. ## 세션 메모리 검색 -선택적으로 세션 대화록을 인덱싱하여 `memory_search`가 이전 대화를 회상할 수 있게 할 수 있습니다. -이는 `memorySearch.experimental.sessionMemory`를 통해 옵트인 방식으로 활성화합니다. -자세한 내용은 [구성 참조](/ko/reference/memory-config)를 확인하세요. +세션 대화 내용을 선택적으로 인덱싱해 `memory_search`가 이전 대화를 기억하도록 할 수 있습니다. 이 기능은 `memorySearch.experimental.sessionMemory`를 통해 옵트인 방식으로 활성화됩니다. 자세한 내용은 [구성 참조](/ko/reference/memory-config)를 확인하세요. ## 문제 해결 -**결과가 없나요?** 인덱스를 확인하려면 `openclaw memory status`를 실행하세요. 비어 있다면 `openclaw memory index --force`를 실행하세요. +**결과가 없나요?** `openclaw memory status`를 실행해 인덱스를 확인하세요. 비어 있다면 `openclaw memory index --force`를 실행하세요. -**키워드 일치만 나오나요?** 임베딩 provider가 구성되지 않았을 수 있습니다. `openclaw memory status --deep`를 확인하세요. +**키워드 일치만 되나요?** 임베딩 공급자가 구성되지 않았을 수 있습니다. `openclaw memory status --deep`로 확인하세요. -**CJK 텍스트를 찾을 수 없나요?** `openclaw memory index --force`로 FTS 인덱스를 다시 빌드하세요. +**CJK 텍스트가 검색되지 않나요?** `openclaw memory index --force`로 FTS 인덱스를 다시 빌드하세요. -## 추가 읽을거리 +## 더 읽어보기 -- [메모리](/ko/concepts/memory) -- 파일 레이아웃, 백엔드, 도구 -- [메모리 구성 참조](/ko/reference/memory-config) -- 모든 구성 옵션 +- [Active Memory](/ko/concepts/active-memory) -- 대화형 채팅 세션을 위한 서브 에이전트 메모리 +- [Memory](/ko/concepts/memory) -- 파일 레이아웃, 백엔드, 도구 +- [Memory configuration reference](/ko/reference/memory-config) -- 모든 구성 옵션 diff --git a/docs/ko/concepts/qa-e2e-automation.md b/docs/ko/concepts/qa-e2e-automation.md index dbe0b97d5..537a9f808 100644 --- a/docs/ko/concepts/qa-e2e-automation.md +++ b/docs/ko/concepts/qa-e2e-automation.md @@ -1,50 +1,51 @@ --- read_when: - - qa-lab 또는 qa-channel 확장 시 - - 리포지토리 기반 QA 시나리오 추가 시 - - Gateway 대시보드를 중심으로 더 높은 현실성의 QA 자동화 구축 시 -summary: qa-lab, qa-channel, 시드된 시나리오, 프로토콜 보고서를 위한 비공개 QA 자동화 구성 + - qa-lab 또는 qa-channel 확장하기 + - 리포지토리 기반 QA 시나리오 추가하기 + - Gateway 대시보드를 중심으로 더 현실적인 QA 자동화 구축하기 +summary: qa-lab, qa-channel, 시드된 시나리오, 프로토콜 보고서를 위한 비공개 QA 자동화 구조 title: QA E2E 자동화 x-i18n: - generated_at: "2026-04-09T01:27:48Z" + generated_at: "2026-04-10T05:59:51Z" model: gpt-5.4 provider: openai - source_hash: c922607d67e0f3a2489ac82bc9f510f7294ced039c1014c15b676d826441d833 + source_hash: 357d6698304ff7a8c4aa8a7be97f684d50f72b524740050aa761ac0ee68266de source_path: concepts/qa-e2e-automation.md workflow: 15 --- # QA E2E 자동화 -비공개 QA 스택은 단일 단위 테스트보다 더 현실적이고 -채널 형태에 가까운 방식으로 OpenClaw를 검증하도록 설계되었습니다. +비공개 QA 스택은 단일 단위 테스트보다 더 현실적이고, +채널 형태에 가까운 방식으로 OpenClaw를 검증하기 위한 것입니다. 현재 구성 요소: - `extensions/qa-channel`: DM, 채널, 스레드, 리액션, 편집, 삭제 인터페이스를 갖춘 합성 메시지 채널 -- `extensions/qa-lab`: 트랜스크립트를 관찰하고, - 인바운드 메시지를 주입하며, Markdown 보고서를 내보내기 위한 디버거 UI 및 QA 버스 +- `extensions/qa-lab`: 대화 기록을 관찰하고, + 인바운드 메시지를 주입하고, Markdown 보고서를 내보내기 위한 디버거 UI 및 QA 버스 - `qa/`: 시작 작업과 기본 QA 시나리오를 위한 리포지토리 기반 시드 자산 -현재 QA 운영자 흐름은 2패널 QA 사이트입니다: +현재 QA 운영자 흐름은 2개 패널로 구성된 QA 사이트입니다: - 왼쪽: 에이전트가 있는 Gateway 대시보드(Control UI) -- 오른쪽: Slack 스타일의 트랜스크립트와 시나리오 계획을 보여주는 QA Lab +- 오른쪽: Slack과 유사한 대화 기록과 시나리오 계획을 보여주는 QA Lab -다음으로 실행합니다: +다음 명령으로 실행합니다: ```bash pnpm qa:lab:up ``` -이 명령은 QA 사이트를 빌드하고, Docker 기반 gateway 레인을 시작하며, 운영자나 자동화 루프가 에이전트에 QA -미션을 부여하고, 실제 채널 동작을 관찰하며, 무엇이 작동했고 실패했으며 -또는 계속 막혀 있었는지를 기록할 수 있는 QA Lab 페이지를 노출합니다. +이 명령은 QA 사이트를 빌드하고, Docker 기반 Gateway 레인을 시작하며, +운영자 또는 자동화 루프가 에이전트에 QA +미션을 부여하고, 실제 채널 동작을 관찰하고, 무엇이 작동했고, 실패했고, 계속 막혀 있었는지 기록할 수 있는 +QA Lab 페이지를 노출합니다. -매번 Docker 이미지를 다시 빌드하지 않고 QA Lab UI를 더 빠르게 반복 개발하려면, -bind mount된 QA Lab 번들로 스택을 시작하세요: +매번 Docker 이미지를 다시 빌드하지 않고 더 빠르게 QA Lab UI를 반복 개발하려면, +바인드 마운트된 QA Lab 번들로 스택을 시작하세요: ```bash pnpm openclaw qa docker-build-image @@ -53,9 +54,24 @@ pnpm qa:lab:up:fast pnpm qa:lab:watch ``` -`qa:lab:up:fast`는 사전 빌드된 이미지에서 Docker 서비스를 유지하고 -`extensions/qa-lab/web/dist`를 `qa-lab` 컨테이너에 bind mount합니다. `qa:lab:watch`는 -변경 시 해당 번들을 다시 빌드하고, QA Lab 자산 해시가 변경되면 브라우저가 자동으로 다시 로드됩니다. +`qa:lab:up:fast`는 Docker 서비스를 사전 빌드된 이미지로 유지하고 +`extensions/qa-lab/web/dist`를 `qa-lab` 컨테이너에 바인드 마운트합니다. `qa:lab:watch`는 +변경 시 해당 번들을 다시 빌드하며, QA Lab 자산 해시가 바뀌면 브라우저가 자동으로 다시 로드됩니다. + +QA 경로에 Docker를 포함하지 않는 일회용 Linux VM 레인의 경우 다음을 실행하세요: + +```bash +pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline +``` + +이 명령은 새 Multipass 게스트를 부팅하고, 의존성을 설치하고, 게스트 내부에서 OpenClaw를 빌드하고, +`qa suite`를 실행한 다음, 일반 QA 보고서와 +요약을 다시 호스트의 `.artifacts/qa-e2e/...`로 복사합니다. +시나리오 선택 동작은 호스트에서의 `qa suite`와 동일하게 재사용합니다. +라이브 실행은 게스트에서 실용적으로 사용할 수 있는 지원 QA 인증 입력을 전달합니다: +환경 변수 기반 제공자 키, QA 라이브 제공자 구성 경로, +그리고 존재할 경우 `CODEX_HOME`입니다. 게스트가 +마운트된 워크스페이스를 통해 다시 쓸 수 있도록 `--output-dir`은 리포지토리 루트 아래에 유지하세요. ## 리포지토리 기반 시드 @@ -64,8 +80,9 @@ pnpm qa:lab:watch - `qa/scenarios/index.md` - `qa/scenarios/*.md` -이 파일들은 QA 계획이 사람과 -에이전트 모두에게 보이도록 의도적으로 git에 포함됩니다. 기본 목록은 다음을 포괄할 만큼 충분히 넓게 유지되어야 합니다: +이 항목들은 QA 계획이 사람과 +에이전트 모두에게 보이도록 의도적으로 git에 포함됩니다. 기본 목록은 다음을 포괄할 수 있을 만큼 +충분히 넓어야 합니다: - DM 및 채널 채팅 - 스레드 동작 @@ -73,22 +90,22 @@ pnpm qa:lab:watch - cron 콜백 - 메모리 회상 - 모델 전환 -- 서브에이전트 핸드오프 +- 하위 에이전트 핸드오프 - 리포지토리 읽기 및 문서 읽기 -- Lobster Invaders 같은 작은 빌드 작업 하나 +- Lobster Invaders와 같은 작은 빌드 작업 하나 ## 보고 `qa-lab`은 관찰된 버스 타임라인에서 Markdown 프로토콜 보고서를 내보냅니다. -보고서는 다음에 답해야 합니다: +이 보고서는 다음에 답해야 합니다: - 무엇이 작동했는가 - 무엇이 실패했는가 - 무엇이 계속 막혀 있었는가 - 어떤 후속 시나리오를 추가할 가치가 있는가 -캐릭터 및 스타일 검사를 위해 동일한 시나리오를 여러 라이브 모델 -ref에서 실행하고 판단된 Markdown 보고서를 작성하세요: +캐릭터 및 스타일 점검을 위해, 동일한 시나리오를 여러 라이브 모델 ref에 걸쳐 실행하고 +판정된 Markdown 보고서를 작성하세요: ```bash pnpm openclaw qa character-eval \ @@ -107,36 +124,38 @@ pnpm openclaw qa character-eval \ --judge-concurrency 16 ``` -이 명령은 Docker가 아니라 로컬 QA gateway 자식 프로세스를 실행합니다. 캐릭터 평가 -시나리오는 `SOUL.md`를 통해 페르소나를 설정한 다음, 채팅, 워크스페이스 도움말, 작은 파일 작업과 같은 -일반 사용자 턴을 실행해야 합니다. 후보 모델에는 자신이 평가되고 있다는 사실을 알려서는 안 됩니다. -이 명령은 각 전체 트랜스크립트를 보존하고, 기본 실행 통계를 기록한 뒤, judge 모델에 fast 모드와 -`xhigh` 추론을 사용해 자연스러움, 분위기, 유머를 기준으로 실행 결과의 순위를 매기도록 요청합니다. -제공자들을 비교할 때는 `--blind-judge-models`를 사용하세요. 이 경우 judge 프롬프트는 여전히 -모든 트랜스크립트와 실행 상태를 받지만, 후보 ref는 `candidate-01` 같은 중립적인 -레이블로 대체됩니다. 보고서는 파싱 후 순위를 실제 ref에 다시 매핑합니다. -후보 실행은 기본적으로 `high` thinking을 사용하며, 이를 지원하는 OpenAI 모델은 `xhigh`를 사용합니다. -특정 후보를 개별적으로 재정의하려면 -`--model provider/model,thinking=`을 사용하세요. `--thinking `은 여전히 전역 기본값을 설정하며, -기존의 `--model-thinking ` 형식도 호환성을 위해 유지됩니다. -OpenAI 후보 ref는 기본적으로 fast 모드를 사용하므로, 제공자가 이를 지원하는 경우 우선 처리됩니다. -단일 후보나 judge에 재정의가 필요하면 인라인으로 `,fast`, `,no-fast`, 또는 `,fast=false`를 추가하세요. -모든 후보 모델에 fast 모드를 강제로 적용하려는 경우에만 `--fast`를 전달하세요. 후보와 judge의 실행 시간은 -벤치마크 분석을 위해 보고서에 기록되지만, judge 프롬프트에는 속도로 순위를 매기지 말라고 명시되어 있습니다. -후보 및 judge 모델 실행은 모두 기본적으로 동시성 16을 사용합니다. -제공자 제한이나 로컬 gateway 부하 때문에 실행이 너무 불안정해지면 -`--concurrency` 또는 `--judge-concurrency`를 낮추세요. -후보 `--model`이 전달되지 않으면 character eval은 기본적으로 +이 명령은 Docker가 아니라 로컬 QA Gateway 자식 프로세스를 실행합니다. 캐릭터 평가 +시나리오는 `SOUL.md`를 통해 페르소나를 설정한 다음, 채팅, 워크스페이스 도움말, +작은 파일 작업과 같은 일반 사용자 턴을 실행해야 합니다. 후보 모델에는 +평가 중이라는 사실을 알려주면 안 됩니다. 이 명령은 각 전체 대화 기록을 보존하고, +기본 실행 통계를 기록한 다음, 판정 모델에 빠른 모드와 +`xhigh` 추론으로 실행 결과를 자연스러움, 분위기, 유머 기준으로 순위를 매기도록 요청합니다. +제공자 간 비교 시에는 `--blind-judge-models`를 사용하세요. 판정 프롬프트는 여전히 +모든 대화 기록과 실행 상태를 받지만, 후보 ref는 +`candidate-01` 같은 중립적인 레이블로 대체됩니다. 이후 보고서는 파싱 후 순위를 실제 ref에 다시 매핑합니다. +후보 실행은 기본적으로 `high` 추론을 사용하며, 이를 지원하는 OpenAI 모델의 경우 `xhigh`를 사용합니다. +특정 후보를 개별적으로 덮어쓰려면 +`--model provider/model,thinking=`을 사용하세요. `--thinking `은 여전히 +전역 대체값을 설정하며, 이전의 `--model-thinking ` 형식도 +호환성을 위해 유지됩니다. +OpenAI 후보 ref는 제공자가 지원하는 경우 우선 처리에 fast 모드를 사용하도록 기본 설정됩니다. +단일 후보 또는 판정자에 대해 재정의가 필요하면 인라인으로 `,fast`, `,no-fast`, 또는 `,fast=false`를 추가하세요. +모든 후보 모델에 fast 모드를 강제로 적용하려는 경우에만 `--fast`를 전달하세요. 후보 및 +판정 모델 실행 시간은 벤치마크 분석을 위해 보고서에 기록되지만, +판정 프롬프트에는 속도로 순위를 매기지 말라고 명시되어 있습니다. +후보 및 판정 모델 실행은 둘 다 기본 동시성 16을 사용합니다. 제공자 제한 또는 로컬 Gateway +부하로 인해 실행 결과에 노이즈가 너무 많다면 `--concurrency` 또는 `--judge-concurrency`를 낮추세요. +후보 `--model`이 전달되지 않으면, 캐릭터 평가는 기본적으로 `openai/gpt-5.4`, `openai/gpt-5.2`, `openai/gpt-5`, `anthropic/claude-opus-4-6`, `anthropic/claude-sonnet-4-6`, `zai/glm-5.1`, `moonshot/kimi-k2.5`, 그리고 `google/gemini-3.1-pro-preview`를 사용합니다. -`--judge-model`이 전달되지 않으면 judge는 기본적으로 +판정 `--judge-model`이 전달되지 않으면, 판정자는 기본적으로 `openai/gpt-5.4,thinking=xhigh,fast` 및 `anthropic/claude-opus-4-6,thinking=high`를 사용합니다. ## 관련 문서 - [테스트](/ko/help/testing) -- [QA 채널](/ko/channels/qa-channel) +- [QA Channel](/ko/channels/qa-channel) - [대시보드](/web/dashboard) diff --git a/docs/ko/gateway/configuration-reference.md b/docs/ko/gateway/configuration-reference.md index 38939dbbe..a28c1433d 100644 --- a/docs/ko/gateway/configuration-reference.md +++ b/docs/ko/gateway/configuration-reference.md @@ -1,70 +1,70 @@ --- read_when: - - 정확한 필드 수준 config 의미 체계나 기본값이 필요할 때 - - 채널, 모델, gateway 또는 도구 config 블록을 검증할 때 -summary: 핵심 OpenClaw 키, 기본값, 전용 하위 시스템 참조 링크를 위한 Gateway config 참조 + - 정확한 필드 수준의 구성 의미 또는 기본값이 필요합니다 + - 채널, 모델, 게이트웨이 또는 도구 구성 블록을 검증하고 있습니다 +summary: 핵심 OpenClaw 키, 기본값, 그리고 전용 하위 시스템 참조 링크를 위한 Gateway 구성 참조 title: 구성 참조 x-i18n: - generated_at: "2026-04-09T01:33:39Z" + generated_at: "2026-04-10T05:59:56Z" model: gpt-5.4 provider: openai - source_hash: a9d6d0c542b9874809491978fdcf8e1a7bb35a4873db56aa797963d03af4453c + source_hash: c6aa34e3a9096c4dabef26b9cdfda4bd7693e16da43a88c1641cfad8ba1ec237 source_path: gateway/configuration-reference.md workflow: 15 --- # 구성 참조 -`~/.openclaw/openclaw.json`용 핵심 config 참조입니다. 작업 중심 개요는 [Configuration](/ko/gateway/configuration)을 참고하세요. +`~/.openclaw/openclaw.json`용 핵심 구성 참조입니다. 작업 중심 개요는 [구성](/ko/gateway/configuration)을 참조하세요. -이 페이지는 주요 OpenClaw config 인터페이스를 다루며, 하위 시스템에 자체적으로 더 깊은 참조 문서가 있는 경우 해당 문서로 연결합니다. 이 페이지는 모든 채널/플러그인 소유 명령 카탈로그나 모든 심층 메모리/QMD 설정을 한 페이지에 인라인으로 넣으려는 것이 **아닙니다**. +이 페이지는 OpenClaw의 주요 구성 표면을 다루며, 하위 시스템에 더 깊은 자체 참조 문서가 있는 경우 해당 문서로 연결합니다. 이 페이지는 모든 채널/플러그인 소유 명령 카탈로그나 모든 심층 메모리/QMD 조정 항목을 한 페이지에 인라인으로 담으려는 목적이 **아닙니다**. -코드 기준 정보: +코드 기준 진실: -- `openclaw config schema`는 검증과 Control UI에 사용되는 실제 JSON Schema를 출력하며, 사용 가능한 경우 번들/플러그인/채널 메타데이터를 병합합니다 -- `config.schema.lookup`은 드릴다운 도구용으로 하나의 경로 범위 schema 노드를 반환합니다 -- `pnpm config:docs:check` / `pnpm config:docs:gen`은 현재 schema 인터페이스에 대해 config 문서 기준 해시를 검증합니다 +- `openclaw config schema`는 검증과 Control UI에 사용되는 현재 JSON 스키마를 출력하며, 사용 가능한 경우 번들/플러그인/채널 메타데이터가 병합됩니다 +- `config.schema.lookup`은 드릴다운 도구용으로 경로 범위가 지정된 단일 스키마 노드를 반환합니다 +- `pnpm config:docs:check` / `pnpm config:docs:gen`은 현재 스키마 표면에 대해 구성 문서 기준 해시를 검증합니다 전용 심화 참조: -- `agents.defaults.memorySearch.*`, `memory.qmd.*`, `memory.citations`, `plugins.entries.memory-core.config.dreaming` 아래 dreaming config에 대해서는 [Memory configuration reference](/ko/reference/memory-config) -- 현재 내장 + 번들 명령 카탈로그에 대해서는 [Slash Commands](/ko/tools/slash-commands) -- 채널별 명령 인터페이스에 대해서는 해당 채널/플러그인 페이지 +- `agents.defaults.memorySearch.*`, `memory.qmd.*`, `memory.citations`, 그리고 `plugins.entries.memory-core.config.dreaming` 아래의 dreaming 구성을 위한 [메모리 구성 참조](/ko/reference/memory-config) +- 현재 기본 제공 + 번들 명령 카탈로그를 위한 [슬래시 명령어](/ko/tools/slash-commands) +- 채널별 명령 표면을 위한 해당 채널/플러그인 페이지 -Config 형식은 **JSON5**입니다(주석 + 후행 쉼표 허용). 모든 필드는 선택 사항이며, 생략 시 OpenClaw가 안전한 기본값을 사용합니다. +구성 형식은 **JSON5**입니다(주석 + 후행 쉼표 허용). 모든 필드는 선택 사항이며, 생략하면 OpenClaw가 안전한 기본값을 사용합니다. --- ## 채널 -각 채널은 해당 config 섹션이 존재할 때 자동으로 시작됩니다(`enabled: false`가 아닌 한). +각 채널은 해당 구성 섹션이 존재하면 자동으로 시작됩니다(`enabled: false`인 경우 제외). -### DM 및 그룹 액세스 +### DM 및 그룹 접근 -모든 채널은 DM 정책과 그룹 정책을 지원합니다: +모든 채널은 DM 정책과 그룹 정책을 지원합니다. -| DM 정책 | 동작 | -| ------------------ | --------------------------------------------------------------- | -| `pairing` (기본값) | 알 수 없는 발신자는 일회성 페어링 코드를 받으며, 소유자가 승인해야 함 | -| `allowlist` | `allowFrom`(또는 페어링된 허용 저장소)에 있는 발신자만 허용 | -| `open` | 모든 인바운드 DM 허용(`allowFrom: ["*"]` 필요) | -| `disabled` | 모든 인바운드 DM 무시 | +| DM 정책 | 동작 | +| ------------------- | -------------------------------------------------------------- | +| `pairing` (기본값) | 알 수 없는 발신자는 1회용 페어링 코드를 받으며, 소유자가 승인해야 함 | +| `allowlist` | `allowFrom`(또는 페어링된 허용 저장소)에 있는 발신자만 허용 | +| `open` | 모든 수신 DM 허용(`allowFrom: ["*"]` 필요) | +| `disabled` | 모든 수신 DM 무시 | -| 그룹 정책 | 동작 | -| --------------------- | ------------------------------------------------------ | -| `allowlist` (기본값) | 구성된 허용 목록과 일치하는 그룹만 허용 | -| `open` | 그룹 허용 목록 우회(단, 멘션 게이팅은 계속 적용) | -| `disabled` | 모든 그룹/룸 메시지 차단 | +| 그룹 정책 | 동작 | +| ---------------------- | -------------------------------------------------------- | +| `allowlist` (기본값) | 구성된 허용 목록과 일치하는 그룹만 허용 | +| `open` | 그룹 허용 목록 우회(멘션 게이팅은 계속 적용됨) | +| `disabled` | 모든 그룹/룸 메시지 차단 | -`channels.defaults.groupPolicy`는 provider의 `groupPolicy`가 설정되지 않았을 때 기본값을 설정합니다. +`channels.defaults.groupPolicy`는 제공자의 `groupPolicy`가 설정되지 않았을 때 기본값을 설정합니다. 페어링 코드는 1시간 후 만료됩니다. 대기 중인 DM 페어링 요청은 **채널당 3개**로 제한됩니다. -provider 블록이 완전히 누락된 경우(`channels.` 없음), 런타임 그룹 정책은 시작 시 경고와 함께 `allowlist`(fail-closed)로 대체됩니다. +제공자 블록이 완전히 없으면(`channels.` 없음), 런타임 그룹 정책은 시작 시 경고와 함께 `allowlist`(실패 시 닫힘)로 대체됩니다. ### 채널 모델 재정의 -특정 채널 ID를 모델에 고정하려면 `channels.modelByChannel`을 사용하세요. 값은 `provider/model` 또는 구성된 모델 별칭을 받습니다. 이 채널 매핑은 세션에 이미 모델 재정의가 없는 경우에 적용됩니다(예: `/model`로 설정된 경우). +특정 채널 ID를 모델에 고정하려면 `channels.modelByChannel`을 사용하세요. 값은 `provider/model` 또는 구성된 모델 별칭을 허용합니다. 채널 매핑은 세션에 이미 모델 재정의가 없는 경우에 적용됩니다(예: `/model`로 설정한 경우). ```json5 { @@ -85,9 +85,9 @@ provider 블록이 완전히 누락된 경우(`channels.` 없음), 런 } ``` -### 채널 기본값과 하트비트 +### 채널 기본값 및 하트비트 -provider 전반에 걸쳐 공유되는 그룹 정책과 하트비트 동작에는 `channels.defaults`를 사용하세요: +제공자 간에 공유되는 그룹 정책 및 하트비트 동작에는 `channels.defaults`를 사용하세요. ```json5 { @@ -105,15 +105,15 @@ provider 전반에 걸쳐 공유되는 그룹 정책과 하트비트 동작에 } ``` -- `channels.defaults.groupPolicy`: provider 수준 `groupPolicy`가 설정되지 않았을 때 사용하는 대체 그룹 정책입니다. -- `channels.defaults.contextVisibility`: 모든 채널의 기본 보조 컨텍스트 표시 모드입니다. 값: `all`(기본값, 인용/스레드/이력 컨텍스트 모두 포함), `allowlist`(허용 목록의 발신자 컨텍스트만 포함), `allowlist_quote`(allowlist와 동일하지만 명시적 인용/답글 컨텍스트는 유지). 채널별 재정의: `channels..contextVisibility`. -- `channels.defaults.heartbeat.showOk`: 하트비트 출력에 정상 채널 상태를 포함합니다. -- `channels.defaults.heartbeat.showAlerts`: 하트비트 출력에 저하/오류 상태를 포함합니다. -- `channels.defaults.heartbeat.useIndicator`: 간결한 인디케이터 스타일 하트비트 출력을 렌더링합니다. +- `channels.defaults.groupPolicy`: 제공자 수준 `groupPolicy`가 설정되지 않았을 때의 대체 그룹 정책입니다. +- `channels.defaults.contextVisibility`: 모든 채널의 기본 보조 컨텍스트 표시 모드입니다. 값: `all`(기본값, 모든 인용/스레드/기록 컨텍스트 포함), `allowlist`(허용 목록에 있는 발신자의 컨텍스트만 포함), `allowlist_quote`(allowlist와 동일하지만 명시적 인용/답글 컨텍스트는 유지). 채널별 재정의: `channels..contextVisibility`. +- `channels.defaults.heartbeat.showOk`: 정상 채널 상태를 하트비트 출력에 포함합니다. +- `channels.defaults.heartbeat.showAlerts`: 성능 저하/오류 상태를 하트비트 출력에 포함합니다. +- `channels.defaults.heartbeat.useIndicator`: 간결한 표시기 스타일 하트비트 출력을 렌더링합니다. ### WhatsApp -WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결된 세션이 있으면 자동으로 시작됩니다. +WhatsApp은 게이트웨이의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결된 세션이 있으면 자동으로 시작됩니다. ```json5 { @@ -164,9 +164,9 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 } ``` -- 아웃바운드 명령은 `default` 계정이 있으면 기본적으로 해당 계정을 사용하고, 없으면 구성된 첫 번째 계정 ID(정렬 기준)를 사용합니다. -- 선택적 `channels.whatsapp.defaultAccount`는 구성된 계정 ID와 일치할 때 이 대체 기본 계정 선택을 재정의합니다. -- 기존 단일 계정 Baileys auth 디렉터리는 `openclaw doctor`에 의해 `whatsapp/default`로 마이그레이션됩니다. +- 발신 명령은 `default` 계정이 있으면 기본적으로 해당 계정을 사용하고, 없으면 첫 번째로 구성된 계정 ID(정렬된 순서)를 사용합니다. +- 선택적 `channels.whatsapp.defaultAccount`는 구성된 계정 ID와 일치할 때 그 대체 기본 계정 선택을 재정의합니다. +- 레거시 단일 계정 Baileys 인증 디렉터리는 `openclaw doctor`에 의해 `whatsapp/default`로 마이그레이션됩니다. - 계정별 재정의: `channels.whatsapp.accounts..sendReadReceipts`, `channels.whatsapp.accounts..dmPolicy`, `channels.whatsapp.accounts..allowFrom`. @@ -202,7 +202,7 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 historyLimit: 50, replyToMode: "first", // off | first | all | batched linkPreview: true, - streaming: "partial", // off | partial | block | progress (기본값: off, preview-edit 속도 제한을 피하려면 명시적으로 opt in) + streaming: "partial", // off | partial | block | progress (기본값: off, 미리보기 편집 속도 제한을 피하려면 명시적으로 opt in) actions: { reactions: true, sendMessage: true }, reactionNotifications: "own", // off | own | all mediaMaxMb: 100, @@ -225,13 +225,13 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 } ``` -- 봇 토큰: `channels.telegram.botToken` 또는 `channels.telegram.tokenFile`(일반 파일만 허용, 심볼릭 링크는 거부), 기본 계정에 대한 대체값으로 `TELEGRAM_BOT_TOKEN` 지원. +- 봇 토큰: `channels.telegram.botToken` 또는 `channels.telegram.tokenFile`(일반 파일만 허용, 심볼릭 링크는 거부), 기본 계정의 대체값으로 `TELEGRAM_BOT_TOKEN` 사용 가능. - 선택적 `channels.telegram.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. -- 다중 계정 설정(계정 ID 2개 이상)에서는 대체 라우팅을 피하기 위해 명시적 기본값(`channels.telegram.defaultAccount` 또는 `channels.telegram.accounts.default`)을 설정하세요. 이것이 누락되었거나 잘못된 경우 `openclaw doctor`가 경고합니다. -- `configWrites: false`는 Telegram에서 시작된 config 쓰기(supergroup ID 마이그레이션, `/config set|unset`)를 차단합니다. -- `type: "acp"`인 최상위 `bindings[]` 항목은 포럼 토픽용 영구 ACP 바인딩을 구성합니다(`match.peer.id`에 정식 `chatId:topic:topicId` 사용). 필드 의미는 [ACP Agents](/ko/tools/acp-agents#channel-specific-settings)와 공유됩니다. -- Telegram 스트림 미리보기는 `sendMessage` + `editMessageText`를 사용합니다(직접 채팅과 그룹 채팅 모두에서 동작). -- 재시도 정책: [Retry policy](/ko/concepts/retry) 참고. +- 다중 계정 설정(계정 ID 2개 이상)에서는 대체 라우팅을 피하기 위해 명시적인 기본값(`channels.telegram.defaultAccount` 또는 `channels.telegram.accounts.default`)을 설정하세요. 이것이 없거나 유효하지 않으면 `openclaw doctor`가 경고합니다. +- `configWrites: false`는 Telegram에서 시작된 구성 쓰기(supergroup ID 마이그레이션, `/config set|unset`)를 차단합니다. +- `type: "acp"`인 최상위 `bindings[]` 항목은 포럼 토픽용 영구 ACP 바인딩을 구성합니다(`match.peer.id`에는 정식 `chatId:topic:topicId` 사용). 필드 의미는 [ACP Agents](/ko/tools/acp-agents#channel-specific-settings)에서 공통으로 정의됩니다. +- Telegram 스트림 미리보기는 `sendMessage` + `editMessageText`를 사용합니다(직접 채팅과 그룹 채팅 모두에서 작동). +- 재시도 정책: [재시도 정책](/ko/concepts/retry)을 참조하세요. ### Discord @@ -333,36 +333,36 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 } ``` -- 토큰: `channels.discord.token`, 기본 계정에 대한 대체값으로 `DISCORD_BOT_TOKEN` 지원. -- 명시적 Discord `token`을 제공하는 직접 아웃바운드 호출은 해당 토큰을 호출에 사용하며, 계정 재시도/정책 설정은 여전히 활성 런타임 스냅샷에서 선택된 계정에서 가져옵니다. +- 토큰: `channels.discord.token`, 기본 계정의 대체값으로 `DISCORD_BOT_TOKEN` 사용 가능. +- 명시적인 Discord `token`을 제공하는 직접 발신 호출은 해당 호출에 그 토큰을 사용합니다. 계정 재시도/정책 설정은 여전히 활성 런타임 스냅샷에서 선택된 계정에서 가져옵니다. - 선택적 `channels.discord.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. -- 전달 대상에는 `user:`(DM) 또는 `channel:`(guild 채널)를 사용하세요. 숫자 ID만 단독으로 쓰는 것은 거부됩니다. -- Guild slug는 소문자이며 공백이 `-`로 바뀝니다. 채널 키는 slug 처리된 이름을 사용합니다(`#` 없음). guild ID 사용을 권장합니다. -- 봇이 작성한 메시지는 기본적으로 무시됩니다. `allowBots: true`로 활성화할 수 있고, `allowBots: "mentions"`는 봇을 멘션한 봇 메시지만 허용합니다(자체 메시지는 계속 필터링됨). -- `channels.discord.guilds..ignoreOtherMentions`(및 채널 재정의)는 봇을 멘션하지 않고 다른 사용자나 역할을 멘션한 메시지를 버립니다(@everyone/@here 제외). -- `maxLinesPerMessage`(기본값 17)는 2000자 미만이어도 세로로 긴 메시지를 분할합니다. -- `channels.discord.threadBindings`는 Discord 스레드 바인딩 라우팅을 제어합니다: - - `enabled`: 스레드 바인딩 세션 기능(`/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`, 바인딩 전달/라우팅)에 대한 Discord 재정의 - - `idleHours`: 비활성 자동 unfocus에 대한 Discord 재정의(시간 단위, `0`은 비활성화) - - `maxAgeHours`: 하드 최대 사용 기간에 대한 Discord 재정의(시간 단위, `0`은 비활성화) - - `spawnSubagentSessions`: `sessions_spawn({ thread: true })` 자동 스레드 생성/바인딩을 위한 opt-in 스위치 -- `type: "acp"`인 최상위 `bindings[]` 항목은 채널과 스레드에 대한 영구 ACP 바인딩을 구성합니다(`match.peer.id`에 채널/스레드 ID 사용). 필드 의미는 [ACP Agents](/ko/tools/acp-agents#channel-specific-settings)와 공유됩니다. +- 전달 대상에는 `user:`(DM) 또는 `channel:`(길드 채널)를 사용하세요. 숫자 ID만 단독으로 쓰면 거부됩니다. +- 길드 슬러그는 소문자이며 공백은 `-`로 바뀝니다. 채널 키는 슬러그화된 이름을 사용합니다(`#` 없음). 길드 ID 사용을 권장합니다. +- 봇이 작성한 메시지는 기본적으로 무시됩니다. `allowBots: true`로 이를 활성화할 수 있으며, `allowBots: "mentions"`를 사용하면 봇을 멘션하는 봇 메시지만 수락합니다(자체 메시지는 여전히 필터링됨). +- `channels.discord.guilds..ignoreOtherMentions`(및 채널 재정의)는 봇은 멘션하지 않고 다른 사용자나 역할을 멘션한 메시지를 삭제합니다(`@everyone`/`@here` 제외). +- `maxLinesPerMessage`(기본값 17)는 메시지가 2000자 미만이어도 줄 수가 많으면 분할합니다. +- `channels.discord.threadBindings`는 Discord 스레드 바인딩 라우팅을 제어합니다. + - `enabled`: 스레드 바인딩 세션 기능(`/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`, 그리고 바인딩된 전달/라우팅)에 대한 Discord 재정의 + - `idleHours`: 비활성 자동 포커스 해제 시간(시간 단위)에 대한 Discord 재정의(`0`은 비활성화) + - `maxAgeHours`: 하드 최대 수명 시간(시간 단위)에 대한 Discord 재정의(`0`은 비활성화) + - `spawnSubagentSessions`: `sessions_spawn({ thread: true })` 자동 스레드 생성/바인딩에 대한 opt-in 스위치 +- `type: "acp"`인 최상위 `bindings[]` 항목은 채널과 스레드에 대한 영구 ACP 바인딩을 구성합니다(`match.peer.id`에 채널/스레드 ID 사용). 필드 의미는 [ACP Agents](/ko/tools/acp-agents#channel-specific-settings)에서 공통으로 정의됩니다. - `channels.discord.ui.components.accentColor`는 Discord components v2 컨테이너의 강조 색상을 설정합니다. - `channels.discord.voice`는 Discord 음성 채널 대화와 선택적 자동 참가 + TTS 재정의를 활성화합니다. -- `channels.discord.voice.daveEncryption` 및 `channels.discord.voice.decryptionFailureTolerance`는 `@discordjs/voice` DAVE 옵션에 그대로 전달됩니다(기본값 각각 `true`, `24`). -- OpenClaw는 또한 반복되는 복호화 실패 후 음성 세션을 나갔다가 다시 참가하는 방식으로 음성 수신 복구를 시도합니다. -- `channels.discord.streaming`은 정식 스트림 모드 키입니다. 기존 `streamMode` 및 불리언 `streaming` 값은 자동 마이그레이션됩니다. -- `channels.discord.autoPresence`는 런타임 가용성을 봇 presence에 매핑하며(정상 => online, 저하 => idle, 소진 => dnd), 선택적 상태 텍스트 재정의를 허용합니다. -- `channels.discord.dangerouslyAllowNameMatching`는 변경 가능한 이름/태그 매칭을 다시 활성화합니다(비상 호환 모드). +- `channels.discord.voice.daveEncryption` 및 `channels.discord.voice.decryptionFailureTolerance`는 `@discordjs/voice` DAVE 옵션에 그대로 전달됩니다(기본값은 각각 `true`와 `24`). +- OpenClaw는 또한 반복적인 복호화 실패 후 음성 세션을 나갔다가 다시 참가하여 음성 수신 복구를 시도합니다. +- `channels.discord.streaming`은 정식 스트림 모드 키입니다. 레거시 `streamMode` 및 불리언 `streaming` 값은 자동 마이그레이션됩니다. +- `channels.discord.autoPresence`는 런타임 가용성을 봇 상태에 매핑합니다(정상 => online, 성능 저하 => idle, 소진 => dnd). 선택적 상태 텍스트 재정의도 허용합니다. +- `channels.discord.dangerouslyAllowNameMatching`는 변경 가능한 이름/태그 매칭을 다시 활성화합니다(비상 호환성 모드). - `channels.discord.execApprovals`: Discord 네이티브 exec 승인 전달 및 승인자 권한 부여. - - `enabled`: `true`, `false`, 또는 `"auto"`(기본값). auto 모드에서는 `approvers` 또는 `commands.ownerAllowFrom`에서 승인자를 해결할 수 있을 때 exec 승인이 활성화됩니다. - - `approvers`: exec 요청을 승인할 수 있는 Discord 사용자 ID입니다. 생략 시 `commands.ownerAllowFrom`으로 대체됩니다. - - `agentFilter`: 선택적 에이전트 ID 허용 목록. 생략하면 모든 에이전트의 승인 요청을 전달합니다. - - `sessionFilter`: 선택적 세션 키 패턴(부분 문자열 또는 regex). - - `target`: 승인 프롬프트를 보낼 위치입니다. `"dm"`(기본값)은 승인자 DM으로 보내고, `"channel"`은 원래 채널로 보내며, `"both"`는 둘 다 보냅니다. target에 `"channel"`이 포함되면 버튼은 해결된 승인자만 사용할 수 있습니다. - - `cleanupAfterResolve`: `true`일 때 승인, 거부, 타임아웃 후 승인 DM을 삭제합니다. + - `enabled`: `true`, `false`, 또는 `"auto"`(기본값). 자동 모드에서는 `approvers` 또는 `commands.ownerAllowFrom`에서 승인자를 확인할 수 있으면 exec 승인이 활성화됩니다. + - `approvers`: exec 요청을 승인할 수 있는 Discord 사용자 ID입니다. 생략하면 `commands.ownerAllowFrom`으로 대체됩니다. + - `agentFilter`: 선택적 에이전트 ID 허용 목록입니다. 생략하면 모든 에이전트의 승인을 전달합니다. + - `sessionFilter`: 선택적 세션 키 패턴(부분 문자열 또는 정규식)입니다. + - `target`: 승인 프롬프트를 보낼 위치입니다. `"dm"`(기본값)은 승인자 DM으로 보내고, `"channel"`은 원래 채널로 보내며, `"both"`는 둘 다로 보냅니다. 대상에 `"channel"`이 포함되면 버튼은 확인된 승인자만 사용할 수 있습니다. + - `cleanupAfterResolve`: `true`이면 승인, 거부 또는 시간 초과 후 승인 DM을 삭제합니다. -**리액션 알림 모드:** `off`(없음), `own`(봇 메시지, 기본값), `all`(모든 메시지), `allowlist`(`guilds..users`의 사용자를 모든 메시지에 적용). +**반응 알림 모드:** `off`(없음), `own`(봇의 메시지, 기본값), `all`(모든 메시지), `allowlist`(모든 메시지에서 `guilds..users` 기준). ### Google Chat @@ -393,11 +393,11 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 } ``` -- 서비스 계정 JSON: 인라인(`serviceAccount`) 또는 파일 기반(`serviceAccountFile`)을 지원합니다. +- 서비스 계정 JSON: 인라인(`serviceAccount`) 또는 파일 기반(`serviceAccountFile`)입니다. - 서비스 계정 SecretRef도 지원됩니다(`serviceAccountRef`). - 환경 변수 대체값: `GOOGLE_CHAT_SERVICE_ACCOUNT` 또는 `GOOGLE_CHAT_SERVICE_ACCOUNT_FILE`. - 전달 대상에는 `spaces/` 또는 `users/`를 사용하세요. -- `channels.googlechat.dangerouslyAllowNameMatching`는 변경 가능한 이메일 principal 매칭을 다시 활성화합니다(비상 호환 모드). +- `channels.googlechat.dangerouslyAllowNameMatching`는 변경 가능한 이메일 프린시펄 매칭을 다시 활성화합니다(비상 호환성 모드). ### Slack @@ -464,36 +464,30 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 } ``` -- **Socket mode**는 `botToken`과 `appToken` 둘 다 필요합니다(기본 계정 환경 변수 대체값으로 `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN`). -- **HTTP mode**는 `botToken`과 `signingSecret`(루트 또는 계정별)이 필요합니다. -- `botToken`, `appToken`, `signingSecret`, `userToken`은 일반 텍스트 - 문자열 또는 SecretRef 객체를 받을 수 있습니다. -- Slack 계정 스냅샷은 - `botTokenSource`, `botTokenStatus`, `appTokenStatus`, 그리고 HTTP 모드의 경우 - `signingSecretStatus`와 같은 자격 증명별 소스/상태 필드를 노출합니다. - `configured_unavailable`는 해당 계정이 - SecretRef를 통해 구성되었지만 현재 명령/런타임 경로에서 - 비밀값을 해결할 수 없었음을 의미합니다. -- `configWrites: false`는 Slack에서 시작된 config 쓰기를 차단합니다. +- **Socket 모드**는 `botToken`과 `appToken` 둘 다 필요합니다(기본 계정 환경 변수 대체값은 `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN`). +- **HTTP 모드**는 `botToken`과 `signingSecret`(루트 또는 계정별)이 필요합니다. +- `botToken`, `appToken`, `signingSecret`, `userToken`은 일반 텍스트 문자열 또는 SecretRef 객체를 허용합니다. +- Slack 계정 스냅샷은 `botTokenSource`, `botTokenStatus`, `appTokenStatus`, 그리고 HTTP 모드에서는 `signingSecretStatus` 같은 자격 증명별 출처/상태 필드를 노출합니다. `configured_unavailable`는 계정이 SecretRef를 통해 구성되었지만 현재 명령/런타임 경로에서 비밀값을 확인할 수 없음을 의미합니다. +- `configWrites: false`는 Slack에서 시작된 구성 쓰기를 차단합니다. - 선택적 `channels.slack.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. -- `channels.slack.streaming.mode`는 정식 Slack 스트림 모드 키입니다. `channels.slack.streaming.nativeTransport`는 Slack의 네이티브 스트리밍 전송을 제어합니다. 기존 `streamMode`, 불리언 `streaming`, `nativeStreaming` 값은 자동 마이그레이션됩니다. +- `channels.slack.streaming.mode`는 정식 Slack 스트림 모드 키입니다. `channels.slack.streaming.nativeTransport`는 Slack의 네이티브 스트리밍 전송을 제어합니다. 레거시 `streamMode`, 불리언 `streaming`, `nativeStreaming` 값은 자동 마이그레이션됩니다. - 전달 대상에는 `user:`(DM) 또는 `channel:`를 사용하세요. -**리액션 알림 모드:** `off`, `own`(기본값), `all`, `allowlist`(`reactionAllowlist` 기준). +**반응 알림 모드:** `off`, `own`(기본값), `all`, `allowlist`(`reactionAllowlist` 기준). -**스레드 세션 격리:** `thread.historyScope`는 스레드별(기본값) 또는 채널 전체 공유입니다. `thread.inheritParent`는 부모 채널 트랜스크립트를 새 스레드에 복사합니다. +**스레드 세션 격리:** `thread.historyScope`는 스레드별(기본값) 또는 채널 전체 공유입니다. `thread.inheritParent`는 상위 채널 대화를 새 스레드에 복사합니다. -- Slack 네이티브 스트리밍과 Slack assistant 스타일 `"is typing..."` 스레드 상태는 답글 스레드 대상을 필요로 합니다. 최상위 DM은 기본적으로 스레드 밖이므로, 스레드 스타일 미리보기 대신 `typingReaction` 또는 일반 전달을 사용합니다. -- `typingReaction`은 답글이 실행되는 동안 인바운드 Slack 메시지에 임시 리액션을 추가하고 완료 시 제거합니다. `"hourglass_flowing_sand"` 같은 Slack 이모지 shortcode를 사용하세요. -- `channels.slack.execApprovals`: Slack 네이티브 exec 승인 전달 및 승인자 권한 부여. Discord와 동일한 schema를 사용합니다: `enabled` (`true`/`false`/`"auto"`), `approvers` (Slack 사용자 ID), `agentFilter`, `sessionFilter`, `target` (`"dm"`, `"channel"`, 또는 `"both"`). +- Slack 네이티브 스트리밍과 Slack assistant 스타일의 "is typing..." 스레드 상태는 답글 스레드 대상을 필요로 합니다. 최상위 DM은 기본적으로 스레드 밖이므로, 스레드 스타일 미리보기 대신 `typingReaction` 또는 일반 전달을 사용합니다. +- `typingReaction`은 답글이 실행되는 동안 수신된 Slack 메시지에 임시 반응을 추가하고, 완료 시 제거합니다. `"hourglass_flowing_sand"` 같은 Slack 이모지 쇼트코드를 사용하세요. +- `channels.slack.execApprovals`: Slack 네이티브 exec 승인 전달 및 승인자 권한 부여. Discord와 동일한 스키마입니다: `enabled`(`true`/`false`/`"auto"`), `approvers`(Slack 사용자 ID), `agentFilter`, `sessionFilter`, `target`(`"dm"`, `"channel"`, 또는 `"both"`). -| 액션 그룹 | 기본값 | 참고 사항 | -| --------- | ------- | ----------------------- | -| reactions | 활성화 | 리액션 추가 + 목록 조회 | -| messages | 활성화 | 읽기/보내기/수정/삭제 | -| pins | 활성화 | 고정/해제/목록 | -| memberInfo| 활성화 | 멤버 정보 | -| emojiList | 활성화 | 사용자 정의 이모지 목록 | +| 작업 그룹 | 기본값 | 참고 | +| ----------- | ------- | ---------------------- | +| reactions | 활성화됨 | 반응 추가 + 반응 목록 | +| messages | 활성화됨 | 읽기/보내기/편집/삭제 | +| pins | 활성화됨 | 고정/해제/목록 | +| memberInfo | 활성화됨 | 멤버 정보 | +| emojiList | 활성화됨 | 사용자 정의 이모지 목록 | ### Mattermost @@ -517,7 +511,7 @@ Mattermost는 플러그인으로 제공됩니다: `openclaw plugins install @ope native: true, // opt-in nativeSkills: true, callbackPath: "/api/channels/mattermost/command", - // 리버스 프록시/공개 배포를 위한 선택적 명시 URL + // 리버스 프록시/공개 배포용 선택적 명시적 URL callbackUrl: "https://gateway.example.com/api/channels/mattermost/command", }, textChunkLimit: 4000, @@ -527,22 +521,17 @@ Mattermost는 플러그인으로 제공됩니다: `openclaw plugins install @ope } ``` -채팅 모드: `oncall`(@-mention에 응답, 기본값), `onmessage`(모든 메시지), `onchar`(트리거 접두사로 시작하는 메시지). +채팅 모드: `oncall`(@-멘션 시 응답, 기본값), `onmessage`(모든 메시지), `onchar`(트리거 접두사로 시작하는 메시지). -Mattermost 네이티브 명령이 활성화된 경우: +Mattermost 네이티브 명령이 활성화되면: -- `commands.callbackPath`는 전체 URL이 아닌 경로여야 합니다(예: `/api/channels/mattermost/command`). -- `commands.callbackUrl`은 OpenClaw gateway 엔드포인트를 가리켜야 하며 Mattermost 서버에서 접근 가능해야 합니다. -- 네이티브 slash callback은 - slash 명령 등록 중 Mattermost가 반환한 명령별 토큰으로 인증됩니다. - 등록이 실패하거나 활성화된 명령이 없으면 OpenClaw는 - `Unauthorized: invalid command token.`과 함께 callback을 거부합니다. -- 비공개/tailnet/내부 callback 호스트의 경우 Mattermost는 - `ServiceSettings.AllowedUntrustedInternalConnections`에 callback 호스트/도메인이 포함되어야 할 수 있습니다. - 전체 URL이 아니라 호스트/도메인 값을 사용하세요. -- `channels.mattermost.configWrites`: Mattermost에서 시작된 config 쓰기를 허용하거나 거부합니다. +- `commands.callbackPath`는 전체 URL이 아니라 경로여야 합니다(예: `/api/channels/mattermost/command`). +- `commands.callbackUrl`은 OpenClaw 게이트웨이 엔드포인트로 해석되어야 하며 Mattermost 서버에서 접근 가능해야 합니다. +- 네이티브 슬래시 콜백은 슬래시 명령 등록 중 Mattermost가 반환한 명령별 토큰으로 인증됩니다. 등록에 실패하거나 활성화된 명령이 없으면 OpenClaw는 `Unauthorized: invalid command token.`으로 콜백을 거부합니다. +- 비공개/tailnet/내부 콜백 호스트의 경우 Mattermost에서 `ServiceSettings.AllowedUntrustedInternalConnections`에 콜백 호스트/도메인을 포함해야 할 수 있습니다. 전체 URL이 아니라 호스트/도메인 값을 사용하세요. +- `channels.mattermost.configWrites`: Mattermost에서 시작된 구성 쓰기를 허용하거나 거부합니다. - `channels.mattermost.requireMention`: 채널에서 응답하기 전에 `@mention`을 요구합니다. -- `channels.mattermost.groups..requireMention`: 채널별 멘션 게이팅 재정의(`"*"`는 기본값). +- `channels.mattermost.groups..requireMention`: 채널별 멘션 게이팅 재정의입니다(기본값은 `"*"`). - 선택적 `channels.mattermost.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. ### Signal @@ -564,15 +553,15 @@ Mattermost 네이티브 명령이 활성화된 경우: } ``` -**리액션 알림 모드:** `off`, `own`(기본값), `all`, `allowlist`(`reactionAllowlist` 기준). +**반응 알림 모드:** `off`, `own`(기본값), `all`, `allowlist`(`reactionAllowlist` 기준). -- `channels.signal.account`: 특정 Signal 계정 식별자에 채널 시작을 고정합니다. -- `channels.signal.configWrites`: Signal에서 시작된 config 쓰기를 허용하거나 거부합니다. +- `channels.signal.account`: 채널 시작을 특정 Signal 계정 식별자에 고정합니다. +- `channels.signal.configWrites`: Signal에서 시작된 구성 쓰기를 허용하거나 거부합니다. - 선택적 `channels.signal.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. ### BlueBubbles -BlueBubbles는 권장되는 iMessage 경로입니다(플러그인 기반, `channels.bluebubbles` 아래 구성). +BlueBubbles는 권장되는 iMessage 경로입니다(플러그인 기반, `channels.bluebubbles` 아래에서 구성). ```json5 { @@ -580,8 +569,8 @@ BlueBubbles는 권장되는 iMessage 경로입니다(플러그인 기반, `chann bluebubbles: { enabled: true, dmPolicy: "pairing", - // serverUrl, password, webhookPath, group controls, 고급 액션: - // /channels/bluebubbles 참고 + // serverUrl, password, webhookPath, group controls, and advanced actions: + // /channels/bluebubbles 참조 }, }, } @@ -589,7 +578,7 @@ BlueBubbles는 권장되는 iMessage 경로입니다(플러그인 기반, `chann - 여기서 다루는 핵심 키 경로: `channels.bluebubbles`, `channels.bluebubbles.dmPolicy`. - 선택적 `channels.bluebubbles.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. -- `type: "acp"`인 최상위 `bindings[]` 항목은 BlueBubbles 대화를 영구 ACP 세션에 바인딩할 수 있습니다. `match.peer.id`에는 BlueBubbles 핸들 또는 대상 문자열(`chat_id:*`, `chat_guid:*`, `chat_identifier:*`)을 사용하세요. 공유 필드 의미: [ACP Agents](/ko/tools/acp-agents#channel-specific-settings). +- `type: "acp"`인 최상위 `bindings[]` 항목은 BlueBubbles 대화를 영구 ACP 세션에 바인딩할 수 있습니다. `match.peer.id`에는 BlueBubbles 핸들 또는 대상 문자열(`chat_id:*`, `chat_guid:*`, `chat_identifier:*`)을 사용하세요. 공통 필드 의미: [ACP Agents](/ko/tools/acp-agents#channel-specific-settings). - 전체 BlueBubbles 채널 구성은 [BlueBubbles](/ko/channels/bluebubbles)에 문서화되어 있습니다. ### iMessage @@ -620,15 +609,15 @@ OpenClaw는 `imsg rpc`(stdio를 통한 JSON-RPC)를 실행합니다. 데몬이 - 선택적 `channels.imessage.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. -- Messages DB에 대한 전체 디스크 액세스 권한이 필요합니다. -- `chat_id:` 대상 사용을 권장합니다. 채팅 목록은 `imsg chats --limit 20`으로 확인하세요. -- `cliPath`는 SSH wrapper를 가리킬 수 있습니다. SCP 첨부 파일 가져오기를 위해 `remoteHost`(`host` 또는 `user@host`)를 설정하세요. -- `attachmentRoots`와 `remoteAttachmentRoots`는 인바운드 첨부 파일 경로를 제한합니다(기본값: `/Users/*/Library/Messages/Attachments`). -- SCP는 엄격한 host-key 검사를 사용하므로, relay 호스트 키가 이미 `~/.ssh/known_hosts`에 있어야 합니다. -- `channels.imessage.configWrites`: iMessage에서 시작된 config 쓰기를 허용하거나 거부합니다. -- `type: "acp"`인 최상위 `bindings[]` 항목은 iMessage 대화를 영구 ACP 세션에 바인딩할 수 있습니다. `match.peer.id`에는 정규화된 핸들 또는 명시적 채팅 대상(`chat_id:*`, `chat_guid:*`, `chat_identifier:*`)을 사용하세요. 공유 필드 의미: [ACP Agents](/ko/tools/acp-agents#channel-specific-settings). +- Messages DB에 대한 전체 디스크 접근 권한이 필요합니다. +- `chat_id:` 대상을 사용하는 것을 권장합니다. 채팅 목록은 `imsg chats --limit 20`으로 확인하세요. +- `cliPath`는 SSH 래퍼를 가리킬 수 있습니다. SCP 첨부 파일 가져오기를 위해 `remoteHost`(`host` 또는 `user@host`)를 설정하세요. +- `attachmentRoots` 및 `remoteAttachmentRoots`는 수신 첨부 파일 경로를 제한합니다(기본값: `/Users/*/Library/Messages/Attachments`). +- SCP는 엄격한 호스트 키 검사를 사용하므로 릴레이 호스트 키가 이미 `~/.ssh/known_hosts`에 있어야 합니다. +- `channels.imessage.configWrites`: iMessage에서 시작된 구성 쓰기를 허용하거나 거부합니다. +- `type: "acp"`인 최상위 `bindings[]` 항목은 iMessage 대화를 영구 ACP 세션에 바인딩할 수 있습니다. `match.peer.id`에는 정규화된 핸들 또는 명시적 채팅 대상(`chat_id:*`, `chat_guid:*`, `chat_identifier:*`)을 사용하세요. 공통 필드 의미: [ACP Agents](/ko/tools/acp-agents#channel-specific-settings). - + ```bash #!/usr/bin/env bash @@ -670,20 +659,20 @@ Matrix는 확장 기반이며 `channels.matrix` 아래에서 구성됩니다. ``` - 토큰 인증은 `accessToken`을 사용하고, 비밀번호 인증은 `userId` + `password`를 사용합니다. -- `channels.matrix.proxy`는 Matrix HTTP 트래픽을 명시적인 HTTP(S) 프록시로 라우팅합니다. 명명된 계정은 `channels.matrix.accounts..proxy`로 이를 재정의할 수 있습니다. +- `channels.matrix.proxy`는 Matrix HTTP 트래픽을 명시적인 HTTP(S) 프록시를 통해 라우팅합니다. 명명된 계정은 `channels.matrix.accounts..proxy`로 이를 재정의할 수 있습니다. - `channels.matrix.network.dangerouslyAllowPrivateNetwork`는 비공개/내부 homeserver를 허용합니다. `proxy`와 이 네트워크 opt-in은 서로 독립적인 제어입니다. -- `channels.matrix.defaultAccount`는 다중 계정 설정에서 선호 계정을 선택합니다. -- `channels.matrix.autoJoin`의 기본값은 `off`이므로, `autoJoin: "allowlist"`와 `autoJoinAllowlist` 또는 `autoJoin: "always"`를 설정하기 전까지 초대된 룸과 새 DM 스타일 초대는 무시됩니다. +- `channels.matrix.defaultAccount`는 다중 계정 구성에서 선호 계정을 선택합니다. +- `channels.matrix.autoJoin`의 기본값은 `off`이므로 `autoJoin: "allowlist"`와 `autoJoinAllowlist` 또는 `autoJoin: "always"`를 설정할 때까지 초대된 룸과 새 DM 스타일 초대는 무시됩니다. - `channels.matrix.execApprovals`: Matrix 네이티브 exec 승인 전달 및 승인자 권한 부여. - - `enabled`: `true`, `false`, 또는 `"auto"`(기본값). auto 모드에서는 `approvers` 또는 `commands.ownerAllowFrom`에서 승인자를 해결할 수 있을 때 exec 승인이 활성화됩니다. + - `enabled`: `true`, `false`, 또는 `"auto"`(기본값). 자동 모드에서는 `approvers` 또는 `commands.ownerAllowFrom`에서 승인자를 확인할 수 있으면 exec 승인이 활성화됩니다. - `approvers`: exec 요청을 승인할 수 있는 Matrix 사용자 ID(예: `@owner:example.org`)입니다. - - `agentFilter`: 선택적 에이전트 ID 허용 목록. 생략하면 모든 에이전트의 승인 요청을 전달합니다. - - `sessionFilter`: 선택적 세션 키 패턴(부분 문자열 또는 regex). + - `agentFilter`: 선택적 에이전트 ID 허용 목록입니다. 생략하면 모든 에이전트의 승인을 전달합니다. + - `sessionFilter`: 선택적 세션 키 패턴(부분 문자열 또는 정규식)입니다. - `target`: 승인 프롬프트를 보낼 위치입니다. `"dm"`(기본값), `"channel"`(원래 룸), 또는 `"both"`. - 계정별 재정의: `channels.matrix.accounts..execApprovals`. -- `channels.matrix.dm.sessionScope`는 Matrix DM이 세션으로 그룹화되는 방식을 제어합니다: `per-user`(기본값)는 라우팅된 peer 기준으로 공유하고, `per-room`은 각 DM 룸을 격리합니다. +- `channels.matrix.dm.sessionScope`는 Matrix DM이 세션으로 그룹화되는 방식을 제어합니다. `per-user`(기본값)는 라우팅된 피어별로 공유하고, `per-room`은 각 DM 룸을 분리합니다. - Matrix 상태 프로브와 라이브 디렉터리 조회는 런타임 트래픽과 동일한 프록시 정책을 사용합니다. -- 전체 Matrix 구성, 대상 지정 규칙, 설정 예시는 [Matrix](/ko/channels/matrix)에 문서화되어 있습니다. +- 전체 Matrix 구성, 대상 지정 규칙, 설정 예제는 [Matrix](/ko/channels/matrix)에 문서화되어 있습니다. ### Microsoft Teams @@ -695,15 +684,15 @@ Microsoft Teams는 확장 기반이며 `channels.msteams` 아래에서 구성됩 msteams: { enabled: true, configWrites: true, - // appId, appPassword, tenantId, webhook, team/channel 정책: - // /channels/msteams 참고 + // appId, appPassword, tenantId, webhook, team/channel policies: + // /channels/msteams 참조 }, }, } ``` - 여기서 다루는 핵심 키 경로: `channels.msteams`, `channels.msteams.configWrites`. -- 전체 Teams config(자격 증명, webhook, DM/그룹 정책, 팀별/채널별 재정의)는 [Microsoft Teams](/ko/channels/msteams)에 문서화되어 있습니다. +- 전체 Teams 구성(자격 증명, webhook, DM/그룹 정책, 팀별/채널별 재정의)은 [Microsoft Teams](/ko/channels/msteams)에 문서화되어 있습니다. ### IRC @@ -734,7 +723,7 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. ### 다중 계정(모든 채널) -채널별로 여러 계정을 실행합니다(각각 고유한 `accountId` 사용): +채널별로 여러 계정을 실행할 수 있습니다(각각 고유한 `accountId` 보유). ```json5 { @@ -755,28 +744,28 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. } ``` -- `accountId`가 생략되면 `default`가 사용됩니다(CLI + 라우팅). -- 환경 변수 토큰은 **기본** 계정에만 적용됩니다. +- `accountId`를 생략하면 `default`가 사용됩니다(CLI + 라우팅). +- 환경 변수 토큰은 **default** 계정에만 적용됩니다. - 기본 채널 설정은 계정별로 재정의하지 않는 한 모든 계정에 적용됩니다. - 각 계정을 다른 에이전트로 라우팅하려면 `bindings[].match.accountId`를 사용하세요. -- `openclaw channels add`(또는 채널 온보딩)로 비기본 계정을 추가할 때 여전히 단일 계정 최상위 채널 config를 사용 중이라면, OpenClaw는 먼저 계정 범위 최상위 단일 계정 값을 채널 계정 맵으로 승격하여 원래 계정이 계속 동작하도록 합니다. 대부분의 채널은 이를 `channels..accounts.default`로 이동하며, Matrix는 기존의 일치하는 명명된/default 대상을 유지할 수 있습니다. +- 단일 계정 최상위 채널 구성 상태에서 `openclaw channels add`(또는 채널 온보딩)를 통해 비기본 계정을 추가하면, OpenClaw는 원래 계정이 계속 작동하도록 계정 범위 최상위 단일 계정 값을 먼저 채널 계정 맵으로 승격합니다. 대부분의 채널은 이를 `channels..accounts.default`로 이동하며, Matrix는 대신 기존의 일치하는 명명된/default 대상을 유지할 수 있습니다. - 기존 채널 전용 바인딩(`accountId` 없음)은 계속 기본 계정과 일치하며, 계정 범위 바인딩은 여전히 선택 사항입니다. -- `openclaw doctor --fix`도 계정 범위 최상위 단일 계정 값을 해당 채널에 대해 선택된 승격 계정으로 이동하여 혼합 형태를 복구합니다. 대부분의 채널은 `accounts.default`를 사용하며, Matrix는 기존의 일치하는 명명된/default 대상을 유지할 수 있습니다. +- `openclaw doctor --fix`도 혼합된 형태를 복구하며, 계정 범위 최상위 단일 계정 값을 해당 채널에 대해 선택된 승격 계정으로 이동합니다. 대부분의 채널은 `accounts.default`를 사용하고, Matrix는 기존의 일치하는 명명된/default 대상을 유지할 수 있습니다. ### 기타 확장 채널 많은 확장 채널은 `channels.`로 구성되며 전용 채널 페이지에 문서화되어 있습니다(예: Feishu, Matrix, LINE, Nostr, Zalo, Nextcloud Talk, Synology Chat, Twitch). -전체 채널 색인은 [Channels](/ko/channels)를 참고하세요. +전체 채널 색인은 [채널](/ko/channels)을 참조하세요. ### 그룹 채팅 멘션 게이팅 -그룹 메시지는 기본적으로 **멘션 필요**(메타데이터 멘션 또는 안전한 regex 패턴)입니다. WhatsApp, Telegram, Discord, Google Chat, iMessage 그룹 채팅에 적용됩니다. +그룹 메시지는 기본적으로 **멘션 필요**입니다(메타데이터 멘션 또는 안전한 정규식 패턴). WhatsApp, Telegram, Discord, Google Chat, iMessage 그룹 채팅에 적용됩니다. **멘션 유형:** - **메타데이터 멘션**: 네이티브 플랫폼 @-멘션. WhatsApp self-chat 모드에서는 무시됩니다. -- **텍스트 패턴**: `agents.list[].groupChat.mentionPatterns`의 안전한 regex 패턴. 잘못된 패턴과 안전하지 않은 중첩 반복은 무시됩니다. -- 멘션 게이팅은 감지가 가능한 경우에만 적용됩니다(네이티브 멘션 또는 최소 하나의 패턴이 있는 경우). +- **텍스트 패턴**: `agents.list[].groupChat.mentionPatterns`의 안전한 정규식 패턴입니다. 잘못된 패턴과 안전하지 않은 중첩 반복은 무시됩니다. +- 멘션 게이팅은 감지가 가능한 경우에만 적용됩니다(네이티브 멘션 또는 최소 하나의 패턴이 있을 때). ```json5 { @@ -789,9 +778,9 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. } ``` -`messages.groupChat.historyLimit`는 전역 기본값을 설정합니다. 채널은 `channels..historyLimit`(또는 계정별)로 재정의할 수 있습니다. 비활성화하려면 `0`으로 설정하세요. +`messages.groupChat.historyLimit`는 전역 기본값을 설정합니다. 채널은 `channels..historyLimit`(또는 계정별)로 이를 재정의할 수 있습니다. 비활성화하려면 `0`으로 설정하세요. -#### DM 이력 제한 +#### DM 기록 제한 ```json5 { @@ -806,13 +795,13 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. } ``` -해결 순서: DM별 재정의 → provider 기본값 → 제한 없음(모두 유지). +해결 순서: DM별 재정의 → 제공자 기본값 → 제한 없음(모두 유지). 지원 대상: `telegram`, `whatsapp`, `discord`, `slack`, `signal`, `imessage`, `msteams`. #### Self-chat 모드 -자기 번호를 `allowFrom`에 포함하면 self-chat 모드를 활성화할 수 있습니다(네이티브 @-멘션은 무시하고 텍스트 패턴에만 응답): +자기 번호를 `allowFrom`에 포함하면 self-chat 모드가 활성화됩니다(네이티브 @-멘션은 무시하고 텍스트 패턴에만 응답). ```json5 { @@ -833,21 +822,21 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. } ``` -### 명령(채팅 명령 처리) +### 명령어(채팅 명령 처리) ```json5 { commands: { native: "auto", // 지원될 때 네이티브 명령 등록 - nativeSkills: "auto", // 지원될 때 네이티브 skill 명령 등록 + nativeSkills: "auto", // 지원될 때 네이티브 스킬 명령 등록 text: true, // 채팅 메시지에서 /commands 파싱 - bash: false, // ! 허용(alias: /bash) + bash: false, // ! 허용(별칭: /bash) bashForegroundMs: 2000, config: false, // /config 허용 mcp: false, // /mcp 허용 plugins: false, // /plugins 허용 debug: false, // /debug 허용 - restart: true, // /restart + gateway 재시작 도구 허용 + restart: true, // /restart + gateway restart 도구 허용 ownerAllowFrom: ["discord:123456789012345678"], ownerDisplay: "raw", // raw | hash ownerDisplaySecret: "${OWNER_ID_HASH_SECRET}", @@ -860,32 +849,32 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. } ``` - + -- 이 블록은 명령 인터페이스를 구성합니다. 현재 내장 + 번들 명령 카탈로그는 [Slash Commands](/ko/tools/slash-commands)를 참고하세요. -- 이 페이지는 전체 명령 카탈로그가 아니라 **config 키 참조**입니다. QQ Bot `/bot-ping` `/bot-help` `/bot-logs`, LINE `/card`, device-pair `/pair`, memory `/dreaming`, phone-control `/phone`, Talk `/voice`와 같은 채널/플러그인 소유 명령은 해당 채널/플러그인 페이지와 [Slash Commands](/ko/tools/slash-commands)에 문서화되어 있습니다. -- 텍스트 명령은 앞에 `/`가 붙은 **독립 실행형** 메시지여야 합니다. -- `native: "auto"`는 Discord/Telegram의 네이티브 명령을 켜고 Slack은 끕니다. -- `nativeSkills: "auto"`는 Discord/Telegram의 네이티브 skill 명령을 켜고 Slack은 끕니다. +- 이 블록은 명령어 표면을 구성합니다. 현재 기본 제공 + 번들 명령 카탈로그는 [슬래시 명령어](/ko/tools/slash-commands)를 참조하세요. +- 이 페이지는 전체 명령 카탈로그가 아니라 **구성 키 참조**입니다. QQ Bot `/bot-ping` `/bot-help` `/bot-logs`, LINE `/card`, device-pair `/pair`, memory `/dreaming`, phone-control `/phone`, Talk `/voice` 같은 채널/플러그인 소유 명령은 해당 채널/플러그인 페이지와 [슬래시 명령어](/ko/tools/slash-commands)에 문서화되어 있습니다. +- 텍스트 명령은 반드시 앞에 `/`가 붙은 **독립형** 메시지여야 합니다. +- `native: "auto"`는 Discord/Telegram의 네이티브 명령을 켜고, Slack은 끕니다. +- `nativeSkills: "auto"`는 Discord/Telegram의 네이티브 Skills 명령을 켜고, Slack은 끕니다. - 채널별 재정의: `channels.discord.commands.native`(bool 또는 `"auto"`). `false`는 이전에 등록된 명령을 지웁니다. -- `channels..commands.nativeSkills`로 네이티브 skill 등록을 provider별로 재정의할 수 있습니다. +- `channels..commands.nativeSkills`로 채널별 네이티브 Skills 등록을 재정의합니다. - `channels.telegram.customCommands`는 추가 Telegram 봇 메뉴 항목을 추가합니다. -- `bash: true`는 호스트 셸용 `! `를 활성화합니다. `tools.elevated.enabled`와 `tools.elevated.allowFrom.` 내 발신자가 필요합니다. -- `config: true`는 `/config`를 활성화합니다(`openclaw.json` 읽기/쓰기). gateway `chat.send` 클라이언트의 경우 영구 `/config set|unset` 쓰기에는 `operator.admin`도 필요합니다. 읽기 전용 `/config show`는 일반 쓰기 범위 operator 클라이언트에서도 계속 사용할 수 있습니다. -- `mcp: true`는 `mcp.servers` 아래의 OpenClaw 관리 MCP 서버 config를 위한 `/mcp`를 활성화합니다. -- `plugins: true`는 플러그인 검색, 설치, 활성화/비활성화 제어를 위한 `/plugins`를 활성화합니다. -- `channels..configWrites`는 채널별 config 변경을 제어합니다(기본값: true). +- `bash: true`는 호스트 셸용 `! `를 활성화합니다. `tools.elevated.enabled`와 발신자가 `tools.elevated.allowFrom.`에 있어야 합니다. +- `config: true`는 `/config`를 활성화합니다(`openclaw.json` 읽기/쓰기). gateway `chat.send` 클라이언트의 경우 영구 `/config set|unset` 쓰기에는 `operator.admin`도 필요합니다. 읽기 전용 `/config show`는 일반 쓰기 범위 operator 클라이언트에도 계속 제공됩니다. +- `mcp: true`는 `mcp.servers` 아래의 OpenClaw 관리 MCP 서버 구성용 `/mcp`를 활성화합니다. +- `plugins: true`는 플러그인 검색, 설치, 활성화/비활성화 제어용 `/plugins`를 활성화합니다. +- `channels..configWrites`는 채널별 구성 변경을 제어합니다(기본값: true). - 다중 계정 채널의 경우 `channels..accounts..configWrites`도 해당 계정을 대상으로 하는 쓰기(예: `/allowlist --config --account ` 또는 `/config set channels..accounts....`)를 제어합니다. -- `restart: false`는 `/restart`와 gateway 재시작 도구 동작을 비활성화합니다. 기본값: `true`. -- `ownerAllowFrom`은 소유자 전용 명령/도구에 대한 명시적 소유자 허용 목록입니다. `allowFrom`과는 별개입니다. -- `ownerDisplay: "hash"`는 시스템 프롬프트에서 소유자 ID를 해시합니다. 해시를 제어하려면 `ownerDisplaySecret`를 설정하세요. -- `allowFrom`은 provider별입니다. 설정하면 이것이 **유일한** 권한 부여 소스가 됩니다(채널 허용 목록/페어링과 `useAccessGroups`는 무시됨). -- `useAccessGroups: false`는 `allowFrom`이 설정되지 않았을 때 명령이 액세스 그룹 정책을 우회할 수 있게 합니다. +- `restart: false`는 `/restart`와 gateway 재시작 도구 작업을 비활성화합니다. 기본값: `true`. +- `ownerAllowFrom`은 소유자 전용 명령/도구를 위한 명시적 소유자 허용 목록입니다. `allowFrom`과는 별개입니다. +- `ownerDisplay: "hash"`는 시스템 프롬프트에서 소유자 ID를 해시 처리합니다. 해시를 제어하려면 `ownerDisplaySecret`를 설정하세요. +- `allowFrom`은 제공자별입니다. 설정되면 이것이 **유일한** 권한 부여 소스가 됩니다(채널 허용 목록/페어링과 `useAccessGroups`는 무시됨). +- `useAccessGroups: false`는 `allowFrom`이 설정되지 않았을 때 명령이 접근 그룹 정책을 우회할 수 있게 합니다. - 명령 문서 맵: - - 내장 + 번들 카탈로그: [Slash Commands](/ko/tools/slash-commands) - - 채널별 명령 인터페이스: [Channels](/ko/channels) + - 기본 제공 + 번들 카탈로그: [슬래시 명령어](/ko/tools/slash-commands) + - 채널별 명령 표면: [채널](/ko/channels) - QQ Bot 명령: [QQ Bot](/ko/channels/qqbot) - - 페어링 명령: [Pairing](/ko/channels/pairing) + - 페어링 명령: [페어링](/ko/channels/pairing) - LINE 카드 명령: [LINE](/ko/channels/line) - memory dreaming: [Dreaming](/ko/concepts/dreaming) @@ -907,7 +896,7 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. ### `agents.defaults.repoRoot` -시스템 프롬프트의 Runtime 줄에 표시되는 선택적 리포지토리 루트입니다. 설정하지 않으면 OpenClaw가 workspace에서 위로 탐색하며 자동 감지합니다. +시스템 프롬프트의 Runtime 줄에 표시되는 선택적 저장소 루트입니다. 설정되지 않으면 OpenClaw가 workspace에서 위로 탐색하며 자동 감지합니다. ```json5 { @@ -917,7 +906,7 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. ### `agents.defaults.skills` -`agents.list[].skills`를 설정하지 않은 에이전트를 위한 선택적 기본 skill 허용 목록입니다. +`agents.list[].skills`를 설정하지 않은 에이전트에 대한 선택적 기본 Skills 허용 목록입니다. ```json5 { @@ -926,15 +915,15 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. list: [ { id: "writer" }, // github, weather 상속 { id: "docs", skills: ["docs-search"] }, // 기본값 대체 - { id: "locked-down", skills: [] }, // skill 없음 + { id: "locked-down", skills: [] }, // Skills 없음 ], }, } ``` -- 기본적으로 제한 없는 Skills를 원하면 `agents.defaults.skills`를 생략하세요. +- 기본적으로 Skills 무제한으로 하려면 `agents.defaults.skills`를 생략하세요. - 기본값을 상속하려면 `agents.list[].skills`를 생략하세요. -- skill이 없게 하려면 `agents.list[].skills: []`로 설정하세요. +- Skills를 사용하지 않으려면 `agents.list[].skills: []`로 설정하세요. - 비어 있지 않은 `agents.list[].skills` 목록은 해당 에이전트의 최종 집합이며, 기본값과 병합되지 않습니다. ### `agents.defaults.skipBootstrap` @@ -949,9 +938,9 @@ workspace bootstrap 파일(`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `U ### `agents.defaults.contextInjection` -workspace bootstrap 파일이 시스템 프롬프트에 주입되는 시점을 제어합니다. 기본값: `"always"`. +workspace bootstrap 파일을 시스템 프롬프트에 언제 주입할지 제어합니다. 기본값: `"always"`. -- `"continuation-skip"`: 완료된 assistant 응답 이후의 안전한 continuation 턴에서는 workspace bootstrap 재주입을 건너뛰어 프롬프트 크기를 줄입니다. 하트비트 실행과 compaction 후 재시도는 여전히 컨텍스트를 재구성합니다. +- `"continuation-skip"`: 안전한 연속 턴(완료된 assistant 응답 이후)에서는 workspace bootstrap 재주입을 건너뛰어 프롬프트 크기를 줄입니다. 하트비트 실행과 압축 후 재시도에서는 여전히 컨텍스트를 다시 구성합니다. ```json5 { @@ -961,7 +950,7 @@ workspace bootstrap 파일이 시스템 프롬프트에 주입되는 시점을 ### `agents.defaults.bootstrapMaxChars` -잘리기 전 각 workspace bootstrap 파일의 최대 문자 수입니다. 기본값: `20000`. +잘리기 전 workspace bootstrap 파일당 최대 문자 수입니다. 기본값: `20000`. ```json5 { @@ -981,12 +970,12 @@ workspace bootstrap 파일이 시스템 프롬프트에 주입되는 시점을 ### `agents.defaults.bootstrapPromptTruncationWarning` -bootstrap 컨텍스트가 잘릴 때 에이전트에게 보이는 경고 텍스트를 제어합니다. +bootstrap 컨텍스트가 잘릴 때 에이전트에게 표시되는 경고 텍스트를 제어합니다. 기본값: `"once"`. - `"off"`: 시스템 프롬프트에 경고 텍스트를 절대 주입하지 않습니다. -- `"once"`: 고유한 truncation 시그니처마다 한 번만 경고를 주입합니다(권장). -- `"always"`: truncation이 존재하는 모든 실행마다 경고를 주입합니다. +- `"once"`: 고유한 잘림 시그니처마다 경고를 한 번 주입합니다(권장). +- `"always"`: 잘림이 존재하면 매 실행마다 경고를 주입합니다. ```json5 { @@ -996,11 +985,11 @@ bootstrap 컨텍스트가 잘릴 때 에이전트에게 보이는 경고 텍스 ### `agents.defaults.imageMaxDimensionPx` -provider 호출 전에 트랜스크립트/도구 이미지 블록에서 가장 긴 이미지 변의 최대 픽셀 크기입니다. +provider 호출 전에 transcript/tool 이미지 블록에서 가장 긴 이미지 변의 최대 픽셀 크기입니다. 기본값: `1200`. -값을 낮추면 일반적으로 vision 토큰 사용량과 요청 페이로드 크기가 줄어들고, -값을 높이면 시각적 세부 정보가 더 잘 유지됩니다. +값을 낮추면 보통 비전 토큰 사용량과 스크린샷이 많은 실행의 요청 페이로드 크기가 줄어듭니다. +값을 높이면 더 많은 시각적 세부 정보를 유지합니다. ```json5 { @@ -1010,7 +999,7 @@ provider 호출 전에 트랜스크립트/도구 이미지 블록에서 가장 ### `agents.defaults.userTimezone` -시스템 프롬프트 컨텍스트용 시간대입니다(메시지 타임스탬프용 아님). 호스트 시간대로 대체됩니다. +시스템 프롬프트 컨텍스트용 시간대입니다(메시지 타임스탬프 아님). 호스트 시간대로 대체됩니다. ```json5 { @@ -1073,45 +1062,45 @@ provider 호출 전에 트랜스크립트/도구 이미지 블록에서 가장 } ``` -- `model`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. +- `model`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 허용합니다. - 문자열 형식은 기본 모델만 설정합니다. - - 객체 형식은 기본 모델과 순서가 있는 failover 모델을 함께 설정합니다. -- `imageModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. - - `image` 도구 경로에서 vision 모델 config로 사용됩니다. + - 객체 형식은 기본 모델과 순서가 있는 장애 조치 모델을 함께 설정합니다. +- `imageModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 허용합니다. + - `image` 도구 경로에서 비전 모델 구성으로 사용됩니다. - 선택된/기본 모델이 이미지 입력을 받을 수 없을 때 대체 라우팅에도 사용됩니다. -- `imageGenerationModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. - - 공유 이미지 생성 기능과 향후 이미지 생성 도구/플러그인 인터페이스에서 사용됩니다. - - 일반적인 값: Gemini 네이티브 이미지 생성을 위한 `google/gemini-3.1-flash-image-preview`, fal용 `fal/fal-ai/flux/dev`, 또는 OpenAI Images용 `openai/gpt-image-1`. - - provider/model을 직접 선택하는 경우 일치하는 provider auth/API 키도 구성하세요(예: `google/*`에는 `GEMINI_API_KEY` 또는 `GOOGLE_API_KEY`, `openai/*`에는 `OPENAI_API_KEY`, `fal/*`에는 `FAL_KEY`). - - 생략된 경우에도 `image_generate`는 auth가 설정된 provider 기본값을 추론할 수 있습니다. 먼저 현재 기본 provider를 시도하고, 그다음 남은 등록된 이미지 생성 provider를 provider-id 순서로 시도합니다. -- `musicGenerationModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. - - 공유 음악 생성 기능과 내장 `music_generate` 도구에서 사용됩니다. +- `imageGenerationModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 허용합니다. + - 공유 이미지 생성 기능과 향후 이미지를 생성하는 모든 도구/플러그인 표면에서 사용됩니다. + - 일반적인 값: Gemini 기본 이미지 생성을 위한 `google/gemini-3.1-flash-image-preview`, fal용 `fal/fal-ai/flux/dev`, OpenAI Images용 `openai/gpt-image-1`. + - provider/model을 직접 선택하는 경우, 일치하는 provider 인증/API 키도 구성해야 합니다(예: `google/*`용 `GEMINI_API_KEY` 또는 `GOOGLE_API_KEY`, `openai/*`용 `OPENAI_API_KEY`, `fal/*`용 `FAL_KEY`). + - 생략해도 `image_generate`는 인증이 설정된 provider 기본값을 추론할 수 있습니다. 현재 기본 provider를 먼저 시도한 뒤, 나머지 등록된 이미지 생성 provider를 provider ID 순서로 시도합니다. +- `musicGenerationModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 허용합니다. + - 공유 음악 생성 기능과 기본 제공 `music_generate` 도구에서 사용됩니다. - 일반적인 값: `google/lyria-3-clip-preview`, `google/lyria-3-pro-preview`, 또는 `minimax/music-2.5+`. - - 생략된 경우에도 `music_generate`는 auth가 설정된 provider 기본값을 추론할 수 있습니다. 먼저 현재 기본 provider를 시도하고, 그다음 남은 등록된 음악 생성 provider를 provider-id 순서로 시도합니다. - - provider/model을 직접 선택하는 경우 일치하는 provider auth/API 키도 구성하세요. -- `videoGenerationModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. - - 공유 비디오 생성 기능과 내장 `video_generate` 도구에서 사용됩니다. + - 생략해도 `music_generate`는 인증이 설정된 provider 기본값을 추론할 수 있습니다. 현재 기본 provider를 먼저 시도한 뒤, 나머지 등록된 음악 생성 provider를 provider ID 순서로 시도합니다. + - provider/model을 직접 선택하는 경우, 일치하는 provider 인증/API 키도 구성해야 합니다. +- `videoGenerationModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 허용합니다. + - 공유 비디오 생성 기능과 기본 제공 `video_generate` 도구에서 사용됩니다. - 일반적인 값: `qwen/wan2.6-t2v`, `qwen/wan2.6-i2v`, `qwen/wan2.6-r2v`, `qwen/wan2.6-r2v-flash`, 또는 `qwen/wan2.7-r2v`. - - 생략된 경우에도 `video_generate`는 auth가 설정된 provider 기본값을 추론할 수 있습니다. 먼저 현재 기본 provider를 시도하고, 그다음 남은 등록된 비디오 생성 provider를 provider-id 순서로 시도합니다. - - provider/model을 직접 선택하는 경우 일치하는 provider auth/API 키도 구성하세요. - - 번들 Qwen 비디오 생성 provider는 최대 1개 출력 비디오, 1개 입력 이미지, 4개 입력 비디오, 10초 길이, provider 수준 `size`, `aspectRatio`, `resolution`, `audio`, `watermark` 옵션을 지원합니다. -- `pdfModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. + - 생략해도 `video_generate`는 인증이 설정된 provider 기본값을 추론할 수 있습니다. 현재 기본 provider를 먼저 시도한 뒤, 나머지 등록된 비디오 생성 provider를 provider ID 순서로 시도합니다. + - provider/model을 직접 선택하는 경우, 일치하는 provider 인증/API 키도 구성해야 합니다. + - 번들 Qwen 비디오 생성 provider는 최대 출력 비디오 1개, 입력 이미지 1개, 입력 비디오 4개, 길이 10초, 그리고 provider 수준 `size`, `aspectRatio`, `resolution`, `audio`, `watermark` 옵션을 지원합니다. +- `pdfModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 허용합니다. - `pdf` 도구의 모델 라우팅에 사용됩니다. - - 생략되면 PDF 도구는 `imageModel`로, 그다음 해결된 세션/기본 모델로 대체됩니다. -- `pdfMaxBytesMb`: `pdf` 도구 호출 시 `maxBytesMb`가 전달되지 않았을 때 적용되는 기본 PDF 크기 제한입니다. + - 생략하면 PDF 도구는 `imageModel`로 대체하고, 그다음 해석된 세션/기본 모델로 대체합니다. +- `pdfMaxBytesMb`: 호출 시점에 `maxBytesMb`가 전달되지 않았을 때 `pdf` 도구에 적용되는 기본 PDF 크기 제한입니다. - `pdfMaxPages`: `pdf` 도구의 추출 대체 모드에서 고려하는 기본 최대 페이지 수입니다. -- `verboseDefault`: 에이전트의 기본 verbose 수준입니다. 값: `"off"`, `"on"`, `"full"`. 기본값: `"off"`. -- `elevatedDefault`: 에이전트의 기본 elevated-output 수준입니다. 값: `"off"`, `"on"`, `"ask"`, `"full"`. 기본값: `"on"`. -- `model.primary`: 형식은 `provider/model`입니다(예: `openai/gpt-5.4`). provider를 생략하면 OpenClaw는 먼저 별칭을 시도하고, 다음으로 해당 정확한 모델 ID에 대한 고유한 구성 provider 일치를 시도한 후, 마지막으로 구성된 기본 provider로 대체합니다(더 이상 권장되지 않는 호환 동작이므로 명시적인 `provider/model` 사용 권장). 해당 provider가 더 이상 구성된 기본 모델을 노출하지 않는 경우, OpenClaw는 오래된 제거된 provider 기본값을 표시하는 대신 구성된 첫 번째 provider/model로 대체합니다. +- `verboseDefault`: 에이전트의 기본 상세 출력 수준입니다. 값: `"off"`, `"on"`, `"full"`. 기본값: `"off"`. +- `elevatedDefault`: 에이전트의 기본 elevated 출력 수준입니다. 값: `"off"`, `"on"`, `"ask"`, `"full"`. 기본값: `"on"`. +- `model.primary`: 형식은 `provider/model`입니다(예: `openai/gpt-5.4`). provider를 생략하면 OpenClaw는 먼저 별칭을 시도하고, 그다음 해당 정확한 모델 ID에 대한 고유한 구성 provider 일치를 시도하며, 마지막으로 구성된 기본 provider로 대체합니다(더 이상 권장되지 않는 호환 동작이므로 명시적인 `provider/model` 사용 권장). 해당 provider가 더 이상 구성된 기본 모델을 제공하지 않으면 OpenClaw는 오래된 제거된-provider 기본값을 표시하는 대신 첫 번째 구성된 provider/model로 대체합니다. - `models`: `/model`용 구성된 모델 카탈로그 및 허용 목록입니다. 각 항목에는 `alias`(바로가기)와 `params`(provider별, 예: `temperature`, `maxTokens`, `cacheRetention`, `context1m`)를 포함할 수 있습니다. - `params`: 모든 모델에 적용되는 전역 기본 provider 매개변수입니다. `agents.defaults.params`에 설정합니다(예: `{ cacheRetention: "long" }`). -- `params` 병합 우선순위(config): `agents.defaults.params`(전역 기본) 위에 `agents.defaults.models["provider/model"].params`(모델별), 그다음 `agents.list[].params`(일치하는 agent id)가 키별로 재정의합니다. 자세한 내용은 [Prompt Caching](/ko/reference/prompt-caching)을 참고하세요. -- 이러한 필드를 변경하는 config writer(예: `/models set`, `/models set-image`, fallback 추가/제거 명령)는 정규 객체 형식으로 저장하고 가능한 경우 기존 fallback 목록을 유지합니다. -- `maxConcurrent`: 세션 전반에서 병렬 실행할 수 있는 최대 에이전트 실행 수입니다(각 세션은 여전히 직렬화됨). 기본값: 4. +- `params` 병합 우선순위(구성): `agents.defaults.params`(전역 기본값)는 `agents.defaults.models["provider/model"].params`(모델별)로 재정의되고, 그다음 `agents.list[].params`(일치하는 에이전트 ID)가 키별로 재정의합니다. 자세한 내용은 [프롬프트 캐싱](/ko/reference/prompt-caching)을 참조하세요. +- 이 필드를 변경하는 구성 작성기(예: `/models set`, `/models set-image`, fallback 추가/제거 명령)는 정식 객체 형식으로 저장하며, 가능하면 기존 fallback 목록을 유지합니다. +- `maxConcurrent`: 세션 전반에서 병렬로 실행할 수 있는 최대 에이전트 수입니다(각 세션은 여전히 직렬화됨). 기본값: 4. -**내장 별칭 단축형** (`agents.defaults.models`에 모델이 있을 때만 적용): +**기본 제공 별칭 단축형** (`agents.defaults.models`에 모델이 있을 때만 적용): -| Alias | 모델 | +| 별칭 | 모델 | | ------------------- | -------------------------------------- | | `opus` | `anthropic/claude-opus-4-6` | | `sonnet` | `anthropic/claude-sonnet-4-6` | @@ -1122,15 +1111,15 @@ provider 호출 전에 트랜스크립트/도구 이미지 블록에서 가장 | `gemini-flash` | `google/gemini-3-flash-preview` | | `gemini-flash-lite` | `google/gemini-3.1-flash-lite-preview` | -사용자가 구성한 별칭은 항상 기본값보다 우선합니다. +구성한 별칭은 항상 기본값보다 우선합니다. Z.AI GLM-4.x 모델은 `--thinking off`를 설정하거나 `agents.defaults.models["zai/"].params.thinking`을 직접 정의하지 않는 한 자동으로 thinking 모드를 활성화합니다. Z.AI 모델은 도구 호출 스트리밍을 위해 기본적으로 `tool_stream`을 활성화합니다. 비활성화하려면 `agents.defaults.models["zai/"].params.tool_stream`을 `false`로 설정하세요. -Anthropic Claude 4.6 모델은 명시적 thinking 수준이 설정되지 않은 경우 기본적으로 `adaptive` thinking을 사용합니다. +Anthropic Claude 4.6 모델은 명시적인 thinking 수준이 설정되지 않으면 기본적으로 `adaptive` thinking을 사용합니다. ### `agents.defaults.cliBackends` -텍스트 전용 대체 실행(도구 호출 없음)을 위한 선택적 CLI backend입니다. API provider가 실패할 때 백업으로 유용합니다. +도구 호출이 없는 텍스트 전용 대체 실행을 위한 선택적 CLI 백엔드입니다. API provider가 실패할 때 백업으로 유용합니다. ```json5 { @@ -1158,13 +1147,13 @@ Anthropic Claude 4.6 모델은 명시적 thinking 수준이 설정되지 않은 } ``` -- CLI backend는 텍스트 우선이며, 도구는 항상 비활성화됩니다. -- `sessionArg`가 설정된 경우 세션을 지원합니다. -- `imageArg`가 파일 경로를 받을 수 있으면 이미지 전달을 지원합니다. +- CLI 백엔드는 텍스트 우선이며, 도구는 항상 비활성화됩니다. +- `sessionArg`가 설정되면 세션이 지원됩니다. +- `imageArg`가 파일 경로를 받을 수 있으면 이미지 전달도 지원됩니다. ### `agents.defaults.systemPromptOverride` -OpenClaw가 조합한 전체 시스템 프롬프트를 고정 문자열로 대체합니다. 기본 수준(`agents.defaults.systemPromptOverride`) 또는 에이전트별(`agents.list[].systemPromptOverride`)로 설정합니다. 에이전트별 값이 우선하며, 빈 문자열 또는 공백만 있는 값은 무시됩니다. 제어된 프롬프트 실험에 유용합니다. +OpenClaw가 조합한 전체 시스템 프롬프트를 고정 문자열로 대체합니다. 기본 수준(`agents.defaults.systemPromptOverride`) 또는 에이전트별(`agents.list[].systemPromptOverride`)로 설정합니다. 에이전트별 값이 우선하며, 비어 있거나 공백만 있는 값은 무시됩니다. 통제된 프롬프트 실험에 유용합니다. ```json5 { @@ -1178,19 +1167,19 @@ OpenClaw가 조합한 전체 시스템 프롬프트를 고정 문자열로 대 ### `agents.defaults.heartbeat` -주기적 하트비트 실행입니다. +주기적인 하트비트 실행입니다. ```json5 { agents: { defaults: { heartbeat: { - every: "30m", // 0m disables + every: "30m", // 0m이면 비활성화 model: "openai/gpt-5.4-mini", includeReasoning: false, - includeSystemPromptSection: true, // 기본값: true; false면 시스템 프롬프트에서 Heartbeat 섹션 생략 - lightContext: false, // 기본값: false; true면 workspace bootstrap 파일 중 HEARTBEAT.md만 유지 - isolatedSession: false, // 기본값: false; true면 각 heartbeat를 새 세션에서 실행(대화 이력 없음) + includeSystemPromptSection: true, // 기본값: true; false이면 시스템 프롬프트에서 Heartbeat 섹션 생략 + lightContext: false, // 기본값: false; true이면 workspace bootstrap 파일 중 HEARTBEAT.md만 유지 + isolatedSession: false, // 기본값: false; true이면 각 하트비트를 새 세션에서 실행(대화 기록 없음) session: "main", to: "+15555550123", directPolicy: "allow", // allow (기본값) | block @@ -1204,14 +1193,14 @@ OpenClaw가 조합한 전체 시스템 프롬프트를 고정 문자열로 대 } ``` -- `every`: 기간 문자열(ms/s/m/h). 기본값: `30m`(API 키 인증) 또는 `1h`(OAuth 인증). 비활성화하려면 `0m`으로 설정하세요. -- `includeSystemPromptSection`: false일 경우 시스템 프롬프트에서 Heartbeat 섹션을 생략하고 bootstrap 컨텍스트에 `HEARTBEAT.md`를 주입하지 않습니다. 기본값: `true`. -- `suppressToolErrorWarnings`: true일 경우 하트비트 실행 중 tool error warning payload를 숨깁니다. -- `directPolicy`: direct/DM 전달 정책입니다. `allow`(기본값)는 direct target 전달을 허용합니다. `block`은 direct target 전달을 억제하고 `reason=dm-blocked`를 출력합니다. -- `lightContext`: true일 경우 heartbeat 실행은 경량 bootstrap 컨텍스트를 사용하며 workspace bootstrap 파일 중 `HEARTBEAT.md`만 유지합니다. -- `isolatedSession`: true일 경우 각 heartbeat는 이전 대화 이력 없이 새 세션에서 실행됩니다. cron `sessionTarget: "isolated"`와 같은 격리 패턴입니다. heartbeat당 토큰 비용을 약 100K에서 약 2~5K 토큰으로 줄입니다. -- 에이전트별: `agents.list[].heartbeat`에 설정합니다. 어떤 에이전트든 `heartbeat`를 정의하면 **해당 에이전트들만** heartbeat를 실행합니다. -- Heartbeat는 완전한 에이전트 턴을 실행하므로, 간격이 짧을수록 토큰을 더 많이 소모합니다. +- `every`: 기간 문자열(ms/s/m/h)입니다. 기본값: `30m`(API 키 인증) 또는 `1h`(OAuth 인증). 비활성화하려면 `0m`으로 설정하세요. +- `includeSystemPromptSection`: false이면 시스템 프롬프트에서 Heartbeat 섹션을 생략하고 bootstrap 컨텍스트에 `HEARTBEAT.md`를 주입하지 않습니다. 기본값: `true`. +- `suppressToolErrorWarnings`: true이면 하트비트 실행 중 도구 오류 경고 페이로드를 숨깁니다. +- `directPolicy`: direct/DM 전달 정책입니다. `allow`(기본값)는 direct 대상 전달을 허용합니다. `block`은 direct 대상 전달을 막고 `reason=dm-blocked`를 출력합니다. +- `lightContext`: true이면 하트비트 실행에서 경량 bootstrap 컨텍스트를 사용하고 workspace bootstrap 파일 중 `HEARTBEAT.md`만 유지합니다. +- `isolatedSession`: true이면 각 하트비트를 이전 대화 기록이 없는 새 세션에서 실행합니다. cron `sessionTarget: "isolated"`와 동일한 격리 패턴입니다. 하트비트당 토큰 비용을 약 100K에서 약 2-5K 토큰으로 줄입니다. +- 에이전트별 설정: `agents.list[].heartbeat`를 사용하세요. 어떤 에이전트든 `heartbeat`를 정의하면 **해당 에이전트들만** 하트비트를 실행합니다. +- 하트비트는 전체 에이전트 턴을 실행하므로, 간격이 짧을수록 더 많은 토큰을 사용합니다. ### `agents.defaults.compaction` @@ -1221,19 +1210,19 @@ OpenClaw가 조합한 전체 시스템 프롬프트를 고정 문자열로 대 defaults: { compaction: { mode: "safeguard", // default | safeguard - provider: "my-provider", // 등록된 compaction provider plugin의 id(선택) + provider: "my-provider", // 등록된 compaction provider plugin의 ID(선택 사항) timeoutSeconds: 900, reserveTokensFloor: 24000, identifierPolicy: "strict", // strict | off | custom - identifierInstructions: "Preserve deployment IDs, ticket IDs, and host:port pairs exactly.", // identifierPolicy=custom일 때 사용 - postCompactionSections: ["Session Startup", "Red Lines"], // []는 재주입 비활성화 + identifierInstructions: "배포 ID, 티켓 ID, host:port 쌍을 정확히 보존하세요.", // identifierPolicy=custom일 때 사용 + postCompactionSections: ["Session Startup", "Red Lines"], // []이면 재주입 비활성화 model: "openrouter/anthropic/claude-sonnet-4-6", // 선택적 compaction 전용 모델 재정의 notifyUser: true, // compaction 시작 시 짧은 알림 전송(기본값: false) memoryFlush: { enabled: true, softThresholdTokens: 6000, - systemPrompt: "Session nearing compaction. Store durable memories now.", - prompt: "Write any lasting notes to memory/YYYY-MM-DD.md; reply with the exact silent token NO_REPLY if nothing to store.", + systemPrompt: "세션이 compaction에 가까워졌습니다. 지속될 메모리를 지금 저장하세요.", + prompt: "lasting notes가 있으면 memory/YYYY-MM-DD.md에 작성하고, 저장할 내용이 없으면 정확히 무응답 토큰 NO_REPLY로 응답하세요.", }, }, }, @@ -1241,19 +1230,19 @@ OpenClaw가 조합한 전체 시스템 프롬프트를 고정 문자열로 대 } ``` -- `mode`: `default` 또는 `safeguard`(긴 이력용 청크 요약). [Compaction](/ko/concepts/compaction) 참고. -- `provider`: 등록된 compaction provider plugin의 id입니다. 설정되면 내장 LLM 요약 대신 provider의 `summarize()`가 호출됩니다. 실패 시 내장 동작으로 대체됩니다. provider를 설정하면 `mode: "safeguard"`가 강제됩니다. [Compaction](/ko/concepts/compaction) 참고. +- `mode`: `default` 또는 `safeguard`(긴 기록을 위한 청크 단위 요약)입니다. [Compaction](/ko/concepts/compaction)을 참조하세요. +- `provider`: 등록된 compaction provider plugin의 ID입니다. 설정하면 기본 제공 LLM 요약 대신 해당 provider의 `summarize()`가 호출됩니다. 실패 시 기본 제공 방식으로 대체됩니다. provider를 설정하면 `mode: "safeguard"`가 강제됩니다. [Compaction](/ko/concepts/compaction)을 참조하세요. - `timeoutSeconds`: OpenClaw가 중단하기 전 단일 compaction 작업에 허용되는 최대 시간(초)입니다. 기본값: `900`. -- `identifierPolicy`: `strict`(기본값), `off`, 또는 `custom`. `strict`는 compaction 요약 중 내장 불투명 식별자 보존 안내를 앞에 붙입니다. +- `identifierPolicy`: `strict`(기본값), `off`, 또는 `custom`입니다. `strict`는 compaction 요약 중 기본 제공 불투명 식별자 보존 지침을 앞에 추가합니다. - `identifierInstructions`: `identifierPolicy=custom`일 때 사용되는 선택적 사용자 지정 식별자 보존 텍스트입니다. -- `postCompactionSections`: compaction 후 재주입할 AGENTS.md H2/H3 섹션 이름의 선택적 목록입니다. 기본값은 `["Session Startup", "Red Lines"]`이며, 비활성화하려면 `[]`로 설정하세요. 설정하지 않았거나 이 기본 쌍으로 명시적으로 설정한 경우, 이전 `Every Session`/`Safety` 헤딩도 레거시 대체값으로 허용됩니다. -- `model`: compaction 요약 전용 선택적 `provider/model-id` 재정의입니다. 메인 세션은 한 모델을 유지하되 compaction 요약은 다른 모델에서 실행하고 싶을 때 사용하세요. 설정하지 않으면 compaction은 세션의 기본 모델을 사용합니다. -- `notifyUser`: `true`일 때 compaction 시작 시 사용자에게 짧은 알림(예: `"Compacting context..."`)을 보냅니다. compaction을 조용히 유지하기 위해 기본적으로 비활성화되어 있습니다. -- `memoryFlush`: 자동 compaction 전에 영속 메모리를 저장하기 위한 무음 에이전트 턴입니다. workspace가 읽기 전용이면 건너뜁니다. +- `postCompactionSections`: compaction 후 다시 주입할 선택적 AGENTS.md H2/H3 섹션 이름입니다. 기본값은 `["Session Startup", "Red Lines"]`이며, 재주입을 비활성화하려면 `[]`로 설정하세요. 설정하지 않았거나 명시적으로 그 기본 쌍으로 설정한 경우, 이전 `Every Session`/`Safety` 헤딩도 레거시 대체값으로 허용됩니다. +- `model`: compaction 요약에만 적용되는 선택적 `provider/model-id` 재정의입니다. 기본 세션은 한 모델을 유지하고 compaction 요약은 다른 모델에서 실행해야 할 때 사용하세요. 설정하지 않으면 compaction은 세션의 기본 모델을 사용합니다. +- `notifyUser`: `true`이면 compaction이 시작될 때 사용자에게 짧은 알림을 보냅니다(예: "Compacting context..."). compaction을 조용히 유지하기 위해 기본적으로 비활성화되어 있습니다. +- `memoryFlush`: 자동 compaction 전에 지속 메모리를 저장하기 위한 무음 agentic 턴입니다. workspace가 읽기 전용이면 건너뜁니다. ### `agents.defaults.contextPruning` -LLM에 보내기 전에 메모리 내 컨텍스트에서 **오래된 도구 결과**를 정리합니다. 디스크의 세션 이력은 **수정하지 않습니다**. +LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 도구 결과**를 제거합니다. 디스크의 세션 기록은 수정하지 않습니다. ```json5 { @@ -1277,23 +1266,23 @@ LLM에 보내기 전에 메모리 내 컨텍스트에서 **오래된 도구 결 -- `mode: "cache-ttl"`은 pruning 패스를 활성화합니다. -- `ttl`은 마지막 캐시 접촉 이후 pruning이 다시 실행될 수 있는 주기를 제어합니다. -- Pruning은 먼저 과도하게 큰 tool 결과를 soft-trim하고, 필요 시 더 오래된 tool 결과를 hard-clear합니다. +- `mode: "cache-ttl"`은 제거 패스를 활성화합니다. +- `ttl`은 마지막 캐시 터치 이후 제거가 다시 실행될 수 있는 빈도를 제어합니다. +- 제거는 먼저 큰 도구 결과를 soft-trim하고, 필요하면 더 오래된 도구 결과를 hard-clear합니다. -**Soft-trim**은 앞부분 + 뒷부분을 유지하고 중간에 `...`를 삽입합니다. +**Soft-trim**은 앞부분 + 끝부분을 유지하고 중간에 `...`를 삽입합니다. -**Hard-clear**는 전체 tool 결과를 placeholder로 대체합니다. +**Hard-clear**는 전체 도구 결과를 placeholder로 대체합니다. 참고: - 이미지 블록은 절대 잘리거나 지워지지 않습니다. -- 비율은 토큰 수가 아닌 문자 수 기준(근사치)입니다. -- `keepLastAssistants`보다 적은 assistant 메시지만 있으면 pruning은 건너뜁니다. +- 비율은 문자 기준(근사치)이며, 정확한 토큰 수 기준이 아닙니다. +- assistant 메시지가 `keepLastAssistants`보다 적으면 제거는 건너뜁니다. -동작 세부 정보는 [Session Pruning](/ko/concepts/session-pruning)을 참고하세요. +동작 세부 사항은 [세션 제거](/ko/concepts/session-pruning)를 참조하세요. ### 블록 스트리밍 @@ -1311,13 +1300,13 @@ LLM에 보내기 전에 메모리 내 컨텍스트에서 **오래된 도구 결 } ``` -- Telegram 이외 채널에서는 블록 응답을 활성화하려면 명시적인 `*.blockStreaming: true`가 필요합니다. +- Telegram이 아닌 채널은 블록 응답을 활성화하려면 명시적인 `*.blockStreaming: true`가 필요합니다. - 채널 재정의: `channels..blockStreamingCoalesce`(및 계정별 변형). Signal/Slack/Discord/Google Chat의 기본값은 `minChars: 1500`입니다. - `humanDelay`: 블록 응답 사이의 무작위 지연입니다. `natural` = 800–2500ms. 에이전트별 재정의: `agents.list[].humanDelay`. -동작 및 청크 세부 정보는 [Streaming](/ko/concepts/streaming)을 참고하세요. +동작 및 청킹 세부 사항은 [스트리밍](/ko/concepts/streaming)을 참조하세요. -### 타이핑 인디케이터 +### 입력 중 표시기 ```json5 { @@ -1333,13 +1322,13 @@ LLM에 보내기 전에 메모리 내 컨텍스트에서 **오래된 도구 결 - 기본값: direct 채팅/멘션에는 `instant`, 멘션되지 않은 그룹 채팅에는 `message`. - 세션별 재정의: `session.typingMode`, `session.typingIntervalSeconds`. -[Typing Indicators](/ko/concepts/typing-indicators)를 참고하세요. +[입력 중 표시기](/ko/concepts/typing-indicators)를 참조하세요. ### `agents.defaults.sandbox` -내장 에이전트를 위한 선택적 sandboxing입니다. 전체 가이드는 [Sandboxing](/ko/gateway/sandboxing)을 참고하세요. +임베디드 에이전트를 위한 선택적 sandboxing입니다. 전체 가이드는 [Sandboxing](/ko/gateway/sandboxing)을 참조하세요. ```json5 { @@ -1436,52 +1425,51 @@ LLM에 보내기 전에 메모리 내 컨텍스트에서 **오래된 도구 결 -**Backend:** +**백엔드:** - `docker`: 로컬 Docker 런타임(기본값) - `ssh`: 일반 SSH 기반 원격 런타임 - `openshell`: OpenShell 런타임 -`backend: "openshell"`이 선택되면 런타임별 설정은 -`plugins.entries.openshell.config`로 이동합니다. +`backend: "openshell"`을 선택하면 런타임별 설정은 `plugins.entries.openshell.config`로 이동합니다. -**SSH backend config:** +**SSH 백엔드 구성:** - `target`: `user@host[:port]` 형식의 SSH 대상 - `command`: SSH 클라이언트 명령(기본값: `ssh`) -- `workspaceRoot`: 범위별 workspace에 사용되는 절대 원격 루트 +- `workspaceRoot`: 범위별 workspace에 사용하는 절대 원격 루트 - `identityFile` / `certificateFile` / `knownHostsFile`: OpenSSH에 전달되는 기존 로컬 파일 - `identityData` / `certificateData` / `knownHostsData`: OpenClaw가 런타임에 임시 파일로 구체화하는 인라인 내용 또는 SecretRef -- `strictHostKeyChecking` / `updateHostKeys`: OpenSSH host-key 정책 설정 +- `strictHostKeyChecking` / `updateHostKeys`: OpenSSH 호스트 키 정책 옵션 **SSH 인증 우선순위:** -- `identityData`가 `identityFile`보다 우선합니다 -- `certificateData`가 `certificateFile`보다 우선합니다 -- `knownHostsData`가 `knownHostsFile`보다 우선합니다 -- SecretRef 기반 `*Data` 값은 sandbox 세션 시작 전에 활성 secrets 런타임 스냅샷에서 해결됩니다 +- `identityData`가 `identityFile`보다 우선 +- `certificateData`가 `certificateFile`보다 우선 +- `knownHostsData`가 `knownHostsFile`보다 우선 +- SecretRef 기반 `*Data` 값은 sandbox 세션 시작 전에 활성 secrets 런타임 스냅샷에서 해석됩니다 -**SSH backend 동작:** +**SSH 백엔드 동작:** -- 생성 또는 재생성 후 원격 workspace를 한 번 시드합니다 -- 이후 원격 SSH workspace를 정식 상태로 유지합니다 -- `exec`, 파일 도구, 미디어 경로를 SSH로 라우팅합니다 -- 원격 변경 내용을 호스트로 자동 동기화하지 않습니다 -- sandbox 브라우저 컨테이너는 지원하지 않습니다 +- 생성 또는 재생성 후 원격 workspace를 한 번 시드함 +- 이후 원격 SSH workspace를 정식 기준으로 유지함 +- `exec`, 파일 도구, 미디어 경로를 SSH를 통해 라우팅함 +- 원격 변경 사항을 호스트에 자동으로 다시 동기화하지 않음 +- sandbox 브라우저 컨테이너는 지원하지 않음 -**Workspace access:** +**Workspace 접근:** -- `none`: `~/.openclaw/sandboxes` 아래 범위별 sandbox workspace -- `ro`: sandbox workspace는 `/workspace`, 에이전트 workspace는 `/agent`에 읽기 전용 마운트 -- `rw`: 에이전트 workspace를 `/workspace`에 읽기/쓰기 마운트 +- `none`: `~/.openclaw/sandboxes` 아래의 범위별 sandbox workspace +- `ro`: `/workspace`의 sandbox workspace, `/agent`에 읽기 전용으로 마운트된 agent workspace +- `rw`: agent workspace를 `/workspace`에 읽기/쓰기로 마운트 -**Scope:** +**범위:** - `session`: 세션별 컨테이너 + workspace -- `agent`: 에이전트별 하나의 컨테이너 + workspace(기본값) -- `shared`: 공유 컨테이너와 workspace(세션 간 격리 없음) +- `agent`: 에이전트별 컨테이너 + workspace 1개(기본값) +- `shared`: 공유 컨테이너 및 workspace(세션 간 격리 없음) -**OpenShell plugin config:** +**OpenShell plugin 구성:** ```json5 { @@ -1509,32 +1497,32 @@ LLM에 보내기 전에 메모리 내 컨텍스트에서 **오래된 도구 결 **OpenShell 모드:** -- `mirror`: exec 전에 로컬에서 원격으로 시드하고, exec 후 다시 동기화합니다. 로컬 workspace가 정식 상태로 유지됩니다 -- `remote`: sandbox 생성 시 원격을 한 번 시드한 뒤, 원격 workspace를 정식 상태로 유지합니다 +- `mirror`: 실행 전 로컬에서 원격으로 시드하고, 실행 후 다시 동기화함. 로컬 workspace가 정식 기준으로 유지됨 +- `remote`: sandbox가 생성될 때 원격을 한 번 시드한 뒤, 원격 workspace를 정식 기준으로 유지함 -`remote` 모드에서는 OpenClaw 외부에서 이루어진 호스트 로컬 편집 내용이 시드 단계 이후 sandbox로 자동 동기화되지 않습니다. -전송은 SSH를 통해 OpenShell sandbox에 접속하지만, sandbox 수명 주기와 선택적 mirror sync는 plugin이 소유합니다. +`remote` 모드에서는 시드 단계 이후 OpenClaw 외부에서 이루어진 호스트 로컬 편집이 sandbox에 자동으로 동기화되지 않습니다. +전송은 OpenShell sandbox로의 SSH를 사용하지만, plugin이 sandbox 수명 주기와 선택적 mirror 동기화를 관리합니다. **`setupCommand`**는 컨테이너 생성 후 한 번 실행됩니다(`sh -lc` 사용). 네트워크 송신, 쓰기 가능한 루트, root 사용자가 필요합니다. -**컨테이너 기본값은 `network: "none"`**입니다. 에이전트가 외부 액세스를 필요로 하면 `"bridge"`(또는 사용자 지정 bridge 네트워크)로 설정하세요. -`"host"`는 차단됩니다. `"container:"`는 -`sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true`를 명시적으로 설정한 경우에만 허용됩니다(비상용). +**컨테이너는 기본적으로 `network: "none"`입니다** — 에이전트에 외부 접근이 필요하면 `"bridge"`(또는 사용자 지정 브리지 네트워크)로 설정하세요. +`"host"`는 차단됩니다. `"container:"`는 기본적으로 차단되며, +`sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true`를 명시적으로 설정한 경우에만 허용됩니다(비상 수단). -**인바운드 첨부 파일**은 활성 workspace의 `media/inbound/*`에 임시 배치됩니다. +**수신 첨부 파일**은 활성 workspace의 `media/inbound/*`에 스테이징됩니다. -**`docker.binds`**는 추가 호스트 디렉터리를 마운트하며, 전역 및 에이전트별 binds가 병합됩니다. +**`docker.binds`**는 추가 호스트 디렉터리를 마운트합니다. 전역 및 에이전트별 bind는 병합됩니다. -**Sandboxed browser** (`sandbox.browser.enabled`): 컨테이너 안의 Chromium + CDP입니다. noVNC URL이 시스템 프롬프트에 주입됩니다. `openclaw.json`에서 `browser.enabled`는 필요하지 않습니다. -noVNC 옵저버 액세스는 기본적으로 VNC 인증을 사용하며, OpenClaw는 공유 URL에 비밀번호를 노출하는 대신 짧은 수명의 토큰 URL을 발급합니다. +**Sandboxed browser** (`sandbox.browser.enabled`): 컨테이너 안의 Chromium + CDP입니다. noVNC URL이 시스템 프롬프트에 주입됩니다. `openclaw.json`에서 `browser.enabled`가 필요하지 않습니다. +noVNC 관찰자 접근은 기본적으로 VNC 인증을 사용하며, OpenClaw는 공유 URL에 비밀번호를 노출하는 대신 짧은 수명의 토큰 URL을 발급합니다. -- `allowHostControl: false`(기본값)는 sandbox 세션이 호스트 브라우저를 대상으로 삼는 것을 차단합니다. -- `network`의 기본값은 `openclaw-sandbox-browser`(전용 bridge 네트워크)입니다. 명시적으로 전체 bridge 연결이 필요할 때만 `bridge`로 설정하세요. -- `cdpSourceRange`는 선택적으로 컨테이너 경계에서 CDP 유입을 CIDR 범위로 제한합니다(예: `172.21.0.1/32`). -- `sandbox.browser.binds`는 추가 호스트 디렉터리를 sandbox browser 컨테이너에만 마운트합니다. 설정되면(`[]` 포함) browser 컨테이너에서는 `docker.binds`를 대체합니다. -- 실행 기본값은 `scripts/sandbox-browser-entrypoint.sh`에 정의되어 있으며 컨테이너 호스트에 맞게 조정되어 있습니다: +- `allowHostControl: false`(기본값)는 sandbox 세션이 호스트 브라우저를 대상으로 지정하는 것을 차단합니다. +- `network`의 기본값은 `openclaw-sandbox-browser`(전용 브리지 네트워크)입니다. 전역 브리지 연결이 명시적으로 필요할 때만 `bridge`로 설정하세요. +- `cdpSourceRange`는 선택적으로 컨테이너 경계에서 CDP 유입을 CIDR 범위(예: `172.21.0.1/32`)로 제한합니다. +- `sandbox.browser.binds`는 추가 호스트 디렉터리를 sandbox 브라우저 컨테이너에만 마운트합니다. 설정되면(`[]` 포함) 브라우저 컨테이너에는 `docker.binds` 대신 이것이 사용됩니다. +- 시작 기본값은 `scripts/sandbox-browser-entrypoint.sh`에 정의되어 있으며 컨테이너 호스트에 맞게 조정되어 있습니다. - `--remote-debugging-address=127.0.0.1` - - `--remote-debugging-port=` + - `--remote-debugging-port=` - `--user-data-dir=${HOME}/.chrome` - `--no-first-run` - `--no-default-browser-check` @@ -1549,18 +1537,12 @@ noVNC 옵저버 액세스는 기본적으로 VNC 인증을 사용하며, OpenCla - `--renderer-process-limit=2` - `--no-zygote` - `--metrics-recording-only` - - `--disable-extensions`(기본 활성화) - - `--disable-3d-apis`, `--disable-software-rasterizer`, `--disable-gpu`는 - 기본적으로 활성화되어 있으며, WebGL/3D 사용에 필요할 경우 - `OPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS=0`으로 비활성화할 수 있습니다. - - 워크플로가 확장 기능에 의존하는 경우 - `OPENCLAW_BROWSER_DISABLE_EXTENSIONS=0`으로 확장 기능을 다시 활성화할 수 있습니다. - - `--renderer-process-limit=2`는 - `OPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT=`으로 변경할 수 있습니다. Chromium의 - 기본 프로세스 제한을 사용하려면 `0`으로 설정하세요. - - 그리고 `noSandbox`가 활성화된 경우 `--no-sandbox` 및 `--disable-setuid-sandbox`. - - 기본값은 컨테이너 이미지 기준선입니다. 컨테이너 기본값을 바꾸려면 - 사용자 지정 entrypoint가 포함된 사용자 지정 browser 이미지를 사용하세요. + - `--disable-extensions`(기본적으로 활성화됨) + - `--disable-3d-apis`, `--disable-software-rasterizer`, `--disable-gpu`는 기본적으로 활성화되어 있으며, WebGL/3D 사용에 필요하면 `OPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS=0`으로 비활성화할 수 있습니다. + - 워크플로가 확장 기능에 의존하면 `OPENCLAW_BROWSER_DISABLE_EXTENSIONS=0`으로 확장 기능을 다시 활성화합니다. + - `--renderer-process-limit=2`는 `OPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT=`으로 변경할 수 있습니다. Chromium 기본 프로세스 제한을 사용하려면 `0`으로 설정하세요. + - 또한 `noSandbox`가 활성화되면 `--no-sandbox` 및 `--disable-setuid-sandbox`가 추가됩니다. + - 기본값은 컨테이너 이미지 기준값입니다. 컨테이너 기본값을 변경하려면 사용자 지정 엔트리포인트가 있는 사용자 지정 브라우저 이미지를 사용하세요. @@ -1570,10 +1552,10 @@ noVNC 옵저버 액세스는 기본적으로 VNC 인증을 사용하며, OpenCla ```bash scripts/sandbox-setup.sh # 기본 sandbox 이미지 -scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 +scripts/sandbox-browser-setup.sh # 선택적 브라우저 이미지 ``` -### `agents.list` (에이전트별 재정의) +### `agents.list`(에이전트별 재정의) ```json5 { @@ -1587,8 +1569,8 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 agentDir: "~/.openclaw/agents/main/agent", model: "anthropic/claude-opus-4-6", // 또는 { primary, fallbacks } thinkingDefault: "high", // 에이전트별 기본 thinking 수준 재정의 - reasoningDefault: "on", // 에이전트별 reasoning 표시 재정의 - fastModeDefault: false, // 에이전트별 fast mode 재정의 + reasoningDefault: "on", // 에이전트별 기본 reasoning 표시 재정의 + fastModeDefault: false, // 에이전트별 기본 fast mode 재정의 params: { cacheRetention: "none" }, // 일치하는 defaults.models params를 키별로 재정의 skills: ["docs-search"], // 설정 시 agents.defaults.skills를 대체 identity: { @@ -1621,26 +1603,26 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 } ``` -- `id`: 안정적인 에이전트 ID(필수). -- `default`: 여러 개가 설정되면 첫 번째가 우선합니다(경고 기록). 아무것도 설정되지 않으면 목록의 첫 번째 항목이 기본값입니다. -- `model`: 문자열 형식은 `primary`만 재정의합니다. 객체 형식 `{ primary, fallbacks }`는 둘 다 재정의합니다(`[]`는 전역 fallback 비활성화). `primary`만 재정의하는 cron 작업은 `fallbacks: []`를 설정하지 않는 한 기본 fallback을 계속 상속합니다. -- `params`: 선택된 모델 항목의 `agents.defaults.models` 위에 병합되는 에이전트별 stream params입니다. 전체 모델 카탈로그를 복제하지 않고 `cacheRetention`, `temperature`, `maxTokens` 같은 에이전트별 재정의에 사용하세요. -- `skills`: 선택적 에이전트별 skill 허용 목록입니다. 생략하면 설정된 경우 `agents.defaults.skills`를 상속하며, 명시적인 목록은 기본값과 병합되지 않고 대체됩니다. `[]`는 skill 없음입니다. -- `thinkingDefault`: 선택적 에이전트별 기본 thinking 수준(`off | minimal | low | medium | high | xhigh | adaptive`). 메시지별 또는 세션 재정의가 없을 때 해당 에이전트에서 `agents.defaults.thinkingDefault`를 재정의합니다. -- `reasoningDefault`: 선택적 에이전트별 기본 reasoning 표시(`on | off | stream`). 메시지별 또는 세션 reasoning 재정의가 없을 때 적용됩니다. -- `fastModeDefault`: 선택적 에이전트별 fast mode 기본값(`true | false`)입니다. 메시지별 또는 세션 fast-mode 재정의가 없을 때 적용됩니다. -- `runtime`: 선택적 에이전트별 런타임 설명자입니다. 에이전트가 기본적으로 ACP harness 세션을 사용해야 할 경우 `type: "acp"`와 `runtime.acp` 기본값(`agent`, `backend`, `mode`, `cwd`)을 사용하세요. +- `id`: 안정적인 에이전트 ID입니다(필수). +- `default`: 여러 개가 설정되면 첫 번째가 적용됩니다(경고 로그 기록). 아무것도 설정되지 않으면 목록의 첫 번째 항목이 기본값입니다. +- `model`: 문자열 형식은 `primary`만 재정의하고, 객체 형식 `{ primary, fallbacks }`는 둘 다 재정의합니다(`[]`는 전역 fallback 비활성화). `primary`만 재정의하는 cron 작업은 `fallbacks: []`를 설정하지 않는 한 여전히 기본 fallback을 상속합니다. +- `params`: 선택된 모델 항목의 `agents.defaults.models` 위에 병합되는 에이전트별 스트림 매개변수입니다. 전체 모델 카탈로그를 복제하지 않고 `cacheRetention`, `temperature`, `maxTokens` 같은 에이전트별 재정의에 사용하세요. +- `skills`: 선택적 에이전트별 Skills 허용 목록입니다. 생략하면 `agents.defaults.skills`가 설정된 경우 이를 상속합니다. 명시적 목록은 병합하지 않고 기본값을 대체하며, `[]`는 Skills 없음을 의미합니다. +- `thinkingDefault`: 선택적 에이전트별 기본 thinking 수준(`off | minimal | low | medium | high | xhigh | adaptive`)입니다. 메시지별 또는 세션별 재정의가 없을 때 이 에이전트의 `agents.defaults.thinkingDefault`를 재정의합니다. +- `reasoningDefault`: 선택적 에이전트별 기본 reasoning 표시 설정(`on | off | stream`)입니다. 메시지별 또는 세션별 reasoning 재정의가 없을 때 적용됩니다. +- `fastModeDefault`: 선택적 에이전트별 기본 fast mode 설정(`true | false`)입니다. 메시지별 또는 세션별 fast-mode 재정의가 없을 때 적용됩니다. +- `runtime`: 선택적 에이전트별 런타임 설명자입니다. 에이전트가 기본적으로 ACP harness 세션을 사용해야 할 때 `type: "acp"`와 `runtime.acp` 기본값(`agent`, `backend`, `mode`, `cwd`)을 사용하세요. - `identity.avatar`: workspace 상대 경로, `http(s)` URL 또는 `data:` URI입니다. -- `identity`는 기본값을 파생합니다: `ackReaction`은 `emoji`에서, `mentionPatterns`는 `name`/`emoji`에서 파생됩니다. -- `subagents.allowAgents`: `sessions_spawn`용 에이전트 ID 허용 목록입니다(`["*"]` = 모두 허용, 기본값: 동일 에이전트만). -- Sandbox 상속 가드: 요청자 세션이 sandbox 상태이면, `sessions_spawn`은 sandbox 없이 실행될 대상은 거부합니다. -- `subagents.requireAgentId`: true일 때 `agentId`를 생략한 `sessions_spawn` 호출을 차단합니다(명시적 프로필 선택 강제, 기본값: false). +- `identity`는 기본값을 파생합니다. `ackReaction`은 `emoji`에서, `mentionPatterns`는 `name`/`emoji`에서 파생됩니다. +- `subagents.allowAgents`: `sessions_spawn`용 에이전트 ID 허용 목록입니다(`["*"]` = 아무 에이전트나, 기본값: 동일 에이전트만). +- Sandbox 상속 보호: 요청 세션이 sandbox 상태이면 `sessions_spawn`은 sandbox 없이 실행될 대상을 거부합니다. +- `subagents.requireAgentId`: true이면 `agentId`를 생략한 `sessions_spawn` 호출을 차단합니다(명시적 프로필 선택 강제, 기본값: false). --- ## 다중 에이전트 라우팅 -하나의 Gateway 안에서 여러 개의 격리된 에이전트를 실행합니다. [Multi-Agent](/ko/concepts/multi-agent)를 참고하세요. +하나의 Gateway 안에서 여러 개의 격리된 에이전트를 실행합니다. [다중 에이전트](/ko/concepts/multi-agent)를 참조하세요. ```json5 { @@ -1657,31 +1639,31 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 } ``` -### 바인딩 match 필드 +### 바인딩 일치 필드 -- `type`(선택): 일반 라우팅에는 `route`(누락 시 기본값), 영구 ACP 대화 바인딩에는 `acp` +- `type`(선택 사항): 일반 라우팅은 `route`(`type`이 없으면 기본값은 route), 영구 ACP 대화 바인딩은 `acp` - `match.channel`(필수) -- `match.accountId`(선택; `*` = 모든 계정, 생략 = 기본 계정) -- `match.peer`(선택; `{ kind: direct|group|channel, id }`) -- `match.guildId` / `match.teamId`(선택; 채널별) -- `acp`(선택; `type: "acp"`일 때만): `{ mode, label, cwd, backend }` +- `match.accountId`(선택 사항, `*` = 모든 계정, 생략 = 기본 계정) +- `match.peer`(선택 사항, `{ kind: direct|group|channel, id }`) +- `match.guildId` / `match.teamId`(선택 사항, 채널별) +- `acp`(선택 사항, `type: "acp"`일 때만): `{ mode, label, cwd, backend }` -**결정적 match 순서:** +**결정적 일치 순서:** 1. `match.peer` 2. `match.guildId` 3. `match.teamId` -4. `match.accountId`(정확 일치, peer/guild/team 없음) +4. `match.accountId`(정확히 일치, peer/guild/team 없음) 5. `match.accountId: "*"`(채널 전체) 6. 기본 에이전트 -같은 tier 안에서는 먼저 일치하는 `bindings` 항목이 우선합니다. +각 단계 안에서는 첫 번째로 일치하는 `bindings` 항목이 적용됩니다. -`type: "acp"` 항목의 경우 OpenClaw는 정확한 대화 식별자(`match.channel` + account + `match.peer.id`)로 해결하며, 위의 route 바인딩 tier 순서는 사용하지 않습니다. +`type: "acp"` 항목의 경우 OpenClaw는 정확한 대화 식별자(`match.channel` + account + `match.peer.id`)로 해석하며, 위의 route 바인딩 단계 순서는 사용하지 않습니다. -### 에이전트별 액세스 프로필 +### 에이전트별 접근 프로필 - + ```json5 { @@ -1728,7 +1710,7 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 - + ```json5 { @@ -1774,7 +1756,7 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 -우선순위 세부 정보는 [Multi-Agent Sandbox & Tools](/ko/tools/multi-agent-sandbox-tools)를 참고하세요. +우선순위 세부 사항은 [다중 에이전트 샌드박스 및 도구](/ko/tools/multi-agent-sandbox-tools)를 참조하세요. --- @@ -1800,7 +1782,7 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 }, resetTriggers: ["/new", "/reset"], store: "~/.openclaw/agents/{agentId}/sessions/sessions.json", - parentForkMaxTokens: 100000, // 이 토큰 수를 초과하면 부모 스레드 포크 건너뜀(0은 비활성화) + parentForkMaxTokens: 100000, // 이 토큰 수를 넘으면 parent-thread 포크 건너뜀(0이면 비활성화) maintenance: { mode: "warn", // warn | enforce pruneAfter: "30d", @@ -1812,8 +1794,8 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 }, threadBindings: { enabled: true, - idleHours: 24, // 기본 비활성 자동 unfocus 시간(`0`은 비활성화) - maxAgeHours: 0, // 기본 하드 최대 사용 기간(`0`은 비활성화) + idleHours: 24, // 기본 비활성 자동 포커스 해제 시간(`0`이면 비활성화) + maxAgeHours: 0, // 기본 하드 최대 수명 시간(`0`이면 비활성화) }, mainKey: "main", // 레거시(런타임은 항상 "main" 사용) agentToAgent: { maxPingPongTurns: 5 }, @@ -1827,35 +1809,35 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 -- **`scope`**: 그룹 채팅 컨텍스트용 기본 세션 그룹화 전략입니다. - - `per-sender`(기본값): 채널 컨텍스트 안에서 각 발신자가 격리된 세션을 가집니다. +- **`scope`**: 그룹 채팅 컨텍스트의 기본 세션 그룹화 전략입니다. + - `per-sender`(기본값): 채널 컨텍스트 내에서 각 발신자마다 격리된 세션을 사용합니다. - `global`: 채널 컨텍스트의 모든 참여자가 하나의 세션을 공유합니다(공유 컨텍스트가 의도된 경우에만 사용). - **`dmScope`**: DM을 그룹화하는 방식입니다. - - `main`: 모든 DM이 메인 세션을 공유합니다. + - `main`: 모든 DM이 기본 세션을 공유합니다. - `per-peer`: 채널 전반에서 발신자 ID별로 격리합니다. - - `per-channel-peer`: 채널 + 발신자별로 격리합니다(다중 사용자 inbox에 권장). + - `per-channel-peer`: 채널 + 발신자별로 격리합니다(다중 사용자 받은편지함에 권장). - `per-account-channel-peer`: 계정 + 채널 + 발신자별로 격리합니다(다중 계정에 권장). -- **`identityLinks`**: 채널 간 세션 공유를 위한 provider 접두어 peer에 정식 ID를 매핑합니다. -- **`reset`**: 기본 reset 정책입니다. `daily`는 로컬 시간 기준 `atHour`에 reset하며, `idle`은 `idleMinutes` 이후 reset합니다. 둘 다 구성된 경우 먼저 만료되는 쪽이 우선합니다. -- **`resetByType`**: 타입별 재정의(`direct`, `group`, `thread`). 기존 `dm`도 `direct` 별칭으로 허용됩니다. -- **`parentForkMaxTokens`**: 포크된 스레드 세션 생성 시 허용되는 부모 세션 `totalTokens` 최대값입니다(기본값 `100000`). - - 부모 `totalTokens`가 이 값을 초과하면 OpenClaw는 부모 트랜스크립트 이력을 상속하지 않고 새로운 스레드 세션을 시작합니다. - - 이 가드를 비활성화하고 항상 부모 포크를 허용하려면 `0`으로 설정하세요. -- **`mainKey`**: 레거시 필드입니다. 런타임은 메인 direct-chat 버킷에 항상 `"main"`을 사용합니다. -- **`agentToAgent.maxPingPongTurns`**: agent-to-agent 교환 중 에이전트 사이의 최대 응답 왕복 턴 수입니다(정수, 범위: `0`–`5`). `0`은 ping-pong 체인을 비활성화합니다. -- **`sendPolicy`**: `channel`, `chatType`(`direct|group|channel`, 레거시 `dm` 별칭 지원), `keyPrefix`, 또는 `rawKeyPrefix`로 일치시킵니다. 첫 번째 deny가 우선합니다. -- **`maintenance`**: session-store 정리 + 보존 제어입니다. +- **`identityLinks`**: 채널 간 세션 공유를 위해 정식 ID를 provider 접두사가 붙은 peer에 매핑합니다. +- **`reset`**: 기본 초기화 정책입니다. `daily`는 로컬 시간 `atHour`에 초기화되고, `idle`은 `idleMinutes` 후 초기화됩니다. 둘 다 구성되면 먼저 만료되는 쪽이 적용됩니다. +- **`resetByType`**: 유형별 재정의(`direct`, `group`, `thread`)입니다. 레거시 `dm`도 `direct`의 별칭으로 허용됩니다. +- **`parentForkMaxTokens`**: 포크된 스레드 세션을 만들 때 허용되는 상위 세션 `totalTokens`의 최대값입니다(기본값 `100000`). + - 상위 `totalTokens`가 이 값을 초과하면 OpenClaw는 상위 transcript 기록을 상속하는 대신 새 스레드 세션을 시작합니다. + - 이 보호를 비활성화하고 항상 상위 포크를 허용하려면 `0`으로 설정하세요. +- **`mainKey`**: 레거시 필드입니다. 런타임은 기본 direct-chat 버킷에 항상 `"main"`을 사용합니다. +- **`agentToAgent.maxPingPongTurns`**: 에이전트 간 교환 중 답장-재답장 턴의 최대 횟수입니다(정수, 범위: `0`–`5`). `0`은 ping-pong 체인을 비활성화합니다. +- **`sendPolicy`**: `channel`, `chatType`(`direct|group|channel`, 레거시 `dm` 별칭 포함), `keyPrefix`, 또는 `rawKeyPrefix`로 일치시킵니다. 첫 번째 deny가 우선합니다. +- **`maintenance`**: 세션 저장소 정리 + 보존 제어입니다. - `mode`: `warn`은 경고만 출력하고, `enforce`는 정리를 적용합니다. - - `pruneAfter`: 오래된 항목에 대한 연령 컷오프입니다(기본값 `30d`). + - `pruneAfter`: 오래된 항목의 기간 기준값입니다(기본값 `30d`). - `maxEntries`: `sessions.json`의 최대 항목 수입니다(기본값 `500`). - - `rotateBytes`: `sessions.json`이 이 크기를 초과하면 회전시킵니다(기본값 `10mb`). - - `resetArchiveRetention`: `*.reset.` 트랜스크립트 아카이브의 보존 기간입니다. 기본값은 `pruneAfter`이며, 비활성화하려면 `false`로 설정하세요. + - `rotateBytes`: `sessions.json`이 이 크기를 넘으면 회전합니다(기본값 `10mb`). + - `resetArchiveRetention`: `*.reset.` transcript 아카이브의 보존 기간입니다. 기본값은 `pruneAfter`이며, 비활성화하려면 `false`로 설정하세요. - `maxDiskBytes`: 선택적 세션 디렉터리 디스크 예산입니다. `warn` 모드에서는 경고를 기록하고, `enforce` 모드에서는 가장 오래된 아티팩트/세션부터 제거합니다. - - `highWaterBytes`: 예산 정리 후 목표값(선택 사항)입니다. 기본값은 `maxDiskBytes`의 `80%`입니다. + - `highWaterBytes`: 예산 정리 후의 선택적 목표값입니다. 기본값은 `maxDiskBytes`의 `80%`입니다. - **`threadBindings`**: 스레드 바인딩 세션 기능의 전역 기본값입니다. - - `enabled`: 마스터 기본 스위치(provider가 재정의 가능; Discord는 `channels.discord.threadBindings.enabled` 사용) - - `idleHours`: 비활성 자동 unfocus의 기본 시간(`0`은 비활성화, provider 재정의 가능) - - `maxAgeHours`: 하드 최대 사용 기간의 기본 시간(`0`은 비활성화, provider 재정의 가능) + - `enabled`: 마스터 기본 스위치입니다(provider가 재정의할 수 있으며, Discord는 `channels.discord.threadBindings.enabled` 사용) + - `idleHours`: 비활성 자동 포커스 해제의 기본 시간 수입니다(`0`은 비활성화, provider가 재정의 가능) + - `maxAgeHours`: 하드 최대 수명의 기본 시간 수입니다(`0`은 비활성화, provider가 재정의 가능) @@ -1881,7 +1863,7 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 }, }, inbound: { - debounceMs: 2000, // 0 disables + debounceMs: 2000, // 0이면 비활성화 byChannel: { whatsapp: 5000, slack: 1500, @@ -1895,7 +1877,7 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 채널/계정별 재정의: `channels..responsePrefix`, `channels..accounts..responsePrefix`. -해결 순서(가장 구체적인 값이 우선): 계정 → 채널 → 전역. `""`는 비활성화하며 연쇄 적용도 중단합니다. `"auto"`는 `[{identity.name}]`를 파생합니다. +해결 순서(가장 구체적인 것이 우선): account → channel → global. `""`는 비활성화하며 상위 단계 탐색도 중단합니다. `"auto"`는 `[{identity.name}]`를 파생합니다. **템플릿 변수:** @@ -1905,26 +1887,26 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 | `{modelFull}` | 전체 모델 식별자 | `anthropic/claude-opus-4-6` | | `{provider}` | provider 이름 | `anthropic` | | `{thinkingLevel}` | 현재 thinking 수준 | `high`, `low`, `off` | -| `{identity.name}` | 에이전트 identity 이름 | ( `"auto"`와 동일) | +| `{identity.name}` | 에이전트 identity 이름 | (`"auto"`와 동일) | 변수는 대소문자를 구분하지 않습니다. `{think}`는 `{thinkingLevel}`의 별칭입니다. -### Ack 리액션 +### 확인 반응 -- 기본값은 활성 에이전트의 `identity.emoji`, 없으면 `"👀"`입니다. 비활성화하려면 `""`로 설정하세요. +- 기본값은 활성 에이전트의 `identity.emoji`이고, 없으면 `"👀"`입니다. 비활성화하려면 `""`로 설정하세요. - 채널별 재정의: `channels..ackReaction`, `channels..accounts..ackReaction`. -- 해결 순서: 계정 → 채널 → `messages.ackReaction` → identity 대체값. +- 해결 순서: account → channel → `messages.ackReaction` → identity 대체값. - 범위: `group-mentions`(기본값), `group-all`, `direct`, `all`. -- `removeAckAfterReply`: Slack, Discord, Telegram에서 응답 후 ack를 제거합니다. -- `messages.statusReactions.enabled`: Slack, Discord, Telegram에서 수명 주기 상태 리액션을 활성화합니다. - Slack과 Discord에서는 미설정 시 ack 리액션이 활성화되어 있으면 상태 리액션도 활성화된 상태를 유지합니다. - Telegram에서는 수명 주기 상태 리액션을 활성화하려면 이를 명시적으로 `true`로 설정해야 합니다. +- `removeAckAfterReply`: Slack, Discord, Telegram에서 응답 후 확인 반응을 제거합니다. +- `messages.statusReactions.enabled`: Slack, Discord, Telegram에서 수명 주기 상태 반응을 활성화합니다. + Slack과 Discord에서는 설정하지 않으면 확인 반응이 활성화되어 있을 때 상태 반응도 활성화된 상태를 유지합니다. + Telegram에서는 수명 주기 상태 반응을 활성화하려면 이를 명시적으로 `true`로 설정하세요. -### 인바운드 디바운스 +### 수신 debounce -같은 발신자의 빠른 텍스트 전용 메시지를 하나의 에이전트 턴으로 묶습니다. 미디어/첨부 파일은 즉시 flush됩니다. 제어 명령은 디바운스를 우회합니다. +같은 발신자의 빠른 텍스트 전용 메시지를 하나의 에이전트 턴으로 묶습니다. 미디어/첨부 파일은 즉시 flush됩니다. 제어 명령은 debounce를 우회합니다. -### TTS (text-to-speech) +### TTS(텍스트 음성 변환) ```json5 { @@ -1965,18 +1947,18 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 } ``` -- `auto`는 기본 자동 TTS 모드를 제어합니다: `off`, `always`, `inbound`, 또는 `tagged`. `/tts on|off`는 로컬 기본 설정을 재정의할 수 있고, `/tts status`는 실제 적용 상태를 표시합니다. -- `summaryModel`은 자동 요약용 `agents.defaults.model.primary`를 재정의합니다. -- `modelOverrides`는 기본적으로 활성화되어 있습니다. `modelOverrides.allowProvider`의 기본값은 `false`(opt-in)입니다. +- `auto`는 기본 자동 TTS 모드를 제어합니다: `off`, `always`, `inbound`, 또는 `tagged`. `/tts on|off`는 로컬 기본 설정을 재정의할 수 있으며, `/tts status`는 실제 적용 상태를 보여줍니다. +- `summaryModel`은 자동 요약에 대해 `agents.defaults.model.primary`를 재정의합니다. +- `modelOverrides`는 기본적으로 활성화되어 있으며, `modelOverrides.allowProvider`의 기본값은 `false`입니다(opt-in). - API 키는 `ELEVENLABS_API_KEY`/`XI_API_KEY` 및 `OPENAI_API_KEY`로 대체됩니다. - `openai.baseUrl`은 OpenAI TTS 엔드포인트를 재정의합니다. 해결 순서는 config, 그다음 `OPENAI_TTS_BASE_URL`, 그다음 `https://api.openai.com/v1`입니다. -- `openai.baseUrl`이 OpenAI가 아닌 엔드포인트를 가리키면 OpenClaw는 이를 OpenAI 호환 TTS 서버로 간주하고 모델/voice 검증을 완화합니다. +- `openai.baseUrl`이 OpenAI가 아닌 엔드포인트를 가리키면 OpenClaw는 이를 OpenAI 호환 TTS 서버로 처리하고 model/voice 검증을 완화합니다. --- ## Talk -Talk 모드(macOS/iOS/Android)의 기본값입니다. +Talk 모드의 기본값입니다(macOS/iOS/Android). ```json5 { @@ -2000,13 +1982,13 @@ Talk 모드(macOS/iOS/Android)의 기본값입니다. } ``` -- `talk.provider`는 여러 Talk provider가 구성된 경우 `talk.providers`의 키와 일치해야 합니다. -- 기존 평면 Talk 키(`talk.voiceId`, `talk.voiceAliases`, `talk.modelId`, `talk.outputFormat`, `talk.apiKey`)는 호환성 전용이며 `talk.providers.`로 자동 마이그레이션됩니다. -- Voice ID는 `ELEVENLABS_VOICE_ID` 또는 `SAG_VOICE_ID`로 대체됩니다. -- `providers.*.apiKey`는 일반 텍스트 문자열 또는 SecretRef 객체를 받을 수 있습니다. +- 여러 Talk provider가 구성된 경우 `talk.provider`는 `talk.providers`의 키와 일치해야 합니다. +- 레거시 평면 Talk 키(`talk.voiceId`, `talk.voiceAliases`, `talk.modelId`, `talk.outputFormat`, `talk.apiKey`)는 호환성 전용이며 `talk.providers.`로 자동 마이그레이션됩니다. +- 음성 ID는 `ELEVENLABS_VOICE_ID` 또는 `SAG_VOICE_ID`로 대체됩니다. +- `providers.*.apiKey`는 일반 텍스트 문자열 또는 SecretRef 객체를 허용합니다. - `ELEVENLABS_API_KEY` 대체값은 Talk API 키가 구성되지 않은 경우에만 적용됩니다. - `providers.*.voiceAliases`는 Talk 지시문에서 친숙한 이름을 사용할 수 있게 합니다. -- `silenceTimeoutMs`는 사용자가 말하지 않은 후 Talk 모드가 트랜스크립트를 전송하기까지 기다리는 시간을 제어합니다. 미설정 시 플랫폼 기본 일시정지 창을 유지합니다(`macOS 및 Android는 700 ms, iOS는 900 ms`). +- `silenceTimeoutMs`는 사용자가 침묵한 뒤 Talk 모드가 transcript를 보내기 전에 기다리는 시간을 제어합니다. 설정하지 않으면 플랫폼 기본 일시정지 창이 유지됩니다(`macOS와 Android는 700 ms, iOS는 900 ms`). --- @@ -2014,37 +1996,37 @@ Talk 모드(macOS/iOS/Android)의 기본값입니다. ### 도구 프로필 -`tools.profile`은 `tools.allow`/`tools.deny` 이전에 적용되는 기본 허용 목록을 설정합니다. +`tools.profile`은 `tools.allow`/`tools.deny` 전에 기본 허용 목록을 설정합니다. -로컬 온보딩은 설정되지 않은 새 로컬 config에 기본적으로 `tools.profile: "coding"`을 적용합니다(기존 명시적 프로필은 유지). +로컬 온보딩은 설정되지 않은 새 로컬 구성에 기본적으로 `tools.profile: "coding"`을 설정합니다(기존의 명시적 프로필은 유지됨). -| 프로필 | 포함 항목 | -| ----------- | ----------------------------------------------------------------------------------------------------------------------------- | -| `minimal` | `session_status`만 | -| `coding` | `group:fs`, `group:runtime`, `group:web`, `group:sessions`, `group:memory`, `cron`, `image`, `image_generate`, `video_generate` | +| 프로필 | 포함 항목 | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------ | +| `minimal` | `session_status`만 | +| `coding` | `group:fs`, `group:runtime`, `group:web`, `group:sessions`, `group:memory`, `cron`, `image`, `image_generate`, `video_generate` | | `messaging` | `group:messaging`, `sessions_list`, `sessions_history`, `sessions_send`, `session_status` | -| `full` | 제한 없음(미설정과 동일) | +| `full` | 제한 없음(설정하지 않은 경우와 동일) | ### 도구 그룹 -| 그룹 | 도구 | -| ------------------ | ---------------------------------------------------------------------------------------------------------------------- | -| `group:runtime` | `exec`, `process`, `code_execution` (`bash`는 `exec`의 별칭으로 허용됨) | -| `group:fs` | `read`, `write`, `edit`, `apply_patch` | +| 그룹 | 도구 | +| ------------------ | ----------------------------------------------------------------------------------------------------------------------- | +| `group:runtime` | `exec`, `process`, `code_execution` (`bash`는 `exec`의 별칭으로 허용됨) | +| `group:fs` | `read`, `write`, `edit`, `apply_patch` | | `group:sessions` | `sessions_list`, `sessions_history`, `sessions_send`, `sessions_spawn`, `sessions_yield`, `subagents`, `session_status` | -| `group:memory` | `memory_search`, `memory_get` | -| `group:web` | `web_search`, `x_search`, `web_fetch` | -| `group:ui` | `browser`, `canvas` | -| `group:automation` | `cron`, `gateway` | -| `group:messaging` | `message` | -| `group:nodes` | `nodes` | -| `group:agents` | `agents_list` | -| `group:media` | `image`, `image_generate`, `video_generate`, `tts` | -| `group:openclaw` | 모든 내장 도구(provider 플러그인 제외) | +| `group:memory` | `memory_search`, `memory_get` | +| `group:web` | `web_search`, `x_search`, `web_fetch` | +| `group:ui` | `browser`, `canvas` | +| `group:automation` | `cron`, `gateway` | +| `group:messaging` | `message` | +| `group:nodes` | `nodes` | +| `group:agents` | `agents_list` | +| `group:media` | `image`, `image_generate`, `video_generate`, `tts` | +| `group:openclaw` | 모든 기본 제공 도구(provider plugins 제외) | ### `tools.allow` / `tools.deny` -전역 도구 허용/거부 정책입니다(deny가 우선). 대소문자를 구분하지 않으며 `*` 와일드카드를 지원합니다. Docker sandbox가 꺼져 있어도 적용됩니다. +전역 도구 허용/거부 정책입니다(거부 우선). 대소문자를 구분하지 않으며 `*` 와일드카드를 지원합니다. Docker sandbox가 꺼져 있어도 적용됩니다. ```json5 { @@ -2070,7 +2052,7 @@ Talk 모드(macOS/iOS/Android)의 기본값입니다. ### `tools.elevated` -sandbox 밖의 elevated exec 액세스를 제어합니다: +sandbox 외부의 elevated exec 접근을 제어합니다. ```json5 { @@ -2086,9 +2068,9 @@ sandbox 밖의 elevated exec 액세스를 제어합니다: } ``` -- 에이전트별 재정의(`agents.list[].tools.elevated`)는 더 제한적으로만 설정할 수 있습니다. -- `/elevated on|off|ask|full`은 세션별 상태를 저장하며, 인라인 지시문은 단일 메시지에만 적용됩니다. -- Elevated `exec`는 sandboxing을 우회하고 구성된 escape path를 사용합니다(기본값은 `gateway`, exec 대상이 `node`인 경우 `node`). +- 에이전트별 재정의(`agents.list[].tools.elevated`)는 더 제한하는 경우에만 가능합니다. +- `/elevated on|off|ask|full`은 상태를 세션별로 저장하며, 인라인 지시문은 단일 메시지에만 적용됩니다. +- Elevated `exec`는 sandboxing을 우회하며 구성된 탈출 경로를 사용합니다(`gateway`가 기본값이고, exec 대상이 `node`이면 `node` 사용). ### `tools.exec` @@ -2112,8 +2094,8 @@ sandbox 밖의 elevated exec 액세스를 제어합니다: ### `tools.loopDetection` -도구 루프 안전 검사는 기본적으로 **비활성화**되어 있습니다. 감지를 활성화하려면 `enabled: true`로 설정하세요. -설정은 전역 `tools.loopDetection`에 정의할 수 있고 에이전트별 `agents.list[].tools.loopDetection`에서 재정의할 수 있습니다. +도구 루프 안전성 검사는 기본적으로 **비활성화**되어 있습니다. 탐지를 활성화하려면 `enabled: true`를 설정하세요. +설정은 전역 `tools.loopDetection`에 정의할 수 있고, `agents.list[].tools.loopDetection`에서 에이전트별로 재정의할 수 있습니다. ```json5 { @@ -2134,13 +2116,13 @@ sandbox 밖의 elevated exec 액세스를 제어합니다: } ``` -- `historySize`: 루프 분석을 위해 유지할 최대 도구 호출 이력입니다. -- `warningThreshold`: 경고를 위한 반복 무진전 패턴 임계값입니다. -- `criticalThreshold`: 치명적 루프 차단을 위한 더 높은 반복 임계값입니다. -- `globalCircuitBreakerThreshold`: 어떤 무진전 실행에도 적용되는 하드 중단 임계값입니다. +- `historySize`: 루프 분석을 위해 유지되는 최대 도구 호출 기록 수입니다. +- `warningThreshold`: 경고를 발생시키는 반복적인 무진전 패턴 임계값입니다. +- `criticalThreshold`: 심각한 루프를 차단하는 더 높은 반복 임계값입니다. +- `globalCircuitBreakerThreshold`: 모든 무진전 실행에 대한 하드 중단 임계값입니다. - `detectors.genericRepeat`: 동일 도구/동일 인자 호출 반복 시 경고합니다. -- `detectors.knownPollNoProgress`: 알려진 poll 도구(`process.poll`, `command_status` 등)의 무진전 상태를 경고/차단합니다. -- `detectors.pingPong`: 번갈아 나타나는 무진전 쌍 패턴을 경고/차단합니다. +- `detectors.knownPollNoProgress`: 알려진 폴링 도구(`process.poll`, `command_status` 등)의 무진전 상태를 경고/차단합니다. +- `detectors.pingPong`: 교대하는 무진전 쌍 패턴을 경고/차단합니다. - `warningThreshold >= criticalThreshold` 또는 `criticalThreshold >= globalCircuitBreakerThreshold`이면 검증이 실패합니다. ### `tools.web` @@ -2151,14 +2133,14 @@ sandbox 밖의 elevated exec 액세스를 제어합니다: web: { search: { enabled: true, - apiKey: "brave_api_key", // 또는 BRAVE_API_KEY env + apiKey: "brave_api_key", // 또는 BRAVE_API_KEY 환경 변수 maxResults: 5, timeoutSeconds: 30, cacheTtlMinutes: 15, }, fetch: { enabled: true, - provider: "firecrawl", // 선택 사항; 자동 감지를 원하면 생략 + provider: "firecrawl", // 선택 사항, 자동 감지를 원하면 생략 maxChars: 50000, maxCharsCap: 50000, maxResponseBytes: 2000000, @@ -2175,7 +2157,7 @@ sandbox 밖의 elevated exec 액세스를 제어합니다: ### `tools.media` -인바운드 미디어 이해(image/audio/video)를 구성합니다: +수신 미디어 이해(image/audio/video)를 구성합니다. ```json5 { @@ -2183,7 +2165,7 @@ sandbox 밖의 elevated exec 액세스를 제어합니다: media: { concurrency: 2, asyncCompletion: { - directSend: false, // opt-in: 완료된 async music/video를 채널로 직접 전송 + directSend: false, // opt-in: 완료된 비동기 music/video를 채널로 직접 전송 }, audio: { enabled: true, @@ -2211,7 +2193,7 @@ sandbox 밖의 elevated exec 액세스를 제어합니다: **Provider 항목** (`type: "provider"` 또는 생략): -- `provider`: API provider id (`openai`, `anthropic`, `google`/`gemini`, `groq` 등) +- `provider`: API provider ID(`openai`, `anthropic`, `google`/`gemini`, `groq` 등) - `model`: 모델 ID 재정의 - `profile` / `preferredProfile`: `auth-profiles.json` 프로필 선택 @@ -2224,15 +2206,13 @@ sandbox 밖의 elevated exec 액세스를 제어합니다: - `capabilities`: 선택적 목록(`image`, `audio`, `video`). 기본값: `openai`/`anthropic`/`minimax` → image, `google` → image+audio+video, `groq` → audio. - `prompt`, `maxChars`, `maxBytes`, `timeoutSeconds`, `language`: 항목별 재정의. -- 실패 시 다음 항목으로 대체됩니다. +- 실패하면 다음 항목으로 대체됩니다. -Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env vars → `models.providers.*.apiKey`. +Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → 환경 변수 → `models.providers.*.apiKey`. **비동기 완료 필드:** -- `asyncCompletion.directSend`: `true`일 때 완료된 async `music_generate` - 및 `video_generate` 작업은 먼저 direct 채널 전달을 시도합니다. 기본값: `false` - (기존 requester-session wake/model-delivery 경로). +- `asyncCompletion.directSend`: `true`이면 완료된 비동기 `music_generate` 및 `video_generate` 작업이 먼저 채널 직접 전달을 시도합니다. 기본값: `false`(레거시 요청자 세션 깨우기/모델 전달 경로). @@ -2251,9 +2231,9 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v ### `tools.sessions` -세션 도구(`sessions_list`, `sessions_history`, `sessions_send`)가 대상으로 삼을 수 있는 세션을 제어합니다. +세션 도구(`sessions_list`, `sessions_history`, `sessions_send`)가 대상으로 지정할 수 있는 세션을 제어합니다. -기본값: `tree`(현재 세션 + 현재 세션이 생성한 세션, 예: subagent). +기본값: `tree`(현재 세션 + 현재 세션이 생성한 세션, 예: 하위 에이전트). ```json5 { @@ -2269,10 +2249,10 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v 참고: - `self`: 현재 세션 키만. -- `tree`: 현재 세션 + 현재 세션이 생성한 세션(subagent). -- `agent`: 현재 agent id에 속한 모든 세션(같은 agent id 아래 per-sender 세션을 실행 중이면 다른 사용자 포함 가능). -- `all`: 모든 세션. 교차 에이전트 대상 지정에는 여전히 `tools.agentToAgent`가 필요합니다. -- Sandbox clamp: 현재 세션이 sandbox 상태이고 `agents.defaults.sandbox.sessionToolsVisibility="spawned"`이면 `tools.sessions.visibility="all"`이더라도 visibility는 강제로 `tree`가 됩니다. +- `tree`: 현재 세션 + 현재 세션이 생성한 세션(하위 에이전트). +- `agent`: 현재 에이전트 ID에 속한 모든 세션(같은 에이전트 ID 아래에서 발신자별 세션을 실행하면 다른 사용자도 포함될 수 있음). +- `all`: 모든 세션. 에이전트 간 대상 지정에는 여전히 `tools.agentToAgent`가 필요합니다. +- Sandbox clamp: 현재 세션이 sandbox 상태이고 `agents.defaults.sandbox.sessionToolsVisibility="spawned"`이면, `tools.sessions.visibility="all"`이어도 visibility는 강제로 `tree`가 됩니다. ### `tools.sessions_spawn` @@ -2283,7 +2263,7 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v tools: { sessions_spawn: { attachments: { - enabled: false, // opt-in: true로 설정하면 인라인 파일 첨부 허용 + enabled: false, // opt-in: 인라인 파일 첨부를 허용하려면 true로 설정 maxTotalBytes: 5242880, // 모든 파일 합계 5 MB maxFiles: 50, maxFileBytes: 1048576, // 파일당 1 MB @@ -2297,15 +2277,15 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v 참고: - 첨부 파일은 `runtime: "subagent"`에서만 지원됩니다. ACP 런타임은 이를 거부합니다. -- 파일은 `.manifest.json`과 함께 child workspace의 `.openclaw/attachments//`에 구체화됩니다. -- 첨부 내용은 트랜스크립트 영속성에서 자동으로 redaction됩니다. -- Base64 입력은 엄격한 알파벳/패딩 검사와 디코드 전 크기 가드로 검증됩니다. +- 파일은 `.manifest.json`과 함께 자식 workspace의 `.openclaw/attachments//`에 구체화됩니다. +- 첨부 파일 내용은 transcript 영속화에서 자동으로 숨김 처리됩니다. +- Base64 입력은 엄격한 알파벳/패딩 검사와 디코딩 전 크기 보호를 통해 검증됩니다. - 파일 권한은 디렉터리 `0700`, 파일 `0600`입니다. -- 정리는 `cleanup` 정책을 따릅니다: `delete`는 항상 첨부 파일을 제거하고, `keep`은 `retainOnSessionKeep: true`일 때만 유지합니다. +- 정리는 `cleanup` 정책을 따릅니다. `delete`는 항상 첨부를 제거하고, `keep`은 `retainOnSessionKeep: true`일 때만 유지합니다. ### `tools.experimental` -실험적 내장 도구 플래그입니다. 런타임별 자동 활성화 규칙이 적용되지 않는 한 기본값은 꺼짐입니다. +실험적 기본 제공 도구 플래그입니다. 런타임별 자동 활성화 규칙이 적용되지 않는 한 기본값은 off입니다. ```json5 { @@ -2319,8 +2299,8 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v 참고: -- `planTool`: 중요하고 여러 단계인 작업 추적을 위한 구조화된 `update_plan` 도구를 활성화합니다. -- 기본값: OpenAI가 아닌 provider에서는 `false`. OpenAI 및 OpenAI Codex 실행에서는 미설정 시 자동 활성화되며, 이 자동 활성화를 끄려면 `false`로 설정하세요. +- `planTool`: 사소하지 않은 다단계 작업 추적을 위한 구조화된 `update_plan` 도구를 활성화합니다. +- 기본값: OpenAI가 아닌 provider에서는 `false`. OpenAI 및 OpenAI Codex 실행은 설정되지 않았을 때 이를 자동 활성화하며, 비활성화하려면 `false`로 설정하세요. - 활성화되면 시스템 프롬프트에도 사용 지침이 추가되어 모델이 실질적인 작업에만 이를 사용하고 `in_progress` 단계는 최대 하나만 유지하도록 합니다. ### `agents.defaults.subagents` @@ -2341,16 +2321,16 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v } ``` -- `model`: 생성된 sub-agent의 기본 모델입니다. 생략하면 sub-agent는 호출자의 모델을 상속합니다. -- `allowAgents`: 요청자 에이전트가 자체 `subagents.allowAgents`를 설정하지 않은 경우 `sessions_spawn` 대상 agent id의 기본 허용 목록입니다(`["*"]` = 모두 허용, 기본값: 동일 에이전트만). -- `runTimeoutSeconds`: 도구 호출에서 `runTimeoutSeconds`를 생략한 경우 `sessions_spawn`의 기본 timeout(초)입니다. `0`은 timeout 없음입니다. -- subagent별 도구 정책: `tools.subagents.tools.allow` / `tools.subagents.tools.deny`. +- `model`: 생성된 하위 에이전트의 기본 모델입니다. 생략하면 하위 에이전트는 호출자의 모델을 상속합니다. +- `allowAgents`: 요청 에이전트가 자체 `subagents.allowAgents`를 설정하지 않았을 때 `sessions_spawn` 대상 에이전트 ID의 기본 허용 목록입니다(`["*"]` = 아무 에이전트나, 기본값: 동일 에이전트만). +- `runTimeoutSeconds`: 도구 호출에서 `runTimeoutSeconds`를 생략했을 때 `sessions_spawn`의 기본 시간 제한(초)입니다. `0`은 시간 제한 없음입니다. +- 하위 에이전트별 도구 정책: `tools.subagents.tools.allow` / `tools.subagents.tools.deny`. --- -## 사용자 지정 provider 및 base URL +## 사용자 지정 provider와 base URL -OpenClaw는 내장 모델 카탈로그를 사용합니다. 사용자 지정 provider는 config의 `models.providers` 또는 `~/.openclaw/agents//agent/models.json`을 통해 추가하세요. +OpenClaw는 기본 제공 모델 카탈로그를 사용합니다. 사용자 지정 provider는 config의 `models.providers` 또는 `~/.openclaw/agents//agent/models.json`을 통해 추가하세요. ```json5 { @@ -2380,46 +2360,47 @@ OpenClaw는 내장 모델 카탈로그를 사용합니다. 사용자 지정 prov ``` - 사용자 지정 인증이 필요하면 `authHeader: true` + `headers`를 사용하세요. -- 에이전트 config 루트는 `OPENCLAW_AGENT_DIR`(또는 레거시 환경 변수 별칭 `PI_CODING_AGENT_DIR`)로 재정의할 수 있습니다. +- `OPENCLAW_AGENT_DIR`로 agent config 루트를 재정의할 수 있습니다(또는 레거시 환경 변수 별칭인 `PI_CODING_AGENT_DIR`). - 일치하는 provider ID에 대한 병합 우선순위: - 비어 있지 않은 agent `models.json` `baseUrl` 값이 우선합니다. - 비어 있지 않은 agent `apiKey` 값은 현재 config/auth-profile 컨텍스트에서 해당 provider가 SecretRef로 관리되지 않을 때만 우선합니다. - - SecretRef로 관리되는 provider `apiKey` 값은 해결된 비밀을 영속화하는 대신 소스 마커(`ENV_VAR_NAME`은 env ref, `secretref-managed`는 file/exec ref)에서 새로고침됩니다. - - SecretRef로 관리되는 provider header 값은 소스 마커(`secretref-env:ENV_VAR_NAME`는 env ref, `secretref-managed`는 file/exec ref)에서 새로고침됩니다. - - 비어 있거나 누락된 agent `apiKey`/`baseUrl`은 config의 `models.providers`로 대체됩니다. - - 일치하는 모델 `contextWindow`/`maxTokens`는 명시적 config 값과 암시적 카탈로그 값 중 더 높은 값을 사용합니다. - - 일치하는 모델 `contextTokens`는 명시적 런타임 cap이 존재하면 이를 유지합니다. 모델의 기본 `contextWindow`를 바꾸지 않고 실제 컨텍스트를 제한할 때 사용하세요. + - SecretRef로 관리되는 provider `apiKey` 값은 해석된 비밀을 저장하는 대신 소스 마커(`ENV_VAR_NAME`은 환경 변수 참조, `secretref-managed`는 file/exec 참조)에서 새로 고쳐집니다. + - SecretRef로 관리되는 provider header 값은 소스 마커(`secretref-env:ENV_VAR_NAME`은 환경 변수 참조, `secretref-managed`는 file/exec 참조)에서 새로 고쳐집니다. + - 비어 있거나 없는 agent `apiKey`/`baseUrl`은 config의 `models.providers`로 대체됩니다. + - 일치하는 모델의 `contextWindow`/`maxTokens`는 명시적 config 값과 암시적 카탈로그 값 중 더 큰 값을 사용합니다. + - 일치하는 모델의 `contextTokens`는 명시적인 런타임 상한이 있으면 이를 유지합니다. 기본 모델 메타데이터를 바꾸지 않고 실제 컨텍스트를 제한할 때 사용하세요. - config가 `models.json`을 완전히 다시 쓰게 하려면 `models.mode: "replace"`를 사용하세요. - - 마커 영속성은 소스가 권위입니다. 마커는 해결된 런타임 비밀값이 아니라 활성 소스 config 스냅샷(해결 전)에서 기록됩니다. + - 마커 영속성은 소스 권위를 따릅니다. 마커는 해석된 런타임 비밀값이 아니라 활성 소스 config 스냅샷(해석 전)에서 기록됩니다. ### Provider 필드 세부 정보 -- `models.mode`: provider 카탈로그 동작(`merge` 또는 `replace`). -- `models.providers`: provider id를 키로 하는 사용자 지정 provider 맵. -- `models.providers.*.api`: 요청 어댑터(`openai-completions`, `openai-responses`, `anthropic-messages`, `google-generative-ai` 등). -- `models.providers.*.apiKey`: provider 자격 증명(SecretRef/env 치환 사용 권장). -- `models.providers.*.auth`: 인증 전략(`api-key`, `token`, `oauth`, `aws-sdk`). +- `models.mode`: provider 카탈로그 동작입니다(`merge` 또는 `replace`). +- `models.providers`: provider ID를 키로 하는 사용자 지정 provider 맵입니다. +- `models.providers.*.api`: 요청 어댑터입니다(`openai-completions`, `openai-responses`, `anthropic-messages`, `google-generative-ai` 등). +- `models.providers.*.apiKey`: provider 자격 증명입니다(SecretRef/환경 변수 치환 권장). +- `models.providers.*.auth`: 인증 전략입니다(`api-key`, `token`, `oauth`, `aws-sdk`). - `models.providers.*.injectNumCtxForOpenAICompat`: Ollama + `openai-completions`용으로 요청에 `options.num_ctx`를 주입합니다(기본값: `true`). -- `models.providers.*.authHeader`: 필요 시 `Authorization` 헤더를 통한 자격 증명 전송을 강제합니다. -- `models.providers.*.baseUrl`: 업스트림 API base URL. -- `models.providers.*.headers`: 프록시/테넌트 라우팅용 추가 정적 헤더. -- `models.providers.*.request`: model-provider HTTP 요청용 전송 재정의. - - `request.headers`: 추가 헤더(provider 기본값과 병합). 값은 SecretRef를 받을 수 있습니다. - - `request.auth`: 인증 전략 재정의. 모드: `"provider-default"`(provider 기본 인증 사용), `"authorization-bearer"`(`token`과 함께 사용), `"header"`(`headerName`, `value`, 선택적 `prefix`와 함께 사용). - - `request.proxy`: HTTP 프록시 재정의. 모드: `"env-proxy"`(`HTTP_PROXY`/`HTTPS_PROXY` env vars 사용), `"explicit-proxy"`(`url`과 함께 사용). 두 모드 모두 선택적 `tls` 하위 객체를 받을 수 있습니다. - - `request.tls`: direct 연결용 TLS 재정의. 필드: `ca`, `cert`, `key`, `passphrase`(모두 SecretRef 지원), `serverName`, `insecureSkipVerify`. -- `models.providers.*.models`: 명시적 provider 모델 카탈로그 항목. -- `models.providers.*.models.*.contextWindow`: 기본 모델 컨텍스트 창 메타데이터. -- `models.providers.*.models.*.contextTokens`: 선택적 런타임 컨텍스트 cap입니다. 모델의 기본 `contextWindow`보다 더 작은 실제 컨텍스트 예산을 원할 때 사용하세요. -- `models.providers.*.models.*.compat.supportsDeveloperRole`: 선택적 호환성 힌트. `api: "openai-completions"`이고 비어 있지 않은 비네이티브 `baseUrl`(호스트가 `api.openai.com`이 아님)인 경우 OpenClaw는 런타임에 이를 `false`로 강제합니다. 비어 있거나 생략된 `baseUrl`은 기본 OpenAI 동작을 유지합니다. -- `models.providers.*.models.*.compat.requiresStringContent`: 문자열 전용 OpenAI 호환 chat 엔드포인트용 선택적 호환성 힌트입니다. `true`일 때 OpenClaw는 요청 전 순수 텍스트 `messages[].content` 배열을 일반 문자열로 평탄화합니다. -- `plugins.entries.amazon-bedrock.config.discovery`: Bedrock 자동 발견 설정 루트. -- `plugins.entries.amazon-bedrock.config.discovery.enabled`: 암시적 발견 켜기/끄기. -- `plugins.entries.amazon-bedrock.config.discovery.region`: 발견용 AWS 리전. -- `plugins.entries.amazon-bedrock.config.discovery.providerFilter`: 대상 발견용 선택적 provider-id 필터. -- `plugins.entries.amazon-bedrock.config.discovery.refreshInterval`: 발견 새로고침 polling 간격. -- `plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow`: 발견된 모델용 대체 컨텍스트 창. -- `plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens`: 발견된 모델용 대체 최대 출력 토큰. +- `models.providers.*.authHeader`: 필요할 때 `Authorization` 헤더를 통한 자격 증명 전달을 강제합니다. +- `models.providers.*.baseUrl`: 업스트림 API base URL입니다. +- `models.providers.*.headers`: 프록시/테넌트 라우팅을 위한 추가 정적 헤더입니다. +- `models.providers.*.request`: model-provider HTTP 요청의 전송 재정의입니다. + - `request.headers`: 추가 헤더입니다(provider 기본값과 병합). 값은 SecretRef를 허용합니다. + - `request.auth`: 인증 전략 재정의입니다. 모드: `"provider-default"`(provider의 기본 제공 인증 사용), `"authorization-bearer"`(`token`과 함께 사용), `"header"`(`headerName`, `value`, 선택적 `prefix`와 함께 사용). + - `request.proxy`: HTTP 프록시 재정의입니다. 모드: `"env-proxy"`(`HTTP_PROXY`/`HTTPS_PROXY` 환경 변수 사용), `"explicit-proxy"`(`url`과 함께 사용). 두 모드 모두 선택적 `tls` 하위 객체를 허용합니다. + - `request.tls`: 직접 연결용 TLS 재정의입니다. 필드: `ca`, `cert`, `key`, `passphrase`(모두 SecretRef 허용), `serverName`, `insecureSkipVerify`. + - `request.allowPrivateNetwork`: `true`이면 provider HTTP fetch 보호를 통해 DNS가 private, CGNAT 또는 유사 범위로 해석되는 `baseUrl`에 대한 HTTPS를 허용합니다(신뢰된 자체 호스팅 OpenAI 호환 엔드포인트를 위한 operator opt-in). WebSocket은 헤더/TLS에 동일한 `request`를 사용하지만 해당 fetch SSRF 게이트는 사용하지 않습니다. 기본값은 `false`입니다. +- `models.providers.*.models`: 명시적인 provider 모델 카탈로그 항목입니다. +- `models.providers.*.models.*.contextWindow`: 기본 모델 컨텍스트 창 메타데이터입니다. +- `models.providers.*.models.*.contextTokens`: 선택적 런타임 컨텍스트 상한입니다. 모델의 기본 `contextWindow`보다 더 작은 실제 컨텍스트 예산을 원할 때 사용하세요. +- `models.providers.*.models.*.compat.supportsDeveloperRole`: 선택적 호환성 힌트입니다. 비어 있지 않은 비기본 `baseUrl`(호스트가 `api.openai.com`이 아님)을 사용하는 `api: "openai-completions"`의 경우 OpenClaw는 런타임에 이를 강제로 `false`로 설정합니다. 비어 있거나 생략된 `baseUrl`은 기본 OpenAI 동작을 유지합니다. +- `models.providers.*.models.*.compat.requiresStringContent`: 문자열 전용 OpenAI 호환 채팅 엔드포인트를 위한 선택적 호환성 힌트입니다. `true`이면 OpenClaw는 요청을 보내기 전에 순수 텍스트 `messages[].content` 배열을 일반 문자열로 평탄화합니다. +- `plugins.entries.amazon-bedrock.config.discovery`: Bedrock 자동 탐지 설정 루트입니다. +- `plugins.entries.amazon-bedrock.config.discovery.enabled`: 암시적 탐지를 켜거나 끕니다. +- `plugins.entries.amazon-bedrock.config.discovery.region`: 탐지에 사용할 AWS 리전입니다. +- `plugins.entries.amazon-bedrock.config.discovery.providerFilter`: 대상 탐지를 위한 선택적 provider ID 필터입니다. +- `plugins.entries.amazon-bedrock.config.discovery.refreshInterval`: 탐지 새로 고침의 폴링 간격입니다. +- `plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow`: 탐지된 모델에 대한 대체 컨텍스트 창입니다. +- `plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens`: 탐지된 모델에 대한 대체 최대 출력 토큰 수입니다. ### Provider 예시 @@ -2457,7 +2438,7 @@ OpenClaw는 내장 모델 카탈로그를 사용합니다. 사용자 지정 prov } ``` -Cerebras에는 `cerebras/zai-glm-4.7`을, Z.AI direct에는 `zai/glm-4.7`을 사용하세요. +Cerebras에는 `cerebras/zai-glm-4.7`을 사용하세요. Z.AI 직접 연결에는 `zai/glm-4.7`을 사용하세요. @@ -2474,7 +2455,7 @@ Cerebras에는 `cerebras/zai-glm-4.7`을, Z.AI direct에는 `zai/glm-4.7`을 사 } ``` -`OPENCODE_API_KEY`(또는 `OPENCODE_ZEN_API_KEY`)를 설정하세요. Zen 카탈로그에는 `opencode/...` ref를, Go 카탈로그에는 `opencode-go/...` ref를 사용하세요. 바로가기: `openclaw onboard --auth-choice opencode-zen` 또는 `openclaw onboard --auth-choice opencode-go`. +`OPENCODE_API_KEY`(또는 `OPENCODE_ZEN_API_KEY`)를 설정하세요. Zen 카탈로그에는 `opencode/...` 참조를, Go 카탈로그에는 `opencode-go/...` 참조를 사용하세요. 바로가기: `openclaw onboard --auth-choice opencode-zen` 또는 `openclaw onboard --auth-choice opencode-go`. @@ -2495,7 +2476,7 @@ Cerebras에는 `cerebras/zai-glm-4.7`을, Z.AI direct에는 `zai/glm-4.7`을 사 - 일반 엔드포인트: `https://api.z.ai/api/paas/v4` - 코딩 엔드포인트(기본값): `https://api.z.ai/api/coding/paas/v4` -- 일반 엔드포인트를 쓰려면 base URL 재정의가 포함된 사용자 지정 provider를 정의하세요. +- 일반 엔드포인트를 사용하려면 base URL 재정의가 포함된 사용자 지정 provider를 정의하세요. @@ -2534,11 +2515,9 @@ Cerebras에는 `cerebras/zai-glm-4.7`을, Z.AI direct에는 `zai/glm-4.7`을 사 } ``` -중국 엔드포인트: `baseUrl: "https://api.moonshot.cn/v1"` 또는 `openclaw onboard --auth-choice moonshot-api-key-cn`. +중국 엔드포인트의 경우: `baseUrl: "https://api.moonshot.cn/v1"` 또는 `openclaw onboard --auth-choice moonshot-api-key-cn`. -네이티브 Moonshot 엔드포인트는 공유 -`openai-completions` 전송에서 스트리밍 사용 호환성을 광고하며, -OpenClaw는 내장 provider id만이 아니라 해당 엔드포인트 기능을 기준으로 동작을 판단합니다. +기본 Moonshot 엔드포인트는 공유 `openai-completions` 전송에서 스트리밍 사용 호환성을 광고하며, OpenClaw는 내장 provider ID만이 아니라 엔드포인트 기능을 기준으로 이를 판단합니다. @@ -2556,11 +2535,11 @@ OpenClaw는 내장 provider id만이 아니라 해당 엔드포인트 기능을 } ``` -Anthropic 호환 내장 provider입니다. 바로가기: `openclaw onboard --auth-choice kimi-code-api-key`. +Anthropic 호환 기본 제공 provider입니다. 바로가기: `openclaw onboard --auth-choice kimi-code-api-key`. - + ```json5 { @@ -2595,11 +2574,11 @@ Anthropic 호환 내장 provider입니다. 바로가기: `openclaw onboard --aut } ``` -Base URL에는 `/v1`를 포함하지 않아야 합니다(Anthropic 클라이언트가 이를 자동으로 추가함). 바로가기: `openclaw onboard --auth-choice synthetic-api-key`. +base URL은 `/v1`을 포함하지 않아야 합니다(Anthropic 클라이언트가 이를 추가함). 바로가기: `openclaw onboard --auth-choice synthetic-api-key`. - + ```json5 { @@ -2638,17 +2617,14 @@ Base URL에는 `/v1`를 포함하지 않아야 합니다(Anthropic 클라이언 `MINIMAX_API_KEY`를 설정하세요. 바로가기: `openclaw onboard --auth-choice minimax-global-api` 또는 `openclaw onboard --auth-choice minimax-cn-api`. -모델 카탈로그는 기본적으로 M2.7만 포함합니다. -Anthropic 호환 스트리밍 경로에서는, -명시적으로 `thinking`을 설정하지 않는 한 OpenClaw가 MiniMax thinking을 기본적으로 비활성화합니다. `/fast on` 또는 -`params.fastMode: true`는 `MiniMax-M2.7`을 -`MiniMax-M2.7-highspeed`로 다시 씁니다. +모델 카탈로그 기본값은 M2.7만 포함합니다. +Anthropic 호환 스트리밍 경로에서 OpenClaw는 `thinking`을 직접 설정하지 않는 한 기본적으로 MiniMax thinking을 비활성화합니다. `/fast on` 또는 `params.fastMode: true`는 `MiniMax-M2.7`을 `MiniMax-M2.7-highspeed`로 다시 씁니다. -[Local Models](/ko/gateway/local-models)를 참고하세요. 요약: 충분한 하드웨어에서 LM Studio Responses API를 통해 대형 로컬 모델을 실행하고, 대체용으로 호스팅 모델은 병합된 상태로 유지하세요. +[로컬 모델](/ko/gateway/local-models)을 참조하세요. 요약: 충분한 하드웨어에서 LM Studio Responses API를 통해 대형 로컬 모델을 실행하고, fallback용으로 호스팅 모델은 병합된 상태로 유지하세요. @@ -2679,14 +2655,12 @@ Anthropic 호환 스트리밍 경로에서는, } ``` -- `allowBundled`: 번들 skill 전용 선택적 허용 목록입니다(관리형/workspace skill에는 영향 없음). -- `load.extraDirs`: 추가 공유 skill 루트(가장 낮은 우선순위). -- `install.preferBrew`: `brew` 사용 가능 시 다른 설치 방식으로 대체하기 전에 - Homebrew 설치 프로그램을 우선 사용합니다. -- `install.nodeManager`: `metadata.openclaw.install` - spec용 node 설치 관리자 선호도 (`npm` | `pnpm` | `yarn` | `bun`). -- `entries..enabled: false`는 번들/설치된 skill이라도 비활성화합니다. -- `entries..apiKey`: 기본 env var를 선언하는 skill에 대한 편의 필드입니다(일반 텍스트 문자열 또는 SecretRef 객체). +- `allowBundled`: 번들 Skills 전용 선택적 허용 목록입니다(managed/workspace Skills는 영향 없음). +- `load.extraDirs`: 추가 공유 Skills 루트입니다(가장 낮은 우선순위). +- `install.preferBrew`: `true`이면 `brew`를 사용할 수 있을 때 다른 설치 방식으로 대체하기 전에 Homebrew 설치를 우선 사용합니다. +- `install.nodeManager`: `metadata.openclaw.install` 사양용 node 설치 관리자 선호도입니다(`npm` | `pnpm` | `yarn` | `bun`). +- `entries..enabled: false`는 번들/설치된 Skill이라도 비활성화합니다. +- `entries..apiKey`: 기본 환경 변수를 선언하는 Skills를 위한 편의 필드입니다(일반 텍스트 문자열 또는 SecretRef 객체). --- @@ -2715,48 +2689,980 @@ Anthropic 호환 스트리밍 경로에서는, ``` - `~/.openclaw/extensions`, `/.openclaw/extensions`, 그리고 `plugins.load.paths`에서 로드됩니다. -- 검색은 네이티브 OpenClaw 플러그인과 호환되는 Codex 번들, Claude 번들, manifest가 없는 Claude 기본 레이아웃 번들을 모두 허용합니다. -- **Config 변경에는 gateway 재시작이 필요합니다.** -- `allow`: 선택적 허용 목록(목록에 있는 플러그인만 로드). `deny`가 우선합니다. -- `plugins.entries..apiKey`: 플러그인이 지원하는 경우 플러그인 수준 API 키 편의 필드입니다. -- `plugins.entries..env`: 플러그인 범위 env var 맵입니다. -- `plugins.entries..hooks.allowPromptInjection`: `false`일 때 core는 `before_prompt_build`를 차단하고, 기존 `before_agent_start`의 프롬프트 변경 필드를 무시하며, 기존 `modelOverride`와 `providerOverride`는 유지합니다. 네이티브 plugin hook과 지원되는 번들 제공 hook 디렉터리에 적용됩니다. -- `plugins.entries..subagent.allowModelOverride`: 이 플러그인이 백그라운드 subagent 실행에 대해 회차별 `provider` 및 `model` 재정의를 요청하도록 명시적으로 신뢰합니다. -- `plugins.entries..subagent.allowedModels`: 신뢰된 subagent 재정의에 대한 선택적 정식 `provider/model` 대상 허용 목록입니다. 모든 모델을 허용하려는 의도가 분명할 때만 `"*"`를 사용하세요. -- `plugins.entries..config`: 플러그인 정의 config 객체입니다(가능한 경우 네이티브 OpenClaw 플러그인 schema로 검증됨). -- `plugins.entries.firecrawl.config.webFetch`: Firecrawl web-fetch provider 설정. - - `apiKey`: Firecrawl API 키(SecretRef 지원). `plugins.entries.firecrawl.config.webSearch.apiKey`, 기존 `tools.web.fetch.firecrawl.apiKey`, 또는 `FIRECRAWL_API_KEY` env var로 대체됩니다. - - `baseUrl`: Firecrawl API base URL(기본값: `https://api.firecrawl.dev`). - - `onlyMainContent`: 페이지에서 주요 콘텐츠만 추출합니다(기본값: `true`). - - `maxAgeMs`: 최대 캐시 유지 기간(밀리초, 기본값: `172800000` / 2일). - - `timeoutSeconds`: scrape 요청 timeout(초, 기본값: `60`). -- `plugins.entries.xai.config.xSearch`: xAI X Search (Grok web search) 설정. - - `enabled`: X Search provider 활성화. - - `model`: 검색에 사용할 Grok 모델(예: `"grok-4-1-fast"`). -- `plugins.entries.memory-core.config.dreaming`: memory dreaming(실험적) 설정. 단계 및 임계값은 [Dreaming](/ko/concepts/dreaming)을 참고하세요. - - `enabled`: dreaming 마스터 스위치(기본값 `false`). - - `frequency`: 각 전체 dreaming sweep의 cron 주기(기본값 `"0 3 * * *"`). - - 단계 정책과 임계값은 구현 세부 사항이며 사용자 대상 config 키가 아닙니다. -- 전체 memory config는 [Memory configuration reference](/ko/reference/memory-config)에 있습니다: +- 탐지는 기본 OpenClaw plugins뿐 아니라 호환되는 Codex 번들과 Claude 번들도 허용하며, manifest가 없는 Claude 기본 레이아웃 번들도 포함합니다. +- **구성 변경에는 gateway 재시작이 필요합니다.** +- `allow`: 선택적 허용 목록입니다(목록에 있는 plugins만 로드됨). `deny`가 우선합니다. +- `plugins.entries..apiKey`: plugin 수준 API 키 편의 필드입니다(plugin이 지원하는 경우). +- `plugins.entries..env`: plugin 범위 환경 변수 맵입니다. +- `plugins.entries..hooks.allowPromptInjection`: `false`이면 core는 `before_prompt_build`를 차단하고 레거시 `before_agent_start`의 프롬프트 변경 필드를 무시하며, 레거시 `modelOverride`와 `providerOverride`는 유지합니다. 기본 plugin hooks와 지원되는 번들 제공 hook 디렉터리에 적용됩니다. +- `plugins.entries..subagent.allowModelOverride`: 이 plugin이 백그라운드 하위 에이전트 실행에 대해 실행별 `provider` 및 `model` 재정의를 요청할 수 있도록 명시적으로 신뢰합니다. +- `plugins.entries..subagent.allowedModels`: 신뢰된 하위 에이전트 재정의를 위한 선택적 정식 `provider/model` 대상 허용 목록입니다. 어떤 모델이든 허용하려는 의도가 명확할 때만 `"*"`를 사용하세요. +- `plugins.entries..config`: plugin이 정의한 구성 객체입니다(가능한 경우 기본 OpenClaw plugin 스키마로 검증됨). +- `plugins.entries.firecrawl.config.webFetch`: Firecrawl web-fetch provider 설정입니다. + - `apiKey`: Firecrawl API 키입니다(SecretRef 허용). `plugins.entries.firecrawl.config.webSearch.apiKey`, 레거시 `tools.web.fetch.firecrawl.apiKey`, 또는 `FIRECRAWL_API_KEY` 환경 변수로 대체됩니다. + - `baseUrl`: Firecrawl API base URL입니다(기본값: `https://api.firecrawl.dev`). + - `onlyMainContent`: 페이지에서 본문 콘텐츠만 추출합니다(기본값: `true`). + - `maxAgeMs`: 최대 캐시 유효 기간(밀리초)입니다(기본값: `172800000` / 2일). + - `timeoutSeconds`: 스크레이프 요청 시간 제한(초)입니다(기본값: `60`). +- `plugins.entries.xai.config.xSearch`: xAI X Search(Grok 웹 검색) 설정입니다. + - `enabled`: X Search provider를 활성화합니다. + - `model`: 검색에 사용할 Grok 모델입니다(예: `"grok-4-1-fast"`). +- `plugins.entries.memory-core.config.dreaming`: memory dreaming(실험적) 설정입니다. 단계와 임계값은 [Dreaming](/ko/concepts/dreaming)을 참조하세요. + - `enabled`: dreaming 마스터 스위치입니다(기본값 `false`). + - `frequency`: 각 전체 dreaming 스윕의 cron 주기입니다(기본값 `"0 3 * * *"`). + - 단계 정책과 임계값은 구현 세부 사항이며(사용자 대상 구성 키 아님). +- 전체 memory 구성은 [메모리 구성 참조](/ko/reference/memory-config)에 있습니다. - `agents.defaults.memorySearch.*` - `memory.backend` - `memory.citations` - `memory.qmd.*` - `plugins.entries.memory-core.config.dreaming` -- 활성화된 Claude bundle plugin은 `settings.json`에서 포함된 Pi 기본값을 제공할 수도 있으며, OpenClaw는 이를 원시 OpenClaw config patch가 아닌 정제된 agent 설정으로 적용합니다. -- `plugins.slots.memory`: 활성 memory plugin id를 선택하거나, memory plugin을 비활성화하려면 `"none"`으로 설정합니다. -- `plugins.slots.contextEngine`: 활성 context engine plugin id를 선택합니다. 다른 엔진을 설치하고 선택하지 않는 한 기본값은 `"legacy"`입니다. +- 활성화된 Claude 번들 plugins는 `settings.json`의 내장 Pi 기본값도 제공할 수 있습니다. OpenClaw는 이를 원시 OpenClaw config 패치가 아니라 정제된 에이전트 설정으로 적용합니다. +- `plugins.slots.memory`: 활성 memory plugin ID를 선택하거나, memory plugins를 비활성화하려면 `"none"`을 사용합니다. +- `plugins.slots.contextEngine`: 활성 context engine plugin ID를 선택합니다. 다른 engine을 설치하고 선택하지 않는 한 기본값은 `"legacy"`입니다. - `plugins.installs`: `openclaw plugins update`에서 사용하는 CLI 관리 설치 메타데이터입니다. - `source`, `spec`, `sourcePath`, `installPath`, `version`, `resolvedName`, `resolvedVersion`, `resolvedSpec`, `integrity`, `shasum`, `resolvedAt`, `installedAt`를 포함합니다. - - `plugins.installs.*`는 관리 상태로 취급하세요. 수동 편집보다 CLI 명령을 사용하는 것이 좋습니다. + - `plugins.installs.*`는 관리되는 상태로 취급하세요. 수동 편집보다 CLI 명령 사용을 권장합니다. -[Plugins](/ko/tools/plugin)를 참고하세요. +[플러그인](/ko/tools/plugin)을 참조하세요. --- -## Browser +## 브라우저 ```json5 { browser: { - enabled: true, \ No newline at end of file + enabled: true, + evaluateEnabled: true, + defaultProfile: "user", + ssrfPolicy: { + dangerouslyAllowPrivateNetwork: true, // 기본 신뢰 네트워크 모드 + // allowPrivateNetwork: true, // 레거시 별칭 + // hostnameAllowlist: ["*.example.com", "example.com"], + // allowedHostnames: ["localhost"], + }, + profiles: { + openclaw: { cdpPort: 18800, color: "#FF4500" }, + work: { cdpPort: 18801, color: "#0066CC" }, + user: { driver: "existing-session", attachOnly: true, color: "#00AA00" }, + brave: { + driver: "existing-session", + attachOnly: true, + userDataDir: "~/Library/Application Support/BraveSoftware/Brave-Browser", + color: "#FB542B", + }, + remote: { cdpUrl: "http://10.0.0.42:9222", color: "#00AA00" }, + }, + color: "#FF4500", + // headless: false, + // noSandbox: false, + // extraArgs: [], + // executablePath: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser", + // attachOnly: false, + }, +} +``` + +- `evaluateEnabled: false`는 `act:evaluate`와 `wait --fn`을 비활성화합니다. +- `ssrfPolicy.dangerouslyAllowPrivateNetwork`는 설정되지 않았을 때 기본값이 `true`입니다(신뢰 네트워크 모델). +- 엄격한 공개 전용 브라우저 탐색을 원하면 `ssrfPolicy.dangerouslyAllowPrivateNetwork: false`로 설정하세요. +- 엄격 모드에서는 원격 CDP 프로필 엔드포인트(`profiles.*.cdpUrl`)도 도달 가능성/탐지 검사 중 동일한 사설 네트워크 차단의 적용을 받습니다. +- `ssrfPolicy.allowPrivateNetwork`는 레거시 별칭으로 계속 지원됩니다. +- 엄격 모드에서는 명시적 예외에 `ssrfPolicy.hostnameAllowlist`와 `ssrfPolicy.allowedHostnames`를 사용하세요. +- 원격 프로필은 attach-only입니다(시작/중지/초기화 비활성화). +- `profiles.*.cdpUrl`은 `http://`, `https://`, `ws://`, `wss://`를 허용합니다. + OpenClaw가 `/json/version`을 탐지하게 하려면 HTTP(S)를 사용하세요. + provider가 직접 DevTools WebSocket URL을 제공하는 경우 WS(S)를 사용하세요. +- `existing-session` 프로필은 호스트 전용이며 CDP 대신 Chrome MCP를 사용합니다. +- `existing-session` 프로필은 Brave 또는 Edge 같은 특정 Chromium 기반 브라우저 프로필을 대상으로 삼기 위해 `userDataDir`를 설정할 수 있습니다. +- `existing-session` 프로필은 현재 Chrome MCP 경로 제한을 유지합니다. CSS 선택자 대상 지정 대신 snapshot/ref 기반 작업, 단일 파일 업로드 hook, 대화 상자 시간 제한 재정의 없음, `wait --load networkidle` 없음, `responsebody`, PDF 내보내기, 다운로드 가로채기, 배치 작업도 지원하지 않습니다. +- 로컬 관리형 `openclaw` 프로필은 `cdpPort`와 `cdpUrl`을 자동 할당합니다. 원격 CDP에만 `cdpUrl`을 명시적으로 설정하세요. +- 자동 감지 순서: 기본 브라우저가 Chromium 기반이면 먼저 사용 → Chrome → Brave → Edge → Chromium → Chrome Canary. +- 제어 서비스: loopback 전용(포트는 `gateway.port`에서 파생되며 기본값은 `18791`). +- `extraArgs`는 로컬 Chromium 시작에 추가 실행 플래그를 덧붙입니다(예: `--disable-gpu`, 창 크기 조정, 디버그 플래그). + +--- + +## UI + +```json5 +{ + ui: { + seamColor: "#FF4500", + assistant: { + name: "OpenClaw", + avatar: "CB", // 이모지, 짧은 텍스트, 이미지 URL 또는 data URI + }, + }, +} +``` + +- `seamColor`: 기본 앱 UI 크롬의 강조 색상입니다(Talk Mode 버블 틴트 등). +- `assistant`: Control UI identity 재정의입니다. 활성 에이전트 identity로 대체됩니다. + +--- + +## Gateway + +```json5 +{ + gateway: { + mode: "local", // local | remote + port: 18789, + bind: "loopback", + auth: { + mode: "token", // none | token | password | trusted-proxy + token: "your-token", + // password: "your-password", // 또는 OPENCLAW_GATEWAY_PASSWORD + // trustedProxy: { userHeader: "x-forwarded-user" }, // mode=trusted-proxy용, /gateway/trusted-proxy-auth 참조 + allowTailscale: true, + rateLimit: { + maxAttempts: 10, + windowMs: 60000, + lockoutMs: 300000, + exemptLoopback: true, + }, + }, + tailscale: { + mode: "off", // off | serve | funnel + resetOnExit: false, + }, + controlUi: { + enabled: true, + basePath: "/openclaw", + // root: "dist/control-ui", + // allowedOrigins: ["https://control.example.com"], // loopback이 아닌 Control UI에는 필수 + // dangerouslyAllowHostHeaderOriginFallback: false, // 위험한 Host-header origin 대체 모드 + // allowInsecureAuth: false, + // dangerouslyDisableDeviceAuth: false, + }, + remote: { + url: "ws://gateway.tailnet:18789", + transport: "ssh", // ssh | direct + token: "your-token", + // password: "your-password", + }, + trustedProxies: ["10.0.0.1"], + // 선택 사항. 기본값 false. + allowRealIpFallback: false, + tools: { + // 추가 /tools/invoke HTTP 거부 + deny: ["browser"], + // 기본 HTTP 거부 목록에서 도구 제거 + allow: ["gateway"], + }, + push: { + apns: { + relay: { + baseUrl: "https://relay.example.com", + timeoutMs: 10000, + }, + }, + }, + }, +} +``` + + + +- `mode`: `local`(gateway 실행) 또는 `remote`(원격 gateway 연결)입니다. Gateway는 `local`이 아니면 시작을 거부합니다. +- `port`: WS + HTTP용 단일 멀티플렉스 포트입니다. 우선순위: `--port` > `OPENCLAW_GATEWAY_PORT` > `gateway.port` > `18789`. +- `bind`: `auto`, `loopback`(기본값), `lan`(`0.0.0.0`), `tailnet`(Tailscale IP만), 또는 `custom`. +- **레거시 bind 별칭**: `gateway.bind`에는 호스트 별칭(`0.0.0.0`, `127.0.0.1`, `localhost`, `::`, `::1`)이 아니라 bind 모드 값(`auto`, `loopback`, `lan`, `tailnet`, `custom`)을 사용하세요. +- **Docker 참고**: 기본 `loopback` bind는 컨테이너 내부의 `127.0.0.1`에서 수신 대기합니다. Docker 브리지 네트워킹(`-p 18789:18789`)에서는 트래픽이 `eth0`로 도착하므로 gateway에 접근할 수 없습니다. `--network host`를 사용하거나, 모든 인터페이스에서 수신 대기하도록 `bind: "lan"`(또는 `customBindHost: "0.0.0.0"`를 사용하는 `bind: "custom"`)을 설정하세요. +- **인증**: 기본적으로 필요합니다. loopback이 아닌 bind에는 gateway 인증이 필요합니다. 실제로는 공유 token/password 또는 `gateway.auth.mode: "trusted-proxy"`를 사용하는 identity-aware reverse proxy를 의미합니다. 온보딩 마법사는 기본적으로 token을 생성합니다. +- `gateway.auth.token`과 `gateway.auth.password`가 둘 다 구성된 경우(SecretRef 포함), `gateway.auth.mode`를 `token` 또는 `password`로 명시적으로 설정하세요. 둘 다 구성되어 있고 mode가 설정되지 않으면 시작 및 서비스 설치/복구 흐름이 실패합니다. +- `gateway.auth.mode: "none"`: 명시적 무인증 모드입니다. 신뢰된 로컬 loopback 설정에서만 사용하세요. 이는 의도적으로 온보딩 프롬프트에서 제공되지 않습니다. +- `gateway.auth.mode: "trusted-proxy"`: 인증을 identity-aware reverse proxy에 위임하고 `gateway.trustedProxies`의 identity 헤더를 신뢰합니다([신뢰 프록시 인증](/ko/gateway/trusted-proxy-auth) 참조). 이 모드는 **loopback이 아닌** 프록시 소스를 기대합니다. 같은 호스트의 loopback reverse proxy는 trusted-proxy 인증 조건을 만족하지 않습니다. +- `gateway.auth.allowTailscale`: `true`이면 Tailscale Serve identity 헤더가 Control UI/WebSocket 인증을 만족할 수 있습니다(`tailscale whois`로 검증). HTTP API 엔드포인트는 해당 Tailscale 헤더 인증을 사용하지 않으며, 대신 gateway의 일반 HTTP 인증 모드를 따릅니다. 이 token 없는 흐름은 gateway 호스트가 신뢰된다는 전제를 둡니다. `tailscale.mode = "serve"`일 때 기본값은 `true`입니다. +- `gateway.auth.rateLimit`: 선택적 인증 실패 제한기입니다. 클라이언트 IP와 인증 범위별로 적용됩니다(공유 비밀과 device-token은 독립적으로 추적됨). 차단된 시도는 `429` + `Retry-After`를 반환합니다. + - 비동기 Tailscale Serve Control UI 경로에서는 동일한 `{scope, clientIp}`에 대한 실패 시도가 실패 기록 전에 직렬화됩니다. 따라서 같은 클라이언트의 동시 잘못된 시도는 둘 다 단순 불일치로 통과하는 대신 두 번째 요청에서 제한기에 걸릴 수 있습니다. + - `gateway.auth.rateLimit.exemptLoopback`의 기본값은 `true`입니다. localhost 트래픽에도 의도적으로 rate limit을 적용하려면(`테스트 설정이나 엄격한 프록시 배포 등`) `false`로 설정하세요. +- 브라우저 출처 WS 인증 시도는 loopback 예외를 비활성화한 상태로 항상 제한됩니다(브라우저 기반 localhost brute force에 대한 심층 방어). +- loopback에서는 이러한 브라우저 출처 lockout이 정규화된 `Origin` 값별로 격리되므로, 한 localhost origin의 반복 실패가 다른 origin까지 자동으로 잠그지는 않습니다. +- `tailscale.mode`: `serve`(tailnet 전용, loopback bind) 또는 `funnel`(공개, 인증 필요). +- `controlUi.allowedOrigins`: Gateway WebSocket 연결용 명시적 브라우저 origin 허용 목록입니다. browser 클라이언트가 loopback이 아닌 origin에서 올 것으로 예상되면 필수입니다. +- `controlUi.dangerouslyAllowHostHeaderOriginFallback`: Host-header origin 정책에 의도적으로 의존하는 배포를 위해 Host-header origin 대체를 활성화하는 위험한 모드입니다. +- `remote.transport`: `ssh`(기본값) 또는 `direct`(ws/wss). `direct`의 경우 `remote.url`은 `ws://` 또는 `wss://`여야 합니다. +- `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`: 신뢰된 사설 네트워크 IP에 대한 평문 `ws://`를 허용하는 클라이언트 측 비상 수단 재정의입니다. 기본값은 여전히 loopback 전용 평문 허용입니다. +- `gateway.remote.token` / `.password`는 원격 클라이언트 자격 증명 필드입니다. 이것만으로 gateway 인증을 구성하지는 않습니다. +- `gateway.push.apns.relay.baseUrl`: 공식/TestFlight iOS 빌드가 relay 기반 등록을 gateway에 게시한 뒤 사용하는 외부 APNs relay의 기본 HTTPS URL입니다. 이 URL은 iOS 빌드에 컴파일된 relay URL과 일치해야 합니다. +- `gateway.push.apns.relay.timeoutMs`: gateway에서 relay로 보내는 시간 제한(밀리초)입니다. 기본값은 `10000`입니다. +- Relay 기반 등록은 특정 gateway identity에 위임됩니다. 페어링된 iOS 앱은 `gateway.identity.get`을 가져오고, 그 identity를 relay 등록에 포함하며, 등록 범위 send grant를 gateway로 전달합니다. 다른 gateway는 저장된 해당 등록을 재사용할 수 없습니다. +- `OPENCLAW_APNS_RELAY_BASE_URL` / `OPENCLAW_APNS_RELAY_TIMEOUT_MS`: 위 relay 구성에 대한 임시 환경 변수 재정의입니다. +- `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true`: loopback HTTP relay URL을 위한 개발 전용 비상 탈출구입니다. 운영 relay URL은 HTTPS를 유지해야 합니다. +- `gateway.channelHealthCheckMinutes`: 채널 상태 모니터 간격(분)입니다. 상태 모니터 재시작을 전역으로 비활성화하려면 `0`으로 설정하세요. 기본값: `5`. +- `gateway.channelStaleEventThresholdMinutes`: 오래된 소켓 임계값(분)입니다. 이는 `gateway.channelHealthCheckMinutes`보다 크거나 같아야 합니다. 기본값: `30`. +- `gateway.channelMaxRestartsPerHour`: 이동하는 1시간 동안 채널/계정별 상태 모니터 재시작 최대 횟수입니다. 기본값: `10`. +- `channels..healthMonitor.enabled`: 전역 모니터는 유지하면서 상태 모니터 재시작만 채널별로 opt-out하는 설정입니다. +- `channels..accounts..healthMonitor.enabled`: 다중 계정 채널용 계정별 재정의입니다. 설정되면 채널 수준 재정의보다 우선합니다. +- 로컬 gateway 호출 경로는 `gateway.auth.*`가 설정되지 않은 경우에만 `gateway.remote.*`를 대체값으로 사용할 수 있습니다. +- `gateway.auth.token` / `gateway.auth.password`가 SecretRef로 명시적으로 구성되어 있으나 해석되지 않으면, 해석은 닫힌 상태로 실패합니다(원격 대체가 이를 가리지 않음). +- `trustedProxies`: TLS를 종료하거나 전달된 클라이언트 헤더를 주입하는 reverse proxy IP입니다. 직접 제어하는 프록시만 나열하세요. loopback 항목도 동일 호스트 프록시/로컬 탐지 설정(예: Tailscale Serve 또는 로컬 reverse proxy)에는 여전히 유효하지만, loopback 요청이 `gateway.auth.mode: "trusted-proxy"` 대상이 되도록 만들지는 않습니다. +- `allowRealIpFallback`: `true`이면 `X-Forwarded-For`가 없을 때 gateway가 `X-Real-IP`를 허용합니다. 실패 시 닫힘 동작을 위해 기본값은 `false`입니다. +- `gateway.tools.deny`: HTTP `POST /tools/invoke`에 대해 차단할 추가 도구 이름입니다(기본 거부 목록 확장). +- `gateway.tools.allow`: 기본 HTTP 거부 목록에서 도구 이름을 제거합니다. + + + +### OpenAI 호환 엔드포인트 + +- Chat Completions: 기본적으로 비활성화됩니다. `gateway.http.endpoints.chatCompletions.enabled: true`로 활성화하세요. +- Responses API: `gateway.http.endpoints.responses.enabled`. +- Responses URL 입력 강화: + - `gateway.http.endpoints.responses.maxUrlParts` + - `gateway.http.endpoints.responses.files.urlAllowlist` + - `gateway.http.endpoints.responses.images.urlAllowlist` + 빈 허용 목록은 설정되지 않은 것으로 처리됩니다. URL 가져오기를 비활성화하려면 `gateway.http.endpoints.responses.files.allowUrl=false` 및/또는 `gateway.http.endpoints.responses.images.allowUrl=false`를 사용하세요. +- 선택적 응답 강화 헤더: + - `gateway.http.securityHeaders.strictTransportSecurity`(직접 제어하는 HTTPS origin에만 설정하세요. [신뢰 프록시 인증](/ko/gateway/trusted-proxy-auth#tls-termination-and-hsts) 참조) + +### 다중 인스턴스 격리 + +고유한 포트와 상태 디렉터리로 한 호스트에서 여러 gateway를 실행합니다. + +```bash +OPENCLAW_CONFIG_PATH=~/.openclaw/a.json \ +OPENCLAW_STATE_DIR=~/.openclaw-a \ +openclaw gateway --port 19001 +``` + +편의 플래그: `--dev`(`~/.openclaw-dev` + 포트 `19001` 사용), `--profile `(`~/.openclaw-` 사용). + +[여러 Gateway](/ko/gateway/multiple-gateways)를 참조하세요. + +### `gateway.tls` + +```json5 +{ + gateway: { + tls: { + enabled: false, + autoGenerate: false, + certPath: "/etc/openclaw/tls/server.crt", + keyPath: "/etc/openclaw/tls/server.key", + caPath: "/etc/openclaw/tls/ca-bundle.crt", + }, + }, +} +``` + +- `enabled`: gateway 리스너에서 TLS 종료(HTTPS/WSS)를 활성화합니다(기본값: `false`). +- `autoGenerate`: 명시적인 파일이 구성되지 않았을 때 로컬 자체 서명 cert/key 쌍을 자동 생성합니다. 로컬/개발 전용입니다. +- `certPath`: TLS 인증서 파일의 파일 시스템 경로입니다. +- `keyPath`: TLS 개인 키 파일의 파일 시스템 경로입니다. 권한을 제한해 두세요. +- `caPath`: 클라이언트 검증 또는 사용자 지정 신뢰 체인을 위한 선택적 CA 번들 경로입니다. + +### `gateway.reload` + +```json5 +{ + gateway: { + reload: { + mode: "hybrid", // off | restart | hot | hybrid + debounceMs: 500, + deferralTimeoutMs: 300000, + }, + }, +} +``` + +- `mode`: 구성 편집이 런타임에 적용되는 방식을 제어합니다. + - `"off"`: 실시간 편집을 무시합니다. 변경 사항에는 명시적 재시작이 필요합니다. + - `"restart"`: 구성 변경 시 항상 gateway 프로세스를 재시작합니다. + - `"hot"`: 재시작 없이 프로세스 내에서 변경 사항을 적용합니다. + - `"hybrid"`(기본값): 먼저 hot reload를 시도하고, 필요하면 재시작으로 대체합니다. +- `debounceMs`: 구성 변경을 적용하기 전의 debounce 창(밀리초)입니다(음수가 아닌 정수). +- `deferralTimeoutMs`: 진행 중인 작업을 기다리다가 재시작을 강제하기 전까지의 최대 시간(밀리초)입니다(기본값: `300000` = 5분). + +--- + +## Hooks + +```json5 +{ + hooks: { + enabled: true, + token: "shared-secret", + path: "/hooks", + maxBodyBytes: 262144, + defaultSessionKey: "hook:ingress", + allowRequestSessionKey: false, + allowedSessionKeyPrefixes: ["hook:"], + allowedAgentIds: ["hooks", "main"], + presets: ["gmail"], + transformsDir: "~/.openclaw/hooks/transforms", + mappings: [ + { + match: { path: "gmail" }, + action: "agent", + agentId: "hooks", + wakeMode: "now", + name: "Gmail", + sessionKey: "hook:gmail:{{messages[0].id}}", + messageTemplate: "From: {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}", + deliver: true, + channel: "last", + model: "openai/gpt-5.4-mini", + }, + ], + }, +} +``` + +인증: `Authorization: Bearer ` 또는 `x-openclaw-token: `. +쿼리 문자열 hook token은 거부됩니다. + +검증 및 안전 참고: + +- `hooks.enabled=true`에는 비어 있지 않은 `hooks.token`이 필요합니다. +- `hooks.token`은 `gateway.auth.token`과 **달라야** 합니다. Gateway token 재사용은 거부됩니다. +- `hooks.path`는 `/`일 수 없습니다. `/hooks` 같은 전용 하위 경로를 사용하세요. +- `hooks.allowRequestSessionKey=true`이면 `hooks.allowedSessionKeyPrefixes`를 제한하세요(예: `["hook:"]`). + +**엔드포인트:** + +- `POST /hooks/wake` → `{ text, mode?: "now"|"next-heartbeat" }` +- `POST /hooks/agent` → `{ message, name?, agentId?, sessionKey?, wakeMode?, deliver?, channel?, to?, model?, thinking?, timeoutSeconds? }` + - 요청 페이로드의 `sessionKey`는 `hooks.allowRequestSessionKey=true`일 때만 허용됩니다(기본값: `false`). +- `POST /hooks/` → `hooks.mappings`를 통해 해석됨 + + + +- `match.path`는 `/hooks` 뒤의 하위 경로와 일치합니다(예: `/hooks/gmail` → `gmail`). +- `match.source`는 일반 경로용 페이로드 필드와 일치합니다. +- `{{messages[0].subject}}` 같은 템플릿은 페이로드에서 값을 읽습니다. +- `transform`은 hook 작업을 반환하는 JS/TS 모듈을 가리킬 수 있습니다. + - `transform.module`은 상대 경로여야 하며 `hooks.transformsDir` 내부에 머물러야 합니다(절대 경로와 경로 탐색은 거부됨). +- `agentId`는 특정 에이전트로 라우팅합니다. 알 수 없는 ID는 기본값으로 대체됩니다. +- `allowedAgentIds`: 명시적 라우팅을 제한합니다(`*` 또는 생략 = 모두 허용, `[]` = 모두 거부). +- `defaultSessionKey`: 명시적 `sessionKey`가 없는 hook 에이전트 실행에 대한 선택적 고정 세션 키입니다. +- `allowRequestSessionKey`: `/hooks/agent` 호출자가 `sessionKey`를 설정할 수 있게 합니다(기본값: `false`). +- `allowedSessionKeyPrefixes`: 명시적 `sessionKey` 값(요청 + 매핑)에 대한 선택적 접두사 허용 목록입니다. 예: `["hook:"]`. +- `deliver: true`는 최종 응답을 채널로 보냅니다. `channel`의 기본값은 `last`입니다. +- `model`은 이 hook 실행의 LLM을 재정의합니다(모델 카탈로그가 설정되어 있으면 허용된 모델이어야 함). + + + +### Gmail 통합 + +```json5 +{ + hooks: { + gmail: { + account: "openclaw@gmail.com", + topic: "projects//topics/gog-gmail-watch", + subscription: "gog-gmail-watch-push", + pushToken: "shared-push-token", + hookUrl: "http://127.0.0.1:18789/hooks/gmail", + includeBody: true, + maxBytes: 20000, + renewEveryMinutes: 720, + serve: { bind: "127.0.0.1", port: 8788, path: "/" }, + tailscale: { mode: "funnel", path: "/gmail-pubsub" }, + model: "openrouter/meta-llama/llama-3.3-70b-instruct:free", + thinking: "off", + }, + }, +} +``` + +- 구성되면 Gateway는 부팅 시 자동으로 `gog gmail watch serve`를 시작합니다. 비활성화하려면 `OPENCLAW_SKIP_GMAIL_WATCHER=1`을 설정하세요. +- Gateway와 함께 별도의 `gog gmail watch serve`를 실행하지 마세요. + +--- + +## Canvas host + +```json5 +{ + canvasHost: { + root: "~/.openclaw/workspace/canvas", + liveReload: true, + // enabled: false, // 또는 OPENCLAW_SKIP_CANVAS_HOST=1 + }, +} +``` + +- Gateway 포트 아래 HTTP로 에이전트가 편집 가능한 HTML/CSS/JS와 A2UI를 제공합니다. + - `http://:/__openclaw__/canvas/` + - `http://:/__openclaw__/a2ui/` +- 로컬 전용: `gateway.bind: "loopback"`(기본값)을 유지하세요. +- loopback이 아닌 bind: canvas 경로는 다른 Gateway HTTP 표면과 동일하게 Gateway 인증(token/password/trusted-proxy)이 필요합니다. +- Node WebView는 일반적으로 인증 헤더를 보내지 않습니다. node가 페어링되고 연결되면 Gateway는 canvas/A2UI 접근용 node 범위 capability URL을 광고합니다. +- Capability URL은 활성 node WS 세션에 바인딩되며 빠르게 만료됩니다. IP 기반 대체는 사용되지 않습니다. +- 제공되는 HTML에 live-reload 클라이언트를 삽입합니다. +- 비어 있으면 시작용 `index.html`을 자동 생성합니다. +- `/__openclaw__/a2ui/`에서도 A2UI를 제공합니다. +- 변경 사항에는 gateway 재시작이 필요합니다. +- 디렉터리가 크거나 `EMFILE` 오류가 발생하면 live reload를 비활성화하세요. + +--- + +## 탐색 + +### mDNS (Bonjour) + +```json5 +{ + discovery: { + mdns: { + mode: "minimal", // minimal | full | off + }, + }, +} +``` + +- `minimal`(기본값): TXT 레코드에서 `cliPath` + `sshPort`를 생략합니다. +- `full`: `cliPath` + `sshPort`를 포함합니다. +- 호스트 이름 기본값은 `openclaw`입니다. `OPENCLAW_MDNS_HOSTNAME`으로 재정의하세요. + +### 광역(Wide-area, DNS-SD) + +```json5 +{ + discovery: { + wideArea: { enabled: true }, + }, +} +``` + +`~/.openclaw/dns/` 아래에 유니캐스트 DNS-SD 존을 기록합니다. 네트워크 간 탐색을 위해 DNS 서버(CoreDNS 권장) + Tailscale 분할 DNS와 함께 사용하세요. + +설정: `openclaw dns setup --apply`. + +--- + +## 환경 + +### `env`(인라인 환경 변수) + +```json5 +{ + env: { + OPENROUTER_API_KEY: "sk-or-...", + vars: { + GROQ_API_KEY: "gsk-...", + }, + shellEnv: { + enabled: true, + timeoutMs: 15000, + }, + }, +} +``` + +- 인라인 환경 변수는 프로세스 환경에 해당 키가 없을 때만 적용됩니다. +- `.env` 파일: CWD의 `.env` + `~/.openclaw/.env`(둘 다 기존 변수를 재정의하지 않음). +- `shellEnv`: 로그인 셸 프로필에서 누락된 예상 키를 가져옵니다. +- 전체 우선순위는 [환경](/ko/help/environment)을 참조하세요. + +### 환경 변수 치환 + +어떤 구성 문자열에서든 `${VAR_NAME}`으로 환경 변수를 참조할 수 있습니다. + +```json5 +{ + gateway: { + auth: { token: "${OPENCLAW_GATEWAY_TOKEN}" }, + }, +} +``` + +- 대문자 이름만 일치합니다: `[A-Z_][A-Z0-9_]*`. +- 누락되거나 빈 변수는 구성 로드 시 오류를 발생시킵니다. +- 리터럴 `${VAR}`는 `$${VAR}`로 이스케이프하세요. +- `$include`와 함께 작동합니다. + +--- + +## 비밀 + +SecretRef는 추가 기능입니다. 일반 텍스트 값도 계속 작동합니다. + +### `SecretRef` + +하나의 객체 형태를 사용하세요. + +```json5 +{ source: "env" | "file" | "exec", provider: "default", id: "..." } +``` + +검증: + +- `provider` 패턴: `^[a-z][a-z0-9_-]{0,63}$` +- `source: "env"` id 패턴: `^[A-Z][A-Z0-9_]{0,127}$` +- `source: "file"` id: 절대 JSON 포인터(예: `"/providers/openai/apiKey"`) +- `source: "exec"` id 패턴: `^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$` +- `source: "exec"` ID에는 `.` 또는 `..` 슬래시 구분 경로 세그먼트가 포함되면 안 됩니다(예: `a/../b`는 거부됨) + +### 지원되는 자격 증명 표면 + +- 정식 매트릭스: [SecretRef 자격 증명 표면](/ko/reference/secretref-credential-surface) +- `secrets apply`는 지원되는 `openclaw.json` 자격 증명 경로를 대상으로 합니다. +- `auth-profiles.json` 참조는 런타임 해석 및 감사 범위에도 포함됩니다. + +### 비밀 provider 구성 + +```json5 +{ + secrets: { + providers: { + default: { source: "env" }, // 선택적 명시적 env provider + filemain: { + source: "file", + path: "~/.openclaw/secrets.json", + mode: "json", + timeoutMs: 5000, + }, + vault: { + source: "exec", + command: "/usr/local/bin/openclaw-vault-resolver", + passEnv: ["PATH", "VAULT_ADDR"], + }, + }, + defaults: { + env: "default", + file: "filemain", + exec: "vault", + }, + }, +} +``` + +참고: + +- `file` provider는 `mode: "json"`과 `mode: "singleValue"`를 지원합니다(`singleValue` 모드에서는 `id`가 `"value"`여야 함). +- `exec` provider는 절대 `command` 경로가 필요하며 stdin/stdout의 프로토콜 페이로드를 사용합니다. +- 기본적으로 심볼릭 링크 command 경로는 거부됩니다. 해석된 대상 경로를 검증하면서 심볼릭 링크 경로를 허용하려면 `allowSymlinkCommand: true`를 설정하세요. +- `trustedDirs`가 구성된 경우 trusted-dir 검사는 해석된 대상 경로에 적용됩니다. +- `exec` 하위 프로세스 환경은 기본적으로 최소화되어 있습니다. 필요한 변수는 `passEnv`로 명시적으로 전달하세요. +- SecretRef는 활성화 시점에 메모리 내 스냅샷으로 해석되며, 이후 요청 경로는 해당 스냅샷만 읽습니다. +- 활성 표면 필터링은 활성화 중에 적용됩니다. 활성화된 표면의 해석되지 않은 참조는 시작/리로드를 실패시키고, 비활성 표면은 진단과 함께 건너뜁니다. + +--- + +## 인증 저장소 + +```json5 +{ + auth: { + profiles: { + "anthropic:default": { provider: "anthropic", mode: "api_key" }, + "anthropic:work": { provider: "anthropic", mode: "api_key" }, + "openai-codex:personal": { provider: "openai-codex", mode: "oauth" }, + }, + order: { + anthropic: ["anthropic:default", "anthropic:work"], + "openai-codex": ["openai-codex:personal"], + }, + }, +} +``` + +- 에이전트별 프로필은 `/auth-profiles.json`에 저장됩니다. +- `auth-profiles.json`은 정적 자격 증명 모드에 대해 값 수준 참조(`api_key`용 `keyRef`, `token`용 `tokenRef`)를 지원합니다. +- OAuth 모드 프로필(`auth.profiles..mode = "oauth"`)은 SecretRef 기반 auth-profile 자격 증명을 지원하지 않습니다. +- 정적 런타임 자격 증명은 메모리 내 해석 스냅샷에서 가져오며, 레거시 정적 `auth.json` 항목은 발견 시 제거됩니다. +- 레거시 OAuth는 `~/.openclaw/credentials/oauth.json`에서 가져옵니다. +- [OAuth](/ko/concepts/oauth)를 참조하세요. +- Secrets 런타임 동작과 `audit/configure/apply` 도구: [Secrets Management](/ko/gateway/secrets). + +### `auth.cooldowns` + +```json5 +{ + auth: { + cooldowns: { + billingBackoffHours: 5, + billingBackoffHoursByProvider: { anthropic: 3, openai: 8 }, + billingMaxHours: 24, + authPermanentBackoffMinutes: 10, + authPermanentMaxMinutes: 60, + failureWindowHours: 24, + overloadedProfileRotations: 1, + overloadedBackoffMs: 0, + rateLimitedProfileRotations: 1, + }, + }, +} +``` + +- `billingBackoffHours`: 실제 청구/크레딧 부족 오류로 프로필이 실패할 때의 기본 백오프 시간(시간 단위)입니다(기본값: `5`). 명시적인 청구 관련 텍스트는 `401`/`403` 응답에서도 여기에 들어올 수 있지만, provider별 텍스트 매처는 해당 provider 범위 안에만 유지됩니다(예: OpenRouter `Key limit exceeded`). 재시도 가능한 HTTP `402` 사용량 창 또는 organization/workspace 지출 한도 메시지는 대신 `rate_limit` 경로에 머뭅니다. +- `billingBackoffHoursByProvider`: 청구 백오프 시간에 대한 선택적 provider별 재정의입니다. +- `billingMaxHours`: 청구 백오프 지수 증가의 상한(시간 단위)입니다(기본값: `24`). +- `authPermanentBackoffMinutes`: 신뢰도 높은 `auth_permanent` 실패에 대한 기본 백오프(분 단위)입니다(기본값: `10`). +- `authPermanentMaxMinutes`: `auth_permanent` 백오프 증가의 상한(분 단위)입니다(기본값: `60`). +- `failureWindowHours`: 백오프 카운터에 사용되는 이동 창(시간 단위)입니다(기본값: `24`). +- `overloadedProfileRotations`: 모델 fallback으로 전환하기 전 과부하 오류에 대해 허용되는 동일 provider auth-profile 회전 최대 횟수입니다(기본값: `1`). `ModelNotReadyException` 같은 provider busy 형태가 여기에 포함됩니다. +- `overloadedBackoffMs`: 과부하된 provider/profile 회전을 재시도하기 전의 고정 지연(밀리초)입니다(기본값: `0`). +- `rateLimitedProfileRotations`: 모델 fallback으로 전환하기 전 rate-limit 오류에 대해 허용되는 동일 provider auth-profile 회전 최대 횟수입니다(기본값: `1`). 이 rate-limit 버킷에는 `Too many concurrent requests`, `ThrottlingException`, `concurrency limit reached`, `workers_ai ... quota limit exceeded`, `resource exhausted` 같은 provider 형태 텍스트가 포함됩니다. + +--- + +## 로깅 + +```json5 +{ + logging: { + level: "info", + file: "/tmp/openclaw/openclaw.log", + consoleLevel: "info", + consoleStyle: "pretty", // pretty | compact | json + redactSensitive: "tools", // off | tools + redactPatterns: ["\\bTOKEN\\b\\s*[=:]\\s*([\"']?)([^\\s\"']+)\\1"], + }, +} +``` + +- 기본 로그 파일: `/tmp/openclaw/openclaw-YYYY-MM-DD.log`. +- 고정 경로를 원하면 `logging.file`을 설정하세요. +- `consoleLevel`은 `--verbose`일 때 `debug`로 올라갑니다. +- `maxFileBytes`: 쓰기가 억제되기 전 로그 파일 최대 크기(바이트)입니다(양의 정수, 기본값: `524288000` = 500 MB). 운영 배포에서는 외부 로그 회전을 사용하세요. + +--- + +## 진단 + +```json5 +{ + diagnostics: { + enabled: true, + flags: ["telegram.*"], + stuckSessionWarnMs: 30000, + + otel: { + enabled: false, + endpoint: "https://otel-collector.example.com:4318", + protocol: "http/protobuf", // http/protobuf | grpc + headers: { "x-tenant-id": "my-org" }, + serviceName: "openclaw-gateway", + traces: true, + metrics: true, + logs: false, + sampleRate: 1.0, + flushIntervalMs: 5000, + }, + + cacheTrace: { + enabled: false, + filePath: "~/.openclaw/logs/cache-trace.jsonl", + includeMessages: true, + includePrompt: true, + includeSystem: true, + }, + }, +} +``` + +- `enabled`: 계측 출력의 마스터 토글입니다(기본값: `true`). +- `flags`: 대상 로그 출력을 활성화하는 플래그 문자열 배열입니다(`"telegram.*"` 또는 `"*"` 같은 와일드카드 지원). +- `stuckSessionWarnMs`: 세션이 처리 상태로 남아 있는 동안 정체된 세션 경고를 출력하는 기준 시간(밀리초)입니다. +- `otel.enabled`: OpenTelemetry 내보내기 파이프라인을 활성화합니다(기본값: `false`). +- `otel.endpoint`: OTel 내보내기용 수집기 URL입니다. +- `otel.protocol`: `"http/protobuf"`(기본값) 또는 `"grpc"`. +- `otel.headers`: OTel 내보내기 요청과 함께 전송되는 추가 HTTP/gRPC 메타데이터 헤더입니다. +- `otel.serviceName`: 리소스 속성용 서비스 이름입니다. +- `otel.traces` / `otel.metrics` / `otel.logs`: trace, metrics, 또는 log 내보내기를 활성화합니다. +- `otel.sampleRate`: trace 샘플링 비율 `0`–`1`. +- `otel.flushIntervalMs`: 주기적 telemetry flush 간격(밀리초)입니다. +- `cacheTrace.enabled`: 임베디드 실행용 캐시 추적 스냅샷을 기록합니다(기본값: `false`). +- `cacheTrace.filePath`: 캐시 추적 JSONL의 출력 경로입니다(기본값: `$OPENCLAW_STATE_DIR/logs/cache-trace.jsonl`). +- `cacheTrace.includeMessages` / `includePrompt` / `includeSystem`: 캐시 추적 출력에 무엇을 포함할지 제어합니다(기본값은 모두 `true`). + +--- + +## 업데이트 + +```json5 +{ + update: { + channel: "stable", // stable | beta | dev + checkOnStart: true, + + auto: { + enabled: false, + stableDelayHours: 6, + stableJitterHours: 12, + betaCheckIntervalHours: 1, + }, + }, +} +``` + +- `channel`: npm/git 설치용 릴리스 채널입니다 — `"stable"`, `"beta"`, 또는 `"dev"`. +- `checkOnStart`: gateway 시작 시 npm 업데이트를 확인합니다(기본값: `true`). +- `auto.enabled`: 패키지 설치에 대한 백그라운드 자동 업데이트를 활성화합니다(기본값: `false`). +- `auto.stableDelayHours`: stable 채널 자동 적용 전 최소 지연 시간(시간 단위)입니다(기본값: `6`; 최대: `168`). +- `auto.stableJitterHours`: stable 채널 배포 분산을 위한 추가 시간 창입니다(기본값: `12`; 최대: `168`). +- `auto.betaCheckIntervalHours`: beta 채널 확인이 실행되는 간격(시간 단위)입니다(기본값: `1`; 최대: `24`). + +--- + +## ACP + +```json5 +{ + acp: { + enabled: false, + dispatch: { enabled: true }, + backend: "acpx", + defaultAgent: "main", + allowedAgents: ["main", "ops"], + maxConcurrentSessions: 10, + + stream: { + coalesceIdleMs: 50, + maxChunkChars: 1000, + repeatSuppression: true, + deliveryMode: "live", // live | final_only + hiddenBoundarySeparator: "paragraph", // none | space | newline | paragraph + maxOutputChars: 50000, + maxSessionUpdateChars: 500, + }, + + runtime: { + ttlMinutes: 30, + }, + }, +} +``` + +- `enabled`: 전역 ACP 기능 게이트입니다(기본값: `false`). +- `dispatch.enabled`: ACP 세션 턴 디스패치를 위한 독립 게이트입니다(기본값: `true`). ACP 명령은 계속 사용 가능하게 두되 실행을 막으려면 `false`로 설정하세요. +- `backend`: 기본 ACP 런타임 backend ID입니다(등록된 ACP 런타임 plugin과 일치해야 함). +- `defaultAgent`: 생성 시 명시적 대상이 지정되지 않았을 때의 대체 ACP 대상 에이전트 ID입니다. +- `allowedAgents`: ACP 런타임 세션에 허용되는 에이전트 ID 허용 목록입니다. 비어 있으면 추가 제한이 없음을 의미합니다. +- `maxConcurrentSessions`: 동시에 활성 상태일 수 있는 ACP 세션의 최대 수입니다. +- `stream.coalesceIdleMs`: 스트리밍 텍스트용 유휴 flush 창(밀리초)입니다. +- `stream.maxChunkChars`: 스트리밍 블록 프로젝션을 분할하기 전 최대 청크 크기입니다. +- `stream.repeatSuppression`: 턴별로 반복된 상태/도구 줄을 억제합니다(기본값: `true`). +- `stream.deliveryMode`: `"live"`는 점진적으로 스트리밍하고, `"final_only"`는 턴 종료 이벤트까지 버퍼링합니다. +- `stream.hiddenBoundarySeparator`: 숨겨진 도구 이벤트 뒤에 표시되는 텍스트 앞에 넣을 구분자입니다(기본값: `"paragraph"`). +- `stream.maxOutputChars`: ACP 턴당 투영되는 assistant 출력 최대 문자 수입니다. +- `stream.maxSessionUpdateChars`: 투영되는 ACP 상태/업데이트 줄의 최대 문자 수입니다. +- `stream.tagVisibility`: 스트리밍 이벤트용 태그 이름별 불리언 표시 재정의 레코드입니다. +- `runtime.ttlMinutes`: 정리 대상이 되기 전 ACP 세션 워커의 유휴 TTL(분 단위)입니다. +- `runtime.installCommand`: ACP 런타임 환경 bootstrap 시 실행할 선택적 설치 명령입니다. + +--- + +## CLI + +```json5 +{ + cli: { + banner: { + taglineMode: "off", // random | default | off + }, + }, +} +``` + +- `cli.banner.taglineMode`는 배너 태그라인 스타일을 제어합니다. + - `"random"`(기본값): 순환하는 재미있는/계절성 태그라인. + - `"default"`: 고정된 중립 태그라인(`모든 채팅을 하나의 OpenClaw로.`). + - `"off"`: 태그라인 텍스트 없음(배너 제목/버전은 계속 표시). +- 전체 배너를 숨기려면(태그라인만이 아니라) 환경 변수 `OPENCLAW_HIDE_BANNER=1`을 설정하세요. + +--- + +## 마법사 + +CLI 안내 설정 흐름(`onboard`, `configure`, `doctor`)에서 기록하는 메타데이터입니다. + +```json5 +{ + wizard: { + lastRunAt: "2026-01-01T00:00:00.000Z", + lastRunVersion: "2026.1.4", + lastRunCommit: "abc1234", + lastRunCommand: "configure", + lastRunMode: "local", + }, +} +``` + +--- + +## Identity + +[에이전트 기본값](#agent-defaults) 아래의 `agents.list` identity 필드를 참조하세요. + +--- + +## Bridge(레거시, 제거됨) + +현재 빌드에는 더 이상 TCP bridge가 포함되지 않습니다. node는 Gateway WebSocket을 통해 연결됩니다. `bridge.*` 키는 더 이상 구성 스키마의 일부가 아닙니다(제거할 때까지 검증이 실패하며, `openclaw doctor --fix`로 알 수 없는 키를 제거할 수 있습니다). + + + +```json +{ + "bridge": { + "enabled": true, + "port": 18790, + "bind": "tailnet", + "tls": { + "enabled": true, + "autoGenerate": true + } + } +} +``` + + + +--- + +## Cron + +```json5 +{ + cron: { + enabled: true, + maxConcurrentRuns: 2, + webhook: "https://example.invalid/legacy", // 저장된 notify:true 작업용 deprecated 대체값 + webhookToken: "replace-with-dedicated-token", // 발신 webhook 인증용 선택적 bearer token + sessionRetention: "24h", // 기간 문자열 또는 false + runLog: { + maxBytes: "2mb", // 기본값 2_000_000 바이트 + keepLines: 2000, // 기본값 2000 + }, + }, +} +``` + +- `sessionRetention`: 완료된 격리 cron 실행 세션을 `sessions.json`에서 제거하기 전까지 유지할 기간입니다. 보관된 삭제 cron transcript 정리도 제어합니다. 기본값: `24h`; 비활성화하려면 `false`로 설정하세요. +- `runLog.maxBytes`: 제거 전 실행 로그 파일(`cron/runs/.jsonl`)당 최대 크기입니다. 기본값: `2_000_000` 바이트. +- `runLog.keepLines`: 실행 로그 제거가 트리거될 때 유지되는 최신 줄 수입니다. 기본값: `2000`. +- `webhookToken`: cron webhook `POST` 전달(`delivery.mode = "webhook"`)에 사용되는 bearer token입니다. 생략하면 인증 헤더를 보내지 않습니다. +- `webhook`: 저장된 작업 중 여전히 `notify: true`가 설정된 작업에만 사용되는 deprecated 레거시 대체 webhook URL(http/https)입니다. + +### `cron.retry` + +```json5 +{ + cron: { + retry: { + maxAttempts: 3, + backoffMs: [30000, 60000, 300000], + retryOn: ["rate_limit", "overloaded", "network", "timeout", "server_error"], + }, + }, +} +``` + +- `maxAttempts`: 일회성 작업에서 일시적 오류가 발생했을 때의 최대 재시도 횟수입니다(기본값: `3`; 범위: `0`–`10`). +- `backoffMs`: 각 재시도 시도에 대한 백오프 지연 시간(밀리초) 배열입니다(기본값: `[30000, 60000, 300000]`; 항목 수 1–10개). +- `retryOn`: 재시도를 트리거하는 오류 유형입니다 — `"rate_limit"`, `"overloaded"`, `"network"`, `"timeout"`, `"server_error"`. 생략하면 모든 일시적 유형을 재시도합니다. + +일회성 cron 작업에만 적용됩니다. 반복 작업은 별도의 실패 처리 방식을 사용합니다. + +### `cron.failureAlert` + +```json5 +{ + cron: { + failureAlert: { + enabled: false, + after: 3, + cooldownMs: 3600000, + mode: "announce", + accountId: "main", + }, + }, +} +``` + +- `enabled`: cron 작업 실패 알림을 활성화합니다(기본값: `false`). +- `after`: 알림이 발생하기 전까지의 연속 실패 횟수입니다(양의 정수, 최소값: `1`). +- `cooldownMs`: 같은 작업에 대해 반복 알림을 보내기 전 최소 간격(밀리초)입니다(0 이상의 정수). +- `mode`: 전달 모드입니다 — `"announce"`는 채널 메시지로 보내고, `"webhook"`은 구성된 webhook으로 게시합니다. +- `accountId`: 알림 전달 범위를 지정하는 선택적 계정 또는 채널 ID입니다. + +### `cron.failureDestination` + +```json5 +{ + cron: { + failureDestination: { + mode: "announce", + channel: "last", + to: "channel:C1234567890", + accountId: "main", + }, + }, +} +``` + +- 모든 작업에 대한 cron 실패 알림의 기본 대상입니다. +- `mode`: `"announce"` 또는 `"webhook"`이며, 충분한 대상 데이터가 있으면 기본값은 `"announce"`입니다. +- `channel`: announce 전달용 채널 재정의입니다. `"last"`는 마지막으로 알려진 전달 채널을 재사용합니다. +- `to`: 명시적 announce 대상 또는 webhook URL입니다. webhook 모드에서는 필수입니다. +- `accountId`: 전달용 선택적 계정 재정의입니다. +- 작업별 `delivery.failureDestination`은 이 전역 기본값을 재정의합니다. +- 전역 또는 작업별 실패 대상이 모두 설정되지 않은 경우, 이미 `announce`로 전달되는 작업은 실패 시 해당 기본 announce 대상으로 대체됩니다. +- `delivery.failureDestination`은 작업의 기본 `delivery.mode`가 `"webhook"`인 경우를 제외하면 `sessionTarget="isolated"` 작업에서만 지원됩니다. + +[cron 작업](/ko/automation/cron-jobs)을 참조하세요. 격리된 cron 실행은 [백그라운드 작업](/ko/automation/tasks)으로 추적됩니다. + +--- + +## 미디어 모델 템플릿 변수 + +`tools.media.models[].args`에서 확장되는 템플릿 placeholder: + +| 변수 | 설명 | +| ------------------ | ------------------------------------- | +| `{{Body}}` | 전체 수신 메시지 본문 | +| `{{RawBody}}` | 원시 본문(기록/발신자 래퍼 없음) | +| `{{BodyStripped}}` | 그룹 멘션이 제거된 본문 | +| `{{From}}` | 발신자 식별자 | +| `{{To}}` | 대상 식별자 | +| `{{MessageSid}}` | 채널 메시지 ID | +| `{{SessionId}}` | 현재 세션 UUID | +| `{{IsNewSession}}` | 새 세션이 생성되었을 때 `"true"` | +| `{{MediaUrl}}` | 수신 미디어 pseudo-URL | +| `{{MediaPath}}` | 로컬 미디어 경로 | +| `{{MediaType}}` | 미디어 유형(image/audio/document/…) | +| `{{Transcript}}` | 오디오 transcript | +| `{{Prompt}}` | CLI 항목에 대해 해석된 미디어 프롬프트 | +| `{{MaxChars}}` | CLI 항목에 대해 해석된 최대 출력 문자 수 | +| `{{ChatType}}` | `"direct"` 또는 `"group"` | +| `{{GroupSubject}}` | 그룹 제목(best effort) | +| `{{GroupMembers}}` | 그룹 멤버 미리보기(best effort) | +| `{{SenderName}}` | 발신자 표시 이름(best effort) | +| `{{SenderE164}}` | 발신자 전화번호(best effort) | +| `{{Provider}}` | provider 힌트(whatsapp, telegram, discord 등) | + +--- + +## 구성 포함(`$include`) + +구성을 여러 파일로 분리합니다. + +```json5 +// ~/.openclaw/openclaw.json +{ + gateway: { port: 18789 }, + agents: { $include: "./agents.json5" }, + broadcast: { + $include: ["./clients/mueller.json5", "./clients/schmidt.json5"], + }, +} +``` + +**병합 동작:** + +- 단일 파일: 포함하는 객체를 대체합니다. +- 파일 배열: 순서대로 깊은 병합됩니다(나중 항목이 이전 항목을 재정의). +- 형제 키: include 이후 병합됩니다(포함된 값을 재정의). +- 중첩 include: 최대 10단계까지 허용됩니다. +- 경로: 포함하는 파일을 기준으로 해석되지만 최상위 구성 디렉터리(`openclaw.json`의 `dirname`) 내부에 머물러야 합니다. 절대 경로/`../` 형식도 최종적으로 그 경계 안에서 해석되면 허용됩니다. +- 오류: 누락된 파일, 파싱 오류, 순환 include에 대해 명확한 메시지를 제공합니다. + +--- + +_관련 문서: [구성](/ko/gateway/configuration) · [구성 예시](/ko/gateway/configuration-examples) · [Doctor](/ko/gateway/doctor)_ diff --git a/docs/ko/help/testing.md b/docs/ko/help/testing.md index 35e96eac7..3b2c9fe5e 100644 --- a/docs/ko/help/testing.md +++ b/docs/ko/help/testing.md @@ -1,288 +1,305 @@ --- read_when: - - 로컬 또는 CI에서 테스트를 실행할 때 - - 모델/provider 버그에 대한 회귀 테스트를 추가할 때 - - gateway + agent 동작을 디버깅할 때 -summary: '테스트 키트: unit/e2e/live 스위트, Docker 러너, 그리고 각 테스트의 커버 범위' + - 로컬 또는 CI에서 테스트 실행하기 + - 모델/프로바이더 버그에 대한 회귀 테스트 추가하기 + - 게이트웨이 + 에이전트 동작 디버깅하기 +summary: '테스트 키트: 단위/e2e/라이브 스위트, Docker 실행기, 그리고 각 테스트가 다루는 내용' title: 테스트 x-i18n: - generated_at: "2026-04-09T01:30:42Z" + generated_at: "2026-04-10T05:59:49Z" model: gpt-5.4 provider: openai - source_hash: 01117f41d8b171a4f1da11ed78486ee700e70ae70af54eb6060c57baf64ab21b + source_hash: 21b78e59a5189f4e8e6e1b490d350f4735c0395da31d21fc5d10b825313026b4 source_path: help/testing.md workflow: 15 --- # 테스트 -OpenClaw에는 세 가지 Vitest 스위트(unit/integration, e2e, live)와 소수의 Docker 러너가 있습니다. +OpenClaw에는 세 가지 Vitest 스위트(단위/통합, e2e, 라이브)와 소수의 Docker 실행기가 있습니다. -이 문서는 "우리가 테스트하는 방식"에 대한 가이드입니다: +이 문서는 “우리가 테스트하는 방식”에 대한 가이드입니다. -- 각 스위트가 무엇을 커버하는지(그리고 의도적으로 무엇을 커버하지 않는지) -- 일반적인 워크플로(로컬, push 전, 디버깅)에서 어떤 명령을 실행해야 하는지 -- live 테스트가 자격 증명을 어떻게 찾고 모델/provider를 어떻게 선택하는지 -- 실제 모델/provider 이슈에 대한 회귀 테스트를 추가하는 방법 +- 각 스위트가 무엇을 다루는지(그리고 의도적으로 무엇을 다루지 않는지) +- 일반적인 워크플로(로컬, 푸시 전, 디버깅)에서 어떤 명령을 실행해야 하는지 +- 라이브 테스트가 자격 증명을 어떻게 탐색하고 모델/프로바이더를 어떻게 선택하는지 +- 실제 모델/프로바이더 이슈에 대한 회귀 테스트를 추가하는 방법 ## 빠른 시작 -대부분의 날에는 다음을 사용하세요: +대부분의 날에는: -- 전체 게이트(push 전에 예상됨): `pnpm build && pnpm check && pnpm test` +- 전체 게이트(푸시 전에 기대되는 항목): `pnpm build && pnpm check && pnpm test` - 여유 있는 머신에서 더 빠른 로컬 전체 스위트 실행: `pnpm test:max` -- 직접 Vitest watch 루프: `pnpm test:watch` -- 이제 직접 파일 타기팅은 extension/channel 경로도 라우팅합니다: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` +- 직접 Vitest 감시 루프 실행: `pnpm test:watch` +- 직접 파일 지정은 이제 확장/채널 경로도 라우팅합니다: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` +- 단일 실패를 반복하고 있다면 먼저 대상 범위를 좁힌 실행을 선호하세요. - Docker 기반 QA 사이트: `pnpm qa:lab:up` +- Linux VM 기반 QA 레인: `pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` 테스트를 수정했거나 추가 확신이 필요할 때: - 커버리지 게이트: `pnpm test:coverage` - E2E 스위트: `pnpm test:e2e` -실제 providers/models를 디버깅할 때(실제 자격 증명 필요): +실제 프로바이더/모델을 디버깅할 때(실제 자격 증명 필요): -- live 스위트(모델 + gateway 도구/이미지 probe): `pnpm test:live` -- 하나의 live 파일만 조용히 타기팅: `pnpm test:live -- src/agents/models.profiles.live.test.ts` +- 라이브 스위트(모델 + 게이트웨이 도구/이미지 프로브): `pnpm test:live` +- 하나의 라이브 파일만 조용히 대상으로 지정: `pnpm test:live -- src/agents/models.profiles.live.test.ts` -팁: 실패하는 케이스 하나만 필요할 때는 아래에 설명된 allowlist 환경 변수를 사용해 live 테스트 범위를 좁히는 방식을 우선 사용하세요. +팁: 하나의 실패 케이스만 필요하다면, 아래에 설명된 허용 목록 환경 변수를 사용해 라이브 테스트 범위를 좁히는 방식을 선호하세요. -## 테스트 스위트(무엇이 어디서 실행되는가) +## QA 전용 실행기 -스위트는 "현실성이 높아지는 순서"(그리고 변동성/비용도 높아지는 순서)로 생각하면 됩니다: +더 현실적인 QA-lab 환경이 필요할 때는 이 명령들을 기본 테스트 스위트와 함께 사용합니다. -### Unit / integration(기본값) +- `pnpm openclaw qa suite` + - 호스트에서 저장소 기반 QA 시나리오를 직접 실행합니다. +- `pnpm openclaw qa suite --runner multipass` + - 동일한 QA 스위트를 일회용 Multipass Linux VM 내부에서 실행합니다. + - 호스트의 `qa suite`와 동일한 시나리오 선택 동작을 유지합니다. + - `qa suite`와 동일한 프로바이더/모델 선택 플래그를 재사용합니다. + - 라이브 실행은 게스트에서 실용적으로 전달 가능한 지원 QA 인증 입력을 전달합니다: + env 기반 프로바이더 키, QA 라이브 프로바이더 구성 경로, 그리고 존재할 경우 `CODEX_HOME`. + - 게스트가 마운트된 워크스페이스를 통해 다시 쓸 수 있도록 출력 디렉터리는 저장소 루트 아래에 있어야 합니다. + - 일반적인 QA 보고서 + 요약과 함께 Multipass 로그를 `.artifacts/qa-e2e/...` 아래에 기록합니다. +- `pnpm qa:lab:up` + - 운영자 스타일 QA 작업을 위한 Docker 기반 QA 사이트를 시작합니다. -- 명령어: `pnpm test` -- 구성: 기존 scoped Vitest 프로젝트에 대해 10개의 순차 샤드 실행(`vitest.full-*.config.ts`) -- 파일: `src/**/*.test.ts`, `packages/**/*.test.ts`, `test/**/*.test.ts` 아래의 core/unit 인벤토리와 `vitest.unit.config.ts`로 커버되는 allowlist된 `ui` node 테스트 +## 테스트 스위트(무엇이 어디서 실행되는지) + +스위트는 “현실성이 점점 높아지는 순서”(그리고 불안정성/비용도 증가)로 생각하면 됩니다. + +### 단위 / 통합(기본값) + +- 명령: `pnpm test` +- 구성: 기존 범위 지정 Vitest 프로젝트에 대한 10개의 순차 샤드 실행(`vitest.full-*.config.ts`) +- 파일: `src/**/*.test.ts`, `packages/**/*.test.ts`, `test/**/*.test.ts` 아래의 코어/단위 인벤토리, 그리고 `vitest.unit.config.ts`가 다루는 허용 목록 `ui` node 테스트 - 범위: - - 순수 unit 테스트 - - 프로세스 내 integration 테스트(gateway auth, routing, tooling, parsing, config) - - 알려진 버그에 대한 결정적 회귀 테스트 + - 순수 단위 테스트 + - 프로세스 내부 통합 테스트(게이트웨이 인증, 라우팅, 도구, 파싱, 구성) + - 알려진 버그에 대한 결정론적 회귀 테스트 - 기대 사항: - CI에서 실행됨 - 실제 키 불필요 - 빠르고 안정적이어야 함 - 프로젝트 참고: - - 타기팅하지 않은 `pnpm test`는 이제 하나의 거대한 네이티브 루트 프로젝트 프로세스 대신 11개의 더 작은 샤드 구성(`core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`)을 실행합니다. 이는 부하가 있는 머신에서 피크 RSS를 줄이고 auto-reply/extension 작업이 관련 없는 스위트를 굶기지 않도록 합니다. - - `pnpm test --watch`는 여전히 네이티브 루트 `vitest.config.ts` 프로젝트 그래프를 사용합니다. 멀티 샤드 watch 루프는 실용적이지 않기 때문입니다. - - `pnpm test`, `pnpm test:watch`, `pnpm test:perf:imports`는 이제 명시적 파일/디렉터리 타깃을 먼저 scoped lane으로 라우팅하므로, `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts`는 전체 루트 프로젝트 시작 비용을 치르지 않습니다. - - `pnpm test:changed`는 diff가 라우팅 가능한 source/test 파일만 건드릴 때 변경된 git 경로를 동일한 scoped lane으로 확장합니다. config/setup 수정은 여전히 광범위한 루트 프로젝트 재실행으로 폴백합니다. - - 선택된 `plugin-sdk` 및 `commands` 테스트도 `test/setup-openclaw-runtime.ts`를 건너뛰는 전용 경량 lane을 통해 라우팅됩니다. 상태 저장/런타임 집약적인 파일은 기존 lane에 남아 있습니다. - - 선택된 `plugin-sdk` 및 `commands` helper source 파일도 변경 모드 실행을 이 경량 lane의 명시적 sibling 테스트에 매핑하므로, helper 수정 시 해당 디렉터리의 무거운 전체 스위트를 다시 실행하지 않아도 됩니다. - - `auto-reply`는 이제 세 개의 전용 버킷을 가집니다: 최상위 core helper, 최상위 `reply.*` integration 테스트, 그리고 `src/auto-reply/reply/**` 하위 트리. 이렇게 하면 가장 무거운 reply harness 작업이 저렴한 status/chunk/token 테스트에 영향을 주지 않습니다. -- 임베디드 러너 참고: - - 메시지 도구 탐색 입력이나 compaction 런타임 컨텍스트를 변경할 때는 - 두 수준의 커버리지를 모두 유지하세요. - - 순수 routing/normalization 경계를 위한 집중된 helper 회귀 테스트를 추가하세요. - - 또한 임베디드 러너 integration 스위트도 정상 상태를 유지하세요: + - 범위를 지정하지 않은 `pnpm test`는 이제 하나의 거대한 네이티브 루트 프로젝트 프로세스 대신 11개의 더 작은 샤드 구성(`core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`)을 실행합니다. 이렇게 하면 부하가 걸린 머신에서 최대 RSS를 줄이고 auto-reply/extension 작업이 관련 없는 스위트를 굶기지 않도록 합니다. + - `pnpm test --watch`는 다중 샤드 감시 루프가 실용적이지 않기 때문에 여전히 네이티브 루트 `vitest.config.ts` 프로젝트 그래프를 사용합니다. + - `pnpm test`, `pnpm test:watch`, `pnpm test:perf:imports`는 명시적 파일/디렉터리 대상을 먼저 범위 지정 레인으로 라우팅하므로, `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts`는 전체 루트 프로젝트 시작 비용을 치르지 않습니다. + - `pnpm test:changed`는 변경된 git 경로가 라우팅 가능한 소스/테스트 파일만 건드릴 때 동일한 범위 지정 레인으로 확장되며, 구성/설정 수정은 여전히 넓은 루트 프로젝트 재실행으로 대체됩니다. + - 일부 `plugin-sdk` 및 `commands` 테스트도 `test/setup-openclaw-runtime.ts`를 건너뛰는 전용 경량 레인을 통해 라우팅되며, 상태 유지/런타임 부담이 큰 파일은 기존 레인에 남습니다. + - 일부 `plugin-sdk` 및 `commands` 헬퍼 소스 파일도 변경 모드 실행을 해당 경량 레인의 명시적 형제 테스트로 매핑하므로, 헬퍼 수정 시 해당 디렉터리의 전체 무거운 스위트를 다시 실행할 필요가 없습니다. + - `auto-reply`는 이제 세 가지 전용 버킷을 가집니다: 최상위 코어 헬퍼, 최상위 `reply.*` 통합 테스트, 그리고 `src/auto-reply/reply/**` 하위 트리. 이렇게 하면 가장 무거운 reply 하네스 작업이 가벼운 status/chunk/token 테스트에 영향을 주지 않습니다. +- 임베디드 실행기 참고: + - 메시지 도구 탐색 입력이나 압축 런타임 컨텍스트를 변경할 때는 두 수준의 커버리지를 모두 유지하세요. + - 순수 라우팅/정규화 경계에 대해 집중된 헬퍼 회귀 테스트를 추가하세요. + - 또한 임베디드 실행기 통합 스위트도 정상 상태를 유지해야 합니다: `src/agents/pi-embedded-runner/compact.hooks.test.ts`, `src/agents/pi-embedded-runner/run.overflow-compaction.test.ts`, 그리고 `src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`. - - 이 스위트들은 scoped id와 compaction 동작이 여전히 실제 - `run.ts` / `compact.ts` 경로를 통해 흐르는지 검증합니다. helper 전용 테스트는 - 이 integration 경로를 대체하기에 충분하지 않습니다. + - 이 스위트들은 범위 지정 id와 압축 동작이 실제 `run.ts` / `compact.ts` 경로를 통해 계속 흐르는지 검증합니다. 헬퍼 전용 테스트만으로는 이러한 통합 경로를 충분히 대체할 수 없습니다. - 풀 참고: - - 기본 Vitest 구성은 이제 기본값으로 `threads`를 사용합니다. - - 공유 Vitest 구성은 또한 `isolate: false`를 고정하고 루트 프로젝트, e2e, live 구성 전반에서 비격리 러너를 사용합니다. - - 루트 UI lane은 `jsdom` 설정과 optimizer를 유지하지만, 이제 공유 비격리 러너에서도 실행됩니다. - - 각 `pnpm test` 샤드는 동일한 공유 Vitest 구성에서 `threads` + `isolate: false` 기본값을 상속합니다. - - 공유 `scripts/run-vitest.mjs` 런처는 이제 큰 로컬 실행 중 V8 컴파일 churn을 줄이기 위해 Vitest 자식 Node 프로세스에 기본적으로 `--no-maglev`도 추가합니다. 기본 V8 동작과 비교해야 한다면 `OPENCLAW_VITEST_ENABLE_MAGLEV=1`을 설정하세요. + - 기본 Vitest 구성은 이제 기본적으로 `threads`를 사용합니다. + - 공유 Vitest 구성은 또한 `isolate: false`를 고정하고 루트 프로젝트, e2e, 라이브 구성 전반에서 비격리 실행기를 사용합니다. + - 루트 UI 레인은 `jsdom` 설정과 옵티마이저를 유지하지만, 이제 공유 비격리 실행기에서도 실행됩니다. + - 각 `pnpm test` 샤드는 공유 Vitest 구성으로부터 동일한 `threads` + `isolate: false` 기본값을 상속합니다. + - 공유 `scripts/run-vitest.mjs` 실행기는 이제 대규모 로컬 실행 중 V8 컴파일 변동을 줄이기 위해 기본적으로 Vitest 자식 Node 프로세스에 `--no-maglev`도 추가합니다. 기본 V8 동작과 비교해야 한다면 `OPENCLAW_VITEST_ENABLE_MAGLEV=1`을 설정하세요. - 빠른 로컬 반복 참고: - - `pnpm test:changed`는 변경된 경로가 더 작은 스위트에 깔끔하게 매핑될 때 scoped lane을 통해 라우팅합니다. - - `pnpm test:max`와 `pnpm test:changed:max`는 같은 라우팅 동작을 유지하되, worker cap만 더 높습니다. - - 로컬 worker 자동 스케일링은 이제 의도적으로 보수적이며, 호스트 load average가 이미 높을 때도 백오프하므로 여러 개의 동시 Vitest 실행이 기본적으로 덜 해롭습니다. - - 기본 Vitest 구성은 프로젝트/구성 파일을 `forceRerunTriggers`로 표시하므로, 테스트 wiring이 바뀌어도 changed 모드 재실행이 올바르게 유지됩니다. - - 이 구성은 지원되는 호스트에서 `OPENCLAW_VITEST_FS_MODULE_CACHE`를 활성화된 상태로 유지합니다. 직접 프로파일링용으로 명시적 캐시 위치 하나를 원하면 `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`를 설정하세요. -- 성능 디버깅 참고: - - `pnpm test:perf:imports`는 Vitest import-duration 리포트와 import-breakdown 출력을 활성화합니다. - - `pnpm test:perf:imports:changed`는 `origin/main` 이후 변경된 파일로 동일한 프로파일링 뷰의 범위를 좁힙니다. -- `pnpm test:perf:changed:bench -- --ref `는 해당 커밋 diff에 대해 라우팅된 `test:changed`와 네이티브 루트 프로젝트 경로를 비교하고 wall time과 macOS max RSS를 출력합니다. -- `pnpm test:perf:changed:bench -- --worktree`는 변경된 파일 목록을 `scripts/test-projects.mjs`와 루트 Vitest 구성으로 라우팅하여 현재 dirty 트리를 벤치마킹합니다. + - `pnpm test:changed`는 변경된 경로가 더 작은 스위트에 깔끔하게 매핑될 때 범위 지정 레인을 통해 라우팅합니다. + - `pnpm test:max`와 `pnpm test:changed:max`도 동일한 라우팅 동작을 유지하며, 단지 더 높은 워커 상한을 사용합니다. + - 로컬 워커 자동 스케일링은 이제 의도적으로 더 보수적이며, 호스트 load average가 이미 높을 때도 물러나므로 여러 개의 동시 Vitest 실행이 기본적으로 덜 큰 피해를 주게 됩니다. + - 기본 Vitest 구성은 프로젝트/구성 파일을 `forceRerunTriggers`로 표시하므로 테스트 배선이 바뀔 때 변경 모드 재실행이 정확하게 유지됩니다. + - 구성은 지원되는 호스트에서 `OPENCLAW_VITEST_FS_MODULE_CACHE`를 활성화한 상태로 유지합니다. 직접 프로파일링을 위해 명시적 캐시 위치 하나를 쓰고 싶다면 `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`를 설정하세요. +- 성능 디버그 참고: + - `pnpm test:perf:imports`는 Vitest 가져오기 지속 시간 보고와 가져오기 분석 출력을 활성화합니다. + - `pnpm test:perf:imports:changed`는 `origin/main` 이후 변경된 파일로 동일한 프로파일링 보기를 범위 지정합니다. +- `pnpm test:perf:changed:bench -- --ref `는 해당 커밋된 diff에 대해 라우팅된 `test:changed`와 네이티브 루트 프로젝트 경로를 비교하고 wall time과 macOS 최대 RSS를 출력합니다. +- `pnpm test:perf:changed:bench -- --worktree`는 변경된 파일 목록을 `scripts/test-projects.mjs`와 루트 Vitest 구성으로 라우팅하여 현재 dirty tree를 벤치마킹합니다. - `pnpm test:perf:profile:main`은 Vitest/Vite 시작 및 transform 오버헤드에 대한 메인 스레드 CPU 프로파일을 기록합니다. - - `pnpm test:perf:profile:runner`는 unit 스위트에 대해 파일 병렬화를 비활성화한 상태에서 러너 CPU+힙 프로파일을 기록합니다. + - `pnpm test:perf:profile:runner`는 파일 병렬화를 비활성화한 상태에서 단위 스위트에 대한 실행기 CPU+힙 프로파일을 기록합니다. -### E2E(gateway 스모크) +### E2E(게이트웨이 스모크) -- 명령어: `pnpm test:e2e` +- 명령: `pnpm test:e2e` - 구성: `vitest.e2e.config.ts` - 파일: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts` - 런타임 기본값: - - 저장소 나머지와 동일하게 Vitest `threads`와 `isolate: false`를 사용합니다. - - 적응형 worker를 사용합니다(CI: 최대 2, 로컬: 기본 1). - - 콘솔 I/O 오버헤드를 줄이기 위해 기본적으로 silent 모드로 실행됩니다. + - 저장소의 나머지 부분과 동일하게 Vitest `threads`와 `isolate: false`를 사용합니다. + - 적응형 워커를 사용합니다(CI: 최대 2, 로컬: 기본 1). + - 콘솔 I/O 오버헤드를 줄이기 위해 기본적으로 무음 모드로 실행합니다. - 유용한 재정의: - - worker 수를 강제하려면 `OPENCLAW_E2E_WORKERS=`(최대 16) - - 자세한 콘솔 출력을 다시 활성화하려면 `OPENCLAW_E2E_VERBOSE=1` + - 워커 수를 강제로 지정하려면 `OPENCLAW_E2E_WORKERS=`(상한 16). + - 자세한 콘솔 출력을 다시 활성화하려면 `OPENCLAW_E2E_VERBOSE=1`. - 범위: - - 다중 인스턴스 gateway end-to-end 동작 + - 다중 인스턴스 게이트웨이 end-to-end 동작 - WebSocket/HTTP 표면, 노드 페어링, 더 무거운 네트워킹 - 기대 사항: - CI에서 실행됨(파이프라인에서 활성화된 경우) - 실제 키 불필요 - - unit 테스트보다 더 많은 이동 부품이 있음(더 느릴 수 있음) + - 단위 테스트보다 더 많은 가변 요소가 있음(더 느릴 수 있음) ### E2E: OpenShell 백엔드 스모크 -- 명령어: `pnpm test:e2e:openshell` +- 명령: `pnpm test:e2e:openshell` - 파일: `test/openshell-sandbox.e2e.test.ts` - 범위: - - Docker를 통해 호스트에서 격리된 OpenShell gateway를 시작 - - 임시 로컬 Dockerfile에서 샌드박스를 생성 - - 실제 `sandbox ssh-config` + SSH exec를 통해 OpenClaw의 OpenShell 백엔드를 실행 - - 샌드박스 fs 브리지를 통해 원격 표준 파일시스템 동작을 검증 + - Docker를 통해 호스트에서 격리된 OpenShell 게이트웨이를 시작합니다. + - 임시 로컬 Dockerfile로부터 샌드박스를 생성합니다. + - 실제 `sandbox ssh-config` + SSH exec를 통해 OpenClaw의 OpenShell 백엔드를 실행합니다. + - 샌드박스 fs 브리지를 통해 원격 정규 파일 시스템 동작을 검증합니다. - 기대 사항: - - 옵트인 전용이며 기본 `pnpm test:e2e` 실행에는 포함되지 않음 - - 로컬 `openshell` CLI와 동작하는 Docker 데몬 필요 - - 격리된 `HOME` / `XDG_CONFIG_HOME`을 사용한 뒤 테스트 gateway와 샌드박스를 제거함 + - 옵트인 전용이며 기본 `pnpm test:e2e` 실행의 일부가 아님 + - 로컬 `openshell` CLI와 정상 동작하는 Docker 데몬 필요 + - 격리된 `HOME` / `XDG_CONFIG_HOME`을 사용한 뒤 테스트 게이트웨이와 샌드박스를 제거함 - 유용한 재정의: - - 더 넓은 e2e 스위트를 수동 실행할 때 테스트를 활성화하려면 `OPENCLAW_E2E_OPENSHELL=1` - - 기본이 아닌 CLI 바이너리나 wrapper 스크립트를 지정하려면 `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` + - 더 넓은 e2e 스위트를 수동으로 실행할 때 테스트를 활성화하려면 `OPENCLAW_E2E_OPENSHELL=1` + - 기본이 아닌 CLI 바이너리 또는 래퍼 스크립트를 가리키려면 `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` -### Live(실제 providers + 실제 모델) +### 라이브(실제 프로바이더 + 실제 모델) -- 명령어: `pnpm test:live` +- 명령: `pnpm test:live` - 구성: `vitest.live.config.ts` - 파일: `src/**/*.live.test.ts` - 기본값: `pnpm test:live`에 의해 **활성화됨**(`OPENCLAW_LIVE_TEST=1` 설정) - 범위: - - "이 provider/model이 오늘 실제 자격 증명으로 정말 동작하는가?" - - provider 포맷 변경, tool-calling 특이사항, auth 이슈, rate limit 동작 포착 + - “이 프로바이더/모델이 오늘 실제 자격 증명으로 정말 동작하는가?” + - 프로바이더 형식 변경, 도구 호출 특이점, 인증 이슈, 속도 제한 동작 포착 - 기대 사항: - - 설계상 CI에서 안정적이지 않음(실제 네트워크, 실제 provider 정책, quota, 장애) - - 비용이 들거나 rate limit를 사용함 - - "모든 것"보다 범위를 좁힌 부분집합 실행을 권장 -- live 실행은 누락된 API 키를 가져오기 위해 `~/.profile`을 소싱합니다. -- 기본적으로 live 실행은 여전히 `HOME`을 격리하고 config/auth 자료를 임시 테스트 홈으로 복사하므로 unit fixture가 실제 `~/.openclaw`를 변경할 수 없습니다. -- live 테스트가 실제 홈 디렉터리를 사용하도록 의도적으로 해야 할 때만 `OPENCLAW_LIVE_USE_REAL_HOME=1`을 설정하세요. -- `pnpm test:live`는 이제 더 조용한 모드를 기본으로 사용합니다. `[live] ...` 진행 출력은 유지하지만 추가 `~/.profile` 알림과 gateway bootstrap 로그/Bonjour chatter는 숨깁니다. 전체 시작 로그를 다시 보려면 `OPENCLAW_LIVE_TEST_QUIET=0`을 설정하세요. -- API 키 로테이션(provider별): `*_API_KEYS`를 쉼표/세미콜론 형식으로 또는 `*_API_KEY_1`, `*_API_KEY_2`로 설정하세요(예: `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`). 또는 live 전용 재정의로 `OPENCLAW_LIVE_*_KEY`를 사용하세요. 테스트는 rate limit 응답 시 재시도합니다. -- 진행/heartbeat 출력: - - live 스위트는 이제 진행 줄을 stderr로 출력하므로 Vitest 콘솔 캡처가 조용해도 긴 provider 호출이 시각적으로 활성 상태로 보입니다. - - `vitest.live.config.ts`는 Vitest 콘솔 가로채기를 비활성화하므로 live 실행 중 provider/gateway 진행 줄이 즉시 스트리밍됩니다. - - 직접 모델 heartbeats는 `OPENCLAW_LIVE_HEARTBEAT_MS`로 조정합니다. - - gateway/probe heartbeats는 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`로 조정합니다. + - 설계상 CI에서 안정적이지 않음(실제 네트워크, 실제 프로바이더 정책, 할당량, 장애) + - 비용이 들고 속도 제한을 사용함 + - “전체” 실행보다는 범위를 좁힌 하위 집합 실행을 선호 +- 라이브 실행은 누락된 API 키를 가져오기 위해 `~/.profile`을 소싱합니다. +- 기본적으로 라이브 실행은 여전히 `HOME`을 격리하고 구성/인증 자료를 임시 테스트 홈으로 복사하므로 단위 픽스처가 실제 `~/.openclaw`를 변경할 수 없습니다. +- 라이브 테스트가 실제 홈 디렉터리를 사용하도록 의도적으로 해야 할 때만 `OPENCLAW_LIVE_USE_REAL_HOME=1`을 설정하세요. +- `pnpm test:live`는 이제 기본적으로 더 조용한 모드를 사용합니다. `[live] ...` 진행 출력은 유지하지만 추가 `~/.profile` 알림은 숨기고 게이트웨이 부트스트랩 로그/Bonjour 잡음을 음소거합니다. 전체 시작 로그를 다시 보고 싶다면 `OPENCLAW_LIVE_TEST_QUIET=0`을 설정하세요. +- API 키 순환(프로바이더별): 쉼표/세미콜론 형식의 `*_API_KEYS` 또는 `*_API_KEY_1`, `*_API_KEY_2`를 설정합니다(예: `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`). 또는 라이브별 재정의로 `OPENCLAW_LIVE_*_KEY`를 사용할 수 있습니다. 테스트는 속도 제한 응답 시 재시도합니다. +- 진행/하트비트 출력: + - 라이브 스위트는 이제 긴 프로바이더 호출이 Vitest 콘솔 캡처가 조용할 때도 눈에 띄게 활성 상태임을 보여주기 위해 진행 줄을 stderr로 출력합니다. + - `vitest.live.config.ts`는 Vitest 콘솔 가로채기를 비활성화하므로 프로바이더/게이트웨이 진행 줄이 라이브 실행 중 즉시 스트리밍됩니다. + - 직접 모델 하트비트를 조정하려면 `OPENCLAW_LIVE_HEARTBEAT_MS`. + - 게이트웨이/프로브 하트비트를 조정하려면 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`. ## 어떤 스위트를 실행해야 하나요? -다음 결정 표를 사용하세요: +다음 결정 표를 사용하세요. -- 로직/테스트 수정: `pnpm test` 실행(많이 변경했다면 `pnpm test:coverage`도) -- gateway 네트워킹 / WS 프로토콜 / 페어링 수정: `pnpm test:e2e` 추가 -- "내 봇이 다운되었다" / provider별 실패 / tool calling 디버깅: 범위를 좁힌 `pnpm test:live` 실행 +- 로직/테스트를 수정하는 경우: `pnpm test` 실행(많이 변경했다면 `pnpm test:coverage`도) +- 게이트웨이 네트워킹 / WS 프로토콜 / 페어링을 건드리는 경우: `pnpm test:e2e` 추가 +- “내 봇이 다운됐다” / 프로바이더별 실패 / 도구 호출을 디버깅하는 경우: 범위를 좁힌 `pnpm test:live` 실행 -## Live: Android 노드 capability 스윕 +## 라이브: Android 노드 기능 스윕 - 테스트: `src/gateway/android-node.capabilities.live.test.ts` - 스크립트: `pnpm android:test:integration` -- 목표: 연결된 Android 노드가 현재 광고하는 **모든 명령**을 호출하고 명령 계약 동작을 검증 +- 목표: 연결된 Android 노드가 현재 광고하는 **모든 명령**을 호출하고 명령 계약 동작을 검증합니다. - 범위: - - 사전 조건이 갖춰진/수동 설정(스위트는 앱을 설치/실행/페어링하지 않음) - - 선택된 Android 노드에 대한 명령별 gateway `node.invoke` 검증 -- 필요한 사전 설정: - - Android 앱이 이미 gateway에 연결되고 페어링되어 있어야 함 - - 앱이 foreground 상태로 유지되어야 함 - - 통과하기를 기대하는 capability에 대해 권한/캡처 동의가 부여되어야 함 -- 선택적 타깃 재정의: + - 사전 준비/수동 설정 필요(이 스위트는 앱을 설치/실행/페어링하지 않음) + - 선택된 Android 노드에 대한 명령별 게이트웨이 `node.invoke` 검증 +- 필수 사전 설정: + - Android 앱이 이미 연결되고 게이트웨이와 페어링되어 있어야 함 + - 앱이 포그라운드 상태로 유지되어야 함 + - 통과를 기대하는 기능에 대해 권한/캡처 동의가 허용되어 있어야 함 +- 선택적 대상 재정의: - `OPENCLAW_ANDROID_NODE_ID` 또는 `OPENCLAW_ANDROID_NODE_NAME` - `OPENCLAW_ANDROID_GATEWAY_URL` / `OPENCLAW_ANDROID_GATEWAY_TOKEN` / `OPENCLAW_ANDROID_GATEWAY_PASSWORD` -- 전체 Android 설정 세부 정보: [Android 앱](/ko/platforms/android) +- 전체 Android 설정 세부 정보: [Android App](/ko/platforms/android) -## Live: 모델 스모크(profile 키) +## 라이브: 모델 스모크(프로필 키) -live 테스트는 실패를 분리할 수 있도록 두 계층으로 나뉩니다: +라이브 테스트는 실패를 분리할 수 있도록 두 계층으로 나뉩니다. -- "직접 모델"은 주어진 키로 provider/model이 최소한 응답할 수 있는지 알려줍니다. -- "Gateway 스모크"는 해당 모델에 대해 전체 gateway+agent 파이프라인이 동작하는지(세션, 히스토리, 도구, 샌드박스 정책 등)를 알려줍니다. +- “직접 모델”은 해당 프로바이더/모델이 주어진 키로 최소한 응답할 수 있는지를 알려줍니다. +- “게이트웨이 스모크”는 전체 게이트웨이+에이전트 파이프라인이 해당 모델에서 동작하는지(세션, 히스토리, 도구, 샌드박스 정책 등)를 알려줍니다. -### 계층 1: 직접 모델 완료(gateway 없음) +### 1계층: 직접 모델 완성(게이트웨이 없음) - 테스트: `src/agents/models.profiles.live.test.ts` - 목표: - - 발견된 모델 열거 + - 탐색된 모델을 열거 - `getApiKeyForModel`을 사용해 자격 증명이 있는 모델 선택 - - 모델별로 작은 completion 실행(필요시 타깃 회귀 포함) + - 모델별로 작은 완성 실행(필요한 경우 대상 회귀 포함) - 활성화 방법: - - `pnpm test:live`(또는 Vitest를 직접 호출하는 경우 `OPENCLAW_LIVE_TEST=1`) -- 이 스위트를 실제로 실행하려면 `OPENCLAW_LIVE_MODELS=modern`(또는 `all`, modern의 별칭)을 설정하세요. 그렇지 않으면 `pnpm test:live`가 gateway 스모크에 집중되도록 건너뜁니다. + - `pnpm test:live`(또는 Vitest를 직접 호출할 경우 `OPENCLAW_LIVE_TEST=1`) +- 이 스위트를 실제로 실행하려면 `OPENCLAW_LIVE_MODELS=modern`(또는 `all`, modern의 별칭)을 설정하세요. 그렇지 않으면 `pnpm test:live`가 게이트웨이 스모크에 집중되도록 건너뜁니다. - 모델 선택 방법: - - modern allowlist를 실행하려면 `OPENCLAW_LIVE_MODELS=modern`(Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4) - - `OPENCLAW_LIVE_MODELS=all`은 modern allowlist의 별칭입니다 - - 또는 `OPENCLAW_LIVE_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,..."`(쉼표 구분 allowlist) - - modern/all 스윕은 기본적으로 선별된 고신호 상한을 사용합니다. exhaustive modern 스윕을 원하면 `OPENCLAW_LIVE_MAX_MODELS=0`, 더 작은 상한을 원하면 양수를 설정하세요. -- provider 선택 방법: - - `OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"`(쉼표 구분 allowlist) -- 키 출처: - - 기본값: profile 저장소와 env 폴백 - - **profile 저장소만** 강제하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 설정 -- 존재 이유: - - "provider API가 망가졌다 / 키가 유효하지 않다"와 "gateway agent 파이프라인이 망가졌다"를 분리 - - 작고 격리된 회귀를 포함(예: OpenAI Responses/Codex Responses reasoning replay + tool-call 플로) + - 현대식 허용 목록(Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4)을 실행하려면 `OPENCLAW_LIVE_MODELS=modern` + - `OPENCLAW_LIVE_MODELS=all`은 현대식 허용 목록의 별칭입니다 + - 또는 `OPENCLAW_LIVE_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,..."`(쉼표 허용 목록) + - modern/all 스윕은 기본적으로 선별된 고신호 상한을 사용합니다. 전체 modern 스윕을 하려면 `OPENCLAW_LIVE_MAX_MODELS=0`, 더 작은 상한을 원하면 양수를 설정하세요. +- 프로바이더 선택 방법: + - `OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"`(쉼표 허용 목록) +- 키의 출처: + - 기본값: 프로필 저장소와 env 대체값 + - **프로필 저장소만** 강제하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 설정 +- 이 계층이 존재하는 이유: + - “프로바이더 API가 깨졌는지 / 키가 잘못되었는지”와 “게이트웨이 에이전트 파이프라인이 깨졌는지”를 분리 + - 작고 고립된 회귀를 담음(예: OpenAI Responses/Codex Responses 추론 재생 + 도구 호출 흐름) -### 계층 2: Gateway + dev agent 스모크(`@openclaw`가 실제로 하는 것) +### 2계층: 게이트웨이 + 개발 에이전트 스모크(실제 "@openclaw"가 하는 일) - 테스트: `src/gateway/gateway-models.profiles.live.test.ts` - 목표: - - 프로세스 내 gateway를 시작 - - `agent:dev:*` 세션을 생성/패치(실행별 모델 재정의) + - 프로세스 내부 게이트웨이 시작 + - `agent:dev:*` 세션 생성/패치(실행별 모델 재정의) - 키가 있는 모델을 순회하며 다음을 검증: - - "의미 있는" 응답(도구 없음) - - 실제 도구 호출 동작(read probe) - - 선택적 추가 도구 probe(exec+read probe) - - OpenAI 회귀 경로(tool-call-only → 후속 응답)가 계속 동작 -- Probe 세부 정보(실패를 빠르게 설명할 수 있도록): - - `read` probe: 테스트가 워크스페이스에 nonce 파일을 쓰고, 에이전트에게 이를 `read`하고 nonce를 다시 말하라고 요청합니다. - - `exec+read` probe: 테스트가 에이전트에게 temp 파일에 nonce를 `exec`로 쓰고, 그 뒤 다시 `read`하라고 요청합니다. - - 이미지 probe: 테스트가 생성된 PNG(cat + 무작위 코드)를 첨부하고 모델이 `cat `를 반환할 것으로 기대합니다. + - “의미 있는” 응답(도구 없음) + - 실제 도구 호출이 동작함(read 프로브) + - 선택적 추가 도구 프로브(exec+read 프로브) + - OpenAI 회귀 경로(도구 호출만 → 후속 호출)가 계속 동작함 +- 프로브 세부 정보(실패를 빠르게 설명할 수 있도록): + - `read` 프로브: 테스트가 워크스페이스에 nonce 파일을 쓰고, 에이전트에게 이를 `read`하고 nonce를 그대로 반환하도록 요청합니다. + - `exec+read` 프로브: 테스트가 에이전트에게 `exec`로 임시 파일에 nonce를 쓰고, 이어서 이를 다시 `read`하도록 요청합니다. + - 이미지 프로브: 테스트가 생성된 PNG(고양이 + 무작위 코드)를 첨부하고 모델이 `cat `를 반환하기를 기대합니다. - 구현 참조: `src/gateway/gateway-models.profiles.live.test.ts` 및 `src/gateway/live-image-probe.ts`. - 활성화 방법: - - `pnpm test:live`(또는 Vitest를 직접 호출하는 경우 `OPENCLAW_LIVE_TEST=1`) + - `pnpm test:live`(또는 Vitest를 직접 호출할 경우 `OPENCLAW_LIVE_TEST=1`) - 모델 선택 방법: - - 기본값: modern allowlist(Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4) - - `OPENCLAW_LIVE_GATEWAY_MODELS=all`은 modern allowlist의 별칭 + - 기본값: 현대식 허용 목록(Opus/Sonnet 4.6+, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.7, Grok 4) + - `OPENCLAW_LIVE_GATEWAY_MODELS=all`은 현대식 허용 목록의 별칭입니다 - 또는 범위를 좁히려면 `OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"`(또는 쉼표 목록) 설정 - - modern/all gateway 스윕은 기본적으로 선별된 고신호 상한을 사용합니다. exhaustive modern 스윕을 원하면 `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0`, 더 작은 상한을 원하면 양수를 설정하세요. -- provider 선택 방법("OpenRouter 전부" 방지): - - `OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"`(쉼표 구분 allowlist) -- 이 live 테스트에서는 도구 + 이미지 probe가 항상 켜져 있습니다: - - `read` probe + `exec+read` probe(도구 스트레스) - - 이미지 입력 지원을 광고하는 모델일 경우 이미지 probe 실행 - - 플로(상위 수준): - - 테스트가 "CAT" + 랜덤 코드가 들어간 작은 PNG를 생성(`src/gateway/live-image-probe.ts`) - - 이를 `agent` `attachments: [{ mimeType: "image/png", content: "" }]`로 전송 - - Gateway가 첨부 파일을 `images[]`로 파싱(`src/gateway/server-methods/agent.ts` + `src/gateway/chat-attachments.ts`) - - 임베디드 에이전트가 멀티모달 사용자 메시지를 모델에 전달 - - 검증: 응답에 `cat` + 코드가 포함됨(OCR 허용 범위: 약간의 실수는 허용) + - modern/all 게이트웨이 스윕은 기본적으로 선별된 고신호 상한을 사용합니다. 전체 modern 스윕을 하려면 `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=0`, 더 작은 상한을 원하면 양수를 설정하세요. +- 프로바이더 선택 방법(“OpenRouter 전체” 피하기): + - `OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"`(쉼표 허용 목록) +- 도구 + 이미지 프로브는 이 라이브 테스트에서 항상 활성화됩니다: + - `read` 프로브 + `exec+read` 프로브(도구 스트레스) + - 이미지 입력 지원을 광고하는 모델에서는 이미지 프로브 실행 + - 흐름(상위 수준): + - 테스트가 “CAT” + 무작위 코드가 들어간 작은 PNG를 생성합니다(`src/gateway/live-image-probe.ts`) + - 이를 `agent` `attachments: [{ mimeType: "image/png", content: "" }]`를 통해 전송합니다 + - 게이트웨이가 첨부 파일을 `images[]`로 파싱합니다(`src/gateway/server-methods/agent.ts` + `src/gateway/chat-attachments.ts`) + - 임베디드 에이전트가 멀티모달 사용자 메시지를 모델로 전달합니다 + - 검증: 응답에 `cat` + 코드가 포함되어야 함(OCR 허용 오차: 사소한 실수는 허용) -팁: 자신의 머신에서 무엇을 테스트할 수 있는지(그리고 정확한 `provider/model` id)를 보려면 다음을 실행하세요: +팁: 현재 사용 중인 머신에서 무엇을 테스트할 수 있는지(그리고 정확한 `provider/model` id)를 보려면 다음을 실행하세요. ```bash openclaw models list openclaw models list --json ``` -## Live: CLI 백엔드 스모크(Claude, Codex, Gemini 또는 기타 로컬 CLI) +## 라이브: CLI 백엔드 스모크(Claude, Codex, Gemini 또는 기타 로컬 CLI) - 테스트: `src/gateway/gateway-cli-backend.live.test.ts` -- 목표: 기본 config를 건드리지 않고 로컬 CLI 백엔드를 사용해 Gateway + agent 파이프라인을 검증 -- 백엔드별 스모크 기본값은 해당 extension의 `cli-backend.ts` 정의와 함께 존재합니다. +- 목표: 기본 구성을 건드리지 않고 로컬 CLI 백엔드를 사용해 게이트웨이 + 에이전트 파이프라인을 검증합니다. +- 백엔드별 스모크 기본값은 소유 확장의 `cli-backend.ts` 정의에 있습니다. - 활성화: - - `pnpm test:live`(또는 Vitest를 직접 호출하는 경우 `OPENCLAW_LIVE_TEST=1`) + - `pnpm test:live`(또는 Vitest를 직접 호출할 경우 `OPENCLAW_LIVE_TEST=1`) - `OPENCLAW_LIVE_CLI_BACKEND=1` - 기본값: - - 기본 provider/model: `claude-cli/claude-sonnet-4-6` - - command/args/image 동작은 해당 CLI 백엔드 plugin 메타데이터에서 가져옵니다. + - 기본 프로바이더/모델: `claude-cli/claude-sonnet-4-6` + - 명령/인자/이미지 동작은 소유 CLI 백엔드 plugin 메타데이터에서 가져옵니다. - 재정의(선택 사항): - `OPENCLAW_LIVE_CLI_BACKEND_MODEL="codex-cli/gpt-5.4"` - `OPENCLAW_LIVE_CLI_BACKEND_COMMAND="/full/path/to/codex"` - `OPENCLAW_LIVE_CLI_BACKEND_ARGS='["exec","--json","--color","never","--sandbox","read-only","--skip-git-repo-check"]'` - - 실제 이미지 첨부를 보내려면 `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1`(경로가 프롬프트에 주입됨) - - 프롬프트 주입 대신 이미지 파일 경로를 CLI 인수로 전달하려면 `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"` - - `IMAGE_ARG`가 설정되었을 때 이미지 인수 전달 방식을 제어하려면 `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"`(또는 `"list"`) - - 두 번째 턴을 보내고 resume 플로를 검증하려면 `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1` - - 기본 Claude Sonnet -> Opus 동일 세션 연속성 probe를 비활성화하려면 `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0`(선택한 모델이 전환 타깃을 지원할 때 강제로 켜려면 `1`) -- 예시: + - 실제 이미지 첨부를 보내려면 `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1`(경로는 프롬프트에 주입됨) + - 프롬프트 주입 대신 이미지 파일 경로를 CLI 인자로 전달하려면 `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"` + - `IMAGE_ARG`가 설정된 경우 이미지 인자 전달 방식을 제어하려면 `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"`(또는 `"list"`) + - 두 번째 턴을 보내고 재개 흐름을 검증하려면 `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1` + - 기본 Claude Sonnet -> Opus 동일 세션 연속성 프로브를 비활성화하려면 `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0`(선택된 모델이 전환 대상을 지원할 때 강제로 켜려면 `1`) + +예시: ```bash OPENCLAW_LIVE_CLI_BACKEND=1 \ @@ -296,7 +313,7 @@ Docker 레시피: pnpm test:docker:live-cli-backend ``` -단일 provider Docker 레시피: +단일 프로바이더 Docker 레시피: ```bash pnpm test:docker:live-cli-backend:claude @@ -306,26 +323,26 @@ pnpm test:docker:live-cli-backend:gemini 참고: -- Docker 러너는 `scripts/test-live-cli-backend-docker.sh`에 있습니다. -- 저장소 Docker 이미지 안에서 비-root `node` 사용자로 live CLI-backend 스모크를 실행합니다. -- 해당 extension에서 CLI 스모크 메타데이터를 확인한 뒤, 일치하는 Linux CLI 패키지(`@anthropic-ai/claude-code`, `@openai/codex`, 또는 `@google/gemini-cli`)를 캐시 가능한 쓰기 가능 prefix `OPENCLAW_DOCKER_CLI_TOOLS_DIR`(기본값: `~/.cache/openclaw/docker-cli-tools`)에 설치합니다. -- live CLI-backend 스모크는 이제 Claude, Codex, Gemini에 대해 동일한 end-to-end 플로를 실행합니다: 텍스트 턴, 이미지 분류 턴, 그 다음 gateway CLI를 통해 검증되는 MCP `cron` 도구 호출. +- Docker 실행기는 `scripts/test-live-cli-backend-docker.sh`에 있습니다. +- 저장소 Docker 이미지 내부에서 비루트 `node` 사용자로 라이브 CLI 백엔드 스모크를 실행합니다. +- 소유 확장에서 CLI 스모크 메타데이터를 해석한 뒤, 일치하는 Linux CLI 패키지(`@anthropic-ai/claude-code`, `@openai/codex`, 또는 `@google/gemini-cli`)를 캐시된 쓰기 가능한 접두사 `OPENCLAW_DOCKER_CLI_TOOLS_DIR`(기본값: `~/.cache/openclaw/docker-cli-tools`)에 설치합니다. +- 이제 라이브 CLI 백엔드 스모크는 Claude, Codex, Gemini에 대해 동일한 end-to-end 흐름을 실행합니다: 텍스트 턴, 이미지 분류 턴, 그리고 게이트웨이 CLI를 통해 검증되는 MCP `cron` 도구 호출. - Claude의 기본 스모크는 또한 세션을 Sonnet에서 Opus로 패치하고 재개된 세션이 이전 메모를 여전히 기억하는지 검증합니다. -## Live: ACP bind 스모크(`/acp spawn ... --bind here`) +## 라이브: ACP 바인드 스모크(`/acp spawn ... --bind here`) - 테스트: `src/gateway/gateway-acp-bind.live.test.ts` -- 목표: live ACP agent를 사용한 실제 ACP 대화 bind 플로 검증: +- 목표: 라이브 ACP 에이전트로 실제 ACP 대화 바인드 흐름을 검증합니다: - `/acp spawn --bind here` 전송 - - 합성 message-channel 대화를 제자리에서 bind - - 같은 대화에서 일반 후속 메시지 전송 - - 후속 메시지가 bind된 ACP 세션 기록에 도달했는지 검증 + - 합성 message-channel 대화를 제자리에서 바인드 + - 동일한 대화에서 일반 후속 메시지 전송 + - 후속 메시지가 바인드된 ACP 세션 transcript에 도착하는지 검증 - 활성화: - `pnpm test:live src/gateway/gateway-acp-bind.live.test.ts` - `OPENCLAW_LIVE_ACP_BIND=1` - 기본값: - - Docker의 ACP agent: `claude,codex,gemini` - - 직접 `pnpm test:live ...`용 ACP agent: `claude` + - Docker의 ACP 에이전트: `claude,codex,gemini` + - 직접 `pnpm test:live ...`용 ACP 에이전트: `claude` - 합성 채널: Slack DM 스타일 대화 컨텍스트 - ACP 백엔드: `acpx` - 재정의: @@ -335,8 +352,8 @@ pnpm test:docker:live-cli-backend:gemini - `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex,gemini` - `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND='npx -y @agentclientprotocol/claude-agent-acp@'` - 참고: - - 이 lane은 테스트가 외부 전달을 가장하지 않고 message-channel 컨텍스트를 붙일 수 있도록 admin 전용 synthetic originating-route 필드와 함께 gateway `chat.send` 표면을 사용합니다. - - `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND`가 설정되지 않은 경우, 테스트는 선택된 ACP harness agent에 대해 임베디드 `acpx` plugin의 내장 agent registry를 사용합니다. + - 이 레인은 관리자 전용 합성 originating-route 필드가 포함된 게이트웨이 `chat.send` 표면을 사용하므로, 테스트가 외부 전달을 가장하지 않고 message-channel 컨텍스트를 부착할 수 있습니다. + - `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND`가 설정되지 않은 경우, 테스트는 선택된 ACP 하네스 에이전트에 대해 임베디드 `acpx` plugin의 내장 에이전트 레지스트리를 사용합니다. 예시: @@ -352,7 +369,7 @@ Docker 레시피: pnpm test:docker:live-acp-bind ``` -단일 agent Docker 레시피: +단일 에이전트 Docker 레시피: ```bash pnpm test:docker:live-acp-bind:claude @@ -362,23 +379,23 @@ pnpm test:docker:live-acp-bind:gemini Docker 참고: -- Docker 러너는 `scripts/test-live-acp-bind-docker.sh`에 있습니다. -- 기본적으로 지원되는 모든 live CLI agent(`claude`, `codex`, `gemini`)에 대해 ACP bind 스모크를 순차 실행합니다. +- Docker 실행기는 `scripts/test-live-acp-bind-docker.sh`에 있습니다. +- 기본적으로 지원되는 모든 라이브 CLI 에이전트(`claude`, `codex`, `gemini`)에 대해 ACP 바인드 스모크를 순차 실행합니다. - 매트릭스 범위를 좁히려면 `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude`, `OPENCLAW_LIVE_ACP_BIND_AGENTS=codex`, 또는 `OPENCLAW_LIVE_ACP_BIND_AGENTS=gemini`를 사용하세요. -- `~/.profile`을 소싱하고, 일치하는 CLI auth 자료를 컨테이너에 스테이징하며, 쓰기 가능한 npm prefix에 `acpx`를 설치한 뒤, 요청된 live CLI(`@anthropic-ai/claude-code`, `@openai/codex`, 또는 `@google/gemini-cli`)가 없으면 설치합니다. -- Docker 내부에서는 러너가 `OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx`를 설정하므로, acpx가 소싱된 profile의 provider env var를 자식 harness CLI에서 계속 사용할 수 있습니다. +- `~/.profile`을 소싱하고, 일치하는 CLI 인증 자료를 컨테이너에 준비하며, `acpx`를 쓰기 가능한 npm 접두사에 설치한 다음, 없으면 요청된 라이브 CLI(`@anthropic-ai/claude-code`, `@openai/codex`, 또는 `@google/gemini-cli`)를 설치합니다. +- Docker 내부에서 실행기는 `OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx`를 설정하므로, 소싱된 프로필의 프로바이더 env 변수를 acpx가 자식 하네스 CLI에 계속 제공할 수 있습니다. -### 권장 live 레시피 +### 권장 라이브 레시피 -범위를 좁힌 명시적 allowlist가 가장 빠르고 변동성이 가장 적습니다: +범위를 좁힌 명시적 허용 목록이 가장 빠르고 가장 덜 불안정합니다. -- 단일 모델, 직접(gateway 없음): +- 단일 모델, 직접 실행(게이트웨이 없음): - `OPENCLAW_LIVE_MODELS="openai/gpt-5.4" pnpm test:live src/agents/models.profiles.live.test.ts` -- 단일 모델, gateway 스모크: +- 단일 모델, 게이트웨이 스모크: - `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` -- 여러 provider에 걸친 tool calling: +- 여러 프로바이더에 걸친 도구 호출: - `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3-flash-preview,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` - Google 중심(Gemini API 키 + Antigravity): @@ -388,34 +405,34 @@ Docker 참고: 참고: - `google/...`는 Gemini API(API 키)를 사용합니다. -- `google-antigravity/...`는 Antigravity OAuth 브리지(Cloud Code Assist 스타일 agent 엔드포인트)를 사용합니다. -- `google-gemini-cli/...`는 머신의 로컬 Gemini CLI를 사용합니다(별도 auth + tooling 특이사항). -- Gemini API vs Gemini CLI: - - API: OpenClaw가 HTTP를 통해 Google의 호스팅된 Gemini API를 호출합니다(API 키 / profile auth). 대부분의 사용자가 "Gemini"라고 할 때 의미하는 것은 이것입니다. - - CLI: OpenClaw가 로컬 `gemini` 바이너리를 shell out으로 호출합니다. 별도의 auth를 가지며 다르게 동작할 수 있습니다(스트리밍/도구 지원/버전 차이). +- `google-antigravity/...`는 Antigravity OAuth 브리지(Cloud Code Assist 스타일 에이전트 엔드포인트)를 사용합니다. +- `google-gemini-cli/...`는 사용자의 머신에 있는 로컬 Gemini CLI를 사용합니다(별도의 인증 + 도구 동작 특이점 존재). +- Gemini API와 Gemini CLI의 차이: + - API: OpenClaw가 Google의 호스팅된 Gemini API를 HTTP(API 키 / 프로필 인증)로 호출합니다. 대부분의 사용자가 “Gemini”라고 할 때 의미하는 것은 이것입니다. + - CLI: OpenClaw가 로컬 `gemini` 바이너리를 셸 실행합니다. 자체 인증을 가지며 동작 방식이 다를 수 있습니다(스트리밍/도구 지원/버전 차이). -## Live: 모델 매트릭스(무엇을 커버하는가) +## 라이브: 모델 매트릭스(무엇을 다루는가) -고정된 "CI 모델 목록"은 없습니다(live는 옵트인). 하지만 키가 있는 개발 머신에서 정기적으로 커버하기를 권장하는 모델은 다음과 같습니다. +고정된 “CI 모델 목록”은 없습니다(라이브는 옵트인). 하지만 키를 가진 개발 머신에서 정기적으로 다루기를 **권장하는** 모델은 다음과 같습니다. -### 최신 스모크 세트(tool calling + 이미지) +### 현대식 스모크 세트(도구 호출 + 이미지) -이는 우리가 계속 동작하기를 기대하는 "일반 모델" 실행입니다: +이것은 계속 동작해야 하는 것으로 기대하는 “공통 모델” 실행입니다. - OpenAI(non-Codex): `openai/gpt-5.4`(선택 사항: `openai/gpt-5.4-mini`) - OpenAI Codex: `openai-codex/gpt-5.4` - Anthropic: `anthropic/claude-opus-4-6`(또는 `anthropic/claude-sonnet-4-6`) -- Google(Gemini API): `google/gemini-3.1-pro-preview` 및 `google/gemini-3-flash-preview`(오래된 Gemini 2.x 모델은 피하세요) +- Google(Gemini API): `google/gemini-3.1-pro-preview` 및 `google/gemini-3-flash-preview`(구형 Gemini 2.x 모델은 피하세요) - Google(Antigravity): `google-antigravity/claude-opus-4-6-thinking` 및 `google-antigravity/gemini-3-flash` - Z.AI(GLM): `zai/glm-4.7` - MiniMax: `minimax/MiniMax-M2.7` -도구 + 이미지와 함께 gateway 스모크 실행: +도구 + 이미지가 포함된 게이트웨이 스모크 실행: `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4,openai-codex/gpt-5.4,anthropic/claude-opus-4-6,google/gemini-3.1-pro-preview,google/gemini-3-flash-preview,google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-flash,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` -### 기준선: tool calling(Read + 선택적 Exec) +### 기준선: 도구 호출(Read + 선택적 Exec) -provider 계열별로 최소 하나는 선택하세요: +프로바이더 계열마다 최소 하나는 선택하세요. - OpenAI: `openai/gpt-5.4`(또는 `openai/gpt-5.4-mini`) - Anthropic: `anthropic/claude-opus-4-6`(또는 `anthropic/claude-sonnet-4-6`) @@ -426,277 +443,251 @@ provider 계열별로 최소 하나는 선택하세요: 선택적 추가 커버리지(있으면 좋음): - xAI: `xai/grok-4`(또는 최신 사용 가능 버전) -- Mistral: `mistral/`…(활성화된 "tools" 지원 모델 하나 선택) +- Mistral: `mistral/`…(활성화된 “tools” 지원 모델 하나 선택) - Cerebras: `cerebras/`…(접근 권한이 있는 경우) -- LM Studio: `lmstudio/`…(로컬, tool calling은 API 모드에 따라 달라짐) +- LM Studio: `lmstudio/`…(로컬; 도구 호출은 API 모드에 따라 다름) -### Vision: 이미지 전송(attachment → 멀티모달 메시지) +### 비전: 이미지 전송(첨부 파일 → 멀티모달 메시지) -이미지 probe를 실행하려면 이미지 지원 모델 하나 이상을 `OPENCLAW_LIVE_GATEWAY_MODELS`에 포함하세요(Claude/Gemini/OpenAI의 vision 지원 변형 등). +이미지 프로브를 실행하려면 이미지 입력이 가능한 모델 하나 이상을 `OPENCLAW_LIVE_GATEWAY_MODELS`에 포함하세요(Claude/Gemini/OpenAI의 비전 지원 변형 등). -### Aggregator / 대체 gateway +### 애그리게이터 / 대체 게이트웨이 -키가 활성화되어 있다면 다음 경로를 통해서도 테스트를 지원합니다: +키가 활성화되어 있다면 다음을 통한 테스트도 지원합니다. -- OpenRouter: `openrouter/...`(수백 개 모델, `openclaw models scan`으로 tool+image 지원 후보 찾기) -- OpenCode: Zen용 `opencode/...`, Go용 `opencode-go/...`(auth는 `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY`) +- OpenRouter: `openrouter/...`(수백 개의 모델; 도구+이미지 지원 후보를 찾으려면 `openclaw models scan` 사용) +- OpenCode: Zen용 `opencode/...`, Go용 `opencode-go/...`(인증은 `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY` 사용) -live 매트릭스에 포함할 수 있는 더 많은 providers(자격 증명/config가 있는 경우): +라이브 매트릭스에 포함할 수 있는 추가 프로바이더(자격 증명/구성이 있는 경우): - 내장: `openai`, `openai-codex`, `anthropic`, `google`, `google-vertex`, `google-antigravity`, `google-gemini-cli`, `zai`, `openrouter`, `opencode`, `opencode-go`, `xai`, `groq`, `cerebras`, `mistral`, `github-copilot` -- `models.providers`를 통해(커스텀 엔드포인트): `minimax`(클라우드/API), 그리고 모든 OpenAI/Anthropic 호환 프록시(LM Studio, vLLM, LiteLLM 등) +- `models.providers` 경유(사용자 지정 엔드포인트): `minimax`(클라우드/API), 그리고 모든 OpenAI/Anthropic 호환 프록시(LM Studio, vLLM, LiteLLM 등) -팁: 문서에 "모든 모델"을 하드코딩하려고 하지 마세요. 권위 있는 목록은 자신의 머신에서 `discoverModels(...)`가 반환하는 값과 사용 가능한 키의 조합입니다. +팁: 문서에 “모든 모델”을 하드코딩하려고 하지 마세요. 권위 있는 목록은 사용자의 머신에서 `discoverModels(...)`가 반환하는 값과 사용 가능한 키의 조합입니다. ## 자격 증명(절대 커밋 금지) -live 테스트는 CLI와 동일한 방식으로 자격 증명을 찾습니다. 실질적인 의미는 다음과 같습니다: +라이브 테스트는 CLI와 같은 방식으로 자격 증명을 탐색합니다. 실무적으로는 다음을 의미합니다. -- CLI가 동작한다면 live 테스트도 동일한 키를 찾아야 합니다. -- live 테스트가 "자격 증명 없음"이라고 하면, `openclaw models list` / 모델 선택을 디버깅하듯 같은 방식으로 디버깅하세요. +- CLI가 동작하면, 라이브 테스트도 동일한 키를 찾아야 합니다. +- 라이브 테스트가 “자격 증명 없음”이라고 하면, `openclaw models list` / 모델 선택을 디버깅하는 것과 같은 방식으로 디버깅하세요. -- 에이전트별 auth profile: `~/.openclaw/agents//agent/auth-profiles.json`(live 테스트에서 "profile 키"가 의미하는 것) -- Config: `~/.openclaw/openclaw.json`(또는 `OPENCLAW_CONFIG_PATH`) -- 레거시 상태 디렉터리: `~/.openclaw/credentials/`(존재할 경우 스테이징된 live 홈으로 복사되지만, 메인 profile-key 저장소는 아님) -- 로컬 live 실행은 기본적으로 활성 config, 에이전트별 `auth-profiles.json`, 레거시 `credentials/`, 그리고 지원되는 외부 CLI auth 디렉터리를 임시 테스트 홈으로 복사합니다. 스테이징된 live 홈은 `workspace/`와 `sandboxes/`를 건너뛰고, `agents.*.workspace` / `agentDir` 경로 재정의는 제거되므로 probe가 실제 호스트 워크스페이스에 영향을 주지 않습니다. +- 에이전트별 인증 프로필: `~/.openclaw/agents//agent/auth-profiles.json`(라이브 테스트에서 “프로필 키”가 의미하는 것) +- 구성: `~/.openclaw/openclaw.json`(또는 `OPENCLAW_CONFIG_PATH`) +- 레거시 상태 디렉터리: `~/.openclaw/credentials/`(존재할 경우 준비된 라이브 홈으로 복사되지만, 기본 프로필 키 저장소는 아님) +- 로컬 라이브 실행은 기본적으로 활성 구성, 에이전트별 `auth-profiles.json` 파일, 레거시 `credentials/`, 지원되는 외부 CLI 인증 디렉터리를 임시 테스트 홈으로 복사합니다. 준비된 라이브 홈은 `workspace/`와 `sandboxes/`를 건너뛰며, `agents.*.workspace` / `agentDir` 경로 재정의도 제거되어 프로브가 실제 호스트 워크스페이스에 영향을 주지 않도록 합니다. -env 키에 의존하고 싶다면(예: `~/.profile`에 export됨), 로컬 테스트 전에 `source ~/.profile`을 실행하거나 아래 Docker 러너를 사용하세요(Docker 러너는 `~/.profile`을 컨테이너에 마운트할 수 있습니다). +env 키에 의존하고 싶다면(예: `~/.profile`에 export된 경우), `source ~/.profile` 후 로컬 테스트를 실행하거나 아래 Docker 실행기를 사용하세요(컨테이너 안으로 `~/.profile`을 마운트할 수 있음). -## Deepgram live(오디오 전사) +## Deepgram 라이브(오디오 전사) - 테스트: `src/media-understanding/providers/deepgram/audio.live.test.ts` - 활성화: `DEEPGRAM_API_KEY=... DEEPGRAM_LIVE_TEST=1 pnpm test:live src/media-understanding/providers/deepgram/audio.live.test.ts` -## BytePlus 코딩 플랜 live +## BytePlus 코딩 플랜 라이브 - 테스트: `src/agents/byteplus.live.test.ts` - 활성화: `BYTEPLUS_API_KEY=... BYTEPLUS_LIVE_TEST=1 pnpm test:live src/agents/byteplus.live.test.ts` - 선택적 모델 재정의: `BYTEPLUS_CODING_MODEL=ark-code-latest` -## ComfyUI 워크플로 미디어 live +## ComfyUI 워크플로 미디어 라이브 - 테스트: `extensions/comfy/comfy.live.test.ts` - 활성화: `OPENCLAW_LIVE_TEST=1 COMFY_LIVE_TEST=1 pnpm test:live -- extensions/comfy/comfy.live.test.ts` - 범위: - - 번들된 comfy 이미지, 비디오, `music_generate` 경로를 실행 - - `models.providers.comfy.`가 구성되어 있지 않으면 각 capability를 건너뜀 - - comfy 워크플로 제출, polling, 다운로드, 또는 plugin 등록을 변경한 뒤 유용함 + - 번들된 comfy 이미지, 비디오, `music_generate` 경로를 실행합니다 + - `models.providers.comfy.`가 구성되지 않은 경우 각 기능을 건너뜁니다 + - comfy 워크플로 제출, 폴링, 다운로드 또는 plugin 등록을 변경한 후 유용합니다 -## 이미지 생성 live +## 이미지 생성 라이브 - 테스트: `src/image-generation/runtime.live.test.ts` -- 명령어: `pnpm test:live src/image-generation/runtime.live.test.ts` -- 하니스: `pnpm test:live:media image` +- 명령: `pnpm test:live src/image-generation/runtime.live.test.ts` +- 하네스: `pnpm test:live:media image` - 범위: - - 등록된 모든 이미지 생성 provider plugin을 열거 - - probe 전에 로그인 셸(`~/.profile`)에서 누락된 provider env var를 로드 - - 기본적으로 저장된 auth profile보다 live/env API 키를 우선 사용하므로, `auth-profiles.json`의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않음 - - 사용 가능한 auth/profile/model이 없는 provider는 건너뜀 - - 공유 런타임 capability를 통해 기본 이미지 생성 변형을 실행: + - 등록된 모든 이미지 생성 프로바이더 plugin을 열거합니다 + - 프로브 전에 로그인 셸(`~/.profile`)에서 누락된 프로바이더 env 변수를 로드합니다 + - 기본적으로 저장된 인증 프로필보다 라이브/env API 키를 우선 사용하므로 `auth-profiles.json`의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않습니다 + - 사용 가능한 인증/프로필/모델이 없는 프로바이더는 건너뜁니다 + - 공유 런타임 기능을 통해 기본 이미지 생성 변형을 실행합니다: - `google:flash-generate` - `google:pro-generate` - `google:pro-edit` - `openai:default-generate` -- 현재 커버되는 번들 provider: +- 현재 다루는 번들 프로바이더: - `openai` - `google` -- 선택적 범위 좁히기: +- 선택적 범위 축소: - `OPENCLAW_LIVE_IMAGE_GENERATION_PROVIDERS="openai,google"` - `OPENCLAW_LIVE_IMAGE_GENERATION_MODELS="openai/gpt-image-1,google/gemini-3.1-flash-image-preview"` - `OPENCLAW_LIVE_IMAGE_GENERATION_CASES="google:flash-generate,google:pro-edit"` -- 선택적 auth 동작: - - profile 저장소 auth를 강제하고 env 전용 재정의를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` +- 선택적 인증 동작: + - 프로필 저장소 인증만 강제하고 env 전용 재정의를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` -## 음악 생성 live +## 음악 생성 라이브 - 테스트: `extensions/music-generation-providers.live.test.ts` - 활성화: `OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/music-generation-providers.live.test.ts` -- 하니스: `pnpm test:live:media music` +- 하네스: `pnpm test:live:media music` - 범위: - - 공유 번들 음악 생성 provider 경로를 실행 - - 현재 Google과 MiniMax를 커버 - - probe 전에 로그인 셸(`~/.profile`)에서 provider env var를 로드 - - 기본적으로 저장된 auth profile보다 live/env API 키를 우선 사용하므로, `auth-profiles.json`의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않음 - - 사용 가능한 auth/profile/model이 없는 provider는 건너뜀 - - 사용 가능한 경우 선언된 두 런타임 모드를 모두 실행: - - 프롬프트 전용 입력으로 `generate` - - provider가 `capabilities.edit.enabled`를 선언할 때 `edit` - - 현재 공유 lane 커버리지: + - 공유 번들 음악 생성 프로바이더 경로를 실행합니다 + - 현재 Google과 MiniMax를 다룹니다 + - 프로브 전에 로그인 셸(`~/.profile`)에서 프로바이더 env 변수를 로드합니다 + - 기본적으로 저장된 인증 프로필보다 라이브/env API 키를 우선 사용하므로 `auth-profiles.json`의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않습니다 + - 사용 가능한 인증/프로필/모델이 없는 프로바이더는 건너뜁니다 + - 사용 가능한 경우 선언된 런타임 모드를 둘 다 실행합니다: + - 프롬프트만 입력으로 사용하는 `generate` + - 프로바이더가 `capabilities.edit.enabled`를 선언한 경우의 `edit` + - 현재 공유 레인 커버리지: - `google`: `generate`, `edit` - `minimax`: `generate` - - `comfy`: 별도 Comfy live 파일이며 이 공유 스윕은 아님 -- 선택적 범위 좁히기: + - `comfy`: 별도의 Comfy 라이브 파일에서 다루며, 이 공유 스윕에서는 다루지 않음 +- 선택적 범위 축소: - `OPENCLAW_LIVE_MUSIC_GENERATION_PROVIDERS="google,minimax"` - `OPENCLAW_LIVE_MUSIC_GENERATION_MODELS="google/lyria-3-clip-preview,minimax/music-2.5+"` -- 선택적 auth 동작: - - profile 저장소 auth를 강제하고 env 전용 재정의를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` +- 선택적 인증 동작: + - 프로필 저장소 인증만 강제하고 env 전용 재정의를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` -## 비디오 생성 live +## 비디오 생성 라이브 - 테스트: `extensions/video-generation-providers.live.test.ts` - 활성화: `OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/video-generation-providers.live.test.ts` -- 하니스: `pnpm test:live:media video` +- 하네스: `pnpm test:live:media video` - 범위: - - 공유 번들 비디오 생성 provider 경로를 실행 - - probe 전에 로그인 셸(`~/.profile`)에서 provider env var를 로드 - - 기본적으로 저장된 auth profile보다 live/env API 키를 우선 사용하므로, `auth-profiles.json`의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않음 - - 사용 가능한 auth/profile/model이 없는 provider는 건너뜀 - - 사용 가능한 경우 선언된 두 런타임 모드를 모두 실행: - - 프롬프트 전용 입력으로 `generate` - - provider가 `capabilities.imageToVideo.enabled`를 선언하고 선택된 provider/model이 공유 스윕에서 버퍼 기반 로컬 이미지 입력을 허용할 때 `imageToVideo` - - provider가 `capabilities.videoToVideo.enabled`를 선언하고 선택된 provider/model이 공유 스윕에서 버퍼 기반 로컬 비디오 입력을 허용할 때 `videoToVideo` - - 공유 스윕에서 현재 선언되었지만 건너뛰는 `imageToVideo` providers: - - `vydra`: 번들 `veo3`는 텍스트 전용이고 번들 `kling`은 원격 이미지 URL이 필요하기 때문 - - provider별 Vydra 커버리지: + - 공유 번들 비디오 생성 프로바이더 경로를 실행합니다 + - 프로브 전에 로그인 셸(`~/.profile`)에서 프로바이더 env 변수를 로드합니다 + - 기본적으로 저장된 인증 프로필보다 라이브/env API 키를 우선 사용하므로 `auth-profiles.json`의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않습니다 + - 사용 가능한 인증/프로필/모델이 없는 프로바이더는 건너뜁니다 + - 사용 가능한 경우 선언된 런타임 모드를 둘 다 실행합니다: + - 프롬프트만 입력으로 사용하는 `generate` + - 프로바이더가 `capabilities.imageToVideo.enabled`를 선언하고 선택된 프로바이더/모델이 공유 스윕에서 버퍼 기반 로컬 이미지 입력을 허용하는 경우의 `imageToVideo` + - 프로바이더가 `capabilities.videoToVideo.enabled`를 선언하고 선택된 프로바이더/모델이 공유 스윕에서 버퍼 기반 로컬 비디오 입력을 허용하는 경우의 `videoToVideo` + - 현재 공유 스윕에서 선언되었지만 건너뛰는 `imageToVideo` 프로바이더: + - `vydra`: 번들된 `veo3`는 텍스트 전용이고 번들된 `kling`은 원격 이미지 URL이 필요하기 때문 + - 프로바이더별 Vydra 커버리지: - `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_VYDRA_VIDEO=1 pnpm test:live -- extensions/vydra/vydra.live.test.ts` - - 이 파일은 기본적으로 원격 이미지 URL fixture를 사용하는 `kling` lane과 함께 `veo3` 텍스트-투-비디오를 실행합니다 - - 현재 `videoToVideo` live 커버리지: - - 선택된 모델이 `runway/gen4_aleph`일 때 `runway`만 - - 공유 스윕에서 현재 선언되었지만 건너뛰는 `videoToVideo` providers: - - `alibaba`, `qwen`, `xai`: 이 경로들이 현재 원격 `http(s)` / MP4 참조 URL을 필요로 하기 때문 - - `google`: 현재 공유 Gemini/Veo lane이 로컬 버퍼 기반 입력을 사용하며 이 경로는 공유 스윕에서 허용되지 않기 때문 - - `openai`: 현재 공유 lane에는 조직별 비디오 inpaint/remix 액세스 보장이 없기 때문 -- 선택적 범위 좁히기: + - 이 파일은 기본적으로 `veo3` 텍스트-비디오와 원격 이미지 URL 픽스처를 사용하는 `kling` 레인을 실행합니다 + - 현재 `videoToVideo` 라이브 커버리지: + - 선택된 모델이 `runway/gen4_aleph`일 때만 `runway` + - 현재 공유 스윕에서 선언되었지만 건너뛰는 `videoToVideo` 프로바이더: + - `alibaba`, `qwen`, `xai`: 현재 해당 경로들이 원격 `http(s)` / MP4 참조 URL을 필요로 하기 때문 + - `google`: 현재 공유 Gemini/Veo 레인이 로컬 버퍼 기반 입력을 사용하며, 이 경로는 공유 스윕에서 허용되지 않기 때문 + - `openai`: 현재 공유 레인에 조직별 비디오 인페인트/리믹스 접근 보장이 없기 때문 +- 선택적 범위 축소: - `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="google,openai,runway"` - `OPENCLAW_LIVE_VIDEO_GENERATION_MODELS="google/veo-3.1-fast-generate-preview,openai/sora-2,runway/gen4_aleph"` -- 선택적 auth 동작: - - profile 저장소 auth를 강제하고 env 전용 재정의를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` +- 선택적 인증 동작: + - 프로필 저장소 인증만 강제하고 env 전용 재정의를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` -## 미디어 live 하니스 +## 미디어 라이브 하네스 -- 명령어: `pnpm test:live:media` +- 명령: `pnpm test:live:media` - 목적: - - 공유 이미지, 음악, 비디오 live 스위트를 하나의 저장소 기본 진입점으로 실행 - - `~/.profile`에서 누락된 provider env var를 자동 로드 - - 기본적으로 현재 사용 가능한 auth가 있는 provider로 각 스위트 범위를 자동 축소 - - `scripts/test-live.mjs`를 재사용하므로 heartbeat 및 quiet-mode 동작이 일관되게 유지됨 + - 저장소 네이티브 진입점 하나로 공유 이미지, 음악, 비디오 라이브 스위트를 실행합니다 + - `~/.profile`에서 누락된 프로바이더 env 변수를 자동으로 로드합니다 + - 기본적으로 현재 사용 가능한 인증이 있는 프로바이더로 각 스위트 범위를 자동 축소합니다 + - `scripts/test-live.mjs`를 재사용하므로 하트비트와 조용한 모드 동작이 일관되게 유지됩니다 - 예시: - `pnpm test:live:media` - `pnpm test:live:media image video --providers openai,google,minimax` - `pnpm test:live:media video --video-providers openai,runway --all-providers` - `pnpm test:live:media music --quiet` -## Docker 러너(선택적 "Linux에서 동작하는지" 확인) +## Docker 실행기(선택적 "Linux에서도 동작하는가" 확인) -이 Docker 러너는 두 범주로 나뉩니다: +이 Docker 실행기들은 두 범주로 나뉩니다: -- live-model 러너: `test:docker:live-models`와 `test:docker:live-gateway`는 저장소 Docker 이미지 안에서 일치하는 profile-key live 파일(`src/agents/models.profiles.live.test.ts`와 `src/gateway/gateway-models.profiles.live.test.ts`)만 실행합니다. 로컬 config 디렉터리와 워크스페이스를 마운트하고(마운트된 경우 `~/.profile`도 소싱) 대응하는 로컬 진입점은 `test:live:models-profiles`와 `test:live:gateway-profiles`입니다. -- Docker live 러너는 전체 Docker 스윕이 실용적이도록 더 작은 스모크 상한을 기본으로 사용합니다: - `test:docker:live-models`는 기본적으로 `OPENCLAW_LIVE_MAX_MODELS=12`, 그리고 +- 라이브 모델 실행기: `test:docker:live-models`와 `test:docker:live-gateway`는 저장소 Docker 이미지 내부에서 각자 대응되는 프로필 키 라이브 파일만 실행합니다(`src/agents/models.profiles.live.test.ts` 및 `src/gateway/gateway-models.profiles.live.test.ts`). 이때 로컬 구성 디렉터리와 워크스페이스를 마운트하고(마운트된 경우 `~/.profile`도 소싱) 실행합니다. 대응되는 로컬 진입점은 `test:live:models-profiles`와 `test:live:gateway-profiles`입니다. +- Docker 라이브 실행기는 전체 Docker 스윕을 실용적으로 유지하기 위해 기본적으로 더 작은 스모크 상한을 사용합니다: + `test:docker:live-models`는 기본적으로 `OPENCLAW_LIVE_MAX_MODELS=12`를 사용하고, `test:docker:live-gateway`는 기본적으로 `OPENCLAW_LIVE_GATEWAY_SMOKE=1`, `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8`, `OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000`, 그리고 - `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`를 설정합니다. 더 큰 exhaustive scan을 - 명시적으로 원할 때는 이 환경 변수를 재정의하세요. -- `test:docker:all`은 `test:docker:live-build`를 통해 live Docker 이미지를 한 번 빌드한 뒤, 두 개의 live Docker lane에 이를 재사용합니다. -- 컨테이너 스모크 러너: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:gateway-network`, `test:docker:mcp-channels`, `test:docker:plugins`는 하나 이상의 실제 컨테이너를 부팅하고 더 높은 수준의 integration 경로를 검증합니다. + `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`를 사용합니다. 더 큰 전체 스캔을 명시적으로 원할 때는 해당 env 변수를 재정의하세요. +- `test:docker:all`은 먼저 `test:docker:live-build`를 통해 라이브 Docker 이미지를 한 번 빌드한 다음, 두 개의 라이브 Docker 레인에서 이를 재사용합니다. +- 컨테이너 스모크 실행기: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:gateway-network`, `test:docker:mcp-channels`, `test:docker:plugins`는 하나 이상의 실제 컨테이너를 부팅하고 더 높은 수준의 통합 경로를 검증합니다. -live-model Docker 러너는 또한 필요한 CLI auth 홈만 bind-mount합니다(실행 범위를 좁히지 않은 경우에는 지원되는 모든 홈). 그런 다음 실행 전에 이를 컨테이너 홈으로 복사하므로 외부 CLI OAuth가 호스트 auth 저장소를 변경하지 않고도 토큰을 갱신할 수 있습니다: +라이브 모델 Docker 실행기는 필요한 CLI 인증 홈만 바인드 마운트하며(실행 범위가 좁혀지지 않은 경우에는 지원되는 모든 홈), 실행 전에 이를 컨테이너 홈으로 복사하므로 외부 CLI OAuth가 호스트 인증 저장소를 변경하지 않고도 토큰을 갱신할 수 있습니다. - 직접 모델: `pnpm test:docker:live-models`(스크립트: `scripts/test-live-models-docker.sh`) -- ACP bind 스모크: `pnpm test:docker:live-acp-bind`(스크립트: `scripts/test-live-acp-bind-docker.sh`) +- ACP 바인드 스모크: `pnpm test:docker:live-acp-bind`(스크립트: `scripts/test-live-acp-bind-docker.sh`) - CLI 백엔드 스모크: `pnpm test:docker:live-cli-backend`(스크립트: `scripts/test-live-cli-backend-docker.sh`) -- Gateway + dev agent: `pnpm test:docker:live-gateway`(스크립트: `scripts/test-live-gateway-models-docker.sh`) -- Open WebUI live 스모크: `pnpm test:docker:openwebui`(스크립트: `scripts/e2e/openwebui-docker.sh`) -- 온보딩 마법사(TTY, 전체 scaffolding): `pnpm test:docker:onboard`(스크립트: `scripts/e2e/onboard-docker.sh`) -- Gateway 네트워킹(두 컨테이너, WS auth + health): `pnpm test:docker:gateway-network`(스크립트: `scripts/e2e/gateway-network-docker.sh`) -- MCP 채널 브리지(seed된 Gateway + stdio 브리지 + raw Claude notification-frame 스모크): `pnpm test:docker:mcp-channels`(스크립트: `scripts/e2e/mcp-channels-docker.sh`) -- Plugins(설치 스모크 + `/plugin` 별칭 + Claude 번들 재시작 의미 체계): `pnpm test:docker:plugins`(스크립트: `scripts/e2e/plugins-docker.sh`) +- 게이트웨이 + 개발 에이전트: `pnpm test:docker:live-gateway`(스크립트: `scripts/test-live-gateway-models-docker.sh`) +- Open WebUI 라이브 스모크: `pnpm test:docker:openwebui`(스크립트: `scripts/e2e/openwebui-docker.sh`) +- 온보딩 마법사(TTY, 전체 스캐폴딩): `pnpm test:docker:onboard`(스크립트: `scripts/e2e/onboard-docker.sh`) +- 게이트웨이 네트워킹(두 컨테이너, WS 인증 + 상태 확인): `pnpm test:docker:gateway-network`(스크립트: `scripts/e2e/gateway-network-docker.sh`) +- MCP 채널 브리지(시드된 Gateway + stdio 브리지 + 원시 Claude 알림 프레임 스모크): `pnpm test:docker:mcp-channels`(스크립트: `scripts/e2e/mcp-channels-docker.sh`) +- Plugins(설치 스모크 + `/plugin` 별칭 + Claude 번들 재시작 의미론): `pnpm test:docker:plugins`(스크립트: `scripts/e2e/plugins-docker.sh`) -live-model Docker 러너는 또한 현재 체크아웃을 읽기 전용으로 bind-mount하고 -이를 컨테이너 내부의 임시 workdir에 스테이징합니다. 이렇게 하면 런타임 -이미지를 슬림하게 유지하면서도 정확히 로컬 source/config에 대해 Vitest를 실행할 수 있습니다. -스테이징 단계는 `.pnpm-store`, `.worktrees`, `__openclaw_vitest__`, 그리고 앱 로컬 `.build` 또는 -Gradle 출력 디렉터리처럼 큰 로컬 전용 캐시와 앱 빌드 출력은 건너뛰므로, -Docker live 실행이 머신별 아티팩트를 복사하느라 수 분씩 걸리지 않습니다. -또한 `OPENCLAW_SKIP_CHANNELS=1`을 설정하므로 gateway live probe가 -컨테이너 내부에서 실제 Telegram/Discord/etc. 채널 워커를 시작하지 않습니다. -`test:docker:live-models`는 여전히 `pnpm test:live`를 실행하므로, -해당 Docker lane에서 gateway live 커버리지를 좁히거나 제외해야 할 때는 -`OPENCLAW_LIVE_GATEWAY_*`도 함께 전달하세요. -`test:docker:openwebui`는 더 높은 수준의 호환성 스모크입니다. OpenAI 호환 HTTP 엔드포인트를 -활성화한 OpenClaw gateway 컨테이너를 시작하고, -그 gateway를 대상으로 고정된 Open WebUI 컨테이너를 시작하며, Open WebUI를 통해 로그인하고, -`/api/models`가 `openclaw/default`를 노출하는지 검증한 뒤, -Open WebUI의 `/api/chat/completions` 프록시를 통해 실제 채팅 요청을 전송합니다. -첫 실행은 Docker가 -Open WebUI 이미지를 pull해야 하거나 Open WebUI 자체의 cold-start 설정을 마쳐야 해서 눈에 띄게 느릴 수 있습니다. -이 lane은 사용 가능한 live 모델 키를 필요로 하며, Dockerized 실행에서 이를 제공하는 주요 방법은 -`OPENCLAW_PROFILE_FILE`(`~/.profile` 기본값)입니다. -성공한 실행은 `{ "ok": true, "model": -"openclaw/default", ... }` 같은 작은 JSON 페이로드를 출력합니다. -`test:docker:mcp-channels`는 의도적으로 결정적이며 실제 -Telegram, Discord, 또는 iMessage 계정이 필요하지 않습니다. 시드된 Gateway -컨테이너를 부팅하고, `openclaw mcp serve`를 실행하는 두 번째 컨테이너를 시작한 뒤, -실제 stdio MCP 브리지를 통해 라우팅된 대화 탐색, 기록 읽기, 첨부 메타데이터, -실시간 이벤트 큐 동작, outbound send routing, 그리고 Claude 스타일 채널 + -권한 알림을 검증합니다. 알림 검사는 raw stdio MCP 프레임을 직접 살펴보므로 -이 스모크는 특정 클라이언트 SDK가 우연히 표면화하는 내용이 아니라 -브리지가 실제로 내보내는 내용을 검증합니다. +라이브 모델 Docker 실행기는 현재 체크아웃도 읽기 전용으로 바인드 마운트하고, 이를 컨테이너 내부의 임시 작업 디렉터리로 준비합니다. 이렇게 하면 런타임 이미지는 가볍게 유지하면서도 정확히 로컬 소스/구성에 대해 Vitest를 실행할 수 있습니다. +준비 단계는 `.pnpm-store`, `.worktrees`, `__openclaw_vitest__`, 앱 로컬 `.build` 또는 Gradle 출력 디렉터리처럼 큰 로컬 전용 캐시와 앱 빌드 출력을 건너뛰므로 Docker 라이브 실행이 머신별 아티팩트를 복사하느라 몇 분씩 소비하지 않습니다. +또한 `OPENCLAW_SKIP_CHANNELS=1`을 설정하므로 게이트웨이 라이브 프로브가 컨테이너 내부에서 실제 Telegram/Discord 등의 채널 워커를 시작하지 않습니다. +`test:docker:live-models`는 여전히 `pnpm test:live`를 실행하므로, 해당 Docker 레인에서 게이트웨이 라이브 커버리지를 좁히거나 제외해야 한다면 `OPENCLAW_LIVE_GATEWAY_*`도 함께 전달하세요. +`test:docker:openwebui`는 더 높은 수준의 호환성 스모크입니다. OpenAI 호환 HTTP 엔드포인트가 활성화된 OpenClaw 게이트웨이 컨테이너를 시작하고, 그 게이트웨이에 연결된 고정 Open WebUI 컨테이너를 시작한 뒤, Open WebUI를 통해 로그인하고, `/api/models`가 `openclaw/default`를 노출하는지 확인한 다음, Open WebUI의 `/api/chat/completions` 프록시를 통해 실제 채팅 요청을 전송합니다. +첫 실행은 Docker가 Open WebUI 이미지를 가져와야 하거나 Open WebUI 자체의 콜드 스타트 설정을 완료해야 할 수 있어 눈에 띄게 느릴 수 있습니다. +이 레인은 사용 가능한 라이브 모델 키를 기대하며, Docker 기반 실행에서는 `OPENCLAW_PROFILE_FILE`(`~/.profile`이 기본값)이 이를 제공하는 기본 방식입니다. +성공적인 실행은 `{ "ok": true, "model": "openclaw/default", ... }`와 같은 작은 JSON 페이로드를 출력합니다. +`test:docker:mcp-channels`는 의도적으로 결정론적이며 실제 Telegram, Discord, 또는 iMessage 계정이 필요하지 않습니다. 시드된 Gateway 컨테이너를 부팅하고, `openclaw mcp serve`를 시작하는 두 번째 컨테이너를 띄운 다음, 라우팅된 대화 탐색, transcript 읽기, 첨부 파일 메타데이터, 라이브 이벤트 큐 동작, 아웃바운드 전송 라우팅, 그리고 실제 stdio MCP 브리지를 통한 Claude 스타일 채널 + 권한 알림을 검증합니다. 알림 검사는 원시 stdio MCP 프레임을 직접 검사하므로, 특정 클라이언트 SDK가 우연히 노출하는 내용이 아니라 브리지가 실제로 내보내는 내용을 검증합니다. -수동 ACP plain-language 스레드 스모크(CI 아님): +수동 ACP 자연어 스레드 스모크(CI 아님): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` - 이 스크립트는 회귀/디버그 워크플로를 위해 유지하세요. ACP 스레드 라우팅 검증에 다시 필요할 수 있으므로 삭제하지 마세요. -유용한 환경 변수: +유용한 env 변수: -- `OPENCLAW_CONFIG_DIR=...`(기본값: `~/.openclaw`)는 `/home/node/.openclaw`에 마운트됨 -- `OPENCLAW_WORKSPACE_DIR=...`(기본값: `~/.openclaw/workspace`)는 `/home/node/.openclaw/workspace`에 마운트됨 -- `OPENCLAW_PROFILE_FILE=...`(기본값: `~/.profile`)는 `/home/node/.profile`에 마운트되고 테스트 실행 전에 소싱됨 -- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(기본값: `~/.cache/openclaw/docker-cli-tools`)는 Docker 내부 캐시된 CLI 설치용으로 `/home/node/.npm-global`에 마운트됨 -- `$HOME` 아래의 외부 CLI auth 디렉터리/파일은 `/host-auth...` 아래에 읽기 전용으로 마운트된 뒤, 테스트 시작 전에 `/home/node/...`로 복사됨 +- `OPENCLAW_CONFIG_DIR=...`(기본값: `~/.openclaw`)를 `/home/node/.openclaw`에 마운트 +- `OPENCLAW_WORKSPACE_DIR=...`(기본값: `~/.openclaw/workspace`)를 `/home/node/.openclaw/workspace`에 마운트 +- `OPENCLAW_PROFILE_FILE=...`(기본값: `~/.profile`)를 `/home/node/.profile`에 마운트하고 테스트 실행 전에 소싱 +- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(기본값: `~/.cache/openclaw/docker-cli-tools`)를 `/home/node/.npm-global`에 마운트하여 Docker 내부 CLI 설치 캐시로 사용 +- `$HOME` 아래의 외부 CLI 인증 디렉터리/파일은 `/host-auth...` 아래에 읽기 전용으로 마운트된 뒤, 테스트 시작 전에 `/home/node/...`로 복사됨 - 기본 디렉터리: `.minimax` - 기본 파일: `~/.codex/auth.json`, `~/.codex/config.toml`, `.claude.json`, `~/.claude/.credentials.json`, `~/.claude/settings.json`, `~/.claude/settings.local.json` - - 범위를 좁힌 provider 실행은 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS`에서 추론된 필요한 디렉터리/파일만 마운트함 + - 범위를 좁힌 프로바이더 실행은 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS`에서 추론된 필요한 디렉터리/파일만 마운트함 - 수동 재정의: `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none`, 또는 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 같은 쉼표 목록 - 실행 범위를 좁히려면 `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` -- 컨테이너 내부 provider 필터링에는 `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` -- 자격 증명이 profile 저장소에서 오도록 보장하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` -- Open WebUI 스모크용으로 gateway가 노출할 모델을 선택하려면 `OPENCLAW_OPENWEBUI_MODEL=...` -- Open WebUI 스모크에서 사용하는 nonce 확인 프롬프트를 재정의하려면 `OPENCLAW_OPENWEBUI_PROMPT=...` +- 컨테이너 내부에서 프로바이더를 필터링하려면 `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` +- 자격 증명이 프로필 저장소에서 오도록 강제하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1`(env 아님) +- Open WebUI 스모크용으로 게이트웨이가 노출할 모델을 선택하려면 `OPENCLAW_OPENWEBUI_MODEL=...` +- Open WebUI 스모크가 사용하는 nonce 확인 프롬프트를 재정의하려면 `OPENCLAW_OPENWEBUI_PROMPT=...` - 고정된 Open WebUI 이미지 태그를 재정의하려면 `OPENWEBUI_IMAGE=...` -## 문서 sanity +## 문서 기본 점검 -문서를 수정한 뒤에는 docs 체크를 실행하세요: `pnpm check:docs`. -인페이지 heading 체크까지 필요하면 전체 Mintlify anchor 검증을 실행하세요: `pnpm docs:check-links:anchors`. +문서를 수정한 뒤에는 문서 검사 실행: `pnpm check:docs`. +페이지 내 heading 검사까지 필요할 때는 전체 Mintlify 앵커 검증 실행: `pnpm docs:check-links:anchors`. ## 오프라인 회귀(CI 안전) -이것들은 실제 provider 없이도 "실제 파이프라인" 회귀를 검증합니다: +실제 프로바이더 없이도 가능한 “실제 파이프라인” 회귀입니다. -- Gateway tool calling(mock OpenAI, 실제 gateway + agent 루프): `src/gateway/gateway.test.ts`(케이스: "runs a mock OpenAI tool call end-to-end via gateway agent loop") -- Gateway wizard(WS `wizard.start`/`wizard.next`, config + auth 쓰기 강제): `src/gateway/gateway.test.ts`(케이스: "runs wizard over ws and writes auth token config") +- 게이트웨이 도구 호출(mock OpenAI, 실제 게이트웨이 + 에이전트 루프): `src/gateway/gateway.test.ts`(케이스: "runs a mock OpenAI tool call end-to-end via gateway agent loop") +- 게이트웨이 마법사(WS `wizard.start`/`wizard.next`, 구성 + 인증 토큰 쓰기 강제): `src/gateway/gateway.test.ts`(케이스: "runs wizard over ws and writes auth token config") ## 에이전트 신뢰성 평가(Skills) -우리는 이미 "에이전트 신뢰성 평가"처럼 동작하는 몇 가지 CI 안전 테스트를 가지고 있습니다: +이미 “에이전트 신뢰성 평가”처럼 동작하는 CI 안전 테스트가 몇 가지 있습니다. -- 실제 gateway + agent 루프를 통한 mock tool-calling(`src/gateway/gateway.test.ts`). -- 세션 wiring 및 config 효과를 검증하는 end-to-end wizard 플로(`src/gateway/gateway.test.ts`). +- 실제 게이트웨이 + 에이전트 루프를 통한 mock 도구 호출(`src/gateway/gateway.test.ts`). +- 세션 연결과 구성 효과를 검증하는 end-to-end 마법사 흐름(`src/gateway/gateway.test.ts`). -Skills에 대해 여전히 부족한 것([Skills](/ko/tools/skills) 참고): +Skills에 대해 아직 부족한 점([Skills](/ko/tools/skills) 참고): -- **의사결정:** 프롬프트에 skill이 나열되었을 때 에이전트가 올바른 skill을 선택하는가(또는 관련 없는 skill을 피하는가)? -- **준수성:** 사용 전에 에이전트가 `SKILL.md`를 읽고 필수 단계/인수를 따르는가? -- **워크플로 계약:** 도구 순서, 세션 기록 이어받기, 샌드박스 경계를 검증하는 멀티턴 시나리오. +- **판단:** 프롬프트에 skill이 나열될 때, 에이전트가 올바른 skill을 선택하는가(또는 관련 없는 skill을 피하는가)? +- **준수:** 에이전트가 사용 전에 `SKILL.md`를 읽고 필수 단계/인자를 따르는가? +- **워크플로 계약:** 도구 순서, 세션 히스토리 유지, 샌드박스 경계를 검증하는 다중 턴 시나리오. -향후 평가는 우선 결정적으로 유지되어야 합니다: +향후 평가는 우선 결정론적으로 유지해야 합니다. -- tool call + 순서, skill 파일 읽기, 세션 wiring을 검증하기 위해 mock provider를 사용하는 시나리오 러너. -- skill 중심 시나리오의 소규모 스위트(사용 vs 회피, 게이팅, 프롬프트 인젝션). -- CI 안전 스위트가 준비된 뒤에만 선택적으로 live 평가(옵트인, env 게이트). +- 도구 호출 + 순서, skill 파일 읽기, 세션 연결을 검증하기 위해 mock 프로바이더를 사용하는 시나리오 실행기 +- skill 중심의 소규모 시나리오 스위트(사용 vs 회피, 게이팅, 프롬프트 주입) +- CI 안전 스위트가 자리 잡은 뒤에만 선택적으로 라이브 평가(옵트인, env 게이트) ## 계약 테스트(plugin 및 channel 형태) -계약 테스트는 등록된 모든 plugin과 channel이 해당 -인터페이스 계약을 준수하는지 검증합니다. 발견된 모든 plugin을 순회하고 -형태 및 동작 검증 스위트를 실행합니다. 기본 `pnpm test` unit lane은 의도적으로 -이 공유 seam 및 스모크 파일을 건너뛰므로, 공유 channel 또는 provider 표면을 수정할 때는 -계약 명령을 명시적으로 실행하세요. +계약 테스트는 등록된 모든 plugin과 channel이 인터페이스 계약을 준수하는지 검증합니다. 발견된 모든 plugin을 순회하고 형태 및 동작 검증 스위트를 실행합니다. 기본 `pnpm test` 단위 레인은 의도적으로 이러한 공유 seam 및 스모크 파일을 건너뛰므로, 공유 channel 또는 provider 표면을 건드렸다면 계약 명령을 명시적으로 실행하세요. -### 명령어 +### 명령 - 모든 계약: `pnpm test:contracts` - channel 계약만: `pnpm test:contracts:channels` @@ -707,52 +698,52 @@ Skills에 대해 여전히 부족한 것([Skills](/ko/tools/skills) 참고): `src/channels/plugins/contracts/*.contract.test.ts`에 위치: - **plugin** - 기본 plugin 형태(id, name, capabilities) -- **setup** - setup wizard 계약 +- **setup** - 설정 마법사 계약 - **session-binding** - 세션 바인딩 동작 - **outbound-payload** - 메시지 페이로드 구조 -- **inbound** - inbound 메시지 처리 -- **actions** - channel action handler -- **threading** - thread ID 처리 -- **directory** - 디렉터리/roster API -- **group-policy** - 그룹 정책 강제 +- **inbound** - 인바운드 메시지 처리 +- **actions** - channel 액션 핸들러 +- **threading** - 스레드 ID 처리 +- **directory** - 디렉터리/명단 API +- **group-policy** - 그룹 정책 적용 ### Provider 상태 계약 `src/plugins/contracts/*.contract.test.ts`에 위치합니다. -- **status** - channel 상태 probe -- **registry** - plugin registry 형태 +- **status** - channel 상태 프로브 +- **registry** - plugin 레지스트리 형태 ### Provider 계약 `src/plugins/contracts/*.contract.test.ts`에 위치: -- **auth** - auth 플로 계약 -- **auth-choice** - auth 선택/선정 -- **catalog** - 모델 catalog API +- **auth** - 인증 흐름 계약 +- **auth-choice** - 인증 선택 +- **catalog** - 모델 카탈로그 API - **discovery** - plugin 탐색 -- **loader** - plugin 로딩 +- **loader** - plugin 로드 - **runtime** - provider 런타임 - **shape** - plugin 형태/인터페이스 -- **wizard** - setup wizard +- **wizard** - 설정 마법사 ### 실행 시점 -- plugin-sdk export 또는 subpath를 변경한 후 +- plugin-sdk export 또는 하위 경로를 변경한 후 - channel 또는 provider plugin을 추가하거나 수정한 후 - plugin 등록 또는 탐색을 리팩터링한 후 계약 테스트는 CI에서 실행되며 실제 API 키가 필요하지 않습니다. -## 회귀 테스트 추가(가이드) +## 회귀 추가하기(가이드) -live에서 발견된 provider/model 이슈를 수정할 때: +라이브에서 발견된 프로바이더/모델 이슈를 수정할 때: -- 가능하면 CI 안전 회귀를 추가하세요(mock/stub provider 또는 정확한 request-shape 변환 캡처) -- 본질적으로 live 전용인 경우(rate limit, auth 정책), live 테스트 범위를 좁게 유지하고 env var로 옵트인되게 하세요 -- 버그를 잡는 가장 작은 계층을 타기팅하세요: - - provider 요청 변환/replay 버그 → 직접 모델 테스트 - - gateway 세션/히스토리/도구 파이프라인 버그 → gateway live 스모크 또는 CI 안전 gateway mock 테스트 +- 가능하면 CI 안전 회귀를 추가하세요(mock/stub 프로바이더를 사용하거나, 정확한 요청 형태 변환을 캡처) +- 본질적으로 라이브 전용이라면(속도 제한, 인증 정책), 라이브 테스트는 좁은 범위로 유지하고 env 변수를 통해 옵트인으로 만드세요 +- 버그를 잡아내는 가장 작은 계층을 대상으로 삼는 것을 선호하세요: + - 프로바이더 요청 변환/재생 버그 → 직접 모델 테스트 + - 게이트웨이 세션/히스토리/도구 파이프라인 버그 → 게이트웨이 라이브 스모크 또는 CI 안전 게이트웨이 mock 테스트 - SecretRef 순회 가드레일: - - `src/secrets/exec-secret-ref-id-parity.test.ts`는 registry 메타데이터(`listSecretTargetRegistryEntries()`)에서 SecretRef 클래스별 샘플 타깃 하나를 도출한 뒤, traversal-segment exec id가 거부되는지 검증합니다. - - `src/secrets/target-registry-data.ts`에 새로운 `includeInPlan` SecretRef 타깃 계열을 추가하면 해당 테스트의 `classifyTargetClass`를 업데이트하세요. 이 테스트는 새 클래스가 조용히 건너뛰어지지 않도록 분류되지 않은 타깃 id에서 의도적으로 실패합니다. + - `src/secrets/exec-secret-ref-id-parity.test.ts`는 레지스트리 메타데이터(`listSecretTargetRegistryEntries()`)에서 SecretRef 클래스별 샘플 대상 하나를 도출한 다음, 순회 세그먼트 exec id가 거부되는지 검증합니다. + - `src/secrets/target-registry-data.ts`에 새로운 `includeInPlan` SecretRef 대상 계열을 추가한다면, 해당 테스트의 `classifyTargetClass`를 업데이트하세요. 이 테스트는 분류되지 않은 대상 id에서 의도적으로 실패하므로 새 클래스가 조용히 건너뛰어질 수 없습니다. diff --git a/docs/ko/reference/memory-config.md b/docs/ko/reference/memory-config.md index ae88b16f5..4ae5d4b5f 100644 --- a/docs/ko/reference/memory-config.md +++ b/docs/ko/reference/memory-config.md @@ -1,47 +1,58 @@ --- read_when: - - 메모리 검색 provider 또는 임베딩 모델을 구성하고 싶을 때 - - QMD 백엔드를 설정하고 싶을 때 - - 하이브리드 검색, MMR 또는 시간 감쇠를 조정하고 싶을 때 - - 멀티모달 메모리 인덱싱을 활성화하고 싶을 때 -summary: 메모리 검색, 임베딩 provider, QMD, 하이브리드 검색, 멀티모달 인덱싱을 위한 모든 구성 항목 + - 메모리 검색 제공자나 임베딩 모델을 구성하려고 합니다 + - QMD 백엔드를 설정하려고 합니다 + - 하이브리드 검색, MMR 또는 시간 감쇠를 조정하려고 합니다 + - 멀티모달 메모리 인덱싱을 활성화하려고 합니다 +summary: 메모리 검색, 임베딩 제공자, QMD, 하이브리드 검색, 멀티모달 인덱싱에 대한 모든 구성 옵션 title: 메모리 구성 참조 x-i18n: - generated_at: "2026-04-06T03:12:41Z" + generated_at: "2026-04-10T05:59:52Z" model: gpt-5.4 provider: openai - source_hash: 0de0b85125443584f4e575cf673ca8d9bd12ecd849d73c537f4a17545afa93fd + source_hash: 5f9076bdfad95b87bd70625821bf401326f8eaeb53842b70823881419dbe43cb source_path: reference/memory-config.md workflow: 15 --- # 메모리 구성 참조 -이 페이지는 OpenClaw 메모리 검색의 모든 구성 항목을 나열합니다. -개념적 개요는 다음을 참고하세요. +이 페이지에는 OpenClaw 메모리 검색의 모든 구성 옵션이 나열되어 있습니다. 개념적 개요는 다음 문서를 참조하세요. -- [Memory Overview](/ko/concepts/memory) -- 메모리가 동작하는 방식 -- [Builtin Engine](/ko/concepts/memory-builtin) -- 기본 SQLite 백엔드 -- [QMD Engine](/ko/concepts/memory-qmd) -- 로컬 우선 사이드카 -- [Memory Search](/ko/concepts/memory-search) -- 검색 파이프라인 및 조정 +- [메모리 개요](/ko/concepts/memory) -- 메모리가 작동하는 방식 +- [내장 엔진](/ko/concepts/memory-builtin) -- 기본 SQLite 백엔드 +- [QMD 엔진](/ko/concepts/memory-qmd) -- 로컬 우선 사이드카 +- [메모리 검색](/ko/concepts/memory-search) -- 검색 파이프라인 및 튜닝 +- [액티브 메모리](/ko/concepts/active-memory) -- 대화형 세션에 메모리 하위 에이전트를 활성화하는 방법 -별도로 언급되지 않는 한 모든 메모리 검색 설정은 -`openclaw.json`의 `agents.defaults.memorySearch` 아래에 있습니다. +모든 메모리 검색 설정은 별도 언급이 없는 한 `openclaw.json`의 +`agents.defaults.memorySearch` 아래에 있습니다. + +**액티브 메모리** 기능 토글과 하위 에이전트 구성을 찾고 있다면, +이는 `memorySearch`가 아니라 `plugins.entries.active-memory` 아래에 있습니다. + +액티브 메모리는 2단계 게이트 모델을 사용합니다. + +1. 플러그인이 활성화되어 있어야 하며 현재 에이전트 ID를 대상으로 해야 합니다 +2. 요청이 적격한 대화형 영구 채팅 세션이어야 합니다 + +활성화 모델, 플러그인 소유 구성, 트랜스크립트 영속성, 안전한 롤아웃 패턴은 +[액티브 메모리](/ko/concepts/active-memory)를 참조하세요. --- -## Provider 선택 +## 제공자 선택 -| 키 | 타입 | 기본값 | 설명 | -| ---------- | --------- | -------------- | -------------------------------------------------------------------------------------- | +| 키 | 유형 | 기본값 | 설명 | +| ---------- | --------- | -------------- | ------------------------------------------------------------------------------------------ | | `provider` | `string` | 자동 감지 | 임베딩 어댑터 ID: `openai`, `gemini`, `voyage`, `mistral`, `bedrock`, `ollama`, `local` | -| `model` | `string` | provider 기본값 | 임베딩 모델 이름 | -| `fallback` | `string` | `"none"` | 기본 어댑터가 실패할 때 사용할 대체 어댑터 ID | -| `enabled` | `boolean` | `true` | 메모리 검색 활성화 또는 비활성화 | +| `model` | `string` | 제공자 기본값 | 임베딩 모델 이름 | +| `fallback` | `string` | `"none"` | 기본 제공자가 실패할 때 사용할 대체 어댑터 ID | +| `enabled` | `boolean` | `true` | 메모리 검색 활성화 또는 비활성화 | ### 자동 감지 순서 -`provider`가 설정되지 않은 경우 OpenClaw는 사용 가능한 첫 항목을 선택합니다. +`provider`가 설정되지 않으면 OpenClaw는 사용 가능한 첫 번째 항목을 선택합니다. 1. `local` -- `memorySearch.local.modelPath`가 구성되어 있고 파일이 존재하는 경우 2. `openai` -- OpenAI 키를 확인할 수 있는 경우 @@ -50,36 +61,36 @@ x-i18n: 5. `mistral` -- Mistral 키를 확인할 수 있는 경우 6. `bedrock` -- AWS SDK 자격 증명 체인이 확인되는 경우(인스턴스 역할, 액세스 키, 프로필, SSO, 웹 아이덴티티 또는 공유 구성) -`ollama`도 지원되지만 자동 감지는 하지 않습니다(명시적으로 설정하세요). +`ollama`도 지원되지만 자동 감지되지는 않습니다(명시적으로 설정해야 함). ### API 키 확인 원격 임베딩에는 API 키가 필요합니다. 대신 Bedrock은 AWS SDK 기본 자격 증명 체인(인스턴스 역할, SSO, 액세스 키)을 사용합니다. -| Provider | Env var | 구성 키 | -| -------- | ------------------------------ | --------------------------------- | -| OpenAI | `OPENAI_API_KEY` | `models.providers.openai.apiKey` | -| Gemini | `GEMINI_API_KEY` | `models.providers.google.apiKey` | -| Voyage | `VOYAGE_API_KEY` | `models.providers.voyage.apiKey` | -| Mistral | `MISTRAL_API_KEY` | `models.providers.mistral.apiKey` | -| Bedrock | AWS 자격 증명 체인 | API 키 필요 없음 | -| Ollama | `OLLAMA_API_KEY` (placeholder) | -- | +| 제공자 | 환경 변수 | 구성 키 | +| ------ | ----------------------------- | --------------------------------- | +| OpenAI | `OPENAI_API_KEY` | `models.providers.openai.apiKey` | +| Gemini | `GEMINI_API_KEY` | `models.providers.google.apiKey` | +| Voyage | `VOYAGE_API_KEY` | `models.providers.voyage.apiKey` | +| Mistral | `MISTRAL_API_KEY` | `models.providers.mistral.apiKey` | +| Bedrock | AWS 자격 증명 체인 | API 키 필요 없음 | +| Ollama | `OLLAMA_API_KEY` (자리표시자) | -- | -Codex OAuth는 채팅/completions만 지원하며 임베딩 +Codex OAuth는 채팅/완성 요청만 지원하며 임베딩 요청에는 사용할 수 없습니다. --- ## 원격 엔드포인트 구성 -사용자 지정 OpenAI 호환 엔드포인트를 사용하거나 provider 기본값을 재정의하려면 다음을 사용하세요. +사용자 지정 OpenAI 호환 엔드포인트를 사용하거나 제공자 기본값을 재정의하려면 다음을 사용하세요. -| 키 | 타입 | 설명 | -| ---------------- | -------- | ---------------------------------------------- | -| `remote.baseUrl` | `string` | 사용자 지정 API 기본 URL | -| `remote.apiKey` | `string` | API 키 재정의 | -| `remote.headers` | `object` | 추가 HTTP 헤더(provider 기본값과 병합됨) | +| 키 | 유형 | 설명 | +| ---------------- | -------- | -------------------------------------------- | +| `remote.baseUrl` | `string` | 사용자 지정 API 기본 URL | +| `remote.apiKey` | `string` | API 키 재정의 | +| `remote.headers` | `object` | 추가 HTTP 헤더(제공자 기본값과 병합됨) | ```json5 { @@ -102,22 +113,22 @@ Codex OAuth는 채팅/completions만 지원하며 임베딩 ## Gemini 전용 구성 -| 키 | 타입 | 기본값 | 설명 | +| 키 | 유형 | 기본값 | 설명 | | ---------------------- | -------- | ---------------------- | ------------------------------------------ | | `model` | `string` | `gemini-embedding-001` | `gemini-embedding-2-preview`도 지원 | | `outputDimensionality` | `number` | `3072` | Embedding 2의 경우: 768, 1536 또는 3072 | -모델 또는 `outputDimensionality`를 변경하면 자동으로 전체 재인덱싱이 수행됩니다. +모델 또는 `outputDimensionality`를 변경하면 자동으로 전체 재인덱싱이 트리거됩니다. --- ## Bedrock 임베딩 구성 -Bedrock은 AWS SDK 기본 자격 증명 체인을 사용하므로 API 키가 필요하지 않습니다. +Bedrock은 AWS SDK 기본 자격 증명 체인을 사용하므로 API 키가 필요 없습니다. OpenClaw가 Bedrock이 활성화된 인스턴스 역할이 있는 EC2에서 실행 중이라면, -provider와 모델만 설정하면 됩니다. +제공자와 모델만 설정하면 됩니다. ```json5 { @@ -132,47 +143,47 @@ provider와 모델만 설정하면 됩니다. } ``` -| 키 | 타입 | 기본값 | 설명 | -| ---------------------- | -------- | ------------------------------ | ------------------------------- | -| `model` | `string` | `amazon.titan-embed-text-v2:0` | 모든 Bedrock 임베딩 모델 ID | +| 키 | 유형 | 기본값 | 설명 | +| ---------------------- | -------- | ------------------------------ | ------------------------------ | +| `model` | `string` | `amazon.titan-embed-text-v2:0` | 모든 Bedrock 임베딩 모델 ID | | `outputDimensionality` | `number` | 모델 기본값 | Titan V2의 경우: 256, 512 또는 1024 | -### 지원 모델 +### 지원되는 모델 다음 모델이 지원됩니다(패밀리 감지 및 차원 기본값 포함). -| 모델 ID | Provider | 기본 차원 | 구성 가능한 차원 | -| ------------------------------------------ | ---------- | ------------ | ------------------- | -| `amazon.titan-embed-text-v2:0` | Amazon | 1024 | 256, 512, 1024 | -| `amazon.titan-embed-text-v1` | Amazon | 1536 | -- | -| `amazon.titan-embed-g1-text-02` | Amazon | 1536 | -- | -| `amazon.titan-embed-image-v1` | Amazon | 1024 | -- | -| `amazon.nova-2-multimodal-embeddings-v1:0` | Amazon | 1024 | 256, 384, 1024, 3072 | -| `cohere.embed-english-v3` | Cohere | 1024 | -- | -| `cohere.embed-multilingual-v3` | Cohere | 1024 | -- | -| `cohere.embed-v4:0` | Cohere | 1536 | 256-1536 | -| `twelvelabs.marengo-embed-3-0-v1:0` | TwelveLabs | 512 | -- | -| `twelvelabs.marengo-embed-2-7-v1:0` | TwelveLabs | 1024 | -- | +| 모델 ID | 제공자 | 기본 차원 | 구성 가능한 차원 | +| ------------------------------------------ | ---------- | --------- | -------------------- | +| `amazon.titan-embed-text-v2:0` | Amazon | 1024 | 256, 512, 1024 | +| `amazon.titan-embed-text-v1` | Amazon | 1536 | -- | +| `amazon.titan-embed-g1-text-02` | Amazon | 1536 | -- | +| `amazon.titan-embed-image-v1` | Amazon | 1024 | -- | +| `amazon.nova-2-multimodal-embeddings-v1:0` | Amazon | 1024 | 256, 384, 1024, 3072 | +| `cohere.embed-english-v3` | Cohere | 1024 | -- | +| `cohere.embed-multilingual-v3` | Cohere | 1024 | -- | +| `cohere.embed-v4:0` | Cohere | 1536 | 256-1536 | +| `twelvelabs.marengo-embed-3-0-v1:0` | TwelveLabs | 512 | -- | +| `twelvelabs.marengo-embed-2-7-v1:0` | TwelveLabs | 1024 | -- | 처리량 접미사가 붙은 변형(예: `amazon.titan-embed-text-v1:2:8k`)은 -기본 모델의 구성을 그대로 상속합니다. +기본 모델의 구성을 상속합니다. ### 인증 Bedrock 인증은 표준 AWS SDK 자격 증명 확인 순서를 사용합니다. -1. 환경 변수(`AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`) +1. 환경 변수 (`AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`) 2. SSO 토큰 캐시 3. 웹 아이덴티티 토큰 자격 증명 4. 공유 자격 증명 및 구성 파일 5. ECS 또는 EC2 메타데이터 자격 증명 -리전은 `AWS_REGION`, `AWS_DEFAULT_REGION`, `amazon-bedrock` -provider의 `baseUrl`에서 확인되며, 없으면 기본값은 `us-east-1`입니다. +리전은 `AWS_REGION`, `AWS_DEFAULT_REGION`, +`amazon-bedrock` 제공자의 `baseUrl`에서 확인되며, 없으면 기본값으로 `us-east-1`을 사용합니다. ### IAM 권한 -IAM 역할 또는 사용자에게 다음 권한이 필요합니다. +IAM 역할 또는 사용자에게는 다음 권한이 필요합니다. ```json { @@ -192,13 +203,13 @@ arn:aws:bedrock:*::foundation-model/amazon.titan-embed-text-v2:0 ## 로컬 임베딩 구성 -| 키 | 타입 | 기본값 | 설명 | -| --------------------- | -------- | ---------------------- | ------------------------------- | -| `local.modelPath` | `string` | 자동 다운로드 | GGUF 모델 파일 경로 | +| 키 | 유형 | 기본값 | 설명 | +| --------------------- | -------- | ---------------------- | ------------------------------ | +| `local.modelPath` | `string` | 자동 다운로드 | GGUF 모델 파일 경로 | | `local.modelCacheDir` | `string` | node-llama-cpp 기본값 | 다운로드된 모델의 캐시 디렉터리 | -기본 모델: `embeddinggemma-300m-qat-Q8_0.gguf`(~0.6 GB, 자동 다운로드). -네이티브 빌드가 필요합니다: `pnpm approve-builds` 후 `pnpm rebuild node-llama-cpp`. +기본 모델: `embeddinggemma-300m-qat-Q8_0.gguf` (~0.6 GB, 자동 다운로드). +네이티브 빌드가 필요합니다: `pnpm approve-builds` 다음 `pnpm rebuild node-llama-cpp`. --- @@ -206,28 +217,28 @@ arn:aws:bedrock:*::foundation-model/amazon.titan-embed-text-v2:0 모두 `memorySearch.query.hybrid` 아래에 있습니다. -| 키 | 타입 | 기본값 | 설명 | -| --------------------- | --------- | ------ | -------------------------------- | +| 키 | 유형 | 기본값 | 설명 | +| --------------------- | --------- | ------ | ---------------------------------- | | `enabled` | `boolean` | `true` | 하이브리드 BM25 + 벡터 검색 활성화 | -| `vectorWeight` | `number` | `0.7` | 벡터 점수 가중치(0-1) | -| `textWeight` | `number` | `0.3` | BM25 점수 가중치(0-1) | -| `candidateMultiplier` | `number` | `4` | 후보 풀 크기 배수 | +| `vectorWeight` | `number` | `0.7` | 벡터 점수 가중치(0-1) | +| `textWeight` | `number` | `0.3` | BM25 점수 가중치(0-1) | +| `candidateMultiplier` | `number` | `4` | 후보 풀 크기 배수 | ### MMR(다양성) -| 키 | 타입 | 기본값 | 설명 | -| ------------- | --------- | ------ | ----------------------------------- | -| `mmr.enabled` | `boolean` | `false` | MMR 재순위화 활성화 | -| `mmr.lambda` | `number` | `0.7` | 0 = 최대 다양성, 1 = 최대 관련성 | +| 키 | 유형 | 기본값 | 설명 | +| ------------- | --------- | ------ | ------------------------------------ | +| `mmr.enabled` | `boolean` | `false`| MMR 재순위화 활성화 | +| `mmr.lambda` | `number` | `0.7` | 0 = 최대 다양성, 1 = 최대 관련성 | ### 시간 감쇠(최신성) -| 키 | 타입 | 기본값 | 설명 | -| ---------------------------- | --------- | ------ | ------------------------------ | -| `temporalDecay.enabled` | `boolean` | `false` | 최신성 부스트 활성화 | -| `temporalDecay.halfLifeDays` | `number` | `30` | N일마다 점수가 절반으로 감소 | +| 키 | 유형 | 기본값 | 설명 | +| ---------------------------- | --------- | ------ | --------------------------- | +| `temporalDecay.enabled` | `boolean` | `false`| 최신성 부스트 활성화 | +| `temporalDecay.halfLifeDays` | `number` | `30` | N일마다 점수가 절반으로 감소 | -상시 유지 파일(`MEMORY.md`, `memory/` 내 날짜가 없는 파일)은 감쇠되지 않습니다. +에버그린 파일(`MEMORY.md`, `memory/`의 날짜가 없는 파일)은 감쇠되지 않습니다. ### 전체 예시 @@ -254,9 +265,9 @@ arn:aws:bedrock:*::foundation-model/amazon.titan-embed-text-v2:0 ## 추가 메모리 경로 -| 키 | 타입 | 설명 | -| ------------ | ---------- | --------------------------------- | -| `extraPaths` | `string[]` | 인덱싱할 추가 디렉터리 또는 파일 | +| 키 | 유형 | 설명 | +| ------------ | ---------- | ------------------------------------- | +| `extraPaths` | `string[]` | 인덱싱할 추가 디렉터리 또는 파일 | ```json5 { @@ -270,154 +281,152 @@ arn:aws:bedrock:*::foundation-model/amazon.titan-embed-text-v2:0 } ``` -경로는 절대 경로 또는 workspace 기준 상대 경로일 수 있습니다. 디렉터리는 +경로는 절대 경로이거나 워크스페이스 기준 상대 경로일 수 있습니다. 디렉터리는 `.md` 파일을 재귀적으로 스캔합니다. 심볼릭 링크 처리 방식은 활성 백엔드에 따라 다릅니다. -builtin 엔진은 심볼릭 링크를 무시하고, QMD는 기반 QMD -스캐너 동작을 따릅니다. +내장 엔진은 심볼릭 링크를 무시하고, QMD는 기반 QMD 스캐너의 동작을 따릅니다. -에이전트 범위의 교차 에이전트 transcript 검색에는 -`memory.qmd.paths` 대신 `agents.list[].memorySearch.qmd.extraCollections`를 -사용하세요. 이 추가 컬렉션은 동일한 `{ path, name, pattern? }` 형태를 따르지만, -에이전트별로 병합되며 경로가 현재 workspace 밖을 가리킬 때도 -명시적인 공유 이름을 유지할 수 있습니다. -같은 확인된 경로가 `memory.qmd.paths`와 -`memorySearch.qmd.extraCollections`에 모두 나타나면 QMD는 첫 번째 항목을 유지하고 -중복은 건너뜁니다. +에이전트 범위의 교차 에이전트 트랜스크립트 검색에는 +`memory.qmd.paths` 대신 `agents.list[].memorySearch.qmd.extraCollections`를 사용하세요. +이 추가 컬렉션은 동일한 `{ path, name, pattern? }` 형태를 따르지만, +에이전트별로 병합되며 경로가 현재 워크스페이스 밖을 가리킬 때 명시적인 공유 이름을 유지할 수 있습니다. +동일한 확인된 경로가 `memory.qmd.paths`와 +`memorySearch.qmd.extraCollections`에 모두 나타나면, QMD는 첫 번째 항목을 유지하고 +중복 항목은 건너뜁니다. --- ## 멀티모달 메모리(Gemini) -Gemini Embedding 2를 사용해 Markdown과 함께 이미지와 오디오도 인덱싱합니다. +Gemini Embedding 2를 사용해 Markdown과 함께 이미지와 오디오를 인덱싱합니다. -| 키 | 타입 | 기본값 | 설명 | -| ------------------------- | ---------- | ---------- | ---------------------------------------- | -| `multimodal.enabled` | `boolean` | `false` | 멀티모달 인덱싱 활성화 | -| `multimodal.modalities` | `string[]` | -- | `["image"]`, `["audio"]` 또는 `["all"]` | -| `multimodal.maxFileBytes` | `number` | `10000000` | 인덱싱할 최대 파일 크기 | +| 키 | 유형 | 기본값 | 설명 | +| ------------------------- | ---------- | ---------- | -------------------------------------- | +| `multimodal.enabled` | `boolean` | `false` | 멀티모달 인덱싱 활성화 | +| `multimodal.modalities` | `string[]` | -- | `["image"]`, `["audio"]` 또는 `["all"]` | +| `multimodal.maxFileBytes` | `number` | `10000000` | 인덱싱할 최대 파일 크기 | -`extraPaths`의 파일에만 적용됩니다. 기본 메모리 루트는 여전히 Markdown 전용입니다. -`gemini-embedding-2-preview`가 필요합니다. `fallback`은 반드시 `"none"`이어야 합니다. +`extraPaths`의 파일에만 적용됩니다. 기본 메모리 루트는 계속 Markdown 전용입니다. +`gemini-embedding-2-preview`가 필요합니다. `fallback`은 `"none"`이어야 합니다. 지원 형식: `.jpg`, `.jpeg`, `.png`, `.webp`, `.gif`, `.heic`, `.heif` -(이미지); `.mp3`, `.wav`, `.ogg`, `.opus`, `.m4a`, `.aac`, `.flac`(오디오). +(이미지); `.mp3`, `.wav`, `.ogg`, `.opus`, `.m4a`, `.aac`, `.flac` (오디오). --- ## 임베딩 캐시 -| 키 | 타입 | 기본값 | 설명 | -| ------------------ | --------- | ------ | ----------------------------------- | -| `cache.enabled` | `boolean` | `false` | SQLite에 청크 임베딩 캐시 | -| `cache.maxEntries` | `number` | `50000` | 최대 캐시 임베딩 수 | +| 키 | 유형 | 기본값 | 설명 | +| ------------------ | --------- | ------ | ------------------------------ | +| `cache.enabled` | `boolean` | `false`| SQLite에 청크 임베딩 캐시 | +| `cache.maxEntries` | `number` | `50000`| 캐시할 최대 임베딩 수 | -재인덱싱 또는 transcript 업데이트 중 변경되지 않은 텍스트를 다시 임베딩하는 일을 방지합니다. +재인덱싱 또는 트랜스크립트 업데이트 중 변경되지 않은 텍스트를 다시 임베딩하는 일을 방지합니다. --- ## 배치 인덱싱 -| 키 | 타입 | 기본값 | 설명 | -| ----------------------------- | --------- | ------ | ------------------------- | -| `remote.batch.enabled` | `boolean` | `false` | 배치 임베딩 API 활성화 | -| `remote.batch.concurrency` | `number` | `2` | 병렬 배치 작업 수 | -| `remote.batch.wait` | `boolean` | `true` | 배치 완료까지 대기 | -| `remote.batch.pollIntervalMs` | `number` | -- | 폴링 간격 | -| `remote.batch.timeoutMinutes` | `number` | -- | 배치 타임아웃 | +| 키 | 유형 | 기본값 | 설명 | +| ----------------------------- | --------- | ------ | ---------------------------- | +| `remote.batch.enabled` | `boolean` | `false`| 배치 임베딩 API 활성화 | +| `remote.batch.concurrency` | `number` | `2` | 병렬 배치 작업 수 | +| `remote.batch.wait` | `boolean` | `true` | 배치 완료까지 대기 | +| `remote.batch.pollIntervalMs` | `number` | -- | 폴링 간격 | +| `remote.batch.timeoutMinutes` | `number` | -- | 배치 타임아웃 | `openai`, `gemini`, `voyage`에서 사용할 수 있습니다. OpenAI 배치는 일반적으로 -대규모 백필에서 가장 빠르고 저렴합니다. +대규모 백필에서 가장 빠르고 비용도 가장 저렴합니다. --- ## 세션 메모리 검색(실험적) -세션 transcript를 인덱싱하고 `memory_search`를 통해 노출합니다. +세션 트랜스크립트를 인덱싱하고 `memory_search`를 통해 노출합니다. -| 키 | 타입 | 기본값 | 설명 | +| 키 | 유형 | 기본값 | 설명 | | ----------------------------- | ---------- | ------------ | ----------------------------------------- | | `experimental.sessionMemory` | `boolean` | `false` | 세션 인덱싱 활성화 | -| `sources` | `string[]` | `["memory"]` | transcript를 포함하려면 `"sessions"` 추가 | +| `sources` | `string[]` | `["memory"]` | 트랜스크립트를 포함하려면 `"sessions"` 추가 | | `sync.sessions.deltaBytes` | `number` | `100000` | 재인덱싱 바이트 임계값 | | `sync.sessions.deltaMessages` | `number` | `50` | 재인덱싱 메시지 임계값 | -세션 인덱싱은 opt-in이며 비동기적으로 실행됩니다. 결과는 약간 -오래되었을 수 있습니다. 세션 로그는 디스크에 있으므로 파일 시스템 접근을 -신뢰 경계로 취급하세요. +세션 인덱싱은 옵트인 방식이며 비동기적으로 실행됩니다. 결과는 약간 +오래되었을 수 있습니다. 세션 로그는 디스크에 저장되므로 파일 시스템 접근을 +신뢰 경계로 취급해야 합니다. --- ## SQLite 벡터 가속(sqlite-vec) -| 키 | 타입 | 기본값 | 설명 | -| ---------------------------- | --------- | ------- | ---------------------------------- | -| `store.vector.enabled` | `boolean` | `true` | 벡터 쿼리에 sqlite-vec 사용 | -| `store.vector.extensionPath` | `string` | bundled | sqlite-vec 경로 재정의 | +| 키 | 유형 | 기본값 | 설명 | +| ---------------------------- | --------- | ------ | --------------------------------- | +| `store.vector.enabled` | `boolean` | `true` | 벡터 쿼리에 sqlite-vec 사용 | +| `store.vector.extensionPath` | `string` | 번들됨 | sqlite-vec 경로 재정의 | -sqlite-vec을 사용할 수 없으면 OpenClaw는 자동으로 프로세스 내 cosine -similarity로 대체합니다. +sqlite-vec를 사용할 수 없으면 OpenClaw는 자동으로 프로세스 내 코사인 +유사도로 대체합니다. --- ## 인덱스 저장소 -| 키 | 타입 | 기본값 | 설명 | -| --------------------- | -------- | ------------------------------------ | ----------------------------------------- | -| `store.path` | `string` | `~/.openclaw/memory/{agentId}.sqlite` | 인덱스 위치(`{agentId}` 토큰 지원) | -| `store.fts.tokenizer` | `string` | `unicode61` | FTS5 tokenizer(`unicode61` 또는 `trigram`) | +| 키 | 유형 | 기본값 | 설명 | +| --------------------- | -------- | ------------------------------------- | ---------------------------------------- | +| `store.path` | `string` | `~/.openclaw/memory/{agentId}.sqlite` | 인덱스 위치(`{agentId}` 토큰 지원) | +| `store.fts.tokenizer` | `string` | `unicode61` | FTS5 토크나이저(`unicode61` 또는 `trigram`) | --- ## QMD 백엔드 구성 -활성화하려면 `memory.backend = "qmd"`를 설정하세요. 모든 QMD 설정은 +활성화하려면 `memory.backend = "qmd"`로 설정합니다. 모든 QMD 설정은 `memory.qmd` 아래에 있습니다. -| 키 | 타입 | 기본값 | 설명 | -| ------------------------ | --------- | -------- | ------------------------------------------------ | -| `command` | `string` | `qmd` | QMD 실행 파일 경로 | -| `searchMode` | `string` | `search` | 검색 명령: `search`, `vsearch`, `query` | -| `includeDefaultMemory` | `boolean` | `true` | `MEMORY.md` + `memory/**/*.md` 자동 인덱싱 | -| `paths[]` | `array` | -- | 추가 경로: `{ name, path, pattern? }` | -| `sessions.enabled` | `boolean` | `false` | 세션 transcript 인덱싱 | -| `sessions.retentionDays` | `number` | -- | transcript 보관 기간 | -| `sessions.exportDir` | `string` | -- | 내보내기 디렉터리 | +| 키 | 유형 | 기본값 | 설명 | +| ------------------------ | --------- | -------- | -------------------------------------------- | +| `command` | `string` | `qmd` | QMD 실행 파일 경로 | +| `searchMode` | `string` | `search` | 검색 명령: `search`, `vsearch`, `query` | +| `includeDefaultMemory` | `boolean` | `true` | `MEMORY.md` + `memory/**/*.md` 자동 인덱싱 | +| `paths[]` | `array` | -- | 추가 경로: `{ name, path, pattern? }` | +| `sessions.enabled` | `boolean` | `false` | 세션 트랜스크립트 인덱싱 | +| `sessions.retentionDays` | `number` | -- | 트랜스크립트 보존 기간 | +| `sessions.exportDir` | `string` | -- | 내보내기 디렉터리 | -OpenClaw는 현재 QMD 컬렉션 및 MCP 쿼리 형태를 우선 사용하지만, -필요할 경우 레거시 `--mask` 컬렉션 플래그와 -이전 MCP 도구 이름으로 대체해 구버전 QMD도 계속 작동하도록 유지합니다. +OpenClaw는 현재 QMD 컬렉션 및 MCP 쿼리 형태를 우선 사용하지만, 필요할 경우 +레거시 `--mask` 컬렉션 플래그와 이전 MCP 도구 이름으로 폴백하여 +오래된 QMD 릴리스도 계속 동작하도록 유지합니다. -QMD 모델 재정의는 OpenClaw 구성 쪽이 아니라 QMD 쪽에 유지됩니다. -QMD 모델을 전역적으로 재정의해야 한다면 gateway -런타임 환경에서 `QMD_EMBED_MODEL`, `QMD_RERANK_MODEL`, -`QMD_GENERATE_MODEL` 같은 환경 변수를 설정하세요. +QMD 모델 재정의는 OpenClaw 구성이 아니라 QMD 측에 유지됩니다. QMD의 모델을 +전역으로 재정의해야 한다면 게이트웨이 런타임 환경에서 +`QMD_EMBED_MODEL`, `QMD_RERANK_MODEL`, `QMD_GENERATE_MODEL` 같은 +환경 변수를 설정하세요. ### 업데이트 일정 -| 키 | 타입 | 기본값 | 설명 | +| 키 | 유형 | 기본값 | 설명 | | ------------------------- | --------- | ------- | ------------------------------------- | -| `update.interval` | `string` | `5m` | 새로고침 간격 | +| `update.interval` | `string` | `5m` | 새로 고침 간격 | | `update.debounceMs` | `number` | `15000` | 파일 변경 디바운스 | -| `update.onBoot` | `boolean` | `true` | 시작 시 새로고침 | -| `update.waitForBootSync` | `boolean` | `false` | 새로고침 완료까지 시작 차단 | -| `update.embedInterval` | `string` | -- | 별도 임베딩 주기 | +| `update.onBoot` | `boolean` | `true` | 시작 시 새로 고침 | +| `update.waitForBootSync` | `boolean` | `false` | 새로 고침이 완료될 때까지 시작 차단 | +| `update.embedInterval` | `string` | -- | 별도의 임베딩 주기 | | `update.commandTimeoutMs` | `number` | -- | QMD 명령 타임아웃 | | `update.updateTimeoutMs` | `number` | -- | QMD 업데이트 작업 타임아웃 | | `update.embedTimeoutMs` | `number` | -- | QMD 임베딩 작업 타임아웃 | ### 제한 -| 키 | 타입 | 기본값 | 설명 | +| 키 | 유형 | 기본값 | 설명 | | ------------------------- | -------- | ------ | ---------------------------- | | `limits.maxResults` | `number` | `6` | 최대 검색 결과 수 | -| `limits.maxSnippetChars` | `number` | -- | snippet 길이 제한 | +| `limits.maxSnippetChars` | `number` | -- | 스니펫 길이 제한 | | `limits.maxInjectedChars` | `number` | -- | 총 주입 문자 수 제한 | | `limits.timeoutMs` | `number` | `4000` | 검색 타임아웃 | ### 범위 -어떤 세션이 QMD 검색 결과를 받을 수 있는지 제어합니다. 스키마는 -[`session.sendPolicy`](/ko/gateway/configuration-reference#session)와 같습니다. +QMD 검색 결과를 받을 수 있는 세션을 제어합니다. +[`session.sendPolicy`](/ko/gateway/configuration-reference#session)와 동일한 스키마를 사용합니다. ```json5 { @@ -441,7 +450,7 @@ QMD 모델을 전역적으로 재정의해야 한다면 gateway | 값 | 동작 | | ---------------- | -------------------------------------------------- | -| `auto` (기본값) | snippet에 `Source: ` 바닥글 포함 | +| `auto` (기본값) | 스니펫에 `Source: ` 바닥글 포함 | | `on` | 항상 바닥글 포함 | | `off` | 바닥글 생략(경로는 여전히 내부적으로 에이전트에 전달됨) | @@ -473,17 +482,17 @@ QMD 모델을 전역적으로 재정의해야 한다면 gateway Dreaming은 `agents.defaults.memorySearch` 아래가 아니라 `plugins.entries.memory-core.config.dreaming` 아래에서 구성합니다. -Dreaming은 하나의 예약된 스윕으로 실행되며, 내부 light/deep/REM 단계는 -구현 세부 사항으로 사용됩니다. +Dreaming은 예약된 하나의 스윕으로 실행되며 내부적인 light/deep/REM 단계를 +구현 세부 사항으로 사용합니다. -개념적 동작과 슬래시 명령은 [Dreaming](/concepts/dreaming)을 참고하세요. +개념적 동작과 슬래시 명령은 [Dreaming](/ko/concepts/dreaming)을 참조하세요. ### 사용자 설정 -| 키 | 타입 | 기본값 | 설명 | -| ----------- | --------- | ----------- | ------------------------------------------- | -| `enabled` | `boolean` | `false` | Dreaming 전체 활성화 또는 비활성화 | -| `frequency` | `string` | `0 3 * * *` | 전체 dreaming 스윕에 대한 선택적 cron 주기 | +| 키 | 유형 | 기본값 | 설명 | +| ----------- | --------- | ----------- | ----------------------------------------- | +| `enabled` | `boolean` | `false` | Dreaming 전체를 활성화 또는 비활성화 | +| `frequency` | `string` | `0 3 * * *` | 전체 Dreaming 스윕의 선택적 cron 주기 | ### 예시 @@ -506,6 +515,6 @@ Dreaming은 하나의 예약된 스윕으로 실행되며, 내부 light/deep/REM 참고: -- Dreaming은 기계 상태를 `memory/.dreams/`에 기록합니다. -- Dreaming은 사람이 읽을 수 있는 서사 출력을 `DREAMS.md`(또는 기존 `dreams.md`)에 기록합니다. -- light/deep/REM 단계 정책과 임계값은 내부 동작이며 사용자 대상 config가 아닙니다. +- Dreaming은 머신 상태를 `memory/.dreams/`에 기록합니다. +- Dreaming은 사람이 읽을 수 있는 내러티브 출력을 `DREAMS.md`(또는 기존 `dreams.md`)에 기록합니다. +- light/deep/REM 단계 정책과 임계값은 사용자 대상 구성이 아니라 내부 동작입니다. diff --git a/docs/ko/tools/browser.md b/docs/ko/tools/browser.md index c9b4a7cf9..777f207c1 100644 --- a/docs/ko/tools/browser.md +++ b/docs/ko/tools/browser.md @@ -1,41 +1,40 @@ --- read_when: - - 에이전트가 제어하는 브라우저 자동화를 추가하는 경우 - - openclaw가 내 Chrome에 왜 간섭하는지 디버깅하는 경우 - - macOS 앱에서 브라우저 설정 + 수명 주기를 구현하는 경우 + - 에이전트 제어 브라우저 자동화 추가 + - openclaw가 사용자의 Chrome에 간섭하는 이유 디버깅하기 + - macOS 앱에서 브라우저 설정 및 수명 주기 구현하기 summary: 통합 브라우저 제어 서비스 + 작업 명령 -title: 브라우저(OpenClaw 관리형) +title: 브라우저(OpenClaw 관리) x-i18n: - generated_at: "2026-04-05T12:58:18Z" + generated_at: "2026-04-10T05:59:51Z" model: gpt-5.4 provider: openai - source_hash: a41162efd397ea918469e16aa67e554bcbb517b3112df1d3e7927539b6a0926a + source_hash: cd3424f62178bbf25923b8bc8e4d9f70e330f35428d01fe153574e5fa45d7604 source_path: tools/browser.md workflow: 15 --- -# 브라우저(openclaw 관리형) +# 브라우저(openclaw 관리) OpenClaw는 에이전트가 제어하는 **전용 Chrome/Brave/Edge/Chromium 프로필**을 실행할 수 있습니다. 이 프로필은 개인 브라우저와 분리되어 있으며 Gateway 내부의 작은 로컬 제어 서비스(루프백 전용)를 통해 관리됩니다. -초보자 관점에서 보면: +초보자용 설명: -- 이를 **에이전트 전용 별도 브라우저**라고 생각하면 됩니다. -- `openclaw` 프로필은 **개인 브라우저 프로필을 건드리지 않습니다**. -- 에이전트는 안전한 범위 안에서 **탭 열기, 페이지 읽기, 클릭, 입력**을 할 수 있습니다. -- 내장 `user` 프로필은 Chrome MCP를 통해 실제 로그인된 Chrome 세션에 연결합니다. +- 이것은 **별도의 에이전트 전용 브라우저**라고 생각하면 됩니다. +- `openclaw` 프로필은 사용자의 개인 브라우저 프로필에 **영향을 주지 않습니다**. +- 에이전트는 안전하게 분리된 환경에서 **탭을 열고, 페이지를 읽고, 클릭하고, 입력할 수 있습니다**. +- 내장된 `user` 프로필은 Chrome MCP를 통해 사용자가 실제로 로그인한 Chrome 세션에 연결됩니다. ## 제공 기능 -- **openclaw**라는 이름의 별도 브라우저 프로필(기본적으로 주황색 강조). +- **openclaw**라는 이름의 별도 브라우저 프로필(기본값은 주황색 강조). - 결정적인 탭 제어(목록/열기/포커스/닫기). - 에이전트 작업(클릭/입력/드래그/선택), 스냅샷, 스크린샷, PDF. -- 선택적 멀티 프로필 지원(`openclaw`, `work`, `remote`, ...). +- 선택적 다중 프로필 지원(`openclaw`, `work`, `remote`, ...). -이 브라우저는 일상적으로 사용하는 메인 브라우저가 **아닙니다**. 에이전트 -자동화와 검증을 위한 안전하고 분리된 표면입니다. +이 브라우저는 **일상적으로 사용하는 기본 브라우저가 아닙니다**. 에이전트 자동화와 검증을 위한 안전하고 격리된 표면입니다. ## 빠른 시작 @@ -46,16 +45,14 @@ openclaw browser --browser-profile openclaw open https://example.com openclaw browser --browser-profile openclaw snapshot ``` -“Browser disabled”가 나오면 config에서 활성화하고(아래 참조) Gateway를 -재시작하세요. +“Browser disabled”가 표시되면 config에서 이를 활성화하고(아래 참조) Gateway를 다시 시작하세요. -`openclaw browser` 명령 자체가 없거나, 에이전트가 브라우저 도구를 사용할 수 없다고 하면 -[브라우저 명령 또는 도구 누락](/tools/browser#missing-browser-command-or-tool)으로 이동하세요. +`openclaw browser` 자체가 완전히 없거나, 에이전트가 브라우저 도구를 사용할 수 없다고 말하면 [브라우저 명령 또는 도구 누락](/ko/tools/browser#missing-browser-command-or-tool)으로 이동하세요. -## plugin 제어 +## 플러그인 제어 -기본 `browser` 도구는 이제 기본적으로 활성화된 상태로 제공되는 번들 plugin입니다. -즉, OpenClaw의 나머지 plugin 시스템을 제거하지 않고도 이를 비활성화하거나 교체할 수 있습니다: +기본 `browser` 도구는 이제 기본적으로 활성화된 상태로 함께 제공되는 번들 플러그인입니다. +즉, 나머지 OpenClaw 플러그인 시스템을 제거하지 않고도 이 도구를 비활성화하거나 교체할 수 있습니다: ```json5 { @@ -69,31 +66,23 @@ openclaw browser --browser-profile openclaw snapshot } ``` -동일한 `browser` 도구 이름을 제공하는 다른 plugin을 설치하기 전에 이 번들 plugin을 비활성화하세요. 기본 브라우저 경험에는 다음 두 가지가 모두 필요합니다: +동일한 `browser` 도구 이름을 제공하는 다른 플러그인을 설치하기 전에 번들 플러그인을 비활성화하세요. 기본 브라우저 경험에는 다음 두 가지가 모두 필요합니다: - `plugins.entries.browser.enabled`가 비활성화되어 있지 않을 것 - `browser.enabled=true` -plugin만 끄면 번들 브라우저 CLI(`openclaw browser`), -gateway 메서드(`browser.request`), 에이전트 도구, 기본 브라우저 제어 -서비스가 모두 함께 사라집니다. `browser.*` config는 그대로 유지되므로 -대체 plugin이 이를 재사용할 수 있습니다. +플러그인만 끄면 번들 브라우저 CLI(`openclaw browser`), gateway 메서드(`browser.request`), 에이전트 도구, 기본 브라우저 제어 서비스가 모두 함께 사라집니다. `browser.*` config는 그대로 유지되므로 교체 플러그인이 이를 재사용할 수 있습니다. -번들 브라우저 plugin은 이제 브라우저 런타임 구현도 소유합니다. -코어에는 공유 Plugin SDK 헬퍼와 이전 내부 import 경로용 호환 re-export만 남아 있습니다. -실제로는 브라우저 plugin 패키지를 제거하거나 교체하면 -코어 소유의 두 번째 런타임이 남는 대신 브라우저 기능 세트 자체가 제거됩니다. +번들 브라우저 플러그인은 이제 브라우저 런타임 구현도 담당합니다. +코어에는 공유 Plugin SDK 도우미와 이전 내부 import 경로용 호환성 re-export만 남아 있습니다. 실제로는 브라우저 플러그인 패키지를 제거하거나 교체하면 코어 소유 런타임이 따로 남는 대신 브라우저 기능 세트가 제거됩니다. -브라우저 config 변경은 번들 plugin이 새 설정으로 브라우저 서비스를 -다시 등록할 수 있도록 여전히 Gateway 재시작이 필요합니다. +브라우저 config 변경 사항을 새 설정으로 번들 플러그인이 브라우저 서비스를 다시 등록할 수 있도록 하려면 여전히 Gateway 재시작이 필요합니다. ## 브라우저 명령 또는 도구 누락 -업그레이드 후 `openclaw browser`가 갑자기 알 수 없는 명령이 되거나, -에이전트가 브라우저 도구가 없다고 보고한다면 가장 흔한 원인은 -제한적인 `plugins.allow` 목록에 `browser`가 포함되어 있지 않은 경우입니다. +업그레이드 후 `openclaw browser`가 갑자기 알 수 없는 명령이 되거나, 에이전트가 브라우저 도구가 없다고 보고하는 경우 가장 흔한 원인은 `browser`가 포함되지 않은 제한적인 `plugins.allow` 목록입니다. -잘못된 config 예시: +문제가 있는 config 예시: ```json5 { @@ -103,7 +92,7 @@ gateway 메서드(`browser.request`), 에이전트 도구, 기본 브라우저 } ``` -plugin allowlist에 `browser`를 추가해 해결하세요: +플러그인 허용 목록에 `browser`를 추가해서 해결할 수 있습니다: ```json5 { @@ -115,28 +104,27 @@ plugin allowlist에 `browser`를 추가해 해결하세요: 중요한 참고 사항: -- `plugins.allow`가 설정된 경우 `browser.enabled=true`만으로는 충분하지 않습니다. -- `plugins.allow`가 설정된 경우 `plugins.entries.browser.enabled=true`만으로도 충분하지 않습니다. -- `tools.alsoAllow: ["browser"]`는 번들 브라우저 plugin을 로드하지 않습니다. plugin이 이미 로드된 후에만 도구 정책을 조정합니다. -- 제한적인 plugin allowlist가 필요 없다면 `plugins.allow`를 제거하는 것만으로도 기본 번들 브라우저 동작이 복원됩니다. +- `plugins.allow`가 설정되어 있으면 `browser.enabled=true`만으로는 충분하지 않습니다. +- `plugins.allow`가 설정되어 있으면 `plugins.entries.browser.enabled=true`만으로도 충분하지 않습니다. +- `tools.alsoAllow: ["browser"]`는 번들 브라우저 플러그인을 로드하지 **않습니다**. 이는 플러그인이 이미 로드된 뒤 도구 정책만 조정합니다. +- 제한적인 플러그인 허용 목록이 필요하지 않다면 `plugins.allow`를 제거해도 기본 번들 브라우저 동작이 복원됩니다. 일반적인 증상: - `openclaw browser`가 알 수 없는 명령입니다. - `browser.request`가 없습니다. -- 에이전트가 브라우저 도구를 사용할 수 없거나 없다고 보고합니다. +- 에이전트가 브라우저 도구를 사용할 수 없거나 누락되었다고 보고합니다. ## 프로필: `openclaw` vs `user` - `openclaw`: 관리형, 격리된 브라우저(확장 프로그램 필요 없음). -- `user`: 실제 **로그인된 Chrome** - 세션에 연결되는 내장 Chrome MCP attach 프로필. +- `user`: 사용자의 **실제 로그인된 Chrome** 세션에 연결하는 내장 Chrome MCP 연결 프로필. -에이전트 브라우저 도구 호출 시: +에이전트 브라우저 도구 호출의 경우: -- 기본값: 격리된 `openclaw` 브라우저를 사용합니다. -- 기존 로그인 세션이 중요하고 사용자가 컴퓨터 앞에서 attach 프롬프트를 클릭/승인할 수 있다면 `profile="user"`를 선호하세요. -- 특정 브라우저 모드가 필요할 때는 `profile`이 명시적 재정의입니다. +- 기본값: 격리된 `openclaw` 브라우저 사용. +- 기존 로그인 세션이 중요하고 사용자가 컴퓨터 앞에서 연결 프롬프트를 클릭/승인할 수 있을 때는 `profile="user"`를 우선 사용. +- `profile`은 특정 브라우저 모드를 원할 때 사용하는 명시적 재정의입니다. 기본적으로 관리형 모드를 사용하려면 `browser.defaultProfile: "openclaw"`를 설정하세요. @@ -183,32 +171,33 @@ plugin allowlist에 `browser`를 추가해 해결하세요: } ``` -참고: +참고 사항: - 브라우저 제어 서비스는 `gateway.port`에서 파생된 포트의 루프백에 바인딩됩니다 (기본값: `18791`, 즉 gateway + 2). - Gateway 포트(`gateway.port` 또는 `OPENCLAW_GATEWAY_PORT`)를 재정의하면 - 파생 브라우저 포트도 같은 “패밀리” 안에 있도록 함께 이동합니다. -- `cdpUrl`이 설정되지 않으면 기본적으로 관리형 로컬 CDP 포트를 사용합니다. + 파생된 브라우저 포트도 같은 “패밀리”를 유지하도록 함께 이동합니다. +- `cdpUrl`이 설정되지 않은 경우 관리형 로컬 CDP 포트가 기본값으로 사용됩니다. - `remoteCdpTimeoutMs`는 원격(비루프백) CDP 도달 가능성 검사에 적용됩니다. - `remoteCdpHandshakeTimeoutMs`는 원격 CDP WebSocket 도달 가능성 검사에 적용됩니다. -- 브라우저 탐색/탭 열기는 탐색 전에 SSRF 보호가 적용되며, 탐색 후 최종 `http(s)` URL에 대해서도 최선의 노력으로 다시 검사합니다. -- 엄격한 SSRF 모드에서는 원격 CDP 엔드포인트 탐색/프로브(`cdpUrl`, `/json/version` 조회 포함)도 검사됩니다. -- `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork`의 기본값은 `true`(신뢰 네트워크 모델)입니다. 엄격한 공용 전용 브라우징이 필요하면 `false`로 설정하세요. +- 브라우저 탐색/탭 열기는 탐색 전에 SSRF 보호가 적용되며, 탐색 후 최종 `http(s)` URL에 대해 가능하면 다시 확인합니다. +- 엄격한 SSRF 모드에서는 원격 CDP 엔드포인트 검색/프로브(`cdpUrl`, `/json/version` 조회 포함)도 검사됩니다. +- `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork`의 기본값은 `true`입니다(신뢰 네트워크 모델). 엄격한 공개 네트워크 전용 탐색을 원하면 `false`로 설정하세요. - `browser.ssrfPolicy.allowPrivateNetwork`는 호환성을 위한 레거시 별칭으로 계속 지원됩니다. -- `attachOnly: true`는 “로컬 브라우저를 절대 실행하지 않고, 이미 실행 중일 때만 연결한다”는 의미입니다. -- `color` 및 프로필별 `color`는 브라우저 UI에 색을 입혀 어느 프로필이 활성 상태인지 볼 수 있게 합니다. -- 기본 프로필은 `openclaw`입니다(OpenClaw 관리형 독립 브라우저). 로그인된 사용자 브라우저를 사용하려면 `defaultProfile: "user"`를 사용하세요. -- 자동 감지 순서: 시스템 기본 브라우저가 Chromium 기반이면 그것을 사용하고, 아니면 Chrome → Brave → Edge → Chromium → Chrome Canary 순입니다. -- 로컬 `openclaw` 프로필은 `cdpPort`/`cdpUrl`이 자동 할당되므로, 원격 CDP가 아닌 경우에는 이를 설정하지 마세요. -- `driver: "existing-session"`은 raw CDP 대신 Chrome DevTools MCP를 사용합니다. 이 드라이버에는 `cdpUrl`을 설정하지 마세요. -- 기존 세션 프로필이 Brave 또는 Edge 같은 비기본 Chromium 사용자 프로필에 연결되어야 한다면 `browser.profiles..userDataDir`을 설정하세요. +- `attachOnly: true`는 “로컬 브라우저를 절대 실행하지 않고, 이미 실행 중일 때만 연결한다”는 뜻입니다. +- `color` 및 프로필별 `color`는 브라우저 UI에 색을 입혀 어떤 프로필이 활성화되어 있는지 확인할 수 있게 합니다. +- 기본 프로필은 `openclaw`입니다(OpenClaw 관리 독립형 브라우저). 로그인된 사용자 브라우저를 사용하려면 `defaultProfile: "user"`를 사용하세요. +- 자동 감지 순서: 시스템 기본 브라우저가 Chromium 기반이면 그것을 사용하고, 그렇지 않으면 Chrome → Brave → Edge → Chromium → Chrome Canary 순입니다. +- 로컬 `openclaw` 프로필은 `cdpPort`/`cdpUrl`을 자동 할당합니다 — 원격 CDP에만 이를 설정하세요. +- `driver: "existing-session"`은 raw CDP 대신 Chrome DevTools MCP를 사용합니다. 이 + 드라이버에는 `cdpUrl`을 설정하지 마세요. +- 기존 세션 프로필이 Brave 또는 Edge 같은 기본값이 아닌 Chromium 사용자 프로필에 + 연결해야 한다면 `browser.profiles..userDataDir`를 설정하세요. ## Brave(또는 다른 Chromium 기반 브라우저) 사용 -**시스템 기본** 브라우저가 Chromium 기반(Chrome/Brave/Edge 등)이면 -OpenClaw가 자동으로 이를 사용합니다. 자동 감지를 재정의하려면 -`browser.executablePath`를 설정하세요: +사용자의 **시스템 기본** 브라우저가 Chromium 기반(Chrome/Brave/Edge 등)이면 +OpenClaw가 자동으로 이를 사용합니다. 자동 감지를 재정의하려면 `browser.executablePath`를 설정하세요: CLI 예시: @@ -242,47 +231,45 @@ openclaw config set browser.executablePath "/usr/bin/google-chrome" ## 로컬 제어 vs 원격 제어 - **로컬 제어(기본값):** Gateway가 루프백 제어 서비스를 시작하고 로컬 브라우저를 실행할 수 있습니다. -- **원격 제어(node host):** 브라우저가 있는 머신에서 node host를 실행하면 Gateway가 브라우저 작업을 그 노드로 프록시합니다. +- **원격 제어(node host):** 브라우저가 있는 머신에서 node host를 실행하면 Gateway가 브라우저 작업을 해당 호스트로 프록시합니다. - **원격 CDP:** 원격 Chromium 기반 브라우저에 연결하려면 `browser.profiles..cdpUrl`(또는 `browser.cdpUrl`)을 설정하세요. 이 경우 OpenClaw는 로컬 브라우저를 실행하지 않습니다. 중지 동작은 프로필 모드에 따라 다릅니다: -- 로컬 관리형 프로필: `openclaw browser stop`은 - OpenClaw가 시작한 브라우저 프로세스를 중지합니다 -- attach-only 및 원격 CDP 프로필: `openclaw browser stop`은 - OpenClaw가 브라우저 프로세스를 시작하지 않았더라도 활성 제어 세션을 닫고 - Playwright/CDP 에뮬레이션 재정의(뷰포트, 색 구성표, 로캘, 시간대, 오프라인 모드 등)를 해제합니다 +- 로컬 관리형 프로필: `openclaw browser stop`은 OpenClaw가 실행한 브라우저 프로세스를 중지합니다 +- attach-only 및 원격 CDP 프로필: `openclaw browser stop`은 활성 제어 세션을 닫고 Playwright/CDP 에뮬레이션 재정의(뷰포트, + 색 구성표, 로캘, 시간대, 오프라인 모드 및 유사한 상태)를 해제하지만, + OpenClaw가 브라우저 프로세스를 실행한 것은 아닙니다 원격 CDP URL에는 인증 정보를 포함할 수 있습니다: - 쿼리 토큰(예: `https://provider.example?token=`) -- HTTP Basic auth(예: `https://user:pass@provider.example`) +- HTTP Basic 인증(예: `https://user:pass@provider.example`) -OpenClaw는 `/json/*` 엔드포인트 호출 시와 -CDP WebSocket 연결 시 인증 정보를 유지합니다. 토큰은 config 파일에 커밋하는 대신 -환경 변수 또는 시크릿 매니저를 사용하는 것이 좋습니다. +OpenClaw는 `/json/*` 엔드포인트 호출 시와 CDP WebSocket 연결 시 +인증 정보를 유지합니다. 토큰은 config 파일에 커밋하는 대신 환경 변수나 시크릿 관리자 사용을 권장합니다. -## Node 브라우저 프록시(기본 제로 구성) +## 노드 브라우저 프록시(기본 무설정) -브라우저가 있는 머신에서 **node host**를 실행 중이라면, OpenClaw는 -추가 브라우저 config 없이도 브라우저 도구 호출을 해당 노드로 -자동 라우팅할 수 있습니다. 이는 원격 게이트웨이의 기본 경로입니다. +브라우저가 있는 머신에서 **node host**를 실행하면 OpenClaw는 +추가 브라우저 config 없이도 브라우저 도구 호출을 해당 노드로 자동 라우팅할 수 있습니다. +이것이 원격 gateway의 기본 경로입니다. -참고: +참고 사항: -- node host는 로컬 브라우저 제어 서버를 **프록시 명령**으로 노출합니다. +- node host는 **프록시 명령**을 통해 자신의 로컬 브라우저 제어 서버를 노출합니다. - 프로필은 노드 자체의 `browser.profiles` config(로컬과 동일)에서 가져옵니다. -- `nodeHost.browserProxy.allowProfiles`는 선택 사항입니다. 비워 두면 레거시/기본 동작이 적용되어, 프로필 생성/삭제 라우트를 포함해 구성된 모든 프로필이 프록시를 통해 접근 가능합니다. -- `nodeHost.browserProxy.allowProfiles`를 설정하면, OpenClaw는 이를 최소 권한 경계로 취급합니다. allowlist에 있는 프로필만 대상으로 지정할 수 있으며, 영구 프로필 생성/삭제 라우트는 프록시 표면에서 차단됩니다. +- `nodeHost.browserProxy.allowProfiles`는 선택 사항입니다. 비워 두면 레거시/기본 동작이 적용되어, 프로필 생성/삭제 경로를 포함해 구성된 모든 프로필에 프록시를 통해 접근할 수 있습니다. +- `nodeHost.browserProxy.allowProfiles`를 설정하면 OpenClaw는 이를 최소 권한 경계로 취급합니다. 허용 목록에 있는 프로필만 대상으로 지정할 수 있고, 영구 프로필 생성/삭제 경로는 프록시 표면에서 차단됩니다. - 원하지 않으면 비활성화하세요: - 노드에서: `nodeHost.browserProxy.enabled=false` - - 게이트웨이에서: `gateway.nodes.browser.mode="off"` + - gateway에서: `gateway.nodes.browser.mode="off"` -## Browserless(호스팅 원격 CDP) +## Browserless(호스팅된 원격 CDP) [Browserless](https://browserless.io)는 HTTPS와 WebSocket을 통해 CDP 연결 URL을 노출하는 호스팅 Chromium 서비스입니다. OpenClaw는 두 형식을 모두 사용할 수 있지만, -원격 브라우저 프로필에는 Browserless 연결 문서에 있는 직접 WebSocket URL을 사용하는 것이 가장 간단합니다. +원격 브라우저 프로필에서는 Browserless의 연결 문서에 있는 직접 WebSocket URL이 가장 간단한 옵션입니다. 예시: @@ -303,29 +290,31 @@ CDP 연결 URL을 노출하는 호스팅 Chromium 서비스입니다. OpenClaw } ``` -참고: +참고 사항: - ``를 실제 Browserless 토큰으로 바꾸세요. - Browserless 계정에 맞는 리전 엔드포인트를 선택하세요(자세한 내용은 해당 문서 참조). -- Browserless가 HTTPS 기본 URL을 제공하는 경우, 직접 CDP 연결을 위해 이를 `wss://`로 변환하거나 HTTPS URL을 그대로 두고 OpenClaw가 `/json/version`을 탐색하도록 할 수 있습니다. +- Browserless가 HTTPS 기본 URL을 제공하는 경우 이를 직접 CDP 연결용 `wss://`로 + 변환해도 되고, HTTPS URL을 그대로 유지한 채 OpenClaw가 + `/json/version`을 검색하도록 해도 됩니다. -## 직접 WebSocket CDP provider +## 직접 WebSocket CDP 제공자 -일부 호스팅 브라우저 서비스는 표준 HTTP 기반 CDP 탐색(`/json/version`)이 아니라 -**직접 WebSocket** 엔드포인트를 제공합니다. OpenClaw는 둘 다 지원합니다: +일부 호스팅 브라우저 서비스는 표준 HTTP 기반 CDP 검색(`/json/version`) 대신 +**직접 WebSocket** 엔드포인트를 제공합니다. OpenClaw는 두 방식 모두 지원합니다: -- **HTTP(S) 엔드포인트** — OpenClaw가 `/json/version`을 호출해 - WebSocket 디버거 URL을 탐색한 후 연결합니다. -- **WebSocket 엔드포인트** (`ws://` / `wss://`) — OpenClaw가 직접 연결하며 - `/json/version`은 건너뜁니다. 이는 +- **HTTP(S) 엔드포인트** — OpenClaw는 `/json/version`을 호출해 + WebSocket 디버거 URL을 찾은 다음 연결합니다. +- **WebSocket 엔드포인트** (`ws://` / `wss://`) — OpenClaw는 `/json/version`을 건너뛰고 + 직접 연결합니다. 이는 [Browserless](https://browserless.io), - [Browserbase](https://www.browserbase.com) 또는 WebSocket URL을 직접 제공하는 - 모든 provider에 사용하세요. + [Browserbase](https://www.browserbase.com) 또는 WebSocket URL을 제공하는 + 모든 서비스에 사용합니다. ### Browserbase -[Browserbase](https://www.browserbase.com)는 내장 CAPTCHA 해결, stealth 모드, -residential proxy를 제공하는 헤드리스 브라우저 실행용 클라우드 플랫폼입니다. +[Browserbase](https://www.browserbase.com)는 내장 CAPTCHA 해결, 스텔스 모드, 주거용 +프록시를 갖춘 헤드리스 브라우저 실행용 클라우드 플랫폼입니다. ```json5 { @@ -344,61 +333,62 @@ residential proxy를 제공하는 헤드리스 브라우저 실행용 클라우 } ``` -참고: +참고 사항: -- [회원 가입](https://www.browserbase.com/sign-up) 후 [Overview dashboard](https://www.browserbase.com/overview)에서 **API Key**를 복사하세요. +- [가입](https://www.browserbase.com/sign-up)한 뒤 [Overview dashboard](https://www.browserbase.com/overview)에서 + **API Key**를 복사하세요. - ``를 실제 Browserbase API 키로 바꾸세요. - Browserbase는 WebSocket 연결 시 브라우저 세션을 자동 생성하므로 - 수동 세션 생성 단계가 필요하지 않습니다. -- 무료 등급은 동시 세션 1개와 월 1 브라우저 시간을 허용합니다. - 유료 요금제 한도는 [pricing](https://www.browserbase.com/pricing)을 참조하세요. + 수동 세션 생성 단계가 필요 없습니다. +- 무료 플랜은 동시 세션 1개와 월 1 브라우저 시간을 제공합니다. + 유료 플랜 제한은 [pricing](https://www.browserbase.com/pricing)을 참조하세요. - 전체 API 참조, SDK 가이드, 통합 예시는 [Browserbase docs](https://docs.browserbase.com)를 참조하세요. ## 보안 핵심 개념: -- 브라우저 제어는 루프백 전용이며, 액세스는 Gateway 인증 또는 node pairing을 통해 흐릅니다. -- 독립형 루프백 브라우저 HTTP API는 **공유 비밀 인증만** 사용합니다: - gateway 토큰 bearer auth, `x-openclaw-password`, 또는 - 구성된 gateway 비밀번호를 사용한 HTTP Basic auth. -- Tailscale Serve identity 헤더와 `gateway.auth.mode: "trusted-proxy"`는 - 이 독립형 루프백 브라우저 API를 인증하지 않습니다. -- 브라우저 제어가 활성화되어 있고 공유 비밀 인증이 구성되지 않은 경우, OpenClaw는 - 시작 시 `gateway.auth.token`을 자동 생성하고 config에 저장합니다. +- 브라우저 제어는 루프백 전용이며, 액세스는 Gateway 인증 또는 노드 페어링을 통해 이루어집니다. +- 독립형 루프백 브라우저 HTTP API는 **공유 시크릿 인증만** 사용합니다: + gateway 토큰 bearer 인증, `x-openclaw-password`, 또는 + 설정된 gateway 비밀번호를 사용하는 HTTP Basic 인증입니다. +- Tailscale Serve ID 헤더와 `gateway.auth.mode: "trusted-proxy"`는 + 이 독립형 루프백 브라우저 API를 **인증하지 않습니다**. +- 브라우저 제어가 활성화되어 있고 공유 시크릿 인증이 구성되지 않은 경우 OpenClaw는 + 시작 시 `gateway.auth.token`을 자동 생성하고 이를 config에 저장합니다. - `gateway.auth.mode`가 이미 - `password`, `none`, 또는 `trusted-proxy`인 경우에는 해당 토큰을 자동 생성하지 않습니다. -- Gateway와 모든 node host는 비공개 네트워크(Tailscale)에 유지하고, 공용 노출은 피하세요. -- 원격 CDP URL/토큰은 시크릿으로 취급하고, env var 또는 시크릿 매니저를 선호하세요. + `password`, `none`, 또는 `trusted-proxy`인 경우 OpenClaw는 해당 토큰을 자동 생성하지 않습니다. +- Gateway와 모든 node host는 비공개 네트워크(Tailscale)에 두고 공개적으로 노출하지 마세요. +- 원격 CDP URL/토큰은 시크릿으로 취급하고 환경 변수나 시크릿 관리자를 사용하는 것이 좋습니다. 원격 CDP 팁: -- 가능하면 암호화된 엔드포인트(HTTPS 또는 WSS)와 짧은 수명의 토큰을 선호하세요. -- 오래 유지되는 토큰을 config 파일에 직접 포함하지 마세요. +- 가능하면 암호화된 엔드포인트(HTTPS 또는 WSS)와 짧은 수명의 토큰을 사용하세요. +- 장기 토큰을 config 파일에 직접 포함하지 마세요. ## 프로필(멀티 브라우저) -OpenClaw는 여러 개의 이름 있는 프로필(라우팅 config)을 지원합니다. 프로필 유형: +OpenClaw는 여러 개의 이름 있는 프로필(라우팅 config)을 지원합니다. 프로필은 다음과 같을 수 있습니다: -- **openclaw-managed**: 자체 사용자 데이터 디렉터리와 CDP 포트를 가진 전용 Chromium 기반 브라우저 인스턴스 -- **remote**: 명시적 CDP URL(다른 곳에서 실행 중인 Chromium 기반 브라우저) -- **existing session**: Chrome DevTools MCP 자동 연결을 통한 기존 Chrome 프로필 +- **openclaw 관리형**: 자체 사용자 데이터 디렉터리와 CDP 포트를 가진 전용 Chromium 기반 브라우저 인스턴스 +- **원격**: 명시적인 CDP URL(다른 위치에서 실행 중인 Chromium 기반 브라우저) +- **기존 세션**: Chrome DevTools MCP 자동 연결을 통한 기존 Chrome 프로필 기본값: - `openclaw` 프로필은 없으면 자동 생성됩니다. -- `user` 프로필은 Chrome MCP existing-session attach용 내장 프로필입니다. -- existing-session 프로필은 `user` 외에는 opt-in이며, `--driver existing-session`으로 생성하세요. +- `user` 프로필은 Chrome MCP 기존 세션 연결용으로 내장되어 있습니다. +- 기존 세션 프로필은 `user` 외에는 opt-in입니다. `--driver existing-session`으로 생성하세요. - 로컬 CDP 포트는 기본적으로 **18800–18899** 범위에서 할당됩니다. - 프로필을 삭제하면 해당 로컬 데이터 디렉터리는 휴지통으로 이동합니다. -모든 제어 엔드포인트는 `?profile=`을 허용하며, CLI는 `--browser-profile`을 사용합니다. +모든 제어 엔드포인트는 `?profile=`을 받으며, CLI는 `--browser-profile`을 사용합니다. -## Chrome DevTools MCP를 통한 existing-session +## Chrome DevTools MCP를 통한 기존 세션 -OpenClaw는 공식 Chrome DevTools MCP 서버를 통해 실행 중인 Chromium 기반 브라우저 프로필에 연결할 수도 있습니다. 이를 통해 해당 브라우저 프로필에 이미 열려 있는 탭과 로그인 상태를 재사용할 수 있습니다. +OpenClaw는 공식 Chrome DevTools MCP 서버를 통해 실행 중인 Chromium 기반 브라우저 프로필에 연결할 수도 있습니다. 이렇게 하면 해당 브라우저 프로필에서 이미 열려 있는 탭과 로그인 상태를 재사용합니다. -공식 배경 자료 및 설정 참고 링크: +공식 배경 및 설정 참고 자료: - [Chrome for Developers: Use Chrome DevTools MCP with your browser session](https://developer.chrome.com/blog/chrome-devtools-mcp-debug-your-browser-session) - [Chrome DevTools MCP README](https://github.com/ChromeDevTools/chrome-devtools-mcp) @@ -407,15 +397,15 @@ OpenClaw는 공식 Chrome DevTools MCP 서버를 통해 실행 중인 Chromium - `user` -선택 사항: 다른 이름, 색상 또는 브라우저 데이터 디렉터리가 필요하면 -직접 custom existing-session 프로필을 만들 수 있습니다. +선택 사항: 다른 이름, 색상 또는 브라우저 데이터 디렉터리를 원하면 +자체 사용자 지정 기존 세션 프로필을 만들 수 있습니다. 기본 동작: -- 내장 `user` 프로필은 Chrome MCP 자동 연결을 사용하며, +- 내장된 `user` 프로필은 Chrome MCP 자동 연결을 사용하며, 기본 로컬 Google Chrome 프로필을 대상으로 합니다. -Brave, Edge, Chromium 또는 비기본 Chrome 프로필에는 `userDataDir`을 사용하세요: +Brave, Edge, Chromium 또는 기본이 아닌 Chrome 프로필에는 `userDataDir`을 사용하세요: ```json5 { @@ -436,7 +426,7 @@ Brave, Edge, Chromium 또는 비기본 Chrome 프로필에는 `userDataDir`을 1. 원격 디버깅용 inspect 페이지를 엽니다. 2. 원격 디버깅을 활성화합니다. -3. 브라우저를 계속 실행한 채 OpenClaw가 연결할 때 나타나는 연결 승인 프롬프트를 수락합니다. +3. 브라우저를 계속 실행한 상태로 두고 OpenClaw가 연결할 때 연결 프롬프트를 승인합니다. 일반적인 inspect 페이지: @@ -444,7 +434,7 @@ Brave, Edge, Chromium 또는 비기본 Chrome 프로필에는 `userDataDir`을 - Brave: `brave://inspect/#remote-debugging` - Edge: `edge://inspect/#remote-debugging` -실시간 attach 스모크 테스트: +라이브 연결 스모크 테스트: ```bash openclaw browser --browser-profile user start @@ -453,57 +443,63 @@ openclaw browser --browser-profile user tabs openclaw browser --browser-profile user snapshot --format ai ``` -성공 시 확인할 수 있는 내용: +성공 시 확인할 수 있는 모습: - `status`에 `driver: existing-session`이 표시됨 - `status`에 `transport: chrome-mcp`가 표시됨 - `status`에 `running: true`가 표시됨 -- `tabs`에 이미 열려 있는 브라우저 탭이 나열됨 +- `tabs`에 이미 열려 있는 브라우저 탭이 표시됨 - `snapshot`이 선택된 라이브 탭의 ref를 반환함 -attach가 작동하지 않을 때 확인할 사항: +연결이 작동하지 않을 때 확인할 사항: - 대상 Chromium 기반 브라우저 버전이 `144+`인지 -- 해당 브라우저 inspect 페이지에서 원격 디버깅이 활성화되어 있는지 -- 브라우저에 연결 승인 프롬프트가 표시되었고 이를 수락했는지 -- `openclaw doctor`는 이전 확장 기반 브라우저 config를 마이그레이션하고 +- 해당 브라우저의 inspect 페이지에서 원격 디버깅이 활성화되어 있는지 +- 브라우저에 연결 동의 프롬프트가 표시되었고 이를 수락했는지 +- `openclaw doctor`는 오래된 확장 기반 브라우저 config를 마이그레이션하고 기본 자동 연결 프로필용으로 Chrome이 로컬에 설치되어 있는지 확인하지만, - 브라우저 측 원격 디버깅까지 대신 활성화해 주지는 않습니다 + 브라우저 측 원격 디버깅을 대신 활성화해 주지는 않습니다 에이전트 사용: -- 사용자의 로그인된 브라우저 상태가 필요할 때는 `profile="user"`를 사용하세요. -- custom existing-session 프로필을 사용한다면 명시적으로 해당 프로필 이름을 전달하세요. -- 사용자가 컴퓨터 앞에 있어 attach 프롬프트를 승인할 수 있을 때만 이 모드를 선택하세요. +- 사용자 로그인 브라우저 상태가 필요할 때는 `profile="user"`를 사용하세요. +- 사용자 지정 기존 세션 프로필을 사용한다면 해당 명시적 프로필 이름을 전달하세요. +- 사용자가 컴퓨터 앞에 있어 연결 프롬프트를 승인할 수 있을 때만 이 모드를 선택하세요. - Gateway 또는 node host는 `npx chrome-devtools-mcp@latest --autoConnect`를 실행할 수 있습니다 -참고: +참고 사항: -- 이 경로는 로그인된 브라우저 세션 내부에서 동작할 수 있으므로 격리된 `openclaw` 프로필보다 위험도가 높습니다. -- 이 드라이버에서는 OpenClaw가 브라우저를 실행하지 않으며, 기존 세션에만 연결합니다. -- OpenClaw는 여기서 공식 Chrome DevTools MCP `--autoConnect` 흐름을 사용합니다. `userDataDir`이 설정되어 있으면 해당 명시적 Chromium 사용자 데이터 디렉터리를 대상으로 하도록 이를 전달합니다. -- existing-session 스크린샷은 페이지 캡처와 스냅샷의 `--ref` 요소 캡처는 지원하지만 CSS `--element` 선택자는 지원하지 않습니다. -- existing-session 페이지 스크린샷은 Chrome MCP를 통해 Playwright 없이도 작동합니다. - ref 기반 요소 스크린샷(`--ref`)도 작동하지만, `--full-page`는 `--ref` 또는 `--element`와 함께 사용할 수 없습니다. -- existing-session 작업은 관리형 브라우저 경로보다 여전히 더 제한적입니다: - - `click`, `type`, `hover`, `scrollIntoView`, `drag`, `select`는 CSS 선택자 대신 스냅샷 ref가 필요합니다 - - `click`은 왼쪽 버튼만 지원합니다(버튼 재정의나 modifier 없음) - - `type`은 `slowly=true`를 지원하지 않으며, `fill` 또는 `press`를 사용해야 합니다 +- 이 경로는 로그인된 브라우저 세션 내부에서 동작할 수 있으므로 격리된 `openclaw` 프로필보다 위험이 더 큽니다. +- OpenClaw는 이 드라이버에 대해 브라우저를 실행하지 않으며, + 기존 세션에만 연결합니다. +- OpenClaw는 여기서 공식 Chrome DevTools MCP `--autoConnect` 흐름을 사용합니다. `userDataDir`이 설정된 경우 OpenClaw는 이를 전달하여 + 해당 명시적 Chromium 사용자 데이터 디렉터리를 대상으로 지정합니다. +- 기존 세션 스크린샷은 페이지 캡처와 스냅샷의 `--ref` 요소 + 캡처는 지원하지만 CSS `--element` 선택자는 지원하지 않습니다. +- 기존 세션 페이지 스크린샷은 Chrome MCP를 통해 Playwright 없이 작동합니다. + ref 기반 요소 스크린샷(`--ref`)도 작동하지만 `--full-page`는 + `--ref` 또는 `--element`와 함께 사용할 수 없습니다. +- 기존 세션 작업은 관리형 브라우저 경로보다 여전히 제한이 많습니다: + - `click`, `type`, `hover`, `scrollIntoView`, `drag`, `select`는 + CSS 선택자 대신 스냅샷 ref가 필요합니다 + - `click`은 왼쪽 버튼만 지원합니다(버튼 재정의 또는 modifier 없음) + - `type`은 `slowly=true`를 지원하지 않으며 `fill` 또는 `press`를 사용해야 합니다 - `press`는 `delayMs`를 지원하지 않습니다 - - `hover`, `scrollIntoView`, `drag`, `select`, `fill`, `evaluate`는 호출별 타임아웃 재정의를 지원하지 않습니다 + - `hover`, `scrollIntoView`, `drag`, `select`, `fill`, `evaluate`는 + 호출별 타임아웃 재정의를 지원하지 않습니다 - `select`는 현재 단일 값만 지원합니다 -- existing-session `wait --url`은 다른 브라우저 드라이버처럼 정확 일치, 부분 문자열, glob 패턴을 지원합니다. `wait --load networkidle`은 아직 지원하지 않습니다. -- existing-session 업로드 훅은 `ref` 또는 `inputRef`가 필요하고, 한 번에 한 파일만 지원하며, CSS `element` 대상 지정은 지원하지 않습니다. -- existing-session 대화상자 훅은 타임아웃 재정의를 지원하지 않습니다. -- 일부 기능은 여전히 관리형 브라우저 경로가 필요합니다. 예를 들면 배치 작업, PDF 내보내기, 다운로드 가로채기, `responsebody` 등이 있습니다. -- existing-session은 호스트 로컬 전용입니다. Chrome이 다른 머신이나 - 다른 네트워크 네임스페이스에 있다면 remote CDP 또는 node host를 대신 사용하세요. +- 기존 세션 `wait --url`은 다른 브라우저 드라이버와 마찬가지로 정확 일치, 부분 문자열, glob 패턴을 지원합니다. `wait --load networkidle`은 아직 지원되지 않습니다. +- 기존 세션 업로드 훅은 `ref` 또는 `inputRef`가 필요하고 한 번에 하나의 파일만 지원하며 CSS `element` 대상 지정은 지원하지 않습니다. +- 기존 세션 대화상자 훅은 타임아웃 재정의를 지원하지 않습니다. +- 배치 작업, PDF 내보내기, 다운로드 가로채기, `responsebody`를 포함한 일부 기능은 여전히 관리형 브라우저 경로가 필요합니다. +- 기존 세션은 호스트 로컬입니다. Chrome이 다른 머신이나 + 다른 네트워크 네임스페이스에 있다면 대신 원격 CDP 또는 node host를 사용하세요. ## 격리 보장 -- **전용 사용자 데이터 디렉터리**: 개인 브라우저 프로필을 절대 건드리지 않습니다. -- **전용 포트**: 개발 워크플로와의 충돌을 피하기 위해 `9222`를 사용하지 않습니다. -- **결정적인 탭 제어**: “마지막 탭”이 아니라 `targetId`로 탭을 대상으로 지정합니다. +- **전용 사용자 데이터 디렉터리**: 사용자의 개인 브라우저 프로필에 절대 영향을 주지 않습니다. +- **전용 포트**: 개발 워크플로와의 충돌을 방지하기 위해 `9222`를 피합니다. +- **결정적인 탭 제어**: “마지막 탭”이 아니라 `targetId`로 탭을 지정합니다. ## 브라우저 선택 @@ -515,9 +511,9 @@ attach가 작동하지 않을 때 확인할 사항: 4. Chromium 5. Chrome Canary -`browser.executablePath`로 이를 재정의할 수 있습니다. +`browser.executablePath`로 재정의할 수 있습니다. -플랫폼별: +플랫폼: - macOS: `/Applications`와 `~/Applications`를 확인합니다. - Linux: `google-chrome`, `brave`, `microsoft-edge`, `chromium` 등을 찾습니다. @@ -540,35 +536,56 @@ attach가 작동하지 않을 때 확인할 사항: - 상태: `GET /storage/:kind`, `POST /storage/:kind/set`, `POST /storage/:kind/clear` - 설정: `POST /set/offline`, `POST /set/headers`, `POST /set/credentials`, `POST /set/geolocation`, `POST /set/media`, `POST /set/timezone`, `POST /set/locale`, `POST /set/device` -모든 엔드포인트는 `?profile=`을 허용합니다. +모든 엔드포인트는 `?profile=`을 받습니다. -공유 비밀 gateway 인증이 구성되어 있다면 브라우저 HTTP 라우트도 인증이 필요합니다: +공유 시크릿 gateway 인증이 구성되어 있으면 브라우저 HTTP 경로에도 인증이 필요합니다: - `Authorization: Bearer ` -- `x-openclaw-password: ` 또는 해당 비밀번호를 사용하는 HTTP Basic auth +- `x-openclaw-password: ` 또는 해당 비밀번호를 사용하는 HTTP Basic 인증 -참고: +참고 사항: - 이 독립형 루프백 브라우저 API는 `trusted-proxy` 또는 - Tailscale Serve identity 헤더를 사용하지 않습니다. -- `gateway.auth.mode`가 `none` 또는 `trusted-proxy`인 경우에도 이 루프백 브라우저 - 라우트는 그런 identity 기반 모드를 상속하지 않으므로 반드시 루프백 전용으로 유지하세요. + Tailscale Serve ID 헤더를 사용하지 않습니다. +- `gateway.auth.mode`가 `none` 또는 `trusted-proxy`이면 이러한 루프백 브라우저 + 경로는 해당 ID 기반 모드를 상속하지 않으므로 루프백 전용으로 유지하세요. -### Playwright 필요 사항 +### `/act` 오류 계약 + +`POST /act`는 경로 수준 유효성 검사와 정책 실패에 대해 +구조화된 오류 응답을 사용합니다: + +```json +{ "error": "", "code": "ACT_*" } +``` + +현재 `code` 값: + +- `ACT_KIND_REQUIRED` (HTTP 400): `kind`가 없거나 인식되지 않습니다. +- `ACT_INVALID_REQUEST` (HTTP 400): 작업 페이로드 정규화 또는 유효성 검사에 실패했습니다. +- `ACT_SELECTOR_UNSUPPORTED` (HTTP 400): 지원되지 않는 작업 종류에 `selector`가 사용되었습니다. +- `ACT_EVALUATE_DISABLED` (HTTP 403): config에서 `evaluate`(또는 `wait --fn`)가 비활성화되어 있습니다. +- `ACT_TARGET_ID_MISMATCH` (HTTP 403): 최상위 또는 배치된 `targetId`가 요청 대상과 충돌합니다. +- `ACT_EXISTING_SESSION_UNSUPPORTED` (HTTP 501): 기존 세션 프로필에서는 작업이 지원되지 않습니다. + +기타 런타임 실패는 여전히 `code` 필드 없이 +`{ "error": "" }`를 반환할 수 있습니다. + +### Playwright 요구 사항 일부 기능(navigate/act/AI snapshot/role snapshot, 요소 스크린샷, -PDF)에는 Playwright가 필요합니다. Playwright가 설치되어 있지 않으면 -해당 엔드포인트는 명확한 501 오류를 반환합니다. +PDF)에는 Playwright가 필요합니다. Playwright가 설치되지 않은 경우 해당 엔드포인트는 +명확한 501 오류를 반환합니다. -Playwright 없이도 작동하는 항목: +Playwright 없이도 여전히 작동하는 기능: - ARIA 스냅샷 - 탭별 CDP - WebSocket을 사용할 수 있는 경우 관리형 `openclaw` 브라우저의 페이지 스크린샷 + WebSocket을 사용할 수 있을 때 관리형 `openclaw` 브라우저의 페이지 스크린샷 - `existing-session` / Chrome MCP 프로필의 페이지 스크린샷 -- 스냅샷 출력에서 `existing-session` ref 기반 스크린샷(`--ref`) +- 스냅샷 출력의 `existing-session` ref 기반 스크린샷(`--ref`) -여전히 Playwright가 필요한 항목: +여전히 Playwright가 필요한 기능: - `navigate` - `act` @@ -576,16 +593,15 @@ Playwright 없이도 작동하는 항목: - CSS 선택자 요소 스크린샷(`--element`) - 전체 브라우저 PDF 내보내기 -요소 스크린샷은 `--full-page`도 거부합니다. 해당 라우트는 `fullPage is +요소 스크린샷은 `--full-page`도 거부하며 경로는 `fullPage is not supported for element screenshots`를 반환합니다. -`Playwright is not available in this gateway build`가 보이면 전체 -Playwright 패키지(`playwright-core`가 아님)를 설치하고 gateway를 재시작하거나, -브라우저 지원이 포함된 OpenClaw를 다시 설치하세요. +`Playwright is not available in this gateway build`가 표시되면 전체 +Playwright 패키지(`playwright-core`가 아님)를 설치하고 gateway를 다시 시작하거나, 브라우저 지원이 포함된 OpenClaw를 다시 설치하세요. #### Docker Playwright 설치 -Gateway가 Docker에서 실행되는 경우 `npx playwright`는 피하세요(npm override 충돌). +Gateway가 Docker에서 실행 중이면 `npx playwright`는 피하세요(npm override 충돌). 대신 번들 CLI를 사용하세요: ```bash @@ -594,8 +610,8 @@ docker compose run --rm openclaw-cli \ ``` 브라우저 다운로드를 유지하려면 `PLAYWRIGHT_BROWSERS_PATH`를 설정하고(예: -`/home/node/.cache/ms-playwright`), `/home/node`가 `OPENCLAW_HOME_VOLUME` 또는 -bind mount를 통해 유지되도록 하세요. [Docker](/ko/install/docker)를 참조하세요. +`/home/node/.cache/ms-playwright`), `/home/node`가 +`OPENCLAW_HOME_VOLUME` 또는 bind mount를 통해 유지되도록 하세요. 자세한 내용은 [Docker](/ko/install/docker)를 참조하세요. ## 작동 방식(내부) @@ -606,13 +622,13 @@ bind mount를 통해 유지되도록 하세요. [Docker](/ko/install/docker)를 - 고급 작업(클릭/입력/스냅샷/PDF)에는 CDP 위에서 **Playwright**를 사용합니다. - Playwright가 없으면 Playwright 비의존 작업만 사용할 수 있습니다. -이 설계는 에이전트에 안정적이고 결정적인 인터페이스를 제공하면서도, -로컬/원격 브라우저와 프로필을 자유롭게 교체할 수 있게 합니다. +이 설계는 에이전트가 안정적이고 결정적인 인터페이스를 사용하도록 유지하면서도 +로컬/원격 브라우저와 프로필을 교체할 수 있게 합니다. ## CLI 빠른 참조 -모든 명령은 특정 프로필을 대상으로 지정하기 위해 `--browser-profile `을 받습니다. -모든 명령은 기계가 읽을 수 있는 출력(안정적인 페이로드)을 위해 `--json`도 받습니다. +모든 명령은 특정 프로필을 대상으로 `--browser-profile `을 받을 수 있습니다. +모든 명령은 기계가 읽을 수 있는 출력(안정적인 페이로드)을 위해 `--json`도 받을 수 있습니다. 기본: @@ -645,9 +661,9 @@ bind mount를 통해 유지되도록 하세요. [Docker](/ko/install/docker)를 수명 주기 참고: -- attach-only 및 원격 CDP 프로필에서는 테스트 후에도 `openclaw browser stop`이 - 올바른 정리 명령입니다. 기본 브라우저를 종료하는 대신 활성 제어 세션을 닫고 - 임시 에뮬레이션 재정의를 해제합니다. +- attach-only 및 원격 CDP 프로필의 경우에도 테스트 후 정리 명령으로는 + `openclaw browser stop`이 올바릅니다. 이 명령은 실제 브라우저를 종료하는 대신 + 활성 제어 세션을 닫고 임시 에뮬레이션 재정의를 지웁니다. - `openclaw browser errors --clear` - `openclaw browser requests --filter api --clear` - `openclaw browser pdf` @@ -696,26 +712,27 @@ bind mount를 통해 유지되도록 하세요. [Docker](/ko/install/docker)를 - `openclaw browser set locale en-US` - `openclaw browser set device "iPhone 14"` -참고: +참고 사항: -- `upload`와 `dialog`는 **arming** 호출입니다. 파일 선택기/대화상자를 트리거하는 클릭/press 전에 먼저 실행하세요. +- `upload`와 `dialog`는 **사전 준비** 호출입니다. 파일 선택기/대화상자를 + 트리거하는 클릭/키 입력 전에 실행하세요. - 다운로드 및 trace 출력 경로는 OpenClaw 임시 루트로 제한됩니다: - - traces: `/tmp/openclaw` (폴백: `${os.tmpdir()}/openclaw`) - - downloads: `/tmp/openclaw/downloads` (폴백: `${os.tmpdir()}/openclaw/downloads`) -- 업로드 경로도 OpenClaw 임시 업로드 루트로 제한됩니다: - - uploads: `/tmp/openclaw/uploads` (폴백: `${os.tmpdir()}/openclaw/uploads`) + - traces: `/tmp/openclaw` (대체 경로: `${os.tmpdir()}/openclaw`) + - downloads: `/tmp/openclaw/downloads` (대체 경로: `${os.tmpdir()}/openclaw/downloads`) +- 업로드 경로는 OpenClaw 임시 업로드 루트로 제한됩니다: + - uploads: `/tmp/openclaw/uploads` (대체 경로: `${os.tmpdir()}/openclaw/uploads`) - `upload`는 `--input-ref` 또는 `--element`를 통해 파일 입력을 직접 설정할 수도 있습니다. - `snapshot`: - - `--format ai`(기본값, Playwright 설치 시): 숫자 ref(`aria-ref=""`)가 있는 AI 스냅샷을 반환합니다. + - `--format ai`(기본값, Playwright 설치 시): 숫자 ref(`aria-ref=""`)가 포함된 AI 스냅샷을 반환합니다. - `--format aria`: 접근성 트리를 반환합니다(ref 없음, 검사 전용). - - `--efficient`(또는 `--mode efficient`): compact role 스냅샷 프리셋(interactive + compact + depth + 낮은 maxChars)입니다. - - config 기본값(도구/CLI 전용): 호출자가 모드를 전달하지 않을 때 efficient 스냅샷을 사용하려면 `browser.snapshotDefaults.mode: "efficient"`를 설정하세요([Gateway configuration](/ko/gateway/configuration-reference#browser) 참조). - - role 스냅샷 옵션(`--interactive`, `--compact`, `--depth`, `--selector`)은 `ref=e12` 같은 ref가 있는 role 기반 스냅샷을 강제합니다. - - `--frame "