From a0d596177daead8b617a36932d7db6c85fb5773e Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Thu, 9 Apr 2026 01:33:40 +0000 Subject: [PATCH] chore(i18n): refresh ko translations --- docs/ko/channels/discord.md | 453 +++--- docs/ko/channels/matrix.md | 726 ++++----- docs/ko/concepts/agent-loop.md | 169 +- docs/ko/concepts/dreaming.md | 102 +- docs/ko/concepts/memory.md | 102 +- docs/ko/concepts/model-providers.md | 669 ++++---- docs/ko/concepts/qa-e2e-automation.md | 86 +- docs/ko/gateway/cli-backends.md | 185 +-- docs/ko/gateway/configuration-reference.md | 1085 ++++++------- docs/ko/gateway/doctor.md | 505 +++--- docs/ko/help/testing.md | 670 ++++---- ...refactor-real-plugin-sdk-workspace-plan.md | 507 ------ docs/ko/plugins/architecture.md | 1363 +++++++---------- docs/ko/plugins/manifest.md | 372 ++--- docs/ko/plugins/sdk-migration.md | 398 ++--- docs/ko/plugins/sdk-overview.md | 579 ++++--- docs/ko/plugins/sdk-provider-plugins.md | 370 ++--- docs/ko/providers/google.md | 99 +- docs/ko/providers/inferrs.md | 91 +- docs/ko/providers/ollama.md | 150 +- docs/ko/providers/qwen.md | 153 +- 21 files changed, 3987 insertions(+), 4847 deletions(-) delete mode 100644 docs/ko/plans/2026-04-05-002-refactor-real-plugin-sdk-workspace-plan.md diff --git a/docs/ko/channels/discord.md b/docs/ko/channels/discord.md index 065ae4aff..682b14202 100644 --- a/docs/ko/channels/discord.md +++ b/docs/ko/channels/discord.md @@ -4,66 +4,66 @@ read_when: summary: Discord 봇 지원 상태, 기능 및 구성 title: Discord x-i18n: - generated_at: "2026-04-06T03:08:11Z" + generated_at: "2026-04-09T01:30:04Z" model: gpt-5.4 provider: openai - source_hash: 54af2176a1b4fa1681e3f07494def0c652a2730165058848000e71a59e2a9d08 + source_hash: 3cd2886fad941ae2129e681911309539e9a65a2352b777b538d7f4686a68f73f source_path: channels/discord.md workflow: 15 --- # Discord (Bot API) -상태: 공식 Discord gateway를 통해 DM 및 길드 채널에서 사용할 준비가 되어 있습니다. +상태: 공식 Discord 게이트웨이를 통해 DM 및 길드 채널에서 사용할 준비가 되었습니다. Discord DM은 기본적으로 페어링 모드입니다. - 기본 명령 동작 및 명령 카탈로그. + 기본 명령 동작 및 명령 카탈로그입니다. - 채널 전반의 진단 및 복구 흐름. + 채널 전반의 진단 및 복구 흐름입니다. ## 빠른 설정 -새 애플리케이션과 봇을 만들고, 봇을 서버에 추가한 뒤, OpenClaw와 페어링해야 합니다. 봇은 본인 전용 비공개 서버에 추가하는 것을 권장합니다. 아직 서버가 없다면 먼저 [서버를 만드세요](https://support.discord.com/hc/en-us/articles/204849977-How-do-I-create-a-server) (**Create My Own > For me and my friends** 선택). +새 애플리케이션과 봇을 만들고, 봇을 서버에 추가한 뒤, OpenClaw와 페어링해야 합니다. 봇은 본인만 사용하는 비공개 서버에 추가하는 것을 권장합니다. 아직 서버가 없다면 먼저 [서버를 만드세요](https://support.discord.com/hc/en-us/articles/204849977-How-do-I-create-a-server) (**Create My Own > For me and my friends** 선택). - [Discord Developer Portal](https://discord.com/developers/applications)로 이동한 뒤 **New Application**을 클릭합니다. 이름은 "OpenClaw"처럼 지정합니다. + [Discord Developer Portal](https://discord.com/developers/applications)로 이동한 다음 **New Application**을 클릭합니다. 이름은 "OpenClaw"처럼 지정합니다. 사이드바에서 **Bot**을 클릭합니다. **Username**은 OpenClaw 에이전트를 부르는 이름으로 설정합니다. - - 계속해서 **Bot** 페이지에서 아래로 스크롤하여 **Privileged Gateway Intents**로 이동한 뒤 다음을 활성화합니다. + + 계속해서 **Bot** 페이지에서 아래로 스크롤하여 **Privileged Gateway Intents**로 이동한 다음, 다음을 활성화합니다. - **Message Content Intent** (필수) - - **Server Members Intent** (권장; 역할 허용 목록 및 이름-대-ID 매칭에 필요) - - **Presence Intent** (선택 사항; 프레즌스 업데이트가 필요한 경우에만 필요) + - **Server Members Intent** (권장; 역할 allowlist 및 이름→ID 매칭에 필요) + - **Presence Intent** (선택 사항; 프레즌스 업데이트가 필요할 때만 사용) - **Bot** 페이지 상단으로 다시 올라가 **Reset Token**을 클릭합니다. + 다시 **Bot** 페이지 상단으로 올라가 **Reset Token**을 클릭합니다. - 이름과 달리, 이는 첫 번째 토큰을 생성하는 동작이며 "재설정"되는 것은 없습니다. + 이름과 달리, 이것은 첫 번째 토큰을 생성하는 동작이며 실제로 무언가를 "재설정"하는 것은 아닙니다. - 토큰을 복사해 어딘가에 저장합니다. 이것이 **Bot Token**이며, 곧 필요합니다. + 토큰을 복사하여 안전한 곳에 저장합니다. 이것이 **Bot Token**이며, 곧 필요합니다. - - 사이드바에서 **OAuth2**를 클릭합니다. 서버에 봇을 추가할 수 있도록 적절한 권한이 포함된 초대 URL을 생성합니다. + + 사이드바에서 **OAuth2**를 클릭합니다. 봇을 서버에 추가할 수 있도록 적절한 권한이 포함된 초대 URL을 생성합니다. - 아래로 스크롤해 **OAuth2 URL Generator**에서 다음을 활성화합니다. + 아래로 스크롤하여 **OAuth2 URL Generator**에서 다음을 활성화합니다. - `bot` - `applications.commands` @@ -77,30 +77,30 @@ x-i18n: - Attach Files - Add Reactions (선택 사항) - 맨 아래에 생성된 URL을 복사해 브라우저에 붙여넣고, 서버를 선택한 뒤 **Continue**를 클릭하여 연결합니다. 이제 Discord 서버에서 봇이 보여야 합니다. + 하단에서 생성된 URL을 복사해 브라우저에 붙여넣고, 서버를 선택한 다음 **Continue**를 클릭해 연결합니다. 이제 Discord 서버에서 봇이 보여야 합니다. - Discord 앱으로 돌아가 내부 ID를 복사할 수 있도록 Developer Mode를 활성화해야 합니다. + 다시 Discord 앱으로 돌아가 내부 ID를 복사할 수 있도록 Developer Mode를 활성화해야 합니다. 1. **User Settings**(아바타 옆 톱니바퀴 아이콘) → **Advanced** → **Developer Mode** 켜기 - 2. 사이드바에서 **서버 아이콘** 우클릭 → **Copy Server ID** - 3. **본인 아바타** 우클릭 → **Copy User ID** + 2. 사이드바에서 **server icon**을 우클릭 → **Copy Server ID** + 3. 자신의 **avatar**를 우클릭 → **Copy User ID** - **Server ID**와 **User ID**를 Bot Token과 함께 저장하세요. 다음 단계에서 이 세 가지를 모두 OpenClaw에 보내게 됩니다. + **Server ID**와 **User ID**를 Bot Token과 함께 저장하세요. 다음 단계에서 이 세 가지 모두를 OpenClaw에 전달합니다. - 페어링이 작동하려면 Discord에서 봇이 사용자에게 DM을 보낼 수 있어야 합니다. **서버 아이콘**을 우클릭 → **Privacy Settings** → **Direct Messages** 켜기. + 페어링이 작동하려면 Discord에서 봇이 사용자에게 DM을 보낼 수 있어야 합니다. **server icon**을 우클릭 → **Privacy Settings** → **Direct Messages** 켜기. - 이렇게 하면 서버 멤버(봇 포함)가 사용자에게 DM을 보낼 수 있습니다. OpenClaw와 Discord DM을 사용하려면 이 설정을 계속 켜 두세요. 길드 채널만 사용할 계획이라면 페어링 후 DM을 비활성화해도 됩니다. + 이렇게 하면 서버 멤버(봇 포함)가 사용자에게 DM을 보낼 수 있습니다. OpenClaw에서 Discord DM을 사용하려면 이 설정을 켜 둡니다. 길드 채널만 사용할 계획이라면, 페어링 후 DM을 비활성화해도 됩니다. - - Discord 봇 토큰은 비밀 정보입니다(비밀번호와 유사). 에이전트에 메시지를 보내기 전에 OpenClaw를 실행하는 머신에 설정하세요. + + Discord 봇 토큰은 비밀 정보입니다(비밀번호와 유사). 에이전트에 메시지를 보내기 전에 OpenClaw가 실행 중인 머신에 설정하세요. ```bash export DISCORD_BOT_TOKEN="YOUR_BOT_TOKEN" @@ -110,7 +110,7 @@ openclaw config set channels.discord.enabled true --strict-json openclaw gateway ``` - OpenClaw가 이미 백그라운드 서비스로 실행 중이라면 OpenClaw Mac 앱에서 다시 시작하거나 `openclaw gateway run` 프로세스를 중지 후 다시 시작하세요. + OpenClaw가 이미 백그라운드 서비스로 실행 중이면 OpenClaw Mac 앱에서 재시작하거나 `openclaw gateway run` 프로세스를 중지했다가 다시 시작하세요. @@ -118,12 +118,12 @@ openclaw gateway - 기존 채널(예: Telegram)에서 OpenClaw 에이전트와 대화하며 이렇게 요청하세요. Discord가 첫 번째 채널이라면 대신 CLI / config 탭을 사용하세요. + 기존 채널(예: Telegram)에서 OpenClaw 에이전트와 대화하며 알려주세요. Discord가 첫 번째 채널이라면 대신 CLI / config 탭을 사용하세요. - > "이미 Discord 봇 토큰을 config에 설정했습니다. User ID ``와 Server ID ``로 Discord 설정을 완료해 주세요." + > "이미 Discord 봇 토큰을 config에 설정했습니다. User ID ``와 Server ID ``로 Discord 설정을 마무리해 주세요." - 파일 기반 config를 선호한다면 다음과 같이 설정하세요. + 파일 기반 구성을 선호한다면 다음을 설정합니다. ```json5 { @@ -146,19 +146,19 @@ openclaw gateway DISCORD_BOT_TOKEN=... ``` - 일반 텍스트 `token` 값도 지원됩니다. `channels.discord.token`에는 env/file/exec provider 전반에서 SecretRef 값도 지원됩니다. 자세한 내용은 [Secrets Management](/ko/gateway/secrets)를 참고하세요. + 일반 텍스트 `token` 값도 지원됩니다. `channels.discord.token`에 대해 env/file/exec provider 전반에서 SecretRef 값도 지원됩니다. 자세한 내용은 [Secrets Management](/ko/gateway/secrets)를 참고하세요. - - gateway가 실행 중이 될 때까지 기다린 뒤 Discord에서 봇에게 DM을 보내세요. 봇이 페어링 코드를 응답합니다. + + 게이트웨이가 실행될 때까지 기다린 다음 Discord에서 봇에 DM을 보내세요. 봇이 페어링 코드로 응답합니다. - 기존 채널의 에이전트에게 페어링 코드를 보내세요. + 기존 채널에서 에이전트에게 페어링 코드를 보냅니다. > "이 Discord 페어링 코드를 승인해 주세요: ``" @@ -174,27 +174,27 @@ openclaw pairing approve discord 페어링 코드는 1시간 후 만료됩니다. - 이제 Discord DM을 통해 에이전트와 대화할 수 있어야 합니다. + 이제 Discord에서 DM을 통해 에이전트와 대화할 수 있습니다. -토큰 확인은 계정을 인식합니다. config의 토큰 값이 env 대체값보다 우선합니다. `DISCORD_BOT_TOKEN`은 기본 계정에만 사용됩니다. -고급 아웃바운드 호출(메시지 도구/채널 작업)의 경우, 명시적인 호출별 `token`이 해당 호출에 사용됩니다. 이는 전송 및 읽기/프로브 계열 작업(예: read/search/fetch/thread/pins/permissions)에 적용됩니다. 계정 정책/재시도 설정은 여전히 활성 런타임 스냅샷에서 선택된 계정에서 가져옵니다. +토큰 해석은 계정을 인식합니다. config의 토큰 값이 env 대체값보다 우선합니다. `DISCORD_BOT_TOKEN`은 기본 계정에만 사용됩니다. +고급 아웃바운드 호출(message tool/channel actions)의 경우, 명시적 호출별 `token`이 해당 호출에 사용됩니다. 이는 send 및 read/probe 계열 작업(예: read/search/fetch/thread/pins/permissions)에 적용됩니다. 계정 정책/재시도 설정은 여전히 활성 런타임 스냅샷에서 선택된 계정에서 가져옵니다. ## 권장: 길드 워크스페이스 설정 -DM이 작동하면 Discord 서버를 전체 워크스페이스로 설정할 수 있습니다. 이렇게 하면 각 채널이 자체 컨텍스트를 가진 독립적인 에이전트 세션을 갖게 됩니다. 본인과 봇만 있는 비공개 서버에 권장됩니다. +DM이 작동하면 Discord 서버를 전체 워크스페이스로 설정할 수 있습니다. 이 경우 각 채널은 자체 컨텍스트를 가진 별도의 에이전트 세션을 갖습니다. 자신과 봇만 있는 비공개 서버에 권장됩니다. - + 이렇게 하면 에이전트가 DM뿐 아니라 서버의 모든 채널에서 응답할 수 있습니다. - > "내 Discord Server ID ``를 길드 허용 목록에 추가해 주세요" + > "내 Discord Server ID ``를 길드 allowlist에 추가해 주세요" @@ -219,15 +219,15 @@ DM이 작동하면 Discord 서버를 전체 워크스페이스로 설정할 수 - - 기본적으로 에이전트는 길드 채널에서 @mention 되었을 때만 응답합니다. 비공개 서버라면 모든 메시지에 응답하도록 설정하는 것이 일반적입니다. + + 기본적으로 에이전트는 길드 채널에서 @mention 되었을 때만 응답합니다. 비공개 서버라면 모든 메시지에 응답하도록 설정하는 것이 일반적으로 더 편리합니다. - > "이 서버에서 내 에이전트가 @mentioned 되지 않아도 응답하도록 해 주세요" + > "이 서버에서 @mentioned 되지 않아도 내 에이전트가 응답하도록 해 주세요" - 길드 config에서 `requireMention: false`로 설정하세요. + 길드 config에서 `requireMention: false`를 설정하세요. ```json5 { @@ -249,39 +249,39 @@ DM이 작동하면 Discord 서버를 전체 워크스페이스로 설정할 수 - 기본적으로 장기 메모리(MEMORY.md)는 DM 세션에서만 로드됩니다. 길드 채널에서는 MEMORY.md를 자동 로드하지 않습니다. + 기본적으로 장기 메모리(`MEMORY.md`)는 DM 세션에서만 로드됩니다. 길드 채널은 `MEMORY.md`를 자동 로드하지 않습니다. - > "Discord 채널에서 질문할 때 MEMORY.md의 장기 컨텍스트가 필요하면 memory_search 또는 memory_get을 사용해 주세요." + > "Discord 채널에서 질문할 때 `MEMORY.md`의 장기 컨텍스트가 필요하면 memory_search 또는 memory_get을 사용해 주세요." - 모든 채널에서 공유 컨텍스트가 필요하다면 안정적인 지침은 `AGENTS.md` 또는 `USER.md`에 두세요(모든 세션에 주입됨). 장기 메모는 `MEMORY.md`에 두고 필요할 때 메모리 도구로 접근하세요. + 모든 채널에서 공유 컨텍스트가 필요하다면 안정적인 지침은 `AGENTS.md` 또는 `USER.md`에 넣으세요(모든 세션에 주입됨). 장기 메모는 `MEMORY.md`에 보관하고, 필요할 때 memory 도구로 접근하세요. -이제 Discord 서버에 몇 개의 채널을 만들고 대화를 시작하세요. 에이전트는 채널 이름을 볼 수 있으며, 각 채널은 자체적으로 격리된 세션을 갖습니다. 따라서 `#coding`, `#home`, `#research` 또는 워크플로에 맞는 어떤 구성이든 만들 수 있습니다. +이제 Discord 서버에 몇 개의 채널을 만들고 대화를 시작하세요. 에이전트는 채널 이름을 볼 수 있으며, 각 채널은 자체적으로 격리된 세션을 갖습니다. 따라서 워크플로에 맞게 `#coding`, `#home`, `#research` 등을 설정할 수 있습니다. ## 런타임 모델 -- Gateway가 Discord 연결을 소유합니다. +- 게이트웨이가 Discord 연결을 소유합니다. - 응답 라우팅은 결정적입니다. Discord 인바운드 응답은 다시 Discord로 돌아갑니다. - 기본값(`session.dmScope=main`)에서는 직접 채팅이 에이전트 메인 세션(`agent:main:main`)을 공유합니다. - 길드 채널은 격리된 세션 키(`agent::discord:channel:`)를 사용합니다. - 그룹 DM은 기본적으로 무시됩니다(`channels.discord.dm.groupEnabled=false`). -- 기본 슬래시 명령은 격리된 명령 세션(`agent::discord:slash:`)에서 실행되지만, 라우팅된 대화 세션에는 계속 `CommandTargetSessionKey`가 전달됩니다. +- 기본 슬래시 명령은 격리된 명령 세션(`agent::discord:slash:`)에서 실행되며, 동시에 라우팅된 대화 세션에 대한 `CommandTargetSessionKey`도 전달합니다. ## 포럼 채널 -Discord 포럼 및 미디어 채널은 스레드 게시물만 허용합니다. OpenClaw는 이를 생성하는 두 가지 방법을 지원합니다. +Discord 포럼 및 미디어 채널은 스레드 게시물만 허용합니다. OpenClaw는 이를 만드는 두 가지 방법을 지원합니다. -- 포럼 부모 채널(`channel:`)로 메시지를 보내 스레드를 자동 생성합니다. 스레드 제목은 메시지의 첫 번째 비어 있지 않은 줄을 사용합니다. -- `openclaw message thread create`를 사용하여 스레드를 직접 생성합니다. 포럼 채널에서는 `--message-id`를 전달하지 마세요. +- 포럼 부모(`channel:`)에 메시지를 보내 스레드를 자동 생성합니다. 스레드 제목은 메시지의 첫 번째 비어 있지 않은 줄을 사용합니다. +- `openclaw message thread create`를 사용해 스레드를 직접 생성합니다. 포럼 채널에서는 `--message-id`를 전달하지 마세요. -예시: 포럼 부모 채널로 보내 스레드 생성 +예시: 포럼 부모로 보내 스레드 생성 ```bash openclaw message send --channel discord --target channel: \ @@ -295,35 +295,35 @@ openclaw message thread create --channel discord --target channel: \ --thread-name "Topic title" --message "Body of the post" ``` -포럼 부모 채널은 Discord 컴포넌트를 허용하지 않습니다. 컴포넌트가 필요하다면 스레드 자체(`channel:`)로 보내세요. +포럼 부모는 Discord 컴포넌트를 허용하지 않습니다. 컴포넌트가 필요하면 스레드 자체(`channel:`)로 보내세요. ## 인터랙티브 컴포넌트 -OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지원합니다. `components` payload와 함께 메시지 도구를 사용하세요. 상호작용 결과는 일반 인바운드 메시지처럼 다시 에이전트로 라우팅되며, 기존 Discord `replyToMode` 설정을 따릅니다. +OpenClaw는 에이전트 메시지에 대해 Discord components v2 컨테이너를 지원합니다. message tool에서 `components` 페이로드를 사용하세요. 인터랙션 결과는 일반적인 인바운드 메시지처럼 에이전트로 다시 라우팅되며, 기존 Discord `replyToMode` 설정을 따릅니다. 지원되는 블록: - `text`, `section`, `separator`, `actions`, `media-gallery`, `file` -- 액션 행은 최대 5개의 버튼 또는 하나의 선택 메뉴를 허용합니다 +- 액션 행은 최대 5개의 버튼 또는 단일 선택 메뉴를 허용합니다. - 선택 유형: `string`, `user`, `role`, `mentionable`, `channel` -기본적으로 컴포넌트는 한 번만 사용할 수 있습니다. 만료될 때까지 버튼, 선택, 폼을 여러 번 사용할 수 있도록 하려면 `components.reusable=true`로 설정하세요. +기본적으로 컴포넌트는 한 번만 사용할 수 있습니다. 버튼, 선택 항목, 폼을 만료될 때까지 여러 번 사용 가능하게 하려면 `components.reusable=true`를 설정하세요. -누가 버튼을 클릭할 수 있는지 제한하려면 해당 버튼에 `allowedUsers`를 설정하세요(Discord 사용자 ID, 태그 또는 `*`). 설정된 경우, 일치하지 않는 사용자는 ephemeral 거부 응답을 받습니다. +버튼을 클릭할 수 있는 사용자를 제한하려면 해당 버튼에 `allowedUsers`를 설정하세요(Discord 사용자 ID, 태그 또는 `*`). 구성된 경우, 일치하지 않는 사용자는 ephemeral 거부 응답을 받습니다. -`/model` 및 `/models` 슬래시 명령은 provider와 model 드롭다운, 그리고 Submit 단계를 포함한 인터랙티브 모델 선택기를 엽니다. 선택기 응답은 ephemeral이며 호출한 사용자만 사용할 수 있습니다. +`/model` 및 `/models` 슬래시 명령은 provider 및 모델 드롭다운과 Submit 단계가 포함된 인터랙티브 모델 선택기를 엽니다. 선택기 응답은 ephemeral이며, 호출한 사용자만 사용할 수 있습니다. 파일 첨부: -- `file` 블록은 첨부 참조(`attachment://`)를 가리켜야 합니다 -- 첨부는 `media`/`path`/`filePath`(단일 파일)로 제공하세요. 여러 파일에는 `media-gallery`를 사용하세요 -- 업로드 이름이 첨부 참조와 일치해야 할 경우 `filename`을 사용해 덮어쓸 수 있습니다 +- `file` 블록은 첨부 참조(`attachment://`)를 가리켜야 합니다. +- 첨부는 `media`/`path`/`filePath`(단일 파일)를 통해 제공하세요. 여러 파일은 `media-gallery`를 사용하세요. +- 첨부 참조와 업로드 이름이 일치해야 할 때는 `filename`으로 업로드 이름을 재정의하세요. 모달 폼: -- 최대 5개 필드와 함께 `components.modal`을 추가하세요 +- 최대 5개 필드로 `components.modal`을 추가합니다. - 필드 유형: `text`, `checkbox`, `radio`, `select`, `role-select`, `user-select` -- OpenClaw가 자동으로 트리거 버튼을 추가합니다 +- OpenClaw가 트리거 버튼을 자동으로 추가합니다. 예시: @@ -379,20 +379,20 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 } ``` -## 접근 제어 및 라우팅 +## 액세스 제어 및 라우팅 - `channels.discord.dmPolicy`는 DM 접근을 제어합니다(레거시: `channels.discord.dm.policy`). + `channels.discord.dmPolicy`는 DM 액세스를 제어합니다(레거시: `channels.discord.dm.policy`). - `pairing` (기본값) - `allowlist` - - `open` (`channels.discord.allowFrom`에 `"*"`가 포함되어야 함; 레거시: `channels.discord.dm.allowFrom`) + - `open` (`channels.discord.allowFrom`에 `"*"` 포함 필요, 레거시: `channels.discord.dm.allowFrom`) - `disabled` - DM 정책이 open이 아니면 알 수 없는 사용자는 차단됩니다(`pairing` 모드에서는 페어링 안내가 표시될 수 있음). + DM 정책이 open이 아니면, 알 수 없는 사용자는 차단되거나(`pairing` 모드에서는) 페어링이 요청됩니다. - 멀티 계정 우선순위: + 다중 계정 우선순위: - `channels.discord.accounts.default.allowFrom`은 `default` 계정에만 적용됩니다. - 이름이 있는 계정은 자체 `allowFrom`이 설정되지 않은 경우 `channels.discord.allowFrom`을 상속합니다. @@ -403,7 +403,7 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - `user:` - `<@id>` 멘션 - 숫자만 있는 ID는 모호하므로, 명시적인 user/channel 대상 종류가 제공되지 않으면 거부됩니다. + 숫자 ID만 단독으로 사용하는 형식은 모호하므로, 명시적인 user/channel 대상 종류가 제공되지 않으면 거부됩니다. @@ -418,12 +418,12 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 `allowlist` 동작: - - 길드는 `channels.discord.guilds`와 일치해야 함(`id` 권장, slug도 허용) - - 선택적 발신자 허용 목록: `users`(안정적인 ID 권장) 및 `roles`(역할 ID만); 둘 중 하나라도 구성되면 발신자는 `users` 또는 `roles` 중 하나와 일치하면 허용됨 - - 직접적인 이름/태그 매칭은 기본적으로 비활성화되어 있음. 비상 호환 모드로만 `channels.discord.dangerouslyAllowNameMatching: true`를 활성화하세요 - - `users`에는 이름/태그도 지원되지만 ID가 더 안전합니다. 이름/태그 항목이 사용되면 `openclaw security audit`가 경고합니다 - - 길드에 `channels`가 구성되어 있으면 목록에 없는 채널은 거부됩니다 - - 길드에 `channels` 블록이 없으면 해당 허용 목록 길드 내의 모든 채널이 허용됩니다 + - 길드는 `channels.discord.guilds`와 일치해야 합니다(`id` 권장, slug 허용) + - 선택적 발신자 allowlist: `users`(안정적인 ID 권장) 및 `roles`(역할 ID만). 둘 중 하나라도 구성되어 있으면 발신자는 `users` 또는 `roles` 중 하나와 일치할 때 허용됩니다. + - 직접적인 이름/태그 매칭은 기본적으로 비활성화됩니다. 비상 호환 모드로만 `channels.discord.dangerouslyAllowNameMatching: true`를 사용하세요. + - `users`에 이름/태그를 사용할 수는 있지만 ID가 더 안전합니다. 이름/태그 항목이 사용되면 `openclaw security audit`가 경고합니다. + - 길드에 `channels`가 구성되어 있으면 목록에 없는 채널은 거부됩니다. + - 길드에 `channels` 블록이 없으면 allowlist에 포함된 해당 길드의 모든 채널이 허용됩니다. 예시: @@ -449,7 +449,7 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 } ``` - `DISCORD_BOT_TOKEN`만 설정하고 `channels.discord` 블록을 생성하지 않으면, 런타임 대체값은 `groupPolicy="allowlist"`입니다(로그에 경고 표시). 이는 `channels.defaults.groupPolicy`가 `open`이어도 동일합니다. + `DISCORD_BOT_TOKEN`만 설정하고 `channels.discord` 블록을 만들지 않으면, 런타임 대체값은 `groupPolicy="allowlist"`입니다(로그에 경고 표시). 이는 `channels.defaults.groupPolicy`가 `open`이어도 동일합니다. @@ -463,19 +463,19 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - 지원되는 경우의 암시적 reply-to-bot 동작 `requireMention`은 길드/채널별로 구성됩니다(`channels.discord.guilds...`). - `ignoreOtherMentions`는 봇이 아닌 다른 사용자/역할을 멘션한 메시지(@everyone/@here 제외)를 선택적으로 버립니다. + `ignoreOtherMentions`는 다른 사용자/역할을 멘션했지만 봇은 멘션하지 않은 메시지를 선택적으로 버립니다(@everyone/@here 제외). 그룹 DM: - - 기본값: 무시(`dm.groupEnabled=false`) - - 선택적 허용 목록: `dm.groupChannels`(채널 ID 또는 slug) + - 기본값: 무시됨(`dm.groupEnabled=false`) + - 선택적 allowlist: `dm.groupChannels`(채널 ID 또는 slug) ### 역할 기반 에이전트 라우팅 -`bindings[].match.roles`를 사용하면 Discord 길드 멤버를 역할 ID 기준으로 서로 다른 에이전트에 라우팅할 수 있습니다. 역할 기반 바인딩은 역할 ID만 허용하며, peer 또는 parent-peer 바인딩 이후, guild-only 바인딩 이전에 평가됩니다. 바인딩이 다른 match 필드도 함께 설정한 경우(예: `peer` + `guildId` + `roles`), 구성된 모든 필드가 일치해야 합니다. +`bindings[].match.roles`를 사용해 Discord 길드 멤버를 역할 ID 기준으로 다른 에이전트로 라우팅합니다. 역할 기반 바인딩은 역할 ID만 허용하며, peer 또는 parent-peer 바인딩 이후이면서 guild-only 바인딩 이전에 평가됩니다. 바인딩이 다른 match 필드도 설정한 경우(예: `peer` + `guildId` + `roles`), 구성된 모든 필드가 일치해야 합니다. ```json5 { @@ -502,7 +502,7 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 ## Developer Portal 설정 - + 1. Discord Developer Portal -> **Applications** -> **New Application** 2. **Bot** -> **Add Bot** @@ -510,7 +510,7 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - + **Bot -> Privileged Gateway Intents**에서 다음을 활성화합니다. - Message Content Intent @@ -523,7 +523,7 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 OAuth URL 생성기: - - 범위: `bot`, `applications.commands` + - scopes: `bot`, `applications.commands` 일반적인 기본 권한: @@ -539,26 +539,26 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - Discord Developer Mode를 활성화한 뒤 다음을 복사합니다. + Discord Developer Mode를 활성화한 다음 다음을 복사합니다. - server ID - channel ID - user ID - 신뢰성 있는 감사 및 프로브를 위해 OpenClaw config에서는 숫자 ID를 권장합니다. + 안정적인 감사 및 probe를 위해 OpenClaw config에서는 숫자 ID 사용을 권장합니다. -## 기본 명령 및 명령 인증 +## 기본 명령과 명령 인증 - `commands.native`의 기본값은 `"auto"`이며 Discord에서 활성화됩니다. - 채널별 재정의: `channels.discord.commands.native`. - `commands.native=false`는 이전에 등록된 Discord 기본 명령을 명시적으로 제거합니다. -- 기본 명령 인증은 일반 메시지 처리와 동일한 Discord 허용 목록/정책을 사용합니다. -- Discord UI에서는 권한이 없는 사용자에게도 명령이 보일 수 있지만, 실행 시에는 여전히 OpenClaw 인증이 적용되며 "not authorized"가 반환됩니다. +- 기본 명령 인증은 일반 메시지 처리와 동일한 Discord allowlist/정책을 사용합니다. +- 권한이 없는 사용자에게도 명령이 Discord UI에 표시될 수 있지만, 실행 시에는 여전히 OpenClaw 인증이 적용되며 "not authorized"를 반환합니다. -명령 카탈로그 및 동작은 [Slash commands](/ko/tools/slash-commands)를 참고하세요. +명령 카탈로그와 동작은 [Slash commands](/ko/tools/slash-commands)를 참고하세요. 기본 슬래시 명령 설정: @@ -580,23 +580,24 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - `all` - `batched` - 참고: `off`는 암시적 응답 스레드 연결을 비활성화합니다. 명시적 `[[reply_to_*]]` 태그는 여전히 적용됩니다. - `first`는 해당 턴의 첫 번째 아웃바운드 Discord 메시지에 항상 암시적인 기본 응답 참조를 첨부합니다. - `batched`는 인바운드 턴이 여러 메시지의 디바운스된 배치였을 때만 Discord의 암시적인 기본 응답 참조를 첨부합니다. 이는 모든 단일 메시지 턴이 아니라 모호한 연속 대화에서만 주로 기본 응답을 사용하고 싶을 때 유용합니다. + 참고: `off`는 암시적 응답 스레딩을 비활성화합니다. 명시적인 `[[reply_to_*]]` 태그는 여전히 적용됩니다. + `first`는 해당 턴의 첫 번째 아웃바운드 Discord 메시지에 암시적 기본 응답 참조를 항상 붙입니다. + `batched`는 + 인바운드 턴이 여러 메시지의 디바운스된 배치였을 때만 Discord의 암시적 기본 응답 참조를 붙입니다. 이는 모든 단일 메시지 턴이 아니라, 주로 모호한 연속 대화에만 기본 응답을 사용하고 싶을 때 유용합니다. - 메시지 ID는 컨텍스트/히스토리에 표시되므로 에이전트가 특정 메시지를 대상으로 지정할 수 있습니다. + 메시지 ID는 컨텍스트/기록에 노출되므로 에이전트가 특정 메시지를 대상으로 지정할 수 있습니다. - - OpenClaw는 임시 메시지를 보내고 텍스트가 도착함에 따라 편집하는 방식으로 초안 응답을 스트리밍할 수 있습니다. + + OpenClaw는 임시 메시지를 보내고 텍스트가 도착할 때마다 수정하는 방식으로 초안 응답을 스트리밍할 수 있습니다. - `channels.discord.streaming`은 미리보기 스트리밍을 제어합니다(`off` | `partial` | `block` | `progress`, 기본값: `off`). - - 기본값이 `off`인 이유는 Discord 미리보기 편집이 특히 여러 봇이나 gateway가 같은 계정 또는 길드 트래픽을 공유하는 경우 빠르게 속도 제한에 걸릴 수 있기 때문입니다. + - 기본값이 `off`인 이유는 Discord 미리보기 수정이 빠르게 rate limit에 걸릴 수 있기 때문이며, 특히 여러 봇 또는 게이트웨이가 같은 계정이나 길드 트래픽을 공유할 때 더 그렇습니다. - `progress`는 채널 간 일관성을 위해 허용되며 Discord에서는 `partial`로 매핑됩니다. - `channels.discord.streamMode`는 레거시 별칭이며 자동 마이그레이션됩니다. - - `partial`은 토큰이 도착할 때 하나의 미리보기 메시지를 계속 편집합니다. - - `block`은 초안 크기의 청크를 출력합니다(크기 및 구분 기준 조정에는 `draftChunk` 사용). + - `partial`은 토큰이 도착할 때 단일 미리보기 메시지를 수정합니다. + - `block`은 초안 크기의 청크를 출력합니다(크기 및 분할 기준은 `draftChunk`로 조정). 예시: @@ -610,7 +611,7 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 } ``` - `block` 모드 청킹 기본값(`channels.discord.textChunkLimit` 범위로 제한됨): + `block` 모드 청크 기본값(`channels.discord.textChunkLimit`로 제한됨): ```json5 { @@ -629,44 +630,45 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 미리보기 스트리밍은 텍스트 전용이며, 미디어 응답은 일반 전달로 대체됩니다. - 참고: 미리보기 스트리밍은 블록 스트리밍과 별개입니다. Discord에서 블록 스트리밍이 명시적으로 활성화되면 OpenClaw는 이중 스트리밍을 피하기 위해 미리보기 스트림을 건너뜁니다. + 참고: 미리보기 스트리밍은 블록 스트리밍과 별개입니다. Discord에 대해 블록 스트리밍이 명시적으로 + 활성화되면 OpenClaw는 이중 스트리밍을 피하기 위해 미리보기 스트림을 건너뜁니다. - - 길드 히스토리 컨텍스트: + + 길드 기록 컨텍스트: - `channels.discord.historyLimit` 기본값 `20` - 대체값: `messages.groupChat.historyLimit` - `0`이면 비활성화 - DM 히스토리 제어: + DM 기록 제어: - `channels.discord.dmHistoryLimit` - `channels.discord.dms[""].historyLimit` 스레드 동작: - - Discord 스레드는 채널 세션으로 라우팅됩니다 - - 부모 스레드 메타데이터는 부모 세션 연결에 사용할 수 있습니다 - - 스레드별 항목이 없으면 스레드 config는 부모 채널 config를 상속합니다 + - Discord 스레드는 채널 세션으로 라우팅됩니다. + - 부모 스레드 메타데이터는 부모 세션 연결에 사용할 수 있습니다. + - 스레드별 항목이 없으면 스레드 config는 부모 채널 config를 상속합니다. - 채널 주제는 **신뢰되지 않는** 컨텍스트로 주입됩니다(시스템 프롬프트 아님). + 채널 주제는 **신뢰할 수 없는** 컨텍스트로 주입되며(시스템 프롬프트 아님), 응답 및 인용 메시지 컨텍스트는 현재 수신된 그대로 유지됩니다. - Discord 허용 목록은 주로 누가 에이전트를 트리거할 수 있는지를 제어하며, 완전한 보조 컨텍스트 리다크션 경계는 아닙니다. + Discord allowlist는 주로 누가 에이전트를 트리거할 수 있는지를 제어하며, 완전한 보조 컨텍스트 리다크션 경계는 아닙니다. - - Discord는 스레드를 세션 대상에 바인딩할 수 있으므로, 해당 스레드의 후속 메시지가 동일한 세션(서브에이전트 세션 포함)으로 계속 라우팅됩니다. + + Discord는 스레드를 세션 대상에 바인딩하여 해당 스레드의 후속 메시지가 동일한 세션(서브에이전트 세션 포함)으로 계속 라우팅되도록 할 수 있습니다. 명령: - `/focus ` 현재/새 스레드를 서브에이전트/세션 대상에 바인딩 - `/unfocus` 현재 스레드 바인딩 제거 - `/agents` 활성 실행 및 바인딩 상태 표시 - - `/session idle ` 포커스된 바인딩의 비활성 자동 unfocus 조회/업데이트 - - `/session max-age ` 포커스된 바인딩의 최대 유지 시간 조회/업데이트 + - `/session idle ` focused 바인딩에 대한 비활성 자동 unfocus 조회/업데이트 + - `/session max-age ` focused 바인딩에 대한 하드 최대 유지 시간 조회/업데이트 Config: @@ -696,8 +698,8 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - `session.threadBindings.*`는 전역 기본값을 설정합니다. - `channels.discord.threadBindings.*`는 Discord 동작을 재정의합니다. - - `sessions_spawn({ thread: true })`에 대해 스레드를 자동 생성/바인딩하려면 `spawnSubagentSessions`가 true여야 합니다. - - ACP(` /acp spawn ... --thread ...` 또는 `sessions_spawn({ runtime: "acp", thread: true })`)에 대해 스레드를 자동 생성/바인딩하려면 `spawnAcpSessions`가 true여야 합니다. + - `spawnSubagentSessions`는 `sessions_spawn({ thread: true })`에 대해 스레드를 자동 생성/바인딩하려면 true여야 합니다. + - `spawnAcpSessions`는 ACP에 대해 스레드를 자동 생성/바인딩하려면 true여야 합니다(`(/acp spawn ... --thread ...` 또는 `sessions_spawn({ runtime: "acp", thread: true })`). - 계정에서 스레드 바인딩이 비활성화되어 있으면 `/focus` 및 관련 스레드 바인딩 작업을 사용할 수 없습니다. 자세한 내용은 [Sub-agents](/ko/tools/subagents), [ACP Agents](/ko/tools/acp-agents), [Configuration Reference](/ko/gateway/configuration-reference)를 참고하세요. @@ -705,11 +707,11 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - 안정적인 "항상 켜짐" ACP 워크스페이스를 위해 Discord 대화를 대상으로 하는 최상위 타입 지정 ACP 바인딩을 구성할 수 있습니다. + 안정적인 "항상 켜짐" ACP 워크스페이스를 위해, Discord 대화를 대상으로 하는 최상위 typed ACP 바인딩을 구성할 수 있습니다. Config 경로: - - `type: "acp"` 및 `match.channel: "discord"`를 사용하는 `bindings[]` + - `type: "acp"` 및 `match.channel: "discord"`가 있는 `bindings[]` 예시: @@ -761,15 +763,15 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 참고: - - `/acp spawn codex --bind here`는 현재 Discord 채널 또는 스레드를 그 자리에서 바인딩하고, 이후 메시지를 동일한 ACP 세션으로 계속 라우팅합니다. - - 이는 여전히 "새로운 Codex ACP 세션 시작"을 의미할 수 있지만, Discord 스레드를 새로 만드는 것은 아닙니다. 기존 채널이 계속 채팅 표면으로 유지됩니다. - - Codex는 여전히 자체 `cwd` 또는 디스크상의 backend 워크스페이스에서 실행될 수 있습니다. 이 워크스페이스는 런타임 상태이며 Discord 스레드가 아닙니다. + - `/acp spawn codex --bind here`는 현재 Discord 채널 또는 스레드를 그 자리에서 바인딩하며, 이후 메시지도 동일한 ACP 세션으로 계속 라우팅되도록 유지합니다. + - 이는 여전히 "새 Codex ACP 세션 시작"을 의미할 수 있지만, 그 자체로 새 Discord 스레드를 생성하지는 않습니다. 기존 채널이 그대로 채팅 표면으로 유지됩니다. + - Codex는 여전히 자체 `cwd` 또는 디스크상의 backend 워크스페이스에서 실행될 수 있습니다. 그 워크스페이스는 Discord 스레드가 아니라 런타임 상태입니다. - 스레드 메시지는 부모 채널 ACP 바인딩을 상속할 수 있습니다. - - 바인딩된 채널 또는 스레드에서 `/new` 및 `/reset`은 동일한 ACP 세션을 그 자리에서 재설정합니다. - - 임시 스레드 바인딩도 계속 작동하며 활성 상태에서는 대상 확인을 재정의할 수 있습니다. - - `spawnAcpSessions`는 OpenClaw가 `--thread auto|here`를 통해 자식 스레드를 생성/바인딩해야 하는 경우에만 필요합니다. 현재 채널에서 `/acp spawn ... --bind here`를 사용하는 데는 필요하지 않습니다. + - 바인딩된 채널 또는 스레드에서는 `/new`와 `/reset`이 동일한 ACP 세션을 그 자리에서 재설정합니다. + - 임시 스레드 바인딩은 여전히 작동하며 활성 상태일 때 대상 해석을 재정의할 수 있습니다. + - `spawnAcpSessions`는 OpenClaw가 `--thread auto|here`를 통해 하위 스레드를 생성/바인딩해야 할 때만 필요합니다. 현재 채널에서 `/acp spawn ... --bind here`를 사용할 때는 필요하지 않습니다. - 바인딩 동작 자세한 내용은 [ACP Agents](/ko/tools/acp-agents)를 참고하세요. + 바인딩 동작에 대한 자세한 내용은 [ACP Agents](/ko/tools/acp-agents)를 참고하세요. @@ -785,25 +787,25 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - + `ackReaction`은 OpenClaw가 인바운드 메시지를 처리하는 동안 확인용 이모지를 보냅니다. - 확인 순서: + 해석 순서: - `channels.discord.accounts..ackReaction` - `channels.discord.ackReaction` - `messages.ackReaction` - - 에이전트 identity 이모지 대체값(`agents.list[].identity.emoji`, 없으면 "👀") + - 에이전트 identity 이모지 대체값(`agents.list[].identity.emoji`, 없으면 `"👀"`) 참고: - - Discord는 유니코드 이모지 또는 사용자 지정 이모지 이름을 허용합니다. - - 채널 또는 계정에서 리액션을 비활성화하려면 `""`를 사용하세요. + - Discord는 유니코드 이모지 또는 커스텀 이모지 이름을 허용합니다. + - 채널이나 계정에서 리액션을 비활성화하려면 `""`를 사용하세요. - 채널에서 시작된 config 쓰기는 기본적으로 활성화되어 있습니다. + 채널에서 시작된 config 쓰기는 기본적으로 활성화됩니다. 이는 `/config set|unset` 흐름에 영향을 줍니다(명령 기능이 활성화된 경우). @@ -821,8 +823,8 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - - `channels.discord.proxy`를 사용해 Discord gateway WebSocket 트래픽과 시작 시 REST 조회(애플리케이션 ID + 허용 목록 확인)를 HTTP(S) 프록시를 통해 라우팅합니다. + + `channels.discord.proxy`를 사용하면 Discord 게이트웨이 WebSocket 트래픽과 시작 시 REST 조회(application ID + allowlist 해석)를 HTTP(S) 프록시를 통해 라우팅할 수 있습니다. ```json5 { @@ -853,7 +855,7 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - 프록시된 메시지를 시스템 멤버 identity에 매핑하도록 PluralKit 확인 기능을 활성화합니다. + 프록시된 메시지를 시스템 멤버 identity에 매핑하기 위해 PluralKit 해석을 활성화합니다. ```json5 { @@ -870,10 +872,10 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 참고: - - 허용 목록은 `pk:`를 사용할 수 있습니다 - - 멤버 표시 이름은 `channels.discord.dangerouslyAllowNameMatching: true`일 때만 name/slug 기준으로 매칭됩니다 - - 조회는 원본 메시지 ID를 사용하며 시간 창 제약이 있습니다 - - 조회에 실패하면 프록시된 메시지는 봇 메시지로 처리되어 `allowBots=true`가 아닌 한 버려집니다 + - allowlist에서 `pk:`를 사용할 수 있습니다. + - 멤버 표시 이름은 `channels.discord.dangerouslyAllowNameMatching: true`일 때만 이름/slug로 매칭됩니다. + - 조회는 원본 메시지 ID를 사용하며 시간 창 제약이 있습니다. + - 조회에 실패하면 프록시된 메시지는 봇 메시지로 처리되어 `allowBots=true`가 아닌 한 버려집니다. @@ -892,7 +894,7 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 } ``` - 활동 예시(기본 활동 유형은 사용자 지정 상태): + 활동 예시(커스텀 상태가 기본 활동 유형): ```json5 { @@ -925,7 +927,7 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - 1: Streaming (`activityUrl` 필요) - 2: Listening - 3: Watching - - 4: Custom (활동 텍스트를 상태 값으로 사용하며, 이모지는 선택 사항) + - 4: Custom (활동 텍스트를 상태 값으로 사용, 이모지는 선택 사항) - 5: Competing auto presence 예시(런타임 상태 신호): @@ -953,72 +955,78 @@ OpenClaw는 에이전트 메시지용 Discord components v2 컨테이너를 지 - - Discord는 DM에서 버튼 기반 승인 처리를 지원하며, 선택적으로 원래 채널에 승인 프롬프트를 게시할 수 있습니다. + + Discord는 DM에서 버튼 기반 승인 처리를 지원하며, 필요하면 원래 채널에 승인 프롬프트를 게시할 수도 있습니다. Config 경로: - `channels.discord.execApprovals.enabled` - - `channels.discord.execApprovals.approvers` (선택 사항; 가능하면 `commands.ownerAllowFrom`으로 대체) + - `channels.discord.execApprovals.approvers` (선택 사항, 가능하면 `commands.ownerAllowFrom`으로 대체) - `channels.discord.execApprovals.target` (`dm` | `channel` | `both`, 기본값: `dm`) - `agentFilter`, `sessionFilter`, `cleanupAfterResolve` - Discord는 `enabled`가 설정되지 않았거나 `"auto"`이고, `execApprovals.approvers` 또는 `commands.ownerAllowFrom`에서 최소 한 명의 승인자를 확인할 수 있으면 기본 exec 승인을 자동 활성화합니다. Discord는 채널 `allowFrom`, 레거시 `dm.allowFrom`, 또는 direct-message `defaultTo`에서 exec 승인자를 추론하지 않습니다. Discord를 기본 승인 클라이언트로 명시적으로 비활성화하려면 `enabled: false`로 설정하세요. + `enabled`가 unset 또는 `"auto"`이고 `execApprovals.approvers` 또는 `commands.ownerAllowFrom`에서 최소 하나의 approver를 해석할 수 있으면, Discord는 기본 exec approval을 자동 활성화합니다. Discord는 채널 `allowFrom`, 레거시 `dm.allowFrom`, 직접 메시지 `defaultTo`로부터 exec approver를 추론하지 않습니다. Discord를 기본 승인 클라이언트로 명시적으로 비활성화하려면 `enabled: false`를 설정하세요. - `target`이 `channel` 또는 `both`이면 승인 프롬프트가 채널에 표시됩니다. 확인된 승인자만 버튼을 사용할 수 있으며, 다른 사용자는 ephemeral 거부 응답을 받습니다. 승인 프롬프트에는 명령 텍스트가 포함되므로, 채널 전달은 신뢰할 수 있는 채널에서만 활성화하세요. 세션 키에서 채널 ID를 유도할 수 없으면 OpenClaw는 DM 전달로 대체합니다. + `target`이 `channel` 또는 `both`이면 승인 프롬프트가 채널에 표시됩니다. 해석된 approver만 버튼을 사용할 수 있으며, 다른 사용자는 ephemeral 거부 응답을 받습니다. 승인 프롬프트에는 명령 텍스트가 포함되므로, 채널 전달은 신뢰할 수 있는 채널에서만 활성화하세요. 세션 키에서 채널 ID를 유도할 수 없으면 OpenClaw는 DM 전달로 대체합니다. - Discord는 다른 채팅 채널에서 사용하는 공용 승인 버튼도 렌더링합니다. 기본 Discord 어댑터는 주로 승인자 DM 라우팅과 채널 팬아웃을 추가합니다. - 이러한 버튼이 존재할 때는 그것이 기본 승인 UX입니다. 도구 결과에서 채팅 승인이 불가능하거나 수동 승인이 유일한 경로라고 말하는 경우에만 OpenClaw는 수동 `/approve` 명령을 포함해야 합니다. + Discord는 다른 채팅 채널에서 사용하는 공용 승인 버튼도 렌더링합니다. 기본 Discord 어댑터는 주로 approver DM 라우팅과 채널 팬아웃을 추가합니다. + 이러한 버튼이 मौजूद할 때는 그것이 기본 승인 UX여야 하며, OpenClaw는 + 도구 결과가 채팅 승인을 사용할 수 없다고 표시하거나 수동 승인이 유일한 경로일 때만 수동 `/approve` 명령을 포함해야 합니다. - 이 핸들러의 gateway 인증은 다른 Gateway 클라이언트와 동일한 공용 자격 증명 확인 계약을 사용합니다. + 이 핸들러의 게이트웨이 인증은 다른 게이트웨이 클라이언트와 동일한 공용 자격 증명 해석 계약을 사용합니다. - - env 우선 로컬 인증(`OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD` 다음 `gateway.auth.*`) - - 로컬 모드에서는 `gateway.auth.*`가 설정되지 않은 경우에만 `gateway.remote.*`를 대체값으로 사용할 수 있으며, 설정되었지만 확인되지 않은 로컬 SecretRef는 fail closed 처리됩니다 - - 해당하는 경우 `gateway.remote.*`를 통한 원격 모드 지원 - - URL 재정의는 override-safe입니다. CLI 재정의는 암시적 자격 증명을 재사용하지 않으며, env 재정의는 env 자격 증명만 사용합니다 + - env 우선 로컬 인증(`OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD` 후 `gateway.auth.*`) + - local 모드에서 `gateway.auth.*`가 unset인 경우에만 `gateway.remote.*`를 대체값으로 사용할 수 있으며, 구성되었지만 해석되지 않은 로컬 SecretRef는 fail closed 됩니다. + - 적용 가능한 경우 `gateway.remote.*`를 통한 remote 모드 지원 + - URL 재정의는 override-safe입니다. CLI 재정의는 암시적 자격 증명을 재사용하지 않으며, env 재정의는 env 자격 증명만 사용합니다. - 승인 확인 동작: + 승인 해석 동작: - - `plugin:` 접두사가 있는 ID는 `plugin.approval.resolve`를 통해 확인됩니다. - - 다른 ID는 `exec.approval.resolve`를 통해 확인됩니다. - - Discord는 여기서 추가적인 exec-to-plugin 대체 확인 단계를 수행하지 않습니다. ID 접두사가 어떤 gateway 메서드를 호출할지 결정합니다. + - `plugin:` 접두사가 붙은 ID는 `plugin.approval.resolve`를 통해 해석됩니다. + - 그 외 ID는 `exec.approval.resolve`를 통해 해석됩니다. + - Discord는 여기서 추가적인 exec-to-plugin 대체 홉을 수행하지 않으며, + ID 접두사가 호출할 게이트웨이 메서드를 결정합니다. - Exec 승인은 기본적으로 30분 후 만료됩니다. 알 수 없는 approval ID 오류로 승인에 실패한다면 승인자 확인, 기능 활성화, 전달된 approval id 종류가 대기 중인 요청과 일치하는지 확인하세요. + exec approval은 기본적으로 30분 후 만료됩니다. 승인에서 + 알 수 없는 approval ID 오류가 발생하면 approver 해석, 기능 활성화, + 그리고 전달된 approval ID 종류가 보류 중 요청과 일치하는지 확인하세요. 관련 문서: [Exec approvals](/ko/tools/exec-approvals) -## 도구 및 작업 게이트 +## 도구 및 액션 게이트 -Discord 메시지 작업에는 메시징, 채널 관리, moderation, 프레즌스, 메타데이터 작업이 포함됩니다. +Discord 메시지 액션에는 메시징, 채널 관리, moderation, presence, 메타데이터 액션이 포함됩니다. 핵심 예시: - 메시징: `sendMessage`, `readMessages`, `editMessage`, `deleteMessage`, `threadReply` - 리액션: `react`, `reactions`, `emojiList` - moderation: `timeout`, `kick`, `ban` -- 프레즌스: `setPresence` +- presence: `setPresence` -작업 게이트는 `channels.discord.actions.*` 아래에 있습니다. +`event-create` 액션은 예약 이벤트 커버 이미지를 설정하기 위한 선택적 `image` 매개변수(URL 또는 로컬 파일 경로)를 허용합니다. + +액션 게이트는 `channels.discord.actions.*` 아래에 있습니다. 기본 게이트 동작: -| 작업 그룹 | 기본값 | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | +| 액션 그룹 | 기본값 | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | | reactions, messages, threads, pins, polls, search, memberInfo, roleInfo, channelInfo, channels, voiceStatus, events, stickers, emojiUploads, stickerUploads, permissions | 활성화됨 | -| roles | 비활성화됨 | -| moderation | 비활성화됨 | -| presence | 비활성화됨 | +| roles | 비활성화 | +| moderation | 비활성화 | +| presence | 비활성화 | ## Components v2 UI -OpenClaw는 exec 승인 및 교차 컨텍스트 마커에 Discord components v2를 사용합니다. Discord 메시지 작업도 사용자 지정 UI용 `components`를 받을 수 있습니다(고급 기능; discord 도구를 통해 컴포넌트 payload를 구성해야 함). 반면 레거시 `embeds`도 계속 사용할 수 있지만 권장되지는 않습니다. +OpenClaw는 exec approval 및 cross-context marker에 Discord components v2를 사용합니다. Discord 메시지 액션도 커스텀 UI를 위해 `components`를 받을 수 있습니다(고급 기능; discord tool을 통해 컴포넌트 페이로드를 구성해야 함). 레거시 `embeds`도 계속 사용할 수 있지만 권장되지는 않습니다. -- `channels.discord.ui.components.accentColor`는 Discord 컴포넌트 컨테이너에 사용하는 강조 색상을 설정합니다(hex). -- 계정별 설정: `channels.discord.accounts..ui.components.accentColor`. -- components v2가 존재하면 `embeds`는 무시됩니다. +- `channels.discord.ui.components.accentColor`는 Discord 컴포넌트 컨테이너에 사용되는 강조 색상을 설정합니다(hex). +- 계정별 설정은 `channels.discord.accounts..ui.components.accentColor`를 사용합니다. +- components v2가 있으면 `embeds`는 무시됩니다. 예시: @@ -1046,7 +1054,7 @@ OpenClaw는 실시간 연속 대화를 위해 Discord 음성 채널에 참여할 - `channels.discord.voice`를 구성합니다. - 봇은 대상 음성 채널에서 Connect + Speak 권한이 필요합니다. -Discord 전용 기본 명령 `/vc join|leave|status`를 사용해 세션을 제어하세요. 이 명령은 계정 기본 에이전트를 사용하며 다른 Discord 명령과 동일한 허용 목록 및 그룹 정책 규칙을 따릅니다. +Discord 전용 기본 명령 `/vc join|leave|status`를 사용해 세션을 제어하세요. 이 명령은 계정 기본 에이전트를 사용하며, 다른 Discord 명령과 동일한 allowlist 및 길드 정책 규칙을 따릅니다. 자동 참여 예시: @@ -1076,23 +1084,23 @@ Discord 전용 기본 명령 `/vc join|leave|status`를 사용해 세션을 제 참고: -- `voice.tts`는 음성 재생에 한해 `messages.tts`를 재정의합니다. -- 음성 전사 턴은 Discord `allowFrom`(또는 `dm.allowFrom`)에서 소유자 상태를 파생합니다. 소유자가 아닌 화자는 소유자 전용 도구(예: `gateway`, `cron`)에 접근할 수 없습니다. -- 음성은 기본적으로 활성화되어 있습니다. 비활성화하려면 `channels.discord.voice.enabled=false`로 설정하세요. -- `voice.daveEncryption` 및 `voice.decryptionFailureTolerance`는 `@discordjs/voice` 참여 옵션으로 그대로 전달됩니다. -- `@discordjs/voice`의 기본값은 설정되지 않은 경우 `daveEncryption=true`, `decryptionFailureTolerance=24`입니다. -- OpenClaw는 수신 복호화 실패도 감시하며, 짧은 시간 동안 반복된 실패가 발생하면 음성 채널을 나갔다가 다시 참여해 자동 복구합니다. -- 수신 로그에 `DecryptionFailed(UnencryptedWhenPassthroughDisabled)`가 반복적으로 표시된다면, 이는 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419)에 추적된 상위 `@discordjs/voice` 수신 버그일 수 있습니다. +- `voice.tts`는 음성 재생에 대해서만 `messages.tts`를 재정의합니다. +- 음성 전사 턴은 Discord `allowFrom`(또는 `dm.allowFrom`)에서 소유자 상태를 파생합니다. 소유자가 아닌 발화자는 소유자 전용 도구(예: `gateway`, `cron`)에 접근할 수 없습니다. +- 음성은 기본적으로 활성화되어 있습니다. 비활성화하려면 `channels.discord.voice.enabled=false`를 설정하세요. +- `voice.daveEncryption` 및 `voice.decryptionFailureTolerance`는 `@discordjs/voice` 조인 옵션으로 그대로 전달됩니다. +- `@discordjs/voice`의 기본값은 설정되지 않은 경우 `daveEncryption=true`와 `decryptionFailureTolerance=24`입니다. +- OpenClaw는 수신 복호화 실패도 감시하며, 짧은 시간 동안 반복 실패가 발생하면 음성 채널에서 나갔다가 다시 참여하여 자동 복구합니다. +- 수신 로그에 `DecryptionFailed(UnencryptedWhenPassthroughDisabled)`가 반복해서 표시되면, 이는 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419)에서 추적 중인 업스트림 `@discordjs/voice` 수신 버그일 수 있습니다. ## 음성 메시지 -Discord 음성 메시지는 파형 미리보기를 표시하며 OGG/Opus 오디오와 메타데이터가 필요합니다. OpenClaw는 파형을 자동 생성하지만, 오디오 파일을 검사하고 변환하려면 gateway 호스트에서 `ffmpeg`와 `ffprobe`를 사용할 수 있어야 합니다. +Discord 음성 메시지는 파형 미리보기를 표시하며 OGG/Opus 오디오와 메타데이터가 필요합니다. OpenClaw는 파형을 자동 생성하지만, 오디오 파일을 검사하고 변환하려면 게이트웨이 호스트에서 `ffmpeg`와 `ffprobe`를 사용할 수 있어야 합니다. 요구 사항 및 제약: - **로컬 파일 경로**를 제공해야 합니다(URL은 거부됨). -- 텍스트 콘텐츠는 생략해야 합니다(Discord는 동일 payload에서 텍스트 + 음성 메시지를 허용하지 않음). -- 어떤 오디오 형식이든 허용되며, 필요하면 OpenClaw가 OGG/Opus로 변환합니다. +- 텍스트 콘텐츠는 생략해야 합니다(Discord는 동일한 페이로드에서 텍스트 + 음성 메시지를 허용하지 않음). +- 어떤 오디오 형식이든 허용되며, 필요할 경우 OpenClaw가 OGG/Opus로 변환합니다. 예시: @@ -1106,19 +1114,19 @@ message(action="send", channel="discord", target="channel:123", path="/path/to/a - Message Content Intent 활성화 - - 사용자/멤버 확인에 의존한다면 Server Members Intent 활성화 - - 인텐트 변경 후 gateway 재시작 + - 사용자/멤버 해석에 의존하는 경우 Server Members Intent 활성화 + - 인텐트를 변경한 뒤 게이트웨이 재시작 - + - `groupPolicy` 확인 - - `channels.discord.guilds` 아래 길드 허용 목록 확인 - - 길드 `channels` 맵이 존재하면 목록에 있는 채널만 허용됨 - - `requireMention` 동작 및 멘션 패턴 확인 + - `channels.discord.guilds` 아래의 길드 allowlist 확인 + - 길드 `channels` 맵이 있으면 목록에 있는 채널만 허용됨 + - `requireMention` 동작과 멘션 패턴 확인 - 유용한 확인 명령: + 유용한 점검: ```bash openclaw doctor @@ -1131,9 +1139,9 @@ openclaw logs --follow 일반적인 원인: - - 일치하는 길드/채널 허용 목록 없이 `groupPolicy="allowlist"` 사용 - - `requireMention`이 잘못된 위치에 구성됨(`channels.discord.guilds` 또는 채널 항목 아래에 있어야 함) - - 발신자가 길드/채널 `users` 허용 목록에 의해 차단됨 + - 일치하는 길드/채널 allowlist 없이 `groupPolicy="allowlist"` 설정 + - `requireMention`이 잘못된 위치에 구성됨(`channels.discord.guilds` 또는 채널 항목 아래여야 함) + - 발신자가 길드/채널 `users` allowlist에 의해 차단됨 @@ -1145,16 +1153,16 @@ openclaw logs --follow - `Slow listener detected ...` - `discord inbound worker timed out after ...` - Listener 예산 조정 값: + 리스너 예산 설정: - 단일 계정: `channels.discord.eventQueue.listenerTimeout` - - 멀티 계정: `channels.discord.accounts..eventQueue.listenerTimeout` + - 다중 계정: `channels.discord.accounts..eventQueue.listenerTimeout` - Worker 실행 시간 초과 조정 값: + 워커 실행 시간 초과 설정: - 단일 계정: `channels.discord.inboundWorker.runTimeoutMs` - - 멀티 계정: `channels.discord.accounts..inboundWorker.runTimeoutMs` - - 기본값: `1800000` (30분); 비활성화하려면 `0`으로 설정 + - 다중 계정: `channels.discord.accounts..inboundWorker.runTimeoutMs` + - 기본값: `1800000` (30분), 비활성화하려면 `0` 설정 권장 기준값: @@ -1177,12 +1185,13 @@ openclaw logs --follow } ``` - 느린 listener 설정에는 `eventQueue.listenerTimeout`을 사용하고, 대기열에 들어간 에이전트 턴에 별도의 안전장치를 두고 싶을 때만 `inboundWorker.runTimeoutMs`를 사용하세요. + 느린 리스너 설정에는 `eventQueue.listenerTimeout`을 사용하고, `inboundWorker.runTimeoutMs`는 + 큐에 들어간 에이전트 턴에 대해 별도의 안전 장치가 필요할 때만 사용하세요. - `channels status --probe` 권한 검사는 숫자 채널 ID에서만 작동합니다. + `channels status --probe` 권한 확인은 숫자 채널 ID에 대해서만 동작합니다. slug 키를 사용하면 런타임 매칭은 여전히 작동할 수 있지만, probe는 권한을 완전히 검증할 수 없습니다. @@ -1199,20 +1208,20 @@ openclaw logs --follow 기본적으로 봇이 작성한 메시지는 무시됩니다. - `channels.discord.allowBots=true`로 설정한 경우, 루프 동작을 피하려면 엄격한 멘션 및 허용 목록 규칙을 사용하세요. - 봇을 멘션하는 봇 메시지만 허용하려면 `channels.discord.allowBots="mentions"`를 권장합니다. + `channels.discord.allowBots=true`를 설정하는 경우, 루프 동작을 피하려면 엄격한 멘션 및 allowlist 규칙을 사용하세요. + 봇을 멘션한 봇 메시지만 허용하려면 `channels.discord.allowBots="mentions"`를 권장합니다. - - Discord 음성 수신 복구 로직이 포함되도록 OpenClaw를 최신 상태로 유지하세요(`openclaw update`) - - `channels.discord.voice.daveEncryption=true`인지 확인하세요(기본값) - - `channels.discord.voice.decryptionFailureTolerance=24`(상위 기본값)에서 시작하고 필요한 경우에만 조정하세요 - - 로그에서 다음을 확인하세요. + - Discord 음성 수신 복구 로직이 포함되도록 OpenClaw를 최신 상태로 유지하세요(`openclaw update`). + - `channels.discord.voice.daveEncryption=true`인지 확인하세요(기본값). + - `channels.discord.voice.decryptionFailureTolerance=24`(업스트림 기본값)부터 시작하고 필요할 때만 조정하세요. + - 다음 로그를 확인하세요. - `discord voice: DAVE decrypt failures detected` - `discord voice: repeated decrypt failures; attempting rejoin` - - 자동 재참여 후에도 실패가 계속되면 로그를 수집하고 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419)와 비교하세요 + - 자동 재참여 후에도 실패가 계속되면 로그를 수집하고 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419)와 비교하세요. @@ -1223,35 +1232,35 @@ openclaw logs --follow - [Configuration reference - Discord](/ko/gateway/configuration-reference#discord) -신호가 강한 Discord 필드: +신호 가치가 높은 Discord 필드: - 시작/인증: `enabled`, `token`, `accounts.*`, `allowBots` - 정책: `groupPolicy`, `dm.*`, `guilds.*`, `guilds.*.channels.*` - 명령: `commands.native`, `commands.useAccessGroups`, `configWrites`, `slashCommand.*` -- 이벤트 큐: `eventQueue.listenerTimeout` (listener 예산), `eventQueue.maxQueueSize`, `eventQueue.maxConcurrency` -- 인바운드 worker: `inboundWorker.runTimeoutMs` -- 응답/히스토리: `replyToMode`, `historyLimit`, `dmHistoryLimit`, `dms.*.historyLimit` +- 이벤트 큐: `eventQueue.listenerTimeout`(리스너 예산), `eventQueue.maxQueueSize`, `eventQueue.maxConcurrency` +- 인바운드 워커: `inboundWorker.runTimeoutMs` +- 응답/기록: `replyToMode`, `historyLimit`, `dmHistoryLimit`, `dms.*.historyLimit` - 전달: `textChunkLimit`, `chunkMode`, `maxLinesPerMessage` -- 스트리밍: `streaming` (레거시 별칭: `streamMode`), `draftChunk`, `blockStreaming`, `blockStreamingCoalesce` +- 스트리밍: `streaming`(레거시 별칭: `streamMode`), `draftChunk`, `blockStreaming`, `blockStreamingCoalesce` - 미디어/재시도: `mediaMaxMb`, `retry` - `mediaMaxMb`는 아웃바운드 Discord 업로드를 제한합니다(기본값: `100MB`) -- 작업: `actions.*` +- 액션: `actions.*` - 프레즌스: `activity`, `status`, `activityType`, `activityUrl` - UI: `ui.components.accentColor` -- 기능: `threadBindings`, 최상위 `bindings[]` (`type: "acp"`), `pluralkit`, `execApprovals`, `intents`, `agentComponents`, `heartbeat`, `responsePrefix` +- 기능: `threadBindings`, 최상위 `bindings[]`(`type: "acp"`), `pluralkit`, `execApprovals`, `intents`, `agentComponents`, `heartbeat`, `responsePrefix` ## 안전 및 운영 -- 봇 토큰은 비밀로 취급하세요(관리 환경에서는 `DISCORD_BOT_TOKEN` 권장). +- 봇 토큰은 비밀 정보로 취급하세요(관리 환경에서는 `DISCORD_BOT_TOKEN` 권장). - Discord 권한은 최소 권한 원칙으로 부여하세요. -- 명령 배포/상태가 오래되었으면 gateway를 재시작하고 `openclaw channels status --probe`로 다시 확인하세요. +- 명령 배포/상태가 오래되었다면 게이트웨이를 재시작하고 `openclaw channels status --probe`로 다시 확인하세요. -## 관련 문서 +## 관련 항목 -- [Pairing](/ko/channels/pairing) -- [Groups](/ko/channels/groups) -- [Channel routing](/ko/channels/channel-routing) -- [Security](/ko/gateway/security) -- [Multi-agent routing](/ko/concepts/multi-agent) -- [Troubleshooting](/ko/channels/troubleshooting) -- [Slash commands](/ko/tools/slash-commands) +- [페어링](/ko/channels/pairing) +- [그룹](/ko/channels/groups) +- [채널 라우팅](/ko/channels/channel-routing) +- [보안](/ko/gateway/security) +- [다중 에이전트 라우팅](/ko/concepts/multi-agent) +- [문제 해결](/ko/channels/troubleshooting) +- [슬래시 명령어](/ko/tools/slash-commands) diff --git a/docs/ko/channels/matrix.md b/docs/ko/channels/matrix.md index 4c5c43511..4b6049206 100644 --- a/docs/ko/channels/matrix.md +++ b/docs/ko/channels/matrix.md @@ -5,24 +5,24 @@ read_when: summary: Matrix 지원 상태, 설정, 및 구성 예제 title: Matrix x-i18n: - generated_at: "2026-04-08T02:16:35Z" + generated_at: "2026-04-09T01:30:07Z" model: gpt-5.4 provider: openai - source_hash: ec926df79a41fa296d63f0ec7219d0f32e075628d76df9ea490e93e4c5030f83 + source_hash: 28fc13c7620c1152200315ae69c94205da6de3180c53c814dd8ce03b5cb1758f source_path: channels/matrix.md workflow: 15 --- # Matrix -Matrix는 OpenClaw용 Matrix 번들 채널 plugin입니다. -공식 `matrix-js-sdk`를 사용하며 DM, 룸, 스레드, 미디어, 반응, 투표, 위치, E2EE를 지원합니다. +Matrix는 OpenClaw에 번들로 포함된 채널 plugin입니다. +공식 `matrix-js-sdk`를 사용하며 DM, room, 스레드, 미디어, 반응, 투표, 위치, E2EE를 지원합니다. ## 번들 plugin -Matrix는 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 제공되므로, 일반적인 패키지 빌드에서는 별도 설치가 필요하지 않습니다. +Matrix는 현재 OpenClaw 릴리스에 번들 plugin으로 포함되어 제공되므로 일반적인 패키지 빌드에서는 별도 설치가 필요하지 않습니다. -이전 빌드 또는 Matrix가 제외된 사용자 지정 설치를 사용 중이라면 수동으로 설치하세요: +이전 빌드나 Matrix가 제외된 사용자 지정 설치를 사용하는 경우 수동으로 설치하세요: npm에서 설치: @@ -36,20 +36,20 @@ openclaw plugins install @openclaw/matrix openclaw plugins install ./path/to/local/matrix-plugin ``` -plugin 동작 및 설치 규칙은 [Plugins](/ko/tools/plugin)에서 확인하세요. +plugin 동작과 설치 규칙은 [Plugins](/ko/tools/plugin)를 참조하세요. ## 설정 1. Matrix plugin을 사용할 수 있는지 확인합니다. - - 현재 패키지된 OpenClaw 릴리스에는 이미 포함되어 있습니다. + - 현재 패키지된 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다. - 이전/사용자 지정 설치에서는 위 명령으로 수동 추가할 수 있습니다. 2. 홈서버에서 Matrix 계정을 만듭니다. 3. `channels.matrix`를 다음 중 하나로 구성합니다: - `homeserver` + `accessToken`, 또는 - `homeserver` + `userId` + `password`. -4. 게이트웨이를 다시 시작합니다. -5. 봇과 DM을 시작하거나 룸에 초대합니다. - - 새 Matrix 초대는 `channels.matrix.autoJoin`이 허용할 때만 작동합니다. +4. gateway를 재시작합니다. +5. 봇과 DM을 시작하거나 room에 초대합니다. + - 새 Matrix 초대는 `channels.matrix.autoJoin`이 허용하는 경우에만 동작합니다. 대화형 설정 경로: @@ -58,39 +58,35 @@ openclaw channels add openclaw configure --section channels ``` -Matrix 마법사가 실제로 묻는 항목: +Matrix 마법사는 다음을 묻습니다: -- 홈서버 URL -- 인증 방식: 액세스 토큰 또는 비밀번호 -- 비밀번호 인증을 선택한 경우에만 사용자 ID -- 선택 사항인 디바이스 이름 +- homeserver URL +- 인증 방식: access token 또는 password +- 사용자 ID (password 인증만) +- 선택적 device 이름 - E2EE 활성화 여부 -- 지금 Matrix 룸 접근을 구성할지 여부 -- 지금 Matrix 초대 자동 참여를 구성할지 여부 -- 초대 자동 참여를 활성화한 경우, `allowlist`, `always`, `off` 중 무엇으로 설정할지 여부 +- room 접근과 초대 자동 참여를 구성할지 여부 -알아두어야 할 마법사 동작: +마법사의 주요 동작: -- 선택한 계정에 대해 Matrix 인증 환경 변수가 이미 존재하고, 해당 계정의 인증이 아직 config에 저장되어 있지 않다면, 마법사는 환경 변수 바로가기를 제안하여 비밀 값을 config에 복사하지 않고 환경 변수에 유지한 채로 설정을 진행할 수 있게 합니다. -- 다른 Matrix 계정을 대화형으로 추가할 때, 입력한 계정 이름은 config와 환경 변수에서 사용하는 계정 ID로 정규화됩니다. 예를 들어 `Ops Bot`은 `ops-bot`이 됩니다. -- DM allowlist 프롬프트는 전체 `@user:server` 값을 즉시 받을 수 있습니다. 표시 이름은 라이브 디렉터리 조회에서 정확히 하나의 일치 항목을 찾았을 때만 작동하며, 그렇지 않으면 마법사가 전체 Matrix ID로 다시 시도하라고 요청합니다. -- 룸 allowlist 프롬프트는 룸 ID와 별칭을 직접 받을 수 있습니다. 현재 참여 중인 룸 이름도 라이브로 확인할 수 있지만, 확인되지 않은 이름은 설정 중 입력된 그대로만 유지되며 이후 런타임 allowlist 확인에서는 무시됩니다. `!room:server` 또는 `#alias:server`를 사용하는 것이 좋습니다. -- `channels.matrix.autoJoin`의 기본값이 `off`이므로, 마법사는 이제 초대 자동 참여 단계 전에 명시적 경고를 표시합니다. 이를 설정하지 않으면 에이전트는 초대된 룸이나 새 DM 스타일 초대에 참여하지 않습니다. -- 초대 자동 참여 allowlist 모드에서는 안정적인 초대 대상만 사용하세요: `!roomId:server`, `#alias:server`, 또는 `*`. 일반 룸 이름은 거부됩니다. -- 런타임 룸/세션 식별에는 안정적인 Matrix 룸 ID를 사용합니다. 룸에 선언된 별칭은 장기 세션 키나 안정적인 그룹 식별자가 아니라 조회 입력에만 사용됩니다. -- 저장 전에 룸 이름을 확인하려면 `openclaw channels resolve --channel matrix "Project Room"`을 사용하세요. +- Matrix 인증 env var가 이미 존재하고 해당 계정에 config에 저장된 인증이 아직 없으면, 마법사는 인증을 env var에 유지하는 env 바로가기를 제안합니다. +- 계정 이름은 계정 ID로 정규화됩니다. 예를 들어 `Ops Bot`은 `ops-bot`이 됩니다. +- DM 허용 목록 항목은 `@user:server`를 직접 받을 수 있습니다. 표시 이름은 라이브 디렉터리 조회에서 정확히 하나의 일치 항목을 찾을 때만 동작합니다. +- Room 허용 목록 항목은 room ID와 alias를 직접 받을 수 있습니다. `!room:server` 또는 `#alias:server`를 권장하며, 해석되지 않은 이름은 허용 목록 해석 시 런타임에서 무시됩니다. +- 초대 자동 참여 허용 목록 모드에서는 안정적인 초대 대상만 사용하세요: `!roomId:server`, `#alias:server`, 또는 `*`. 일반 room 이름은 거부됩니다. +- 저장 전에 room 이름을 해석하려면 `openclaw channels resolve --channel matrix "Project Room"`를 사용하세요. `channels.matrix.autoJoin`의 기본값은 `off`입니다. -설정하지 않으면 봇은 초대된 룸이나 새 DM 스타일 초대에 참여하지 않으므로, 먼저 수동으로 참여하지 않는 한 새 그룹이나 초대된 DM에 나타나지 않습니다. +설정하지 않으면 봇은 초대된 room이나 새로운 DM 스타일 초대에 참여하지 않으므로, 먼저 수동으로 참여하지 않는 한 새 그룹이나 초대된 DM에 나타나지 않습니다. -허용할 초대를 제한하려면 `autoJoin: "allowlist"`와 함께 `autoJoinAllowlist`를 설정하거나, 모든 초대에 참여하려면 `autoJoin: "always"`를 설정하세요. +수락할 초대를 제한하려면 `autoJoinAllowlist`와 함께 `autoJoin: "allowlist"`를 설정하거나, 모든 초대에 참여하게 하려면 `autoJoin: "always"`를 설정하세요. `allowlist` 모드에서 `autoJoinAllowlist`는 `!roomId:server`, `#alias:server`, 또는 `*`만 허용합니다. -Allowlist 예제: +허용 목록 예제: ```json5 { @@ -120,7 +116,7 @@ Allowlist 예제: } ``` -최소 토큰 기반 설정: +최소 token 기반 설정: ```json5 { @@ -135,7 +131,7 @@ Allowlist 예제: } ``` -비밀번호 기반 설정(로그인 후 토큰이 캐시됨): +password 기반 설정 (로그인 후 token이 캐시됨): ```json5 { @@ -152,10 +148,10 @@ Allowlist 예제: ``` Matrix는 캐시된 자격 증명을 `~/.openclaw/credentials/matrix/`에 저장합니다. -기본 계정은 `credentials.json`을 사용하고, 이름 있는 계정은 `credentials-.json`을 사용합니다. -해당 위치에 캐시된 자격 증명이 있으면, 현재 인증이 config에 직접 설정되어 있지 않더라도 OpenClaw는 설정, doctor, 채널 상태 검색에서 Matrix가 구성된 것으로 간주합니다. +기본 계정은 `credentials.json`을 사용하고, 이름이 있는 계정은 `credentials-.json`을 사용합니다. +그 위치에 캐시된 자격 증명이 있으면 현재 인증이 config에 직접 설정되어 있지 않더라도 OpenClaw는 설정, doctor, 채널 상태 검색에서 Matrix를 구성된 것으로 취급합니다. -환경 변수 대응 항목(config 키가 설정되지 않은 경우 사용됨): +환경 변수 대응 항목(설정 키가 지정되지 않은 경우 사용됨): - `MATRIX_HOMESERVER` - `MATRIX_ACCESS_TOKEN` @@ -164,7 +160,7 @@ Matrix는 캐시된 자격 증명을 `~/.openclaw/credentials/matrix/`에 저장 - `MATRIX_DEVICE_ID` - `MATRIX_DEVICE_NAME` -기본이 아닌 계정의 경우, 계정 범위 환경 변수를 사용하세요: +기본이 아닌 계정의 경우 계정 범위 env var를 사용하세요: - `MATRIX__HOMESERVER` - `MATRIX__ACCESS_TOKEN` @@ -178,19 +174,19 @@ Matrix는 캐시된 자격 증명을 `~/.openclaw/credentials/matrix/`에 저장 - `MATRIX_OPS_HOMESERVER` - `MATRIX_OPS_ACCESS_TOKEN` -정규화된 계정 ID `ops-bot`의 경우 사용 항목: +정규화된 계정 ID `ops-bot`의 경우 다음을 사용합니다: - `MATRIX_OPS_X2D_BOT_HOMESERVER` - `MATRIX_OPS_X2D_BOT_ACCESS_TOKEN` -Matrix는 계정 ID의 구두점을 이스케이프하여 범위 지정 환경 변수 간 충돌이 없도록 합니다. -예를 들어 `-`는 `_X2D_`가 되므로, `ops-prod`는 `MATRIX_OPS_X2D_PROD_*`에 매핑됩니다. +Matrix는 계정 ID의 구두점을 이스케이프하여 범위 지정된 env var 간 충돌이 없도록 합니다. +예를 들어 `-`는 `_X2D_`가 되므로 `ops-prod`는 `MATRIX_OPS_X2D_PROD_*`에 매핑됩니다. -대화형 마법사는 해당 인증 환경 변수가 이미 존재하고 선택한 계정에 Matrix 인증이 아직 config에 저장되어 있지 않을 때만 환경 변수 바로가기를 제안합니다. +대화형 마법사는 해당 인증 env var가 이미 존재하고 선택한 계정에 Matrix 인증이 config에 아직 저장되어 있지 않은 경우에만 env-var 바로가기를 제안합니다. ## 구성 예제 -다음은 DM 페어링, 룸 allowlist, E2EE 활성화를 포함한 실용적인 기준 config입니다: +다음은 DM 페어링, room 허용 목록, E2EE 활성화를 포함한 실용적인 기준 구성입니다: ```json5 { @@ -225,20 +221,13 @@ Matrix는 계정 ID의 구두점을 이스케이프하여 범위 지정 환경 } ``` -`autoJoin`은 룸/그룹 초대뿐 아니라 일반적인 Matrix 초대에 적용됩니다. -여기에는 새 DM 스타일 초대도 포함됩니다. 초대 시점에는 OpenClaw가 -초대된 룸이 최종적으로 DM으로 처리될지 그룹으로 처리될지 신뢰성 있게 알 수 없으므로, 모든 초대는 -먼저 동일한 `autoJoin` 판단을 거칩니다. 봇이 참여한 후 룸이 -DM으로 분류되면 `dm.policy`가 여전히 적용되므로, `autoJoin`은 참여 동작을 제어하고 `dm.policy`는 응답/접근 -동작을 제어합니다. +`autoJoin`은 DM 스타일 초대를 포함한 모든 Matrix 초대에 적용됩니다. OpenClaw는 초대 시점에 초대된 room이 DM인지 그룹인지 신뢰성 있게 분류할 수 없으므로, 모든 초대는 먼저 `autoJoin`을 거칩니다. `dm.policy`는 봇이 참여한 뒤 room이 DM으로 분류된 후에 적용됩니다. ## 스트리밍 미리보기 -Matrix 응답 스트리밍은 옵트인입니다. +Matrix 답변 스트리밍은 옵트인입니다. -OpenClaw가 하나의 라이브 미리보기 응답을 보내고, -모델이 텍스트를 생성하는 동안 그 미리보기를 제자리에서 수정한 뒤, -응답이 완료되면 마무리하도록 하려면 `channels.matrix.streaming`을 `"partial"`로 설정하세요: +OpenClaw가 하나의 라이브 미리보기 답변을 보내고, 모델이 텍스트를 생성하는 동안 그 미리보기를 제자리에서 편집한 다음, 답변이 완료되면 최종 확정하도록 하려면 `channels.matrix.streaming`을 `"partial"`로 설정하세요: ```json5 { @@ -250,36 +239,35 @@ OpenClaw가 하나의 라이브 미리보기 응답을 보내고, } ``` -- `streaming: "off"`가 기본값입니다. OpenClaw는 최종 응답을 기다렸다가 한 번만 전송합니다. -- `streaming: "partial"`은 현재 assistant 블록에 대해 일반 Matrix 텍스트 메시지를 사용한 수정 가능한 미리보기 메시지 하나를 만듭니다. 이는 Matrix의 기존 미리보기 우선 알림 동작을 유지하므로, 기본 클라이언트는 완료된 블록 대신 첫 번째 스트리밍 미리보기 텍스트에 대해 알림을 보낼 수 있습니다. -- `streaming: "quiet"`은 현재 assistant 블록에 대해 수정 가능한 조용한 미리보기 알림 하나를 만듭니다. 최종 미리보기 수정에 대한 수신자 푸시 규칙도 함께 구성하는 경우에만 사용하세요. -- `blockStreaming: true`는 별도의 Matrix 진행 메시지를 활성화합니다. 미리보기 스트리밍이 활성화된 경우, Matrix는 현재 블록의 라이브 초안을 유지하면서 완료된 블록은 별도 메시지로 보존합니다. -- 미리보기 스트리밍이 켜져 있고 `blockStreaming`이 꺼져 있으면, Matrix는 라이브 초안을 제자리에서 수정하고 블록 또는 턴이 끝날 때 같은 이벤트를 마무리합니다. -- 미리보기가 더 이상 하나의 Matrix 이벤트에 들어가지 않으면, OpenClaw는 미리보기 스트리밍을 중단하고 일반 최종 전송으로 대체합니다. -- 미디어 응답은 여전히 첨부 파일을 일반 방식으로 전송합니다. 오래된 미리보기를 더 이상 안전하게 재사용할 수 없으면, OpenClaw는 최종 미디어 응답을 보내기 전에 이를 redact합니다. -- 미리보기 수정은 추가 Matrix API 호출 비용이 듭니다. 가장 보수적인 rate limit 동작을 원한다면 스트리밍을 꺼 두세요. +- `streaming: "off"`가 기본값입니다. OpenClaw는 최종 답변을 기다렸다가 한 번만 전송합니다. +- `streaming: "partial"`은 현재 assistant 블록에 대해 편집 가능한 미리보기 메시지 하나를 일반 Matrix 텍스트 메시지로 생성합니다. 이는 Matrix의 기존 미리보기 우선 알림 동작을 유지하므로, 기본 클라이언트에서는 완성된 블록 대신 첫 번째 스트리밍 미리보기 텍스트에 대해 알림이 올 수 있습니다. +- `streaming: "quiet"`는 현재 assistant 블록에 대해 편집 가능한 조용한 미리보기 알림 하나를 생성합니다. 최종 확정된 미리보기 편집에 대한 수신자 푸시 규칙도 함께 구성하는 경우에만 이것을 사용하세요. +- `blockStreaming: true`는 별도의 Matrix 진행 상황 메시지를 활성화합니다. 미리보기 스트리밍이 활성화된 상태에서는 Matrix가 현재 블록의 라이브 초안을 유지하고 완료된 블록은 별도 메시지로 보존합니다. +- 미리보기 스트리밍이 켜져 있고 `blockStreaming`이 꺼져 있으면, Matrix는 라이브 초안을 제자리에서 편집하고 블록 또는 턴이 끝나면 같은 이벤트를 최종 확정합니다. +- 미리보기가 더 이상 하나의 Matrix 이벤트에 맞지 않으면 OpenClaw는 미리보기 스트리밍을 중단하고 일반 최종 전달로 대체합니다. +- 미디어 답변은 여전히 첨부 파일을 정상적으로 전송합니다. 오래된 미리보기를 더 이상 안전하게 재사용할 수 없으면 OpenClaw는 최종 미디어 답변을 보내기 전에 그것을 redact합니다. +- 미리보기 편집은 추가 Matrix API 호출 비용이 듭니다. 가장 보수적인 rate limit 동작을 원한다면 스트리밍을 꺼두세요. `blockStreaming`만으로는 초안 미리보기가 활성화되지 않습니다. -미리보기 수정에는 `streaming: "partial"` 또는 `streaming: "quiet"`을 사용하고, 완료된 assistant 블록도 별도의 진행 메시지로 유지하려는 경우에만 `blockStreaming: true`를 추가하세요. +미리보기 편집에는 `streaming: "partial"` 또는 `streaming: "quiet"`를 사용하고, 완료된 assistant 블록도 별도의 진행 상황 메시지로 남기고 싶을 때만 `blockStreaming: true`를 추가하세요. -사용자 지정 푸시 규칙 없이 기본 Matrix 알림이 필요하다면, 미리보기 우선 동작에는 `streaming: "partial"`을 사용하거나 최종 응답만 전송하려면 `streaming`을 꺼 두세요. `streaming: "off"`인 경우: +사용자 지정 푸시 규칙 없이 기본 Matrix 알림이 필요하면 미리보기 우선 동작을 위해 `streaming: "partial"`을 사용하거나, 최종 결과만 전달하려면 `streaming`을 꺼두세요. `streaming: "off"`일 때: -- `blockStreaming: true`는 완료된 각 블록을 일반 알림 Matrix 메시지로 전송합니다. -- `blockStreaming: false`는 최종 완료 응답만 일반 알림 Matrix 메시지로 전송합니다. +- `blockStreaming: true`는 각 완료된 블록을 일반적인 알림 Matrix 메시지로 보냅니다. +- `blockStreaming: false`는 최종 완료된 답변만 일반적인 알림 Matrix 메시지로 보냅니다. -### 조용한 최종 미리보기를 위한 자체 호스팅 푸시 규칙 +### 조용한 최종 확정 미리보기를 위한 자체 호스팅 푸시 규칙 -자체 Matrix 인프라를 운영하면서 블록 또는 -최종 응답이 완료되었을 때만 조용한 미리보기가 알림을 보내도록 하려면, `streaming: "quiet"`을 설정하고 최종 미리보기 수정에 대한 사용자별 푸시 규칙을 추가하세요. +자체 Matrix 인프라를 운영하며 블록 또는 최종 답변이 완료되었을 때만 조용한 미리보기에 알림이 가도록 하려면 `streaming: "quiet"`를 설정하고 최종 확정된 미리보기 편집에 대한 사용자별 푸시 규칙을 추가하세요. -이 설정은 일반적으로 홈서버 전체 config 변경이 아니라 수신 사용자 설정입니다: +이는 보통 homeserver 전역 config 변경이 아니라 수신자 사용자 설정입니다: 시작 전 빠른 개요: -- 수신 사용자 = 알림을 받아야 하는 사람 -- 봇 사용자 = 응답을 보내는 OpenClaw Matrix 계정 -- 아래 API 호출에는 수신 사용자의 액세스 토큰을 사용 -- 푸시 규칙의 `sender`는 봇 사용자의 전체 MXID와 일치해야 함 +- 수신자 사용자 = 알림을 받아야 하는 사람 +- 봇 사용자 = 답변을 보내는 OpenClaw Matrix 계정 +- 아래 API 호출에는 수신자 사용자의 access token을 사용 +- 푸시 규칙의 `sender`는 봇 사용자의 전체 MXID와 일치시킴 1. OpenClaw가 조용한 미리보기를 사용하도록 구성합니다: @@ -293,13 +281,12 @@ OpenClaw가 하나의 라이브 미리보기 응답을 보내고, } ``` -2. 수신 계정이 이미 일반 Matrix 푸시 알림을 받고 있는지 확인합니다. 조용한 미리보기 - 규칙은 해당 사용자에게 이미 작동 중인 pusher/디바이스가 있을 때만 동작합니다. +2. 수신자 계정이 이미 일반 Matrix 푸시 알림을 받고 있는지 확인합니다. 조용한 미리보기 규칙은 해당 사용자에게 이미 작동하는 pusher/device가 있을 때만 동작합니다. -3. 수신 사용자의 액세스 토큰을 가져옵니다. - - 봇의 토큰이 아니라 수신 사용자의 토큰을 사용하세요. - - 기존 클라이언트 세션 토큰을 재사용하는 것이 보통 가장 쉽습니다. - - 새 토큰을 발급해야 한다면, 표준 Matrix Client-Server API를 통해 로그인할 수 있습니다: +3. 수신자 사용자의 access token을 가져옵니다. + - 봇의 token이 아니라 수신 사용자 token을 사용하세요. + - 기존 클라이언트 세션 token을 재사용하는 것이 보통 가장 쉽습니다. + - 새 token을 발급해야 하면 표준 Matrix Client-Server API를 통해 로그인할 수 있습니다: ```bash curl -sS -X POST \ @@ -315,7 +302,7 @@ curl -sS -X POST \ }' ``` -4. 수신 계정에 이미 pusher가 있는지 확인합니다: +4. 수신자 계정에 이미 pusher가 있는지 확인합니다: ```bash curl -sS \ @@ -323,10 +310,9 @@ curl -sS \ "https://matrix.example.org/_matrix/client/v3/pushers" ``` -활성 pusher/디바이스가 반환되지 않으면, 아래 -OpenClaw 규칙을 추가하기 전에 먼저 일반 Matrix 알림을 수정하세요. +활성 pusher/device가 하나도 반환되지 않으면, 아래 OpenClaw 규칙을 추가하기 전에 먼저 일반 Matrix 알림부터 수정하세요. -OpenClaw는 최종 텍스트 전용 미리보기 수정에 다음 표시를 추가합니다: +OpenClaw는 최종 확정된 텍스트 전용 미리보기 편집에 다음 표시를 추가합니다: ```json { @@ -334,7 +320,7 @@ OpenClaw는 최종 텍스트 전용 미리보기 수정에 다음 표시를 추 } ``` -5. 이러한 알림을 받아야 하는 각 수신 계정에 대해 override 푸시 규칙을 만듭니다: +5. 이러한 알림을 받아야 하는 각 수신자 계정에 대해 override 푸시 규칙을 생성합니다: ```bash curl -sS -X PUT \ @@ -366,20 +352,20 @@ curl -sS -X PUT \ 명령을 실행하기 전에 다음 값을 바꾸세요: -- `https://matrix.example.org`: 홈서버 기본 URL -- `$USER_ACCESS_TOKEN`: 수신 사용자의 액세스 토큰 -- `openclaw-finalized-preview-botname`: 이 수신 사용자에 대해 이 봇에 고유한 규칙 ID -- `@bot:example.org`: 수신 사용자의 MXID가 아니라 OpenClaw Matrix 봇 MXID +- `https://matrix.example.org`: homeserver 기본 URL +- `$USER_ACCESS_TOKEN`: 수신 사용자 access token +- `openclaw-finalized-preview-botname`: 이 수신 사용자에 대한 이 봇 전용 고유한 rule ID +- `@bot:example.org`: 수신 사용자 MXID가 아니라 OpenClaw Matrix 봇 MXID -다중 봇 설정에서 중요: +여러 봇을 사용하는 구성에서 중요 사항: -- 푸시 규칙은 `ruleId`를 기준으로 키가 지정됩니다. 같은 규칙 ID에 대해 `PUT`을 다시 실행하면 해당 규칙 하나가 갱신됩니다. -- 한 수신 사용자가 여러 OpenClaw Matrix 봇 계정에 대해 알림을 받아야 한다면, 각 sender 일치 항목마다 고유한 규칙 ID를 사용해 봇별로 하나의 규칙을 만드세요. -- 간단한 패턴은 `openclaw-finalized-preview-`이며, 예를 들어 `openclaw-finalized-preview-ops` 또는 `openclaw-finalized-preview-support`가 있습니다. +- 푸시 규칙은 `ruleId`를 키로 사용합니다. 같은 rule ID에 대해 `PUT`을 다시 실행하면 해당 규칙 하나가 업데이트됩니다. +- 한 수신 사용자가 여러 OpenClaw Matrix 봇 계정에 대해 알림을 받아야 한다면, 각 sender 일치 항목마다 고유한 rule ID로 봇당 하나의 규칙을 생성하세요. +- 간단한 패턴은 `openclaw-finalized-preview-`이며, 예를 들어 `openclaw-finalized-preview-ops` 또는 `openclaw-finalized-preview-support`처럼 사용할 수 있습니다. -이 규칙은 이벤트 발신자를 기준으로 평가됩니다: +규칙은 이벤트 sender를 기준으로 평가됩니다: -- 수신 사용자의 토큰으로 인증 +- 수신 사용자 token으로 인증 - `sender`를 OpenClaw 봇 MXID와 일치시킴 6. 규칙이 존재하는지 확인합니다: @@ -390,10 +376,9 @@ curl -sS \ "https://matrix.example.org/_matrix/client/v3/pushrules/global/override/openclaw-finalized-preview-botname" ``` -7. 스트리밍 응답을 테스트합니다. 조용한 모드에서는 룸에 조용한 초안 미리보기가 표시되고, - 블록 또는 턴이 끝나면 최종 제자리 수정이 한 번 알림을 보내야 합니다. +7. 스트리밍 답변을 테스트합니다. 조용한 모드에서는 room에 조용한 초안 미리보기가 표시되어야 하며, 블록이나 턴이 끝나면 제자리 최종 편집에 대해 한 번 알림이 와야 합니다. -나중에 규칙을 제거해야 한다면, 수신 사용자의 토큰으로 같은 규칙 ID를 삭제하세요: +나중에 규칙을 제거해야 하면 같은 수신 사용자 token으로 동일한 rule ID를 삭제하세요: ```bash curl -sS -X DELETE \ @@ -403,37 +388,33 @@ curl -sS -X DELETE \ 참고: -- 규칙은 봇 토큰이 아니라 수신 사용자의 액세스 토큰으로 만드세요. -- 새 사용자 정의 `override` 규칙은 기본 suppress 규칙보다 앞에 삽입되므로 추가 순서 지정 매개변수는 필요하지 않습니다. -- 이는 OpenClaw가 안전하게 제자리에서 마무리할 수 있는 텍스트 전용 미리보기 수정에만 영향을 줍니다. 미디어 대체 전송과 오래된 미리보기 대체 전송은 여전히 일반 Matrix 전송을 사용합니다. -- `GET /_matrix/client/v3/pushers`에서 pusher가 표시되지 않으면, 해당 사용자는 아직 이 계정/디바이스에 대해 정상적인 Matrix 푸시 전송이 작동하지 않는 상태입니다. +- 규칙은 봇 token이 아니라 수신 사용자 access token으로 생성하세요. +- 새 사용자 정의 `override` 규칙은 기본 억제 규칙보다 앞에 삽입되므로 추가 순서 지정 매개변수는 필요하지 않습니다. +- 이는 OpenClaw가 안전하게 제자리 확정할 수 있는 텍스트 전용 미리보기 편집에만 영향을 줍니다. 미디어 대체와 오래된 미리보기 대체는 여전히 일반 Matrix 전달을 사용합니다. +- `GET /_matrix/client/v3/pushers`에 pusher가 없으면, 해당 사용자는 아직 이 계정/device에 대해 작동하는 Matrix 푸시 전달을 갖고 있지 않습니다. #### Synapse -Synapse의 경우, 위 설정만으로도 보통 충분합니다: +Synapse에서는 위 설정만으로 보통 충분합니다: -- 최종 OpenClaw 미리보기 알림을 위해 특별한 `homeserver.yaml` 변경은 필요하지 않습니다. -- Synapse 배포가 이미 일반 Matrix 푸시 알림을 전송하고 있다면, 사용자 토큰 + 위 `pushrules` 호출이 주요 설정 단계입니다. -- Synapse를 reverse proxy 또는 worker 뒤에서 실행 중이라면, `/_matrix/client/.../pushrules/`가 Synapse에 올바르게 전달되는지 확인하세요. -- Synapse worker를 사용하는 경우 pusher 상태가 정상인지 확인하세요. 푸시 전송은 메인 프로세스 또는 `synapse.app.pusher` / 구성된 pusher worker에서 처리됩니다. +- 최종 확정된 OpenClaw 미리보기 알림을 위해 특별한 `homeserver.yaml` 변경은 필요하지 않습니다. +- Synapse 배포가 이미 일반 Matrix 푸시 알림을 보내고 있다면, 사용자 token + 위 `pushrules` 호출이 주요 설정 단계입니다. +- Synapse를 reverse proxy 또는 worker 뒤에서 실행한다면 `/_matrix/client/.../pushrules/`가 Synapse에 올바르게 도달하는지 확인하세요. +- Synapse worker를 실행 중이라면 pusher가 정상인지 확인하세요. 푸시 전달은 메인 프로세스 또는 `synapse.app.pusher` / 구성된 pusher worker가 처리합니다. #### Tuwunel -Tuwunel에서는 위에 나온 동일한 설정 흐름과 push-rule API 호출을 사용하세요: +Tuwunel에서는 위에 표시된 동일한 설정 흐름과 push-rule API 호출을 사용하세요: -- 최종 미리보기 표시 자체를 위한 Tuwunel 전용 config는 필요하지 않습니다. -- 해당 사용자에 대해 일반 Matrix 알림이 이미 작동한다면, 사용자 토큰 + 위 `pushrules` 호출이 주요 설정 단계입니다. -- 사용자가 다른 디바이스에서 활성 상태일 때 알림이 사라지는 것 같다면 `suppress_push_when_active`가 활성화되어 있는지 확인하세요. Tuwunel은 2025년 9월 12일 Tuwunel 1.4.2에서 이 옵션을 추가했으며, 한 디바이스가 활성일 때 다른 디바이스로의 푸시를 의도적으로 억제할 수 있습니다. +- 최종 확정 미리보기 마커 자체를 위한 Tuwunel 전용 config는 필요하지 않습니다. +- 해당 사용자에 대해 일반 Matrix 알림이 이미 작동한다면, 사용자 token + 위 `pushrules` 호출이 주요 설정 단계입니다. +- 사용자가 다른 device에서 활성 상태일 때 알림이 사라지는 것 같다면 `suppress_push_when_active`가 활성화되어 있는지 확인하세요. Tuwunel은 2025년 9월 12일 Tuwunel 1.4.2에서 이 옵션을 추가했으며, 하나의 device가 활성일 때 다른 device로의 푸시를 의도적으로 억제할 수 있습니다. -## 암호화 및 검증 - -암호화된(E2EE) 룸에서는 아웃바운드 이미지 이벤트가 `thumbnail_file`을 사용하므로 이미지 미리보기도 전체 첨부 파일과 함께 암호화됩니다. 암호화되지 않은 룸은 계속 일반 `thumbnail_url`을 사용합니다. 별도 설정은 필요하지 않습니다 — plugin이 E2EE 상태를 자동으로 감지합니다. - -### 봇 간 룸 +## 봇 간 room 기본적으로 다른 구성된 OpenClaw Matrix 계정에서 온 Matrix 메시지는 무시됩니다. -의도적으로 에이전트 간 Matrix 트래픽을 허용하려면 `allowBots`를 사용하세요: +에이전트 간 Matrix 트래픽을 의도적으로 원할 때는 `allowBots`를 사용하세요: ```json5 { @@ -450,13 +431,17 @@ Tuwunel에서는 위에 나온 동일한 설정 흐름과 push-rule API 호출 } ``` -- `allowBots: true`는 허용된 룸과 DM에서 다른 구성된 Matrix 봇 계정의 메시지를 받아들입니다. -- `allowBots: "mentions"`는 룸에서 해당 메시지가 이 봇을 눈에 띄게 멘션한 경우에만 받아들입니다. DM은 여전히 허용됩니다. -- `groups..allowBots`는 하나의 룸에 대해 계정 수준 설정을 재정의합니다. -- OpenClaw는 자체 응답 루프를 방지하기 위해 동일한 Matrix 사용자 ID의 메시지는 계속 무시합니다. -- Matrix는 여기서 기본적인 봇 플래그를 제공하지 않으므로, OpenClaw는 "봇이 작성한"을 "이 OpenClaw 게이트웨이에서 구성된 다른 Matrix 계정이 보낸" 것으로 간주합니다. +- `allowBots: true`는 허용된 room과 DM에서 다른 구성된 Matrix 봇 계정의 메시지를 수락합니다. +- `allowBots: "mentions"`는 room에서는 이 봇을 눈에 띄게 언급할 때만 해당 메시지를 수락합니다. DM은 여전히 허용됩니다. +- `groups..allowBots`는 하나의 room에 대해 계정 수준 설정을 재정의합니다. +- OpenClaw는 자기 자신에게 답하는 루프를 피하기 위해 동일한 Matrix 사용자 ID의 메시지는 여전히 무시합니다. +- Matrix는 여기서 기본 bot 플래그를 노출하지 않으므로, OpenClaw는 "봇 작성"을 "이 OpenClaw gateway에 구성된 다른 Matrix 계정이 보낸 것"으로 취급합니다. -공유 룸에서 봇 간 트래픽을 활성화할 때는 엄격한 룸 allowlist와 멘션 요구 사항을 사용하세요. +공유 room에서 봇 간 트래픽을 활성화할 때는 엄격한 room 허용 목록과 멘션 요구 사항을 사용하세요. + +## 암호화 및 검증 + +암호화된(E2EE) room에서 outbound 이미지 이벤트는 `thumbnail_file`을 사용하므로 이미지 미리보기도 전체 첨부 파일과 함께 암호화됩니다. 암호화되지 않은 room은 여전히 일반 `thumbnail_url`을 사용합니다. 별도 구성은 필요하지 않습니다 — plugin이 E2EE 상태를 자동으로 감지합니다. 암호화 활성화: @@ -480,13 +465,13 @@ Tuwunel에서는 위에 나온 동일한 설정 흐름과 push-rule API 호출 openclaw matrix verify status ``` -상세 상태(전체 진단): +자세한 상태(전체 진단): ```bash openclaw matrix verify status --verbose ``` -저장된 복구 키를 기계 판독 가능 출력에 포함: +저장된 recovery key를 machine-readable 출력에 포함: ```bash openclaw matrix verify status --include-recovery-key --json @@ -498,70 +483,66 @@ openclaw matrix verify status --include-recovery-key --json openclaw matrix verify bootstrap ``` -다중 계정 지원: 계정별 자격 증명과 선택 사항인 `name`을 포함해 `channels.matrix.accounts`를 사용하세요. 공통 패턴은 [Configuration reference](/ko/gateway/configuration-reference#multi-account-all-channels)를 참조하세요. - -상세 부트스트랩 진단: +자세한 부트스트랩 진단: ```bash openclaw matrix verify bootstrap --verbose ``` -부트스트랩 전에 새 교차 서명 ID 재설정을 강제로 수행: +부트스트랩 전에 새 교차 서명 ID 재설정을 강제: ```bash openclaw matrix verify bootstrap --force-reset-cross-signing ``` -복구 키로 이 디바이스 검증: +recovery key로 이 device 검증: ```bash openclaw matrix verify device "" ``` -상세 디바이스 검증 정보: +자세한 device 검증 세부 정보: ```bash openclaw matrix verify device "" --verbose ``` -룸 키 백업 상태 확인: +room-key 백업 상태 확인: ```bash openclaw matrix verify backup status ``` -상세 백업 상태 진단: +자세한 백업 상태 진단: ```bash openclaw matrix verify backup status --verbose ``` -서버 백업에서 룸 키 복원: +서버 백업에서 room key 복원: ```bash openclaw matrix verify backup restore ``` -상세 복원 진단: +자세한 복원 진단: ```bash openclaw matrix verify backup restore --verbose ``` -현재 서버 백업을 삭제하고 새 백업 기준선을 만듭니다. 저장된 -백업 키를 정상적으로 불러올 수 없는 경우, 이 재설정은 비밀 저장소도 다시 만들어 -향후 콜드 스타트에서 새 백업 키를 불러올 수 있게 할 수 있습니다: +현재 서버 백업을 삭제하고 새 백업 기준 상태를 만듭니다. 저장된 백업 키를 정상적으로 불러올 수 없으면 이 재설정으로 secret storage도 다시 생성되어 향후 콜드 스타트에서 새 백업 키를 불러올 수 있게 됩니다: ```bash openclaw matrix verify backup reset --yes ``` -모든 `verify` 명령은 기본적으로 간결하게 동작하며(조용한 내부 SDK 로깅 포함), 자세한 진단은 `--verbose`를 사용할 때만 표시합니다. -스크립트에서 사용할 때 전체 기계 판독 가능 출력을 원하면 `--json`을 사용하세요. +모든 `verify` 명령은 기본적으로 간결하게 동작하며(조용한 내부 SDK 로깅 포함), 자세한 진단은 `--verbose`에서만 표시합니다. +스크립팅할 때는 전체 machine-readable 출력을 위해 `--json`을 사용하세요. -다중 계정 설정에서 Matrix CLI 명령은 `--account `를 전달하지 않으면 암시적 Matrix 기본 계정을 사용합니다. -여러 이름 있는 계정을 구성했다면 `channels.matrix.defaultAccount`를 먼저 설정하세요. 그렇지 않으면 해당 암시적 CLI 작업은 중단되고 명시적으로 계정을 선택하라고 요청합니다. -검증 또는 디바이스 작업을 특정 이름 있는 계정으로 명시적으로 지정하려면 항상 `--account`를 사용하세요: +다중 계정 구성에서 Matrix CLI 명령은 `--account `를 전달하지 않으면 암묵적인 Matrix 기본 계정을 사용합니다. +이름이 지정된 여러 계정을 구성한 경우 `channels.matrix.defaultAccount`를 먼저 설정하지 않으면, 이러한 암묵적 CLI 작업은 중단되고 계정을 명시적으로 선택하라고 요청합니다. +검증 또는 device 작업이 특정 이름 있는 계정을 명시적으로 대상으로 하게 하려면 `--account`를 사용하세요: ```bash openclaw matrix verify status --account assistant @@ -569,43 +550,40 @@ openclaw matrix verify backup restore --account assistant openclaw matrix devices list --account assistant ``` -암호화가 비활성화되어 있거나 이름 있는 계정에서 사용할 수 없는 경우, Matrix 경고와 검증 오류는 해당 계정의 config 키를 가리킵니다. 예: `channels.matrix.accounts.assistant.encryption`. +이름 있는 계정에서 암호화가 비활성화되었거나 사용할 수 없을 때 Matrix 경고와 검증 오류는 예를 들어 `channels.matrix.accounts.assistant.encryption`처럼 해당 계정의 config 키를 가리킵니다. ### "검증됨"의 의미 -OpenClaw는 이 Matrix 디바이스가 사용자 자신의 교차 서명 ID에 의해 검증되었을 때만 검증된 것으로 간주합니다. -실제로 `openclaw matrix verify status --verbose`는 세 가지 신뢰 신호를 표시합니다: +OpenClaw는 이 Matrix device가 자신의 교차 서명 ID에 의해 검증된 경우에만 검증된 것으로 취급합니다. +실제로 `openclaw matrix verify status --verbose`는 세 가지 신뢰 신호를 노출합니다: -- `Locally trusted`: 이 디바이스는 현재 클라이언트에서만 신뢰됨 -- `Cross-signing verified`: SDK가 이 디바이스를 교차 서명을 통해 검증된 것으로 보고함 -- `Signed by owner`: 이 디바이스가 사용자의 자체 self-signing 키로 서명됨 +- `Locally trusted`: 현재 클라이언트에서만 이 device를 신뢰함 +- `Cross-signing verified`: SDK가 교차 서명을 통해 이 device를 검증된 것으로 보고함 +- `Signed by owner`: 이 device가 자신의 self-signing key로 서명됨 `Verified by owner`는 교차 서명 검증 또는 소유자 서명이 있을 때만 `yes`가 됩니다. -로컬 신뢰만으로는 OpenClaw가 이 디바이스를 완전히 검증된 것으로 간주하기에 충분하지 않습니다. +로컬 신뢰만으로는 OpenClaw가 이 device를 완전히 검증된 것으로 취급하기에 충분하지 않습니다. -### bootstrap이 하는 일 +### bootstrap이 수행하는 작업 -`openclaw matrix verify bootstrap`은 암호화된 Matrix 계정용 복구 및 설정 명령입니다. +`openclaw matrix verify bootstrap`은 암호화된 Matrix 계정을 위한 복구 및 설정 명령입니다. 다음 작업을 순서대로 모두 수행합니다: -- 가능하면 기존 복구 키를 재사용하면서 비밀 저장소 부트스트랩 -- 교차 서명 부트스트랩 및 누락된 공개 교차 서명 키 업로드 -- 현재 디바이스를 표시하고 교차 서명하려고 시도 -- 아직 존재하지 않는 경우 새 서버 측 룸 키 백업 생성 +- 가능하면 기존 recovery key를 재사용하여 secret storage를 bootstrap +- 교차 서명을 bootstrap하고 누락된 공개 교차 서명 키 업로드 +- 현재 device를 표시하고 교차 서명하려고 시도 +- 서버 측 room-key 백업이 아직 없으면 새로 생성 -홈서버가 교차 서명 키 업로드에 대화형 인증을 요구하면, OpenClaw는 먼저 인증 없이 업로드를 시도하고, 그다음 `m.login.dummy`, 마지막으로 `channels.matrix.password`가 구성된 경우 `m.login.password`로 시도합니다. +홈서버가 교차 서명 키 업로드에 interactive auth를 요구하면, OpenClaw는 먼저 인증 없이 업로드를 시도한 다음 `m.login.dummy`, 그다음 `channels.matrix.password`가 구성된 경우 `m.login.password`로 시도합니다. 현재 교차 서명 ID를 폐기하고 새로 만들려는 의도가 있을 때만 `--force-reset-cross-signing`을 사용하세요. -현재 룸 키 백업을 의도적으로 폐기하고 향후 메시지를 위한 새 -백업 기준선을 시작하려면 `openclaw matrix verify backup reset --yes`를 사용하세요. -복구할 수 없는 오래된 암호화 기록은 계속 -사용할 수 없게 되고 OpenClaw가 현재 백업 -비밀을 안전하게 불러올 수 없을 경우 비밀 저장소를 다시 만들 수 있다는 점을 받아들일 때만 이 작업을 하세요. +현재 room-key 백업을 의도적으로 폐기하고 향후 메시지를 위한 새 백업 기준 상태를 시작하려면 `openclaw matrix verify backup reset --yes`를 사용하세요. +복구할 수 없는 이전 암호화 기록은 계속 사용할 수 없게 되며 OpenClaw가 현재 백업 secret을 안전하게 불러올 수 없을 경우 secret storage를 다시 만들 수 있다는 점을 받아들일 때만 이렇게 하세요. -### 새 백업 기준선 +### 새 백업 기준 상태 -향후 암호화된 메시지가 계속 작동하도록 유지하면서 복구할 수 없는 오래된 기록 손실을 받아들일 수 있다면, 다음 명령을 순서대로 실행하세요: +향후 암호화된 메시지를 계속 정상적으로 사용하고, 복구할 수 없는 이전 기록은 잃어도 괜찮다면 다음 명령을 순서대로 실행하세요: ```bash openclaw matrix verify backup reset --yes @@ -613,81 +591,26 @@ openclaw matrix verify backup status --verbose openclaw matrix verify status ``` -특정 이름 있는 Matrix 계정을 명시적으로 대상으로 지정하려면 각 명령에 `--account `를 추가하세요. +특정 이름 있는 Matrix 계정을 명시적으로 대상으로 하려면 각 명령에 `--account `를 추가하세요. -### 시작 시 동작 +### 시작 동작 -`encryption: true`일 때 Matrix는 `startupVerification`의 기본값을 `"if-unverified"`로 설정합니다. -시작 시 이 디바이스가 아직 검증되지 않았다면, Matrix는 다른 Matrix 클라이언트에서 자기 검증을 요청하고, -이미 하나가 대기 중일 때는 중복 요청을 건너뛰며, 재시작 후 재시도 전에 로컬 cooldown을 적용합니다. -기본적으로 요청 생성에 성공한 경우보다 요청 시도가 실패한 경우 더 빨리 재시도합니다. -자동 시작 요청을 비활성화하려면 `startupVerification: "off"`를 설정하거나, 더 짧거나 긴 재시도 창을 원하면 `startupVerificationCooldownHours` -를 조정하세요. +`encryption: true`일 때 Matrix는 `startupVerification` 기본값을 `"if-unverified"`로 설정합니다. +시작 시 이 device가 아직 검증되지 않았으면 Matrix는 다른 Matrix 클라이언트에서 self-verification을 요청하고, 이미 하나가 대기 중일 때 중복 요청을 건너뛰며, 재시작 후 재시도 전에 로컬 cooldown을 적용합니다. +실패한 요청 시도는 기본적으로 성공적인 요청 생성보다 더 빨리 재시도됩니다. +자동 시작 요청을 비활성화하려면 `startupVerification: "off"`로 설정하거나, 더 짧거나 긴 재시도 창이 필요하면 `startupVerificationCooldownHours`를 조정하세요. -시작 시에는 자동으로 보수적인 crypto bootstrap pass도 수행됩니다. -이 pass는 먼저 현재 비밀 저장소와 교차 서명 ID를 재사용하려고 하며, 명시적인 bootstrap 복구 흐름을 실행하지 않는 한 교차 서명을 재설정하지 않습니다. +시작 시에는 보수적인 crypto bootstrap 단계도 자동으로 수행됩니다. +이 단계는 먼저 현재 secret storage와 교차 서명 ID를 재사용하려고 하며, 명시적인 bootstrap 복구 흐름을 실행하지 않는 한 교차 서명을 재설정하지 않습니다. -시작 시 손상된 bootstrap 상태가 감지되고 `channels.matrix.password`가 구성되어 있으면, OpenClaw는 더 엄격한 복구 경로를 시도할 수 있습니다. -현재 디바이스가 이미 소유자 서명 상태라면, OpenClaw는 이를 자동으로 재설정하지 않고 해당 ID를 보존합니다. +시작 중 손상된 bootstrap 상태를 발견하고 `channels.matrix.password`가 구성되어 있으면 OpenClaw는 더 엄격한 복구 경로를 시도할 수 있습니다. +현재 device가 이미 소유자 서명 상태라면 OpenClaw는 이를 자동으로 재설정하지 않고 해당 ID를 보존합니다. -이전 공개 Matrix plugin에서 업그레이드하는 경우: +전체 업그레이드 흐름, 제한 사항, 복구 명령, 일반적인 마이그레이션 메시지는 [Matrix migration](/ko/install/migrating-matrix)을 참조하세요. -- OpenClaw는 가능하면 동일한 Matrix 계정, 액세스 토큰, 디바이스 ID를 자동으로 재사용합니다. -- 실행 가능한 Matrix 마이그레이션 변경이 적용되기 전에, OpenClaw는 `~/Backups/openclaw-migrations/` 아래에 복구 스냅샷을 만들거나 재사용합니다. -- 여러 Matrix 계정을 사용하는 경우, 이전 플랫 스토어 레이아웃에서 업그레이드하기 전에 `channels.matrix.defaultAccount`를 설정하여 해당 공유 레거시 상태를 어떤 계정이 받아야 하는지 OpenClaw가 알 수 있게 하세요. -- 이전 plugin이 Matrix 룸 키 백업 복호화 키를 로컬에 저장했다면, 시작 시 또는 `openclaw doctor --fix` 실행 시 이를 자동으로 새 복구 키 흐름으로 가져옵니다. -- 마이그레이션 준비 후 Matrix 액세스 토큰이 변경되었다면, 시작 시 이제 자동 백업 복원을 포기하기 전에 대기 중인 레거시 복원 상태가 있는 sibling token-hash 저장소 루트를 검사합니다. -- 이후 같은 계정, 홈서버, 사용자에 대해 Matrix 액세스 토큰이 다시 바뀌면, OpenClaw는 빈 Matrix 상태 디렉터리에서 새로 시작하는 대신 가장 완전한 기존 token-hash 저장소 루트를 재사용하는 쪽을 선호합니다. -- 다음 게이트웨이 시작 시, 백업된 룸 키가 새 crypto store로 자동 복원됩니다. -- 이전 plugin에 백업되지 않은 로컬 전용 룸 키가 있었다면, OpenClaw는 이를 명확히 경고합니다. 해당 키는 이전 rust crypto store에서 자동 내보내기를 할 수 없으므로, 수동 복구 전까지 일부 오래된 암호화 기록은 계속 사용할 수 없을 수 있습니다. -- 전체 업그레이드 흐름, 제한 사항, 복구 명령, 일반적인 마이그레이션 메시지는 [Matrix migration](/ko/install/migrating-matrix)를 참조하세요. +### 검증 알림 -암호화된 런타임 상태는 계정별, 사용자별 token-hash 루트 아래 -`~/.openclaw/matrix/accounts//__//`에 구성됩니다. -이 디렉터리에는 sync store(`bot-storage.json`), crypto store(`crypto/`), -복구 키 파일(`recovery-key.json`), IndexedDB 스냅샷(`crypto-idb-snapshot.json`), -스레드 바인딩(`thread-bindings.json`), 시작 검증 상태(`startup-verification.json`) -가 해당 기능을 사용할 때 포함됩니다. -토큰이 변경되더라도 계정 ID가 동일하면, OpenClaw는 해당 계정/홈서버/사용자 조합에 대해 가장 적절한 기존 -루트를 재사용하여 이전 sync 상태, crypto 상태, 스레드 바인딩, -시작 검증 상태를 계속 볼 수 있게 합니다. - -### Node crypto store 모델 - -이 plugin의 Matrix E2EE는 Node에서 공식 `matrix-js-sdk` Rust crypto 경로를 사용합니다. -이 경로는 crypto 상태를 재시작 간 유지하려면 IndexedDB 기반 영속성을 필요로 합니다. - -OpenClaw는 현재 Node에서 이를 다음 방식으로 제공합니다: - -- SDK가 기대하는 IndexedDB API shim으로 `fake-indexeddb` 사용 -- `initRustCrypto` 전에 `crypto-idb-snapshot.json`에서 Rust crypto IndexedDB 내용을 복원 -- 초기화 후와 런타임 중에 갱신된 IndexedDB 내용을 다시 `crypto-idb-snapshot.json`에 영속화 -- 게이트웨이 런타임 영속화와 CLI 유지 관리가 동일한 스냅샷 파일에서 경쟁하지 않도록, advisory file lock으로 `crypto-idb-snapshot.json`에 대한 스냅샷 복원 및 영속화 작업을 직렬화 - -이것은 사용자 지정 crypto 구현이 아니라 호환성/저장소용 배관입니다. -스냅샷 파일은 민감한 런타임 상태이며 제한적인 파일 권한으로 저장됩니다. -OpenClaw의 보안 모델에서는 게이트웨이 호스트와 로컬 OpenClaw 상태 디렉터리가 이미 신뢰된 운영자 경계 안에 있으므로, 이는 별도의 원격 신뢰 경계라기보다 주로 운영상 내구성 문제입니다. - -계획된 개선 사항: - -- 지속적인 Matrix 키 자료에 대한 SecretRef 지원 추가하여 복구 키 및 관련 store 암호화 비밀을 로컬 파일뿐 아니라 OpenClaw 비밀 제공자에서도 가져올 수 있도록 지원 - -## 프로필 관리 - -선택한 계정의 Matrix 자체 프로필을 다음과 같이 업데이트합니다: - -```bash -openclaw matrix profile set --name "OpenClaw Assistant" -openclaw matrix profile set --avatar-url https://cdn.example.org/avatar.png -``` - -특정 이름 있는 Matrix 계정을 명시적으로 대상으로 지정하려면 `--account `를 추가하세요. - -Matrix는 `mxc://` 아바타 URL을 직접 허용합니다. `http://` 또는 `https://` 아바타 URL을 전달하면, OpenClaw는 먼저 이를 Matrix에 업로드하고 확인된 `mxc://` URL을 다시 `channels.matrix.avatarUrl`(또는 선택한 계정 재정의)로 저장합니다. - -## 자동 검증 알림 - -이제 Matrix는 엄격한 DM 검증 룸에 검증 수명 주기 알림을 `m.notice` 메시지로 직접 게시합니다. +Matrix는 검증 수명 주기 알림을 엄격한 DM 검증 room에 `m.notice` 메시지로 직접 게시합니다. 여기에는 다음이 포함됩니다: - 검증 요청 알림 @@ -695,91 +618,90 @@ Matrix는 `mxc://` 아바타 URL을 직접 허용합니다. `http://` 또는 `ht - 검증 시작 및 완료 알림 - 사용 가능한 경우 SAS 세부 정보(이모지 및 십진수) -다른 Matrix 클라이언트에서 들어오는 검증 요청은 OpenClaw가 추적하고 자동 수락합니다. -자기 검증 흐름의 경우, OpenClaw는 이모지 검증이 가능해지면 SAS 흐름도 자동으로 시작하고 자신의 쪽을 확인합니다. -다른 Matrix 사용자/디바이스의 검증 요청에 대해서는 OpenClaw가 요청을 자동 수락한 뒤 SAS 흐름이 정상적으로 진행되기를 기다립니다. +다른 Matrix 클라이언트에서 들어온 검증 요청은 OpenClaw가 추적하고 자동 수락합니다. +self-verification 흐름의 경우 OpenClaw는 이모지 검증을 사용할 수 있게 되면 SAS 흐름도 자동으로 시작하고 자체 측 확인도 수행합니다. +다른 Matrix 사용자/device의 검증 요청에 대해서는 OpenClaw가 요청을 자동 수락한 뒤 SAS 흐름이 정상적으로 진행되도록 기다립니다. 검증을 완료하려면 여전히 Matrix 클라이언트에서 이모지 또는 십진수 SAS를 비교하고 "They match"를 확인해야 합니다. -OpenClaw는 self-initiated 중복 흐름을 무조건 자동 수락하지 않습니다. 시작 시 자기 검증 요청이 이미 대기 중이면 새 요청 생성을 건너뜁니다. +OpenClaw는 self-initiated 중복 흐름을 무조건 자동 수락하지 않습니다. 시작 시에는 self-verification 요청이 이미 대기 중이면 새 요청을 만들지 않습니다. -검증 프로토콜/시스템 알림은 에이전트 채팅 파이프라인으로 전달되지 않으므로 `NO_REPLY`를 생성하지 않습니다. +검증 프로토콜/시스템 알림은 agent 채팅 파이프라인으로 전달되지 않으므로 `NO_REPLY`를 생성하지 않습니다. -### 디바이스 정리 +### device 관리 -오래된 OpenClaw 관리 Matrix 디바이스가 계정에 누적되면 암호화된 룸의 신뢰 상태를 파악하기 어려워질 수 있습니다. +이전 OpenClaw 관리 Matrix device가 계정에 쌓이면 암호화된 room의 신뢰 상태를 이해하기 어려워질 수 있습니다. 다음으로 목록을 확인하세요: ```bash openclaw matrix devices list ``` -오래된 OpenClaw 관리 디바이스 제거: +오래된 OpenClaw 관리 device 제거: ```bash openclaw matrix devices prune-stale ``` -### Direct Room Repair +### crypto 저장소 -다이렉트 메시지 상태가 어긋나면 OpenClaw가 현재 DM이 아니라 오래된 1인 룸을 가리키는 오래된 `m.direct` 매핑을 갖게 될 수 있습니다. 상대방에 대한 현재 매핑은 다음으로 확인할 수 있습니다: +Matrix E2EE는 Node에서 공식 `matrix-js-sdk` Rust crypto 경로를 사용하며 IndexedDB shim으로 `fake-indexeddb`를 사용합니다. Crypto 상태는 스냅샷 파일(`crypto-idb-snapshot.json`)에 영속화되고 시작 시 복원됩니다. 이 스냅샷 파일은 제한적인 파일 권한으로 저장되는 민감한 런타임 상태입니다. + +암호화된 런타임 상태는 계정별, 사용자별 token hash 루트 아래의 `~/.openclaw/matrix/accounts//__//`에 저장됩니다. +이 디렉터리에는 sync 저장소(`bot-storage.json`), crypto 저장소(`crypto/`), recovery key 파일(`recovery-key.json`), IndexedDB 스냅샷(`crypto-idb-snapshot.json`), thread 바인딩(`thread-bindings.json`), 시작 검증 상태(`startup-verification.json`)가 포함됩니다. +token이 바뀌더라도 계정 ID가 같으면 OpenClaw는 해당 account/homeserver/user 조합에 대해 가장 적절한 기존 루트를 재사용하므로 이전 sync 상태, crypto 상태, thread 바인딩, 시작 검증 상태를 계속 볼 수 있습니다. + +## 프로필 관리 + +선택한 계정의 Matrix self-profile을 다음으로 업데이트합니다: ```bash -openclaw matrix direct inspect --user-id @alice:example.org +openclaw matrix profile set --name "OpenClaw Assistant" +openclaw matrix profile set --avatar-url https://cdn.example.org/avatar.png ``` -다음으로 복구할 수 있습니다: +특정 이름 있는 계정을 명시적으로 대상으로 하려면 `--account `를 추가하세요. -```bash -openclaw matrix direct repair --user-id @alice:example.org -``` - -복구는 Matrix 전용 로직을 plugin 내부에 유지합니다: - -- 먼저 `m.direct`에 이미 매핑된 엄격한 1:1 DM을 우선 사용합니다 -- 그렇지 않으면 해당 사용자와 현재 참여 중인 엄격한 1:1 DM으로 대체합니다 -- 정상적인 DM이 없으면 새 direct room을 만들고 `m.direct`를 다시 써서 그 룸을 가리키게 합니다 - -복구 흐름은 오래된 룸을 자동으로 삭제하지 않습니다. 정상적인 DM을 선택하고 매핑만 갱신하여 새 Matrix 전송, 검증 알림, 기타 direct-message 흐름이 다시 올바른 룸을 대상으로 하도록 합니다. +Matrix는 `mxc://` avatar URL을 직접 허용합니다. `http://` 또는 `https://` avatar URL을 전달하면 OpenClaw가 먼저 이를 Matrix에 업로드하고 해석된 `mxc://` URL을 `channels.matrix.avatarUrl`(또는 선택한 계정 재정의)에 다시 저장합니다. ## 스레드 -Matrix는 자동 응답과 message-tool 전송 모두에 대해 기본 Matrix 스레드를 지원합니다. +Matrix는 자동 답변과 message-tool 전송 모두에 대해 기본 Matrix 스레드를 지원합니다. -- `dm.sessionScope: "per-user"`(기본값)는 Matrix DM 라우팅을 발신자 범위로 유지하므로, 같은 상대방으로 확인되면 여러 DM 룸이 하나의 세션을 공유할 수 있습니다. -- `dm.sessionScope: "per-room"`은 각 Matrix DM 룸을 자체 세션 키로 분리하면서 일반적인 DM 인증 및 allowlist 확인은 계속 사용합니다. -- 명시적인 Matrix 대화 바인딩은 여전히 `dm.sessionScope`보다 우선하므로, 바인딩된 룸과 스레드는 선택된 대상 세션을 유지합니다. -- `threadReplies: "off"`는 응답을 최상위에 유지하고, 인바운드 스레드 메시지도 부모 세션에 유지합니다. -- `threadReplies: "inbound"`는 인바운드 메시지가 이미 해당 스레드에 있었던 경우에만 스레드 안에서 응답합니다. -- `threadReplies: "always"`는 룸 응답을 트리거 메시지를 루트로 하는 스레드 안에 유지하고, 첫 번째 트리거 메시지부터 해당 대화를 일치하는 스레드 범위 세션으로 라우팅합니다. -- `dm.threadReplies`는 DM에 대해서만 최상위 설정을 재정의합니다. 예를 들어 룸 스레드는 분리해 두면서 DM은 평면으로 유지할 수 있습니다. -- 인바운드 스레드 메시지에는 스레드 루트 메시지가 추가 에이전트 컨텍스트로 포함됩니다. -- 이제 message-tool 전송은 동일한 룸 또는 동일한 DM 사용자 대상일 때 현재 Matrix 스레드를 자동 상속합니다. 단, 명시적인 `threadId`가 제공된 경우는 예외입니다. -- 동일 세션 DM 사용자 대상 재사용은 현재 세션 메타데이터가 같은 Matrix 계정의 같은 DM 상대방임을 증명할 때만 동작합니다. 그렇지 않으면 OpenClaw는 일반적인 사용자 범위 라우팅으로 대체합니다. -- OpenClaw가 Matrix DM 룸이 같은 공유 Matrix DM 세션에서 다른 DM 룸과 충돌하는 것을 감지하면, 스레드 바인딩이 활성화되어 있고 `dm.sessionScope` 힌트가 있을 때 해당 룸에 `/focus` 탈출구와 함께 일회성 `m.notice`를 게시합니다. -- 런타임 스레드 바인딩은 Matrix에서 지원됩니다. `/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`, 그리고 스레드 바인딩된 `/acp spawn`이 이제 Matrix 룸과 DM에서 동작합니다. -- 최상위 Matrix 룸/DM에서의 `/focus`는 `threadBindings.spawnSubagentSessions=true`일 때 새 Matrix 스레드를 만들고 이를 대상 세션에 바인딩합니다. -- 기존 Matrix 스레드 안에서 `/focus` 또는 `/acp spawn --thread here`를 실행하면 대신 현재 스레드를 바인딩합니다. +- `dm.sessionScope: "per-user"`(기본값)는 Matrix DM 라우팅을 발신자 범위로 유지하므로, 같은 상대방으로 해석되면 여러 DM room이 하나의 세션을 공유할 수 있습니다. +- `dm.sessionScope: "per-room"`은 정상적인 DM 인증 및 허용 목록 검사를 계속 사용하면서 각 Matrix DM room을 자체 세션 키로 격리합니다. +- 명시적인 Matrix 대화 바인딩은 여전히 `dm.sessionScope`보다 우선하므로, 바인딩된 room과 스레드는 선택된 대상 세션을 유지합니다. +- `threadReplies: "off"`는 답변을 최상위로 유지하고 들어오는 스레드 메시지를 부모 세션에 유지합니다. +- `threadReplies: "inbound"`는 들어온 메시지가 이미 해당 스레드에 있을 때만 스레드 안에서 답변합니다. +- `threadReplies: "always"`는 room 답변을 트리거 메시지를 루트로 하는 스레드에 유지하고, 첫 트리거 메시지부터 일치하는 스레드 범위 세션을 통해 해당 대화를 라우팅합니다. +- `dm.threadReplies`는 DM에 대해서만 최상위 설정을 재정의합니다. 예를 들어 room 스레드는 격리한 채 DM은 평면으로 유지할 수 있습니다. +- 들어오는 스레드 메시지에는 추가 agent 컨텍스트로 스레드 루트 메시지가 포함됩니다. +- message-tool 전송은 명시적인 `threadId`가 제공되지 않는 한 대상이 같은 room 또는 같은 DM 사용자 대상일 때 현재 Matrix 스레드를 자동 상속합니다. +- 동일 세션 DM 사용자 대상 재사용은 현재 세션 메타데이터가 같은 Matrix 계정의 동일한 DM 상대방임을 입증할 때만 시작되며, 그렇지 않으면 OpenClaw는 일반적인 사용자 범위 라우팅으로 되돌아갑니다. +- OpenClaw가 같은 공유 Matrix DM 세션에서 Matrix DM room이 다른 DM room과 충돌하는 것을 감지하면, thread 바인딩이 활성화되어 있고 `dm.sessionScope` 힌트가 있는 경우 해당 room에 `/focus` 탈출구를 안내하는 일회성 `m.notice`를 게시합니다. +- Matrix는 런타임 thread 바인딩을 지원합니다. `/focus`, `/unfocus`, `/agents`, `/session idle`, `/session max-age`, 그리고 스레드에 바인딩된 `/acp spawn`은 Matrix room과 DM에서 동작합니다. +- 최상위 Matrix room/DM의 `/focus`는 `threadBindings.spawnSubagentSessions=true`일 때 새 Matrix 스레드를 만들고 이를 대상 세션에 바인딩합니다. +- 기존 Matrix 스레드 내부에서 `/focus` 또는 `/acp spawn --thread here`를 실행하면 대신 현재 스레드를 바인딩합니다. ## ACP 대화 바인딩 -Matrix 룸, DM, 기존 Matrix 스레드는 채팅 표면을 바꾸지 않고도 지속적인 ACP 작업 공간으로 전환할 수 있습니다. +Matrix room, DM, 기존 Matrix 스레드는 채팅 표면을 바꾸지 않고도 지속 가능한 ACP 작업 공간으로 전환할 수 있습니다. 빠른 운영자 흐름: -- 계속 사용하려는 Matrix DM, 룸 또는 기존 스레드 안에서 `/acp spawn codex --bind here`를 실행합니다. -- 최상위 Matrix DM 또는 룸에서는 현재 DM/룸이 그대로 채팅 표면으로 유지되고, 이후 메시지는 생성된 ACP 세션으로 라우팅됩니다. -- 기존 Matrix 스레드 안에서는 `--bind here`가 현재 스레드를 그 자리에서 바인딩합니다. -- `/new`와 `/reset`은 같은 바인딩된 ACP 세션을 그 자리에서 재설정합니다. +- 계속 사용할 Matrix DM, room 또는 기존 스레드 안에서 `/acp spawn codex --bind here`를 실행합니다. +- 최상위 Matrix DM 또는 room에서는 현재 DM/room이 채팅 표면으로 유지되고 향후 메시지는 생성된 ACP 세션으로 라우팅됩니다. +- 기존 Matrix 스레드 안에서는 `--bind here`가 현재 스레드를 제자리에서 바인딩합니다. +- `/new`와 `/reset`은 같은 바인딩된 ACP 세션을 제자리에서 재설정합니다. - `/acp close`는 ACP 세션을 닫고 바인딩을 제거합니다. 참고: - `--bind here`는 하위 Matrix 스레드를 만들지 않습니다. -- `threadBindings.spawnAcpSessions`는 `/acp spawn --thread auto|here`에서만 필요하며, 이 경우 OpenClaw가 하위 Matrix 스레드를 만들거나 바인딩해야 합니다. +- `threadBindings.spawnAcpSessions`는 OpenClaw가 하위 Matrix 스레드를 만들거나 바인딩해야 하는 `/acp spawn --thread auto|here`에만 필요합니다. -### Thread Binding Config +### 스레드 바인딩 구성 -Matrix는 `session.threadBindings`의 전역 기본값을 상속하며, 채널별 재정의도 지원합니다: +Matrix는 `session.threadBindings`에서 전역 기본값을 상속하며 채널별 재정의도 지원합니다: - `threadBindings.enabled` - `threadBindings.idleHours` @@ -789,25 +711,25 @@ Matrix는 `session.threadBindings`의 전역 기본값을 상속하며, 채널 Matrix 스레드 바인딩 spawn 플래그는 옵트인입니다: -- 최상위 `/focus`가 새 Matrix 스레드를 생성하고 바인딩할 수 있도록 하려면 `threadBindings.spawnSubagentSessions: true`를 설정하세요. -- `/acp spawn --thread auto|here`가 ACP 세션을 Matrix 스레드에 바인딩할 수 있도록 하려면 `threadBindings.spawnAcpSessions: true`를 설정하세요. +- 최상위 `/focus`가 새 Matrix 스레드를 만들고 바인딩하도록 허용하려면 `threadBindings.spawnSubagentSessions: true`를 설정하세요. +- `/acp spawn --thread auto|here`가 ACP 세션을 Matrix 스레드에 바인딩하도록 허용하려면 `threadBindings.spawnAcpSessions: true`를 설정하세요. ## 반응 -Matrix는 아웃바운드 반응 작업, 인바운드 반응 알림, 인바운드 ack 반응을 지원합니다. +Matrix는 outbound 반응 작업, inbound 반응 알림, inbound ack 반응을 지원합니다. -- 아웃바운드 반응 tooling은 `channels["matrix"].actions.reactions`로 제한됩니다. +- Outbound 반응 도구는 `channels["matrix"].actions.reactions`로 제어됩니다. - `react`는 특정 Matrix 이벤트에 반응을 추가합니다. - `reactions`는 특정 Matrix 이벤트의 현재 반응 요약을 나열합니다. -- `emoji=""`는 해당 이벤트에서 봇 계정 자신의 반응을 제거합니다. -- `remove: true`는 봇 계정의 지정된 이모지 반응만 제거합니다. +- `emoji=""`는 해당 이벤트에 대한 봇 계정 자신의 반응을 제거합니다. +- `remove: true`는 봇 계정의 지정한 이모지 반응만 제거합니다. Ack 반응은 표준 OpenClaw 해석 순서를 사용합니다: - `channels["matrix"].accounts..ackReaction` - `channels["matrix"].ackReaction` - `messages.ackReaction` -- 에이전트 identity 이모지 대체값 +- agent identity emoji 대체값 Ack 반응 범위는 다음 순서로 해석됩니다: @@ -821,33 +743,32 @@ Ack 반응 범위는 다음 순서로 해석됩니다: - `channels["matrix"].reactionNotifications` - 기본값: `own` -현재 동작: +동작: - `reactionNotifications: "own"`은 봇이 작성한 Matrix 메시지를 대상으로 하는 추가된 `m.reaction` 이벤트를 전달합니다. - `reactionNotifications: "off"`는 반응 시스템 이벤트를 비활성화합니다. -- 반응 제거는 Matrix가 이를 독립적인 `m.reaction` 제거가 아니라 redaction으로 표시하므로 여전히 시스템 이벤트로 합성되지 않습니다. +- Matrix는 반응 제거를 독립적인 `m.reaction` 제거가 아니라 redaction으로 노출하므로, 반응 제거는 시스템 이벤트로 합성되지 않습니다. ## 기록 컨텍스트 -- `channels.matrix.historyLimit`는 Matrix 룸 메시지가 에이전트를 트리거할 때 `InboundHistory`로 포함할 최근 룸 메시지 수를 제어합니다. -- 이는 `messages.groupChat.historyLimit`로 대체됩니다. 둘 다 설정되지 않으면 유효 기본값은 `0`이므로, 멘션 제한 룸 메시지는 버퍼링되지 않습니다. 비활성화하려면 `0`으로 설정하세요. -- Matrix 룸 기록은 룸 전용입니다. DM은 계속 일반 세션 기록을 사용합니다. -- Matrix 룸 기록은 pending-only입니다. OpenClaw는 아직 응답을 트리거하지 않은 룸 메시지를 버퍼링한 뒤, 멘션 또는 다른 트리거가 들어오면 그 창을 스냅샷으로 저장합니다. -- 현재 트리거 메시지는 `InboundHistory`에 포함되지 않으며, 해당 턴의 주 인바운드 본문에 남아 있습니다. -- 동일한 Matrix 이벤트를 다시 시도할 때는 최신 룸 메시지로 앞으로 밀리지 않고 원래 기록 스냅샷을 재사용합니다. +- `channels.matrix.historyLimit`은 Matrix room 메시지가 agent를 트리거할 때 `InboundHistory`에 포함할 최근 room 메시지 수를 제어합니다. `messages.groupChat.historyLimit`으로 대체되며, 둘 다 설정되지 않으면 실제 기본값은 `0`입니다. 비활성화하려면 `0`으로 설정하세요. +- Matrix room 기록은 room 전용입니다. DM은 계속 일반 세션 기록을 사용합니다. +- Matrix room 기록은 pending 전용입니다. OpenClaw는 아직 답변을 트리거하지 않은 room 메시지를 버퍼링한 다음, 멘션이나 다른 트리거가 오면 해당 창을 스냅샷합니다. +- 현재 트리거 메시지는 `InboundHistory`에 포함되지 않습니다. 해당 턴의 기본 inbound 본문에 그대로 남습니다. +- 같은 Matrix 이벤트의 재시도는 새로운 room 메시지로 앞으로 이동하지 않고 원래 기록 스냅샷을 재사용합니다. -## 컨텍스트 표시 범위 +## 컨텍스트 가시성 -Matrix는 가져온 응답 텍스트, 스레드 루트, pending history 같은 보조 룸 컨텍스트에 대해 공통 `contextVisibility` 제어를 지원합니다. +Matrix는 가져온 답장 텍스트, 스레드 루트, 대기 중 기록과 같은 보조 room 컨텍스트를 위한 공용 `contextVisibility` 제어를 지원합니다. -- `contextVisibility: "all"`이 기본값입니다. 보조 컨텍스트는 수신된 그대로 유지됩니다. -- `contextVisibility: "allowlist"`는 활성 룸/사용자 allowlist 검사에서 허용된 발신자로 보조 컨텍스트를 필터링합니다. -- `contextVisibility: "allowlist_quote"`는 `allowlist`처럼 동작하지만, 명시적으로 인용된 응답 하나는 계속 유지합니다. +- `contextVisibility: "all"`이 기본값입니다. 보조 컨텍스트는 받은 그대로 유지됩니다. +- `contextVisibility: "allowlist"`는 보조 컨텍스트를 활성 room/사용자 허용 목록 검사에서 허용된 발신자로 필터링합니다. +- `contextVisibility: "allowlist_quote"`는 `allowlist`처럼 동작하지만 하나의 명시적 인용 답장은 계속 유지합니다. -이 설정은 보조 컨텍스트의 표시 범위에 영향을 주며, 인바운드 메시지 자체가 응답을 트리거할 수 있는지 여부에는 영향을 주지 않습니다. -트리거 권한은 계속 `groupPolicy`, `groups`, `groupAllowFrom`, DM 정책 설정에서 결정됩니다. +이 설정은 보조 컨텍스트 가시성에 영향을 주며, inbound 메시지 자체가 답변을 트리거할 수 있는지 여부에는 영향을 주지 않습니다. +트리거 권한은 여전히 `groupPolicy`, `groups`, `groupAllowFrom`, DM 정책 설정에서 결정됩니다. -## DM 및 룸 정책 예제 +## DM 및 room 정책 ```json5 { @@ -870,7 +791,7 @@ Matrix는 가져온 응답 텍스트, 스레드 루트, pending history 같은 } ``` -멘션 제한 및 allowlist 동작은 [Groups](/ko/channels/groups)에서 확인하세요. +멘션 게이팅 및 허용 목록 동작은 [Groups](/ko/channels/groups)를 참조하세요. Matrix DM 페어링 예제: @@ -879,47 +800,66 @@ openclaw pairing list matrix openclaw pairing approve matrix ``` -승인되지 않은 Matrix 사용자가 승인 전에 계속 메시지를 보내면, OpenClaw는 동일한 대기 중인 페어링 코드를 재사용하고 새 코드를 발급하는 대신 짧은 cooldown 후에 다시 리마인더 응답을 보낼 수 있습니다. +승인되지 않은 Matrix 사용자가 승인 전에 계속 메시지를 보내면 OpenClaw는 새 코드를 발급하지 않고 동일한 대기 중 pairing 코드를 재사용하며, 짧은 cooldown 후 다시 리마인더 답장을 보낼 수 있습니다. -공통 DM 페어링 흐름 및 저장소 레이아웃은 [Pairing](/ko/channels/pairing)에서 확인하세요. +공용 DM pairing 흐름 및 저장소 레이아웃은 [Pairing](/ko/channels/pairing)을 참조하세요. -## Exec 승인 +## direct room 복구 -Matrix는 Matrix 계정용 기본 승인 클라이언트로 동작할 수 있습니다. 기본 -DM/채널 라우팅 조정 항목은 계속 exec 승인 config 아래에 있습니다: +direct-message 상태가 동기화되지 않으면 OpenClaw가 라이브 DM 대신 오래된 solo room을 가리키는 낡은 `m.direct` 매핑을 갖게 될 수 있습니다. 다음으로 상대방의 현재 매핑을 검사합니다: + +```bash +openclaw matrix direct inspect --user-id @alice:example.org +``` + +다음으로 복구합니다: + +```bash +openclaw matrix direct repair --user-id @alice:example.org +``` + +복구 흐름: + +- 이미 `m.direct`에 매핑된 엄격한 1:1 DM을 우선 선택 +- 해당 사용자와 현재 참여 중인 엄격한 1:1 DM으로 대체 +- 정상적인 DM이 없으면 새 direct room을 만들고 `m.direct`를 다시 작성 + +복구 흐름은 오래된 room을 자동 삭제하지 않습니다. 정상적인 DM을 선택하고 매핑을 업데이트하여 새로운 Matrix 전송, 검증 알림, 기타 direct-message 흐름이 다시 올바른 room을 대상으로 하도록만 합니다. + +## exec 승인 + +Matrix는 Matrix 계정의 네이티브 승인 클라이언트 역할을 할 수 있습니다. 네이티브 DM/채널 라우팅 제어는 여전히 exec 승인 config 아래에 있습니다: - `channels.matrix.execApprovals.enabled` -- `channels.matrix.execApprovals.approvers`(선택 사항; `channels.matrix.dm.allowFrom`으로 대체) +- `channels.matrix.execApprovals.approvers` (선택 사항, `channels.matrix.dm.allowFrom`으로 대체) - `channels.matrix.execApprovals.target` (`dm` | `channel` | `both`, 기본값: `dm`) - `channels.matrix.execApprovals.agentFilter` - `channels.matrix.execApprovals.sessionFilter` -승인자는 `@owner:example.org` 같은 Matrix 사용자 ID여야 합니다. Matrix는 `enabled`가 설정되지 않았거나 `"auto"`이고 적어도 하나의 승인자를 확인할 수 있을 때 기본 승인을 자동 활성화합니다. Exec 승인은 먼저 `execApprovals.approvers`를 사용하며 `channels.matrix.dm.allowFrom`으로 대체될 수 있습니다. Plugin 승인은 `channels.matrix.dm.allowFrom`을 통해 승인됩니다. Matrix를 기본 승인 클라이언트로 명시적으로 비활성화하려면 `enabled: false`를 설정하세요. 그렇지 않으면 승인 요청은 다른 구성된 승인 경로 또는 승인 대체 정책으로 대체됩니다. +승인자는 `@owner:example.org`와 같은 Matrix 사용자 ID여야 합니다. Matrix는 `enabled`가 설정되지 않았거나 `"auto"`이고 적어도 하나의 승인자를 해석할 수 있으면 네이티브 승인을 자동 활성화합니다. Exec 승인은 먼저 `execApprovals.approvers`를 사용하고 `channels.matrix.dm.allowFrom`으로 대체될 수 있습니다. Plugin 승인은 `channels.matrix.dm.allowFrom`을 통해 승인합니다. Matrix를 네이티브 승인 클라이언트로 명시적으로 비활성화하려면 `enabled: false`로 설정하세요. 그렇지 않으면 승인 요청은 다른 구성된 승인 경로 또는 승인 대체 정책으로 대체됩니다. -이제 Matrix 기본 라우팅은 두 승인 종류를 모두 지원합니다: +Matrix 네이티브 라우팅은 두 승인 종류를 모두 지원합니다: -- `channels.matrix.execApprovals.*`는 Matrix 승인 프롬프트의 기본 DM/채널 fanout 모드를 제어합니다. +- `channels.matrix.execApprovals.*`는 Matrix 승인 프롬프트의 네이티브 DM/채널 fanout 모드를 제어합니다. - Exec 승인은 `execApprovals.approvers` 또는 `channels.matrix.dm.allowFrom`의 exec 승인자 집합을 사용합니다. -- Plugin 승인은 Matrix DM allowlist인 `channels.matrix.dm.allowFrom`을 사용합니다. +- Plugin 승인은 Matrix DM 허용 목록 `channels.matrix.dm.allowFrom`을 사용합니다. - Matrix 반응 바로가기와 메시지 업데이트는 exec 승인과 plugin 승인 모두에 적용됩니다. -전송 규칙: +전달 규칙: -- `target: "dm"`은 승인 프롬프트를 승인자 DM으로 보냅니다 -- `target: "channel"`은 프롬프트를 원래 Matrix 룸 또는 DM으로 다시 보냅니다 -- `target: "both"`는 승인자 DM과 원래 Matrix 룸 또는 DM 모두로 보냅니다 +- `target: "dm"`은 승인 프롬프트를 승인자 DM으로 전송 +- `target: "channel"`은 프롬프트를 원래 Matrix room 또는 DM으로 다시 전송 +- `target: "both"`는 승인자 DM과 원래 Matrix room 또는 DM 둘 다로 전송 -Matrix 승인 프롬프트는 기본 승인 메시지에 반응 바로가기를 미리 추가합니다: +Matrix 승인 프롬프트는 기본 승인 메시지에 반응 바로가기를 추가합니다: - `✅` = 한 번 허용 - `❌` = 거부 -- `♾️` = 유효한 exec 정책이 그 결정을 허용하는 경우 항상 허용 +- `♾️` = 해당 결정이 유효한 exec 정책에서 허용될 때 항상 허용 승인자는 해당 메시지에 반응하거나 대체 슬래시 명령 `/approve allow-once`, `/approve allow-always`, 또는 `/approve deny`를 사용할 수 있습니다. -확인된 승인자만 승인 또는 거부할 수 있습니다. Exec 승인에서 채널 전송은 명령 텍스트를 포함하므로, `channel` 또는 `both`는 신뢰된 룸에서만 활성화하세요. - -Matrix 승인 프롬프트는 공통 코어 승인 planner를 재사용합니다. Matrix 전용 기본 표면은 exec 승인과 plugin 승인 모두에 대해 룸/DM 라우팅, 반응, 메시지 전송/업데이트/삭제 동작을 처리합니다. +해석된 승인자만 승인 또는 거부할 수 있습니다. Exec 승인의 경우 채널 전달에는 명령 텍스트가 포함되므로 신뢰할 수 있는 room에서만 `channel` 또는 `both`를 활성화하세요. 계정별 재정의: @@ -927,7 +867,7 @@ Matrix 승인 프롬프트는 공통 코어 승인 planner를 재사용합니다 관련 문서: [Exec approvals](/ko/tools/exec-approvals) -## 다중 계정 예제 +## 다중 계정 ```json5 { @@ -958,21 +898,21 @@ Matrix 승인 프롬프트는 공통 코어 승인 planner를 재사용합니다 ``` 최상위 `channels.matrix` 값은 계정이 재정의하지 않는 한 이름 있는 계정의 기본값으로 동작합니다. -상속된 룸 항목을 특정 Matrix 계정 하나로 제한하려면 `groups..account`(또는 레거시 `rooms..account`)를 사용할 수 있습니다. -`account`가 없는 항목은 모든 Matrix 계정에서 공유되며, `account: "default"`가 있는 항목도 기본 계정이 최상위 `channels.matrix.*`에 직접 구성된 경우 계속 작동합니다. -부분적인 공유 인증 기본값만으로는 별도의 암시적 기본 계정을 생성하지 않습니다. OpenClaw는 해당 기본값에 최신 인증(`homeserver` + `accessToken`, 또는 `homeserver` + `userId` 및 `password`)이 있을 때만 최상위 `default` 계정을 합성합니다. 이름 있는 계정은 나중에 캐시된 자격 증명이 인증을 충족하면 `homeserver` + `userId`만으로도 계속 검색 가능 상태를 유지할 수 있습니다. -Matrix에 이미 이름 있는 계정이 정확히 하나 있거나 `defaultAccount`가 기존 이름 있는 계정 키를 가리키는 경우, 단일 계정에서 다중 계정으로의 복구/설정 승격은 새 `accounts.default` 항목을 만드는 대신 해당 계정을 보존합니다. Matrix 인증/bootstrap 키만 그 승격된 계정으로 이동하며, 공유 전송 정책 키는 최상위에 남습니다. -암시적 라우팅, 프로브, CLI 작업에서 특정 이름 있는 Matrix 계정을 우선 사용하게 하려면 `defaultAccount`를 설정하세요. -여러 이름 있는 계정을 구성한 경우, 암시적 계정 선택에 의존하는 CLI 명령에는 `defaultAccount`를 설정하거나 `--account `를 전달하세요. -하나의 명령에서 그 암시적 선택을 재정의하려면 `openclaw matrix verify ...` 및 `openclaw matrix devices ...`에 `--account `를 전달하세요. +상속된 room 항목 하나를 특정 Matrix 계정에 범위 지정하려면 `groups..account`를 사용할 수 있습니다. +`account`가 없는 항목은 모든 Matrix 계정에서 공유되며, `account: "default"`가 있는 항목도 기본 계정이 최상위 `channels.matrix.*`에 직접 구성되어 있을 때 계속 동작합니다. +부분적인 공유 인증 기본값만으로는 별도의 암묵적 기본 계정을 만들지 않습니다. OpenClaw는 해당 기본값에 새로운 인증(`homeserver` + `accessToken` 또는 `homeserver` + `userId` + `password`)이 있을 때만 최상위 `default` 계정을 합성하며, 이름 있는 계정은 나중에 캐시된 자격 증명이 인증을 충족하면 `homeserver` + `userId`만으로도 계속 검색 가능할 수 있습니다. +Matrix에 이미 정확히 하나의 이름 있는 계정이 있거나 `defaultAccount`가 기존 이름 있는 계정 키를 가리키는 경우, 단일 계정에서 다중 계정으로의 복구/설정 승격은 새 `accounts.default` 항목을 만들지 않고 해당 계정을 보존합니다. Matrix 인증/bootstrap 키만 승격된 계정으로 이동하며, 공유 전달 정책 키는 최상위에 유지됩니다. +암묵적 라우팅, 프로빙, CLI 작업에 대해 하나의 이름 있는 Matrix 계정을 우선 사용하게 하려면 `defaultAccount`를 설정하세요. +이름 있는 계정을 여러 개 구성한 경우 암묵적 계정 선택에 의존하는 CLI 명령에는 `defaultAccount`를 설정하거나 `--account `를 전달하세요. +하나의 명령에 대해 이 암묵적 선택을 재정의하려면 `openclaw matrix verify ...`와 `openclaw matrix devices ...`에 `--account `를 전달하세요. -## 비공개/LAN 홈서버 +공용 다중 계정 패턴은 [Configuration reference](/ko/gateway/configuration-reference#multi-account-all-channels)를 참조하세요. -기본적으로 OpenClaw는 SSRF 방지를 위해 비공개/내부 Matrix 홈서버를 차단하며, 계정별로 -명시적으로 옵트인해야만 허용합니다. +## 비공개/LAN homeserver -홈서버가 localhost, LAN/Tailscale IP, 또는 내부 호스트 이름에서 실행된다면, -해당 Matrix 계정에 대해 `network.dangerouslyAllowPrivateNetwork`를 활성화하세요: +기본적으로 OpenClaw는 SSRF 보호를 위해 비공개/내부 Matrix homeserver를 차단하며, 계정별로 명시적으로 옵트인해야만 허용합니다. + +homeserver가 localhost, LAN/Tailscale IP, 또는 내부 호스트 이름에서 실행되는 경우 해당 Matrix 계정에 대해 `network.dangerouslyAllowPrivateNetwork`를 활성화하세요: ```json5 { @@ -998,12 +938,11 @@ openclaw matrix account add \ --access-token syt_ops_xxx ``` -이 옵트인은 신뢰된 비공개/내부 대상만 허용합니다. 다음과 같은 공개 평문 홈서버는 -`http://matrix.example.org:8008`처럼 계속 차단됩니다. 가능하면 `https://`를 사용하세요. +이 옵트인은 신뢰할 수 있는 비공개/내부 대상만 허용합니다. `http://matrix.example.org:8008` 같은 공개 cleartext homeserver는 여전히 차단됩니다. 가능하면 `https://`를 우선 사용하세요. ## Matrix 트래픽 프록시 -Matrix 배포에 명시적인 아웃바운드 HTTP(S) 프록시가 필요하다면 `channels.matrix.proxy`를 설정하세요: +Matrix 배포에 명시적인 outbound HTTP(S) 프록시가 필요하면 `channels.matrix.proxy`를 설정하세요: ```json5 { @@ -1020,84 +959,83 @@ Matrix 배포에 명시적인 아웃바운드 HTTP(S) 프록시가 필요하다 이름 있는 계정은 `channels.matrix.accounts..proxy`로 최상위 기본값을 재정의할 수 있습니다. OpenClaw는 런타임 Matrix 트래픽과 계정 상태 프로브에 동일한 프록시 설정을 사용합니다. -## 대상 확인 +## 대상 해석 -Matrix는 OpenClaw가 룸 또는 사용자 대상을 물어보는 모든 곳에서 다음 대상 형식을 허용합니다: +Matrix는 OpenClaw가 room 또는 사용자 대상을 요청하는 모든 위치에서 다음 대상 형식을 허용합니다: - 사용자: `@user:server`, `user:@user:server`, 또는 `matrix:user:@user:server` -- 룸: `!room:server`, `room:!room:server`, 또는 `matrix:room:!room:server` -- 별칭: `#alias:server`, `channel:#alias:server`, 또는 `matrix:channel:#alias:server` +- Room: `!room:server`, `room:!room:server`, 또는 `matrix:room:!room:server` +- Alias: `#alias:server`, `channel:#alias:server`, 또는 `matrix:channel:#alias:server` 라이브 디렉터리 조회는 로그인된 Matrix 계정을 사용합니다: -- 사용자 조회는 해당 홈서버의 Matrix 사용자 디렉터리를 질의합니다. -- 룸 조회는 명시적인 룸 ID와 별칭을 직접 허용한 뒤, 해당 계정에서 참여 중인 룸 이름 검색으로 대체합니다. -- 참여 중인 룸 이름 조회는 best-effort입니다. 룸 이름을 ID나 별칭으로 확인할 수 없으면 런타임 allowlist 확인에서 무시됩니다. +- 사용자 조회는 해당 homeserver의 Matrix 사용자 디렉터리를 조회합니다. +- Room 조회는 명시적인 room ID와 alias를 직접 허용한 뒤 해당 계정에 대해 참여 중인 room 이름 검색으로 대체됩니다. +- 참여 중인 room 이름 조회는 최선의 노력 방식입니다. room 이름을 ID 또는 alias로 해석할 수 없으면 허용 목록 해석 시 런타임에서 무시됩니다. ## 구성 참조 - `enabled`: 채널 활성화 또는 비활성화. -- `name`: 계정의 선택 사항 레이블. -- `defaultAccount`: 여러 Matrix 계정이 구성된 경우 우선 사용할 계정 ID. -- `homeserver`: 홈서버 URL, 예: `https://matrix.example.org`. -- `network.dangerouslyAllowPrivateNetwork`: 이 Matrix 계정이 비공개/내부 홈서버에 연결되도록 허용합니다. 홈서버가 `localhost`, LAN/Tailscale IP, 또는 `matrix-synapse` 같은 내부 호스트로 확인되는 경우 활성화하세요. -- `proxy`: Matrix 트래픽에 사용할 선택 사항인 HTTP(S) 프록시 URL. 이름 있는 계정은 자체 `proxy`로 최상위 기본값을 재정의할 수 있습니다. +- `name`: 계정의 선택적 레이블. +- `defaultAccount`: 여러 Matrix 계정이 구성된 경우 선호되는 계정 ID. +- `homeserver`: homeserver URL, 예: `https://matrix.example.org`. +- `network.dangerouslyAllowPrivateNetwork`: 이 Matrix 계정이 비공개/내부 homeserver에 연결되도록 허용합니다. homeserver가 `localhost`, LAN/Tailscale IP, 또는 `matrix-synapse` 같은 내부 호스트로 해석될 때 이를 활성화하세요. +- `proxy`: Matrix 트래픽용 선택적 HTTP(S) 프록시 URL. 이름 있는 계정은 자체 `proxy`로 최상위 기본값을 재정의할 수 있습니다. - `userId`: 전체 Matrix 사용자 ID, 예: `@bot:example.org`. -- `accessToken`: 토큰 기반 인증용 액세스 토큰. 일반 텍스트 값과 SecretRef 값은 env/file/exec provider 전반에서 `channels.matrix.accessToken` 및 `channels.matrix.accounts..accessToken`에 대해 지원됩니다. [Secrets Management](/ko/gateway/secrets)를 참조하세요. -- `password`: 비밀번호 기반 로그인용 비밀번호. 일반 텍스트 값과 SecretRef 값이 지원됩니다. -- `deviceId`: 명시적인 Matrix 디바이스 ID. -- `deviceName`: 비밀번호 로그인용 디바이스 표시 이름. -- `avatarUrl`: 프로필 동기화 및 `set-profile` 업데이트용으로 저장된 self-avatar URL. -- `initialSyncLimit`: 시작 시 동기화 이벤트 제한. +- `accessToken`: token 기반 인증용 access token. 일반 텍스트 값과 SecretRef 값은 env/file/exec provider 전반에서 `channels.matrix.accessToken` 및 `channels.matrix.accounts..accessToken`에 대해 지원됩니다. [Secrets Management](/ko/gateway/secrets)를 참조하세요. +- `password`: password 기반 로그인용 password. 일반 텍스트 값과 SecretRef 값이 지원됩니다. +- `deviceId`: 명시적 Matrix device ID. +- `deviceName`: password 로그인용 device 표시 이름. +- `avatarUrl`: 프로필 동기화와 `profile set` 업데이트를 위한 저장된 self-avatar URL. +- `initialSyncLimit`: 시작 sync 중 가져오는 최대 이벤트 수. - `encryption`: E2EE 활성화. -- `allowlistOnly`: DM 및 룸에 대해 allowlist-only 동작 강제. +- `allowlistOnly`: `true`일 때 `open` room 정책을 `allowlist`로 승격하고, 활성 DM 정책 중 `disabled`를 제외한 모든 정책(`pairing` 및 `open` 포함)을 `allowlist`로 강제합니다. `disabled` 정책에는 영향을 주지 않습니다. - `allowBots`: 다른 구성된 OpenClaw Matrix 계정의 메시지 허용(`true` 또는 `"mentions"`). - `groupPolicy`: `open`, `allowlist`, 또는 `disabled`. -- `contextVisibility`: 보조 룸 컨텍스트 표시 범위 모드(`all`, `allowlist`, `allowlist_quote`). -- `groupAllowFrom`: 룸 트래픽용 사용자 ID allowlist. -- `groupAllowFrom` 항목은 전체 Matrix 사용자 ID여야 합니다. 확인되지 않은 이름은 런타임에서 무시됩니다. -- `historyLimit`: 그룹 기록 컨텍스트로 포함할 최대 룸 메시지 수. `messages.groupChat.historyLimit`로 대체되며, 둘 다 설정되지 않으면 유효 기본값은 `0`입니다. 비활성화하려면 `0`으로 설정하세요. +- `contextVisibility`: 보조 room 컨텍스트 가시성 모드 (`all`, `allowlist`, `allowlist_quote`). +- `groupAllowFrom`: room 트래픽용 사용자 ID 허용 목록. 항목은 전체 Matrix 사용자 ID여야 하며, 해석되지 않은 이름은 런타임에서 무시됩니다. +- `historyLimit`: 그룹 기록 컨텍스트에 포함할 최대 room 메시지 수. `messages.groupChat.historyLimit`으로 대체되며, 둘 다 설정되지 않으면 실제 기본값은 `0`입니다. 비활성화하려면 `0`으로 설정하세요. - `replyToMode`: `off`, `first`, `all`, 또는 `batched`. -- `markdown`: 아웃바운드 Matrix 텍스트용 선택 사항 Markdown 렌더링 config. -- `streaming`: `off`(기본값), `partial`, `quiet`, `true`, 또는 `false`. `partial`과 `true`는 일반 Matrix 텍스트 메시지로 미리보기 우선 초안 업데이트를 활성화합니다. `quiet`은 자체 호스팅 push-rule 설정용 비알림 미리보기 notice를 사용합니다. -- `blockStreaming`: `true`는 초안 미리보기 스트리밍이 활성일 때 완료된 assistant 블록에 대해 별도의 진행 메시지를 활성화합니다. +- `markdown`: outbound Matrix 텍스트용 선택적 Markdown 렌더링 구성. +- `streaming`: `off`(기본값), `"partial"`, `"quiet"`, `true`, 또는 `false`. `"partial"`과 `true`는 일반 Matrix 텍스트 메시지로 미리보기 우선 초안 업데이트를 활성화합니다. `"quiet"`은 자체 호스팅 push-rule 설정을 위한 무알림 미리보기 알림을 사용합니다. `false`는 `"off"`와 같습니다. +- `blockStreaming`: `true`는 초안 미리보기 스트리밍이 활성화되어 있을 때 완료된 assistant 블록용 별도 진행 상황 메시지를 활성화합니다. - `threadReplies`: `off`, `inbound`, 또는 `always`. - `threadBindings`: 스레드 바인딩 세션 라우팅 및 수명 주기에 대한 채널별 재정의. -- `startupVerification`: 시작 시 자동 자기 검증 요청 모드(`if-unverified`, `off`). -- `startupVerificationCooldownHours`: 자동 시작 검증 요청을 재시도하기 전의 cooldown. -- `textChunkLimit`: 아웃바운드 메시지 청크 크기. -- `chunkMode`: `length` 또는 `newline`. -- `responsePrefix`: 아웃바운드 응답용 선택 사항 메시지 접두사. -- `ackReaction`: 이 채널/계정용 선택 사항 ack 반응 재정의. -- `ackReactionScope`: 선택 사항 ack 반응 범위 재정의(`group-mentions`, `group-all`, `direct`, `all`, `none`, `off`). -- `reactionNotifications`: 인바운드 반응 알림 모드(`own`, `off`). -- `mediaMaxMb`: Matrix 미디어 처리용 MB 단위 미디어 크기 상한. 아웃바운드 전송과 인바운드 미디어 처리에 적용됩니다. -- `autoJoin`: 초대 자동 참여 정책(`always`, `allowlist`, `off`). 기본값: `off`. 이는 룸/그룹 초대뿐 아니라 DM 스타일 초대를 포함한 일반 Matrix 초대에 적용됩니다. OpenClaw는 참여한 룸을 DM 또는 그룹으로 신뢰성 있게 분류하기 전에 초대 시점에 이 결정을 내립니다. -- `autoJoinAllowlist`: `autoJoin`이 `allowlist`일 때 허용되는 룸/별칭. 별칭 항목은 초대 처리 중 룸 ID로 확인되며, OpenClaw는 초대된 룸이 주장하는 별칭 상태를 신뢰하지 않습니다. -- `dm`: DM 정책 블록(`enabled`, `policy`, `allowFrom`, `sessionScope`, `threadReplies`). -- `dm.policy`: OpenClaw가 룸에 참여하고 이를 DM으로 분류한 뒤의 DM 접근을 제어합니다. 초대를 자동 참여할지 여부는 바꾸지 않습니다. -- `dm.allowFrom` 항목은 라이브 디렉터리 조회로 이미 확인한 경우가 아니라면 전체 Matrix 사용자 ID여야 합니다. -- `dm.sessionScope`: `per-user`(기본값) 또는 `per-room`. 상대방이 같더라도 각 Matrix DM 룸이 별도 컨텍스트를 유지하길 원하면 `per-room`을 사용하세요. -- `dm.threadReplies`: DM 전용 스레드 정책 재정의(`off`, `inbound`, `always`). DM에서 응답 위치와 세션 분리 모두에 대해 최상위 `threadReplies` 설정을 재정의합니다. -- `execApprovals`: Matrix 기본 exec 승인 전송(`enabled`, `approvers`, `target`, `agentFilter`, `sessionFilter`). +- `startupVerification`: 시작 시 자동 self-verification 요청 모드 (`if-unverified`, `off`). +- `startupVerificationCooldownHours`: 자동 시작 검증 요청을 다시 시도하기 전 cooldown. +- `textChunkLimit`: 문자 기준 outbound 메시지 청크 크기 (`chunkMode`가 `length`일 때 적용). +- `chunkMode`: `length`는 문자 수 기준으로 메시지를 분할하고, `newline`은 줄 경계에서 분할합니다. +- `responsePrefix`: 이 채널의 모든 outbound 답변 앞에 붙는 선택적 문자열. +- `ackReaction`: 이 채널/계정에 대한 선택적 ack 반응 재정의. +- `ackReactionScope`: 선택적 ack 반응 범위 재정의 (`group-mentions`, `group-all`, `direct`, `all`, `none`, `off`). +- `reactionNotifications`: inbound 반응 알림 모드 (`own`, `off`). +- `mediaMaxMb`: outbound 전송 및 inbound 미디어 처리용 미디어 크기 상한(MB). +- `autoJoin`: 초대 자동 참여 정책 (`always`, `allowlist`, `off`). 기본값: `off`. DM 스타일 초대를 포함한 모든 Matrix 초대에 적용됩니다. +- `autoJoinAllowlist`: `autoJoin`이 `allowlist`일 때 허용되는 room/alias. Alias 항목은 초대 처리 중 room ID로 해석되며, OpenClaw는 초대된 room이 주장하는 alias 상태를 신뢰하지 않습니다. +- `dm`: DM 정책 블록 (`enabled`, `policy`, `allowFrom`, `sessionScope`, `threadReplies`). +- `dm.policy`: OpenClaw가 room에 참여하고 이를 DM으로 분류한 후의 DM 접근을 제어합니다. 초대가 자동 참여되는지 여부는 변경하지 않습니다. +- `dm.allowFrom`: live directory lookup으로 이미 해석하지 않았다면 항목은 전체 Matrix 사용자 ID여야 합니다. +- `dm.sessionScope`: `per-user`(기본값) 또는 `per-room`. 같은 상대방이라도 각 Matrix DM room이 별도 컨텍스트를 유지하게 하려면 `per-room`을 사용하세요. +- `dm.threadReplies`: DM 전용 스레드 정책 재정의 (`off`, `inbound`, `always`). DMs에서 답변 배치와 세션 격리 모두에 대해 최상위 `threadReplies` 설정을 재정의합니다. +- `execApprovals`: Matrix 네이티브 exec 승인 전달 (`enabled`, `approvers`, `target`, `agentFilter`, `sessionFilter`). - `execApprovals.approvers`: exec 요청을 승인할 수 있는 Matrix 사용자 ID. `dm.allowFrom`이 이미 승인자를 식별하는 경우 선택 사항입니다. -- `execApprovals.target`: `dm | channel | both`(기본값: `dm`). -- `accounts`: 이름 있는 계정별 재정의. 최상위 `channels.matrix` 값이 이 항목들의 기본값으로 동작합니다. -- `groups`: 룸별 정책 맵. 룸 ID 또는 별칭을 사용하는 것이 좋으며, 확인되지 않은 룸 이름은 런타임에서 무시됩니다. 세션/그룹 식별은 확인 후 안정적인 룸 ID를 사용하며, 사람이 읽는 레이블은 계속 룸 이름에서 가져옵니다. -- `groups..account`: 다중 계정 설정에서 상속된 하나의 룸 항목을 특정 Matrix 계정으로 제한합니다. -- `groups..allowBots`: 구성된 봇 발신자에 대한 룸 수준 재정의(`true` 또는 `"mentions"`). -- `groups..users`: 룸별 발신자 allowlist. -- `groups..tools`: 룸별 tool 허용/거부 재정의. -- `groups..autoReply`: 룸 수준 멘션 제한 재정의. `true`는 해당 룸의 멘션 요구를 비활성화하고, `false`는 다시 강제합니다. -- `groups..skills`: 선택 사항인 룸 수준 Skills 필터. -- `groups..systemPrompt`: 선택 사항인 룸 수준 system prompt 스니펫. -- `rooms`: `groups`의 레거시 별칭. -- `actions`: 작업별 tool gating (`messages`, `reactions`, `pins`, `profile`, `memberInfo`, `channelInfo`, `verification`). +- `execApprovals.target`: `dm | channel | both` (기본값: `dm`). +- `accounts`: 이름 있는 계정별 재정의. 최상위 `channels.matrix` 값은 이 항목들의 기본값으로 동작합니다. +- `groups`: room별 정책 맵. room ID 또는 alias를 권장하며, 해석되지 않은 room 이름은 런타임에서 무시됩니다. 세션/그룹 ID는 해석 후 안정적인 room ID를 사용합니다. +- `groups..account`: 다중 계정 구성에서 하나의 상속된 room 항목을 특정 Matrix 계정으로 제한합니다. +- `groups..allowBots`: 구성된 봇 발신자에 대한 room 수준 재정의 (`true` 또는 `"mentions"`). +- `groups..users`: room별 발신자 허용 목록. +- `groups..tools`: room별 도구 허용/거부 재정의. +- `groups..autoReply`: room 수준 멘션 게이팅 재정의. `true`는 해당 room의 멘션 요구 사항을 비활성화하고, `false`는 다시 강제 적용합니다. +- `groups..skills`: 선택적 room 수준 Skills 필터. +- `groups..systemPrompt`: 선택적 room 수준 system prompt 스니펫. +- `rooms`: `groups`의 레거시 alias. +- `actions`: 작업별 도구 게이팅 (`messages`, `reactions`, `pins`, `profile`, `memberInfo`, `channelInfo`, `verification`). ## 관련 항목 - [Channels Overview](/ko/channels) — 지원되는 모든 채널 -- [Pairing](/ko/channels/pairing) — DM 인증 및 페어링 흐름 -- [Groups](/ko/channels/groups) — 그룹 채팅 동작 및 멘션 제한 -- [Channel Routing](/ko/channels/channel-routing) — 메시지용 세션 라우팅 -- [Security](/ko/gateway/security) — 접근 모델 및 보안 강화 +- [Pairing](/ko/channels/pairing) — DM 인증 및 pairing 흐름 +- [Groups](/ko/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅 +- [Channel Routing](/ko/channels/channel-routing) — 메시지 세션 라우팅 +- [Security](/ko/gateway/security) — 접근 모델 및 하드닝 diff --git a/docs/ko/concepts/agent-loop.md b/docs/ko/concepts/agent-loop.md index b1b4a79a1..0ce0d3359 100644 --- a/docs/ko/concepts/agent-loop.md +++ b/docs/ko/concepts/agent-loop.md @@ -1,176 +1,175 @@ --- read_when: - - 에이전트 루프 또는 수명 주기 이벤트에 대한 정확한 단계별 설명이 필요함 -summary: 에이전트 루프 수명 주기, 스트림 및 wait 의미론 -title: Agent Loop + - 에이전트 루프 또는 수명 주기 이벤트에 대한 정확한 단계별 설명이 필요할 때 +summary: 에이전트 루프 수명 주기, 스트림, 대기 의미 체계 +title: 에이전트 루프 x-i18n: - generated_at: "2026-04-05T12:39:36Z" + generated_at: "2026-04-09T01:27:57Z" model: gpt-5.4 provider: openai - source_hash: 8e562e63c494881e9c345efcb93c5f972d69aaec61445afc3d4ad026b2d26883 + source_hash: 32d3a73df8dabf449211a6183a70dcfd2a9b6f584dc76d0c4c9147582b2ca6a1 source_path: concepts/agent-loop.md workflow: 15 --- -# Agent Loop (OpenClaw) +# 에이전트 루프 (OpenClaw) -에이전트 루프는 에이전트의 전체 “실제” 실행입니다: 입력 수집 → 컨텍스트 조립 → 모델 추론 → -도구 실행 → 응답 스트리밍 → 영속화. 이는 메시지를 동작과 최종 응답으로 -변환하면서 세션 상태의 일관성을 유지하는 권위 있는 경로입니다. +에이전트형 루프는 에이전트의 전체 "실제" 실행입니다: 입력 수집 → 컨텍스트 조립 → 모델 추론 → +도구 실행 → 스트리밍 응답 → 영속화. 이는 메시지를 작업과 최종 응답으로 바꾸는 권위 있는 경로이며, +세션 상태를 일관되게 유지합니다. OpenClaw에서 루프는 세션당 하나의 직렬화된 실행이며, 모델이 생각하고, 도구를 호출하고, 출력을 스트리밍할 때 -수명 주기 및 스트림 이벤트를 발생시킵니다. 이 문서는 그 실제 루프가 -엔드 투 엔드로 어떻게 연결되어 있는지 설명합니다. +수명 주기 및 스트림 이벤트를 내보냅니다. 이 문서는 이 실제 루프가 엔드 투 엔드로 어떻게 연결되는지 설명합니다. ## 진입점 - Gateway RPC: `agent` 및 `agent.wait`. -- CLI: `agent` 명령. +- CLI: `agent` 명령어. ## 작동 방식(상위 수준) -1. `agent` RPC가 매개변수를 검증하고, 세션(sessionKey/sessionId)을 확인하고, 세션 메타데이터를 저장한 다음, 즉시 `{ runId, acceptedAt }`를 반환합니다. +1. `agent` RPC는 매개변수를 검증하고, 세션을 확인하며(sessionKey/sessionId), 세션 메타데이터를 영속화하고, 즉시 `{ runId, acceptedAt }`를 반환합니다. 2. `agentCommand`가 에이전트를 실행합니다: - 모델 + thinking/verbose 기본값 확인 - Skills 스냅샷 로드 - - `runEmbeddedPiAgent` 호출(pi-agent-core 런타임) - - 임베디드 루프가 수명 주기 종료/오류를 발생시키지 않으면 **lifecycle end/error** 발생 + - `runEmbeddedPiAgent` 호출 (`pi-agent-core` 런타임) + - 임베디드 루프가 내보내지 않으면 **수명 주기 end/error** 내보내기 3. `runEmbeddedPiAgent`: - - 세션별 + 전역 큐를 통해 실행을 직렬화 - - 모델 + 인증 프로필을 확인하고 pi 세션 빌드 + - 세션별 + 전역 큐를 통해 실행 직렬화 + - 모델 + auth 프로필 확인 및 pi 세션 빌드 - pi 이벤트를 구독하고 assistant/tool 델타 스트리밍 - - 타임아웃 강제 적용 -> 초과 시 실행 중단 + - 제한 시간 강제 적용 -> 초과 시 실행 중단 - 페이로드 + 사용량 메타데이터 반환 -4. `subscribeEmbeddedPiSession`이 pi-agent-core 이벤트를 OpenClaw `agent` 스트림으로 브리지합니다: +4. `subscribeEmbeddedPiSession`이 `pi-agent-core` 이벤트를 OpenClaw `agent` 스트림으로 브리지합니다: - 도구 이벤트 => `stream: "tool"` - assistant 델타 => `stream: "assistant"` - 수명 주기 이벤트 => `stream: "lifecycle"` (`phase: "start" | "end" | "error"`) 5. `agent.wait`는 `waitForAgentRun`을 사용합니다: - - `runId`에 대한 **lifecycle end/error** 대기 + - `runId`에 대한 **수명 주기 end/error** 대기 - `{ status: ok|error|timeout, startedAt, endedAt, error? }` 반환 ## 큐잉 + 동시성 -- 실행은 세션 키(세션 레인)별로 직렬화되며 선택적으로 전역 레인을 통과합니다. -- 이를 통해 도구/세션 경쟁 상태를 방지하고 세션 기록의 일관성을 유지합니다. +- 실행은 세션 키(세션 레인)별로 직렬화되며, 필요에 따라 전역 레인을 통해서도 직렬화됩니다. +- 이렇게 하면 도구/세션 경쟁 상태를 방지하고 세션 히스토리를 일관되게 유지할 수 있습니다. - 메시징 채널은 이 레인 시스템에 연결되는 큐 모드(collect/steer/followup)를 선택할 수 있습니다. - 자세한 내용은 [Command Queue](/concepts/queue)를 참조하세요. + [명령 큐](/ko/concepts/queue)를 참고하세요. -## 세션 + workspace 준비 +## 세션 + 워크스페이스 준비 -- workspace가 확인 및 생성되며, 샌드박스 실행은 샌드박스 workspace 루트로 리디렉션될 수 있습니다. -- Skills가 로드되거나(또는 스냅샷에서 재사용되며) env와 프롬프트에 주입됩니다. -- bootstrap/context 파일이 확인되어 시스템 프롬프트 보고서에 주입됩니다. +- 워크스페이스가 확인되고 생성되며, 샌드박스 실행은 샌드박스 워크스페이스 루트로 리디렉션될 수 있습니다. +- Skills가 로드되거나(또는 스냅샷에서 재사용되거나) env 및 프롬프트에 주입됩니다. +- 부트스트랩/컨텍스트 파일이 확인되고 시스템 프롬프트 보고서에 주입됩니다. - 세션 쓰기 잠금이 획득되며, 스트리밍 전에 `SessionManager`가 열리고 준비됩니다. ## 프롬프트 조립 + 시스템 프롬프트 -- 시스템 프롬프트는 OpenClaw의 기본 프롬프트, skills 프롬프트, bootstrap 컨텍스트, 실행별 재정의로 구성됩니다. -- 모델별 제한과 compaction reserve 토큰이 강제 적용됩니다. -- 모델이 실제로 보는 내용은 [System prompt](/concepts/system-prompt)를 참조하세요. +- 시스템 프롬프트는 OpenClaw의 기본 프롬프트, skills 프롬프트, 부트스트랩 컨텍스트, 실행별 오버라이드로 구성됩니다. +- 모델별 제한과 compaction 예약 토큰이 강제 적용됩니다. +- 모델이 무엇을 보는지에 대해서는 [시스템 프롬프트](/ko/concepts/system-prompt)를 참고하세요. -## Hook 지점(가로챌 수 있는 위치) +## 훅 지점(가로챌 수 있는 위치) -OpenClaw에는 두 가지 hook 시스템이 있습니다. +OpenClaw에는 두 가지 훅 시스템이 있습니다: -- **내부 hooks**(Gateway hooks): 명령 및 수명 주기 이벤트를 위한 이벤트 기반 스크립트. -- **Plugin hooks**: 에이전트/도구 수명 주기와 gateway 파이프라인 내부의 확장 지점. +- **내부 훅**(Gateway hooks): 명령 및 수명 주기 이벤트를 위한 이벤트 기반 스크립트. +- **플러그인 훅**: 에이전트/도구 수명 주기 및 gateway 파이프라인 내부의 확장 지점. -### 내부 hooks (Gateway hooks) +### 내부 훅(Gateway hooks) -- **`agent:bootstrap`**: 시스템 프롬프트가 최종 확정되기 전에 bootstrap 파일을 빌드하는 동안 실행됩니다. - bootstrap 컨텍스트 파일을 추가/제거할 때 사용합니다. -- **명령 hooks**: `/new`, `/reset`, `/stop` 및 기타 명령 이벤트(Hooks 문서 참조). +- **`agent:bootstrap`**: 시스템 프롬프트가 최종 확정되기 전에 부트스트랩 파일을 빌드하는 동안 실행됩니다. + 부트스트랩 컨텍스트 파일을 추가/제거하는 데 사용합니다. +- **명령 훅**: `/new`, `/reset`, `/stop` 및 기타 명령 이벤트(Hooks 문서 참고). -설정 및 예시는 [Hooks](/automation/hooks)를 참조하세요. +설정 및 예제는 [Hooks](/ko/automation/hooks)를 참고하세요. -### Plugin hooks (에이전트 + gateway 수명 주기) +### 플러그인 훅(에이전트 + gateway 수명 주기) -이들은 에이전트 루프 또는 gateway 파이프라인 내부에서 실행됩니다. +이 훅들은 에이전트 루프 또는 gateway 파이프라인 내부에서 실행됩니다: -- **`before_model_resolve`**: 모델 확인 전에 세션 사전 단계(`messages` 없음)에서 실행되어 provider/model을 결정적으로 재정의합니다. -- **`before_prompt_build`**: 세션 로드 후(`messages` 포함) 실행되어 프롬프트 제출 전에 `prependContext`, `systemPrompt`, `prependSystemContext`, 또는 `appendSystemContext`를 주입합니다. 턴별 동적 텍스트에는 `prependContext`를 사용하고, 시스템 프롬프트 공간에 들어가야 하는 안정적인 안내에는 system-context 필드를 사용하세요. -- **`before_agent_start`**: 레거시 호환성 hook으로 어느 단계에서든 실행될 수 있습니다. 위의 명시적 hooks를 우선 사용하세요. -- **`before_agent_reply`**: 인라인 동작 후 및 LLM 호출 전에 실행되며, plugin이 해당 턴을 점유하고 합성 응답을 반환하거나 턴 전체를 완전히 무음 처리할 수 있게 합니다. +- **`before_model_resolve`**: 세션 전(`messages` 없음)에 실행되어, 모델 확인 전에 provider/model을 결정적으로 오버라이드합니다. +- **`before_prompt_build`**: 세션 로드 후(`messages` 포함) 실행되어, 프롬프트 제출 전에 `prependContext`, `systemPrompt`, `prependSystemContext`, 또는 `appendSystemContext`를 주입합니다. 턴별 동적 텍스트에는 `prependContext`를 사용하고, 시스템 프롬프트 공간에 배치되어야 하는 안정적인 지침에는 system-context 필드를 사용하세요. +- **`before_agent_start`**: 레거시 호환성 훅으로, 두 단계 중 어느 쪽에서든 실행될 수 있습니다. 가능하면 위의 명시적 훅을 우선 사용하세요. +- **`before_agent_reply`**: 인라인 작업 후, 그리고 LLM 호출 전에 실행되어, 플러그인이 해당 턴을 가져가 합성 응답을 반환하거나 턴 자체를 완전히 무음 처리할 수 있게 합니다. - **`agent_end`**: 완료 후 최종 메시지 목록과 실행 메타데이터를 검사합니다. - **`before_compaction` / `after_compaction`**: compaction 주기를 관찰하거나 주석을 추가합니다. - **`before_tool_call` / `after_tool_call`**: 도구 매개변수/결과를 가로챕니다. -- **`before_install`**: 내장 스캔 결과를 검사하고 skill 또는 plugin 설치를 선택적으로 차단합니다. +- **`before_install`**: 내장 스캔 결과를 검사하고 skill 또는 플러그인 설치를 선택적으로 차단합니다. - **`tool_result_persist`**: 도구 결과가 세션 기록에 기록되기 전에 동기적으로 변환합니다. -- **`message_received` / `message_sending` / `message_sent`**: 수신 + 발신 메시지 hooks. +- **`message_received` / `message_sending` / `message_sent`**: 수신 + 발신 메시지 훅. - **`session_start` / `session_end`**: 세션 수명 주기 경계. - **`gateway_start` / `gateway_stop`**: gateway 수명 주기 이벤트. -발신/도구 가드에 대한 hook 결정 규칙: +발신/도구 가드에 대한 훅 결정 규칙: -- `before_tool_call`: `{ block: true }`는 최종 결정이며 더 낮은 우선순위 핸들러를 중단합니다. +- `before_tool_call`: `{ block: true }`는 종료 동작이며 더 낮은 우선순위의 핸들러를 중단합니다. - `before_tool_call`: `{ block: false }`는 no-op이며 이전 block을 해제하지 않습니다. -- `before_install`: `{ block: true }`는 최종 결정이며 더 낮은 우선순위 핸들러를 중단합니다. +- `before_install`: `{ block: true }`는 종료 동작이며 더 낮은 우선순위의 핸들러를 중단합니다. - `before_install`: `{ block: false }`는 no-op이며 이전 block을 해제하지 않습니다. -- `message_sending`: `{ cancel: true }`는 최종 결정이며 더 낮은 우선순위 핸들러를 중단합니다. +- `message_sending`: `{ cancel: true }`는 종료 동작이며 더 낮은 우선순위의 핸들러를 중단합니다. - `message_sending`: `{ cancel: false }`는 no-op이며 이전 cancel을 해제하지 않습니다. -hook API 및 등록 세부 사항은 [Plugin hooks](/plugins/architecture#provider-runtime-hooks)를 참조하세요. +훅 API와 등록 세부 정보는 [플러그인 훅](/ko/plugins/architecture#provider-runtime-hooks)을 참고하세요. ## 스트리밍 + 부분 응답 -- Assistant 델타는 pi-agent-core에서 스트리밍되며 `assistant` 이벤트로 발생합니다. -- Block streaming은 `text_end` 또는 `message_end`에서 부분 응답을 발생시킬 수 있습니다. -- Reasoning streaming은 별도 스트림 또는 block reply로 발생할 수 있습니다. -- 청크 분할 및 block reply 동작은 [Streaming](/concepts/streaming)을 참조하세요. +- assistant 델타는 `pi-agent-core`에서 스트리밍되어 `assistant` 이벤트로 내보내집니다. +- 블록 스트리밍은 `text_end` 또는 `message_end`에서 부분 응답을 내보낼 수 있습니다. +- reasoning 스트리밍은 별도의 스트림으로 또는 블록 응답으로 내보낼 수 있습니다. +- 청킹 및 블록 응답 동작은 [스트리밍](/ko/concepts/streaming)을 참고하세요. ## 도구 실행 + 메시징 도구 -- 도구 시작/업데이트/종료 이벤트는 `tool` 스트림에서 발생합니다. -- 도구 결과는 기록/발생 전에 크기와 이미지 페이로드 기준으로 정리됩니다. -- 메시징 도구 전송은 중복 assistant 확인 메시지를 억제하기 위해 추적됩니다. +- 도구 start/update/end 이벤트는 `tool` 스트림으로 내보내집니다. +- 도구 결과는 로깅/내보내기 전에 크기와 이미지 페이로드 기준으로 정리됩니다. +- 메시징 도구 전송은 중복된 assistant 확인 메시지를 억제하기 위해 추적됩니다. ## 응답 형태 조정 + 억제 - 최종 페이로드는 다음으로 조립됩니다: - assistant 텍스트(및 선택적 reasoning) - 인라인 도구 요약(verbose + 허용 시) - - 모델 오류 시 assistant 오류 텍스트 -- 정확히 `NO_REPLY` / `no_reply`인 무응답 토큰은 발신 + - 모델 오류 발생 시 assistant 오류 텍스트 +- 정확한 무음 토큰 `NO_REPLY` / `no_reply`는 발신 페이로드에서 필터링됩니다. -- 메시징 도구 중복은 최종 페이로드 목록에서 제거됩니다. -- 렌더링 가능한 페이로드가 남지 않았고 도구 오류가 발생한 경우, - 폴백 도구 오류 응답이 발생합니다 +- 메시징 도구 중복 항목은 최종 페이로드 목록에서 제거됩니다. +- 렌더링 가능한 페이로드가 남지 않았고 도구에서 오류가 발생한 경우, 대체 도구 오류 응답이 내보내집니다 (단, 메시징 도구가 이미 사용자에게 보이는 응답을 보낸 경우는 제외). ## Compaction + 재시도 -- 자동 compaction은 `compaction` 스트림 이벤트를 발생시키고 재시도를 트리거할 수 있습니다. -- 재시도 시 중복 출력을 피하기 위해 메모리 내 버퍼와 도구 요약이 재설정됩니다. -- compaction 파이프라인은 [Compaction](/concepts/compaction)을 참조하세요. +- 자동 compaction은 `compaction` 스트림 이벤트를 내보내고 재시도를 유발할 수 있습니다. +- 재시도 시, 중복 출력을 방지하기 위해 메모리 내 버퍼와 도구 요약이 재설정됩니다. +- compaction 파이프라인은 [Compaction](/ko/concepts/compaction)을 참고하세요. ## 이벤트 스트림(현재) -- `lifecycle`: `subscribeEmbeddedPiSession`에서 발생(그리고 폴백으로 `agentCommand`에서도 발생) -- `assistant`: pi-agent-core의 스트리밍 델타 -- `tool`: pi-agent-core의 스트리밍 도구 이벤트 +- `lifecycle`: `subscribeEmbeddedPiSession`에서 내보냄(`agentCommand`에서 대체용으로도 내보냄) +- `assistant`: `pi-agent-core`의 스트리밍 델타 +- `tool`: `pi-agent-core`의 스트리밍 도구 이벤트 ## 채팅 채널 처리 -- Assistant 델타는 채팅 `delta` 메시지로 버퍼링됩니다. -- 채팅 `final`은 **lifecycle end/error**에서 발생합니다. +- assistant 델타는 채팅 `delta` 메시지로 버퍼링됩니다. +- 채팅 `final`은 **수명 주기 end/error**에서 내보내집니다. -## 타임아웃 +## 제한 시간 -- `agent.wait` 기본값: 30초(wait만 해당). `timeoutMs` 매개변수로 재정의 가능. -- 에이전트 런타임: `agents.defaults.timeoutSeconds` 기본값 172800초(48시간); `runEmbeddedPiAgent`의 중단 타이머에서 강제 적용. +- `agent.wait` 기본값: 30초(대기만 해당). `timeoutMs` 매개변수로 재정의합니다. +- 에이전트 런타임: `agents.defaults.timeoutSeconds` 기본값은 172800초(48시간)이며, `runEmbeddedPiAgent`의 abort 타이머에서 강제 적용됩니다. +- LLM 유휴 제한 시간: `agents.defaults.llm.idleTimeoutSeconds`는 유휴 시간 창 안에 응답 청크가 도착하지 않으면 모델 요청을 중단합니다. 느린 로컬 모델 또는 reasoning/도구 호출 provider에 대해 명시적으로 설정하세요. 비활성화하려면 0으로 설정하세요. 설정되지 않은 경우, OpenClaw는 `agents.defaults.timeoutSeconds`가 구성되어 있으면 이를 사용하고, 그렇지 않으면 60초를 사용합니다. 명시적인 LLM 또는 에이전트 제한 시간이 없는 cron 트리거 실행은 유휴 watchdog을 비활성화하고 cron 외부 제한 시간에 의존합니다. -## 조기 종료될 수 있는 위치 +## 조기에 종료될 수 있는 위치 -- 에이전트 타임아웃(중단) -- AbortSignal(취소) -- Gateway 연결 해제 또는 RPC 타임아웃 -- `agent.wait` 타임아웃(wait만 해당, 에이전트를 중지하지는 않음) +- 에이전트 제한 시간(abort) +- AbortSignal(cancel) +- Gateway 연결 해제 또는 RPC 제한 시간 +- `agent.wait` 제한 시간(대기만 해당하며, 에이전트를 중지하지는 않음) ## 관련 문서 -- [Tools](/tools) — 사용 가능한 에이전트 도구 -- [Hooks](/automation/hooks) — 에이전트 수명 주기 이벤트에 의해 트리거되는 이벤트 기반 스크립트 -- [Compaction](/concepts/compaction) — 긴 대화가 요약되는 방식 -- [Exec Approvals](/tools/exec-approvals) — 셸 명령에 대한 승인 게이트 -- [Thinking](/tools/thinking) — thinking/reasoning 수준 구성 +- [도구](/ko/tools) — 사용 가능한 에이전트 도구 +- [Hooks](/ko/automation/hooks) — 에이전트 수명 주기 이벤트에 의해 트리거되는 이벤트 기반 스크립트 +- [Compaction](/ko/concepts/compaction) — 긴 대화가 요약되는 방식 +- [Exec Approvals](/ko/tools/exec-approvals) — 셸 명령에 대한 승인 게이트 +- [Thinking](/ko/tools/thinking) — thinking/reasoning 수준 구성 diff --git a/docs/ko/concepts/dreaming.md b/docs/ko/concepts/dreaming.md index c3ad8c79e..ab7b81e82 100644 --- a/docs/ko/concepts/dreaming.md +++ b/docs/ko/concepts/dreaming.md @@ -1,15 +1,15 @@ --- read_when: - - 메모리 승격이 자동으로 실행되길 원합니다 + - 메모리 승격이 자동으로 실행되도록 하고 싶습니다 - 각 dreaming 단계가 무엇을 하는지 이해하고 싶습니다 - MEMORY.md를 오염시키지 않고 통합을 조정하고 싶습니다 -summary: Dream Diary와 함께 light, deep, REM 단계로 이루어진 백그라운드 메모리 통합 +summary: 가벼운 수면, 깊은 수면, REM 단계와 Dream Diary를 포함한 백그라운드 메모리 통합 title: Dreaming (실험적) x-i18n: - generated_at: "2026-04-06T06:00:21Z" + generated_at: "2026-04-09T01:27:50Z" model: gpt-5.4 provider: openai - source_hash: 36c4b1e70801d662090dc8ce20608c2f141c23cd7ce53c54e3dcf332c801fd4e + source_hash: 26476eddb8260e1554098a6adbb069cf7f5e284cf2e09479c6d9d8f8b93280ef source_path: concepts/dreaming.md workflow: 15 --- @@ -18,7 +18,7 @@ x-i18n: Dreaming은 `memory-core`의 백그라운드 메모리 통합 시스템입니다. 이 기능은 OpenClaw가 강한 단기 신호를 오래 유지되는 메모리로 옮기도록 도우면서, -그 과정이 설명 가능하고 검토 가능하도록 유지합니다. +과정을 설명 가능하고 검토 가능하게 유지합니다. Dreaming은 **옵트인** 기능이며 기본적으로 비활성화되어 있습니다. @@ -26,40 +26,40 @@ Dreaming은 **옵트인** 기능이며 기본적으로 비활성화되어 있습 Dreaming은 두 종류의 출력을 유지합니다. -- `memory/.dreams/`의 **머신 상태**(리콜 저장소, 단계 신호, 수집 체크포인트, 잠금). -- `DREAMS.md`(또는 기존 `dreams.md`)의 **사람이 읽을 수 있는 출력**, 그리고 선택적으로 `memory/dreaming//YYYY-MM-DD.md` 아래의 단계 보고서 파일. +- `memory/.dreams/`의 **기계 상태**(recall 저장소, 단계 신호, 수집 체크포인트, 잠금). +- `DREAMS.md`(또는 기존 `dreams.md`)의 **사람이 읽을 수 있는 출력**와 `memory/dreaming//YYYY-MM-DD.md` 아래의 선택적 단계 보고서 파일. 장기 승격은 계속해서 `MEMORY.md`에만 기록됩니다. ## 단계 모델 -Dreaming은 협력적으로 동작하는 세 단계로 이루어져 있습니다. +Dreaming은 세 가지 협력 단계로 동작합니다. | 단계 | 목적 | 영구 기록 | | ----- | ---- | --------- | -| Light | 최근 단기 자료를 정렬하고 준비 | 아니요 | -| Deep | 오래 유지할 후보를 점수화하고 승격 | 예 (`MEMORY.md`) | -| REM | 주제와 반복되는 아이디어를 되돌아봄 | 아니요 | +| Light | 최근 단기 자료 정렬 및 준비 | 아니요 | +| Deep | 오래 유지할 후보 점수화 및 승격 | 예 (`MEMORY.md`) | +| REM | 주제와 반복되는 아이디어 성찰 | 아니요 | 이 단계들은 별도의 사용자 설정 "모드"가 아니라 내부 구현 세부 사항입니다. ### Light 단계 -Light 단계는 최근 일일 메모리 신호와 리콜 추적을 수집하고, 중복을 제거한 뒤, -후보 줄을 준비합니다. +Light 단계는 최근 일일 메모리 신호와 recall 추적을 수집하고, 중복을 제거한 뒤, +후보 라인을 준비합니다. -- 단기 리콜 상태와 최근 일일 메모리 파일에서 읽습니다. +- 사용 가능한 경우 단기 recall 상태, 최근 일일 메모리 파일, 그리고 민감 정보가 제거된 세션 대화록을 읽습니다. - 저장소에 인라인 출력이 포함된 경우 관리되는 `## Light Sleep` 블록을 기록합니다. -- 이후 deep 순위 산정에 사용할 강화 신호를 기록합니다. -- 절대 `MEMORY.md`에 기록하지 않습니다. +- 이후 deep 순위 산정을 위한 강화 신호를 기록합니다. +- 절대로 `MEMORY.md`에 기록하지 않습니다. ### Deep 단계 Deep 단계는 무엇이 장기 메모리가 될지 결정합니다. -- 가중치가 적용된 점수와 임계값 게이트를 사용해 후보의 순위를 매깁니다. -- `minScore`, `minRecallCount`, `minUniqueQueries`를 모두 통과해야 합니다. -- 기록 전에 실제 일일 파일에서 스니펫을 다시 불러오므로, 오래되었거나 삭제된 스니펫은 건너뜁니다. +- 가중치 기반 점수와 임계값 게이트를 사용해 후보의 순위를 매깁니다. +- 통과하려면 `minScore`, `minRecallCount`, `minUniqueQueries`가 필요합니다. +- 기록 전에 실제 일일 파일에서 스니펫을 다시 가져오므로, 오래되었거나 삭제된 스니펫은 건너뜁니다. - 승격된 항목을 `MEMORY.md`에 추가합니다. - `DREAMS.md`에 `## Deep Sleep` 요약을 기록하고, 선택적으로 `memory/dreaming/deep/YYYY-MM-DD.md`도 기록합니다. @@ -67,36 +67,55 @@ Deep 단계는 무엇이 장기 메모리가 될지 결정합니다. REM 단계는 패턴과 성찰 신호를 추출합니다. -- 최근 단기 추적에서 주제 및 성찰 요약을 만듭니다. +- 최근 단기 추적에서 주제 및 성찰 요약을 생성합니다. - 저장소에 인라인 출력이 포함된 경우 관리되는 `## REM Sleep` 블록을 기록합니다. - deep 순위 산정에 사용되는 REM 강화 신호를 기록합니다. -- 절대 `MEMORY.md`에 기록하지 않습니다. +- 절대로 `MEMORY.md`에 기록하지 않습니다. + +## 세션 대화록 수집 + +Dreaming은 민감 정보가 제거된 세션 대화록을 dreaming 코퍼스에 수집할 수 있습니다. +대화록을 사용할 수 있는 경우, 일일 메모리 신호와 recall 추적과 함께 light 단계에 +입력됩니다. 개인 정보와 민감한 내용은 수집 전에 제거됩니다. ## Dream Diary Dreaming은 또한 `DREAMS.md`에 서술형 **Dream Diary**를 유지합니다. -각 단계에 충분한 자료가 쌓이면 `memory-core`는 최선 노력 방식의 백그라운드 -서브에이전트 턴을 실행하고(기본 런타임 모델 사용), 짧은 일지 항목을 추가합니다. +각 단계에 충분한 자료가 쌓이면 `memory-core`는 최선형 백그라운드 서브에이전트 +턴(기본 런타임 모델 사용)을 실행하고 짧은 일지 항목을 추가합니다. 이 일지는 Dreams UI에서 사람이 읽기 위한 것이며, 승격 소스는 아닙니다. +검토 및 복구 작업을 위한 근거 기반 과거 백필 경로도 있습니다. + +- `memory rem-harness --path ... --grounded`는 과거 `YYYY-MM-DD.md` 노트에서 근거 기반 일지 출력을 미리 봅니다. +- `memory rem-backfill --path ...`는 되돌릴 수 있는 근거 기반 일지 항목을 `DREAMS.md`에 기록합니다. +- `memory rem-backfill --path ... --stage-short-term`은 일반 deep 단계가 이미 사용하는 것과 동일한 단기 증거 저장소에 근거 기반의 오래 유지할 후보를 준비합니다. +- `memory rem-backfill --rollback` 및 `--rollback-short-term`은 일반 일지 항목이나 실시간 단기 recall을 건드리지 않고 이렇게 준비된 백필 아티팩트를 제거합니다. + +Control UI는 동일한 일지 백필/재설정 흐름을 제공하므로, 어떤 근거 기반 후보가 +승격될 가치가 있는지 결정하기 전에 Dreams 장면에서 결과를 검사할 수 있습니다. +장면은 또한 별도의 근거 기반 레인도 표시하므로, 어떤 준비된 단기 항목이 과거 +재생에서 왔는지, 어떤 승격된 항목이 근거 기반 주도로 이루어졌는지 확인하고, +일반 실시간 단기 상태를 건드리지 않고 근거 기반 전용 준비 항목만 지울 수 있습니다. + ## Deep 순위 산정 신호 -Deep 순위 산정은 6개의 가중 기본 신호와 단계 강화 신호를 사용합니다. +Deep 순위 산정은 6개의 가중치 기반 기본 신호와 단계 강화 신호를 사용합니다. | 신호 | 가중치 | 설명 | -| ------------------- | ------ | ------------------------------------------------- | -| 빈도 | 0.24 | 항목이 누적한 단기 신호 수 | -| 관련성 | 0.30 | 해당 항목의 평균 검색 품질 | -| 쿼리 다양성 | 0.15 | 해당 항목이 드러난 서로 다른 쿼리/일 컨텍스트 | -| 최신성 | 0.15 | 시간 감쇠가 적용된 최신성 점수 | -| 통합도 | 0.10 | 여러 날에 걸친 반복 강도 | -| 개념적 풍부함 | 0.06 | 스니펫/경로의 개념 태그 밀도 | +| ---- | ------ | ---- | +| 빈도 | 0.24 | 항목이 축적한 단기 신호 수 | +| 관련성 | 0.30 | 항목의 평균 검색 품질 | +| 쿼리 다양성 | 0.15 | 해당 항목이 드러난 서로 다른 쿼리/일자 맥락 | +| 최신성 | 0.15 | 시간 감쇠 기반 신선도 점수 | +| 통합도 | 0.10 | 여러 날에 걸친 반복 강도 | +| 개념적 풍부함 | 0.06 | 스니펫/경로의 개념 태그 밀도 | Light 및 REM 단계 적중은 -`memory/.dreams/phase-signals.json`에서 작은 최신성 감쇠 부스트를 추가합니다. +`memory/.dreams/phase-signals.json`에서 작은 최신성 감쇠 기반 부스트를 추가합니다. -## 일정 관리 +## 스케줄링 활성화되면 `memory-core`는 전체 dreaming 스윕을 위한 cron 작업 하나를 자동 관리합니다. 각 스윕은 단계를 순서대로 실행합니다: light -> REM -> deep. @@ -104,7 +123,7 @@ Light 및 REM 단계 적중은 기본 주기 동작: | 설정 | 기본값 | -| -------------------- | ----------- | +| ---- | ------ | | `dreaming.frequency` | `0 3 * * *` | ## 빠른 시작 @@ -158,7 +177,7 @@ dreaming 활성화: ## CLI 워크플로 -미리 보기 또는 수동 적용에는 CLI 승격을 사용하세요. +미리 보기 또는 수동 적용에는 CLI 승격을 사용합니다. ```bash openclaw memory promote @@ -176,7 +195,7 @@ openclaw memory promote-explain "router vlan" openclaw memory promote-explain "router vlan" --json ``` -아무것도 기록하지 않고 REM 성찰, 후보 사실, deep 승격 출력을 미리 봅니다. +아무 것도 기록하지 않고 REM 성찰, 후보 사실, deep 승격 출력을 미리 봅니다. ```bash openclaw memory rem-harness @@ -188,7 +207,7 @@ openclaw memory rem-harness --json 모든 설정은 `plugins.entries.memory-core.config.dreaming` 아래에 있습니다. | 키 | 기본값 | -| ----------- | ----------- | +| --- | ------ | | `enabled` | `false` | | `frequency` | `0 3 * * *` | @@ -199,15 +218,16 @@ openclaw memory rem-harness --json ## Dreams UI -활성화되면 Gateway의 **Dreams** 탭에 다음이 표시됩니다. +활성화되면 Gateway **Dreams** 탭에는 다음이 표시됩니다. - 현재 dreaming 활성화 상태 - 단계별 상태와 관리형 스윕 존재 여부 -- 단기, 장기, 오늘 승격된 항목 수 -- 다음 예약 실행 시각 +- 단기, 근거 기반, 신호, 오늘 승격 수 +- 다음 예약 실행 시점 +- 과거 재생 항목을 준비하는 별도의 근거 기반 장면 레인 - `doctor.memory.dreamDiary`를 기반으로 하는 확장 가능한 Dream Diary 리더 -## 관련 항목 +## 관련 문서 - [메모리](/ko/concepts/memory) - [메모리 검색](/ko/concepts/memory-search) diff --git a/docs/ko/concepts/memory.md b/docs/ko/concepts/memory.md index 902a0a4af..d4c7dc1d8 100644 --- a/docs/ko/concepts/memory.md +++ b/docs/ko/concepts/memory.md @@ -1,83 +1,83 @@ --- read_when: - 메모리가 어떻게 작동하는지 이해하고 싶을 때 - - 어떤 메모리 파일을 작성해야 하는지 알고 싶을 때 -summary: OpenClaw가 세션 전반에 걸쳐 정보를 기억하는 방식 + - 어떤 메모리 파일에 작성해야 하는지 알고 싶을 때 +summary: OpenClaw가 세션 전반에 걸쳐 정보를 기억하는 방법 title: 메모리 개요 x-i18n: - generated_at: "2026-04-08T05:55:50Z" + generated_at: "2026-04-09T01:27:57Z" model: gpt-5.4 provider: openai - source_hash: 3bb8552341b0b651609edaaae826a22fdc535d240aed4fad4af4b069454004af + source_hash: 2fe47910f5bf1c44be379e971c605f1cb3a29befcf2a7ee11fb3833cbe3b9059 source_path: concepts/memory.md workflow: 15 --- # 메모리 개요 -OpenClaw는 에이전트의 작업 공간에 **일반 Markdown 파일**을 작성하여 정보를 기억합니다. 모델은 디스크에 저장된 내용만 "기억"하며, 숨겨진 상태는 없습니다. +OpenClaw는 에이전트의 워크스페이스에 **일반 Markdown 파일**을 작성하여 정보를 기억합니다. 모델이 "기억하는" 것은 디스크에 저장된 내용뿐이며, 숨겨진 상태는 없습니다. ## 작동 방식 -에이전트에는 메모리와 관련된 파일이 세 가지 있습니다: +에이전트에는 메모리와 관련된 파일이 세 가지 있습니다. -- **`MEMORY.md`** -- 장기 메모리. 오래 유지되는 사실, 선호, 결정 사항입니다. 모든 DM 세션 시작 시 로드됩니다. -- **`memory/YYYY-MM-DD.md`** -- 일일 노트. 진행 중인 컨텍스트와 관찰 내용을 담습니다. 오늘과 어제의 노트는 자동으로 로드됩니다. -- **`DREAMS.md`** (실험적, 선택 사항) -- 사람이 검토할 수 있도록 만든 Dream Diary 및 dreaming sweep 요약입니다. +- **`MEMORY.md`** -- 장기 메모리입니다. 지속되는 사실, 선호 사항, 결정 사항을 담습니다. 모든 DM 세션이 시작될 때 로드됩니다. +- **`memory/YYYY-MM-DD.md`** -- 일일 노트입니다. 진행 중인 컨텍스트와 관찰 내용을 담습니다. 오늘과 어제의 노트는 자동으로 로드됩니다. +- **`DREAMS.md`** (실험적, 선택 사항) -- 사람의 검토를 위한 Dream Diary 및 dreaming sweep 요약을 담으며, 근거 기반의 과거 백필 항목도 포함합니다. -이 파일들은 에이전트 작업 공간(기본값: `~/.openclaw/workspace`)에 있습니다. +이 파일들은 에이전트 워크스페이스에 있습니다(기본값 `~/.openclaw/workspace`). -에이전트가 무언가를 기억하길 원한다면 그냥 이렇게 요청하면 됩니다: "내가 TypeScript를 선호한다고 기억해." 그러면 적절한 파일에 기록합니다. +에이전트가 무언가를 기억하길 원한다면, 그냥 이렇게 요청하면 됩니다: "내가 TypeScript를 선호한다고 기억해." 그러면 적절한 파일에 기록합니다. ## 메모리 도구 -에이전트에는 메모리를 다루기 위한 두 가지 도구가 있습니다: +에이전트에는 메모리를 다루기 위한 두 가지 도구가 있습니다. - **`memory_search`** -- 원문과 표현이 달라도 시맨틱 검색을 사용해 관련 노트를 찾습니다. - **`memory_get`** -- 특정 메모리 파일 또는 줄 범위를 읽습니다. -두 도구 모두 활성 메모리 plugin(기본값: `memory-core`)에서 제공합니다. +두 도구 모두 활성 메모리 플러그인(기본값: `memory-core`)에서 제공합니다. -## Memory Wiki companion plugin +## Memory Wiki 컴패니언 플러그인 -지속 메모리가 단순한 원시 노트보다 관리되는 지식 베이스처럼 동작하길 원한다면, 번들된 `memory-wiki` plugin을 사용하세요. +지속 메모리가 단순한 원시 노트가 아니라 관리되는 지식 베이스처럼 동작하길 원한다면, 번들된 `memory-wiki` 플러그인을 사용하세요. -`memory-wiki`는 지속 지식을 다음 요소를 갖춘 위키 볼트로 컴파일합니다: +`memory-wiki`는 지속 지식을 위키 볼트로 컴파일하며, 다음을 제공합니다. -- 결정론적 페이지 구조 -- 구조화된 주장과 근거 +- 결정론적인 페이지 구조 +- 구조화된 주장과 증거 - 모순 및 최신성 추적 - 생성된 대시보드 - 에이전트/런타임 소비자를 위한 컴파일된 다이제스트 - `wiki_search`, `wiki_get`, `wiki_apply`, `wiki_lint` 같은 위키 네이티브 도구 -이 plugin은 활성 메모리 plugin을 대체하지 않습니다. 활성 메모리 plugin은 여전히 회상, 승격, dreaming을 담당합니다. `memory-wiki`는 그 옆에 출처 정보가 풍부한 지식 계층을 추가합니다. +이 플러그인은 활성 메모리 플러그인을 대체하지 않습니다. 활성 메모리 플러그인은 여전히 회상, 승격, dreaming을 담당합니다. `memory-wiki`는 그 옆에 출처가 풍부한 지식 계층을 추가합니다. 자세한 내용은 [Memory Wiki](/ko/plugins/memory-wiki)를 참조하세요. ## 메모리 검색 -임베딩 provider가 구성되어 있으면 `memory_search`는 **하이브리드 검색**을 사용합니다. 즉, 벡터 유사도(의미적 의미)와 키워드 매칭(ID 및 코드 심볼 같은 정확한 용어)을 결합합니다. 지원되는 provider 중 하나의 API 키만 있으면 별도 설정 없이 바로 동작합니다. +임베딩 제공자가 구성되어 있으면 `memory_search`는 **하이브리드 검색**을 사용합니다. 즉, 벡터 유사도(의미적 의미)와 키워드 매칭(ID나 코드 심볼 같은 정확한 용어)을 결합합니다. 지원되는 제공자 중 하나의 API 키만 있으면 바로 사용할 수 있습니다. -OpenClaw는 사용 가능한 API 키를 바탕으로 임베딩 provider를 자동 감지합니다. OpenAI, Gemini, Voyage 또는 Mistral 키가 구성되어 있으면 메모리 검색이 자동으로 활성화됩니다. +OpenClaw는 사용 가능한 API 키를 바탕으로 임베딩 제공자를 자동 감지합니다. OpenAI, Gemini, Voyage 또는 Mistral 키가 구성되어 있으면 메모리 검색이 자동으로 활성화됩니다. -검색 작동 방식, 튜닝 옵션, provider 설정에 대한 자세한 내용은 [Memory Search](/ko/concepts/memory-search)를 참조하세요. +검색 작동 방식, 튜닝 옵션, 제공자 설정에 대한 자세한 내용은 [Memory Search](/ko/concepts/memory-search)를 참조하세요. ## 메모리 백엔드 -SQLite 기반입니다. 키워드 검색, 벡터 유사도, 하이브리드 검색을 별도 설정 없이 사용할 수 있습니다. 추가 의존성이 필요하지 않습니다. +SQLite 기반입니다. 키워드 검색, 벡터 유사도, 하이브리드 검색을 즉시 사용할 수 있습니다. 추가 의존성이 필요 없습니다. -재순위 지정, 쿼리 확장, 작업 공간 외부 디렉터리 인덱싱 기능을 갖춘 로컬 우선 사이드카입니다. +재순위 지정, 쿼리 확장, 워크스페이스 외부 디렉터리 인덱싱 기능을 갖춘 로컬 우선 사이드카입니다. -사용자 모델링, 시맨틱 검색, 멀티 에이전트 인식을 지원하는 AI 네이티브 교차 세션 메모리입니다. plugin 설치가 필요합니다. +사용자 모델링, 시맨틱 검색, 멀티 에이전트 인식을 갖춘 AI 네이티브 크로스세션 메모리입니다. 플러그인을 설치해야 합니다. @@ -85,35 +85,63 @@ SQLite 기반입니다. 키워드 검색, 벡터 유사도, 하이브리드 검 -주장, 대시보드, bridge mode, Obsidian 친화적 워크플로를 갖춘 출처 정보가 풍부한 위키 볼트로 지속 메모리를 컴파일합니다. +지속 메모리를 주장, 대시보드, 브리지 모드, Obsidian 친화적 워크플로를 갖춘 출처 풍부한 위키 볼트로 컴파일합니다. ## 자동 메모리 플러시 -[compaction](/ko/concepts/compaction)이 대화를 요약하기 전에 OpenClaw는 에이전트에게 중요한 컨텍스트를 메모리 파일에 저장하라고 상기시키는 무음 턴을 실행합니다. 이것은 기본적으로 활성화되어 있으므로 별도로 설정할 필요가 없습니다. +[compaction](/ko/concepts/compaction)이 대화를 요약하기 전에, OpenClaw는 에이전트에게 중요한 컨텍스트를 메모리 파일에 저장하라고 상기시키는 조용한 턴을 실행합니다. 이 기능은 기본적으로 켜져 있으므로 별도로 설정할 필요가 없습니다. -메모리 플러시는 compaction 중 컨텍스트 손실을 방지합니다. 대화에 중요한 사실이 있지만 아직 파일에 기록되지 않았다면, 요약이 이루어지기 전에 자동으로 저장됩니다. +메모리 플러시는 compaction 중 컨텍스트 손실을 방지합니다. 대화에 중요한 사실이 아직 파일에 기록되지 않았다면, 요약이 이루어지기 전에 자동으로 저장됩니다. ## Dreaming (실험적) -Dreaming은 메모리를 위한 선택적 백그라운드 통합 패스입니다. 단기 신호를 수집하고, 후보를 점수화하며, 기준을 충족한 항목만 장기 메모리(`MEMORY.md`)로 승격합니다. +Dreaming은 메모리를 위한 선택적 백그라운드 통합 패스입니다. 단기 신호를 수집하고, 후보를 점수화하며, 자격을 충족한 항목만 장기 메모리(`MEMORY.md`)로 승격합니다. -장기 메모리의 신호 대 잡음비를 높게 유지하도록 설계되었습니다: +이 기능은 장기 메모리의 신호 대 잡음비를 높게 유지하도록 설계되었습니다. -- **옵트인**: 기본적으로 비활성화되어 있습니다. +- **Opt-in**: 기본적으로 비활성화되어 있습니다. - **예약 실행**: 활성화되면 `memory-core`가 전체 dreaming sweep을 위한 반복 cron 작업 하나를 자동으로 관리합니다. -- **임곗값 기반**: 승격은 점수, 회상 빈도, 쿼리 다양성 게이트를 통과해야 합니다. -- **검토 가능**: 단계별 요약과 다이어리 항목이 사람이 검토할 수 있도록 `DREAMS.md`에 기록됩니다. +- **임곗값 적용**: 승격은 점수, 회상 빈도, 쿼리 다양성 게이트를 통과해야 합니다. +- **검토 가능**: 단계 요약과 다이어리 항목이 사람이 검토할 수 있도록 `DREAMS.md`에 기록됩니다. -단계 동작, 점수화 신호, Dream Diary 세부 정보는 [Dreaming (experimental)](/ko/concepts/dreaming)을 참조하세요. +단계별 동작, 점수 신호, Dream Diary 세부 정보는 [Dreaming (experimental)](/ko/concepts/dreaming)을 참조하세요. + +## 근거 기반 백필과 라이브 승격 + +dreaming 시스템에는 이제 밀접하게 연관된 두 가지 검토 경로가 있습니다. + +- **라이브 dreaming**은 `memory/.dreams/` 아래의 단기 dreaming 저장소를 기반으로 작동하며, 일반적인 딥 단계가 무엇을 `MEMORY.md`로 승격할 수 있는지 결정할 때 사용하는 방식입니다. +- **근거 기반 백필**은 과거의 `memory/YYYY-MM-DD.md` 노트를 독립적인 일일 파일로 읽고, 구조화된 검토 출력을 `DREAMS.md`에 기록합니다. + +근거 기반 백필은 `MEMORY.md`를 수동으로 편집하지 않고도 오래된 노트를 다시 처리하고 시스템이 무엇을 지속적인 정보로 판단하는지 확인하고 싶을 때 유용합니다. + +다음 명령을 사용하면: + +```bash +openclaw memory rem-backfill --path ./memory --stage-short-term +``` + +근거 기반의 지속 후보는 직접 승격되지 않습니다. 대신 일반적인 딥 단계가 이미 사용하는 것과 동일한 단기 dreaming 저장소에 스테이징됩니다. 즉, 다음을 의미합니다. + +- `DREAMS.md`는 계속 사람 검토용 표면으로 남습니다. +- 단기 저장소는 계속 머신 대상 순위화 표면으로 남습니다. +- `MEMORY.md`는 여전히 딥 승격에 의해서만 기록됩니다. + +재처리가 유용하지 않았다고 판단되면, 일반 다이어리 항목이나 정상적인 회상 상태를 건드리지 않고 스테이징된 아티팩트를 제거할 수 있습니다. + +```bash +openclaw memory rem-backfill --rollback +openclaw memory rem-backfill --rollback-short-term +``` ## CLI ```bash -openclaw memory status # 인덱스 상태와 provider 확인 +openclaw memory status # 인덱스 상태와 제공자 확인 openclaw memory search "query" # 명령줄에서 검색 openclaw memory index --force # 인덱스 다시 빌드 ``` @@ -122,9 +150,9 @@ openclaw memory index --force # 인덱스 다시 빌드 - [Builtin Memory Engine](/ko/concepts/memory-builtin) -- 기본 SQLite 백엔드 - [QMD Memory Engine](/ko/concepts/memory-qmd) -- 고급 로컬 우선 사이드카 -- [Honcho Memory](/ko/concepts/memory-honcho) -- AI 네이티브 교차 세션 메모리 +- [Honcho Memory](/ko/concepts/memory-honcho) -- AI 네이티브 크로스세션 메모리 - [Memory Wiki](/ko/plugins/memory-wiki) -- 컴파일된 지식 볼트 및 위키 네이티브 도구 -- [Memory Search](/ko/concepts/memory-search) -- 검색 파이프라인, provider, 튜닝 +- [Memory Search](/ko/concepts/memory-search) -- 검색 파이프라인, 제공자 및 튜닝 - [Dreaming (experimental)](/ko/concepts/dreaming) -- 단기 회상에서 장기 메모리로의 백그라운드 승격 - [Memory configuration reference](/ko/reference/memory-config) -- 모든 구성 옵션 - [Compaction](/ko/concepts/compaction) -- compaction이 메모리와 상호작용하는 방식 diff --git a/docs/ko/concepts/model-providers.md b/docs/ko/concepts/model-providers.md index 46ca326f6..7e1265309 100644 --- a/docs/ko/concepts/model-providers.md +++ b/docs/ko/concepts/model-providers.md @@ -1,40 +1,41 @@ --- read_when: - - provider별 모델 설정 참조가 필요합니다 - - 모델 provider용 예시 config 또는 CLI 온보딩 명령이 필요합니다 -summary: 예시 config와 CLI 흐름이 포함된 모델 provider 개요 -title: 모델 provider + - 제공자별 모델 설정 참고 자료가 필요합니다 + - 모델 제공자를 위한 예제 구성이나 CLI 온보딩 명령이 필요합니다 +summary: 예제 구성과 CLI 흐름이 포함된 모델 제공자 개요 +title: 모델 제공자 x-i18n: - generated_at: "2026-04-08T05:57:21Z" + generated_at: "2026-04-09T01:29:44Z" model: gpt-5.4 provider: openai - source_hash: 558ac9e34b67fcc3dd6791a01bebc17e1c34152fa6c5611593d681e8cfa532d9 + source_hash: 53e3141256781002bbe1d7e7b78724a18d061fcf36a203baae04a091b8c9ea1b source_path: concepts/model-providers.md workflow: 15 --- -# 모델 provider +# 모델 제공자 -이 페이지는 **LLM/모델 provider**를 다룹니다(WhatsApp/Telegram 같은 채팅 채널은 아님). -모델 선택 규칙은 [/concepts/models](/ko/concepts/models)을 참고하세요. +이 페이지는 **LLM/모델 제공자**를 다룹니다(WhatsApp/Telegram 같은 채팅 채널이 아님). +모델 선택 규칙은 [/concepts/models](/ko/concepts/models)을 참조하세요. ## 빠른 규칙 -- 모델 ref는 `provider/model`을 사용합니다(예: `opencode/claude-opus-4-6`). -- `agents.defaults.models`를 설정하면 allowlist가 됩니다. +- 모델 참조는 `provider/model` 형식을 사용합니다(예: `opencode/claude-opus-4-6`). +- `agents.defaults.models`를 설정하면 허용 목록이 됩니다. - CLI 도우미: `openclaw onboard`, `openclaw models list`, `openclaw models set `. -- 폴백 런타임 규칙, 쿨다운 프로브, 세션 override 지속성은 - [/concepts/model-failover](/ko/concepts/model-failover)에 설명되어 있습니다. -- `models.providers.*.models[].contextWindow`는 네이티브 모델 메타데이터입니다. - `models.providers.*.models[].contextTokens`는 유효 런타임 상한입니다. -- Provider plugin은 `registerProvider({ catalog })`를 통해 모델 catalog를 주입할 수 있습니다. +- 폴백 런타임 규칙, 쿨다운 프로브, 세션 재정의 지속성은 + [/concepts/model-failover](/ko/concepts/model-failover)에 문서화되어 있습니다. +- `models.providers.*.models[].contextWindow`는 네이티브 모델 메타데이터이고, + `models.providers.*.models[].contextTokens`는 실제 런타임 상한입니다. +- 제공자 플러그인은 `registerProvider({ catalog })`를 통해 모델 카탈로그를 주입할 수 있으며, OpenClaw는 그 출력을 `models.providers`에 병합한 뒤 `models.json`을 기록합니다. -- Provider manifest는 `providerAuthEnvVars`를 선언할 수 있으므로 일반적인 env 기반 - 인증 프로브가 plugin 런타임을 로드할 필요가 없습니다. 남아 있는 코어 env-var - 맵은 이제 non-plugin/core provider와 Anthropic API-key-first 온보딩 같은 - 일부 일반 우선순위 사례에만 사용됩니다. -- Provider plugin은 다음을 통해 provider 런타임 동작도 직접 소유할 수 있습니다. +- 제공자 매니페스트는 `providerAuthEnvVars`와 + `providerAuthAliases`를 선언할 수 있으므로 일반적인 env 기반 인증 프로브와 제공자 변형은 + 플러그인 런타임을 로드할 필요가 없습니다. 남아 있는 코어 env-var 맵은 이제 + 비플러그인/코어 제공자와 Anthropic API 키 우선 온보딩 같은 몇 가지 일반 우선순위 사례에만 + 사용됩니다. +- 제공자 플러그인은 다음을 통해 제공자 런타임 동작도 소유할 수 있습니다: `normalizeModelId`, `normalizeTransport`, `normalizeConfig`, `applyNativeStreamingUsageCompat`, `resolveConfigApiKey`, `resolveSyntheticAuth`, `shouldDeferSyntheticProfileAuth`, @@ -52,219 +53,209 @@ x-i18n: `resolveDefaultThinkingLevel`, `applyConfigDefaults`, `isModernModelRef`, `prepareRuntimeAuth`, `resolveUsageAuth`, `fetchUsageSnapshot`, 그리고 `onModelSelected`. -- 참고: provider 런타임 `capabilities`는 공유 runner 메타데이터입니다(provider - 계열, transcript/tooling 특이사항, transport/cache 힌트). 이것은 - plugin이 무엇을 등록하는지 설명하는 [공개 capability 모델](/ko/plugins/architecture#public-capability-model) - 과는 다릅니다(텍스트 추론, 음성 등). +- 참고: 제공자 런타임 `capabilities`는 공유 러너 메타데이터입니다(제공자 + 계열, 전사 기록/도구 관련 특이점, 전송/캐시 힌트). 이는 + 플러그인이 무엇을 등록하는지(텍스트 추론, 음성 등)를 설명하는 + [공개 capability 모델](/ko/plugins/architecture#public-capability-model)과는 다릅니다. -## Plugin 소유 provider 동작 +## 플러그인 소유 제공자 동작 -Provider plugin은 이제 대부분의 provider별 로직을 소유할 수 있고, OpenClaw는 -일반 추론 루프를 유지합니다. +제공자 플러그인은 이제 OpenClaw가 일반 추론 루프를 유지하는 동안 +대부분의 제공자별 로직을 소유할 수 있습니다. -일반적인 분리는 다음과 같습니다. +일반적인 분할: -- `auth[].run` / `auth[].runNonInteractive`: provider가 `openclaw onboard`, `openclaw models auth`, 헤드리스 설정을 위한 온보딩/로그인 - 흐름을 소유 -- `wizard.setup` / `wizard.modelPicker`: provider가 인증 선택 라벨, - 레거시 alias, 온보딩 allowlist 힌트, 온보딩/모델 picker의 설정 항목을 소유 -- `catalog`: provider가 `models.providers`에 표시됨 -- `normalizeModelId`: provider가 조회 또는 canonicalization 전에 - 레거시/preview 모델 id를 정규화 -- `normalizeTransport`: provider가 일반 모델 조립 전에 transport 계열 `api` / `baseUrl`을 - 정규화합니다. OpenClaw는 먼저 일치하는 provider를 확인한 다음, - transport를 실제로 변경할 때까지 다른 hook 가능 provider plugin도 확인합니다. -- `normalizeConfig`: provider가 런타임 사용 전에 `models.providers.` config를 - 정규화합니다. OpenClaw는 먼저 일치하는 provider를 확인한 다음, - config를 실제로 변경할 때까지 다른 hook 가능 provider plugin도 확인합니다. 어떤 - provider hook도 config를 다시 쓰지 않으면, 번들된 Google 계열 도우미가 계속해서 - 지원되는 Google provider 항목을 정규화합니다. -- `applyNativeStreamingUsageCompat`: provider가 config provider에 대해 - 엔드포인트 기반 네이티브 스트리밍 사용량 호환성 재작성을 적용 -- `resolveConfigApiKey`: provider가 config provider에 대해 전체 런타임 인증을 강제로 로드하지 않고 - env-marker 인증을 해결합니다. - `amazon-bedrock`도 Bedrock 런타임 인증이 - AWS SDK 기본 체인을 사용하더라도, 여기에서 내장 AWS env-marker resolver를 가집니다. -- `resolveSyntheticAuth`: provider가 평문 비밀을 저장하지 않고도 - 로컬/셀프호스트 또는 기타 config 기반 인증 가용성을 노출할 수 있음 -- `shouldDeferSyntheticProfileAuth`: provider가 저장된 synthetic profile - placeholder를 env/config 기반 인증보다 낮은 우선순위로 표시할 수 있음 -- `resolveDynamicModel`: provider가 로컬 정적 catalog에 아직 없는 모델 id를 - 허용 -- `prepareDynamicModel`: provider가 동적 해결을 다시 시도하기 전에 - 메타데이터 새로고침이 필요 -- `normalizeResolvedModel`: provider가 transport 또는 base URL 재작성이 필요 -- `contributeResolvedModelCompat`: provider가 다른 호환 transport를 통해 들어온 경우에도 - 해당 vendor 모델에 대한 compat 플래그를 제공 -- `capabilities`: provider가 transcript/tooling/provider 계열 특이사항을 게시 -- `normalizeToolSchemas`: provider가 내장 runner가 보기 전에 - tool schema를 정리 -- `inspectToolSchemas`: provider가 정규화 후 transport별 schema 경고를 표시 -- `resolveReasoningOutputMode`: provider가 네이티브 대 태그 기반 - reasoning-output 계약을 선택 -- `prepareExtraParams`: provider가 모델별 요청 param의 기본값을 적용하거나 정규화 -- `createStreamFn`: provider가 일반 stream 경로를 완전히 - 커스텀 transport로 대체 -- `wrapStreamFn`: provider가 요청 헤더/본문/모델 compat wrapper를 적용 -- `resolveTransportTurnState`: provider가 턴별 네이티브 transport - 헤더 또는 메타데이터를 제공 -- `resolveWebSocketSessionPolicy`: provider가 네이티브 WebSocket 세션 - 헤더 또는 세션 쿨다운 정책을 제공 -- `createEmbeddingProvider`: provider가 코어 embedding switchboard 대신 - provider plugin에 속하는 메모리 embedding 동작을 소유 -- `formatApiKey`: provider가 저장된 인증 profile을 transport가 기대하는 - 런타임 `apiKey` 문자열로 포맷 +- `auth[].run` / `auth[].runNonInteractive`: 제공자가 `openclaw onboard`, `openclaw models auth`, 헤드리스 설정을 위한 온보딩/로그인 흐름을 소유 +- `wizard.setup` / `wizard.modelPicker`: 제공자가 인증 선택 라벨, + 레거시 별칭, 온보딩 허용 목록 힌트, 온보딩/모델 선택기의 설정 항목을 소유 +- `catalog`: 제공자가 `models.providers`에 나타남 +- `normalizeModelId`: 제공자가 조회나 정규화 전에 레거시/프리뷰 모델 id를 정규화 +- `normalizeTransport`: 제공자가 일반 모델 조립 전에 전송 계열 `api` / `baseUrl`을 정규화합니다. OpenClaw는 먼저 일치한 제공자를 확인한 다음, + 실제로 전송을 변경할 때까지 다른 hook 지원 제공자 플러그인을 확인합니다 +- `normalizeConfig`: 제공자가 런타임이 사용하기 전에 `models.providers.` 구성을 정규화합니다. OpenClaw는 먼저 일치한 제공자를 확인한 다음, 실제로 구성을 변경할 때까지 다른 + hook 지원 제공자 플러그인을 확인합니다. 어떤 제공자 hook도 구성을 재작성하지 않으면, + 번들된 Google 계열 도우미가 계속 지원되는 Google 제공자 항목을 + 정규화합니다. +- `applyNativeStreamingUsageCompat`: 제공자가 구성 제공자에 대해 엔드포인트 기반 네이티브 스트리밍 사용량 호환성 재작성을 적용 +- `resolveConfigApiKey`: 제공자가 전체 런타임 인증 로딩을 강제하지 않고 + 구성 제공자의 env-marker 인증을 해석합니다. + `amazon-bedrock`은 Bedrock 런타임 인증이 AWS SDK 기본 체인을 사용하더라도, + 여기에서 내장 AWS env-marker 해석기도 가집니다. +- `resolveSyntheticAuth`: 제공자가 평문 비밀을 저장하지 않고도 + 로컬/셀프호스트형 또는 기타 구성 기반 인증 가용성을 노출할 수 있음 +- `shouldDeferSyntheticProfileAuth`: 제공자가 저장된 synthetic profile + 플레이스홀더를 env/구성 기반 인증보다 낮은 우선순위로 표시할 수 있음 +- `resolveDynamicModel`: 제공자가 아직 로컬 정적 카탈로그에 없는 + 모델 id를 수용 +- `prepareDynamicModel`: 제공자가 동적 해석을 다시 시도하기 전에 메타데이터 새로 고침이 필요 +- `normalizeResolvedModel`: 제공자에 전송 또는 base URL 재작성이 필요 +- `contributeResolvedModelCompat`: 제공자가 다른 호환 전송을 통해 들어오더라도 + 자사 공급업체 모델에 대한 호환 플래그를 제공 +- `capabilities`: 제공자가 전사 기록/도구/제공자 계열 관련 특이점을 게시 +- `normalizeToolSchemas`: 제공자가 내장 러너가 보기 전에 + 도구 스키마를 정리 +- `inspectToolSchemas`: 제공자가 정규화 후 + 전송별 스키마 경고를 노출 +- `resolveReasoningOutputMode`: 제공자가 네이티브와 태그형 + 추론 출력 계약 중에서 선택 +- `prepareExtraParams`: 제공자가 모델별 요청 파라미터의 기본값을 설정하거나 정규화 +- `createStreamFn`: 제공자가 일반 스트림 경로를 완전히 + 사용자 지정된 전송으로 대체 +- `wrapStreamFn`: 제공자가 요청 헤더/본문/모델 호환 래퍼를 적용 +- `resolveTransportTurnState`: 제공자가 턴별 네이티브 전송 + 헤더나 메타데이터를 제공 +- `resolveWebSocketSessionPolicy`: 제공자가 네이티브 WebSocket 세션 + 헤더나 세션 쿨다운 정책을 제공 +- `createEmbeddingProvider`: 제공자 플러그인 쪽에 속하는 경우 + 제공자가 메모리 임베딩 동작을 소유하고, 코어 임베딩 스위치보드는 사용하지 않음 +- `formatApiKey`: 제공자가 저장된 인증 프로필을 전송이 기대하는 런타임 + `apiKey` 문자열로 형식화 - `refreshOAuth`: 공유 `pi-ai` - refresher로 충분하지 않을 때 provider가 OAuth 새로고침을 소유 -- `buildAuthDoctorHint`: OAuth 새로고침이 실패할 때 provider가 - 복구 안내를 추가 -- `matchesContextOverflowError`: provider가 일반 heuristic이 놓치는 - provider별 컨텍스트 창 초과 오류를 인식 -- `classifyFailoverReason`: provider가 provider별 원시 transport/API - 오류를 rate limit 또는 overload 같은 failover reason으로 매핑 -- `isCacheTtlEligible`: provider가 어떤 업스트림 모델 id가 prompt-cache TTL을 지원하는지 결정 -- `buildMissingAuthMessage`: provider가 일반 인증 저장소 오류를 - provider별 복구 힌트로 대체 -- `suppressBuiltInModel`: provider가 오래된 업스트림 행을 숨기고 - 직접 해결 실패에 대해 vendor 소유 오류를 반환할 수 있음 -- `augmentModelCatalog`: provider가 발견 및 config 병합 후 - synthetic/final catalog 행을 추가 -- `isBinaryThinking`: provider가 이진 on/off thinking UX를 소유 -- `supportsXHighThinking`: provider가 선택한 모델에서 `xhigh`를 사용하도록 설정 -- `resolveDefaultThinkingLevel`: provider가 모델 계열의 기본 `/think` 정책을 소유 -- `applyConfigDefaults`: provider가 인증 모드, env 또는 모델 계열에 따라 - config materialization 중 provider별 전역 기본값을 적용 -- `isModernModelRef`: provider가 라이브/스모크 선호 모델 매칭을 소유 -- `prepareRuntimeAuth`: provider가 구성된 자격 증명을 짧은 수명의 - 런타임 토큰으로 변환 -- `resolveUsageAuth`: provider가 `/usage` - 및 관련 상태/리포팅 화면을 위한 사용량/할당량 자격 증명을 해결 -- `fetchUsageSnapshot`: provider가 사용량 엔드포인트 fetch/parsing을 소유하고 - 코어는 여전히 요약 셸과 포맷팅을 소유 -- `onModelSelected`: provider가 텔레메트리 또는 provider 소유 세션 bookkeeping 같은 - 선택 후 부수 효과를 실행 + 리프레셔로 충분하지 않을 때 제공자가 OAuth 갱신을 소유 +- `buildAuthDoctorHint`: OAuth 갱신이 + 실패할 때 제공자가 복구 안내를 덧붙임 +- `matchesContextOverflowError`: 제공자가 일반 휴리스틱으로는 놓치는 + 제공자별 컨텍스트 창 초과 오류를 인식 +- `classifyFailoverReason`: 제공자가 제공자별 원시 전송/API + 오류를 rate limit 또는 overload 같은 페일오버 이유로 매핑 +- `isCacheTtlEligible`: 제공자가 어떤 업스트림 모델 id가 프롬프트 캐시 TTL을 지원하는지 결정 +- `buildMissingAuthMessage`: 제공자가 일반 인증 저장소 오류를 + 제공자별 복구 힌트로 대체 +- `suppressBuiltInModel`: 제공자가 오래된 업스트림 행을 숨기고 + 직접 해석 실패에 대해 공급업체 소유 오류를 반환할 수 있음 +- `augmentModelCatalog`: 제공자가 발견 및 구성 병합 후 + synthetic/final 카탈로그 행을 추가 +- `isBinaryThinking`: 제공자가 이진 on/off thinking UX를 소유 +- `supportsXHighThinking`: 제공자가 선택된 모델에 `xhigh`를 활성화 +- `resolveDefaultThinkingLevel`: 제공자가 모델 계열의 기본 `/think` 정책을 소유 +- `applyConfigDefaults`: 제공자가 인증 모드, env 또는 모델 계열에 따라 + 구성 구체화 중 제공자별 전역 기본값을 적용 +- `isModernModelRef`: 제공자가 live/smoke 선호 모델 매칭을 소유 +- `prepareRuntimeAuth`: 제공자가 구성된 자격 증명을 짧은 수명의 런타임 토큰으로 변환 +- `resolveUsageAuth`: 제공자가 `/usage` 및 관련 상태/보고 표면을 위한 + 사용량/쿼터 자격 증명을 해석 +- `fetchUsageSnapshot`: 제공자가 사용량 엔드포인트 조회/파싱을 소유하고, + 코어는 여전히 요약 셸과 형식화를 소유 +- `onModelSelected`: 제공자가 텔레메트리 또는 제공자 소유 세션 bookkeeping 같은 + 모델 선택 후 부수 효과를 실행 -현재 번들 예시: +현재 번들된 예시: -- `anthropic`: Claude 4.6 forward-compat 폴백, 인증 복구 힌트, 사용량 - 엔드포인트 fetch, cache-TTL/provider 계열 메타데이터, 인증 인식 전역 - config 기본값 -- `amazon-bedrock`: Bedrock별 throttle/not-ready 오류에 대한 provider 소유 - 컨텍스트 초과 매칭 및 failover - reason 분류, 그리고 Anthropic 트래픽에서 Claude 전용 replay-policy - 가드를 위한 공유 `anthropic-by-model` 재생 계열 +- `anthropic`: Claude 4.6 순방향 호환 폴백, 인증 복구 힌트, 사용량 + 엔드포인트 조회, cache-TTL/제공자 계열 메타데이터, 인증 인지 전역 + 구성 기본값 +- `amazon-bedrock`: Bedrock 전용 throttle/not-ready 오류에 대한 제공자 소유 + 컨텍스트 초과 매칭과 페일오버 이유 분류, 그리고 Anthropic 트래픽의 Claude 전용 리플레이 정책 + 가드를 위한 공유 `anthropic-by-model` 리플레이 계열 - `anthropic-vertex`: Anthropic-message - 트래픽에서 Claude 전용 replay-policy 가드 -- `openrouter`: pass-through 모델 id, 요청 wrapper, provider capability + 트래픽에 대한 Claude 전용 리플레이 정책 가드 +- `openrouter`: 패스스루 모델 id, 요청 래퍼, 제공자 capability 힌트, 프록시 Gemini 트래픽에서 Gemini thought-signature 정리, - `openrouter-thinking` stream 계열을 통한 프록시 reasoning 주입, + `openrouter-thinking` 스트림 계열을 통한 프록시 추론 주입, 라우팅 메타데이터 전달, cache-TTL 정책 -- `github-copilot`: 온보딩/디바이스 로그인, forward-compat 모델 폴백, - Claude-thinking transcript 힌트, 런타임 토큰 교환, 사용량 엔드포인트 - fetch -- `openai`: GPT-5.4 forward-compat 폴백, 직접 OpenAI transport - 정규화, Codex 인식 missing-auth 힌트, Spark 숨김, synthetic - OpenAI/Codex catalog 행, thinking/live-model 정책, usage-token alias +- `github-copilot`: 온보딩/디바이스 로그인, 순방향 호환 모델 폴백, + Claude-thinking 전사 기록 힌트, 런타임 토큰 교환, 사용량 엔드포인트 + 조회 +- `openai`: GPT-5.4 순방향 호환 폴백, 직접 OpenAI 전송 + 정규화, Codex 인지 누락 인증 힌트, Spark 억제, synthetic + OpenAI/Codex 카탈로그 행, thinking/live-model 정책, 사용량 토큰 별칭 정규화(`input` / `output` 및 `prompt` / `completion` 계열), 네이티브 OpenAI/Codex - wrapper를 위한 공유 `openai-responses-defaults` stream 계열, - provider 계열 메타데이터, `gpt-image-1`용 번들 이미지 생성 provider - 등록, `sora-2`용 번들 비디오 생성 provider + 래퍼를 위한 공유 `openai-responses-defaults` 스트림 계열, + 제공자 계열 메타데이터, `gpt-image-1`용 번들 이미지 생성 제공자 + 등록, `sora-2`용 번들 비디오 생성 제공자 등록 -- `google` 및 `google-gemini-cli`: Gemini 3.1 forward-compat 폴백, - 네이티브 Gemini replay 검증, bootstrap replay 정리, 태그 기반 - reasoning-output 모드, modern-model 매칭, Gemini image-preview 모델용 - 번들 이미지 생성 provider 등록, Veo 모델용 번들 - 비디오 생성 provider 등록; Gemini CLI OAuth는 또한 - 사용량 화면용 인증 profile 토큰 포맷팅, usage-token parsing, 할당량 엔드포인트 - fetch를 소유 -- `moonshot`: 공유 transport, plugin 소유 thinking payload 정규화 -- `kilocode`: 공유 transport, plugin 소유 요청 헤더, reasoning payload - 정규화, 프록시 Gemini thought-signature 정리, cache-TTL +- `google` 및 `google-gemini-cli`: Gemini 3.1 순방향 호환 폴백, + 네이티브 Gemini 리플레이 검증, bootstrap 리플레이 정리, 태그형 + 추론 출력 모드, 최신 모델 매칭, Gemini 이미지 프리뷰 모델용 번들 이미지 생성 + 제공자 등록, Veo 모델용 번들 + 비디오 생성 제공자 등록; Gemini CLI OAuth는 또한 + 인증 프로필 토큰 형식화, 사용량 토큰 파싱, 사용량 표면용 쿼터 엔드포인트 + 조회를 소유 +- `moonshot`: 공유 전송, 플러그인 소유 thinking 페이로드 정규화 +- `kilocode`: 공유 전송, 플러그인 소유 요청 헤더, 추론 페이로드 + 정규화, 프록시-Gemini thought-signature 정리, cache-TTL 정책 -- `zai`: GLM-5 forward-compat 폴백, `tool_stream` 기본값, cache-TTL - 정책, binary-thinking/live-model 정책, 사용량 인증 + 할당량 fetch; - 알 수 없는 `glm-5*` id는 번들된 `glm-4.7` 템플릿에서 합성됨 -- `xai`: 네이티브 Responses transport 정규화, Grok fast variant용 - `/fast` alias 재작성, 기본 `tool_stream`, xAI별 tool-schema / - reasoning-payload 정리, `grok-imagine-video`용 번들 비디오 생성 provider +- `zai`: GLM-5 순방향 호환 폴백, `tool_stream` 기본값, cache-TTL + 정책, binary-thinking/live-model 정책, 사용량 인증 + 쿼터 조회; + 알 수 없는 `glm-5*` id는 번들된 `glm-4.7` 템플릿에서 synthesize됨 +- `xai`: 네이티브 Responses 전송 정규화, Grok 빠른 변형용 + `/fast` 별칭 재작성, 기본 `tool_stream`, xAI 전용 도구 스키마 / + 추론 페이로드 정리, `grok-imagine-video`용 번들 비디오 생성 제공자 등록 -- `mistral`: plugin 소유 capability 메타데이터 -- `opencode` 및 `opencode-go`: plugin 소유 capability 메타데이터와 - 프록시 Gemini thought-signature 정리 -- `alibaba`: `alibaba/wan2.6-t2v` 같은 직접 Wan 모델 ref용 - plugin 소유 비디오 생성 catalog -- `byteplus`: plugin 소유 catalog와 Seedance 텍스트-비디오/이미지-비디오 모델용 - 번들 비디오 생성 provider 등록 -- `fal`: 호스팅된 서드파티용 번들 비디오 생성 provider 등록, - FLUX 이미지 모델용 이미지 생성 provider 등록, - 그리고 호스팅된 서드파티 비디오 모델용 번들 - 비디오 생성 provider 등록 +- `mistral`: 플러그인 소유 capability 메타데이터 +- `opencode` 및 `opencode-go`: 플러그인 소유 capability 메타데이터와 + 프록시-Gemini thought-signature 정리 +- `alibaba`: `alibaba/wan2.6-t2v` 같은 직접 Wan 모델 참조용 + 플러그인 소유 비디오 생성 카탈로그 +- `byteplus`: 플러그인 소유 카탈로그와 Seedance 텍스트-비디오/이미지-비디오 모델용 + 번들 비디오 생성 제공자 + 등록 +- `fal`: 호스팅된 서드파티 이미지 생성 모델용 + 번들 이미지 생성 제공자 등록과 호스팅된 서드파티 비디오 모델용 + 번들 비디오 생성 제공자 등록 - `cloudflare-ai-gateway`, `huggingface`, `kimi`, `nvidia`, `qianfan`, `stepfun`, `synthetic`, `venice`, `vercel-ai-gateway`, `volcengine`: - plugin 소유 catalog만 제공 -- `qwen`: 텍스트 모델용 plugin 소유 catalog와 멀티모달 화면용 - 공유 media-understanding 및 비디오 생성 provider 등록; + 플러그인 소유 카탈로그 בלבד +- `qwen`: 텍스트 모델용 플러그인 소유 카탈로그와 멀티모달 표면용 + 공유 media-understanding 및 비디오 생성 제공자 등록; Qwen 비디오 생성은 `wan2.6-t2v` 및 `wan2.7-r2v` 같은 번들 Wan 모델과 함께 - Standard DashScope 비디오 엔드포인트를 사용 -- `runway`: `gen4.5` 같은 네이티브 Runway 태스크 기반 모델용 - plugin 소유 비디오 생성 provider 등록 -- `minimax`: plugin 소유 catalog, Hailuo 비디오 모델용 번들 비디오 생성 provider - 등록, `image-01`용 번들 이미지 생성 provider - 등록, 하이브리드 Anthropic/OpenAI replay-policy + 표준 DashScope 비디오 엔드포인트를 사용 +- `runway`: `gen4.5` 같은 네이티브 + Runway 작업 기반 모델용 플러그인 소유 비디오 생성 제공자 등록 +- `minimax`: 플러그인 소유 카탈로그, Hailuo 비디오 모델용 번들 비디오 생성 제공자 + 등록, `image-01`용 번들 이미지 생성 제공자 + 등록, 하이브리드 Anthropic/OpenAI 리플레이 정책 선택, 사용량 인증/스냅샷 로직 -- `together`: plugin 소유 catalog와 Wan 비디오 모델용 번들 비디오 생성 provider - 등록 -- `xiaomi`: plugin 소유 catalog와 사용량 인증/스냅샷 로직 +- `together`: 플러그인 소유 카탈로그와 Wan 비디오 모델용 + 번들 비디오 생성 제공자 등록 +- `xiaomi`: 플러그인 소유 카탈로그와 사용량 인증/스냅샷 로직 -번들된 `openai` plugin은 이제 `openai`와 -`openai-codex` 두 provider id를 모두 소유합니다. +번들된 `openai` 플러그인은 이제 두 제공자 id인 `openai`와 +`openai-codex`를 모두 소유합니다. -여기까지는 여전히 OpenClaw의 일반 transport에 맞는 provider를 다룹니다. 완전히 -커스텀 요청 실행기가 필요한 provider는 별도의 더 깊은 확장 표면입니다. +여기까지는 여전히 OpenClaw의 일반 전송에 맞는 제공자들입니다. 완전히 사용자 지정된 요청 실행기가 필요한 제공자는 별도의, 더 깊은 확장 표면입니다. -## API 키 로테이션 +## API 키 순환 -- 선택된 provider에 대해 일반 provider 로테이션을 지원합니다. -- 여러 키를 다음으로 구성합니다: - - `OPENCLAW_LIVE__KEY`(단일 라이브 override, 최우선) +- 선택된 제공자에 대해 일반적인 제공자 키 순환을 지원합니다. +- 여러 키는 다음을 통해 구성합니다: + - `OPENCLAW_LIVE__KEY`(단일 live override, 최우선) - `_API_KEYS`(쉼표 또는 세미콜론 목록) - `_API_KEY`(기본 키) - - `_API_KEY_*`(번호가 붙은 목록, 예: `_API_KEY_1`) -- Google provider의 경우 `GOOGLE_API_KEY`도 폴백으로 포함됩니다. -- 키 선택 순서는 우선순위를 유지하고 값을 중복 제거합니다. -- 요청은 rate-limit 응답에서만 다음 키로 재시도됩니다(예: - `429`, `rate_limit`, `quota`, `resource exhausted`, `Too many + - `_API_KEY_*`(번호가 매겨진 목록, 예: `_API_KEY_1`) +- Google 제공자의 경우 `GOOGLE_API_KEY`도 폴백으로 포함됩니다. +- 키 선택 순서는 우선순위를 보존하고 값을 중복 제거합니다. +- 요청은 rate-limit 응답에서만 다음 키로 재시도됩니다( + 예: `429`, `rate_limit`, `quota`, `resource exhausted`, `Too many concurrent requests`, `ThrottlingException`, `concurrency limit reached`, - `workers_ai ... quota limit exceeded`, 또는 주기적인 usage-limit 메시지). -- rate-limit가 아닌 실패는 즉시 실패하며 키 로테이션을 시도하지 않습니다. + `workers_ai ... quota limit exceeded`, 또는 주기적인 사용량 제한 메시지). +- rate-limit이 아닌 실패는 즉시 실패하며, 키 순환은 시도되지 않습니다. - 모든 후보 키가 실패하면 마지막 시도의 최종 오류가 반환됩니다. -## 내장 provider (pi-ai catalog) +## 기본 제공 제공자 (pi-ai 카탈로그) -OpenClaw는 pi‑ai catalog를 함께 제공합니다. 이 provider는 -`models.providers` config가 **필요하지 않습니다**. -인증만 설정하고 모델을 선택하면 됩니다. +OpenClaw에는 pi‑ai 카탈로그가 포함되어 있습니다. 이 제공자들은 +`models.providers` 구성이 **필요하지 않습니다**. 인증을 설정하고 모델만 고르면 됩니다. ### OpenAI -- Provider: `openai` +- 제공자: `openai` - 인증: `OPENAI_API_KEY` -- 선택적 로테이션: `OPENAI_API_KEYS`, `OPENAI_API_KEY_1`, `OPENAI_API_KEY_2`, 그리고 `OPENCLAW_LIVE_OPENAI_KEY`(단일 override) +- 선택적 순환: `OPENAI_API_KEYS`, `OPENAI_API_KEY_1`, `OPENAI_API_KEY_2`, 그리고 `OPENCLAW_LIVE_OPENAI_KEY`(단일 override) - 예시 모델: `openai/gpt-5.4`, `openai/gpt-5.4-pro` - CLI: `openclaw onboard --auth-choice openai-api-key` -- 기본 transport는 `auto`입니다(WebSocket 우선, SSE 폴백) -- 모델별 override는 `agents.defaults.models["openai/"].params.transport`로 설정합니다(`"sse"`, `"websocket"`, 또는 `"auto"`) -- OpenAI Responses WebSocket 워밍업은 기본적으로 `params.openaiWsWarmup`으로 활성화됩니다(`true`/`false`) -- OpenAI priority processing은 `agents.defaults.models["openai/"].params.serviceTier`로 활성화할 수 있습니다 +- 기본 전송은 `auto`입니다(WebSocket 우선, SSE 폴백) +- 모델별 재정의는 `agents.defaults.models["openai/"].params.transport`를 통해 수행합니다(`"sse"`, `"websocket"`, 또는 `"auto"`) +- OpenAI Responses WebSocket 워밍업은 `params.openaiWsWarmup`(`true`/`false`)을 통해 기본적으로 활성화됩니다 +- OpenAI priority processing은 `agents.defaults.models["openai/"].params.serviceTier`를 통해 활성화할 수 있습니다 - `/fast`와 `params.fastMode`는 직접 `openai/*` Responses 요청을 `api.openai.com`의 `service_tier=priority`로 매핑합니다 -- 공유 `/fast` 토글 대신 명시적 tier를 원하면 `params.serviceTier`를 사용하세요 +- 공유 `/fast` 토글 대신 명시적 티어를 원하면 `params.serviceTier`를 사용하세요 - 숨겨진 OpenClaw attribution 헤더(`originator`, `version`, - `User-Agent`)는 일반 OpenAI 호환 프록시가 아니라 - `api.openai.com`으로 가는 네이티브 OpenAI 트래픽에만 적용됩니다 -- 네이티브 OpenAI 경로는 Responses `store`, prompt-cache 힌트, - OpenAI reasoning-compat payload shaping도 유지하지만, - 프록시 경로는 그렇지 않습니다 -- `openai/gpt-5.3-codex-spark`는 라이브 OpenAI API가 이를 거부하기 때문에 OpenClaw에서 의도적으로 숨겨집니다. Spark는 Codex 전용으로 처리됩니다 + `User-Agent`)는 일반 OpenAI 호환 프록시가 아니라 `api.openai.com`으로 향하는 + 네이티브 OpenAI 트래픽에만 적용됩니다 +- 네이티브 OpenAI 경로는 Responses `store`, 프롬프트 캐시 힌트, + OpenAI 추론 호환 페이로드 형성도 유지하지만, 프록시 경로는 그렇지 않습니다 +- `openai/gpt-5.3-codex-spark`는 live OpenAI API가 이를 거부하므로 OpenClaw에서 의도적으로 숨겨져 있습니다. Spark는 Codex 전용으로 처리됩니다 ```json5 { @@ -274,14 +265,14 @@ OpenClaw는 pi‑ai catalog를 함께 제공합니다. 이 provider는 ### Anthropic -- Provider: `anthropic` +- 제공자: `anthropic` - 인증: `ANTHROPIC_API_KEY` -- 선택적 로테이션: `ANTHROPIC_API_KEYS`, `ANTHROPIC_API_KEY_1`, `ANTHROPIC_API_KEY_2`, 그리고 `OPENCLAW_LIVE_ANTHROPIC_KEY`(단일 override) +- 선택적 순환: `ANTHROPIC_API_KEYS`, `ANTHROPIC_API_KEY_1`, `ANTHROPIC_API_KEY_2`, 그리고 `OPENCLAW_LIVE_ANTHROPIC_KEY`(단일 override) - 예시 모델: `anthropic/claude-opus-4-6` - CLI: `openclaw onboard --auth-choice apiKey` -- 직접 공개 Anthropic 요청은 공유 `/fast` 토글과 `params.fastMode`도 지원하며, 여기에는 `api.anthropic.com`으로 전송되는 API-key 및 OAuth 인증 트래픽이 포함됩니다. OpenClaw는 이를 Anthropic `service_tier`(`auto` 대 `standard_only`)로 매핑합니다 -- Anthropic 참고: Anthropic 직원이 OpenClaw 스타일 Claude CLI 사용이 다시 허용된다고 알려왔으므로, Anthropic이 새 정책을 게시하지 않는 한 OpenClaw는 이 통합에 대해 Claude CLI 재사용과 `claude -p` 사용을 허용된 것으로 처리합니다. -- Anthropic setup-token은 여전히 지원되는 OpenClaw 토큰 경로로 제공되지만, OpenClaw는 이제 가능하면 Claude CLI 재사용과 `claude -p`를 우선합니다. +- 직접 공개 Anthropic 요청은 `api.anthropic.com`으로 전송되는 API 키 및 OAuth 인증 트래픽을 포함해 공유 `/fast` 토글과 `params.fastMode`를 지원합니다. OpenClaw는 이를 Anthropic `service_tier`(`auto` 대 `standard_only`)에 매핑합니다 +- Anthropic 참고: Anthropic 직원이 OpenClaw 스타일 Claude CLI 사용이 다시 허용된다고 알려주었으므로, Anthropic이 새 정책을 게시하지 않는 한 OpenClaw는 이 통합을 위해 Claude CLI 재사용과 `claude -p` 사용을 승인된 것으로 취급합니다. +- Anthropic setup-token은 계속 지원되는 OpenClaw 토큰 경로로 제공되지만, OpenClaw는 이제 가능하면 Claude CLI 재사용과 `claude -p`를 선호합니다. ```json5 { @@ -291,21 +282,20 @@ OpenClaw는 pi‑ai catalog를 함께 제공합니다. 이 provider는 ### OpenAI Code (Codex) -- Provider: `openai-codex` +- 제공자: `openai-codex` - 인증: OAuth (ChatGPT) - 예시 모델: `openai-codex/gpt-5.4` - CLI: `openclaw onboard --auth-choice openai-codex` 또는 `openclaw models auth login --provider openai-codex` -- 기본 transport는 `auto`입니다(WebSocket 우선, SSE 폴백) -- 모델별 override는 `agents.defaults.models["openai-codex/"].params.transport`로 설정합니다(`"sse"`, `"websocket"`, 또는 `"auto"`) -- `params.serviceTier`도 네이티브 Codex Responses 요청(`chatgpt.com/backend-api`)에서 전달됩니다 +- 기본 전송은 `auto`입니다(WebSocket 우선, SSE 폴백) +- 모델별 재정의는 `agents.defaults.models["openai-codex/"].params.transport`를 통해 수행합니다(`"sse"`, `"websocket"`, 또는 `"auto"`) +- `params.serviceTier`도 네이티브 Codex Responses 요청(`chatgpt.com/backend-api`)에 전달됩니다 - 숨겨진 OpenClaw attribution 헤더(`originator`, `version`, `User-Agent`)는 일반 OpenAI 호환 프록시가 아니라 - `chatgpt.com/backend-api`로 가는 네이티브 Codex 트래픽에만 - 첨부됩니다 -- 직접 `openai/*`와 같은 `/fast` 토글 및 `params.fastMode` config를 공유하며, OpenClaw는 이를 `service_tier=priority`로 매핑합니다 -- `openai-codex/gpt-5.3-codex-spark`는 Codex OAuth catalog가 이를 노출할 때 계속 사용할 수 있습니다. entitlement에 따라 달라집니다 -- `openai-codex/gpt-5.4`는 네이티브 `contextWindow = 1050000`과 기본 런타임 `contextTokens = 272000`을 유지합니다. 런타임 상한은 `models.providers.openai-codex.models[].contextTokens`로 override하세요 -- 정책 참고: OpenAI Codex OAuth는 OpenClaw 같은 외부 도구/워크플로우에 대해 명시적으로 지원됩니다. + `chatgpt.com/backend-api`로 향하는 네이티브 Codex 트래픽에만 첨부됩니다 +- 직접 `openai/*`와 동일한 `/fast` 토글 및 `params.fastMode` 구성을 공유하며, OpenClaw는 이를 `service_tier=priority`로 매핑합니다 +- `openai-codex/gpt-5.3-codex-spark`는 Codex OAuth 카탈로그가 이를 노출할 때 계속 사용할 수 있습니다. entitlement에 따라 달라집니다 +- `openai-codex/gpt-5.4`는 네이티브 `contextWindow = 1050000`과 기본 런타임 `contextTokens = 272000`을 유지합니다. 런타임 상한은 `models.providers.openai-codex.models[].contextTokens`로 재정의하세요 +- 정책 참고: OpenAI Codex OAuth는 OpenClaw 같은 외부 도구/워크플로에 대해 명시적으로 지원됩니다. ```json5 { @@ -327,15 +317,15 @@ OpenClaw는 pi‑ai catalog를 함께 제공합니다. 이 provider는 ### 기타 구독형 호스팅 옵션 -- [Qwen Cloud](/ko/providers/qwen): Qwen Cloud provider 표면과 Alibaba DashScope 및 Coding Plan 엔드포인트 매핑 +- [Qwen Cloud](/ko/providers/qwen): Qwen Cloud 제공자 표면과 Alibaba DashScope 및 Coding Plan 엔드포인트 매핑 - [MiniMax](/ko/providers/minimax): MiniMax Coding Plan OAuth 또는 API 키 액세스 - [GLM Models](/ko/providers/glm): Z.AI Coding Plan 또는 일반 API 엔드포인트 ### OpenCode - 인증: `OPENCODE_API_KEY`(또는 `OPENCODE_ZEN_API_KEY`) -- Zen 런타임 provider: `opencode` -- Go 런타임 provider: `opencode-go` +- Zen 런타임 제공자: `opencode` +- Go 런타임 제공자: `opencode-go` - 예시 모델: `opencode/claude-opus-4-6`, `opencode-go/kimi-k2.5` - CLI: `openclaw onboard --auth-choice opencode-zen` 또는 `openclaw onboard --auth-choice opencode-go` @@ -347,89 +337,90 @@ OpenClaw는 pi‑ai catalog를 함께 제공합니다. 이 provider는 ### Google Gemini (API 키) -- Provider: `google` +- 제공자: `google` - 인증: `GEMINI_API_KEY` -- 선택적 로테이션: `GEMINI_API_KEYS`, `GEMINI_API_KEY_1`, `GEMINI_API_KEY_2`, `GOOGLE_API_KEY` 폴백, 그리고 `OPENCLAW_LIVE_GEMINI_KEY`(단일 override) +- 선택적 순환: `GEMINI_API_KEYS`, `GEMINI_API_KEY_1`, `GEMINI_API_KEY_2`, `GOOGLE_API_KEY` 폴백, 그리고 `OPENCLAW_LIVE_GEMINI_KEY`(단일 override) - 예시 모델: `google/gemini-3.1-pro-preview`, `google/gemini-3-flash-preview` -- 호환성: `google/gemini-3.1-flash-preview`를 사용하는 레거시 OpenClaw config는 `google/gemini-3-flash-preview`로 정규화됩니다 +- 호환성: `google/gemini-3.1-flash-preview`를 사용하는 레거시 OpenClaw 구성은 `google/gemini-3-flash-preview`로 정규화됩니다 - CLI: `openclaw onboard --auth-choice gemini-api-key` -- 직접 Gemini 실행은 `agents.defaults.models["google/"].params.cachedContent` - (또는 레거시 `cached_content`)도 허용하며, provider 네이티브 - `cachedContents/...` 핸들을 전달합니다. Gemini cache hit는 OpenClaw `cacheRead`로 표시됩니다 +- 직접 Gemini 실행은 또한 제공자 네이티브 + `cachedContents/...` 핸들을 전달하기 위해 `agents.defaults.models["google/"].params.cachedContent` + (또는 레거시 `cached_content`)를 받을 수 있습니다. Gemini 캐시 히트는 OpenClaw `cacheRead`로 표시됩니다 ### Google Vertex 및 Gemini CLI -- Provider: `google-vertex`, `google-gemini-cli` -- 인증: Vertex는 gcloud ADC 사용, Gemini CLI는 자체 OAuth 흐름 사용 -- 주의: OpenClaw에서의 Gemini CLI OAuth는 비공식 통합입니다. 일부 사용자는 서드파티 클라이언트를 사용한 뒤 Google 계정 제한을 보고했습니다. 진행하기로 선택했다면 Google 약관을 검토하고 중요하지 않은 계정을 사용하세요. -- Gemini CLI OAuth는 번들된 `google` plugin의 일부로 제공됩니다. - - 먼저 Gemini CLI를 설치하세요: +- 제공자: `google-vertex`, `google-gemini-cli` +- 인증: Vertex는 gcloud ADC를 사용하고, Gemini CLI는 자체 OAuth 흐름을 사용합니다 +- 주의: OpenClaw의 Gemini CLI OAuth는 비공식 통합입니다. 일부 사용자는 서드파티 클라이언트 사용 후 Google 계정 제한을 보고했습니다. 진행하기로 선택한 경우 Google 약관을 검토하고 중요하지 않은 계정을 사용하세요. +- Gemini CLI OAuth는 번들된 `google` 플러그인의 일부로 제공됩니다. + - 먼저 Gemini CLI를 설치합니다: - `brew install gemini-cli` - 또는 `npm install -g @google/gemini-cli` - 활성화: `openclaw plugins enable google` - 로그인: `openclaw models auth login --provider google-gemini-cli --set-default` - 기본 모델: `google-gemini-cli/gemini-3-flash-preview` - - 참고: `openclaw.json`에 client id나 secret을 붙여 넣지 **않습니다**. CLI 로그인 흐름은 - 게이트웨이 호스트의 인증 profile에 토큰을 저장합니다. - - 로그인 후 요청이 실패하면 게이트웨이 호스트에서 `GOOGLE_CLOUD_PROJECT` 또는 `GOOGLE_CLOUD_PROJECT_ID`를 설정하세요. - - Gemini CLI JSON 응답은 `response`에서 파싱되며, 사용량은 - `stats`로 폴백되고, `stats.cached`는 OpenClaw `cacheRead`로 정규화됩니다. + - 참고: `openclaw.json`에 client id나 secret을 붙여 넣을 **필요가 없습니다**. CLI 로그인 흐름이 + 게이트웨이 호스트의 인증 프로필에 토큰을 저장합니다. + - 로그인 후 요청이 실패하면 게이트웨이 호스트에 `GOOGLE_CLOUD_PROJECT` 또는 `GOOGLE_CLOUD_PROJECT_ID`를 설정하세요. + - Gemini CLI JSON 응답은 `response`에서 파싱되며, 사용량은 `stats`로 폴백되고, + `stats.cached`는 OpenClaw `cacheRead`로 정규화됩니다. ### Z.AI (GLM) -- Provider: `zai` +- 제공자: `zai` - 인증: `ZAI_API_KEY` - 예시 모델: `zai/glm-5.1` - CLI: `openclaw onboard --auth-choice zai-api-key` - - Alias: `z.ai/*` 및 `z-ai/*`는 `zai/*`로 정규화됩니다 - - `zai-api-key`는 일치하는 Z.AI 엔드포인트를 자동 감지하며, `zai-coding-global`, `zai-coding-cn`, `zai-global`, `zai-cn`은 특정 표면을 강제합니다 + - 별칭: `z.ai/*`와 `z-ai/*`는 `zai/*`로 정규화됩니다 + - `zai-api-key`는 일치하는 Z.AI 엔드포인트를 자동 감지합니다. `zai-coding-global`, `zai-coding-cn`, `zai-global`, `zai-cn`은 특정 표면을 강제로 선택합니다 ### Vercel AI Gateway -- Provider: `vercel-ai-gateway` +- 제공자: `vercel-ai-gateway` - 인증: `AI_GATEWAY_API_KEY` - 예시 모델: `vercel-ai-gateway/anthropic/claude-opus-4.6` - CLI: `openclaw onboard --auth-choice ai-gateway-api-key` ### Kilo Gateway -- Provider: `kilocode` +- 제공자: `kilocode` - 인증: `KILOCODE_API_KEY` - 예시 모델: `kilocode/kilo/auto` - CLI: `openclaw onboard --auth-choice kilocode-api-key` - 기본 URL: `https://api.kilo.ai/api/gateway/` -- 정적 폴백 catalog는 `kilocode/kilo/auto`를 포함하며, 라이브 - `https://api.kilo.ai/api/gateway/models` 발견을 통해 런타임 - catalog가 더 확장될 수 있습니다. -- `kilocode/kilo/auto` 뒤의 정확한 업스트림 라우팅은 OpenClaw에 - 하드코딩되어 있지 않고 Kilo Gateway가 소유합니다. +- 정적 폴백 카탈로그는 `kilocode/kilo/auto`를 포함하며, live + `https://api.kilo.ai/api/gateway/models` 탐색은 런타임 + 카탈로그를 더 확장할 수 있습니다. +- `kilocode/kilo/auto` 뒤의 정확한 업스트림 라우팅은 Kilo Gateway가 소유하며, + OpenClaw에 하드코딩되어 있지 않습니다. -설정 세부 사항은 [/providers/kilocode](/ko/providers/kilocode)를 참고하세요. +설정 세부 사항은 [/providers/kilocode](/ko/providers/kilocode)를 참조하세요. -### 기타 번들 provider plugin +### 기타 번들 제공자 플러그인 - OpenRouter: `openrouter` (`OPENROUTER_API_KEY`) - 예시 모델: `openrouter/auto` - OpenClaw는 요청이 실제로 `openrouter.ai`를 대상으로 할 때만 - OpenRouter 문서의 앱 attribution 헤더를 적용합니다 + OpenRouter의 문서화된 앱 attribution 헤더를 적용합니다 - OpenRouter 전용 Anthropic `cache_control` 마커도 - 임의의 프록시 URL이 아니라 검증된 OpenRouter 경로에만 적용됩니다 -- OpenRouter는 프록시 스타일 OpenAI 호환 경로에 남아 있으므로 네이티브 - OpenAI 전용 요청 shaping(`serviceTier`, Responses `store`, - prompt-cache 힌트, OpenAI reasoning-compat payload)은 전달되지 않습니다 -- Gemini 기반 OpenRouter ref는 프록시 Gemini thought-signature 정리만 - 유지하며, 네이티브 Gemini replay 검증과 bootstrap 재작성은 비활성화됩니다 + 임의 프록시 URL이 아니라 검증된 OpenRouter 경로에만 적용됩니다 +- OpenRouter는 프록시 스타일 OpenAI 호환 경로에 머무르므로, 네이티브 + OpenAI 전용 요청 형성(`serviceTier`, Responses `store`, + 프롬프트 캐시 힌트, OpenAI 추론 호환 페이로드)은 전달되지 않습니다 +- Gemini 기반 OpenRouter 참조는 프록시-Gemini thought-signature 정리만 + 유지합니다. 네이티브 Gemini 리플레이 검증과 bootstrap 재작성은 비활성 상태로 유지됩니다 - Kilo Gateway: `kilocode` (`KILOCODE_API_KEY`) - 예시 모델: `kilocode/kilo/auto` -- Gemini 기반 Kilo ref도 동일한 프록시 Gemini thought-signature - 정리 경로를 유지하며, `kilocode/kilo/auto` 및 다른 proxy-reasoning-unsupported - 힌트는 프록시 reasoning 주입을 건너뜁니다 +- Gemini 기반 Kilo 참조는 동일한 프록시-Gemini thought-signature + 정리 경로를 유지합니다. `kilocode/kilo/auto`와 기타 프록시 추론 미지원 + 힌트는 프록시 추론 주입을 건너뜁니다 - MiniMax: `minimax`(API 키) 및 `minimax-portal`(OAuth) -- 인증: `minimax`에는 `MINIMAX_API_KEY`; `minimax-portal`에는 `MINIMAX_OAUTH_TOKEN` 또는 `MINIMAX_API_KEY` +- 인증: `minimax`에는 `MINIMAX_API_KEY`, `minimax-portal`에는 `MINIMAX_OAUTH_TOKEN` 또는 `MINIMAX_API_KEY` - 예시 모델: `minimax/MiniMax-M2.7` 또는 `minimax-portal/MiniMax-M2.7` - MiniMax 온보딩/API 키 설정은 명시적인 M2.7 모델 정의를 - `input: ["text", "image"]`와 함께 기록합니다. 번들된 provider catalog는 해당 provider config가 materialize될 때까지 - 채팅 ref를 텍스트 전용으로 유지합니다 + `input: ["text", "image"]`와 함께 기록합니다. 번들된 제공자 카탈로그는 + 해당 제공자 구성이 구체화될 때까지 채팅 참조를 + 텍스트 전용으로 유지합니다 - Moonshot: `moonshot` (`MOONSHOT_API_KEY`) - 예시 모델: `moonshot/kimi-k2.5` - Kimi Coding: `kimi` (`KIMI_API_KEY` 또는 `KIMICODE_API_KEY`) @@ -457,8 +448,8 @@ OpenClaw는 pi‑ai catalog를 함께 제공합니다. 이 provider는 - xAI: `xai` (`XAI_API_KEY`) - 네이티브 번들 xAI 요청은 xAI Responses 경로를 사용합니다 - `/fast` 또는 `params.fastMode: true`는 `grok-3`, `grok-3-mini`, - `grok-4`, `grok-4-0709`를 해당 `*-fast` variant로 재작성합니다 - - `tool_stream`은 기본 활성화되어 있습니다. + `grok-4`, `grok-4-0709`를 해당 `*-fast` 변형으로 재작성합니다 + - `tool_stream`은 기본적으로 활성화됩니다. 비활성화하려면 `agents.defaults.models["xai/"].params.tool_stream`을 `false`로 설정하세요 - Mistral: `mistral` (`MISTRAL_API_KEY`) @@ -469,24 +460,23 @@ OpenClaw는 pi‑ai catalog를 함께 제공합니다. 이 provider는 - Cerebras의 GLM 모델은 `zai-glm-4.7` 및 `zai-glm-4.6` id를 사용합니다. - OpenAI 호환 base URL: `https://api.cerebras.ai/v1`. - GitHub Copilot: `github-copilot` (`COPILOT_GITHUB_TOKEN` / `GH_TOKEN` / `GITHUB_TOKEN`) -- Hugging Face Inference 예시 모델: `huggingface/deepseek-ai/DeepSeek-R1`; CLI: `openclaw onboard --auth-choice huggingface-api-key`. [Hugging Face (Inference)](/ko/providers/huggingface)를 참고하세요. +- Hugging Face Inference 예시 모델: `huggingface/deepseek-ai/DeepSeek-R1`; CLI: `openclaw onboard --auth-choice huggingface-api-key`. [Hugging Face (Inference)](/ko/providers/huggingface)를 참조하세요. -## `models.providers`를 통한 provider (커스텀/base URL) +## `models.providers`를 통한 제공자 (커스텀/base URL) -**커스텀** provider 또는 -OpenAI/Anthropic 호환 프록시를 추가하려면 `models.providers`(또는 `models.json`)를 사용하세요. +`models.providers`(또는 `models.json`)를 사용해 **커스텀** 제공자 또는 +OpenAI/Anthropic 호환 프록시를 추가할 수 있습니다. -아래의 많은 번들 provider plugin은 이미 기본 catalog를 게시합니다. -기본 base URL, 헤더 또는 모델 목록을 override하려는 경우에만 -명시적인 `models.providers.` 항목을 사용하세요. +아래의 많은 번들 제공자 플러그인은 이미 기본 카탈로그를 게시합니다. +기본 base URL, 헤더 또는 모델 목록을 재정의하려는 경우에만 명시적인 +`models.providers.` 항목을 사용하세요. ### Moonshot AI (Kimi) -Moonshot은 번들 provider plugin으로 제공됩니다. 기본적으로 내장 provider를 -사용하고, base URL 또는 모델 메타데이터를 override해야 할 때만 -명시적인 `models.providers.moonshot` 항목을 추가하세요. +Moonshot은 번들 제공자 플러그인으로 제공됩니다. 기본적으로는 내장 제공자를 사용하고, +base URL이나 모델 메타데이터를 재정의해야 할 때만 명시적인 `models.providers.moonshot` 항목을 추가하세요: -- Provider: `moonshot` +- 제공자: `moonshot` - 인증: `MOONSHOT_API_KEY` - 예시 모델: `moonshot/kimi-k2.5` - CLI: `openclaw onboard --auth-choice moonshot-api-key` 또는 `openclaw onboard --auth-choice moonshot-api-key-cn` @@ -523,9 +513,9 @@ Kimi K2 모델 ID: ### Kimi Coding -Kimi Coding은 Moonshot AI의 Anthropic 호환 엔드포인트를 사용합니다. +Kimi Coding은 Moonshot AI의 Anthropic 호환 엔드포인트를 사용합니다: -- Provider: `kimi` +- 제공자: `kimi` - 인증: `KIMI_API_KEY` - 예시 모델: `kimi/kimi-code` @@ -538,13 +528,13 @@ Kimi Coding은 Moonshot AI의 Anthropic 호환 엔드포인트를 사용합니 } ``` -레거시 `kimi/k2p5`는 호환성 모델 id로 계속 허용됩니다. +레거시 `kimi/k2p5`는 계속 호환 모델 id로 허용됩니다. ### Volcano Engine (Doubao) -Volcano Engine(화산엔진)은 중국에서 Doubao 및 기타 모델에 대한 액세스를 제공합니다. +Volcano Engine(화산엔진, 火山引擎)은 중국에서 Doubao 및 기타 모델에 대한 액세스를 제공합니다. -- Provider: `volcengine` (coding: `volcengine-plan`) +- 제공자: `volcengine`(코딩: `volcengine-plan`) - 인증: `VOLCANO_ENGINE_API_KEY` - 예시 모델: `volcengine-plan/ark-code-latest` - CLI: `openclaw onboard --auth-choice volcengine-api-key` @@ -557,13 +547,12 @@ Volcano Engine(화산엔진)은 중국에서 Doubao 및 기타 모델에 대한 } ``` -온보딩은 기본적으로 coding 표면을 사용하지만, 일반 `volcengine/*` -catalog도 동시에 등록됩니다. +온보딩은 기본적으로 코딩 표면을 선택하지만, 일반 `volcengine/*` +카탈로그도 동시에 등록됩니다. -온보딩/모델 구성 picker에서 Volcengine 인증 선택은 -`volcengine/*`와 `volcengine-plan/*` 행을 모두 우선합니다. 해당 모델이 아직 로드되지 않았다면 -OpenClaw는 provider 범위 picker가 비어 보이지 않도록 -필터링되지 않은 catalog로 폴백합니다. +온보딩/모델 선택기에서 Volcengine 인증 선택은 `volcengine/*`와 `volcengine-plan/*` 행을 모두 선호합니다. 이 모델들이 아직 로드되지 않았다면, +OpenClaw는 비어 있는 제공자 범위 선택기를 표시하는 대신 +필터링되지 않은 카탈로그로 폴백합니다. 사용 가능한 모델: @@ -573,7 +562,7 @@ OpenClaw는 provider 범위 picker가 비어 보이지 않도록 - `volcengine/glm-4-7-251222` (GLM 4.7) - `volcengine/deepseek-v3-2-251201` (DeepSeek V3.2 128K) -Coding 모델(`volcengine-plan`): +코딩 모델(`volcengine-plan`): - `volcengine-plan/ark-code-latest` - `volcengine-plan/doubao-seed-code` @@ -581,11 +570,11 @@ Coding 모델(`volcengine-plan`): - `volcengine-plan/kimi-k2-thinking` - `volcengine-plan/glm-4.7` -### BytePlus (International) +### BytePlus (국제) BytePlus ARK는 국제 사용자를 위해 Volcano Engine과 동일한 모델에 대한 액세스를 제공합니다. -- Provider: `byteplus` (coding: `byteplus-plan`) +- 제공자: `byteplus`(코딩: `byteplus-plan`) - 인증: `BYTEPLUS_API_KEY` - 예시 모델: `byteplus-plan/ark-code-latest` - CLI: `openclaw onboard --auth-choice byteplus-api-key` @@ -598,13 +587,12 @@ BytePlus ARK는 국제 사용자를 위해 Volcano Engine과 동일한 모델에 } ``` -온보딩은 기본적으로 coding 표면을 사용하지만, 일반 `byteplus/*` -catalog도 동시에 등록됩니다. +온보딩은 기본적으로 코딩 표면을 선택하지만, 일반 `byteplus/*` +카탈로그도 동시에 등록됩니다. -온보딩/모델 구성 picker에서 BytePlus 인증 선택은 -`byteplus/*`와 `byteplus-plan/*` 행을 모두 우선합니다. 해당 모델이 아직 로드되지 않았다면 -OpenClaw는 provider 범위 picker가 비어 보이지 않도록 -필터링되지 않은 catalog로 폴백합니다. +온보딩/모델 선택기에서 BytePlus 인증 선택은 `byteplus/*`와 `byteplus-plan/*` 행을 모두 선호합니다. 이 모델들이 아직 로드되지 않았다면, +OpenClaw는 비어 있는 제공자 범위 선택기를 표시하는 대신 +필터링되지 않은 카탈로그로 폴백합니다. 사용 가능한 모델: @@ -612,7 +600,7 @@ OpenClaw는 provider 범위 picker가 비어 보이지 않도록 - `byteplus/kimi-k2-5-260127` (Kimi K2.5) - `byteplus/glm-4-7-251222` (GLM 4.7) -Coding 모델(`byteplus-plan`): +코딩 모델(`byteplus-plan`): - `byteplus-plan/ark-code-latest` - `byteplus-plan/doubao-seed-code` @@ -622,9 +610,9 @@ Coding 모델(`byteplus-plan`): ### Synthetic -Synthetic는 `synthetic` provider 뒤에서 Anthropic 호환 모델을 제공합니다. +Synthetic는 `synthetic` 제공자 뒤에서 Anthropic 호환 모델을 제공합니다: -- Provider: `synthetic` +- 제공자: `synthetic` - 인증: `SYNTHETIC_API_KEY` - 예시 모델: `synthetic/hf:MiniMaxAI/MiniMax-M2.5` - CLI: `openclaw onboard --auth-choice synthetic-api-key` @@ -650,39 +638,40 @@ Synthetic는 `synthetic` provider 뒤에서 Anthropic 호환 모델을 제공합 ### MiniMax -MiniMax는 커스텀 엔드포인트를 사용하므로 `models.providers`를 통해 구성합니다. +MiniMax는 커스텀 엔드포인트를 사용하므로 `models.providers`를 통해 구성됩니다: - MiniMax OAuth (Global): `--auth-choice minimax-global-oauth` - MiniMax OAuth (CN): `--auth-choice minimax-cn-oauth` -- MiniMax API 키 (Global): `--auth-choice minimax-global-api` -- MiniMax API 키 (CN): `--auth-choice minimax-cn-api` -- 인증: `minimax`에는 `MINIMAX_API_KEY`, `minimax-portal`에는 - `MINIMAX_OAUTH_TOKEN` 또는 `MINIMAX_API_KEY` +- MiniMax API key (Global): `--auth-choice minimax-global-api` +- MiniMax API key (CN): `--auth-choice minimax-cn-api` +- 인증: `minimax`에는 `MINIMAX_API_KEY`, + `minimax-portal`에는 `MINIMAX_OAUTH_TOKEN` 또는 + `MINIMAX_API_KEY` -설정 세부 사항, 모델 옵션, config snippet은 [/providers/minimax](/ko/providers/minimax)를 참고하세요. +설정 세부 사항, 모델 옵션, 구성 스니펫은 [/providers/minimax](/ko/providers/minimax)를 참조하세요. -MiniMax의 Anthropic 호환 스트리밍 경로에서는 OpenClaw가 thinking을 -명시적으로 설정하지 않는 한 기본적으로 비활성화하며, `/fast on`은 -`MiniMax-M2.7`을 `MiniMax-M2.7-highspeed`로 재작성합니다. +MiniMax의 Anthropic 호환 스트리밍 경로에서 OpenClaw는 +명시적으로 설정하지 않는 한 기본적으로 thinking을 비활성화하며, +`/fast on`은 `MiniMax-M2.7`을 `MiniMax-M2.7-highspeed`로 재작성합니다. -Plugin 소유 capability 분리: +플러그인 소유 capability 분할: - 텍스트/채팅 기본값은 `minimax/MiniMax-M2.7`에 유지 - 이미지 생성은 `minimax/image-01` 또는 `minimax-portal/image-01` -- 이미지 이해는 두 MiniMax 인증 경로 모두에서 plugin 소유 `MiniMax-VL-01` -- 웹 검색은 provider id `minimax`에 유지 +- 이미지 이해는 두 MiniMax 인증 경로 모두에서 플러그인 소유 `MiniMax-VL-01` +- 웹 검색은 제공자 id `minimax`에 유지 ### Ollama -Ollama는 번들 provider plugin으로 제공되며 Ollama의 네이티브 API를 사용합니다. +Ollama는 번들 제공자 플러그인으로 제공되며 Ollama의 네이티브 API를 사용합니다: -- Provider: `ollama` +- 제공자: `ollama` - 인증: 필요 없음(로컬 서버) - 예시 모델: `ollama/llama3.3` - 설치: [https://ollama.com/download](https://ollama.com/download) ```bash -# Ollama를 설치한 다음 모델을 pull하세요: +# Ollama를 설치한 다음 모델을 가져옵니다: ollama pull llama3.3 ``` @@ -694,27 +683,27 @@ ollama pull llama3.3 } ``` -Ollama는 `OLLAMA_API_KEY`로 opt in하면 로컬 `http://127.0.0.1:11434`에서 -감지되며, 번들 provider plugin이 Ollama를 직접 -`openclaw onboard`와 모델 picker에 추가합니다. 온보딩, cloud/local 모드, -커스텀 구성은 [/providers/ollama](/ko/providers/ollama)를 참고하세요. +Ollama는 `OLLAMA_API_KEY`로 opt in하면 로컬의 `http://127.0.0.1:11434`에서 +감지되며, 번들 제공자 플러그인은 Ollama를 직접 +`openclaw onboard`와 모델 선택기에 추가합니다. 온보딩, 클라우드/로컬 모드, 커스텀 구성은 [/providers/ollama](/ko/providers/ollama)를 +참조하세요. ### vLLM -vLLM은 로컬/셀프호스트 OpenAI 호환 -서버를 위한 번들 provider plugin으로 제공됩니다. +vLLM은 로컬/셀프호스트형 OpenAI 호환 +서버용 번들 제공자 플러그인으로 제공됩니다: -- Provider: `vllm` +- 제공자: `vllm` - 인증: 선택 사항(서버에 따라 다름) - 기본 base URL: `http://127.0.0.1:8000/v1` -로컬에서 자동 감지를 opt in하려면(서버가 인증을 강제하지 않으면 아무 값이나 가능): +로컬 자동 감지를 opt in하려면(서버가 인증을 강제하지 않으면 어떤 값이든 작동): ```bash export VLLM_API_KEY="vllm-local" ``` -그런 다음 모델을 설정하세요(`/v1/models`가 반환하는 ID 중 하나로 교체): +그런 다음 모델을 설정합니다(`/v1/models`가 반환하는 ID 중 하나로 바꾸세요): ```json5 { @@ -724,25 +713,25 @@ export VLLM_API_KEY="vllm-local" } ``` -자세한 내용은 [/providers/vllm](/ko/providers/vllm)을 참고하세요. +자세한 내용은 [/providers/vllm](/ko/providers/vllm)를 참조하세요. ### SGLang -SGLang은 빠른 셀프호스트 -OpenAI 호환 서버를 위한 번들 provider plugin으로 제공됩니다. +SGLang은 빠른 셀프호스트형 +OpenAI 호환 서버용 번들 제공자 플러그인으로 제공됩니다: -- Provider: `sglang` +- 제공자: `sglang` - 인증: 선택 사항(서버에 따라 다름) - 기본 base URL: `http://127.0.0.1:30000/v1` -로컬에서 자동 감지를 opt in하려면(서버가 인증을 -강제하지 않으면 아무 값이나 가능): +로컬 자동 감지를 opt in하려면(서버가 +인증을 강제하지 않으면 어떤 값이든 작동): ```bash export SGLANG_API_KEY="sglang-local" ``` -그런 다음 모델을 설정하세요(`/v1/models`가 반환하는 ID 중 하나로 교체): +그런 다음 모델을 설정합니다(`/v1/models`가 반환하는 ID 중 하나로 바꾸세요): ```json5 { @@ -752,9 +741,9 @@ export SGLANG_API_KEY="sglang-local" } ``` -자세한 내용은 [/providers/sglang](/ko/providers/sglang)을 참고하세요. +자세한 내용은 [/providers/sglang](/ko/providers/sglang)를 참조하세요. -### 로컬 프록시(LM Studio, vLLM, LiteLLM 등) +### 로컬 프록시 (LM Studio, vLLM, LiteLLM 등) 예시(OpenAI 호환): @@ -791,21 +780,21 @@ export SGLANG_API_KEY="sglang-local" 참고: -- 커스텀 provider의 경우 `reasoning`, `input`, `cost`, `contextWindow`, `maxTokens`는 선택 사항입니다. - 생략하면 OpenClaw는 기본적으로 다음 값을 사용합니다: +- 커스텀 제공자의 경우 `reasoning`, `input`, `cost`, `contextWindow`, `maxTokens`는 선택 사항입니다. + 생략하면 OpenClaw는 다음 기본값을 사용합니다: - `reasoning: false` - `input: ["text"]` - `cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }` - `contextWindow: 200000` - `maxTokens: 8192` - 권장: 프록시/모델 한도에 맞는 명시적 값을 설정하세요. -- 비네이티브 엔드포인트(`api.openai.com`이 아닌 호스트를 가진 비어 있지 않은 `baseUrl`)의 `api: "openai-completions"`에 대해 OpenClaw는 지원되지 않는 `developer` 역할로 인한 provider 400 오류를 피하기 위해 `compat.supportsDeveloperRole: false`를 강제로 적용합니다. -- 프록시 스타일 OpenAI 호환 경로도 네이티브 OpenAI 전용 요청 - shaping을 건너뜁니다: `service_tier` 없음, Responses `store` 없음, prompt-cache 힌트 없음, - OpenAI reasoning-compat payload shaping 없음, 숨겨진 OpenClaw attribution +- 네이티브 엔드포인트가 아닌 곳(호스트가 `api.openai.com`이 아닌 비어 있지 않은 `baseUrl`)에서 `api: "openai-completions"`를 사용할 경우, OpenClaw는 지원되지 않는 `developer` 역할로 인한 제공자 400 오류를 피하기 위해 `compat.supportsDeveloperRole: false`를 강제합니다. +- 프록시 스타일 OpenAI 호환 경로는 네이티브 OpenAI 전용 요청 + 형성도 건너뜁니다: `service_tier` 없음, Responses `store` 없음, 프롬프트 캐시 힌트 없음, + OpenAI 추론 호환 페이로드 형성 없음, 숨겨진 OpenClaw attribution 헤더 없음. -- `baseUrl`이 비어 있거나 생략되면 OpenClaw는 기본 OpenAI 동작을 유지합니다(`api.openai.com`으로 해결됨). -- 안전을 위해 비네이티브 `openai-completions` 엔드포인트에서는 명시적인 `compat.supportsDeveloperRole: true`도 여전히 override됩니다. +- `baseUrl`이 비어 있거나 생략되면 OpenClaw는 기본 OpenAI 동작을 유지합니다(`api.openai.com`으로 해석됨). +- 안전을 위해 명시적인 `compat.supportsDeveloperRole: true`도 비네이티브 `openai-completions` 엔드포인트에서는 여전히 재정의됩니다. ## CLI 예시 @@ -815,11 +804,11 @@ openclaw models set opencode/claude-opus-4-6 openclaw models list ``` -전체 구성 예시는 [/gateway/configuration](/ko/gateway/configuration)도 참고하세요. +전체 구성 예시는 [/gateway/configuration](/ko/gateway/configuration)을 참조하세요. -## 관련 항목 +## 관련 -- [Models](/ko/concepts/models) — 모델 구성 및 alias -- [Model Failover](/ko/concepts/model-failover) — 폴백 체인과 재시도 동작 -- [Configuration Reference](/ko/gateway/configuration-reference#agent-defaults) — 모델 config 키 -- [Providers](/ko/providers) — provider별 설정 가이드 +- [Models](/ko/concepts/models) — 모델 구성 및 별칭 +- [Model Failover](/ko/concepts/model-failover) — 폴백 체인 및 재시도 동작 +- [Configuration Reference](/ko/gateway/configuration-reference#agent-defaults) — 모델 구성 키 +- [Providers](/ko/providers) — 제공자별 설정 가이드 diff --git a/docs/ko/concepts/qa-e2e-automation.md b/docs/ko/concepts/qa-e2e-automation.md index d56b6b8bf..dbe0b97d5 100644 --- a/docs/ko/concepts/qa-e2e-automation.md +++ b/docs/ko/concepts/qa-e2e-automation.md @@ -2,14 +2,14 @@ read_when: - qa-lab 또는 qa-channel 확장 시 - 리포지토리 기반 QA 시나리오 추가 시 - - Gateway 대시보드 주변에 더 높은 현실성의 QA 자동화를 구축할 때 -summary: qa-lab, qa-channel, 시드된 시나리오, 프로토콜 보고서를 위한 비공개 QA 자동화 구조 + - Gateway 대시보드를 중심으로 더 높은 현실성의 QA 자동화 구축 시 +summary: qa-lab, qa-channel, 시드된 시나리오, 프로토콜 보고서를 위한 비공개 QA 자동화 구성 title: QA E2E 자동화 x-i18n: - generated_at: "2026-04-08T05:55:40Z" + generated_at: "2026-04-09T01:27:48Z" model: gpt-5.4 provider: openai - source_hash: 57da147dc06abf9620290104e01a83b42182db1806514114fd9e8467492cda99 + source_hash: c922607d67e0f3a2489ac82bc9f510f7294ced039c1014c15b676d826441d833 source_path: concepts/qa-e2e-automation.md workflow: 15 --- @@ -22,16 +22,16 @@ x-i18n: 현재 구성 요소: - `extensions/qa-channel`: DM, 채널, 스레드, - 반응, 수정, 삭제 표면을 갖춘 합성 메시지 채널 -- `extensions/qa-lab`: 대화 기록을 관찰하고, + 리액션, 편집, 삭제 인터페이스를 갖춘 합성 메시지 채널 +- `extensions/qa-lab`: 트랜스크립트를 관찰하고, 인바운드 메시지를 주입하며, Markdown 보고서를 내보내기 위한 디버거 UI 및 QA 버스 -- `qa/`: 시작 작업과 기준 QA +- `qa/`: 시작 작업과 기본 QA 시나리오를 위한 리포지토리 기반 시드 자산 현재 QA 운영자 흐름은 2패널 QA 사이트입니다: - 왼쪽: 에이전트가 있는 Gateway 대시보드(Control UI) -- 오른쪽: Slack과 유사한 대화 기록 및 시나리오 계획을 보여주는 QA Lab +- 오른쪽: Slack 스타일의 트랜스크립트와 시나리오 계획을 보여주는 QA Lab 다음으로 실행합니다: @@ -39,12 +39,12 @@ x-i18n: pnpm qa:lab:up ``` -이 명령은 QA 사이트를 빌드하고, Docker 기반 gateway 레인을 시작하며, 운영자 또는 자동화 루프가 에이전트에 QA -미션을 전달하고, 실제 채널 동작을 관찰하며, 무엇이 성공했고 실패했으며 -무엇이 계속 막혀 있었는지 기록할 수 있는 QA Lab 페이지를 노출합니다. +이 명령은 QA 사이트를 빌드하고, Docker 기반 gateway 레인을 시작하며, 운영자나 자동화 루프가 에이전트에 QA +미션을 부여하고, 실제 채널 동작을 관찰하며, 무엇이 작동했고 실패했으며 +또는 계속 막혀 있었는지를 기록할 수 있는 QA Lab 페이지를 노출합니다. -매번 Docker 이미지를 다시 빌드하지 않고 더 빠르게 QA Lab UI를 반복 개발하려면, -바인드 마운트된 QA Lab 번들로 스택을 시작하세요: +매번 Docker 이미지를 다시 빌드하지 않고 QA Lab UI를 더 빠르게 반복 개발하려면, +bind mount된 QA Lab 번들로 스택을 시작하세요: ```bash pnpm openclaw qa docker-build-image @@ -54,8 +54,8 @@ pnpm qa:lab:watch ``` `qa:lab:up:fast`는 사전 빌드된 이미지에서 Docker 서비스를 유지하고 -`extensions/qa-lab/web/dist`를 `qa-lab` 컨테이너에 바인드 마운트합니다. `qa:lab:watch`는 -변경 시 해당 번들을 다시 빌드하며, QA Lab 자산 해시가 바뀌면 브라우저가 자동으로 다시 로드됩니다. +`extensions/qa-lab/web/dist`를 `qa-lab` 컨테이너에 bind mount합니다. `qa:lab:watch`는 +변경 시 해당 번들을 다시 빌드하고, QA Lab 자산 해시가 변경되면 브라우저가 자동으로 다시 로드됩니다. ## 리포지토리 기반 시드 @@ -64,12 +64,12 @@ pnpm qa:lab:watch - `qa/scenarios/index.md` - `qa/scenarios/*.md` -이들은 QA 계획이 사람과 -에이전트 모두에게 보이도록 의도적으로 git에 포함됩니다. 기준 목록은 다음을 포괄할 만큼 충분히 넓게 유지되어야 합니다: +이 파일들은 QA 계획이 사람과 +에이전트 모두에게 보이도록 의도적으로 git에 포함됩니다. 기본 목록은 다음을 포괄할 만큼 충분히 넓게 유지되어야 합니다: - DM 및 채널 채팅 - 스레드 동작 -- 메시지 작업 수명 주기 +- 메시지 액션 수명 주기 - cron 콜백 - 메모리 회상 - 모델 전환 @@ -80,13 +80,61 @@ pnpm qa:lab:watch ## 보고 `qa-lab`은 관찰된 버스 타임라인에서 Markdown 프로토콜 보고서를 내보냅니다. -이 보고서는 다음에 답해야 합니다: +보고서는 다음에 답해야 합니다: - 무엇이 작동했는가 - 무엇이 실패했는가 - 무엇이 계속 막혀 있었는가 - 어떤 후속 시나리오를 추가할 가치가 있는가 +캐릭터 및 스타일 검사를 위해 동일한 시나리오를 여러 라이브 모델 +ref에서 실행하고 판단된 Markdown 보고서를 작성하세요: + +```bash +pnpm openclaw qa character-eval \ + --model openai/gpt-5.4,thinking=xhigh \ + --model openai/gpt-5.2,thinking=xhigh \ + --model openai/gpt-5,thinking=xhigh \ + --model anthropic/claude-opus-4-6,thinking=high \ + --model anthropic/claude-sonnet-4-6,thinking=high \ + --model zai/glm-5.1,thinking=high \ + --model moonshot/kimi-k2.5,thinking=high \ + --model google/gemini-3.1-pro-preview,thinking=high \ + --judge-model openai/gpt-5.4,thinking=xhigh,fast \ + --judge-model anthropic/claude-opus-4-6,thinking=high \ + --blind-judge-models \ + --concurrency 16 \ + --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은 기본적으로 +`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는 기본적으로 +`openai/gpt-5.4,thinking=xhigh,fast` 및 +`anthropic/claude-opus-4-6,thinking=high`를 사용합니다. + ## 관련 문서 - [테스트](/ko/help/testing) diff --git a/docs/ko/gateway/cli-backends.md b/docs/ko/gateway/cli-backends.md index 3f2f42112..5d1a7e715 100644 --- a/docs/ko/gateway/cli-backends.md +++ b/docs/ko/gateway/cli-backends.md @@ -1,47 +1,41 @@ --- read_when: - - API 제공자가 실패할 때 신뢰할 수 있는 대체 수단을 원할 때 - - Codex CLI 또는 다른 로컬 AI CLI를 실행 중이며 이를 재사용하고 싶을 때 - - CLI 백엔드 도구 접근을 위한 MCP 루프백 브리지를 이해하고 싶을 때 -summary: 선택적 MCP 도구 브리지와 함께 사용하는 로컬 AI CLI 대체용 CLI 백엔드 + - API 제공자가 실패할 때 안정적인 폴백이 필요합니다 + - Codex CLI 또는 다른 로컬 AI CLI를 실행 중이며 이를 재사용하고 싶습니다 + - CLI 백엔드 도구 액세스를 위한 MCP 루프백 브리지를 이해하고 싶습니다 +summary: 'CLI 백엔드: 선택적 MCP 도구 브리지와 함께 사용하는 로컬 AI CLI 폴백' title: CLI 백엔드 x-i18n: - generated_at: "2026-04-08T02:14:36Z" + generated_at: "2026-04-09T01:28:04Z" model: gpt-5.4 provider: openai - source_hash: b0e8c41f5f5a8e34466f6b765e5c08585ef1788fa9e9d953257324bcc6cbc414 + source_hash: 9b458f9fe6fa64c47864c8c180f3dedfd35c5647de470a2a4d31c26165663c20 source_path: gateway/cli-backends.md workflow: 15 --- -# CLI 백엔드 (대체 런타임) +# CLI 백엔드(폴백 런타임) -OpenClaw는 API 제공자가 중단되거나, -속도 제한에 걸리거나, 일시적으로 오작동할 때 **텍스트 전용 대체 수단**으로 **로컬 AI CLI**를 실행할 수 있습니다. 이는 의도적으로 보수적으로 설계되었습니다: +OpenClaw는 API 제공자가 중단되거나, 속도 제한에 걸리거나, 일시적으로 오작동할 때 **텍스트 전용 폴백**으로 **로컬 AI CLI**를 실행할 수 있습니다. 이는 의도적으로 보수적으로 설계되었습니다. -- `bundleMcp: true`가 설정된 백엔드는 루프백 MCP 브리지를 통해 gateway 도구를 받을 수 있지만, **OpenClaw 도구가 직접 주입되지는 않습니다**. -- 이를 지원하는 CLI에 대해 **JSONL 스트리밍**을 지원합니다. -- **세션이 지원되므로** 후속 턴도 일관성을 유지합니다. -- CLI가 이미지 경로를 받는다면 **이미지를 전달할 수 있습니다**. +- **OpenClaw 도구는 직접 주입되지 않지만**, `bundleMcp: true`가 설정된 백엔드는 루프백 MCP 브리지를 통해 게이트웨이 도구를 받을 수 있습니다. +- 이를 지원하는 CLI를 위한 **JSONL 스트리밍** +- **세션 지원**(후속 턴의 일관성 유지) +- CLI가 이미지 경로를 허용하면 **이미지 전달 가능** -이 기능은 기본 경로라기보다 **안전망**으로 설계되었습니다. 외부 API에 의존하지 않고 -“항상 동작하는” 텍스트 응답이 필요할 때 사용하세요. +이는 기본 경로라기보다 **안전망**으로 설계되었습니다. 외부 API에 의존하지 않고 “항상 동작하는” 텍스트 응답이 필요할 때 사용하세요. -ACP 세션 제어, 백그라운드 작업, -스레드/대화 바인딩, 영구적인 외부 코딩 세션을 갖춘 전체 하네스 런타임이 필요하다면 -대신 [ACP Agents](/ko/tools/acp-agents)를 사용하세요. CLI 백엔드는 ACP가 아닙니다. +ACP 세션 제어, 백그라운드 작업, 스레드/대화 바인딩, 영구적인 외부 코딩 세션을 포함한 전체 하네스 런타임이 필요하다면 대신 [ACP Agents](/ko/tools/acp-agents)를 사용하세요. CLI 백엔드는 ACP가 아닙니다. ## 초보자용 빠른 시작 -Codex CLI는 **아무 설정 없이도** 사용할 수 있습니다(번들된 OpenAI plugin이 -기본 백엔드를 등록합니다): +Codex CLI는 **아무 설정 없이도** 사용할 수 있습니다(번들 OpenAI plugin이 기본 백엔드를 등록합니다). ```bash openclaw agent --message "hi" --model codex-cli/gpt-5.4 ``` -gateway가 launchd/systemd 아래에서 실행되고 PATH가 최소화되어 있다면, -명령 경로만 추가하세요: +게이트웨이가 launchd/systemd 아래에서 실행되고 PATH가 최소화되어 있다면 명령 경로만 추가하세요. ```json5 { @@ -57,15 +51,13 @@ gateway가 launchd/systemd 아래에서 실행되고 PATH가 최소화되어 있 } ``` -이것으로 끝입니다. CLI 자체 외에 별도의 키나 추가 인증 설정은 필요하지 않습니다. +이것으로 충분합니다. CLI 자체 외에는 키도, 추가 인증 설정도 필요하지 않습니다. -gateway 호스트에서 번들된 CLI 백엔드를 **기본 메시지 제공자**로 사용하는 경우, -이제 OpenClaw는 설정이 모델 ref 또는 -`agents.defaults.cliBackends` 아래에서 해당 백엔드를 명시적으로 참조하면 소유 번들 plugin을 자동으로 로드합니다. +번들 CLI 백엔드를 게이트웨이 호스트의 **기본 메시지 제공자**로 사용하는 경우, 이제 OpenClaw는 구성에서 모델 ref 또는 `agents.defaults.cliBackends` 아래에 해당 백엔드를 명시적으로 참조하면 소유 번들 plugin을 자동으로 로드합니다. -## 대체 수단으로 사용하기 +## 폴백으로 사용하기 -CLI 백엔드를 대체 목록에 추가하면 기본 모델이 실패할 때만 실행됩니다: +CLI 백엔드를 폴백 목록에 추가하면 기본 모델이 실패할 때만 실행됩니다. ```json5 { @@ -86,26 +78,25 @@ CLI 백엔드를 대체 목록에 추가하면 기본 모델이 실패할 때만 참고: -- `agents.defaults.models`(허용 목록)을 사용하는 경우 CLI 백엔드 모델도 여기에 포함해야 합니다. -- 기본 제공자가 실패하면(인증, 속도 제한, 타임아웃), OpenClaw가 - 다음으로 CLI 백엔드를 시도합니다. +- `agents.defaults.models`(허용 목록)를 사용하는 경우, CLI 백엔드 모델도 여기에 포함해야 합니다. +- 기본 제공자가 실패하면(auth, 속도 제한, 시간 초과) OpenClaw가 다음으로 CLI 백엔드를 시도합니다. -## 설정 개요 +## 구성 개요 -모든 CLI 백엔드는 다음 아래에 있습니다: +모든 CLI 백엔드는 다음 아래에 있습니다. ``` agents.defaults.cliBackends ``` -각 항목은 **provider id**(예: `codex-cli`, `my-cli`)로 키 지정됩니다. -provider id는 모델 ref의 왼쪽 부분이 됩니다: +각 항목은 **provider id**(예: `codex-cli`, `my-cli`)를 키로 사용합니다. +provider id는 모델 ref의 왼쪽 부분이 됩니다. ``` / ``` -### 설정 예시 +### 예시 구성 ```json5 { @@ -129,6 +120,9 @@ provider id는 모델 ref의 왼쪽 부분이 됩니다: sessionMode: "existing", sessionIdFields: ["session_id", "conversation_id"], systemPromptArg: "--system", + // Codex 스타일 CLI는 대신 프롬프트 파일을 가리킬 수 있습니다: + // systemPromptFileConfigArg: "-c", + // systemPromptFileConfigKey: "model_instructions_file", systemPromptWhen: "first", imageArg: "--image", imageMode: "repeat", @@ -140,71 +134,63 @@ provider id는 모델 ref의 왼쪽 부분이 됩니다: } ``` -## 동작 방식 +## 작동 방식 -1. provider 접두사(`codex-cli/...`)를 기준으로 **백엔드를 선택합니다**. -2. 동일한 OpenClaw 프롬프트 + 워크스페이스 컨텍스트를 사용해 **시스템 프롬프트를 구성합니다**. -3. 기록의 일관성을 유지하기 위해 지원되는 경우 세션 id와 함께 **CLI를 실행합니다**. -4. 출력을 **파싱**(JSON 또는 일반 텍스트)하고 최종 텍스트를 반환합니다. -5. 후속 요청이 동일한 CLI 세션을 재사용할 수 있도록 백엔드별 **세션 id를 저장합니다**. +1. provider 접두사(`codex-cli/...`)를 기준으로 **백엔드를 선택**합니다. +2. 동일한 OpenClaw 프롬프트 + 워크스페이스 컨텍스트를 사용해 **시스템 프롬프트를 구성**합니다. +3. 기록의 일관성을 유지하기 위해 지원되는 경우 세션 id와 함께 **CLI를 실행**합니다. +4. **출력을 파싱**(JSON 또는 일반 텍스트)하고 최종 텍스트를 반환합니다. +5. **백엔드별로 세션 id를 유지**하여 후속 요청에서 동일한 CLI 세션을 재사용합니다. -번들된 Anthropic `claude-cli` 백엔드가 다시 지원됩니다. Anthropic 직원이 -OpenClaw 스타일의 Claude CLI 사용이 다시 허용된다고 알려주었기 때문에, Anthropic이 -새 정책을 발표하지 않는 한 OpenClaw는 이 통합에 대해 -`claude -p` 사용을 허용된 것으로 간주합니다. +번들 Anthropic `claude-cli` 백엔드가 다시 지원됩니다. Anthropic 직원이 OpenClaw 스타일 Claude CLI 사용이 다시 허용된다고 알려주었으므로, Anthropic이 새로운 정책을 발표하지 않는 한 OpenClaw는 이 통합에 대해 `claude -p` 사용을 허용된 것으로 간주합니다. +번들 OpenAI `codex-cli` 백엔드는 OpenClaw의 시스템 프롬프트를 Codex의 `model_instructions_file` 구성 재정의(`-c +model_instructions_file="..."`)를 통해 전달합니다. Codex는 Claude 스타일 `--append-system-prompt` 플래그를 제공하지 않으므로, OpenClaw는 새 Codex CLI 세션마다 조합된 프롬프트를 임시 파일에 기록합니다. + ## 세션 -- CLI가 세션을 지원하면 `sessionArg`(예: `--session-id`) 또는 - 세션 ID를 여러 플래그에 삽입해야 할 때 `sessionArgs`(플레이스홀더 `{sessionId}`)를 설정하세요. -- CLI가 다른 플래그를 사용하는 **resume 하위 명령**을 사용한다면, - `resumeArgs`(`resuming` 시 `args`를 대체)와 필요하다면 `resumeOutput` - (JSON이 아닌 resume용)을 설정하세요. +- CLI가 세션을 지원하면 `sessionArg`(예: `--session-id`) 또는 여러 플래그에 ID를 삽입해야 할 때 `sessionArgs`(플레이스홀더 `{sessionId}`)를 설정하세요. +- CLI가 다른 플래그를 사용하는 **재개 서브커맨드**를 사용한다면 `resumeArgs`(`args`를 대체)를 설정하고, 선택적으로 `resumeOutput`(JSON이 아닌 재개용)을 설정하세요. - `sessionMode`: - - `always`: 항상 세션 id를 전송합니다(저장된 값이 없으면 새 UUID 사용). - - `existing`: 이전에 저장된 세션 id가 있을 때만 전송합니다. - - `none`: 세션 id를 절대 전송하지 않습니다. + - `always`: 항상 세션 id를 보냅니다(저장된 값이 없으면 새 UUID 생성). + - `existing`: 이전에 저장된 세션 id가 있을 때만 보냅니다. + - `none`: 세션 id를 절대 보내지 않습니다. -직렬화 관련 참고: +직렬화 참고: -- `serialize: true`는 동일 레인 실행의 순서를 유지합니다. +- `serialize: true`는 동일한 레인에서의 실행 순서를 유지합니다. - 대부분의 CLI는 하나의 provider 레인에서 직렬화됩니다. -- OpenClaw는 재로그인, 토큰 교체, 또는 변경된 인증 프로필 자격 증명을 포함해 백엔드 인증 상태가 바뀌면 저장된 CLI 세션 재사용을 중단합니다. +- OpenClaw는 백엔드 인증 상태가 변경되면 저장된 CLI 세션 재사용을 중단합니다. 여기에는 재로그인, 토큰 교체, 인증 프로필 자격 증명 변경이 포함됩니다. ## 이미지(전달) -CLI가 이미지 경로를 받을 수 있다면 `imageArg`를 설정하세요: +CLI가 이미지 경로를 허용하면 `imageArg`를 설정하세요. ```json5 imageArg: "--image", imageMode: "repeat" ``` -OpenClaw는 base64 이미지를 임시 파일에 씁니다. `imageArg`가 설정되어 있으면 해당 -경로가 CLI 인수로 전달됩니다. `imageArg`가 없으면 OpenClaw는 -파일 경로를 프롬프트에 추가합니다(경로 주입). 이는 일반 경로에서 로컬 파일을 자동으로 -로드하는 CLI에는 충분합니다. +OpenClaw는 base64 이미지를 임시 파일에 기록합니다. `imageArg`가 설정되어 있으면 해당 경로가 CLI 인수로 전달됩니다. `imageArg`가 없으면 OpenClaw는 파일 경로를 프롬프트에 추가합니다(경로 주입). 이는 일반 경로에서 로컬 파일을 자동 로드하는 CLI에는 충분합니다. ## 입력 / 출력 - `output: "json"`(기본값)은 JSON을 파싱하고 텍스트 + 세션 id를 추출하려고 시도합니다. -- Gemini CLI JSON 출력의 경우, `usage`가 없거나 비어 있으면 OpenClaw는 - `response`에서 응답 텍스트를, `stats`에서 사용량을 읽습니다. -- `output: "jsonl"`은 JSONL 스트림(예: Codex CLI `--json`)을 파싱하고, 존재할 경우 최종 에이전트 메시지와 세션 - 식별자를 추출합니다. +- Gemini CLI JSON 출력의 경우 `usage`가 없거나 비어 있으면 OpenClaw는 `response`에서 응답 텍스트를, `stats`에서 사용량을 읽습니다. +- `output: "jsonl"`은 JSONL 스트림(예: Codex CLI `--json`)을 파싱하고 존재할 경우 최종 에이전트 메시지와 세션 식별자를 추출합니다. - `output: "text"`는 stdout을 최종 응답으로 처리합니다. 입력 모드: - `input: "arg"`(기본값)는 프롬프트를 마지막 CLI 인수로 전달합니다. -- `input: "stdin"`은 프롬프트를 stdin으로 보냅니다. +- `input: "stdin"`은 stdin을 통해 프롬프트를 보냅니다. - 프롬프트가 매우 길고 `maxPromptArgChars`가 설정되어 있으면 stdin이 사용됩니다. ## 기본값(plugin 소유) -번들된 OpenAI plugin은 `codex-cli`에 대한 기본값도 등록합니다: +번들 OpenAI plugin도 `codex-cli`에 대한 기본값을 등록합니다. - `command: "codex"` - `args: ["exec","--json","--color","never","--sandbox","workspace-write","--skip-git-repo-check"]` @@ -215,7 +201,7 @@ OpenClaw는 base64 이미지를 임시 파일에 씁니다. `imageArg`가 설정 - `imageArg: "--image"` - `sessionMode: "existing"` -번들된 Google plugin도 `google-gemini-cli`에 대한 기본값을 등록합니다: +번들 Google plugin도 `google-gemini-cli`에 대한 기본값을 등록합니다. - `command: "gemini"` - `args: ["--output-format", "json", "--prompt", "{prompt}"]` @@ -226,68 +212,57 @@ OpenClaw는 base64 이미지를 임시 파일에 씁니다. `imageArg`가 설정 - `sessionMode: "existing"` - `sessionIdFields: ["session_id", "sessionId"]` -전제 조건: 로컬 Gemini CLI가 설치되어 있어야 하며 -`PATH`에서 `gemini`로 사용할 수 있어야 합니다(`brew install gemini-cli` 또는 -`npm install -g @google/gemini-cli`). +전제 조건: 로컬 Gemini CLI가 설치되어 있어야 하며 `PATH`에서 `gemini`로 사용할 수 있어야 합니다(`brew install gemini-cli` 또는 `npm install -g @google/gemini-cli`). -Gemini CLI JSON 관련 참고: +Gemini CLI JSON 참고: - 응답 텍스트는 JSON `response` 필드에서 읽습니다. -- `usage`가 없거나 비어 있으면 사용량은 `stats`로 대체됩니다. +- `usage`가 없거나 비어 있으면 사용량은 `stats`로 폴백합니다. - `stats.cached`는 OpenClaw `cacheRead`로 정규화됩니다. -- `stats.input`이 없으면 OpenClaw는 - `stats.input_tokens - stats.cached`에서 입력 토큰 수를 계산합니다. +- `stats.input`이 없으면 OpenClaw는 `stats.input_tokens - stats.cached`에서 입력 토큰 수를 계산합니다. -필요한 경우에만 덮어쓰세요(일반적으로 절대 `command` 경로). +필요한 경우에만 재정의하세요(일반적으로는 절대 `command` 경로). ## plugin 소유 기본값 -이제 CLI 백엔드 기본값은 plugin 표면의 일부입니다: +CLI 백엔드 기본값은 이제 plugin 표면의 일부입니다. - plugin은 `api.registerCliBackend(...)`로 이를 등록합니다. - 백엔드 `id`는 모델 ref의 provider 접두사가 됩니다. -- `agents.defaults.cliBackends.` 아래의 사용자 설정은 여전히 plugin 기본값을 덮어씁니다. -- 백엔드별 설정 정리는 선택적 `normalizeConfig` 훅을 통해 계속 plugin 소유로 유지됩니다. +- `agents.defaults.cliBackends.`의 사용자 구성은 여전히 plugin 기본값을 재정의합니다. +- 백엔드별 구성 정리는 선택적 `normalizeConfig` 훅을 통해 계속 plugin 소유로 유지됩니다. -## Bundle MCP 오버레이 +## 번들 MCP 오버레이 -CLI 백엔드는 **OpenClaw 도구 호출을 직접 받지 않지만**, 백엔드는 -`bundleMcp: true`로 생성된 MCP 설정 오버레이를 선택적으로 사용할 수 있습니다. +CLI 백엔드는 **OpenClaw 도구 호출을 직접 받지 않지만**, 백엔드는 `bundleMcp: true`로 생성된 MCP 구성 오버레이 사용을 선택할 수 있습니다. 현재 번들 동작: -- `claude-cli`: 생성된 엄격한 MCP 설정 파일 -- `codex-cli`: `mcp_servers`용 인라인 설정 오버라이드 +- `claude-cli`: 생성된 strict MCP 구성 파일 +- `codex-cli`: `mcp_servers`에 대한 인라인 구성 재정의 - `google-gemini-cli`: 생성된 Gemini 시스템 설정 파일 -bundle MCP가 활성화되면 OpenClaw는 다음을 수행합니다: +bundle MCP가 활성화되면 OpenClaw는 다음을 수행합니다. -- CLI 프로세스에 gateway 도구를 노출하는 루프백 HTTP MCP 서버를 시작합니다 -- 세션별 토큰(`OPENCLAW_MCP_TOKEN`)으로 브리지를 인증합니다 -- 도구 접근 범위를 현재 세션, 계정, 채널 컨텍스트로 제한합니다 -- 현재 워크스페이스에 대해 활성화된 bundle-MCP 서버를 로드합니다 -- 이를 기존 백엔드 MCP 설정/설정 형태와 병합합니다 -- 소유 extension의 백엔드 소유 통합 모드를 사용해 실행 설정을 다시 작성합니다 +- 게이트웨이 도구를 CLI 프로세스에 노출하는 루프백 HTTP MCP 서버를 시작합니다. +- 세션별 토큰(`OPENCLAW_MCP_TOKEN`)으로 브리지를 인증합니다. +- 현재 세션, 계정, 채널 컨텍스트로 도구 액세스 범위를 제한합니다. +- 현재 워크스페이스에서 활성화된 bundle-MCP 서버를 로드합니다. +- 이를 기존 백엔드 MCP 구성/설정 형태와 병합합니다. +- 소유 확장의 백엔드 소유 통합 모드를 사용해 시작 구성을 다시 작성합니다. -활성화된 MCP 서버가 없더라도, 백엔드가 bundle MCP를 선택한 경우 OpenClaw는 -백그라운드 실행이 격리된 상태를 유지하도록 여전히 엄격한 설정을 주입합니다. +활성화된 MCP 서버가 없더라도, 백엔드가 bundle MCP 사용을 선택한 경우 OpenClaw는 백그라운드 실행이 격리된 상태를 유지하도록 strict 구성을 계속 주입합니다. ## 제한 사항 -- **직접적인 OpenClaw 도구 호출은 없습니다.** OpenClaw는 - CLI 백엔드 프로토콜에 도구 호출을 주입하지 않습니다. 백엔드는 - `bundleMcp: true`를 선택한 경우에만 gateway 도구를 볼 수 있습니다. -- **스트리밍은 백엔드마다 다릅니다.** 일부 백엔드는 JSONL을 스트리밍하고, 다른 백엔드는 - 종료 시점까지 버퍼링합니다. +- **직접 OpenClaw 도구 호출 없음.** OpenClaw는 CLI 백엔드 프로토콜에 도구 호출을 주입하지 않습니다. 백엔드는 `bundleMcp: true`를 선택한 경우에만 게이트웨이 도구를 볼 수 있습니다. +- **스트리밍은 백엔드별입니다.** 일부 백엔드는 JSONL을 스트리밍하고, 다른 백엔드는 종료 시까지 버퍼링합니다. - **구조화된 출력**은 CLI의 JSON 형식에 따라 달라집니다. -- **Codex CLI 세션**은 텍스트 출력으로 resume되며(JSONL 아님), - 이는 초기 `--json` 실행보다 구조화가 덜 되어 있습니다. OpenClaw 세션은 여전히 - 정상적으로 동작합니다. +- **Codex CLI 세션**은 텍스트 출력(JSONL 아님)으로 재개되므로 초기 `--json` 실행보다 구조가 덜 엄격합니다. OpenClaw 세션 자체는 여전히 정상적으로 동작합니다. ## 문제 해결 - **CLI를 찾을 수 없음**: `command`를 전체 경로로 설정하세요. - **잘못된 모델 이름**: `modelAliases`를 사용해 `provider/model` → CLI 모델로 매핑하세요. -- **세션 연속성 없음**: `sessionArg`가 설정되어 있고 `sessionMode`가 - `none`이 아닌지 확인하세요(Codex CLI는 현재 JSON 출력으로 resume할 수 없습니다). -- **이미지가 무시됨**: `imageArg`를 설정하고(그리고 CLI가 파일 경로를 지원하는지 확인하세요). +- **세션 연속성 없음**: `sessionArg`가 설정되어 있고 `sessionMode`가 `none`이 아닌지 확인하세요(Codex CLI는 현재 JSON 출력으로 재개할 수 없음). +- **이미지가 무시됨**: `imageArg`를 설정하고(CLI가 파일 경로를 지원하는지도 확인하세요). diff --git a/docs/ko/gateway/configuration-reference.md b/docs/ko/gateway/configuration-reference.md index bcd90124d..38939dbbe 100644 --- a/docs/ko/gateway/configuration-reference.md +++ b/docs/ko/gateway/configuration-reference.md @@ -1,43 +1,43 @@ --- read_when: - - 정확한 필드 수준의 구성 의미 또는 기본값이 필요할 때 - - 채널, 모델, gateway 또는 tool 구성 블록을 검증하고 있을 때 -summary: 핵심 OpenClaw 키, 기본값, 그리고 전용 서브시스템 참조 링크를 위한 Gateway 구성 참조 + - 정확한 필드 수준 config 의미 체계나 기본값이 필요할 때 + - 채널, 모델, gateway 또는 도구 config 블록을 검증할 때 +summary: 핵심 OpenClaw 키, 기본값, 전용 하위 시스템 참조 링크를 위한 Gateway config 참조 title: 구성 참조 x-i18n: - generated_at: "2026-04-08T06:01:03Z" + generated_at: "2026-04-09T01:33:39Z" model: gpt-5.4 provider: openai - source_hash: 2f9ab34fb56897a77cb038d95bea21e8530d8f0402b66d1ee97c73822a1e8fd4 + source_hash: a9d6d0c542b9874809491978fdcf8e1a7bb35a4873db56aa797963d03af4453c source_path: gateway/configuration-reference.md workflow: 15 --- # 구성 참조 -`~/.openclaw/openclaw.json`에 대한 핵심 구성 참조입니다. 작업 중심 개요는 [Configuration](/ko/gateway/configuration)을 참고하세요. +`~/.openclaw/openclaw.json`용 핵심 config 참조입니다. 작업 중심 개요는 [Configuration](/ko/gateway/configuration)을 참고하세요. -이 페이지는 주요 OpenClaw 구성 표면을 다루며, 서브시스템에 별도의 더 깊은 참조가 있는 경우 해당 링크를 제공합니다. 이 페이지는 모든 채널/플러그인 소유 명령 카탈로그나 모든 심층 메모리/QMD 노브를 한 페이지에 인라인으로 넣으려는 것은 **아닙니다**. +이 페이지는 주요 OpenClaw config 인터페이스를 다루며, 하위 시스템에 자체적으로 더 깊은 참조 문서가 있는 경우 해당 문서로 연결합니다. 이 페이지는 모든 채널/플러그인 소유 명령 카탈로그나 모든 심층 메모리/QMD 설정을 한 페이지에 인라인으로 넣으려는 것이 **아닙니다**. -코드 기준 진실: +코드 기준 정보: -- `openclaw config schema`는 검증과 Control UI에 사용되는 실제 JSON Schema를 출력하며, 사용 가능한 경우 번들/플러그인/채널 메타데이터가 병합됩니다 -- `config.schema.lookup`는 드릴다운 도구용으로 경로 범위가 지정된 단일 스키마 노드를 반환합니다 -- `pnpm config:docs:check` / `pnpm config:docs:gen`는 현재 스키마 표면과 구성 문서 기준 해시를 검증합니다 +- `openclaw config schema`는 검증과 Control UI에 사용되는 실제 JSON Schema를 출력하며, 사용 가능한 경우 번들/플러그인/채널 메타데이터를 병합합니다 +- `config.schema.lookup`은 드릴다운 도구용으로 하나의 경로 범위 schema 노드를 반환합니다 +- `pnpm config:docs:check` / `pnpm config:docs:gen`은 현재 schema 인터페이스에 대해 config 문서 기준 해시를 검증합니다 -전용 심층 참조: +전용 심화 참조: -- `agents.defaults.memorySearch.*`, `memory.qmd.*`, `memory.citations`, 그리고 `plugins.entries.memory-core.config.dreaming` 아래의 dreaming 구성을 위한 [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 config에 대해서는 [Memory configuration reference](/ko/reference/memory-config) +- 현재 내장 + 번들 명령 카탈로그에 대해서는 [Slash Commands](/ko/tools/slash-commands) +- 채널별 명령 인터페이스에 대해서는 해당 채널/플러그인 페이지 -구성 형식은 **JSON5**입니다(주석 + 후행 쉼표 허용). 모든 필드는 선택 사항이며, 생략되면 OpenClaw가 안전한 기본값을 사용합니다. +Config 형식은 **JSON5**입니다(주석 + 후행 쉼표 허용). 모든 필드는 선택 사항이며, 생략 시 OpenClaw가 안전한 기본값을 사용합니다. --- ## 채널 -각 채널은 해당 구성 섹션이 존재하면 자동으로 시작됩니다(`enabled: false`가 아닌 경우). +각 채널은 해당 config 섹션이 존재할 때 자동으로 시작됩니다(`enabled: false`가 아닌 한). ### DM 및 그룹 액세스 @@ -46,25 +46,25 @@ x-i18n: | DM 정책 | 동작 | | ------------------ | --------------------------------------------------------------- | | `pairing` (기본값) | 알 수 없는 발신자는 일회성 페어링 코드를 받으며, 소유자가 승인해야 함 | -| `allowlist` | `allowFrom`(또는 페어링된 허용 저장소)에 있는 발신자만 허용 | -| `open` | 모든 수신 DM 허용(`allowFrom: ["*"]` 필요) | -| `disabled` | 모든 수신 DM 무시 | +| `allowlist` | `allowFrom`(또는 페어링된 허용 저장소)에 있는 발신자만 허용 | +| `open` | 모든 인바운드 DM 허용(`allowFrom: ["*"]` 필요) | +| `disabled` | 모든 인바운드 DM 무시 | -| 그룹 정책 | 동작 | -| --------------------- | -------------------------------------------------------- | -| `allowlist` (기본값) | 구성된 허용 목록과 일치하는 그룹만 허용 | -| `open` | 그룹 허용 목록 우회(멘션 게이팅은 계속 적용) | -| `disabled` | 모든 그룹/룸 메시지 차단 | +| 그룹 정책 | 동작 | +| --------------------- | ------------------------------------------------------ | +| `allowlist` (기본값) | 구성된 허용 목록과 일치하는 그룹만 허용 | +| `open` | 그룹 허용 목록 우회(단, 멘션 게이팅은 계속 적용) | +| `disabled` | 모든 그룹/룸 메시지 차단 | -`channels.defaults.groupPolicy`는 공급자의 `groupPolicy`가 설정되지 않았을 때 기본값을 설정합니다. +`channels.defaults.groupPolicy`는 provider의 `groupPolicy`가 설정되지 않았을 때 기본값을 설정합니다. 페어링 코드는 1시간 후 만료됩니다. 대기 중인 DM 페어링 요청은 **채널당 3개**로 제한됩니다. -공급자 블록이 완전히 누락된 경우(`channels.` 부재), 런타임 그룹 정책은 시작 경고와 함께 `allowlist`(fail-closed)로 대체됩니다. +provider 블록이 완전히 누락된 경우(`channels.` 없음), 런타임 그룹 정책은 시작 시 경고와 함께 `allowlist`(fail-closed)로 대체됩니다. ### 채널 모델 재정의 -특정 채널 ID를 모델에 고정하려면 `channels.modelByChannel`을 사용하세요. 값은 `provider/model` 또는 구성된 모델 별칭을 받습니다. 이 채널 매핑은 세션에 이미 모델 재정의가 없는 경우(예: `/model`로 설정된 경우) 적용됩니다. +특정 채널 ID를 모델에 고정하려면 `channels.modelByChannel`을 사용하세요. 값은 `provider/model` 또는 구성된 모델 별칭을 받습니다. 이 채널 매핑은 세션에 이미 모델 재정의가 없는 경우에 적용됩니다(예: `/model`로 설정된 경우). ```json5 { @@ -85,9 +85,9 @@ x-i18n: } ``` -### 채널 기본값 및 heartbeat +### 채널 기본값과 하트비트 -공급자 간 공유 그룹 정책 및 heartbeat 동작에는 `channels.defaults`를 사용하세요: +provider 전반에 걸쳐 공유되는 그룹 정책과 하트비트 동작에는 `channels.defaults`를 사용하세요: ```json5 { @@ -105,15 +105,15 @@ x-i18n: } ``` -- `channels.defaults.groupPolicy`: 공급자 수준 `groupPolicy`가 설정되지 않았을 때의 대체 그룹 정책입니다. -- `channels.defaults.contextVisibility`: 모든 채널의 기본 보조 컨텍스트 가시성 모드입니다. 값: `all`(기본값, 인용/스레드/기록 컨텍스트를 모두 포함), `allowlist`(허용 목록 발신자의 컨텍스트만 포함), `allowlist_quote`(allowlist와 동일하지만 명시적 인용/답글 컨텍스트는 유지). 채널별 재정의: `channels..contextVisibility`. -- `channels.defaults.heartbeat.showOk`: heartbeat 출력에 정상 채널 상태를 포함합니다. -- `channels.defaults.heartbeat.showAlerts`: heartbeat 출력에 성능 저하/오류 상태를 포함합니다. -- `channels.defaults.heartbeat.useIndicator`: 압축된 표시기 스타일 heartbeat 출력을 렌더링합니다. +- `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`: 간결한 인디케이터 스타일 하트비트 출력을 렌더링합니다. ### WhatsApp -WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결된 세션이 존재하면 자동으로 시작됩니다. +WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결된 세션이 있으면 자동으로 시작됩니다. ```json5 { @@ -124,7 +124,7 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 textChunkLimit: 4000, chunkMode: "length", // length | newline mediaMaxMb: 50, - sendReadReceipts: true, // 파란 체크(셀프 채팅 모드에서는 false) + sendReadReceipts: true, // 파란 체크 표시(self-chat 모드에서는 false) groups: { "*": { requireMention: true }, }, @@ -164,9 +164,9 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 } ``` -- 아웃바운드 명령은 `default` 계정이 있으면 기본적으로 해당 계정을 사용하고, 그렇지 않으면 정렬된 첫 번째 구성 계정 ID를 사용합니다. -- 선택적 `channels.whatsapp.defaultAccount`는 구성된 계정 ID와 일치하는 경우 해당 대체 기본 계정 선택을 재정의합니다. -- 레거시 단일 계정 Baileys 인증 디렉터리는 `openclaw doctor`에 의해 `whatsapp/default`로 마이그레이션됩니다. +- 아웃바운드 명령은 `default` 계정이 있으면 기본적으로 해당 계정을 사용하고, 없으면 구성된 첫 번째 계정 ID(정렬 기준)를 사용합니다. +- 선택적 `channels.whatsapp.defaultAccount`는 구성된 계정 ID와 일치할 때 이 대체 기본 계정 선택을 재정의합니다. +- 기존 단일 계정 Baileys auth 디렉터리는 `openclaw doctor`에 의해 `whatsapp/default`로 마이그레이션됩니다. - 계정별 재정의: `channels.whatsapp.accounts..sendReadReceipts`, `channels.whatsapp.accounts..dmPolicy`, `channels.whatsapp.accounts..allowFrom`. @@ -185,24 +185,24 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 "*": { requireMention: true }, "-1001234567890": { allowFrom: ["@admin"], - systemPrompt: "응답은 짧게 유지하세요.", + systemPrompt: "Keep answers brief.", topics: { "99": { requireMention: false, skills: ["search"], - systemPrompt: "주제를 벗어나지 마세요.", + systemPrompt: "Stay on topic.", }, }, }, }, customCommands: [ - { command: "backup", description: "Git 백업" }, - { command: "generate", description: "이미지 생성" }, + { command: "backup", description: "Git backup" }, + { command: "generate", description: "Create an image" }, ], historyLimit: 50, replyToMode: "first", // off | first | all | batched linkPreview: true, - streaming: "partial", // off | partial | block | progress (기본값: off; 미리보기-편집 속도 제한을 피하려면 명시적으로 opt in) + streaming: "partial", // off | partial | block | progress (기본값: off, preview-edit 속도 제한을 피하려면 명시적으로 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`(일반 파일만 허용, symlink는 거부), 기본 계정에는 `TELEGRAM_BOT_TOKEN`이 대체값으로 사용됩니다. -- 선택적 `channels.telegram.defaultAccount`는 구성된 계정 ID와 일치하는 경우 기본 계정 선택을 재정의합니다. -- 다중 계정 구성(계정 ID 2개 이상)에서는 대체 라우팅을 피하려면 명시적 기본값(`channels.telegram.defaultAccount` 또는 `channels.telegram.accounts.default`)을 설정하세요. 누락되거나 잘못된 경우 `openclaw doctor`가 경고합니다. -- `configWrites: false`는 Telegram에서 시작된 구성 쓰기(슈퍼그룹 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)를 참고하세요. +- 봇 토큰: `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) 참고. ### Discord @@ -278,7 +278,7 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 requireMention: true, users: ["987654321098765432"], skills: ["docs"], - systemPrompt: "짧게만 답하세요.", + systemPrompt: "Short answers only.", }, }, }, @@ -297,7 +297,7 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 enabled: true, idleHours: 24, maxAgeHours: 0, - spawnSubagentSessions: false, // `sessions_spawn({ thread: true })`에 대한 opt-in + spawnSubagentSessions: false, // sessions_spawn({ thread: true })에 대한 opt-in }, voice: { enabled: true, @@ -333,36 +333,36 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 } ``` -- 토큰: `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 시간 단위 재정의(`0`은 비활성화) - - `maxAgeHours`: 하드 최대 사용 기간 시간 단위 재정의(`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.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)와 공유됩니다. - `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.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.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"`(기본값). 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을 삭제합니다. -**반응 알림 모드:** `off`(없음), `own`(봇의 메시지, 기본값), `all`(모든 메시지), `allowlist`(`guilds..users`의 모든 메시지). +**리액션 알림 모드:** `off`(없음), `own`(봇 메시지, 기본값), `all`(모든 메시지), `allowlist`(`guilds..users`의 사용자를 모든 메시지에 적용). ### Google Chat @@ -393,9 +393,9 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 } ``` -- 서비스 계정 JSON: 인라인(`serviceAccount`) 또는 파일 기반(`serviceAccountFile`)입니다. +- 서비스 계정 JSON: 인라인(`serviceAccount`) 또는 파일 기반(`serviceAccountFile`)을 지원합니다. - 서비스 계정 SecretRef도 지원됩니다(`serviceAccountRef`). -- env 대체값: `GOOGLE_CHAT_SERVICE_ACCOUNT` 또는 `GOOGLE_CHAT_SERVICE_ACCOUNT_FILE`. +- 환경 변수 대체값: `GOOGLE_CHAT_SERVICE_ACCOUNT` 또는 `GOOGLE_CHAT_SERVICE_ACCOUNT_FILE`. - 전달 대상에는 `spaces/` 또는 `users/`를 사용하세요. - `channels.googlechat.dangerouslyAllowNameMatching`는 변경 가능한 이메일 principal 매칭을 다시 활성화합니다(비상 호환 모드). @@ -419,7 +419,7 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 allowBots: false, users: ["U123"], skills: ["docs"], - systemPrompt: "짧게만 답하세요.", + systemPrompt: "Short answers only.", }, }, historyLimit: 50, @@ -464,30 +464,36 @@ WhatsApp은 gateway의 웹 채널(Baileys Web)을 통해 실행됩니다. 연결 } ``` -- **Socket mode**에는 `botToken`과 `appToken`이 모두 필요합니다(기본 계정 env 대체값은 `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN`). -- **HTTP mode**에는 `botToken`과 `signingSecret`(루트 또는 계정별)이 필요합니다. -- `botToken`, `appToken`, `signingSecret`, `userToken`은 일반 텍스트 문자열 또는 SecretRef 객체를 받을 수 있습니다. -- Slack 계정 스냅샷은 `botTokenSource`, `botTokenStatus`, `appTokenStatus`, 그리고 HTTP mode에서는 `signingSecretStatus`와 같은 자격 증명별 소스/상태 필드를 노출합니다. `configured_unavailable`은 해당 계정이 SecretRef를 통해 구성되었지만 현재 명령/런타임 경로에서 비밀 값을 해석할 수 없었음을 의미합니다. -- `configWrites: false`는 Slack에서 시작된 구성 쓰기를 차단합니다. -- 선택적 `channels.slack.defaultAccount`는 구성된 계정 ID와 일치하는 경우 기본 계정 선택을 재정의합니다. -- `channels.slack.streaming.mode`는 정규 Slack 스트림 모드 키입니다. `channels.slack.streaming.nativeTransport`는 Slack의 네이티브 스트리밍 전송을 제어합니다. 레거시 `streamMode`, 불리언 `streaming`, `nativeStreaming` 값은 자동 마이그레이션됩니다. +- **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 쓰기를 차단합니다. +- 선택적 `channels.slack.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. +- `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 스타일의 "입력 중..." 스레드 상태는 답글 스레드 대상을 요구합니다. 최상위 DM은 기본적으로 스레드 밖으로 유지되므로, 스레드 스타일 미리보기 대신 `typingReaction` 또는 일반 전달을 사용합니다. -- `typingReaction`은 답글이 실행되는 동안 수신 Slack 메시지에 임시 반응을 추가하고, 완료 시 제거합니다. `"hourglass_flowing_sand"`와 같은 Slack 이모지 shortcode를 사용하세요. -- `channels.slack.execApprovals`: Slack 네이티브 exec 승인 전달 및 승인자 권한 부여. 스키마는 Discord와 동일합니다: `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 이모지 shortcode를 사용하세요. +- `channels.slack.execApprovals`: Slack 네이티브 exec 승인 전달 및 승인자 권한 부여. Discord와 동일한 schema를 사용합니다: `enabled` (`true`/`false`/`"auto"`), `approvers` (Slack 사용자 ID), `agentFilter`, `sessionFilter`, `target` (`"dm"`, `"channel"`, 또는 `"both"`). -| 작업 그룹 | 기본값 | 참고 | -| ----------- | ------- | ---------------------- | -| reactions | 활성화 | 반응 추가 + 반응 목록 | -| messages | 활성화 | 읽기/보내기/편집/삭제 | -| pins | 활성화 | 고정/해제/목록 | -| memberInfo | 활성화 | 멤버 정보 | -| emojiList | 활성화 | 커스텀 이모지 목록 | +| 액션 그룹 | 기본값 | 참고 사항 | +| --------- | ------- | ----------------------- | +| reactions | 활성화 | 리액션 추가 + 목록 조회 | +| messages | 활성화 | 읽기/보내기/수정/삭제 | +| pins | 활성화 | 고정/해제/목록 | +| memberInfo| 활성화 | 멤버 정보 | +| emojiList | 활성화 | 사용자 정의 이모지 목록 | ### Mattermost @@ -511,7 +517,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, @@ -521,19 +527,23 @@ Mattermost는 플러그인으로 제공됩니다: `openclaw plugins install @ope } ``` -채팅 모드: `oncall`(@-멘션 시 응답, 기본값), `onmessage`(모든 메시지), `onchar`(트리거 접두사로 시작하는 메시지). +채팅 모드: `oncall`(@-mention에 응답, 기본값), `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는 callback 호스트/도메인을 포함하도록 `ServiceSettings.AllowedUntrustedInternalConnections`가 필요할 수 있습니다. +- `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에서 시작된 구성 쓰기를 허용하거나 거부합니다. +- `channels.mattermost.configWrites`: Mattermost에서 시작된 config 쓰기를 허용하거나 거부합니다. - `channels.mattermost.requireMention`: 채널에서 응답하기 전에 `@mention`을 요구합니다. - `channels.mattermost.groups..requireMention`: 채널별 멘션 게이팅 재정의(`"*"`는 기본값). -- 선택적 `channels.mattermost.defaultAccount`는 구성된 계정 ID와 일치하는 경우 기본 계정 선택을 재정의합니다. +- 선택적 `channels.mattermost.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. ### Signal @@ -554,15 +564,15 @@ Mattermost 네이티브 명령이 활성화되면: } ``` -**반응 알림 모드:** `off`, `own`(기본값), `all`, `allowlist`(`reactionAllowlist`에서 가져옴). +**리액션 알림 모드:** `off`, `own`(기본값), `all`, `allowlist`(`reactionAllowlist` 기준). -- `channels.signal.account`: 채널 시작을 특정 Signal 계정 식별자에 고정합니다. -- `channels.signal.configWrites`: Signal에서 시작된 구성 쓰기를 허용하거나 거부합니다. -- 선택적 `channels.signal.defaultAccount`는 구성된 계정 ID와 일치하는 경우 기본 계정 선택을 재정의합니다. +- `channels.signal.account`: 특정 Signal 계정 식별자에 채널 시작을 고정합니다. +- `channels.signal.configWrites`: Signal에서 시작된 config 쓰기를 허용하거나 거부합니다. +- 선택적 `channels.signal.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. ### BlueBubbles -BlueBubbles는 권장되는 iMessage 경로입니다(플러그인 기반, `channels.bluebubbles` 아래에서 구성). +BlueBubbles는 권장되는 iMessage 경로입니다(플러그인 기반, `channels.bluebubbles` 아래 구성). ```json5 { @@ -570,21 +580,21 @@ BlueBubbles는 권장되는 iMessage 경로입니다(플러그인 기반, `chann bluebubbles: { enabled: true, dmPolicy: "pairing", - // serverUrl, password, webhookPath, 그룹 제어 및 고급 작업: + // serverUrl, password, webhookPath, group controls, 고급 액션: // /channels/bluebubbles 참고 }, }, } ``` -- 여기에서 다루는 핵심 키 경로: `channels.bluebubbles`, `channels.bluebubbles.dmPolicy`. -- 선택적 `channels.bluebubbles.defaultAccount`는 구성된 계정 ID와 일치하는 경우 기본 계정 선택을 재정의합니다. -- `type: "acp"`를 가진 최상위 `bindings[]` 항목은 BlueBubbles 대화를 영구 ACP 세션에 바인딩할 수 있습니다. `match.peer.id`에는 BlueBubbles handle 또는 대상 문자열(`chat_id:*`, `chat_guid:*`, `chat_identifier:*`)을 사용하세요. 공유 필드 의미: [ACP Agents](/ko/tools/acp-agents#channel-specific-settings). +- 여기서 다루는 핵심 키 경로: `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). - 전체 BlueBubbles 채널 구성은 [BlueBubbles](/ko/channels/bluebubbles)에 문서화되어 있습니다. ### iMessage -OpenClaw는 `imsg rpc`(stdio를 통한 JSON-RPC)를 생성합니다. 데몬이나 포트는 필요하지 않습니다. +OpenClaw는 `imsg rpc`(stdio를 통한 JSON-RPC)를 실행합니다. 데몬이나 포트가 필요하지 않습니다. ```json5 { @@ -608,17 +618,17 @@ OpenClaw는 `imsg rpc`(stdio를 통한 JSON-RPC)를 생성합니다. 데몬이 } ``` -- 선택적 `channels.imessage.defaultAccount`는 구성된 계정 ID와 일치하는 경우 기본 계정 선택을 재정의합니다. +- 선택적 `channels.imessage.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. -- Messages DB에 대한 Full Disk Access가 필요합니다. -- `chat_id:` 대상을 선호하세요. 채팅을 나열하려면 `imsg chats --limit 20`을 사용하세요. -- `cliPath`는 SSH wrapper를 가리킬 수 있으며, SCP 첨부 파일 가져오기를 위해 `remoteHost`(`host` 또는 `user@host`)를 설정하세요. -- `attachmentRoots` 및 `remoteAttachmentRoots`는 수신 첨부 파일 경로를 제한합니다(기본값: `/Users/*/Library/Messages/Attachments`). -- SCP는 strict host-key checking을 사용하므로, 릴레이 호스트 키가 이미 `~/.ssh/known_hosts`에 존재하는지 확인하세요. -- `channels.imessage.configWrites`: iMessage에서 시작된 구성 쓰기를 허용하거나 거부합니다. -- `type: "acp"`를 가진 최상위 `bindings[]` 항목은 iMessage 대화를 영구 ACP 세션에 바인딩할 수 있습니다. `match.peer.id`에는 정규화된 handle 또는 명시적 채팅 대상(`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 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). - + ```bash #!/usr/bin/env bash @@ -660,15 +670,15 @@ 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"`(기본값). auto 모드에서는 `approvers` 또는 `commands.ownerAllowFrom`에서 승인자를 해결할 수 있을 때 exec 승인이 활성화됩니다. - `approvers`: exec 요청을 승인할 수 있는 Matrix 사용자 ID(예: `@owner:example.org`)입니다. - - `agentFilter`: 선택적 에이전트 ID 허용 목록입니다. 생략하면 모든 에이전트에 대한 승인을 전달합니다. - - `sessionFilter`: 선택적 세션 키 패턴(부분 문자열 또는 regex)입니다. + - `agentFilter`: 선택적 에이전트 ID 허용 목록. 생략하면 모든 에이전트의 승인 요청을 전달합니다. + - `sessionFilter`: 선택적 세션 키 패턴(부분 문자열 또는 regex). - `target`: 승인 프롬프트를 보낼 위치입니다. `"dm"`(기본값), `"channel"`(원래 룸), 또는 `"both"`. - 계정별 재정의: `channels.matrix.accounts..execApprovals`. - `channels.matrix.dm.sessionScope`는 Matrix DM이 세션으로 그룹화되는 방식을 제어합니다: `per-user`(기본값)는 라우팅된 peer 기준으로 공유하고, `per-room`은 각 DM 룸을 격리합니다. @@ -685,15 +695,15 @@ Microsoft Teams는 확장 기반이며 `channels.msteams` 아래에서 구성됩 msteams: { enabled: true, configWrites: true, - // appId, appPassword, tenantId, webhook, 팀/채널 정책: + // appId, appPassword, tenantId, webhook, team/channel 정책: // /channels/msteams 참고 }, }, } ``` -- 여기에서 다루는 핵심 키 경로: `channels.msteams`, `channels.msteams.configWrites`. -- 전체 Teams 구성(자격 증명, webhook, DM/그룹 정책, 팀별/채널별 재정의)은 [Microsoft Teams](/ko/channels/msteams)에 문서화되어 있습니다. +- 여기서 다루는 핵심 키 경로: `channels.msteams`, `channels.msteams.configWrites`. +- 전체 Teams config(자격 증명, webhook, DM/그룹 정책, 팀별/채널별 재정의)는 [Microsoft Teams](/ko/channels/msteams)에 문서화되어 있습니다. ### IRC @@ -718,8 +728,8 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. } ``` -- 여기에서 다루는 핵심 키 경로: `channels.irc`, `channels.irc.dmPolicy`, `channels.irc.configWrites`, `channels.irc.nickserv.*`. -- 선택적 `channels.irc.defaultAccount`는 구성된 계정 ID와 일치하는 경우 기본 계정 선택을 재정의합니다. +- 여기서 다루는 핵심 키 경로: `channels.irc`, `channels.irc.dmPolicy`, `channels.irc.configWrites`, `channels.irc.nickserv.*`. +- 선택적 `channels.irc.defaultAccount`는 구성된 계정 ID와 일치할 때 기본 계정 선택을 재정의합니다. - 전체 IRC 채널 구성(호스트/포트/TLS/채널/허용 목록/멘션 게이팅)은 [IRC](/ko/channels/irc)에 문서화되어 있습니다. ### 다중 계정(모든 채널) @@ -732,11 +742,11 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. telegram: { accounts: { default: { - name: "주 봇", + name: "Primary bot", botToken: "123456:ABC...", }, alerts: { - name: "알림 봇", + name: "Alerts bot", botToken: "987654:XYZ...", }, }, @@ -745,18 +755,18 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. } ``` -- `default`는 `accountId`가 생략되었을 때 사용됩니다(CLI + 라우팅). -- env 토큰은 **default** 계정에만 적용됩니다. -- 기본 채널 설정은 계정별로 재정의되지 않는 한 모든 계정에 적용됩니다. -- `bindings[].match.accountId`를 사용해 각 계정을 다른 에이전트로 라우팅하세요. -- 아직 단일 계정 최상위 채널 구성 상태에서 `openclaw channels add`(또는 채널 온보딩)를 통해 비기본 계정을 추가하면, OpenClaw는 먼저 계정 범위의 최상위 단일 계정 값을 채널 계정 맵으로 승격하여 원래 계정이 계속 작동하게 합니다. 대부분의 채널은 이를 `channels..accounts.default`로 옮기며, Matrix는 기존의 일치하는 명명/default 대상을 대신 유지할 수 있습니다. -- 기존 채널 전용 바인딩(`accountId` 없음)은 기본 계정과 계속 일치하며, 계정 범위 바인딩은 여전히 선택 사항입니다. -- `openclaw doctor --fix`도 계정 범위의 최상위 단일 계정 값을 해당 채널에 대해 선택된 승격 계정으로 옮겨 혼합 형태를 복구합니다. 대부분의 채널은 `accounts.default`를 사용하고, Matrix는 기존의 일치하는 명명/default 대상을 유지할 수 있습니다. +- `accountId`가 생략되면 `default`가 사용됩니다(CLI + 라우팅). +- 환경 변수 토큰은 **기본** 계정에만 적용됩니다. +- 기본 채널 설정은 계정별로 재정의하지 않는 한 모든 계정에 적용됩니다. +- 각 계정을 다른 에이전트로 라우팅하려면 `bindings[].match.accountId`를 사용하세요. +- `openclaw channels add`(또는 채널 온보딩)로 비기본 계정을 추가할 때 여전히 단일 계정 최상위 채널 config를 사용 중이라면, OpenClaw는 먼저 계정 범위 최상위 단일 계정 값을 채널 계정 맵으로 승격하여 원래 계정이 계속 동작하도록 합니다. 대부분의 채널은 이를 `channels..accounts.default`로 이동하며, Matrix는 기존의 일치하는 명명된/default 대상을 유지할 수 있습니다. +- 기존 채널 전용 바인딩(`accountId` 없음)은 계속 기본 계정과 일치하며, 계정 범위 바인딩은 여전히 선택 사항입니다. +- `openclaw doctor --fix`도 계정 범위 최상위 단일 계정 값을 해당 채널에 대해 선택된 승격 계정으로 이동하여 혼합 형태를 복구합니다. 대부분의 채널은 `accounts.default`를 사용하며, Matrix는 기존의 일치하는 명명된/default 대상을 유지할 수 있습니다. ### 기타 확장 채널 많은 확장 채널은 `channels.`로 구성되며 전용 채널 페이지에 문서화되어 있습니다(예: Feishu, Matrix, LINE, Nostr, Zalo, Nextcloud Talk, Synology Chat, Twitch). -전체 채널 인덱스는 [Channels](/ko/channels)를 참고하세요. +전체 채널 색인은 [Channels](/ko/channels)를 참고하세요. ### 그룹 채팅 멘션 게이팅 @@ -764,9 +774,9 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. **멘션 유형:** -- **메타데이터 멘션**: 네이티브 플랫폼 @-멘션. WhatsApp 셀프 채팅 모드에서는 무시됩니다. +- **메타데이터 멘션**: 네이티브 플랫폼 @-멘션. WhatsApp self-chat 모드에서는 무시됩니다. - **텍스트 패턴**: `agents.list[].groupChat.mentionPatterns`의 안전한 regex 패턴. 잘못된 패턴과 안전하지 않은 중첩 반복은 무시됩니다. -- 멘션 게이팅은 감지가 가능한 경우에만 적용됩니다(네이티브 멘션 또는 패턴이 최소 하나 이상). +- 멘션 게이팅은 감지가 가능한 경우에만 적용됩니다(네이티브 멘션 또는 최소 하나의 패턴이 있는 경우). ```json5 { @@ -781,7 +791,7 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. `messages.groupChat.historyLimit`는 전역 기본값을 설정합니다. 채널은 `channels..historyLimit`(또는 계정별)로 재정의할 수 있습니다. 비활성화하려면 `0`으로 설정하세요. -#### DM 기록 제한 +#### DM 이력 제한 ```json5 { @@ -796,13 +806,13 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. } ``` -해석 순서: DM별 재정의 → 공급자 기본값 → 제한 없음(모두 유지). +해결 순서: DM별 재정의 → provider 기본값 → 제한 없음(모두 유지). 지원 대상: `telegram`, `whatsapp`, `discord`, `slack`, `signal`, `imessage`, `msteams`. -#### 셀프 채팅 모드 +#### Self-chat 모드 -자기 번호를 `allowFrom`에 포함해 셀프 채팅 모드를 활성화합니다(네이티브 @-멘션은 무시하고, 텍스트 패턴에만 응답함): +자기 번호를 `allowFrom`에 포함하면 self-chat 모드를 활성화할 수 있습니다(네이티브 @-멘션은 무시하고 텍스트 패턴에만 응답): ```json5 { @@ -830,14 +840,14 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. commands: { native: "auto", // 지원될 때 네이티브 명령 등록 nativeSkills: "auto", // 지원될 때 네이티브 skill 명령 등록 - text: true, // 채팅 메시지에서 /commands 구문 분석 - bash: false, // ! 허용(별칭: /bash) + text: true, // 채팅 메시지에서 /commands 파싱 + bash: false, // ! 허용(alias: /bash) bashForegroundMs: 2000, config: false, // /config 허용 mcp: false, // /mcp 허용 plugins: false, // /plugins 허용 debug: false, // /debug 허용 - restart: true, // /restart + gateway 재시작 tool 허용 + restart: true, // /restart + gateway 재시작 도구 허용 ownerAllowFrom: ["discord:123456789012345678"], ownerDisplay: "raw", // raw | hash ownerDisplaySecret: "${OWNER_ID_HASH_SECRET}", @@ -852,28 +862,28 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. -- 이 블록은 명령 표면을 구성합니다. 현재 내장 + 번들 명령 카탈로그는 [Slash Commands](/ko/tools/slash-commands)를 참고하세요. -- 이 페이지는 전체 명령 카탈로그가 아니라 **구성 키 참조**입니다. 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에서는 끕니다. +- 이 블록은 명령 인터페이스를 구성합니다. 현재 내장 + 번들 명령 카탈로그는 [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은 끕니다. - 채널별 재정의: `channels.discord.commands.native`(bool 또는 `"auto"`). `false`는 이전에 등록된 명령을 지웁니다. -- 네이티브 skill 등록은 `channels..commands.nativeSkills`로 채널별 재정의할 수 있습니다. +- `channels..commands.nativeSkills`로 네이티브 skill 등록을 provider별로 재정의할 수 있습니다. - `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 서버 구성을 위한 `/mcp`를 활성화합니다. +- `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`는 채널별 구성 변경을 제어합니다(기본값: true). +- `channels..configWrites`는 채널별 config 변경을 제어합니다(기본값: true). - 다중 계정 채널의 경우 `channels..accounts..configWrites`도 해당 계정을 대상으로 하는 쓰기(예: `/allowlist --config --account ` 또는 `/config set channels..accounts....`)를 제어합니다. -- `restart: false`는 `/restart`와 gateway 재시작 tool 작업을 비활성화합니다. 기본값: `true`. -- `ownerAllowFrom`은 소유자 전용 명령/tool을 위한 명시적 소유자 허용 목록입니다. `allowFrom`과는 별개입니다. -- `ownerDisplay: "hash"`는 시스템 프롬프트에서 소유자 ID를 해시합니다. 해싱을 제어하려면 `ownerDisplaySecret`을 설정하세요. -- `allowFrom`은 공급자별입니다. 설정되면 이것이 **유일한** 권한 부여 소스가 됩니다(채널 허용 목록/페어링 및 `useAccessGroups`는 무시됨). -- `useAccessGroups: false`는 `allowFrom`이 설정되지 않았을 때 명령이 액세스 그룹 정책을 우회하도록 허용합니다. +- `restart: false`는 `/restart`와 gateway 재시작 도구 동작을 비활성화합니다. 기본값: `true`. +- `ownerAllowFrom`은 소유자 전용 명령/도구에 대한 명시적 소유자 허용 목록입니다. `allowFrom`과는 별개입니다. +- `ownerDisplay: "hash"`는 시스템 프롬프트에서 소유자 ID를 해시합니다. 해시를 제어하려면 `ownerDisplaySecret`를 설정하세요. +- `allowFrom`은 provider별입니다. 설정하면 이것이 **유일한** 권한 부여 소스가 됩니다(채널 허용 목록/페어링과 `useAccessGroups`는 무시됨). +- `useAccessGroups: false`는 `allowFrom`이 설정되지 않았을 때 명령이 액세스 그룹 정책을 우회할 수 있게 합니다. - 명령 문서 맵: - 내장 + 번들 카탈로그: [Slash Commands](/ko/tools/slash-commands) - - 채널별 명령 표면: [Channels](/ko/channels) + - 채널별 명령 인터페이스: [Channels](/ko/channels) - QQ Bot 명령: [QQ Bot](/ko/channels/qqbot) - 페어링 명령: [Pairing](/ko/channels/pairing) - LINE 카드 명령: [LINE](/ko/channels/line) @@ -897,7 +907,7 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. ### `agents.defaults.repoRoot` -시스템 프롬프트의 Runtime 줄에 표시되는 선택적 리포지토리 루트입니다. 설정되지 않으면 OpenClaw가 workspace에서 위쪽으로 이동하며 자동 감지합니다. +시스템 프롬프트의 Runtime 줄에 표시되는 선택적 리포지토리 루트입니다. 설정하지 않으면 OpenClaw가 workspace에서 위로 탐색하며 자동 감지합니다. ```json5 { @@ -922,9 +932,9 @@ IRC는 확장 기반이며 `channels.irc` 아래에서 구성됩니다. } ``` -- 기본적으로 제한 없는 skill을 원하면 `agents.defaults.skills`를 생략하세요. +- 기본적으로 제한 없는 Skills를 원하면 `agents.defaults.skills`를 생략하세요. - 기본값을 상속하려면 `agents.list[].skills`를 생략하세요. -- skill이 없게 하려면 `agents.list[].skills: []`를 설정하세요. +- skill이 없게 하려면 `agents.list[].skills: []`로 설정하세요. - 비어 있지 않은 `agents.list[].skills` 목록은 해당 에이전트의 최종 집합이며, 기본값과 병합되지 않습니다. ### `agents.defaults.skipBootstrap` @@ -939,9 +949,9 @@ workspace bootstrap 파일(`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `U ### `agents.defaults.contextInjection` -workspace bootstrap 파일이 시스템 프롬프트에 삽입되는 시점을 제어합니다. 기본값은 `"always"`입니다. +workspace bootstrap 파일이 시스템 프롬프트에 주입되는 시점을 제어합니다. 기본값: `"always"`. -- `"continuation-skip"`: 안전한 연속 턴(완료된 assistant 응답 이후)에서는 workspace bootstrap 재삽입을 건너뛰어 프롬프트 크기를 줄입니다. Heartbeat 실행과 compaction 이후 재시도는 여전히 컨텍스트를 다시 빌드합니다. +- `"continuation-skip"`: 완료된 assistant 응답 이후의 안전한 continuation 턴에서는 workspace bootstrap 재주입을 건너뛰어 프롬프트 크기를 줄입니다. 하트비트 실행과 compaction 후 재시도는 여전히 컨텍스트를 재구성합니다. ```json5 { @@ -951,7 +961,7 @@ workspace bootstrap 파일이 시스템 프롬프트에 삽입되는 시점을 ### `agents.defaults.bootstrapMaxChars` -잘리기 전 workspace bootstrap 파일당 최대 문자 수입니다. 기본값: `20000`. +잘리기 전 각 workspace bootstrap 파일의 최대 문자 수입니다. 기본값: `20000`. ```json5 { @@ -961,7 +971,7 @@ workspace bootstrap 파일이 시스템 프롬프트에 삽입되는 시점을 ### `agents.defaults.bootstrapTotalMaxChars` -모든 workspace bootstrap 파일에 걸쳐 삽입되는 총 최대 문자 수입니다. 기본값: `150000`. +모든 workspace bootstrap 파일에 걸쳐 주입되는 총 최대 문자 수입니다. 기본값: `150000`. ```json5 { @@ -971,12 +981,12 @@ workspace bootstrap 파일이 시스템 프롬프트에 삽입되는 시점을 ### `agents.defaults.bootstrapPromptTruncationWarning` -bootstrap 컨텍스트가 잘렸을 때 에이전트에게 보이는 경고 텍스트를 제어합니다. +bootstrap 컨텍스트가 잘릴 때 에이전트에게 보이는 경고 텍스트를 제어합니다. 기본값: `"once"`. -- `"off"`: 시스템 프롬프트에 경고 텍스트를 절대 삽입하지 않습니다. -- `"once"`: 고유한 잘림 시그니처당 한 번 경고를 삽입합니다(권장). -- `"always"`: 잘림이 존재하면 매 실행마다 경고를 삽입합니다. +- `"off"`: 시스템 프롬프트에 경고 텍스트를 절대 주입하지 않습니다. +- `"once"`: 고유한 truncation 시그니처마다 한 번만 경고를 주입합니다(권장). +- `"always"`: truncation이 존재하는 모든 실행마다 경고를 주입합니다. ```json5 { @@ -986,11 +996,11 @@ bootstrap 컨텍스트가 잘렸을 때 에이전트에게 보이는 경고 텍 ### `agents.defaults.imageMaxDimensionPx` -공급자 호출 전에 대화 기록/tool 이미지 블록에서 가장 긴 이미지 변의 최대 픽셀 크기입니다. +provider 호출 전에 트랜스크립트/도구 이미지 블록에서 가장 긴 이미지 변의 최대 픽셀 크기입니다. 기본값: `1200`. -값을 낮추면 일반적으로 스크린샷이 많은 실행에서 vision 토큰 사용량과 요청 페이로드 크기가 줄어듭니다. -값을 높이면 더 많은 시각적 디테일이 보존됩니다. +값을 낮추면 일반적으로 vision 토큰 사용량과 요청 페이로드 크기가 줄어들고, +값을 높이면 시각적 세부 정보가 더 잘 유지됩니다. ```json5 { @@ -1000,7 +1010,7 @@ bootstrap 컨텍스트가 잘렸을 때 에이전트에게 보이는 경고 텍 ### `agents.defaults.userTimezone` -시스템 프롬프트 컨텍스트용 시간대입니다(메시지 타임스탬프용 아님). 호스트 시간대를 대체값으로 사용합니다. +시스템 프롬프트 컨텍스트용 시간대입니다(메시지 타임스탬프용 아님). 호스트 시간대로 대체됩니다. ```json5 { @@ -1010,7 +1020,7 @@ bootstrap 컨텍스트가 잘렸을 때 에이전트에게 보이는 경고 텍 ### `agents.defaults.timeFormat` -시스템 프롬프트의 시간 형식입니다. 기본값: `auto`(OS 환경설정). +시스템 프롬프트의 시간 형식입니다. 기본값: `auto`(OS 기본 설정). ```json5 { @@ -1064,44 +1074,44 @@ bootstrap 컨텍스트가 잘렸을 때 에이전트에게 보이는 경고 텍 ``` - `model`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. - - 문자열 형식은 primary 모델만 설정합니다. - - 객체 형식은 primary와 순서가 있는 failover 모델을 설정합니다. + - 문자열 형식은 기본 모델만 설정합니다. + - 객체 형식은 기본 모델과 순서가 있는 failover 모델을 함께 설정합니다. - `imageModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. - - `image` tool 경로의 vision 모델 구성으로 사용됩니다. + - `image` 도구 경로에서 vision 모델 config로 사용됩니다. - 선택된/기본 모델이 이미지 입력을 받을 수 없을 때 대체 라우팅에도 사용됩니다. - `imageGenerationModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. - - 공유 이미지 생성 기능과 이미지를 생성하는 향후 tool/플러그인 표면에서 사용됩니다. - - 일반적인 값: 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 ID 순으로 나머지 등록된 이미지 생성 provider를 시도합니다. + - 공유 이미지 생성 기능과 향후 이미지 생성 도구/플러그인 인터페이스에서 사용됩니다. + - 일반적인 값: 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` tool에서 사용됩니다. + - 공유 음악 생성 기능과 내장 `music_generate` 도구에서 사용됩니다. - 일반적인 값: `google/lyria-3-clip-preview`, `google/lyria-3-pro-preview`, 또는 `minimax/music-2.5+`. - - 생략해도 `music_generate`는 인증이 설정된 provider 기본값을 추론할 수 있습니다. 먼저 현재 기본 provider를 시도하고, 그다음 provider ID 순으로 나머지 등록된 음악 생성 provider를 시도합니다. - - provider/model을 직접 선택하면 일치하는 provider 인증/API 키도 구성하세요. + - 생략된 경우에도 `music_generate`는 auth가 설정된 provider 기본값을 추론할 수 있습니다. 먼저 현재 기본 provider를 시도하고, 그다음 남은 등록된 음악 생성 provider를 provider-id 순서로 시도합니다. + - provider/model을 직접 선택하는 경우 일치하는 provider auth/API 키도 구성하세요. - `videoGenerationModel`: 문자열(`"provider/model"`) 또는 객체(`{ primary, fallbacks }`)를 받을 수 있습니다. - - 공유 비디오 생성 기능과 내장 `video_generate` tool에서 사용됩니다. + - 공유 비디오 생성 기능과 내장 `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`는 인증이 설정된 provider 기본값을 추론할 수 있습니다. 먼저 현재 기본 provider를 시도하고, 그다음 provider ID 순으로 나머지 등록된 비디오 생성 provider를 시도합니다. - - provider/model을 직접 선택하면 일치하는 provider 인증/API 키도 구성하세요. - - 번들 Qwen 비디오 생성 provider는 현재 최대 출력 비디오 1개, 입력 이미지 1개, 입력 비디오 4개, 10초 길이, 그리고 provider 수준 `size`, `aspectRatio`, `resolution`, `audio`, `watermark` 옵션을 지원합니다. + - 생략된 경우에도 `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 }`)를 받을 수 있습니다. - - `pdf` tool의 모델 라우팅에 사용됩니다. - - 생략하면 PDF tool은 `imageModel`, 그다음 해석된 세션/기본 모델로 대체됩니다. -- `pdfMaxBytesMb`: 호출 시점에 `maxBytesMb`가 전달되지 않았을 때 `pdf` tool의 기본 PDF 크기 제한입니다. -- `pdfMaxPages`: `pdf` tool의 추출 대체 모드에서 고려하는 기본 최대 페이지 수입니다. + - `pdf` 도구의 모델 라우팅에 사용됩니다. + - 생략되면 PDF 도구는 `imageModel`로, 그다음 해결된 세션/기본 모델로 대체됩니다. +- `pdfMaxBytesMb`: `pdf` 도구 호출 시 `maxBytesMb`가 전달되지 않았을 때 적용되는 기본 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으로 대체됩니다. -- `models`: `/model`용 구성된 모델 카탈로그 및 허용 목록입니다. 각 항목은 `alias`(단축키)와 `params`(예: `temperature`, `maxTokens`, `cacheRetention`, `context1m` 같은 provider별 값)를 포함할 수 있습니다. -- `params`: 모든 모델에 적용되는 전역 기본 provider 매개변수입니다. `agents.defaults.params`에서 설정합니다(예: `{ cacheRetention: "long" }`). -- `params` 병합 우선순위(구성): `agents.defaults.params`(전역 기본) 위에 `agents.defaults.models["provider/model"].params`(모델별), 그다음 `agents.list[].params`(일치하는 에이전트 ID)가 키별로 덮어씁니다. 자세한 내용은 [Prompt Caching](/ko/reference/prompt-caching)을 참고하세요. -- 이러한 필드를 변경하는 구성 작성기(예: `/models set`, `/models set-image`, fallback 추가/제거 명령)는 정규 객체 형식으로 저장하고 가능하면 기존 fallback 목록을 보존합니다. -- `maxConcurrent`: 세션 전반에서 병렬 에이전트 실행의 최대 수입니다(각 세션은 여전히 직렬화됨). 기본값: 4. +- `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. -**내장 별칭 단축키** (`agents.defaults.models`에 모델이 있을 때만 적용): +**내장 별칭 단축형** (`agents.defaults.models`에 모델이 있을 때만 적용): -| 별칭 | 모델 | +| Alias | 모델 | | ------------------- | -------------------------------------- | | `opus` | `anthropic/claude-opus-4-6` | | `sonnet` | `anthropic/claude-sonnet-4-6` | @@ -1112,15 +1122,15 @@ bootstrap 컨텍스트가 잘렸을 때 에이전트에게 보이는 경고 텍 | `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 호출 스트리밍을 위해 `tool_stream`을 활성화합니다. 비활성화하려면 `agents.defaults.models["zai/"].params.tool_stream`을 `false`로 설정하세요. -Anthropic Claude 4.6 모델은 명시적 thinking 수준이 설정되지 않았을 때 기본적으로 `adaptive` thinking을 사용합니다. +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을 사용합니다. ### `agents.defaults.cliBackends` -텍스트 전용 대체 실행(도구 호출 없음)을 위한 선택적 CLI 백엔드입니다. API provider가 실패할 때 백업으로 유용합니다. +텍스트 전용 대체 실행(도구 호출 없음)을 위한 선택적 CLI backend입니다. API provider가 실패할 때 백업으로 유용합니다. ```json5 { @@ -1148,29 +1158,44 @@ Anthropic Claude 4.6 모델은 명시적 thinking 수준이 설정되지 않았 } ``` -- CLI 백엔드는 텍스트 우선이며, 도구는 항상 비활성화됩니다. -- `sessionArg`가 설정되면 세션이 지원됩니다. -- `imageArg`가 파일 경로를 받을 수 있으면 이미지 전달이 지원됩니다. +- CLI backend는 텍스트 우선이며, 도구는 항상 비활성화됩니다. +- `sessionArg`가 설정된 경우 세션을 지원합니다. +- `imageArg`가 파일 경로를 받을 수 있으면 이미지 전달을 지원합니다. + +### `agents.defaults.systemPromptOverride` + +OpenClaw가 조합한 전체 시스템 프롬프트를 고정 문자열로 대체합니다. 기본 수준(`agents.defaults.systemPromptOverride`) 또는 에이전트별(`agents.list[].systemPromptOverride`)로 설정합니다. 에이전트별 값이 우선하며, 빈 문자열 또는 공백만 있는 값은 무시됩니다. 제어된 프롬프트 실험에 유용합니다. + +```json5 +{ + agents: { + defaults: { + systemPromptOverride: "You are a helpful assistant.", + }, + }, +} +``` ### `agents.defaults.heartbeat` -주기적 heartbeat 실행입니다. +주기적 하트비트 실행입니다. ```json5 { agents: { defaults: { heartbeat: { - every: "30m", // 0m은 비활성화 + every: "30m", // 0m disables model: "openai/gpt-5.4-mini", includeReasoning: false, - 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면 각 heartbeat를 새 세션에서 실행(대화 이력 없음) session: "main", to: "+15555550123", directPolicy: "allow", // allow (기본값) | block target: "none", // 기본값: none | 옵션: last | whatsapp | telegram | discord | ... - prompt: "HEARTBEAT.md가 있으면 읽으세요...", + prompt: "Read HEARTBEAT.md if it exists...", ackMaxChars: 300, suppressToolErrorWarnings: false, }, @@ -1180,12 +1205,13 @@ Anthropic Claude 4.6 모델은 명시적 thinking 수준이 설정되지 않았 ``` - `every`: 기간 문자열(ms/s/m/h). 기본값: `30m`(API 키 인증) 또는 `1h`(OAuth 인증). 비활성화하려면 `0m`으로 설정하세요. -- `suppressToolErrorWarnings`: true일 때 heartbeat 실행 중 tool 오류 경고 페이로드를 억제합니다. -- `directPolicy`: 직접/DM 전달 정책입니다. `allow`(기본값)는 직접 대상 전달을 허용합니다. `block`은 직접 대상 전달을 억제하고 `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는 전체 에이전트 턴을 실행하므로, 간격이 짧을수록 더 많은 토큰을 사용합니다. +- `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는 완전한 에이전트 턴을 실행하므로, 간격이 짧을수록 토큰을 더 많이 소모합니다. ### `agents.defaults.compaction` @@ -1195,19 +1221,19 @@ Anthropic Claude 4.6 모델은 명시적 thinking 수준이 설정되지 않았 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: "배포 ID, 티켓 ID, host:port 쌍을 정확히 보존하세요.", // identifierPolicy=custom일 때 사용 - postCompactionSections: ["Session Startup", "Red Lines"], // []는 재삽입 비활성화 + identifierInstructions: "Preserve deployment IDs, ticket IDs, and host:port pairs exactly.", // 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: "세션이 compaction에 가까워지고 있습니다. 오래 유지할 기억을 지금 저장하세요.", - prompt: "지속될 메모가 있으면 memory/YYYY-MM-DD.md에 작성하고, 저장할 것이 없으면 정확한 무음 토큰 NO_REPLY로 답하세요.", + 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.", }, }, }, @@ -1215,19 +1241,19 @@ Anthropic Claude 4.6 모델은 명시적 thinking 수준이 설정되지 않았 } ``` -- `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 요약 중 내장된 불투명 식별자 보존 지침을 앞에 추가합니다. +- `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 요약 중 내장 불투명 식별자 보존 안내를 앞에 붙입니다. - `identifierInstructions`: `identifierPolicy=custom`일 때 사용되는 선택적 사용자 지정 식별자 보존 텍스트입니다. -- `postCompactionSections`: compaction 후 재삽입할 선택적 AGENTS.md H2/H3 섹션 이름입니다. 기본값은 `["Session Startup", "Red Lines"]`이며, 비활성화하려면 `[]`로 설정하세요. 설정되지 않았거나 명시적으로 해당 기본 쌍으로 설정된 경우, 이전 `Every Session`/`Safety` 제목도 레거시 대체값으로 허용됩니다. -- `model`: compaction 요약 전용의 선택적 `provider/model-id` 재정의입니다. 메인 세션은 한 모델을 유지하되 compaction 요약은 다른 모델에서 실행하고 싶을 때 사용하세요. 설정하지 않으면 compaction은 세션의 primary 모델을 사용합니다. -- `notifyUser`: `true`일 때 compaction이 시작되면 사용자에게 짧은 알림(예: "컨텍스트를 압축하는 중...")을 보냅니다. 기본적으로는 compaction을 조용히 유지하기 위해 비활성화되어 있습니다. -- `memoryFlush`: 자동 compaction 전에 지속될 메모리를 저장하기 위한 무음 agentic 턴입니다. 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 전에 영속 메모리를 저장하기 위한 무음 에이전트 턴입니다. workspace가 읽기 전용이면 건너뜁니다. ### `agents.defaults.contextPruning` -LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 tool 결과**를 가지치기합니다. 디스크의 세션 기록은 **수정하지 않습니다**. +LLM에 보내기 전에 메모리 내 컨텍스트에서 **오래된 도구 결과**를 정리합니다. 디스크의 세션 이력은 **수정하지 않습니다**. ```json5 { @@ -1241,7 +1267,7 @@ LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 tool 결 hardClearRatio: 0.5, minPrunableToolChars: 50000, softTrim: { maxChars: 4000, headChars: 1500, tailChars: 1500 }, - hardClear: { enabled: true, placeholder: "[이전 tool 결과 내용이 지워졌습니다]" }, + hardClear: { enabled: true, placeholder: "[Old tool result content cleared]" }, tools: { deny: ["browser", "canvas"] }, }, }, @@ -1251,19 +1277,19 @@ LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 tool 결 -- `mode: "cache-ttl"`는 가지치기 패스를 활성화합니다. -- `ttl`은 마지막 캐시 터치 이후 다시 가지치기를 실행할 수 있는 빈도를 제어합니다. -- 가지치기는 먼저 과도하게 큰 tool 결과를 soft-trim하고, 필요하면 더 오래된 tool 결과를 hard-clear합니다. +- `mode: "cache-ttl"`은 pruning 패스를 활성화합니다. +- `ttl`은 마지막 캐시 접촉 이후 pruning이 다시 실행될 수 있는 주기를 제어합니다. +- Pruning은 먼저 과도하게 큰 tool 결과를 soft-trim하고, 필요 시 더 오래된 tool 결과를 hard-clear합니다. -**Soft-trim**은 시작과 끝을 유지하고 가운데에 `...`를 삽입합니다. +**Soft-trim**은 앞부분 + 뒷부분을 유지하고 중간에 `...`를 삽입합니다. -**Hard-clear**는 전체 tool 결과를 placeholder로 교체합니다. +**Hard-clear**는 전체 tool 결과를 placeholder로 대체합니다. 참고: - 이미지 블록은 절대 잘리거나 지워지지 않습니다. -- 비율은 토큰 수가 아니라 문자 수 기준의 근사값입니다. -- `keepLastAssistants`보다 적은 assistant 메시지만 존재하면 가지치기를 건너뜁니다. +- 비율은 토큰 수가 아닌 문자 수 기준(근사치)입니다. +- `keepLastAssistants`보다 적은 assistant 메시지만 있으면 pruning은 건너뜁니다. @@ -1285,13 +1311,13 @@ LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 tool 결 } ``` -- Telegram이 아닌 채널은 블록 답글을 활성화하려면 명시적인 `*.blockStreaming: true`가 필요합니다. -- 채널 재정의: `channels..blockStreamingCoalesce`(및 계정별 변형). Signal/Slack/Discord/Google Chat은 기본값으로 `minChars: 1500`을 사용합니다. -- `humanDelay`: 블록 답글 사이의 무작위 지연입니다. `natural` = 800–2500ms. 에이전트별 재정의: `agents.list[].humanDelay`. +- Telegram 이외 채널에서는 블록 응답을 활성화하려면 명시적인 `*.blockStreaming: true`가 필요합니다. +- 채널 재정의: `channels..blockStreamingCoalesce`(및 계정별 변형). Signal/Slack/Discord/Google Chat의 기본값은 `minChars: 1500`입니다. +- `humanDelay`: 블록 응답 사이의 무작위 지연입니다. `natural` = 800–2500ms. 에이전트별 재정의: `agents.list[].humanDelay`. -동작 및 청크 세부 사항은 [Streaming](/ko/concepts/streaming)을 참고하세요. +동작 및 청크 세부 정보는 [Streaming](/ko/concepts/streaming)을 참고하세요. -### 입력 중 표시기 +### 타이핑 인디케이터 ```json5 { @@ -1304,7 +1330,7 @@ LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 tool 결 } ``` -- 기본값: 직접 채팅/멘션에는 `instant`, 멘션 없는 그룹 채팅에는 `message`. +- 기본값: direct 채팅/멘션에는 `instant`, 멘션되지 않은 그룹 채팅에는 `message`. - 세션별 재정의: `session.typingMode`, `session.typingIntervalSeconds`. [Typing Indicators](/ko/concepts/typing-indicators)를 참고하세요. @@ -1313,7 +1339,7 @@ LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 tool 결 ### `agents.defaults.sandbox` -임베디드 에이전트용 선택적 sandboxing입니다. 전체 가이드는 [Sandboxing](/ko/gateway/sandboxing)을 참고하세요. +내장 에이전트를 위한 선택적 sandboxing입니다. 전체 가이드는 [Sandboxing](/ko/gateway/sandboxing)을 참고하세요. ```json5 { @@ -1410,51 +1436,52 @@ LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 tool 결 -**백엔드:** +**Backend:** - `docker`: 로컬 Docker 런타임(기본값) - `ssh`: 일반 SSH 기반 원격 런타임 - `openshell`: OpenShell 런타임 -`backend: "openshell"`을 선택하면 런타임별 설정은 `plugins.entries.openshell.config`로 이동합니다. +`backend: "openshell"`이 선택되면 런타임별 설정은 +`plugins.entries.openshell.config`로 이동합니다. -**SSH 백엔드 구성:** +**SSH backend config:** - `target`: `user@host[:port]` 형식의 SSH 대상 - `command`: SSH 클라이언트 명령(기본값: `ssh`) - `workspaceRoot`: 범위별 workspace에 사용되는 절대 원격 루트 - `identityFile` / `certificateFile` / `knownHostsFile`: OpenSSH에 전달되는 기존 로컬 파일 - `identityData` / `certificateData` / `knownHostsData`: OpenClaw가 런타임에 임시 파일로 구체화하는 인라인 내용 또는 SecretRef -- `strictHostKeyChecking` / `updateHostKeys`: OpenSSH host-key 정책 노브 +- `strictHostKeyChecking` / `updateHostKeys`: OpenSSH host-key 정책 설정 **SSH 인증 우선순위:** - `identityData`가 `identityFile`보다 우선합니다 - `certificateData`가 `certificateFile`보다 우선합니다 - `knownHostsData`가 `knownHostsFile`보다 우선합니다 -- SecretRef 기반 `*Data` 값은 sandbox 세션 시작 전에 활성 비밀 런타임 스냅샷에서 해석됩니다 +- SecretRef 기반 `*Data` 값은 sandbox 세션 시작 전에 활성 secrets 런타임 스냅샷에서 해결됩니다 -**SSH 백엔드 동작:** +**SSH backend 동작:** - 생성 또는 재생성 후 원격 workspace를 한 번 시드합니다 -- 그 후 원격 SSH workspace를 정규 상태로 유지합니다 -- `exec`, 파일 tool, media 경로를 SSH를 통해 라우팅합니다 +- 이후 원격 SSH workspace를 정식 상태로 유지합니다 +- `exec`, 파일 도구, 미디어 경로를 SSH로 라우팅합니다 - 원격 변경 내용을 호스트로 자동 동기화하지 않습니다 -- sandbox browser 컨테이너는 지원하지 않습니다 +- sandbox 브라우저 컨테이너는 지원하지 않습니다 -**Workspace 액세스:** +**Workspace access:** - `none`: `~/.openclaw/sandboxes` 아래 범위별 sandbox workspace -- `ro`: `/workspace`의 sandbox workspace, `/agent`에 읽기 전용으로 마운트된 agent workspace -- `rw`: agent workspace를 `/workspace`에 읽기/쓰기 가능하게 마운트 +- `ro`: sandbox workspace는 `/workspace`, 에이전트 workspace는 `/agent`에 읽기 전용 마운트 +- `rw`: 에이전트 workspace를 `/workspace`에 읽기/쓰기 마운트 -**범위:** +**Scope:** - `session`: 세션별 컨테이너 + workspace - `agent`: 에이전트별 하나의 컨테이너 + workspace(기본값) - `shared`: 공유 컨테이너와 workspace(세션 간 격리 없음) -**OpenShell 플러그인 구성:** +**OpenShell plugin config:** ```json5 { @@ -1469,7 +1496,7 @@ LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 tool 결 remoteAgentWorkspaceDir: "/agent", gateway: "lab", // 선택 사항 gatewayEndpoint: "https://lab.example", // 선택 사항 - policy: "strict", // 선택적 OpenShell 정책 id + policy: "strict", // 선택적 OpenShell policy id providers: ["openai"], // 선택 사항 autoProviders: true, timeoutSeconds: 120, @@ -1482,30 +1509,30 @@ LLM으로 보내기 전에 메모리 내 컨텍스트에서 **오래된 tool 결 **OpenShell 모드:** -- `mirror`: exec 전에 로컬에서 원격으로 시드하고, exec 후 다시 동기화; 로컬 workspace가 정규 상태를 유지 -- `remote`: sandbox 생성 시 한 번 원격으로 시드한 뒤, 원격 workspace를 정규 상태로 유지 +- `mirror`: exec 전에 로컬에서 원격으로 시드하고, exec 후 다시 동기화합니다. 로컬 workspace가 정식 상태로 유지됩니다 +- `remote`: sandbox 생성 시 원격을 한 번 시드한 뒤, 원격 workspace를 정식 상태로 유지합니다 -`remote` 모드에서는 OpenClaw 외부에서 호스트 로컬에 가해진 편집은 시드 단계 이후 sandbox로 자동 동기화되지 않습니다. -전송은 OpenShell sandbox로의 SSH이지만, 플러그인이 sandbox 생명주기와 선택적 미러 동기화를 소유합니다. +`remote` 모드에서는 OpenClaw 외부에서 이루어진 호스트 로컬 편집 내용이 시드 단계 이후 sandbox로 자동 동기화되지 않습니다. +전송은 SSH를 통해 OpenShell sandbox에 접속하지만, sandbox 수명 주기와 선택적 mirror sync는 plugin이 소유합니다. -**`setupCommand`**는 컨테이너 생성 후 한 번 실행됩니다(`sh -lc`를 통해). 네트워크 송신, 쓰기 가능한 루트, root 사용자가 필요합니다. +**`setupCommand`**는 컨테이너 생성 후 한 번 실행됩니다(`sh -lc` 사용). 네트워크 송신, 쓰기 가능한 루트, root 사용자가 필요합니다. -**컨테이너 기본값은 `network: "none"`**입니다 — 에이전트에 아웃바운드 액세스가 필요하면 `"bridge"`(또는 사용자 지정 bridge 네트워크)로 설정하세요. -`"host"`는 차단됩니다. `"container:"`는 기본적으로 차단되며, +**컨테이너 기본값은 `network: "none"`**입니다. 에이전트가 외부 액세스를 필요로 하면 `"bridge"`(또는 사용자 지정 bridge 네트워크)로 설정하세요. +`"host"`는 차단됩니다. `"container:"`는 `sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true`를 명시적으로 설정한 경우에만 허용됩니다(비상용). -**수신 첨부 파일**은 활성 workspace의 `media/inbound/*`에 스테이징됩니다. +**인바운드 첨부 파일**은 활성 workspace의 `media/inbound/*`에 임시 배치됩니다. -**`docker.binds`**는 추가 호스트 디렉터리를 마운트합니다. 전역 및 에이전트별 bind는 병합됩니다. +**`docker.binds`**는 추가 호스트 디렉터리를 마운트하며, 전역 및 에이전트별 binds가 병합됩니다. -**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된 세션이 호스트 browser를 대상으로 하는 것을 차단합니다. -- `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 네트워크)입니다. 명시적으로 전체 bridge 연결이 필요할 때만 `bridge`로 설정하세요. +- `cdpSourceRange`는 선택적으로 컨테이너 경계에서 CDP 유입을 CIDR 범위로 제한합니다(예: `172.21.0.1/32`). +- `sandbox.browser.binds`는 추가 호스트 디렉터리를 sandbox browser 컨테이너에만 마운트합니다. 설정되면(`[]` 포함) browser 컨테이너에서는 `docker.binds`를 대체합니다. +- 실행 기본값은 `scripts/sandbox-browser-entrypoint.sh`에 정의되어 있으며 컨테이너 호스트에 맞게 조정되어 있습니다: - `--remote-debugging-address=127.0.0.1` - `--remote-debugging-port=` - `--user-data-dir=${HOME}/.chrome` @@ -1522,21 +1549,27 @@ 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`으로 설정하세요. + - `--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`. - - 기본값은 컨테이너 이미지 기준선이며, 컨테이너 기본값을 변경하려면 사용자 지정 진입점이 있는 사용자 지정 browser 이미지를 사용하세요. + - 기본값은 컨테이너 이미지 기준선입니다. 컨테이너 기본값을 바꾸려면 + 사용자 지정 entrypoint가 포함된 사용자 지정 browser 이미지를 사용하세요. -browser sandboxing과 `sandbox.docker.binds`는 현재 Docker 전용입니다. +브라우저 sandboxing과 `sandbox.docker.binds`는 Docker 전용입니다. 이미지 빌드: ```bash -scripts/sandbox-setup.sh # 메인 sandbox 이미지 +scripts/sandbox-setup.sh # 기본 sandbox 이미지 scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 ``` @@ -1549,18 +1582,18 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 { id: "main", default: true, - name: "메인 에이전트", + name: "Main Agent", workspace: "~/.openclaw/workspace", agentDir: "~/.openclaw/agents/main/agent", model: "anthropic/claude-opus-4-6", // 또는 { primary, fallbacks } - thinkingDefault: "high", // 에이전트별 thinking 수준 재정의 - reasoningDefault: "on", // 에이전트별 reasoning 가시성 재정의 + thinkingDefault: "high", // 에이전트별 기본 thinking 수준 재정의 + reasoningDefault: "on", // 에이전트별 reasoning 표시 재정의 fastModeDefault: false, // 에이전트별 fast mode 재정의 params: { cacheRetention: "none" }, // 일치하는 defaults.models params를 키별로 재정의 - skills: ["docs-search"], // 설정되면 agents.defaults.skills를 대체 + skills: ["docs-search"], // 설정 시 agents.defaults.skills를 대체 identity: { name: "Samantha", - theme: "도움이 되는 나무늘보", + theme: "helpful sloth", emoji: "🦥", avatar: "avatars/samantha.png", }, @@ -1589,25 +1622,25 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 ``` - `id`: 안정적인 에이전트 ID(필수). -- `default`: 여러 개가 설정되면 첫 번째가 우선합니다(경고 기록). 아무것도 설정되지 않으면 첫 번째 목록 항목이 기본값입니다. -- `model`: 문자열 형식은 `primary`만 재정의하고, 객체 형식 `{ primary, fallbacks }`는 둘 다 재정의합니다(`[]`는 전역 fallback 비활성화). `primary`만 재정의하는 cron 작업은 `fallbacks: []`를 설정하지 않는 한 기본 fallback을 계속 상속합니다. -- `params`: `agents.defaults.models`에서 선택된 모델 항목 위에 병합되는 에이전트별 스트림 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 하네스 세션을 사용해야 할 때 `type: "acp"`와 `runtime.acp` 기본값(`agent`, `backend`, `mode`, `cwd`)을 사용하세요. +- `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`)을 사용하세요. - `identity.avatar`: workspace 상대 경로, `http(s)` URL 또는 `data:` URI입니다. -- `identity`는 기본값을 파생합니다: `emoji`에서 `ackReaction`, `name`/`emoji`에서 `mentionPatterns`. -- `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 안에서 여러 개의 격리된 에이전트를 실행합니다. [Multi-Agent](/ko/concepts/multi-agent)를 참고하세요. ```json5 { @@ -1626,25 +1659,25 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 ### 바인딩 match 필드 -- `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 }` +- `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 순서:** 1. `match.peer` 2. `match.guildId` 3. `match.teamId` -4. `match.accountId` (정확 일치, peer/guild/team 없음) -5. `match.accountId: "*"` (채널 전체) +4. `match.accountId`(정확 일치, peer/guild/team 없음) +5. `match.accountId: "*"`(채널 전체) 6. 기본 에이전트 -각 계층 내에서는 첫 번째로 일치하는 `bindings` 항목이 우선합니다. +같은 tier 안에서는 먼저 일치하는 `bindings` 항목이 우선합니다. -`type: "acp"` 항목의 경우 OpenClaw는 정확한 대화 식별자(`match.channel` + account + `match.peer.id`)로 해석하며, 위의 route 바인딩 계층 순서를 사용하지 않습니다. +`type: "acp"` 항목의 경우 OpenClaw는 정확한 대화 식별자(`match.channel` + account + `match.peer.id`)로 해결하며, 위의 route 바인딩 tier 순서는 사용하지 않습니다. ### 에이전트별 액세스 프로필 @@ -1666,7 +1699,7 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 - + ```json5 { @@ -1775,12 +1808,12 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 rotateBytes: "10mb", resetArchiveRetention: "30d", // 기간 또는 false maxDiskBytes: "500mb", // 선택적 하드 예산 - highWaterBytes: "400mb", // 선택적 정리 목표치 + highWaterBytes: "400mb", // 선택적 정리 목표 }, threadBindings: { enabled: true, - idleHours: 24, // 기본 비활성 자동 unfocus 시간 (`0`은 비활성화) - maxAgeHours: 0, // 기본 하드 최대 사용 기간 시간 (`0`은 비활성화) + idleHours: 24, // 기본 비활성 자동 unfocus 시간(`0`은 비활성화) + maxAgeHours: 0, // 기본 하드 최대 사용 기간(`0`은 비활성화) }, mainKey: "main", // 레거시(런타임은 항상 "main" 사용) agentToAgent: { maxPingPongTurns: 5 }, @@ -1794,35 +1827,35 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 -- **`scope`**: 그룹 채팅 컨텍스트의 기본 세션 그룹화 전략입니다. - - `per-sender`(기본값): 채널 컨텍스트 내에서 각 발신자가 격리된 세션을 가집니다. - - `global`: 채널 컨텍스트의 모든 참가자가 하나의 세션을 공유합니다(공유 컨텍스트가 의도된 경우에만 사용). -- **`dmScope`**: DM이 그룹화되는 방식입니다. +- **`scope`**: 그룹 채팅 컨텍스트용 기본 세션 그룹화 전략입니다. + - `per-sender`(기본값): 채널 컨텍스트 안에서 각 발신자가 격리된 세션을 가집니다. + - `global`: 채널 컨텍스트의 모든 참여자가 하나의 세션을 공유합니다(공유 컨텍스트가 의도된 경우에만 사용). +- **`dmScope`**: DM을 그룹화하는 방식입니다. - `main`: 모든 DM이 메인 세션을 공유합니다. - - `per-peer`: 채널 간 발신자 ID별로 격리합니다. + - `per-peer`: 채널 전반에서 발신자 ID별로 격리합니다. - `per-channel-peer`: 채널 + 발신자별로 격리합니다(다중 사용자 inbox에 권장). - `per-account-channel-peer`: 계정 + 채널 + 발신자별로 격리합니다(다중 계정에 권장). -- **`identityLinks`**: 채널 간 세션 공유를 위한 정규 ID를 provider 접두사가 있는 peer에 매핑합니다. -- **`reset`**: 기본 리셋 정책입니다. `daily`는 로컬 시간 `atHour`에 리셋되고, `idle`은 `idleMinutes` 후 리셋됩니다. 둘 다 구성된 경우 먼저 만료되는 쪽이 우선합니다. -- **`resetByType`**: 타입별 재정의(`direct`, `group`, `thread`)입니다. 레거시 `dm`도 `direct`의 별칭으로 허용됩니다. +- **`identityLinks`**: 채널 간 세션 공유를 위한 provider 접두어 peer에 정식 ID를 매핑합니다. +- **`reset`**: 기본 reset 정책입니다. `daily`는 로컬 시간 기준 `atHour`에 reset하며, `idle`은 `idleMinutes` 이후 reset합니다. 둘 다 구성된 경우 먼저 만료되는 쪽이 우선합니다. +- **`resetByType`**: 타입별 재정의(`direct`, `group`, `thread`). 기존 `dm`도 `direct` 별칭으로 허용됩니다. - **`parentForkMaxTokens`**: 포크된 스레드 세션 생성 시 허용되는 부모 세션 `totalTokens` 최대값입니다(기본값 `100000`). - - 부모 `totalTokens`가 이 값을 초과하면 OpenClaw는 부모 대화 기록을 상속하지 않고 새 스레드 세션을 시작합니다. + - 부모 `totalTokens`가 이 값을 초과하면 OpenClaw는 부모 트랜스크립트 이력을 상속하지 않고 새로운 스레드 세션을 시작합니다. - 이 가드를 비활성화하고 항상 부모 포크를 허용하려면 `0`으로 설정하세요. -- **`mainKey`**: 레거시 필드입니다. 런타임은 이제 메인 직접 채팅 버킷에 항상 `"main"`을 사용합니다. -- **`agentToAgent.maxPingPongTurns`**: 에이전트 간 교환 중 에이전트 사이에서 허용되는 최대 응답 왕복 횟수입니다(정수, 범위: `0`–`5`). `0`은 ping-pong 체이닝을 비활성화합니다. -- **`sendPolicy`**: `channel`, `chatType`(`direct|group|channel`, 레거시 `dm` 별칭 포함), `keyPrefix`, `rawKeyPrefix`로 일치시킵니다. 첫 번째 deny가 우선합니다. -- **`maintenance`**: 세션 저장소 정리 + 보존 제어입니다. +- **`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 정리 + 보존 제어입니다. - `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.` 트랜스크립트 아카이브의 보존 기간입니다. 기본값은 `pruneAfter`이며, 비활성화하려면 `false`로 설정하세요. - `maxDiskBytes`: 선택적 세션 디렉터리 디스크 예산입니다. `warn` 모드에서는 경고를 기록하고, `enforce` 모드에서는 가장 오래된 아티팩트/세션부터 제거합니다. - - `highWaterBytes`: 예산 정리 후의 선택적 목표치입니다. 기본값은 `maxDiskBytes`의 `80%`입니다. -- **`threadBindings`**: 스레드 바운드 세션 기능의 전역 기본값입니다. + - `highWaterBytes`: 예산 정리 후 목표값(선택 사항)입니다. 기본값은 `maxDiskBytes`의 `80%`입니다. +- **`threadBindings`**: 스레드 바인딩 세션 기능의 전역 기본값입니다. - `enabled`: 마스터 기본 스위치(provider가 재정의 가능; Discord는 `channels.discord.threadBindings.enabled` 사용) - - `idleHours`: 기본 비활성 자동 unfocus 시간(`0`은 비활성화; provider가 재정의 가능) - - `maxAgeHours`: 기본 하드 최대 사용 기간 시간(`0`은 비활성화; provider가 재정의 가능) + - `idleHours`: 비활성 자동 unfocus의 기본 시간(`0`은 비활성화, provider 재정의 가능) + - `maxAgeHours`: 하드 최대 사용 기간의 기본 시간(`0`은 비활성화, provider 재정의 가능) @@ -1848,7 +1881,7 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 }, }, inbound: { - debounceMs: 2000, // 0은 비활성화 + debounceMs: 2000, // 0 disables byChannel: { whatsapp: 5000, slack: 1500, @@ -1862,34 +1895,34 @@ scripts/sandbox-browser-setup.sh # 선택적 browser 이미지 채널/계정별 재정의: `channels..responsePrefix`, `channels..accounts..responsePrefix`. -해석 순서(가장 구체적인 것이 우선): 계정 → 채널 → 전역. `""`는 비활성화하며 상위 단계 전파도 중단합니다. `"auto"`는 `[{identity.name}]`을 파생합니다. +해결 순서(가장 구체적인 값이 우선): 계정 → 채널 → 전역. `""`는 비활성화하며 연쇄 적용도 중단합니다. `"auto"`는 `[{identity.name}]`를 파생합니다. **템플릿 변수:** -| 변수 | 설명 | 예시 | -| ----------------- | ---------------------- | --------------------------- | -| `{model}` | 짧은 모델 이름 | `claude-opus-4-6` | -| `{modelFull}` | 전체 모델 식별자 | `anthropic/claude-opus-4-6` | -| `{provider}` | provider 이름 | `anthropic` | -| `{thinkingLevel}` | 현재 thinking 수준 | `high`, `low`, `off` | -| `{identity.name}` | 에이전트 identity 이름 | ( `"auto"`와 동일 ) | +| 변수 | 설명 | 예시 | +| ----------------- | --------------------- | --------------------------- | +| `{model}` | 짧은 모델 이름 | `claude-opus-4-6` | +| `{modelFull}` | 전체 모델 식별자 | `anthropic/claude-opus-4-6` | +| `{provider}` | provider 이름 | `anthropic` | +| `{thinkingLevel}` | 현재 thinking 수준 | `high`, `low`, `off` | +| `{identity.name}` | 에이전트 identity 이름 | ( `"auto"`와 동일) | 변수는 대소문자를 구분하지 않습니다. `{think}`는 `{thinkingLevel}`의 별칭입니다. -### Ack 반응 +### Ack 리액션 -- 기본값은 활성 에이전트의 `identity.emoji`, 없으면 `"👀"`입니다. 비활성화하려면 `""`를 설정하세요. +- 기본값은 활성 에이전트의 `identity.emoji`, 없으면 `"👀"`입니다. 비활성화하려면 `""`로 설정하세요. - 채널별 재정의: `channels..ackReaction`, `channels..accounts..ackReaction`. -- 해석 순서: 계정 → 채널 → `messages.ackReaction` → identity 대체값. +- 해결 순서: 계정 → 채널 → `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에서 응답 후 ack를 제거합니다. +- `messages.statusReactions.enabled`: Slack, Discord, Telegram에서 수명 주기 상태 리액션을 활성화합니다. + Slack과 Discord에서는 미설정 시 ack 리액션이 활성화되어 있으면 상태 리액션도 활성화된 상태를 유지합니다. + Telegram에서는 수명 주기 상태 리액션을 활성화하려면 이를 명시적으로 `true`로 설정해야 합니다. -### 수신 debounce +### 인바운드 디바운스 -같은 발신자의 빠른 연속 텍스트 전용 메시지를 하나의 에이전트 턴으로 묶습니다. 미디어/첨부 파일은 즉시 flush됩니다. 제어 명령은 debounce를 우회합니다. +같은 발신자의 빠른 텍스트 전용 메시지를 하나의 에이전트 턴으로 묶습니다. 미디어/첨부 파일은 즉시 flush됩니다. 제어 명령은 디바운스를 우회합니다. ### TTS (text-to-speech) @@ -1932,12 +1965,12 @@ 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)입니다. -- API 키의 대체값은 `ELEVENLABS_API_KEY`/`XI_API_KEY`, `OPENAI_API_KEY`입니다. -- `openai.baseUrl`은 OpenAI TTS 엔드포인트를 재정의합니다. 해석 순서는 구성, 그다음 `OPENAI_TTS_BASE_URL`, 그다음 `https://api.openai.com/v1`입니다. -- `openai.baseUrl`이 OpenAI가 아닌 엔드포인트를 가리키면, OpenClaw는 이를 OpenAI 호환 TTS 서버로 간주하고 모델/음성 검증을 완화합니다. +- `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 검증을 완화합니다. --- @@ -1967,51 +2000,51 @@ 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`입니다. +- `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 객체를 받을 수 있습니다. -- `ELEVENLABS_API_KEY` 대체값은 Talk API 키가 구성되지 않았을 때만 적용됩니다. -- `providers.*.voiceAliases`를 사용하면 Talk 지시문에서 친숙한 이름을 사용할 수 있습니다. -- `silenceTimeoutMs`는 Talk 모드가 사용자 침묵 후 대본을 전송하기 전에 얼마나 기다릴지 제어합니다. 설정하지 않으면 플랫폼 기본 일시정지 창을 유지합니다(`macOS 및 Android에서는 700 ms, iOS에서는 900 ms`). +- `ELEVENLABS_API_KEY` 대체값은 Talk API 키가 구성되지 않은 경우에만 적용됩니다. +- `providers.*.voiceAliases`는 Talk 지시문에서 친숙한 이름을 사용할 수 있게 합니다. +- `silenceTimeoutMs`는 사용자가 말하지 않은 후 Talk 모드가 트랜스크립트를 전송하기까지 기다리는 시간을 제어합니다. 미설정 시 플랫폼 기본 일시정지 창을 유지합니다(`macOS 및 Android는 700 ms, iOS는 900 ms`). --- ## 도구 -### Tool 프로필 +### 도구 프로필 -`tools.profile`은 `tools.allow`/`tools.deny` 이전에 기본 허용 목록을 설정합니다: +`tools.profile`은 `tools.allow`/`tools.deny` 이전에 적용되는 기본 허용 목록을 설정합니다. -로컬 온보딩은 설정되지 않은 새 로컬 구성에 기본적으로 `tools.profile: "coding"`을 적용합니다(기존의 명시적 프로필은 보존됨). +로컬 온보딩은 설정되지 않은 새 로컬 config에 기본적으로 `tools.profile: "coding"`을 적용합니다(기존 명시적 프로필은 유지). -| 프로필 | 포함 항목 | -| ----------- | --------------------------------------------------------------------------------------------------------------------------- | -| `minimal` | `session_status`만 | +| 프로필 | 포함 항목 | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------- | +| `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` | 제한 없음(설정 안 함과 동일) | +| `messaging` | `group:messaging`, `sessions_list`, `sessions_history`, `sessions_send`, `session_status` | +| `full` | 제한 없음(미설정과 동일) | -### Tool 그룹 +### 도구 그룹 -| 그룹 | 도구 | -| ------------------ | ------------------------------------------------------------------------------------------------------------------------ | -| `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` | 모든 내장 tool(provider plugin 제외) | +| `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 플러그인 제외) | ### `tools.allow` / `tools.deny` -전역 tool 허용/거부 정책입니다(deny 우선). 대소문자를 구분하지 않으며 `*` 와일드카드를 지원합니다. Docker sandbox가 꺼져 있어도 적용됩니다. +전역 도구 허용/거부 정책입니다(deny가 우선). 대소문자를 구분하지 않으며 `*` 와일드카드를 지원합니다. Docker sandbox가 꺼져 있어도 적용됩니다. ```json5 { @@ -2021,7 +2054,7 @@ Talk 모드(macOS/iOS/Android)의 기본값입니다. ### `tools.byProvider` -특정 provider 또는 모델에 대해 tool을 추가로 제한합니다. 순서: 기본 프로필 → provider 프로필 → allow/deny. +특정 provider 또는 모델에 대해 도구를 추가로 제한합니다. 순서: 기본 프로필 → provider 프로필 → allow/deny. ```json5 { @@ -2037,7 +2070,7 @@ Talk 모드(macOS/iOS/Android)의 기본값입니다. ### `tools.elevated` -sandbox 외부의 elevated exec 액세스를 제어합니다: +sandbox 밖의 elevated exec 액세스를 제어합니다: ```json5 { @@ -2053,9 +2086,9 @@ sandbox 외부의 elevated exec 액세스를 제어합니다: } ``` -- 에이전트별 재정의(`agents.list[].tools.elevated`)는 추가 제한만 할 수 있습니다. -- `/elevated on|off|ask|full`은 상태를 세션별로 저장하고, 인라인 지시문은 단일 메시지에 적용됩니다. -- Elevated `exec`는 sandboxing을 우회하며 구성된 이스케이프 경로(`gateway`가 기본값, exec 대상이 `node`일 때는 `node`)를 사용합니다. +- 에이전트별 재정의(`agents.list[].tools.elevated`)는 더 제한적으로만 설정할 수 있습니다. +- `/elevated on|off|ask|full`은 세션별 상태를 저장하며, 인라인 지시문은 단일 메시지에만 적용됩니다. +- Elevated `exec`는 sandboxing을 우회하고 구성된 escape path를 사용합니다(기본값은 `gateway`, exec 대상이 `node`인 경우 `node`). ### `tools.exec` @@ -2079,8 +2112,8 @@ sandbox 외부의 elevated exec 액세스를 제어합니다: ### `tools.loopDetection` -Tool 루프 안전 검사는 기본적으로 **비활성화**되어 있습니다. 감지를 활성화하려면 `enabled: true`를 설정하세요. -설정은 전역 `tools.loopDetection`에 정의할 수 있으며 에이전트별로 `agents.list[].tools.loopDetection`에서 재정의할 수 있습니다. +도구 루프 안전 검사는 기본적으로 **비활성화**되어 있습니다. 감지를 활성화하려면 `enabled: true`로 설정하세요. +설정은 전역 `tools.loopDetection`에 정의할 수 있고 에이전트별 `agents.list[].tools.loopDetection`에서 재정의할 수 있습니다. ```json5 { @@ -2101,13 +2134,13 @@ Tool 루프 안전 검사는 기본적으로 **비활성화**되어 있습니다 } ``` -- `historySize`: 루프 분석을 위해 유지되는 최대 tool 호출 기록 수입니다. -- `warningThreshold`: 경고를 위한 반복적 무진전 패턴 임계값입니다. -- `criticalThreshold`: 심각한 루프를 차단하기 위한 더 높은 반복 임계값입니다. -- `globalCircuitBreakerThreshold`: 모든 무진전 실행에 대한 하드 중단 임계값입니다. -- `detectors.genericRepeat`: 같은 tool/같은 인자 호출 반복 시 경고합니다. -- `detectors.knownPollNoProgress`: 알려진 poll tool(`process.poll`, `command_status` 등)에 대한 무진전 시 경고/차단합니다. -- `detectors.pingPong`: 교대하는 무진전 쌍 패턴에 대해 경고/차단합니다. +- `historySize`: 루프 분석을 위해 유지할 최대 도구 호출 이력입니다. +- `warningThreshold`: 경고를 위한 반복 무진전 패턴 임계값입니다. +- `criticalThreshold`: 치명적 루프 차단을 위한 더 높은 반복 임계값입니다. +- `globalCircuitBreakerThreshold`: 어떤 무진전 실행에도 적용되는 하드 중단 임계값입니다. +- `detectors.genericRepeat`: 동일 도구/동일 인자 호출 반복 시 경고합니다. +- `detectors.knownPollNoProgress`: 알려진 poll 도구(`process.poll`, `command_status` 등)의 무진전 상태를 경고/차단합니다. +- `detectors.pingPong`: 번갈아 나타나는 무진전 쌍 패턴을 경고/차단합니다. - `warningThreshold >= criticalThreshold` 또는 `criticalThreshold >= globalCircuitBreakerThreshold`이면 검증이 실패합니다. ### `tools.web` @@ -2142,7 +2175,7 @@ Tool 루프 안전 검사는 기본적으로 **비활성화**되어 있습니다 ### `tools.media` -수신 미디어 이해(image/audio/video)를 구성합니다: +인바운드 미디어 이해(image/audio/video)를 구성합니다: ```json5 { @@ -2150,7 +2183,7 @@ Tool 루프 안전 검사는 기본적으로 **비활성화**되어 있습니다 media: { concurrency: 2, asyncCompletion: { - directSend: false, // opt-in: 완료된 비동기 music/video를 채널로 직접 전송 + directSend: false, // opt-in: 완료된 async music/video를 채널로 직접 전송 }, audio: { enabled: true, @@ -2179,7 +2212,7 @@ Tool 루프 안전 검사는 기본적으로 **비활성화**되어 있습니다 **Provider 항목** (`type: "provider"` 또는 생략): - `provider`: API provider id (`openai`, `anthropic`, `google`/`gemini`, `groq` 등) -- `model`: 모델 id 재정의 +- `model`: 모델 ID 재정의 - `profile` / `preferredProfile`: `auth-profiles.json` 프로필 선택 **CLI 항목** (`type: "cli"`): @@ -2191,13 +2224,15 @@ Tool 루프 안전 검사는 기본적으로 **비활성화**되어 있습니다 - `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`. **비동기 완료 필드:** -- `asyncCompletion.directSend`: `true`이면 완료된 비동기 `music_generate` 및 `video_generate` 작업이 먼저 직접 채널 전달을 시도합니다. 기본값은 `false`(레거시 requester-session wake/model-delivery 경로)입니다. +- `asyncCompletion.directSend`: `true`일 때 완료된 async `music_generate` + 및 `video_generate` 작업은 먼저 direct 채널 전달을 시도합니다. 기본값: `false` + (기존 requester-session wake/model-delivery 경로). @@ -2216,9 +2251,9 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v ### `tools.sessions` -세션 tool(`sessions_list`, `sessions_history`, `sessions_send`)이 어떤 세션을 대상으로 할 수 있는지 제어합니다. +세션 도구(`sessions_list`, `sessions_history`, `sessions_send`)가 대상으로 삼을 수 있는 세션을 제어합니다. -기본값: `tree` (현재 세션 + 그것이 생성한 세션, 예: subagent). +기본값: `tree`(현재 세션 + 현재 세션이 생성한 세션, 예: subagent). ```json5 { @@ -2235,9 +2270,9 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v - `self`: 현재 세션 키만. - `tree`: 현재 세션 + 현재 세션이 생성한 세션(subagent). -- `agent`: 현재 에이전트 ID에 속한 모든 세션(같은 에이전트 ID 아래에서 발신자별 세션을 실행하는 경우 다른 사용자도 포함될 수 있음). -- `all`: 모든 세션. 에이전트 간 대상 지정은 여전히 `tools.agentToAgent`가 필요합니다. -- Sandbox clamp: 현재 세션이 sandbox 상태이고 `agents.defaults.sandbox.sessionToolsVisibility="spawned"`이면 `tools.sessions.visibility="all"`이어도 visibility는 `tree`로 강제됩니다. +- `agent`: 현재 agent id에 속한 모든 세션(같은 agent id 아래 per-sender 세션을 실행 중이면 다른 사용자 포함 가능). +- `all`: 모든 세션. 교차 에이전트 대상 지정에는 여전히 `tools.agentToAgent`가 필요합니다. +- Sandbox clamp: 현재 세션이 sandbox 상태이고 `agents.defaults.sandbox.sessionToolsVisibility="spawned"`이면 `tools.sessions.visibility="all"`이더라도 visibility는 강제로 `tree`가 됩니다. ### `tools.sessions_spawn` @@ -2248,11 +2283,11 @@ 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 - retainOnSessionKeep: false, // cleanup="keep"일 때 첨부 보존 + retainOnSessionKeep: false, // cleanup="keep"일 때 첨부 유지 }, }, }, @@ -2262,15 +2297,15 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v 참고: - 첨부 파일은 `runtime: "subagent"`에서만 지원됩니다. ACP 런타임은 이를 거부합니다. -- 파일은 자식 workspace의 `.openclaw/attachments//`에 `.manifest.json`과 함께 구체화됩니다. -- 첨부 파일 내용은 대화 기록 저장에서 자동으로 redaction됩니다. +- 파일은 `.manifest.json`과 함께 child workspace의 `.openclaw/attachments//`에 구체화됩니다. +- 첨부 내용은 트랜스크립트 영속성에서 자동으로 redaction됩니다. - Base64 입력은 엄격한 알파벳/패딩 검사와 디코드 전 크기 가드로 검증됩니다. -- 파일 권한은 디렉터리에 `0700`, 파일에 `0600`입니다. +- 파일 권한은 디렉터리 `0700`, 파일 `0600`입니다. - 정리는 `cleanup` 정책을 따릅니다: `delete`는 항상 첨부 파일을 제거하고, `keep`은 `retainOnSessionKeep: true`일 때만 유지합니다. ### `tools.experimental` -실험적 내장 tool 플래그입니다. 런타임별 자동 활성화 규칙이 적용되는 경우를 제외하면 기본적으로 꺼져 있습니다. +실험적 내장 도구 플래그입니다. 런타임별 자동 활성화 규칙이 적용되지 않는 한 기본값은 꺼짐입니다. ```json5 { @@ -2284,9 +2319,9 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v 참고: -- `planTool`: 중요하고 여러 단계가 있는 작업 추적용 구조화된 `update_plan` tool을 활성화합니다. -- 기본값: OpenAI가 아닌 provider에서는 `false`. OpenAI와 OpenAI Codex 실행은 설정되지 않은 경우 자동으로 활성화합니다. 이 자동 활성화를 끄려면 `false`로 설정하세요. -- 활성화되면 시스템 프롬프트에도 사용 지침이 추가되어 모델이 실질적인 작업에만 사용하고 동시에 최대 하나의 단계만 `in_progress`로 유지하게 됩니다. +- `planTool`: 중요하고 여러 단계인 작업 추적을 위한 구조화된 `update_plan` 도구를 활성화합니다. +- 기본값: OpenAI가 아닌 provider에서는 `false`. OpenAI 및 OpenAI Codex 실행에서는 미설정 시 자동 활성화되며, 이 자동 활성화를 끄려면 `false`로 설정하세요. +- 활성화되면 시스템 프롬프트에도 사용 지침이 추가되어 모델이 실질적인 작업에만 이를 사용하고 `in_progress` 단계는 최대 하나만 유지하도록 합니다. ### `agents.defaults.subagents` @@ -2307,15 +2342,15 @@ Provider 인증은 표준 순서를 따릅니다: `auth-profiles.json` → env v ``` - `model`: 생성된 sub-agent의 기본 모델입니다. 생략하면 sub-agent는 호출자의 모델을 상속합니다. -- `allowAgents`: 요청 에이전트가 자체 `subagents.allowAgents`를 설정하지 않았을 때 `sessions_spawn`용 기본 대상 에이전트 ID 허용 목록입니다(`["*"]` = 아무거나, 기본값: 동일 에이전트만). -- `runTimeoutSeconds`: tool 호출에서 `runTimeoutSeconds`를 생략했을 때 `sessions_spawn`의 기본 타임아웃(초)입니다. `0`은 타임아웃 없음입니다. -- subagent별 tool 정책: `tools.subagents.tools.allow` / `tools.subagents.tools.deny`. +- `allowAgents`: 요청자 에이전트가 자체 `subagents.allowAgents`를 설정하지 않은 경우 `sessions_spawn` 대상 agent id의 기본 허용 목록입니다(`["*"]` = 모두 허용, 기본값: 동일 에이전트만). +- `runTimeoutSeconds`: 도구 호출에서 `runTimeoutSeconds`를 생략한 경우 `sessions_spawn`의 기본 timeout(초)입니다. `0`은 timeout 없음입니다. +- subagent별 도구 정책: `tools.subagents.tools.allow` / `tools.subagents.tools.deny`. --- ## 사용자 지정 provider 및 base URL -OpenClaw는 내장 모델 카탈로그를 사용합니다. 사용자 지정 provider는 구성의 `models.providers` 또는 `~/.openclaw/agents//agent/models.json`을 통해 추가합니다. +OpenClaw는 내장 모델 카탈로그를 사용합니다. 사용자 지정 provider는 config의 `models.providers` 또는 `~/.openclaw/agents//agent/models.json`을 통해 추가하세요. ```json5 { @@ -2344,47 +2379,47 @@ OpenClaw는 내장 모델 카탈로그를 사용합니다. 사용자 지정 prov } ``` -- 사용자 지정 인증 요구사항에는 `authHeader: true` + `headers`를 사용하세요. -- 에이전트 구성 루트는 `OPENCLAW_AGENT_DIR`(또는 레거시 환경 변수 별칭 `PI_CODING_AGENT_DIR`)로 재정의할 수 있습니다. -- 일치하는 provider ID의 병합 우선순위: - - 비어 있지 않은 에이전트 `models.json` `baseUrl` 값이 우선합니다. - - 비어 있지 않은 에이전트 `apiKey` 값은 해당 provider가 현재 구성/auth-profile 컨텍스트에서 SecretRef 관리가 아닐 때만 우선합니다. - - SecretRef 관리 provider `apiKey` 값은 해석된 비밀을 유지하는 대신 소스 마커(`env` ref의 경우 `ENV_VAR_NAME`, file/exec ref의 경우 `secretref-managed`)에서 새로 고쳐집니다. - - SecretRef 관리 provider header 값은 소스 마커(`env` ref의 경우 `secretref-env:ENV_VAR_NAME`, file/exec ref의 경우 `secretref-managed`)에서 새로 고쳐집니다. - - 비어 있거나 누락된 에이전트 `apiKey`/`baseUrl`은 구성의 `models.providers`로 대체됩니다. - - 일치하는 모델 `contextWindow`/`maxTokens`는 명시적 구성값과 암시적 카탈로그 값 중 더 큰 값을 사용합니다. - - 일치하는 모델 `contextTokens`는 존재하는 경우 명시적 런타임 캡을 보존합니다. 모델의 네이티브 메타데이터를 변경하지 않고 실제 컨텍스트를 제한하려면 이를 사용하세요. - - 구성이 `models.json`을 완전히 다시 쓰게 하려면 `models.mode: "replace"`를 사용하세요. - - 마커 유지 저장은 소스 권위적입니다: 마커는 해석된 런타임 비밀 값이 아니라 활성 소스 구성 스냅샷(해석 전)에서 기록됩니다. +- 사용자 지정 인증이 필요하면 `authHeader: true` + `headers`를 사용하세요. +- 에이전트 config 루트는 `OPENCLAW_AGENT_DIR`(또는 레거시 환경 변수 별칭 `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`를 바꾸지 않고 실제 컨텍스트를 제한할 때 사용하세요. + - config가 `models.json`을 완전히 다시 쓰게 하려면 `models.mode: "replace"`를 사용하세요. + - 마커 영속성은 소스가 권위입니다. 마커는 해결된 런타임 비밀값이 아니라 활성 소스 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.*.apiKey`: provider 자격 증명(SecretRef/env 치환 사용 권장). - `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 기본 URL. +- `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`: 모델 provider HTTP 요청용 전송 재정의. +- `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`: 직접 연결용 TLS 재정의. 필드: `ca`, `cert`, `key`, `passphrase`(모두 SecretRef 허용), `serverName`, `insecureSkipVerify`. + - `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`: 선택적 런타임 컨텍스트 캡. 모델의 네이티브 `contextWindow`보다 작은 실제 컨텍스트 예산을 원할 때 사용하세요. -- `models.providers.*.models.*.compat.supportsDeveloperRole`: 선택적 호환성 힌트. 비어 있지 않은 비네이티브 `baseUrl`(호스트가 `api.openai.com`이 아님)을 가진 `api: "openai-completions"`의 경우 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`: 검색 새로 고침 폴링 간격. -- `plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow`: 검색된 모델의 대체 컨텍스트 윈도. -- `plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens`: 검색된 모델의 대체 최대 출력 토큰. +- `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`: 발견된 모델용 대체 최대 출력 토큰. ### Provider 예시 @@ -2422,7 +2457,7 @@ OpenClaw는 내장 모델 카탈로그를 사용합니다. 사용자 지정 prov } ``` -Cerebras에는 `cerebras/zai-glm-4.7`을 사용하고, Z.AI 직접 연결에는 `zai/glm-4.7`을 사용하세요. +Cerebras에는 `cerebras/zai-glm-4.7`을, Z.AI direct에는 `zai/glm-4.7`을 사용하세요. @@ -2439,7 +2474,7 @@ Cerebras에는 `cerebras/zai-glm-4.7`을 사용하고, Z.AI 직접 연결에는 } ``` -`OPENCODE_API_KEY`(또는 `OPENCODE_ZEN_API_KEY`)를 설정하세요. Zen 카탈로그에는 `opencode/...` 참조를, Go 카탈로그에는 `opencode-go/...` 참조를 사용하세요. 단축키: `openclaw onboard --auth-choice opencode-zen` 또는 `openclaw onboard --auth-choice opencode-go`. +`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`. @@ -2456,11 +2491,11 @@ Cerebras에는 `cerebras/zai-glm-4.7`을 사용하고, Z.AI 직접 연결에는 } ``` -`ZAI_API_KEY`를 설정하세요. `z.ai/*`와 `z-ai/*`는 허용되는 별칭입니다. 단축키: `openclaw onboard --auth-choice zai-api-key`. +`ZAI_API_KEY`를 설정하세요. `z.ai/*`와 `z-ai/*`는 허용되는 별칭입니다. 바로가기: `openclaw onboard --auth-choice zai-api-key`. - 일반 엔드포인트: `https://api.z.ai/api/paas/v4` - 코딩 엔드포인트(기본값): `https://api.z.ai/api/coding/paas/v4` -- 일반 엔드포인트의 경우 base URL 재정의를 가진 사용자 지정 provider를 정의하세요. +- 일반 엔드포인트를 쓰려면 base URL 재정의가 포함된 사용자 지정 provider를 정의하세요. @@ -2499,9 +2534,11 @@ Cerebras에는 `cerebras/zai-glm-4.7`을 사용하고, Z.AI 직접 연결에는 } ``` -중국 엔드포인트의 경우: `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만이 아니라 해당 엔드포인트 기능을 기준으로 동작을 판단합니다. @@ -2519,11 +2556,11 @@ Cerebras에는 `cerebras/zai-glm-4.7`을 사용하고, Z.AI 직접 연결에는 } ``` -Anthropic 호환 내장 provider입니다. 단축키: `openclaw onboard --auth-choice kimi-code-api-key`. +Anthropic 호환 내장 provider입니다. 바로가기: `openclaw onboard --auth-choice kimi-code-api-key`. - + ```json5 { @@ -2558,11 +2595,11 @@ Anthropic 호환 내장 provider입니다. 단축키: `openclaw onboard --auth-c } ``` -Base URL은 `/v1`을 생략해야 합니다(Anthropic 클라이언트가 이를 추가함). 단축키: `openclaw onboard --auth-choice synthetic-api-key`. +Base URL에는 `/v1`를 포함하지 않아야 합니다(Anthropic 클라이언트가 이를 자동으로 추가함). 바로가기: `openclaw onboard --auth-choice synthetic-api-key`. - + ```json5 { @@ -2598,17 +2635,20 @@ Base URL은 `/v1`을 생략해야 합니다(Anthropic 클라이언트가 이를 } ``` -`MINIMAX_API_KEY`를 설정하세요. 단축키: +`MINIMAX_API_KEY`를 설정하세요. 바로가기: `openclaw onboard --auth-choice minimax-global-api` 또는 `openclaw onboard --auth-choice minimax-cn-api`. -모델 카탈로그는 이제 기본적으로 M2.7만 사용합니다. -Anthropic 호환 스트리밍 경로에서 OpenClaw는 명시적으로 `thinking`을 설정하지 않는 한 기본적으로 MiniMax thinking을 비활성화합니다. `/fast on` 또는 `params.fastMode: true`는 `MiniMax-M2.7`을 `MiniMax-M2.7-highspeed`로 다시 씁니다. +모델 카탈로그는 기본적으로 M2.7만 포함합니다. +Anthropic 호환 스트리밍 경로에서는, +명시적으로 `thinking`을 설정하지 않는 한 OpenClaw가 MiniMax thinking을 기본적으로 비활성화합니다. `/fast on` 또는 +`params.fastMode: true`는 `MiniMax-M2.7`을 +`MiniMax-M2.7-highspeed`로 다시 씁니다. -[Local Models](/ko/gateway/local-models)를 참고하세요. 요약: 충분한 하드웨어에서 LM Studio Responses API를 통해 대형 로컬 모델을 실행하고, 대체를 위해 호스팅된 모델은 병합된 상태로 유지하세요. +[Local Models](/ko/gateway/local-models)를 참고하세요. 요약: 충분한 하드웨어에서 LM Studio Responses API를 통해 대형 로컬 모델을 실행하고, 대체용으로 호스팅 모델은 병합된 상태로 유지하세요. @@ -2639,12 +2679,14 @@ Anthropic 호환 스트리밍 경로에서 OpenClaw는 명시적으로 `thinking } ``` -- `allowBundled`: 번들 skill만을 위한 선택적 허용 목록입니다(관리형/workspace skill에는 영향 없음). +- `allowBundled`: 번들 skill 전용 선택적 허용 목록입니다(관리형/workspace skill에는 영향 없음). - `load.extraDirs`: 추가 공유 skill 루트(가장 낮은 우선순위). -- `install.preferBrew`: `brew`를 사용할 수 있을 때 다른 설치 방식으로 대체되기 전에 Homebrew 설치 프로그램을 우선합니다. -- `install.nodeManager`: `metadata.openclaw.install` 명세용 node 설치 프로그램 선호도 (`npm` | `pnpm` | `yarn` | `bun`). +- `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 객체). +- `entries..apiKey`: 기본 env var를 선언하는 skill에 대한 편의 필드입니다(일반 텍스트 문자열 또는 SecretRef 객체). --- @@ -2673,45 +2715,48 @@ Anthropic 호환 스트리밍 경로에서 OpenClaw는 명시적으로 `thinking ``` - `~/.openclaw/extensions`, `/.openclaw/extensions`, 그리고 `plugins.load.paths`에서 로드됩니다. -- 검색은 네이티브 OpenClaw 플러그인과 호환 가능한 Codex 번들 및 Claude 번들을 허용하며, manifest가 없는 Claude 기본 레이아웃 번들도 포함합니다. -- **구성 변경에는 gateway 재시작이 필요합니다.** +- 검색은 네이티브 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`: 플러그인 정의 구성 객체(사용 가능한 경우 네이티브 OpenClaw plugin 스키마로 검증됨). +- `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를 대체값으로 사용합니다. + - `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`: 스크래핑 요청 타임아웃(초)입니다(기본값: `60`). -- `plugins.entries.xai.config.xSearch`: xAI X Search (Grok 웹 검색) 설정. - - `enabled`: X Search provider를 활성화합니다. + - `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 스윕의 cron 주기(기본값은 `"0 3 * * *"`). - - 단계 정책과 임계값은 구현 세부 사항입니다(사용자 대상 구성 키 아님). -- 전체 memory 구성은 [Memory configuration reference](/ko/reference/memory-config)에 있습니다: +- `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)에 있습니다: - `agents.defaults.memorySearch.*` - `memory.backend` - `memory.citations` - `memory.qmd.*` - `plugins.entries.memory-core.config.dreaming` -- 활성화된 Claude 번들 플러그인은 `settings.json`에서 임베디드 Pi 기본값도 제공할 수 있습니다. OpenClaw는 이를 원시 OpenClaw 구성 패치가 아니라 정제된 에이전트 설정으로 적용합니다. -- `plugins.slots.memory`: 활성 memory plugin id를 선택하거나 memory plugin을 비활성화하려면 `"none"`을 선택합니다. +- 활성화된 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"`입니다. -- `plugins.installs`: `openclaw plugins update`가 사용하는 CLI 관리 설치 메타데이터입니다. +- `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)를 참고하세요. --- -## 브라우저 +## Browser -``` \ No newline at end of file +```json5 +{ + browser: { + enabled: true, \ No newline at end of file diff --git a/docs/ko/gateway/doctor.md b/docs/ko/gateway/doctor.md index 7f25e8898..9b9c178cf 100644 --- a/docs/ko/gateway/doctor.md +++ b/docs/ko/gateway/doctor.md @@ -1,14 +1,14 @@ --- read_when: - - doctor 마이그레이션 추가 또는 수정하기 - - 호환되지 않는 구성 변경 도입하기 -summary: 'Doctor 명령: 상태 점검, 구성 마이그레이션, 및 복구 단계' + - doctor 마이그레이션을 추가하거나 수정하는 경우 + - 호환되지 않는 설정 변경을 도입하는 경우 +summary: 'Doctor 명령: 상태 점검, 설정 마이그레이션, 복구 단계' title: Doctor x-i18n: - generated_at: "2026-04-08T02:15:43Z" + generated_at: "2026-04-09T01:29:19Z" model: gpt-5.4 provider: openai - source_hash: 3761a222d9db7088f78215575fa84e5896794ad701aa716e8bf9039a4424dca6 + source_hash: 75d321bd1ad0e16c29f2382e249c51edfc3a8d33b55bdceea39e7dbcd4901fce source_path: gateway/doctor.md workflow: 15 --- @@ -36,101 +36,135 @@ openclaw doctor --yes openclaw doctor --repair ``` -프롬프트 없이 권장 복구를 적용합니다(안전한 경우 복구 + 재시작). +권장 복구를 프롬프트 없이 적용합니다(안전한 경우 복구 + 재시작). ```bash openclaw doctor --repair --force ``` -공격적인 복구까지 적용합니다(사용자 지정 supervisor config를 덮어씁니다). +공격적인 복구도 적용합니다(사용자 지정 supervisor config를 덮어씀). ```bash openclaw doctor --non-interactive ``` 프롬프트 없이 실행하고 안전한 마이그레이션만 적용합니다(config 정규화 + 디스크 상태 이동). 사람의 확인이 필요한 재시작/서비스/샌드박스 작업은 건너뜁니다. -감지된 레거시 상태 마이그레이션은 자동으로 실행됩니다. +기존 상태 마이그레이션은 감지되면 자동으로 실행됩니다. ```bash openclaw doctor --deep ``` -추가 gateway 설치를 위해 시스템 서비스(launchd/systemd/schtasks)를 검사합니다. +추가 gateway 설치를 위해 시스템 서비스를 검사합니다(launchd/systemd/schtasks). -쓰기 전에 변경 사항을 검토하려면 먼저 config 파일을 여세요: +기록하기 전에 변경 사항을 검토하려면 먼저 config 파일을 여세요. ```bash cat ~/.openclaw/openclaw.json ``` -## 수행 작업(요약) +## 수행 내용(요약) -- git 설치를 위한 선택적 사전 업데이트(대화형 전용). -- UI 프로토콜 최신 상태 검사(프로토콜 스키마가 더 최신이면 Control UI를 다시 빌드). +- git 설치에 대한 선택적 사전 업데이트(대화형 전용). +- UI 프로토콜 최신 상태 점검(프로토콜 스키마가 더 새로우면 Control UI를 다시 빌드). - 상태 점검 + 재시작 프롬프트. - Skills 상태 요약(적격/누락/차단) 및 plugin 상태. -- 레거시 값에 대한 config 정규화. -- 레거시 평면 `talk.*` 필드에서 `talk.provider` + `talk.providers.`로의 Talk config 마이그레이션. -- 레거시 Chrome 확장 config 및 Chrome MCP 준비 상태를 위한 브라우저 마이그레이션 검사. +- 기존 값에 대한 config 정규화. +- 기존 평면 `talk.*` 필드에서 `talk.provider` + `talk.providers.`로의 Talk config 마이그레이션. +- 기존 Chrome 확장 프로그램 config 및 Chrome MCP 준비 상태에 대한 브라우저 마이그레이션 점검. - OpenCode provider 재정의 경고(`models.providers.opencode` / `models.providers.opencode-go`). -- Codex OAuth 섀도잉 경고(`models.providers.openai-codex`). -- OpenAI Codex OAuth 프로필에 대한 OAuth TLS 선행 조건 검사. -- 레거시 디스크 상태 마이그레이션(세션/agent 디렉터리/WhatsApp 인증). -- 레거시 plugin manifest 계약 키 마이그레이션(`speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders`, `webSearchProviders` → `contracts`). -- 레거시 cron 저장소 마이그레이션(`jobId`, `schedule.cron`, 최상위 delivery/payload 필드, payload `provider`, 단순 `notify: true` webhook 폴백 작업). +- Codex OAuth 가림 경고(`models.providers.openai-codex`). +- OpenAI Codex OAuth 프로필용 OAuth TLS 선행 조건 점검. +- 기존 디스크 상태 마이그레이션(세션/agent 디렉터리/WhatsApp 인증). +- 기존 plugin manifest 계약 키 마이그레이션(`speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders`, `webSearchProviders` → `contracts`). +- 기존 cron 저장소 마이그레이션(`jobId`, `schedule.cron`, 최상위 delivery/payload 필드, payload `provider`, 단순 `notify: true` webhook 대체 작업). - 세션 잠금 파일 검사 및 오래된 잠금 정리. -- 상태 무결성 및 권한 검사(세션, transcript, 상태 디렉터리). -- 로컬 실행 시 config 파일 권한 검사(chmod 600). -- 모델 인증 상태: OAuth 만료를 확인하고, 만료 임박 토큰을 갱신할 수 있으며, 인증 프로필의 쿨다운/비활성 상태를 보고합니다. -- 추가 워크스페이스 디렉터리 감지(`~/openclaw`). +- 상태 무결성 및 권한 점검(세션, 대화록, 상태 디렉터리). +- 로컬 실행 시 config 파일 권한 점검(chmod 600). +- 모델 인증 상태: OAuth 만료를 점검하고, 만료 예정 토큰을 갱신할 수 있으며, auth-profile cooldown/비활성 상태를 보고합니다. +- 추가 workspace 디렉터리 감지(`~/openclaw`). - 샌드박싱이 활성화된 경우 샌드박스 이미지 복구. -- 레거시 서비스 마이그레이션 및 추가 gateway 감지. -- Matrix 채널 레거시 상태 마이그레이션(`--fix` / `--repair` 모드에서). -- Gateway 런타임 검사(서비스는 설치되었지만 실행되지 않음, 캐시된 launchd 레이블). +- 기존 서비스 마이그레이션 및 추가 gateway 감지. +- Matrix 채널 기존 상태 마이그레이션(`--fix` / `--repair` 모드에서). +- Gateway 런타임 점검(서비스는 설치되었지만 실행 중이 아님, 캐시된 launchd 레이블). - 채널 상태 경고(실행 중인 gateway에서 프로브). - 선택적 복구가 포함된 supervisor config 감사(launchd/systemd/schtasks). -- Gateway 런타임 모범 사례 검사(Node 대 Bun, 버전 관리자 경로). +- Gateway 런타임 모범 사례 점검(Node vs Bun, 버전 관리자 경로). - Gateway 포트 충돌 진단(기본값 `18789`). - 열린 DM 정책에 대한 보안 경고. -- 로컬 토큰 모드용 gateway 인증 검사(토큰 소스가 없을 때 토큰 생성을 제안하며, token SecretRef config는 덮어쓰지 않음). -- Linux의 systemd linger 검사. -- 워크스페이스 bootstrap 파일 크기 검사(context 파일의 잘림/한계 근접 경고). -- 셸 completion 상태 검사 및 자동 설치/업그레이드. -- 메모리 검색 임베딩 provider 준비 상태 검사(로컬 모델, 원격 API 키 또는 QMD 바이너리). -- 소스 설치 검사(pnpm 워크스페이스 불일치, 누락된 UI 자산, 누락된 tsx 바이너리). +- 로컬 토큰 모드용 gateway 인증 점검(토큰 소스가 없을 때 토큰 생성을 제안하며, 토큰 SecretRef config는 덮어쓰지 않음). +- Linux에서 systemd linger 점검. +- Workspace 부트스트랩 파일 크기 점검(컨텍스트 파일에 대한 잘림/한계 근접 경고). +- 셸 자동 완성 상태 점검 및 자동 설치/업그레이드. +- 메모리 검색 임베딩 provider 준비 상태 점검(로컬 모델, 원격 API 키 또는 QMD 바이너리). +- 소스 설치 점검(pnpm workspace 불일치, 누락된 UI 자산, 누락된 tsx 바이너리). - 업데이트된 config + wizard 메타데이터 기록. +## Dreams UI 백필 및 재설정 + +Control UI Dreams 장면에는 근거 기반 dreaming 워크플로를 위한 **Backfill**, **Reset**, **Clear Grounded** +작업이 포함됩니다. 이러한 작업은 gateway +doctor 스타일 RPC 메서드를 사용하지만, `openclaw doctor` CLI +복구/마이그레이션의 일부는 **아닙니다**. + +수행하는 작업: + +- **Backfill**은 활성 + workspace의 과거 `memory/YYYY-MM-DD.md` 파일을 스캔하고, 근거 기반 REM 일지 패스를 실행하며, 되돌릴 수 있는 백필 + 항목을 `DREAMS.md`에 기록합니다. +- **Reset**은 표시된 백필 일지 항목만 `DREAMS.md`에서 제거합니다. +- **Clear Grounded**는 과거 재생에서 온, + 아직 실제 recall 또는 일일 + 지원이 누적되지 않은, 준비된 근거 기반 전용 단기 항목만 제거합니다. + +자동으로 수행하지 않는 작업: + +- `MEMORY.md`를 편집하지 않습니다 +- 전체 doctor 마이그레이션을 실행하지 않습니다 +- 먼저 준비 CLI 경로를 명시적으로 실행하지 않는 한, 근거 기반 후보를 실시간 단기 + 승격 저장소에 자동으로 준비하지 않습니다 + +근거 기반 과거 재생이 일반 deep 승격 +경로에 영향을 주게 하려면 대신 CLI 흐름을 사용하세요. + +```bash +openclaw memory rem-backfill --path ./memory --stage-short-term +``` + +이렇게 하면 `DREAMS.md`를 검토 표면으로 유지하면서 +근거 기반의 오래 유지할 후보를 단기 dreaming 저장소에 준비합니다. + ## 자세한 동작 및 근거 ### 0) 선택적 업데이트(git 설치) -git 체크아웃이고 doctor가 대화형으로 실행 중이면, -doctor를 실행하기 전에 업데이트(fetch/rebase/build)할지 제안합니다. +이것이 git 체크아웃이고 doctor가 대화형으로 실행 중이면, +doctor 실행 전에 업데이트(fetch/rebase/build)할지 제안합니다. ### 1) Config 정규화 -config에 레거시 값 형태가 포함되어 있으면(예: 채널별 재정의가 없는 -`messages.ackReaction`) doctor는 이를 현재 스키마로 정규화합니다. +config에 기존 값 형태가 포함되어 있는 경우(예: 채널별 재정의가 없는 `messages.ackReaction`) +doctor는 이를 현재 스키마로 정규화합니다. -여기에는 레거시 Talk 평면 필드도 포함됩니다. 현재 공개 Talk config는 -`talk.provider` + `talk.providers.`입니다. Doctor는 이전 +여기에는 기존 Talk 평면 필드도 포함됩니다. 현재 공개 Talk config는 +`talk.provider` + `talk.providers.`입니다. Doctor는 기존 `talk.voiceId` / `talk.voiceAliases` / `talk.modelId` / `talk.outputFormat` / -`talk.apiKey` 형태를 provider 맵으로 다시 씁니다. +`talk.apiKey` 형태를 provider 맵으로 다시 작성합니다. -### 2) 레거시 config 키 마이그레이션 +### 2) 기존 config 키 마이그레이션 config에 더 이상 사용되지 않는 키가 포함되어 있으면, 다른 명령은 실행을 거부하고 -`openclaw doctor`를 실행하라고 안내합니다. +`openclaw doctor`를 실행하라고 요청합니다. -Doctor는 다음을 수행합니다: +Doctor는 다음을 수행합니다. -- 어떤 레거시 키가 발견되었는지 설명합니다. +- 어떤 기존 키가 발견되었는지 설명합니다. - 적용한 마이그레이션을 보여줍니다. -- 업데이트된 스키마로 `~/.openclaw/openclaw.json`을 다시 씁니다. +- 업데이트된 스키마로 `~/.openclaw/openclaw.json`을 다시 기록합니다. -Gateway도 시작 시 레거시 config 형식을 감지하면 doctor 마이그레이션을 자동 실행하므로 -오래된 config가 수동 개입 없이 복구됩니다. -Cron 작업 저장소 마이그레이션은 `openclaw doctor --fix`에서 처리됩니다. +Gateway도 시작 시 +기존 config 형식을 감지하면 doctor 마이그레이션을 자동 실행하므로, 오래된 config가 수동 개입 없이 복구됩니다. +Cron 작업 저장소 마이그레이션은 `openclaw doctor --fix`가 처리합니다. 현재 마이그레이션: @@ -141,7 +175,7 @@ Cron 작업 저장소 마이그레이션은 `openclaw doctor --fix`에서 처리 - `routing.queue` → `messages.queue` - `routing.bindings` → 최상위 `bindings` - `routing.agents`/`routing.defaultAgentId` → `agents.list` + `agents.list[].default` -- 레거시 `talk.voiceId`/`talk.voiceAliases`/`talk.modelId`/`talk.outputFormat`/`talk.apiKey` → `talk.provider` + `talk.providers.` +- 기존 `talk.voiceId`/`talk.voiceAliases`/`talk.modelId`/`talk.outputFormat`/`talk.apiKey` → `talk.provider` + `talk.providers.` - `routing.agentToAgent` → `tools.agentToAgent` - `routing.transcribeAudio` → `tools.media.audio.models` - `messages.tts.` (`openai`/`elevenlabs`/`microsoft`/`edge`) → `messages.tts.providers.` @@ -154,19 +188,19 @@ Cron 작업 저장소 마이그레이션은 `openclaw doctor --fix`에서 처리 - `plugins.entries.voice-call.config.streaming.openaiApiKey|sttModel|silenceDurationMs|vadThreshold` → `plugins.entries.voice-call.config.streaming.providers.openai.*` - `bindings[].match.accountID` → `bindings[].match.accountId` -- 이름이 지정된 `accounts`가 있는 채널에서 단일 계정용 최상위 채널 값이 남아 있는 경우, 해당 계정 범위 값을 그 채널에 대해 선택된 승격 계정으로 이동합니다(대부분 채널은 `accounts.default`; Matrix는 기존에 일치하는 이름 있는/default 대상을 유지할 수 있음) +- 이름 있는 `accounts`가 있지만 단일 계정용 최상위 채널 값이 남아 있는 채널의 경우, 해당 계정 범위 값을 그 채널에 대해 선택된 승격 대상 계정으로 이동합니다(대부분의 채널은 `accounts.default`; Matrix는 기존에 일치하는 이름 있는/기본 대상을 유지할 수 있음) - `identity` → `agents.list[].identity` - `agent.*` → `agents.defaults` + `tools.*` (tools/elevated/exec/sandbox/subagents) - `agent.model`/`allowedModels`/`modelAliases`/`modelFallbacks`/`imageModelFallbacks` → `agents.defaults.models` + `agents.defaults.model.primary/fallbacks` + `agents.defaults.imageModel.primary/fallbacks` - `browser.ssrfPolicy.allowPrivateNetwork` → `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork` - `browser.profiles.*.driver: "extension"` → `"existing-session"` -- `browser.relayBindHost` 제거(레거시 확장 relay 설정) +- `browser.relayBindHost` 제거(기존 확장 프로그램 relay 설정) -Doctor 경고에는 다중 계정 채널에 대한 account 기본값 안내도 포함됩니다: +Doctor 경고에는 다중 계정 채널에 대한 계정 기본값 안내도 포함됩니다. -- `channels..defaultAccount` 또는 `accounts.default` 없이 두 개 이상의 `channels..accounts` 항목이 구성된 경우, doctor는 폴백 라우팅이 예상치 못한 계정을 선택할 수 있다고 경고합니다. -- `channels..defaultAccount`가 알 수 없는 계정 ID로 설정된 경우, doctor는 경고하고 구성된 계정 ID를 나열합니다. +- `channels..accounts` 항목이 둘 이상 구성되어 있는데 `channels..defaultAccount` 또는 `accounts.default`가 없으면, doctor는 대체 라우팅이 예상치 못한 계정을 선택할 수 있다고 경고합니다. +- `channels..defaultAccount`가 알 수 없는 계정 ID로 설정되어 있으면, doctor는 경고하고 구성된 계정 ID 목록을 보여줍니다. ### 2b) OpenCode provider 재정의 @@ -177,328 +211,335 @@ Doctor 경고에는 다중 계정 채널에 대한 account 기본값 안내도 ### 2c) 브라우저 마이그레이션 및 Chrome MCP 준비 상태 -브라우저 config가 아직 제거된 Chrome 확장 경로를 가리키는 경우, doctor는 -이를 현재 호스트 로컬 Chrome MCP 연결 모델로 정규화합니다: +브라우저 config가 여전히 제거된 Chrome 확장 프로그램 경로를 가리키는 경우, doctor는 +이를 현재 호스트 로컬 Chrome MCP 연결 모델로 정규화합니다. - `browser.profiles.*.driver: "extension"`은 `"existing-session"`이 됩니다 - `browser.relayBindHost`는 제거됩니다 -`defaultProfile: -"user"` 또는 구성된 `existing-session` 프로필을 사용할 때 doctor는 호스트 로컬 Chrome MCP 경로도 감사합니다: +Doctor는 또한 `defaultProfile: +"user"` 또는 구성된 `existing-session` 프로필을 사용할 때 호스트 로컬 Chrome MCP 경로를 점검합니다. -- 기본 자동 연결 프로필에 대해 동일한 호스트에 Google Chrome이 설치되어 있는지 확인 -- 감지된 Chrome 버전을 확인하고 Chrome 144 미만이면 경고 -- 브라우저 inspect 페이지에서 원격 디버깅을 활성화하라고 안내 - (예: `chrome://inspect/#remote-debugging`, `brave://inspect/#remote-debugging`, +- 기본 + 자동 연결 프로필에 대해 같은 호스트에 Google Chrome이 설치되어 있는지 확인합니다 +- 감지된 Chrome 버전을 확인하고 Chrome 144 미만이면 경고합니다 +- 브라우저 inspect 페이지에서 원격 디버깅을 활성화하라고 알려줍니다(예: + `chrome://inspect/#remote-debugging`, `brave://inspect/#remote-debugging`, 또는 `edge://inspect/#remote-debugging`) -Doctor는 Chrome 측 설정을 대신 활성화할 수 없습니다. 호스트 로컬 Chrome MCP에는 여전히 다음이 필요합니다: +Doctor는 Chrome 측 설정을 대신 활성화할 수 없습니다. 호스트 로컬 Chrome MCP에는 여전히 다음이 필요합니다. -- gateway/node 호스트에 설치된 Chromium 기반 브라우저 144+ -- 로컬에서 실행 중인 브라우저 -- 해당 브라우저에서 활성화된 원격 디버깅 -- 브라우저에서 첫 연결 동의 프롬프트 승인 +- gateway/node 호스트에 Chromium 기반 브라우저 144+가 있어야 함 +- 브라우저가 로컬에서 실행 중이어야 함 +- 해당 브라우저에서 원격 디버깅이 활성화되어 있어야 함 +- 브라우저에서 최초 연결 동의 프롬프트를 승인해야 함 -여기서의 준비 상태는 로컬 연결 선행 조건에만 관한 것입니다. Existing-session은 -현재 Chrome MCP 경로 제한을 유지합니다. `responsebody`, PDF 내보내기, -다운로드 가로채기, 배치 작업 같은 고급 경로는 여전히 관리형 +여기서의 준비 상태는 로컬 연결 선행 조건에만 해당합니다. Existing-session은 +현재 Chrome MCP 경로 제한을 유지합니다. `responsebody`, PDF +내보내기, 다운로드 가로채기, 배치 작업과 같은 고급 경로는 여전히 관리형 브라우저 또는 원시 CDP 프로필이 필요합니다. -이 검사는 Docker, sandbox, remote-browser 또는 기타 -헤드리스 흐름에는 **적용되지 않습니다**. 이러한 경우는 계속 원시 CDP를 사용합니다. +이 점검은 Docker, 샌드박스, 원격 브라우저 또는 기타 +헤드리스 흐름에는 **적용되지 않습니다**. 이러한 경우는 계속해서 원시 CDP를 사용합니다. ### 2d) OAuth TLS 선행 조건 -OpenAI Codex OAuth 프로필이 구성되어 있으면 doctor는 OpenAI -인증 엔드포인트를 프로브하여 로컬 Node/OpenSSL TLS 스택이 인증서 체인을 -검증할 수 있는지 확인합니다. 프로브가 인증서 오류로 실패하면(예: +OpenAI Codex OAuth 프로필이 구성되어 있으면, doctor는 OpenAI +인증 엔드포인트를 프로브하여 로컬 Node/OpenSSL TLS 스택이 +인증서 체인을 검증할 수 있는지 확인합니다. 프로브가 인증서 오류로 실패하면(예: `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`, 만료된 인증서 또는 자체 서명 인증서), -doctor는 플랫폼별 해결 안내를 출력합니다. Homebrew Node를 사용하는 macOS에서는 -보통 `brew postinstall ca-certificates`가 해결 방법입니다. `--deep`를 사용하면 -gateway가 정상이어도 프로브가 실행됩니다. +doctor는 플랫폼별 수정 안내를 출력합니다. Homebrew Node를 사용하는 macOS에서는 +보통 `brew postinstall ca-certificates`로 해결합니다. `--deep`를 사용하면 gateway가 정상이어도 +프로브가 실행됩니다. ### 2c) Codex OAuth provider 재정의 -이전에 레거시 OpenAI 전송 설정을 -`models.providers.openai-codex` 아래에 추가했다면, 이는 최신 릴리스가 자동으로 사용하는 -내장 Codex OAuth provider 경로를 가릴 수 있습니다. Doctor는 -Codex OAuth와 함께 이러한 오래된 전송 설정을 감지하면 경고하여, -오래된 전송 재정의를 제거하거나 다시 작성해 내장 라우팅/폴백 동작을 -복원할 수 있도록 합니다. 사용자 지정 프록시와 헤더 전용 재정의는 여전히 지원되며 -이 경고를 발생시키지 않습니다. +이전에 +`models.providers.openai-codex` 아래에 기존 OpenAI 전송 설정을 추가했다면, +최신 릴리스가 자동으로 사용하는 내장 Codex OAuth +provider 경로를 가릴 수 있습니다. Doctor는 Codex OAuth와 함께 이러한 기존 전송 설정을 발견하면 +오래된 전송 재정의를 제거하거나 다시 작성하여 내장 라우팅/대체 동작을 +다시 사용할 수 있도록 경고합니다. 사용자 지정 프록시와 헤더 전용 재정의는 여전히 지원되며 이 경고를 +발생시키지 않습니다. -### 3) 레거시 상태 마이그레이션(디스크 레이아웃) +### 3) 기존 상태 마이그레이션(디스크 레이아웃) -Doctor는 오래된 디스크 레이아웃을 현재 구조로 마이그레이션할 수 있습니다: +Doctor는 오래된 디스크 레이아웃을 현재 구조로 마이그레이션할 수 있습니다. -- 세션 저장소 + transcript: +- 세션 저장소 + 대화록: - `~/.openclaw/sessions/`에서 `~/.openclaw/agents//sessions/`로 - Agent 디렉터리: - `~/.openclaw/agent/`에서 `~/.openclaw/agents//agent/`로 - WhatsApp 인증 상태(Baileys): - - 레거시 `~/.openclaw/credentials/*.json` (`oauth.json` 제외)에서 - - `~/.openclaw/credentials/whatsapp//...`로 (기본 account id: `default`) + - 기존 `~/.openclaw/credentials/*.json`(`oauth.json` 제외)에서 + - `~/.openclaw/credentials/whatsapp//...`로(기본 계정 ID: `default`) -이 마이그레이션은 최선의 노력 기준이며 멱등적입니다. 백업으로 남겨진 레거시 폴더가 있으면 -doctor는 경고를 출력합니다. Gateway/CLI도 시작 시 -레거시 세션 + agent 디렉터리를 자동 마이그레이션하므로, 수동 doctor 실행 없이도 -기록/인증/모델이 agent별 경로에 저장됩니다. WhatsApp 인증은 의도적으로 -`openclaw doctor`를 통해서만 마이그레이션됩니다. Talk provider/provider 맵 정규화는 이제 -구조적 동등성으로 비교하므로, 키 순서만 다른 차이로는 -반복적인 no-op `doctor --fix` 변경이 더 이상 발생하지 않습니다. +이 마이그레이션은 최선형이며 멱등적입니다. doctor는 +기존 폴더를 백업으로 남겨둘 때 경고를 출력합니다. Gateway/CLI도 시작 시 +기존 세션 + agent 디렉터리를 자동 마이그레이션하므로, 기록/인증/모델이 수동 doctor 실행 없이 +agent별 경로에 저장됩니다. WhatsApp 인증은 의도적으로 `openclaw doctor`를 통해서만 +마이그레이션됩니다. Talk provider/provider-map 정규화는 이제 +구조적 동등성으로 비교하므로, 키 순서만 다른 차이로 인해 +반복적인 무의미한 `doctor --fix` 변경이 더 이상 발생하지 않습니다. -### 3a) 레거시 plugin manifest 마이그레이션 +### 3a) 기존 plugin manifest 마이그레이션 -Doctor는 설치된 모든 plugin manifest를 검사해 더 이상 사용되지 않는 최상위 기능 +Doctor는 설치된 모든 plugin manifest를 검사하여 더 이상 사용되지 않는 최상위 capability 키(`speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders`, `webSearchProviders`)를 찾습니다. 발견되면 이를 `contracts` -객체로 이동하고 manifest 파일을 제자리에서 다시 쓸지 제안합니다. 이 마이그레이션은 멱등적이며, -`contracts` 키에 이미 동일한 값이 있으면 레거시 키만 제거되고 -데이터는 중복되지 않습니다. +객체로 이동하고 manifest 파일을 제자리에서 다시 쓰도록 제안합니다. 이 마이그레이션은 멱등적입니다. +`contracts` 키에 이미 같은 값이 있으면, +기존 키는 데이터를 중복하지 않고 제거됩니다. -### 3b) 레거시 cron 저장소 마이그레이션 +### 3b) 기존 cron 저장소 마이그레이션 -Doctor는 cron 작업 저장소(기본값은 `~/.openclaw/cron/jobs.json`, -또는 재정의된 경우 `cron.store`)에서 스케줄러가 호환성을 위해 여전히 허용하는 -오래된 작업 형태도 검사합니다. +Doctor는 또한 cron 작업 저장소(기본값 `~/.openclaw/cron/jobs.json`, +또는 재정의된 경우 `cron.store`)에 대해 스케줄러가 호환성을 위해 여전히 +허용하는 오래된 작업 형태가 있는지 점검합니다. -현재 cron 정리 항목은 다음과 같습니다: +현재 cron 정리 항목: - `jobId` → `id` - `schedule.cron` → `schedule.expr` - 최상위 payload 필드(`message`, `model`, `thinking`, ...) → `payload` - 최상위 delivery 필드(`deliver`, `channel`, `to`, `provider`, ...) → `delivery` - payload `provider` delivery 별칭 → 명시적 `delivery.channel` -- 단순 레거시 `notify: true` webhook 폴백 작업 → 명시적 `delivery.mode="webhook"` 및 `delivery.to=cron.webhook` +- 단순 기존 `notify: true` webhook 대체 작업 → 명시적 `delivery.mode="webhook"`와 `delivery.to=cron.webhook` -Doctor는 동작을 변경하지 않고 수행할 수 있을 때만 `notify: true` 작업을 -자동 마이그레이션합니다. 작업이 레거시 notify 폴백과 기존 -비-webhook delivery 모드를 함께 사용하면, doctor는 경고하고 해당 작업은 -수동 검토용으로 남겨 둡니다. +Doctor는 동작을 바꾸지 않고 수행할 수 있을 때만 `notify: true` 작업을 자동 마이그레이션합니다. +작업이 기존 notify 대체와 기존의 +비-webhook delivery 모드를 함께 사용하는 경우, doctor는 경고하고 해당 작업은 수동 검토용으로 남겨둡니다. ### 3c) 세션 잠금 정리 -Doctor는 모든 agent 세션 디렉터리를 검사해 오래된 쓰기 잠금 파일을 찾습니다 — -세션이 비정상 종료될 때 남겨진 파일입니다. 발견된 각 잠금 파일에 대해 doctor는 -다음을 보고합니다: 경로, PID, PID가 아직 살아 있는지 여부, 잠금 생성 후 경과 시간, -그리고 오래된 것으로 간주되는지 여부(죽은 PID 또는 30분 초과). `--fix` / `--repair` +Doctor는 모든 agent 세션 디렉터리를 스캔하여 오래된 쓰기 잠금 파일을 찾습니다. 이는 +세션이 비정상적으로 종료될 때 남겨진 파일입니다. 발견된 각 잠금 파일에 대해 다음을 보고합니다. +경로, PID, 해당 PID가 아직 살아 있는지, 잠금 경과 시간, 그리고 +오래된 것으로 간주되는지 여부(죽은 PID이거나 30분 초과). `--fix` / `--repair` 모드에서는 오래된 잠금 파일을 자동으로 제거합니다. 그렇지 않으면 메모를 출력하고 `--fix`로 다시 실행하라고 안내합니다. -### 4) 상태 무결성 검사(세션 지속성, 라우팅 및 안전성) +### 4) 상태 무결성 점검(세션 지속성, 라우팅, 안전성) -상태 디렉터리는 운영의 핵심 중추입니다. 이것이 사라지면 +상태 디렉터리는 운영의 핵심 기반입니다. 이것이 사라지면 세션, 자격 증명, 로그, config를 잃게 됩니다(다른 곳에 백업이 없는 한). -Doctor는 다음을 검사합니다: +Doctor는 다음을 점검합니다. -- **상태 디렉터리 누락**: 치명적인 상태 손실을 경고하고, 디렉터리를 다시 만들지 묻고, - 누락된 데이터를 복구할 수 없음을 상기시킵니다. +- **상태 디렉터리 누락**: 치명적인 상태 손실을 경고하고, 디렉터리 재생성을 제안하며, + 누락된 데이터를 복구할 수 없음을 알려줍니다. - **상태 디렉터리 권한**: 쓰기 가능 여부를 확인하고, 권한 복구를 제안합니다 (소유자/그룹 불일치가 감지되면 `chown` 힌트도 출력). - **macOS 클라우드 동기화 상태 디렉터리**: 상태가 iCloud Drive (`~/Library/Mobile Documents/com~apple~CloudDocs/...`) 또는 - `~/Library/CloudStorage/...` 아래로 확인되면 경고합니다. 동기화 기반 경로는 더 느린 I/O와 - 잠금/동기화 경쟁 상태를 유발할 수 있기 때문입니다. + `~/Library/CloudStorage/...` 아래로 해석되면 경고합니다. 동기화 기반 경로는 느린 I/O와 + 잠금/동기화 경쟁을 유발할 수 있기 때문입니다. - **Linux SD 또는 eMMC 상태 디렉터리**: 상태가 `mmcblk*` - 마운트 소스로 확인되면 경고합니다. SD 또는 eMMC 기반 랜덤 I/O는 세션 및 자격 증명 쓰기에서 - 더 느리고 마모가 빠를 수 있기 때문입니다. -- **세션 디렉터리 누락**: `sessions/` 및 세션 저장소 디렉터리는 + 마운트 소스로 해석되면 경고합니다. SD 또는 eMMC 기반 랜덤 I/O는 + 세션 및 자격 증명 기록에서 더 느리고 마모가 더 빠를 수 있기 때문입니다. +- **세션 디렉터리 누락**: `sessions/`와 세션 저장소 디렉터리는 기록을 유지하고 `ENOENT` 충돌을 방지하는 데 필요합니다. -- **Transcript 불일치**: 최근 세션 항목에 누락된 - transcript 파일이 있으면 경고합니다. -- **메인 세션 “1줄 JSONL”**: 메인 transcript가 한 줄뿐인 경우를 표시합니다 - (기록이 누적되지 않음). -- **여러 상태 디렉터리**: 서로 다른 홈 디렉터리에 여러 `~/.openclaw` 폴더가 있거나 - `OPENCLAW_STATE_DIR`이 다른 곳을 가리키면 경고합니다(기록이 설치 간에 분리될 수 있음). +- **대화록 불일치**: 최근 세션 항목에 누락된 + 대화록 파일이 있으면 경고합니다. +- **메인 세션 “1줄 JSONL”**: 메인 대화록에 한 줄만 있는 경우(기록이 누적되지 않음)를 표시합니다. +- **여러 상태 디렉터리**: 여러 홈 디렉터리에 `~/.openclaw` 폴더가 있거나 + `OPENCLAW_STATE_DIR`이 다른 곳을 가리키면 경고합니다(기록이 설치 간에 + 분리될 수 있음). - **원격 모드 알림**: `gateway.mode=remote`이면 doctor는 - 원격 호스트에서 실행하라고 알려줍니다(상태는 այնտեղ에 있음). + 원격 호스트에서 실행하라고 알려줍니다(상태는 그곳에 있음). - **Config 파일 권한**: `~/.openclaw/openclaw.json`이 - 그룹/전체 읽기 가능하면 경고하고 `600`으로 강화할지 제안합니다. + 그룹/전체 읽기 가능하면 경고하고 `600`으로 제한할 것을 제안합니다. ### 5) 모델 인증 상태(OAuth 만료) Doctor는 인증 저장소의 OAuth 프로필을 검사하고, 토큰이 -곧 만료되거나 이미 만료되었을 때 경고하며, 안전한 경우 갱신할 수 있습니다. Anthropic -OAuth/토큰 프로필이 오래되었으면 Anthropic API 키 또는 +곧 만료되거나 이미 만료된 경우 경고하며, 안전한 경우 갱신할 수 있습니다. Anthropic +OAuth/토큰 프로필이 오래된 경우, Anthropic API 키 또는 Anthropic setup-token 경로를 제안합니다. -갱신 프롬프트는 대화형(TTY) 실행 시에만 표시되며, `--non-interactive`는 +갱신 프롬프트는 대화형(TTY)으로 실행할 때만 표시되며, `--non-interactive`는 갱신 시도를 건너뜁니다. -Doctor는 또한 다음 이유로 일시적으로 사용할 수 없는 인증 프로필도 보고합니다: +OAuth 갱신이 영구적으로 실패하면(예: `refresh_token_reused`, +`invalid_grant`, 또는 provider가 다시 로그인하라고 알리는 경우), +doctor는 재인증이 필요하다고 보고하고 실행해야 할 정확한 +`openclaw models auth login --provider ...` 명령을 출력합니다. -- 짧은 쿨다운(속도 제한/타임아웃/인증 실패) -- 더 긴 비활성화(결제/크레딧 실패) +Doctor는 또한 다음과 같은 이유로 일시적으로 사용할 수 없는 auth profile도 보고합니다. + +- 짧은 cooldown(속도 제한/타임아웃/인증 실패) +- 더 긴 비활성화(청구/크레딧 실패) ### 6) Hooks 모델 검증 -`hooks.gmail.model`이 설정되어 있으면 doctor는 모델 참조를 -카탈로그 및 allowlist와 대조해 검증하고, 해석되지 않거나 허용되지 않으면 경고합니다. +`hooks.gmail.model`이 설정되어 있으면, doctor는 모델 참조를 +카탈로그 및 허용 목록과 대조해 검증하고, 해결되지 않거나 허용되지 않으면 경고합니다. ### 7) 샌드박스 이미지 복구 -샌드박싱이 활성화되어 있으면 doctor는 Docker 이미지를 확인하고 -현재 이미지가 없을 때 빌드하거나 레거시 이름으로 전환할지 제안합니다. +샌드박싱이 활성화된 경우, doctor는 Docker 이미지를 점검하고 현재 이미지가 없으면 +빌드하거나 기존 이름으로 전환할 것을 제안합니다. ### 7b) 번들 plugin 런타임 의존성 -Doctor는 번들 plugin 런타임 의존성(예: Discord plugin 런타임 패키지)이 -OpenClaw 설치 루트에 존재하는지 확인합니다. +Doctor는 번들 plugin 런타임 의존성(예: +Discord plugin 런타임 패키지)이 OpenClaw 설치 루트에 존재하는지 확인합니다. 누락된 항목이 있으면 doctor는 해당 패키지를 보고하고 `openclaw doctor --fix` / `openclaw doctor --repair` 모드에서 설치합니다. ### 8) Gateway 서비스 마이그레이션 및 정리 힌트 -Doctor는 레거시 gateway 서비스(launchd/systemd/schtasks)를 감지하고 -이를 제거한 뒤 현재 gateway 포트를 사용해 OpenClaw 서비스를 설치할지 제안합니다. -추가적인 gateway 유사 서비스도 검사하고 정리 힌트를 출력할 수 있습니다. -프로필 이름이 지정된 OpenClaw gateway 서비스는 1급 대상으로 간주되며 "추가"로 표시되지 않습니다. +Doctor는 기존 gateway 서비스(launchd/systemd/schtasks)를 감지하고 +이를 제거한 뒤 현재 gateway +포트를 사용하는 OpenClaw 서비스를 설치할 것을 제안합니다. 또한 추가 gateway 유사 서비스를 검사하여 정리 힌트를 출력할 수 있습니다. +프로필 이름이 붙은 OpenClaw gateway 서비스는 정식 항목으로 간주되며 "추가"로 표시되지 않습니다. -### 8b) 시작 시 Matrix 마이그레이션 +### 8b) 시작 Matrix 마이그레이션 -Matrix 채널 계정에 보류 중이거나 처리 가능한 레거시 상태 마이그레이션이 있으면, -doctor(`--fix` / `--repair` 모드)는 먼저 마이그레이션 전 스냅샷을 만든 다음 -최선의 노력 기준 마이그레이션 단계를 실행합니다: 레거시 Matrix 상태 마이그레이션 및 -레거시 암호화 상태 준비. 두 단계 모두 치명적이지 않으며, 오류는 로그에 기록되고 -시작은 계속됩니다. 읽기 전용 모드(`--fix` 없는 `openclaw doctor`)에서는 이 검사를 -완전히 건너뜁니다. +Matrix 채널 계정에 보류 중이거나 실행 가능한 기존 상태 마이그레이션이 있으면, +doctor는(`--fix` / `--repair` 모드에서) 마이그레이션 전 스냅샷을 생성한 다음 +최선형 마이그레이션 단계를 실행합니다: 기존 Matrix 상태 마이그레이션과 기존 +암호화 상태 준비. 두 단계 모두 치명적이지 않으며, 오류는 기록되고 +시작은 계속됩니다. 읽기 전용 모드(`--fix` 없는 `openclaw doctor`)에서는 이 점검이 +완전히 건너뛰어집니다. ### 9) 보안 경고 -Doctor는 provider가 allowlist 없이 DM에 열려 있거나, +Doctor는 provider가 허용 목록 없이 DM에 열려 있거나, 정책이 위험한 방식으로 구성된 경우 경고를 출력합니다. ### 10) systemd linger(Linux) -systemd 사용자 서비스로 실행 중이면 doctor는 로그아웃 후에도 -gateway가 계속 살아 있도록 lingering이 활성화되어 있는지 확인합니다. +systemd 사용자 서비스로 실행 중인 경우, doctor는 로그아웃 후에도 +gateway가 계속 실행되도록 linger가 활성화되어 있는지 확인합니다. -### 11) 워크스페이스 상태(Skills, plugins 및 레거시 디렉터리) +### 11) Workspace 상태(Skills, plugins, 기존 디렉터리) -Doctor는 기본 agent의 워크스페이스 상태 요약을 출력합니다: +Doctor는 기본 agent에 대한 workspace 상태 요약을 출력합니다. -- **Skills 상태**: 적격, 요구 사항 누락, allowlist 차단된 skill 수를 집계합니다. -- **레거시 워크스페이스 디렉터리**: 현재 워크스페이스와 함께 `~/openclaw` 또는 기타 레거시 워크스페이스 디렉터리가 +- **Skills 상태**: 적격, 요구 사항 누락, 허용 목록 차단된 skills 수를 집계합니다. +- **기존 workspace 디렉터리**: 현재 workspace와 함께 `~/openclaw` 또는 기타 기존 workspace 디렉터리가 존재하면 경고합니다. -- **Plugin 상태**: 로드됨/비활성/오류 plugin 수를 집계하고, 오류가 있는 경우 plugin ID를 나열하며, - 번들 plugin 기능을 보고합니다. -- **Plugin 호환성 경고**: 현재 런타임과 호환성 문제가 있는 plugin을 표시합니다. -- **Plugin 진단**: plugin 레지스트리가 로드 시점에 출력한 경고 또는 오류를 노출합니다. +- **Plugin 상태**: 로드됨/비활성화됨/오류 plugin 수를 집계하고, 오류가 있는 경우 plugin ID를 나열하며, + 번들 plugin capability를 보고합니다. +- **Plugin 호환성 경고**: 현재 런타임과 호환성 문제가 있는 plugins를 표시합니다. +- **Plugin 진단**: plugin registry가 + 로드 시 출력한 경고나 오류를 표시합니다. -### 11b) Bootstrap 파일 크기 +### 11b) 부트스트랩 파일 크기 -Doctor는 워크스페이스 bootstrap 파일(예: `AGENTS.md`, -`CLAUDE.md` 또는 기타 주입된 context 파일)이 구성된 -문자 수 예산에 근접했거나 초과했는지 검사합니다. 파일별 원본 대비 주입 문자 수, 잘림 -비율, 잘림 원인(`max/file` 또는 `max/total`), 그리고 전체 예산 대비 총 주입 문자 수를 -보고합니다. 파일이 잘렸거나 한계에 근접하면 doctor는 -`agents.defaults.bootstrapMaxChars` +Doctor는 workspace 부트스트랩 파일(예: `AGENTS.md`, +`CLAUDE.md`, 또는 기타 주입된 컨텍스트 파일)이 구성된 +문자 예산에 근접했거나 초과했는지 점검합니다. 파일별 원본 문자 수 대 주입 문자 수, 잘림 +비율, 잘림 원인(`max/file` 또는 `max/total`), 그리고 전체 예산 대비 총 주입 +문자 수를 비율로 보고합니다. 파일이 잘렸거나 한계에 근접한 경우, +doctor는 `agents.defaults.bootstrapMaxChars` 및 `agents.defaults.bootstrapTotalMaxChars` 조정을 위한 팁을 출력합니다. -### 11c) 셸 completion +### 11c) 셸 자동 완성 -Doctor는 현재 셸에 tab completion이 설치되어 있는지 검사합니다 -(zsh, bash, fish 또는 PowerShell): +Doctor는 현재 셸에 대해 탭 자동 완성이 설치되어 있는지 점검합니다 +(zsh, bash, fish, 또는 PowerShell). -- 셸 프로필이 느린 동적 completion 패턴 - (`source <(openclaw completion ...)`)을 사용하면, doctor는 이를 더 빠른 +- 셸 프로필이 느린 동적 자동 완성 패턴을 사용하는 경우 + (`source <(openclaw completion ...)`), doctor는 이를 더 빠른 캐시 파일 변형으로 업그레이드합니다. -- 프로필에 completion이 구성되어 있지만 캐시 파일이 없으면, +- 프로필에 자동 완성이 구성되어 있지만 캐시 파일이 없으면, doctor는 캐시를 자동으로 다시 생성합니다. -- completion이 전혀 구성되어 있지 않으면, doctor는 설치를 제안합니다 - (대화형 모드 전용, `--non-interactive`에서는 건너뜀). +- 자동 완성이 전혀 구성되어 있지 않으면, doctor는 설치를 제안합니다 + (대화형 모드에서만, `--non-interactive`에서는 건너뜀). 캐시를 수동으로 다시 생성하려면 `openclaw completion --write-state`를 실행하세요. -### 12) Gateway 인증 검사(로컬 토큰) +### 12) Gateway 인증 점검(로컬 토큰) -Doctor는 로컬 gateway 토큰 인증 준비 상태를 검사합니다. +Doctor는 로컬 gateway 토큰 인증 준비 상태를 점검합니다. -- 토큰 모드에 토큰이 필요하지만 토큰 소스가 없으면 doctor는 토큰 생성을 제안합니다. -- `gateway.auth.token`이 SecretRef로 관리되지만 사용할 수 없으면 doctor는 경고하고 일반 텍스트로 덮어쓰지 않습니다. -- `openclaw doctor --generate-gateway-token`은 token SecretRef가 구성되지 않은 경우에만 생성을 강제합니다. +- 토큰 모드에 토큰이 필요하고 토큰 소스가 없으면, doctor는 토큰 생성을 제안합니다. +- `gateway.auth.token`이 SecretRef로 관리되지만 사용할 수 없으면, doctor는 경고하고 평문으로 덮어쓰지 않습니다. +- `openclaw doctor --generate-gateway-token`은 토큰 SecretRef가 구성되지 않았을 때만 강제로 생성합니다. ### 12b) 읽기 전용 SecretRef 인식 복구 -일부 복구 흐름은 런타임 fail-fast 동작을 약화시키지 않고 구성된 자격 증명을 검사해야 합니다. +일부 복구 흐름은 런타임 fail-fast 동작을 약화시키지 않으면서 +구성된 자격 증명을 검사해야 합니다. -- `openclaw doctor --fix`는 이제 상태 계열 명령과 동일한 읽기 전용 SecretRef 요약 모델을 사용해 대상 config 복구를 수행합니다. -- 예: Telegram `allowFrom` / `groupAllowFrom` `@username` 복구는 가능한 경우 구성된 봇 자격 증명을 사용하려고 시도합니다. -- Telegram 봇 토큰이 SecretRef를 통해 구성되어 있지만 현재 명령 경로에서 사용할 수 없으면, doctor는 자격 증명이 구성되었지만 현재 사용할 수 없다고 보고하고, 충돌하거나 토큰이 누락되었다고 잘못 보고하는 대신 자동 확인을 건너뜁니다. +- `openclaw doctor --fix`는 이제 대상 config 복구를 위해 상태 계열 명령과 동일한 읽기 전용 SecretRef 요약 모델을 사용합니다. +- 예: Telegram `allowFrom` / `groupAllowFrom` `@username` 복구는 가능하면 구성된 bot 자격 증명을 사용하려고 시도합니다. +- Telegram bot 토큰이 SecretRef를 통해 구성되었지만 현재 명령 경로에서 사용할 수 없으면, doctor는 해당 자격 증명이 구성되었지만 사용할 수 없다고 보고하고, 충돌하거나 토큰이 누락된 것으로 잘못 보고하는 대신 자동 해결을 건너뜁니다. ### 13) Gateway 상태 점검 + 재시작 Doctor는 상태 점검을 실행하고 gateway가 -비정상으로 보이면 재시작을 제안합니다. +정상적이지 않아 보이면 재시작을 제안합니다. ### 13b) 메모리 검색 준비 상태 -Doctor는 구성된 메모리 검색 임베딩 provider가 기본 -agent에 대해 준비되었는지 확인합니다. 동작은 구성된 백엔드와 provider에 따라 다릅니다: +Doctor는 구성된 메모리 검색 임베딩 provider가 +기본 agent에 대해 준비되어 있는지 점검합니다. 동작은 구성된 백엔드와 provider에 따라 달라집니다. -- **QMD 백엔드**: `qmd` 바이너리가 사용 가능하고 시작 가능한지 프로브합니다. - 그렇지 않으면 npm 패키지와 수동 바이너리 경로 옵션을 포함한 해결 안내를 출력합니다. +- **QMD 백엔드**: `qmd` 바이너리를 사용할 수 있고 시작 가능한지 프로브합니다. + 그렇지 않으면 npm 패키지 및 수동 바이너리 경로 옵션을 포함한 수정 안내를 출력합니다. - **명시적 로컬 provider**: 로컬 모델 파일 또는 인식 가능한 - 원격/다운로드 가능한 모델 URL이 있는지 확인합니다. 없으면 원격 provider로 전환하라고 제안합니다. -- **명시적 원격 provider** (`openai`, `voyage` 등): 환경 또는 인증 저장소에 - API 키가 있는지 검증합니다. 누락된 경우 실행 가능한 해결 힌트를 출력합니다. -- **자동 provider**: 먼저 로컬 모델 가용성을 확인한 다음 자동 선택 순서대로 - 각 원격 provider를 시도합니다. + 원격/다운로드 가능한 모델 URL이 있는지 점검합니다. 없으면 원격 provider로 전환할 것을 제안합니다. +- **명시적 원격 provider** (`openai`, `voyage` 등): API 키가 + 환경 변수 또는 인증 저장소에 있는지 확인합니다. 없으면 실행 가능한 수정 힌트를 출력합니다. +- **자동 provider**: 먼저 로컬 모델 가용성을 점검한 다음, 자동 선택 순서대로 각 원격 + provider를 시도합니다. -gateway 프로브 결과를 사용할 수 있는 경우(검사 시점에 gateway가 정상 상태였음), -doctor는 그 결과를 CLI에서 보이는 config와 교차 참조하고 -불일치가 있으면 알려줍니다. +gateway 프로브 결과를 사용할 수 있는 경우(gateway가 점검 시점에 정상적이었던 경우), +doctor는 이를 CLI에서 보이는 config와 교차 확인하고 +불일치를 알려줍니다. 런타임에서 임베딩 준비 상태를 확인하려면 `openclaw memory status --deep`를 사용하세요. ### 14) 채널 상태 경고 -gateway가 정상 상태이면 doctor는 채널 상태 프로브를 실행하고 -권장 해결 방법과 함께 경고를 보고합니다. +gateway가 정상적이면, doctor는 채널 상태 프로브를 실행하고 +권장 수정과 함께 경고를 보고합니다. ### 15) Supervisor config 감사 + 복구 -Doctor는 설치된 supervisor config(launchd/systemd/schtasks)를 검사해 -누락되었거나 오래된 기본값(예: systemd network-online 의존성과 -재시작 지연)이 있는지 확인합니다. 불일치를 찾으면 -업데이트를 권장하고 현재 기본값으로 서비스 파일/작업을 다시 쓸 수 있습니다. +Doctor는 설치된 supervisor config(launchd/systemd/schtasks)를 점검하여 +누락되었거나 오래된 기본값(예: systemd network-online 의존성 및 +재시작 지연)을 찾습니다. 불일치를 발견하면 +업데이트를 권장하고 서비스 파일/작업을 현재 기본값으로 다시 쓸 수 있습니다. 참고: - `openclaw doctor`는 supervisor config를 다시 쓰기 전에 프롬프트를 표시합니다. - `openclaw doctor --yes`는 기본 복구 프롬프트를 수락합니다. -- `openclaw doctor --repair`는 프롬프트 없이 권장 수정 사항을 적용합니다. +- `openclaw doctor --repair`는 프롬프트 없이 권장 수정을 적용합니다. - `openclaw doctor --repair --force`는 사용자 지정 supervisor config를 덮어씁니다. -- 토큰 인증에 토큰이 필요하고 `gateway.auth.token`이 SecretRef로 관리되는 경우, doctor 서비스 설치/복구는 SecretRef를 검증하지만 해결된 일반 텍스트 토큰 값을 supervisor 서비스 환경 메타데이터에 유지하지 않습니다. -- 토큰 인증에 토큰이 필요하고 구성된 token SecretRef가 해결되지 않으면, doctor는 실행 가능한 안내와 함께 설치/복구 경로를 차단합니다. -- `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있고 `gateway.auth.mode`가 설정되지 않은 경우, doctor는 mode가 명시적으로 설정될 때까지 설치/복구를 차단합니다. -- Linux user-systemd unit의 경우, doctor 토큰 드리프트 검사는 이제 서비스 인증 메타데이터를 비교할 때 `Environment=` 및 `EnvironmentFile=` 소스를 모두 포함합니다. -- 언제든 `openclaw gateway install --force`를 통해 전체 다시 쓰기를 강제할 수 있습니다. +- 토큰 인증에 토큰이 필요하고 `gateway.auth.token`이 SecretRef로 관리되는 경우, doctor 서비스 설치/복구는 SecretRef를 검증하지만 해결된 평문 토큰 값을 supervisor 서비스 환경 메타데이터에 저장하지 않습니다. +- 토큰 인증에 토큰이 필요하고 구성된 토큰 SecretRef가 해결되지 않으면, doctor는 실행 가능한 안내와 함께 설치/복구 경로를 차단합니다. +- `gateway.auth.token`과 `gateway.auth.password`가 모두 구성되어 있는데 `gateway.auth.mode`가 설정되지 않으면, doctor는 모드가 명시적으로 설정될 때까지 설치/복구를 차단합니다. +- Linux user-systemd 유닛의 경우, doctor 토큰 드리프트 점검은 이제 서비스 인증 메타데이터 비교 시 `Environment=`와 `EnvironmentFile=` 소스를 모두 포함합니다. +- 언제든지 `openclaw gateway install --force`로 전체 다시 쓰기를 강제할 수 있습니다. ### 16) Gateway 런타임 + 포트 진단 Doctor는 서비스 런타임(PID, 마지막 종료 상태)을 검사하고, -서비스가 설치되어 있지만 실제로 실행 중이 아니면 경고합니다. 또한 gateway 포트 -(기본값 `18789`)의 포트 충돌을 확인하고 가능한 원인(gateway가 이미 실행 중, SSH 터널)을 보고합니다. +서비스는 설치되었지만 실제로 실행 중이 아닐 때 경고합니다. 또한 gateway 포트(기본값 `18789`)의 +포트 충돌을 점검하고 가능한 원인(gateway가 이미 실행 중, SSH 터널)을 보고합니다. ### 17) Gateway 런타임 모범 사례 -Doctor는 gateway 서비스가 Bun 또는 버전 관리된 Node 경로 -(`nvm`, `fnm`, `volta`, `asdf` 등)에서 실행 중이면 경고합니다. WhatsApp + Telegram 채널은 Node가 필요하며, -버전 관리자 경로는 서비스가 셸 초기화를 로드하지 않기 때문에 업그레이드 후 깨질 수 있습니다. -시스템 Node 설치가 가능하면(Homebrew/apt/choco) 해당 설치로 마이그레이션할지 제안합니다. +Doctor는 gateway 서비스가 Bun 또는 버전 관리형 Node 경로 +(`nvm`, `fnm`, `volta`, `asdf` 등)에서 실행될 때 경고합니다. WhatsApp + Telegram 채널은 Node를 필요로 하며, +버전 관리자 경로는 서비스가 셸 초기화 스크립트를 로드하지 않기 때문에 업그레이드 후 깨질 수 있습니다. +사용 가능한 경우, doctor는 시스템 Node 설치(Homebrew/apt/choco)로 마이그레이션할 것을 제안합니다. -### 18) Config 쓰기 + wizard 메타데이터 +### 18) Config 기록 + wizard 메타데이터 -Doctor는 모든 config 변경 사항을 저장하고 -doctor 실행을 기록하기 위해 wizard 메타데이터를 남깁니다. +Doctor는 모든 config 변경 사항을 저장하고 doctor 실행을 기록하기 위해 +wizard 메타데이터를 기록합니다. -### 19) 워크스페이스 팁(백업 + 메모리 시스템) +### 19) Workspace 팁(백업 + 메모리 시스템) -Doctor는 누락된 경우 워크스페이스 메모리 시스템을 제안하고, -워크스페이스가 아직 git 아래에 없으면 백업 팁을 출력합니다. +Doctor는 workspace 메모리 시스템이 없으면 이를 제안하고, workspace가 아직 git 아래에 있지 않으면 +백업 팁을 출력합니다. -워크스페이스 구조와 git 백업(권장: 비공개 GitHub 또는 GitLab)에 대한 전체 가이드는 +workspace 구조와 git 백업(권장: 비공개 GitHub 또는 GitLab)에 대한 전체 가이드는 [/concepts/agent-workspace](/ko/concepts/agent-workspace)를 참조하세요. diff --git a/docs/ko/help/testing.md b/docs/ko/help/testing.md index 570787f66..35e96eac7 100644 --- a/docs/ko/help/testing.md +++ b/docs/ko/help/testing.md @@ -1,15 +1,15 @@ --- read_when: - - 로컬 또는 CI에서 테스트를 실행하는 경우 - - 모델/프로바이더 버그에 대한 회귀 테스트를 추가하는 경우 - - gateway + agent 동작을 디버깅하는 경우 -summary: '테스트 키트: unit/e2e/live 스위트, Docker 러너, 그리고 각 테스트가 다루는 내용' + - 로컬 또는 CI에서 테스트를 실행할 때 + - 모델/provider 버그에 대한 회귀 테스트를 추가할 때 + - gateway + agent 동작을 디버깅할 때 +summary: '테스트 키트: unit/e2e/live 스위트, Docker 러너, 그리고 각 테스트의 커버 범위' title: 테스트 x-i18n: - generated_at: "2026-04-08T02:18:23Z" + generated_at: "2026-04-09T01:30:42Z" model: gpt-5.4 provider: openai - source_hash: ace2c19bfc350780475f4348264a4b55be2b4ccbb26f0d33b4a6af34510943b5 + source_hash: 01117f41d8b171a4f1da11ed78486ee700e70ae70af54eb6060c57baf64ab21b source_path: help/testing.md workflow: 15 --- @@ -18,242 +18,244 @@ x-i18n: OpenClaw에는 세 가지 Vitest 스위트(unit/integration, e2e, live)와 소수의 Docker 러너가 있습니다. -이 문서는 “우리가 어떻게 테스트하는지”에 대한 가이드입니다: +이 문서는 "우리가 테스트하는 방식"에 대한 가이드입니다: -- 각 스위트가 다루는 내용(그리고 의도적으로 _다루지 않는_ 내용) -- 일반적인 워크플로(로컬, 푸시 전, 디버깅)에 어떤 명령을 실행해야 하는지 -- live 테스트가 자격 증명을 어떻게 찾고 모델/프로바이더를 어떻게 선택하는지 -- 실제 모델/프로바이더 이슈에 대한 회귀 테스트를 추가하는 방법 +- 각 스위트가 무엇을 커버하는지(그리고 의도적으로 무엇을 커버하지 않는지) +- 일반적인 워크플로(로컬, push 전, 디버깅)에서 어떤 명령을 실행해야 하는지 +- live 테스트가 자격 증명을 어떻게 찾고 모델/provider를 어떻게 선택하는지 +- 실제 모델/provider 이슈에 대한 회귀 테스트를 추가하는 방법 ## 빠른 시작 -대부분의 날에는: +대부분의 날에는 다음을 사용하세요: -- 전체 게이트(푸시 전 기대값): `pnpm build && pnpm check && pnpm test` +- 전체 게이트(push 전에 예상됨): `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` +- 이제 직접 파일 타기팅은 extension/channel 경로도 라우팅합니다: `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` - Docker 기반 QA 사이트: `pnpm qa:lab:up` -테스트를 건드렸거나 추가 확신이 필요할 때: +테스트를 수정했거나 추가 확신이 필요할 때: - 커버리지 게이트: `pnpm test:coverage` - E2E 스위트: `pnpm test:e2e` -실제 프로바이더/모델을 디버깅할 때(실제 자격 증명 필요): +실제 providers/models를 디버깅할 때(실제 자격 증명 필요): -- Live 스위트(모델 + gateway tool/image 프로브): `pnpm test:live` -- 하나의 live 파일만 조용히 대상으로 지정: `pnpm test:live -- src/agents/models.profiles.live.test.ts` +- live 스위트(모델 + gateway 도구/이미지 probe): `pnpm test:live` +- 하나의 live 파일만 조용히 타기팅: `pnpm test:live -- src/agents/models.profiles.live.test.ts` -팁: 실패하는 사례 하나만 필요할 때는 아래에 설명된 allowlist 환경 변수를 사용해 live 테스트를 좁히는 편이 좋습니다. +팁: 실패하는 케이스 하나만 필요할 때는 아래에 설명된 allowlist 환경 변수를 사용해 live 테스트 범위를 좁히는 방식을 우선 사용하세요. ## 테스트 스위트(무엇이 어디서 실행되는가) -스위트를 “현실성이 점점 높아지는” 순서로 생각하면 됩니다(그리고 불안정성/비용도 점점 증가): +스위트는 "현실성이 높아지는 순서"(그리고 변동성/비용도 높아지는 순서)로 생각하면 됩니다: ### Unit / integration(기본값) -- 명령: `pnpm test` -- Config: 기존 범위별 Vitest 프로젝트에 대한 10개의 순차 샤드 실행(`vitest.full-*.config.ts`) -- 파일: `src/**/*.test.ts`, `packages/**/*.test.ts`, `test/**/*.test.ts`, 그리고 `vitest.unit.config.ts`가 다루는 화이트리스트된 `ui` node 테스트 아래의 core/unit 인벤토리 +- 명령어: `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 테스트 - 범위: - 순수 unit 테스트 - - 프로세스 내 integration 테스트(gateway auth, 라우팅, tooling, 파싱, config) + - 프로세스 내 integration 테스트(gateway auth, routing, tooling, parsing, config) - 알려진 버그에 대한 결정적 회귀 테스트 - 기대 사항: - CI에서 실행됨 - 실제 키 불필요 - 빠르고 안정적이어야 함 - 프로젝트 참고: - - 타기팅하지 않은 `pnpm test`는 이제 하나의 거대한 네이티브 루트 프로젝트 프로세스 대신 11개의 더 작은 샤드 config(`core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-support-boundary`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`)를 실행합니다. 이렇게 하면 부하가 걸린 머신에서 최대 RSS를 줄이고 auto-reply/extension 작업이 관련 없는 스위트를 굶기지 않게 합니다. - - `pnpm test --watch`는 멀티 샤드 watch 루프가 실용적이지 않기 때문에 여전히 네이티브 루트 `vitest.config.ts` 프로젝트 그래프를 사용합니다. - - `pnpm test`, `pnpm test:watch`, `pnpm test:perf:imports`는 명시적 파일/디렉터리 타깃을 먼저 범위별 레인으로 라우팅하므로, `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts`는 전체 루트 프로젝트 시작 비용을 치르지 않습니다. - - `pnpm test:changed`는 diff가 라우팅 가능한 소스/테스트 파일만 건드린 경우 변경된 git 경로를 동일한 범위별 레인으로 확장합니다. config/setup 편집은 여전히 넓은 루트 프로젝트 재실행으로 폴백합니다. - - 선택된 `plugin-sdk` 및 `commands` 테스트도 `test/setup-openclaw-runtime.ts`를 건너뛰는 전용 경량 레인으로 라우팅되며, 상태가 있거나 런타임이 무거운 파일은 기존 레인에 남습니다. - - 선택된 `plugin-sdk` 및 `commands` 헬퍼 소스 파일도 변경 모드 실행 시 같은 경량 레인의 명시적 형제 테스트로 매핑되므로, 헬퍼 편집이 해당 디렉터리 전체의 무거운 스위트를 재실행하지 않도록 합니다. - - `auto-reply`는 이제 세 개의 전용 버킷을 가집니다: 최상위 core 헬퍼, 최상위 `reply.*` integration 테스트, 그리고 `src/auto-reply/reply/**` 하위 트리. 이렇게 하면 가장 무거운 reply 하니스 작업이 저렴한 status/chunk/token 테스트에 영향을 주지 않습니다. + - 타기팅하지 않은 `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 테스트에 영향을 주지 않습니다. - 임베디드 러너 참고: - - 메시지-tool discovery 입력이나 compaction 런타임 컨텍스트를 변경할 때는 + - 메시지 도구 탐색 입력이나 compaction 런타임 컨텍스트를 변경할 때는 두 수준의 커버리지를 모두 유지하세요. - - 순수 라우팅/정규화 경계를 위한 집중 헬퍼 회귀 테스트를 추가하세요. - - 또한 임베디드 러너 integration 스위트도 정상 상태로 유지하세요: + - 순수 routing/normalization 경계를 위한 집중된 helper 회귀 테스트를 추가하세요. + - 또한 임베디드 러너 integration 스위트도 정상 상태를 유지하세요: `src/agents/pi-embedded-runner/compact.hooks.test.ts`, `src/agents/pi-embedded-runner/run.overflow-compaction.test.ts`, 그리고 `src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`. - - 이 스위트들은 범위 지정된 id와 compaction 동작이 실제 - `run.ts` / `compact.ts` 경로를 통해 계속 흐르는지를 검증합니다. 헬퍼 전용 테스트만으로는 - 이러한 integration 경로를 충분히 대체할 수 없습니다. + - 이 스위트들은 scoped id와 compaction 동작이 여전히 실제 + `run.ts` / `compact.ts` 경로를 통해 흐르는지 검증합니다. helper 전용 테스트는 + 이 integration 경로를 대체하기에 충분하지 않습니다. - 풀 참고: - - 기본 Vitest config는 이제 기본적으로 `threads`를 사용합니다. - - 공유 Vitest config는 또한 `isolate: false`를 고정하고 루트 프로젝트, e2e, live config 전체에서 비격리 러너를 사용합니다. - - 루트 UI 레인은 `jsdom` 설정과 optimizer를 유지하지만, 이제 공유 비격리 러너에서도 실행됩니다. - - 각 `pnpm test` 샤드는 공유 Vitest config에서 동일한 `threads` + `isolate: false` 기본값을 상속합니다. - - 공유 `scripts/run-vitest.mjs` 런처는 이제 Vitest 자식 Node 프로세스에 기본적으로 `--no-maglev`도 추가해 대규모 로컬 실행 중 V8 컴파일 변동을 줄입니다. 기본 V8 동작과 비교해야 한다면 `OPENCLAW_VITEST_ENABLE_MAGLEV=1`을 설정하세요. + - 기본 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`을 설정하세요. - 빠른 로컬 반복 참고: - - `pnpm test:changed`는 변경된 경로가 더 작은 스위트로 깔끔하게 매핑될 때 범위별 레인으로 라우팅합니다. - - `pnpm test:max`와 `pnpm test:changed:max`는 동일한 라우팅 동작을 유지하되 워커 상한만 더 높습니다. - - 로컬 워커 자동 스케일링은 이제 의도적으로 더 보수적이며, 호스트 load average가 이미 높을 때도 자동으로 물러서므로 여러 개의 동시 Vitest 실행이 기본적으로 덜 해롭습니다. - - 기본 Vitest config는 프로젝트/config 파일을 `forceRerunTriggers`로 표시하므로 테스트 배선이 변경될 때 changed 모드 재실행의 정확성이 유지됩니다. - - 이 config는 지원되는 호스트에서 `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 최대 RSS를 출력합니다. -- `pnpm test:perf:changed:bench -- --worktree`는 현재 더티 트리를 기준으로 변경된 파일 목록을 `scripts/test-projects.mjs`와 루트 Vitest config를 통해 라우팅하여 벤치마크합니다. + - `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:perf:profile:main`은 Vitest/Vite 시작 및 transform 오버헤드에 대한 메인 스레드 CPU 프로파일을 기록합니다. - - `pnpm test:perf:profile:runner`는 파일 병렬화를 비활성화한 상태에서 unit 스위트의 러너 CPU+heap 프로파일을 기록합니다. + - `pnpm test:perf:profile:runner`는 unit 스위트에 대해 파일 병렬화를 비활성화한 상태에서 러너 CPU+힙 프로파일을 기록합니다. ### E2E(gateway 스모크) -- 명령: `pnpm test:e2e` -- Config: `vitest.e2e.config.ts` +- 명령어: `pnpm test:e2e` +- 구성: `vitest.e2e.config.ts` - 파일: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts` - 런타임 기본값: - - 저장소의 나머지 부분과 동일하게 Vitest `threads`와 `isolate: false`를 사용합니다. - - 적응형 워커를 사용합니다(CI: 최대 2, 로컬: 기본 1). - - 콘솔 I/O 오버헤드를 줄이기 위해 기본적으로 silent 모드로 실행합니다. -- 유용한 override: - - `OPENCLAW_E2E_WORKERS=`으로 워커 수 강제 지정(상한 16). - - `OPENCLAW_E2E_VERBOSE=1`로 자세한 콘솔 출력 재활성화. + - 저장소 나머지와 동일하게 Vitest `threads`와 `isolate: false`를 사용합니다. + - 적응형 worker를 사용합니다(CI: 최대 2, 로컬: 기본 1). + - 콘솔 I/O 오버헤드를 줄이기 위해 기본적으로 silent 모드로 실행됩니다. +- 유용한 재정의: + - worker 수를 강제하려면 `OPENCLAW_E2E_WORKERS=`(최대 16) + - 자세한 콘솔 출력을 다시 활성화하려면 `OPENCLAW_E2E_VERBOSE=1` - 범위: - - 다중 인스턴스 gateway 종단 간 동작 - - WebSocket/HTTP 표면, node pairing, 그리고 더 무거운 네트워킹 + - 다중 인스턴스 gateway end-to-end 동작 + - WebSocket/HTTP 표면, 노드 페어링, 더 무거운 네트워킹 - 기대 사항: - CI에서 실행됨(파이프라인에서 활성화된 경우) - 실제 키 불필요 - - unit 테스트보다 움직이는 부분이 더 많음(더 느릴 수 있음) + - unit 테스트보다 더 많은 이동 부품이 있음(더 느릴 수 있음) ### E2E: OpenShell 백엔드 스모크 -- 명령: `pnpm test:e2e:openshell` +- 명령어: `pnpm test:e2e:openshell` - 파일: `test/openshell-sandbox.e2e.test.ts` - 범위: - Docker를 통해 호스트에서 격리된 OpenShell gateway를 시작 - - 임시 로컬 Dockerfile에서 sandbox 생성 + - 임시 로컬 Dockerfile에서 샌드박스를 생성 - 실제 `sandbox ssh-config` + SSH exec를 통해 OpenClaw의 OpenShell 백엔드를 실행 - - sandbox fs bridge를 통한 원격 canonical filesystem 동작 검증 + - 샌드박스 fs 브리지를 통해 원격 표준 파일시스템 동작을 검증 - 기대 사항: - - 옵트인 전용, 기본 `pnpm test:e2e` 실행에는 포함되지 않음 - - 로컬 `openshell` CLI와 정상 동작하는 Docker daemon 필요 - - 격리된 `HOME` / `XDG_CONFIG_HOME`을 사용한 뒤 테스트 gateway와 sandbox를 삭제 -- 유용한 override: - - 더 넓은 e2e 스위트를 수동으로 실행할 때 이 테스트를 활성화하려면 `OPENCLAW_E2E_OPENSHELL=1` - - 기본이 아닌 CLI 바이너리나 wrapper script를 가리키려면 `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` + - 옵트인 전용이며 기본 `pnpm test:e2e` 실행에는 포함되지 않음 + - 로컬 `openshell` CLI와 동작하는 Docker 데몬 필요 + - 격리된 `HOME` / `XDG_CONFIG_HOME`을 사용한 뒤 테스트 gateway와 샌드박스를 제거함 +- 유용한 재정의: + - 더 넓은 e2e 스위트를 수동 실행할 때 테스트를 활성화하려면 `OPENCLAW_E2E_OPENSHELL=1` + - 기본이 아닌 CLI 바이너리나 wrapper 스크립트를 지정하려면 `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` -### Live(실제 프로바이더 + 실제 모델) +### Live(실제 providers + 실제 모델) -- 명령: `pnpm test:live` -- Config: `vitest.live.config.ts` +- 명령어: `pnpm test:live` +- 구성: `vitest.live.config.ts` - 파일: `src/**/*.live.test.ts` -- 기본값: `pnpm test:live`가 **활성화**함(`OPENCLAW_LIVE_TEST=1` 설정) +- 기본값: `pnpm test:live`에 의해 **활성화됨**(`OPENCLAW_LIVE_TEST=1` 설정) - 범위: - - “이 프로바이더/모델이 _오늘_ 실제 자격 증명으로 실제로 작동하는가?” - - 프로바이더 형식 변경, tool-calling 특이점, auth 이슈, rate limit 동작 탐지 + - "이 provider/model이 오늘 실제 자격 증명으로 정말 동작하는가?" + - provider 포맷 변경, tool-calling 특이사항, auth 이슈, rate limit 동작 포착 - 기대 사항: - - 설계상 CI 안정적이지 않음(실제 네트워크, 실제 프로바이더 정책, 쿼터, 장애) - - 비용이 들고 / rate limit를 사용함 - - “전부”보다 범위를 좁힌 부분집합 실행을 선호 -- Live 실행은 누락된 API 키를 가져오기 위해 `~/.profile`을 source합니다. + - 설계상 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 잡음은 음소거합니다. 전체 시작 로그를 다시 보려면 `OPENCLAW_LIVE_TEST_QUIET=0`을 설정하세요. -- API 키 로테이션(프로바이더별): 쉼표/세미콜론 형식의 `*_API_KEYS` 또는 `*_API_KEY_1`, `*_API_KEY_2`(예: `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`)를 설정하거나, live별 override로 `OPENCLAW_LIVE_*_KEY`를 설정하세요. 테스트는 rate limit 응답 시 재시도합니다. -- 진행/하트비트 출력: - - Live 스위트는 이제 stderr로 진행 라인을 출력하므로, Vitest 콘솔 캡처가 조용하더라도 긴 프로바이더 호출이 눈에 띄게 활성 상태로 보입니다. - - `vitest.live.config.ts`는 Vitest 콘솔 가로채기를 비활성화하므로 프로바이더/gateway 진행 라인이 live 실행 중 즉시 스트리밍됩니다. - - 직접 모델 하트비트는 `OPENCLAW_LIVE_HEARTBEAT_MS`로 조정하세요. - - gateway/프로브 하트비트는 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS`로 조정하세요. +- 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`로 조정합니다. ## 어떤 스위트를 실행해야 하나요? -다음 의사결정 표를 사용하세요: +다음 결정 표를 사용하세요: -- 로직/테스트를 편집하는 경우: `pnpm test` 실행(많이 바꿨다면 `pnpm test:coverage`도) -- gateway 네트워킹 / WS 프로토콜 / pairing을 건드리는 경우: `pnpm test:e2e` 추가 -- “내 봇이 다운됨” / 프로바이더별 실패 / tool calling을 디버깅하는 경우: 범위를 좁힌 `pnpm test:live` 실행 +- 로직/테스트 수정: `pnpm test` 실행(많이 변경했다면 `pnpm test:coverage`도) +- gateway 네트워킹 / WS 프로토콜 / 페어링 수정: `pnpm test:e2e` 추가 +- "내 봇이 다운되었다" / provider별 실패 / tool calling 디버깅: 범위를 좁힌 `pnpm test:live` 실행 -## Live: Android node capability 스윕 +## Live: Android 노드 capability 스윕 - 테스트: `src/gateway/android-node.capabilities.live.test.ts` - 스크립트: `pnpm android:test:integration` -- 목표: 연결된 Android node가 현재 광고하는 **모든 명령**을 호출하고 명령 계약 동작을 검증 +- 목표: 연결된 Android 노드가 현재 광고하는 **모든 명령**을 호출하고 명령 계약 동작을 검증 - 범위: - - 사전 조건이 있는 수동 설정(스위트는 앱을 설치/실행/pairing하지 않음) - - 선택된 Android node에 대한 명령별 gateway `node.invoke` 검증 + - 사전 조건이 갖춰진/수동 설정(스위트는 앱을 설치/실행/페어링하지 않음) + - 선택된 Android 노드에 대한 명령별 gateway `node.invoke` 검증 - 필요한 사전 설정: - - Android 앱이 이미 gateway에 연결되고 pairing되어 있어야 함 - - 앱이 foreground에 유지되어야 함 - - 통과를 기대하는 capability에 대해 권한/캡처 동의가 부여되어야 함 -- 선택적 타깃 override: + - Android 앱이 이미 gateway에 연결되고 페어링되어 있어야 함 + - 앱이 foreground 상태로 유지되어야 함 + - 통과하기를 기대하는 capability에 대해 권한/캡처 동의가 부여되어야 함 +- 선택적 타깃 재정의: - `OPENCLAW_ANDROID_NODE_ID` 또는 `OPENCLAW_ANDROID_NODE_NAME` - `OPENCLAW_ANDROID_GATEWAY_URL` / `OPENCLAW_ANDROID_GATEWAY_TOKEN` / `OPENCLAW_ANDROID_GATEWAY_PASSWORD` -- 전체 Android 설정 세부 정보: [Android App](/ko/platforms/android) +- 전체 Android 설정 세부 정보: [Android 앱](/ko/platforms/android) ## Live: 모델 스모크(profile 키) live 테스트는 실패를 분리할 수 있도록 두 계층으로 나뉩니다: -- “직접 모델”은 주어진 키로 프로바이더/모델이 최소한 응답할 수 있는지를 알려줍니다. -- “Gateway 스모크”는 전체 gateway+agent 파이프라인이 해당 모델에 대해 작동하는지를 알려줍니다(세션, 기록, 도구, sandbox 정책 등). +- "직접 모델"은 주어진 키로 provider/model이 최소한 응답할 수 있는지 알려줍니다. +- "Gateway 스모크"는 해당 모델에 대해 전체 gateway+agent 파이프라인이 동작하는지(세션, 히스토리, 도구, 샌드박스 정책 등)를 알려줍니다. -### 계층 1: 직접 모델 completion(gateway 없음) +### 계층 1: 직접 모델 완료(gateway 없음) - 테스트: `src/agents/models.profiles.live.test.ts` - 목표: - 발견된 모델 열거 - `getApiKeyForModel`을 사용해 자격 증명이 있는 모델 선택 - - 모델별 작은 completion 실행(필요한 경우 타깃 회귀 테스트 포함) + - 모델별로 작은 completion 실행(필요시 타깃 회귀 포함) - 활성화 방법: - `pnpm test:live`(또는 Vitest를 직접 호출하는 경우 `OPENCLAW_LIVE_TEST=1`) -- 실제로 이 스위트를 실행하려면 `OPENCLAW_LIVE_MODELS=modern`(또는 `all`, modern의 별칭)을 설정하세요. 그렇지 않으면 `pnpm test:live`를 gateway 스모크 중심으로 유지하기 위해 건너뜁니다. +- 이 스위트를 실제로 실행하려면 `OPENCLAW_LIVE_MODELS=modern`(또는 `all`, modern의 별칭)을 설정하세요. 그렇지 않으면 `pnpm test:live`가 gateway 스모크에 집중되도록 건너뜁니다. - 모델 선택 방법: - - 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의 별칭 + - 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 store와 env 폴백 - - **profile store**만 강제하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 설정 + - 기본값: profile 저장소와 env 폴백 + - **profile 저장소만** 강제하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 설정 - 존재 이유: - - “프로바이더 API가 깨졌음 / 키가 유효하지 않음”과 “gateway agent 파이프라인이 깨졌음”을 분리 - - 작고 고립된 회귀 테스트 포함(예: OpenAI Responses/Codex Responses 추론 재생 + tool-call 흐름) + - "provider API가 망가졌다 / 키가 유효하지 않다"와 "gateway agent 파이프라인이 망가졌다"를 분리 + - 작고 격리된 회귀를 포함(예: OpenAI Responses/Codex Responses reasoning replay + tool-call 플로) -### 계층 2: Gateway + dev agent 스모크(“@openclaw”가 실제로 하는 것) +### 계층 2: Gateway + dev agent 스모크(`@openclaw`가 실제로 하는 것) - 테스트: `src/gateway/gateway-models.profiles.live.test.ts` - 목표: - 프로세스 내 gateway를 시작 - - `agent:dev:*` 세션 생성/패치(실행별 모델 override) - - 키가 있는 모델들을 순회하며 다음을 검증: - - “의미 있는” 응답(도구 없음) - - 실제 도구 호출 작동(read probe) - - 선택적 추가 도구 프로브(exec+read probe) - - OpenAI 회귀 경로(tool-call-only → follow-up)가 계속 작동 -- 프로브 세부 정보(실패를 빠르게 설명할 수 있도록): - - `read` 프로브: 테스트가 workspace에 nonce 파일을 쓰고 에이전트에게 이를 `read`하고 nonce를 다시 말하도록 요청합니다. - - `exec+read` 프로브: 테스트가 에이전트에게 `exec`로 temp 파일에 nonce를 쓴 다음 다시 `read`하게 요청합니다. - - image 프로브: 테스트가 생성된 PNG(cat + 무작위 코드)를 첨부하고 모델이 `cat `를 반환하길 기대합니다. - - 구현 참고: `src/gateway/gateway-models.profiles.live.test.ts` 및 `src/gateway/live-image-probe.ts`. + - `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 `를 반환할 것으로 기대합니다. + - 구현 참조: `src/gateway/gateway-models.profiles.live.test.ts` 및 `src/gateway/live-image-probe.ts`. - 활성화 방법: - `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의 별칭 - - 또는 `OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"`(또는 쉼표 목록)로 범위 축소 -- 프로바이더 선택 방법(“OpenRouter 전부” 방지): + - 또는 범위를 좁히려면 `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) -- tool + image 프로브는 이 live 테스트에서 항상 활성화됩니다: - - `read` 프로브 + `exec+read` 프로브(tool 스트레스) - - image 입력 지원을 광고하는 모델에 대해서는 image 프로브 실행 - - 흐름(상위 수준): - - 테스트가 “CAT” + 무작위 코드가 있는 작은 PNG를 생성(`src/gateway/live-image-probe.ts`) +- 이 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`) - - 임베디드 agent가 멀티모달 사용자 메시지를 모델로 전달 - - 검증: 응답에 `cat` + 코드가 포함됨(OCR 허용: 사소한 오류 허용) + - Gateway가 첨부 파일을 `images[]`로 파싱(`src/gateway/server-methods/agent.ts` + `src/gateway/chat-attachments.ts`) + - 임베디드 에이전트가 멀티모달 사용자 메시지를 모델에 전달 + - 검증: 응답에 `cat` + 코드가 포함됨(OCR 허용 범위: 약간의 실수는 허용) -팁: 현재 머신에서 무엇을 테스트할 수 있는지(그리고 정확한 `provider/model` id)를 보려면 다음을 실행하세요: +팁: 자신의 머신에서 무엇을 테스트할 수 있는지(그리고 정확한 `provider/model` id)를 보려면 다음을 실행하세요: ```bash openclaw models list @@ -270,18 +272,17 @@ openclaw models list --json - `OPENCLAW_LIVE_CLI_BACKEND=1` - 기본값: - 기본 provider/model: `claude-cli/claude-sonnet-4-6` - - 명령/args/image 동작은 해당 CLI 백엔드 plugin 메타데이터에서 가져옵니다. -- override(선택 사항): + - command/args/image 동작은 해당 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 args로 전달하려면 `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"` - - `IMAGE_ARG`가 설정되었을 때 이미지 args 전달 방식을 제어하려면 `OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"`(또는 `"list"`) - - 두 번째 턴을 보내고 resume 흐름을 검증하려면 `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1` - - 기본 Claude Sonnet -> Opus 동일 세션 연속성 프로브를 비활성화하려면 `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0`(선택된 모델이 switch 타깃을 지원할 때 강제 활성화하려면 `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"`) + - 두 번째 턴을 보내고 resume 플로를 검증하려면 `OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1` + - 기본 Claude Sonnet -> Opus 동일 세션 연속성 probe를 비활성화하려면 `OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE=0`(선택한 모델이 전환 타깃을 지원할 때 강제로 켜려면 `1`) +- 예시: ```bash OPENCLAW_LIVE_CLI_BACKEND=1 \ @@ -295,7 +296,7 @@ Docker 레시피: pnpm test:docker:live-cli-backend ``` -단일 프로바이더 Docker 레시피: +단일 provider Docker 레시피: ```bash pnpm test:docker:live-cli-backend:claude @@ -306,36 +307,36 @@ pnpm test:docker:live-cli-backend:gemini 참고: - Docker 러너는 `scripts/test-live-cli-backend-docker.sh`에 있습니다. -- 저장소 Docker 이미지 내부에서 비-root `node` 사용자로 live CLI-backend 스모크를 실행합니다. -- 해당 extension에서 CLI 스모크 메타데이터를 해석한 뒤, 캐시 가능한 쓰기 가능한 prefix `OPENCLAW_DOCKER_CLI_TOOLS_DIR`(기본값: `~/.cache/openclaw/docker-cli-tools`)에 해당 Linux CLI 패키지(`@anthropic-ai/claude-code`, `@openai/codex`, 또는 `@google/gemini-cli`)를 설치합니다. -- live CLI-backend 스모크는 이제 Claude, Codex, Gemini에 대해 동일한 end-to-end 흐름을 실행합니다: 텍스트 턴, 이미지 분류 턴, 그다음 gateway CLI를 통해 검증되는 MCP `cron` 도구 호출. -- Claude의 기본 스모크는 또한 세션을 Sonnet에서 Opus로 패치하고, 재개된 세션이 이전 메모를 여전히 기억하는지 검증합니다. +- 저장소 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` 도구 호출. +- Claude의 기본 스모크는 또한 세션을 Sonnet에서 Opus로 패치하고 재개된 세션이 이전 메모를 여전히 기억하는지 검증합니다. -## Live: ACP 바인드 스모크(`/acp spawn ... --bind here`) +## Live: ACP bind 스모크(`/acp spawn ... --bind here`) - 테스트: `src/gateway/gateway-acp-bind.live.test.ts` -- 목표: live ACP agent와 함께 실제 ACP conversation-bind 흐름 검증: +- 목표: live ACP agent를 사용한 실제 ACP 대화 bind 플로 검증: - `/acp spawn --bind here` 전송 - - 합성 메시지 채널 대화를 제자리에서 바인드 + - 합성 message-channel 대화를 제자리에서 bind - 같은 대화에서 일반 후속 메시지 전송 - - 후속 메시지가 바인드된 ACP 세션 transcript에 도달하는지 검증 + - 후속 메시지가 bind된 ACP 세션 기록에 도달했는지 검증 - 활성화: - `pnpm test:live src/gateway/gateway-acp-bind.live.test.ts` - `OPENCLAW_LIVE_ACP_BIND=1` - 기본값: - - Docker 내 ACP agent: `claude,codex,gemini` + - Docker의 ACP agent: `claude,codex,gemini` - 직접 `pnpm test:live ...`용 ACP agent: `claude` - 합성 채널: Slack DM 스타일 대화 컨텍스트 - ACP 백엔드: `acpx` -- override: +- 재정의: - `OPENCLAW_LIVE_ACP_BIND_AGENT=claude` - `OPENCLAW_LIVE_ACP_BIND_AGENT=codex` - `OPENCLAW_LIVE_ACP_BIND_AGENT=gemini` - `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex,gemini` - `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND='npx -y @agentclientprotocol/claude-agent-acp@'` - 참고: - - 이 레인은 gateway `chat.send` 표면을 사용하며, 테스트가 외부 전달을 가장하지 않고도 메시지 채널 컨텍스트를 부착할 수 있도록 admin 전용 synthetic originating-route 필드를 사용합니다. - - `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND`가 설정되지 않은 경우 테스트는 선택된 ACP 하니스 agent에 대해 임베디드 `acpx` plugin의 내장 agent registry를 사용합니다. + - 이 lane은 테스트가 외부 전달을 가장하지 않고 message-channel 컨텍스트를 붙일 수 있도록 admin 전용 synthetic originating-route 필드와 함께 gateway `chat.send` 표면을 사용합니다. + - `OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND`가 설정되지 않은 경우, 테스트는 선택된 ACP harness agent에 대해 임베디드 `acpx` plugin의 내장 agent registry를 사용합니다. 예시: @@ -362,14 +363,14 @@ pnpm test:docker:live-acp-bind:gemini Docker 참고: - Docker 러너는 `scripts/test-live-acp-bind-docker.sh`에 있습니다. -- 기본적으로 지원되는 모든 live CLI agent(`claude`, `codex`, `gemini`)에 대해 ACP 바인드 스모크를 순서대로 실행합니다. -- 행렬 범위를 줄이려면 `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude`, `OPENCLAW_LIVE_ACP_BIND_AGENTS=codex`, 또는 `OPENCLAW_LIVE_ACP_BIND_AGENTS=gemini`를 사용하세요. -- `~/.profile`을 source하고, 일치하는 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`를 설정하여 source된 profile에서 가져온 프로바이더 env 변수를 자식 harness CLI에서 계속 사용할 수 있게 합니다. +- 기본적으로 지원되는 모든 live CLI agent(`claude`, `codex`, `gemini`)에 대해 ACP bind 스모크를 순차 실행합니다. +- 매트릭스 범위를 좁히려면 `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에서 계속 사용할 수 있습니다. ### 권장 live 레시피 -좁고 명시적인 allowlist가 가장 빠르고 가장 불안정성이 적습니다: +범위를 좁힌 명시적 allowlist가 가장 빠르고 변동성이 가장 적습니다: - 단일 모델, 직접(gateway 없음): - `OPENCLAW_LIVE_MODELS="openai/gpt-5.4" pnpm test:live src/agents/models.profiles.live.test.ts` @@ -377,7 +378,7 @@ Docker 참고: - 단일 모델, gateway 스모크: - `OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.4" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts` -- 여러 프로바이더에 걸친 tool calling: +- 여러 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): @@ -387,21 +388,21 @@ Docker 참고: 참고: - `google/...`는 Gemini API(API 키)를 사용합니다. -- `google-antigravity/...`는 Antigravity OAuth bridge(Cloud Code Assist 스타일 agent endpoint)를 사용합니다. -- `google-gemini-cli/...`는 머신의 로컬 Gemini CLI를 사용합니다(별도 auth + tooling 특이점). +- `google-antigravity/...`는 Antigravity OAuth 브리지(Cloud Code Assist 스타일 agent 엔드포인트)를 사용합니다. +- `google-gemini-cli/...`는 머신의 로컬 Gemini CLI를 사용합니다(별도 auth + tooling 특이사항). - Gemini API vs Gemini CLI: - - API: OpenClaw가 Google의 호스팅된 Gemini API를 HTTP를 통해 호출합니다(API 키 / profile auth). 대부분의 사용자가 “Gemini”라고 할 때 의미하는 것은 이것입니다. - - CLI: OpenClaw가 로컬 `gemini` 바이너리를 셸 실행합니다. 자체 auth가 있으며 다르게 동작할 수 있습니다(streaming/tool 지원/버전 차이). + - API: OpenClaw가 HTTP를 통해 Google의 호스팅된 Gemini API를 호출합니다(API 키 / profile auth). 대부분의 사용자가 "Gemini"라고 할 때 의미하는 것은 이것입니다. + - CLI: OpenClaw가 로컬 `gemini` 바이너리를 shell out으로 호출합니다. 별도의 auth를 가지며 다르게 동작할 수 있습니다(스트리밍/도구 지원/버전 차이). ## Live: 모델 매트릭스(무엇을 커버하는가) -고정된 “CI 모델 목록”은 없습니다(live는 옵트인). 하지만 키가 있는 개발 머신에서 정기적으로 커버하길 권장하는 모델은 다음과 같습니다. +고정된 "CI 모델 목록"은 없습니다(live는 옵트인). 하지만 키가 있는 개발 머신에서 정기적으로 커버하기를 권장하는 모델은 다음과 같습니다. -### 최신 스모크 세트(tool calling + image) +### 최신 스모크 세트(tool calling + 이미지) -우리가 계속 작동하길 기대하는 “일반 모델” 실행입니다: +이는 우리가 계속 동작하기를 기대하는 "일반 모델" 실행입니다: -- OpenAI(비-Codex): `openai/gpt-5.4`(선택 사항: `openai/gpt-5.4-mini`) +- 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 모델은 피하세요) @@ -409,12 +410,12 @@ Docker 참고: - Z.AI(GLM): `zai/glm-4.7` - MiniMax: `minimax/MiniMax-M2.7` -tools + image와 함께 gateway 스모크 실행: +도구 + 이미지와 함께 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) -프로바이더 계열별로 최소 하나는 선택하세요: +provider 계열별로 최소 하나는 선택하세요: - OpenAI: `openai/gpt-5.4`(또는 `openai/gpt-5.4-mini`) - Anthropic: `anthropic/claude-opus-4-6`(또는 `anthropic/claude-sonnet-4-6`) @@ -424,87 +425,87 @@ tools + image와 함께 gateway 스모크 실행: 선택적 추가 커버리지(있으면 좋음): -- xAI: `xai/grok-4`(또는 최신 사용 가능 모델) -- Mistral: `mistral/`…(활성화된 “tools” 지원 모델 하나 선택) +- xAI: `xai/grok-4`(또는 최신 사용 가능 버전) +- Mistral: `mistral/`…(활성화된 "tools" 지원 모델 하나 선택) - Cerebras: `cerebras/`…(접근 권한이 있는 경우) -- LM Studio: `lmstudio/`…(로컬, tool calling은 API 모드에 따라 다름) +- LM Studio: `lmstudio/`…(로컬, tool calling은 API 모드에 따라 달라짐) -### 비전: image 전송(첨부 파일 → 멀티모달 메시지) +### Vision: 이미지 전송(attachment → 멀티모달 메시지) -image 프로브를 실행하려면 `OPENCLAW_LIVE_GATEWAY_MODELS`에 image-capable 모델 하나 이상(Claude/Gemini/OpenAI의 비전 지원 변형 등)을 포함하세요. +이미지 probe를 실행하려면 이미지 지원 모델 하나 이상을 `OPENCLAW_LIVE_GATEWAY_MODELS`에 포함하세요(Claude/Gemini/OpenAI의 vision 지원 변형 등). -### 어그리게이터 / 대체 gateway +### Aggregator / 대체 gateway -키가 활성화되어 있다면 다음을 통한 테스트도 지원합니다: +키가 활성화되어 있다면 다음 경로를 통해서도 테스트를 지원합니다: -- OpenRouter: `openrouter/...`(수백 개의 모델, `openclaw models scan`으로 tool+image 지원 후보 찾기) +- OpenRouter: `openrouter/...`(수백 개 모델, `openclaw models scan`으로 tool+image 지원 후보 찾기) - OpenCode: Zen용 `opencode/...`, Go용 `opencode-go/...`(auth는 `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY`) -live 매트릭스에 포함할 수 있는 더 많은 프로바이더(자격 증명/config가 있는 경우): +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가 작동하면 live 테스트도 같은 키를 찾아야 합니다. -- live 테스트가 “자격 증명 없음”이라고 하면, `openclaw models list` / 모델 선택을 디버깅하듯 같은 방식으로 디버깅하세요. +- CLI가 동작한다면 live 테스트도 동일한 키를 찾아야 합니다. +- live 테스트가 "자격 증명 없음"이라고 하면, `openclaw models list` / 모델 선택을 디버깅하듯 같은 방식으로 디버깅하세요. -- 에이전트별 auth profile: `~/.openclaw/agents//agent/auth-profiles.json`(live 테스트에서 “profile 키”가 의미하는 것) +- 에이전트별 auth profile: `~/.openclaw/agents//agent/auth-profiles.json`(live 테스트에서 "profile 키"가 의미하는 것) - Config: `~/.openclaw/openclaw.json`(또는 `OPENCLAW_CONFIG_PATH`) -- 레거시 state 디렉터리: `~/.openclaw/credentials/`(존재할 경우 스테이징된 live 홈으로 복사되지만, 기본 profile-key 저장소는 아님) -- 로컬 live 실행은 기본적으로 활성 config, 에이전트별 `auth-profiles.json` 파일, 레거시 `credentials/`, 지원되는 외부 CLI auth 디렉터리를 임시 테스트 홈으로 복사합니다. 스테이징된 live 홈은 `workspace/`와 `sandboxes/`를 건너뛰고, `agents.*.workspace` / `agentDir` 경로 override도 제거하므로 프로브가 실제 호스트 workspace를 건드리지 않습니다. +- 레거시 상태 디렉터리: `~/.openclaw/credentials/`(존재할 경우 스테이징된 live 홈으로 복사되지만, 메인 profile-key 저장소는 아님) +- 로컬 live 실행은 기본적으로 활성 config, 에이전트별 `auth-profiles.json`, 레거시 `credentials/`, 그리고 지원되는 외부 CLI auth 디렉터리를 임시 테스트 홈으로 복사합니다. 스테이징된 live 홈은 `workspace/`와 `sandboxes/`를 건너뛰고, `agents.*.workspace` / `agentDir` 경로 재정의는 제거되므로 probe가 실제 호스트 워크스페이스에 영향을 주지 않습니다. -env 키(예: `~/.profile`에 export된 키)에 의존하고 싶다면, 로컬 테스트를 `source ~/.profile` 후 실행하거나 아래 Docker 러너를 사용하세요(컨테이너에 `~/.profile`을 마운트할 수 있음). +env 키에 의존하고 싶다면(예: `~/.profile`에 export됨), 로컬 테스트 전에 `source ~/.profile`을 실행하거나 아래 Docker 러너를 사용하세요(Docker 러너는 `~/.profile`을 컨테이너에 마운트할 수 있습니다). ## Deepgram live(오디오 전사) - 테스트: `src/media-understanding/providers/deepgram/audio.live.test.ts` - 활성화: `DEEPGRAM_API_KEY=... DEEPGRAM_LIVE_TEST=1 pnpm test:live src/media-understanding/providers/deepgram/audio.live.test.ts` -## BytePlus coding plan live +## BytePlus 코딩 플랜 live - 테스트: `src/agents/byteplus.live.test.ts` - 활성화: `BYTEPLUS_API_KEY=... BYTEPLUS_LIVE_TEST=1 pnpm test:live src/agents/byteplus.live.test.ts` -- 선택적 모델 override: `BYTEPLUS_CODING_MODEL=ark-code-latest` +- 선택적 모델 재정의: `BYTEPLUS_CODING_MODEL=ark-code-latest` -## ComfyUI workflow media live +## ComfyUI 워크플로 미디어 live - 테스트: `extensions/comfy/comfy.live.test.ts` - 활성화: `OPENCLAW_LIVE_TEST=1 COMFY_LIVE_TEST=1 pnpm test:live -- extensions/comfy/comfy.live.test.ts` - 범위: - - 번들된 comfy image, video, `music_generate` 경로 실행 - - `models.providers.comfy.`가 구성되지 않은 capability는 각각 건너뜀 - - comfy workflow 제출, polling, 다운로드, 또는 plugin 등록을 변경한 뒤 유용함 + - 번들된 comfy 이미지, 비디오, `music_generate` 경로를 실행 + - `models.providers.comfy.`가 구성되어 있지 않으면 각 capability를 건너뜀 + - comfy 워크플로 제출, polling, 다운로드, 또는 plugin 등록을 변경한 뒤 유용함 -## image 생성 live +## 이미지 생성 live - 테스트: `src/image-generation/runtime.live.test.ts` -- 명령: `pnpm test:live src/image-generation/runtime.live.test.ts` +- 명령어: `pnpm test:live src/image-generation/runtime.live.test.ts` - 하니스: `pnpm test:live:media image` - 범위: - - 등록된 모든 image-generation provider plugin 열거 - - 프로브 전에 로그인 셸(`~/.profile`)에서 누락된 provider env 변수를 로드 + - 등록된 모든 이미지 생성 provider plugin을 열거 + - probe 전에 로그인 셸(`~/.profile`)에서 누락된 provider env var를 로드 - 기본적으로 저장된 auth profile보다 live/env API 키를 우선 사용하므로, `auth-profiles.json`의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않음 - - 사용 가능한 auth/profile/model이 없는 프로바이더는 건너뜀 - - 공유 런타임 capability를 통해 기본 image-generation 변형 실행: + - 사용 가능한 auth/profile/model이 없는 provider는 건너뜀 + - 공유 런타임 capability를 통해 기본 이미지 생성 변형을 실행: - `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-store auth를 강제하고 env 전용 override를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` + - profile 저장소 auth를 강제하고 env 전용 재정의를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` ## 음악 생성 live @@ -512,23 +513,23 @@ env 키(예: `~/.profile`에 export된 키)에 의존하고 싶다면, 로컬 - 활성화: `OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/music-generation-providers.live.test.ts` - 하니스: `pnpm test:live:media music` - 범위: - - 공유 번들 music-generation provider 경로 실행 + - 공유 번들 음악 생성 provider 경로를 실행 - 현재 Google과 MiniMax를 커버 - - 프로브 전에 로그인 셸(`~/.profile`)에서 provider env 변수를 로드 + - probe 전에 로그인 셸(`~/.profile`)에서 provider env var를 로드 - 기본적으로 저장된 auth profile보다 live/env API 키를 우선 사용하므로, `auth-profiles.json`의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않음 - - 사용 가능한 auth/profile/model이 없는 프로바이더는 건너뜀 - - 사용 가능한 경우 선언된 런타임 모드를 모두 실행: - - prompt 전용 입력으로 `generate` - - 프로바이더가 `capabilities.edit.enabled`를 선언한 경우 `edit` - - 현재 공유 레인 커버리지: + - 사용 가능한 auth/profile/model이 없는 provider는 건너뜀 + - 사용 가능한 경우 선언된 두 런타임 모드를 모두 실행: + - 프롬프트 전용 입력으로 `generate` + - provider가 `capabilities.edit.enabled`를 선언할 때 `edit` + - 현재 공유 lane 커버리지: - `google`: `generate`, `edit` - `minimax`: `generate` - - `comfy`: 별도의 Comfy live 파일에서 다루며, 이 공유 스윕에서는 다루지 않음 -- 선택적 범위 축소: + - `comfy`: 별도 Comfy live 파일이며 이 공유 스윕은 아님 +- 선택적 범위 좁히기: - `OPENCLAW_LIVE_MUSIC_GENERATION_PROVIDERS="google,minimax"` - `OPENCLAW_LIVE_MUSIC_GENERATION_MODELS="google/lyria-3-clip-preview,minimax/music-2.5+"` - 선택적 auth 동작: - - profile-store auth를 강제하고 env 전용 override를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` + - profile 저장소 auth를 강제하고 env 전용 재정의를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` ## 비디오 생성 live @@ -536,175 +537,180 @@ env 키(예: `~/.profile`에 export된 키)에 의존하고 싶다면, 로컬 - 활성화: `OPENCLAW_LIVE_TEST=1 pnpm test:live -- extensions/video-generation-providers.live.test.ts` - 하니스: `pnpm test:live:media video` - 범위: - - 공유 번들 video-generation provider 경로 실행 - - 프로브 전에 로그인 셸(`~/.profile`)에서 provider env 변수를 로드 + - 공유 번들 비디오 생성 provider 경로를 실행 + - probe 전에 로그인 셸(`~/.profile`)에서 provider env var를 로드 - 기본적으로 저장된 auth profile보다 live/env API 키를 우선 사용하므로, `auth-profiles.json`의 오래된 테스트 키가 실제 셸 자격 증명을 가리지 않음 - - 사용 가능한 auth/profile/model이 없는 프로바이더는 건너뜀 - - 사용 가능한 경우 선언된 런타임 모드를 모두 실행: - - prompt 전용 입력으로 `generate` - - 프로바이더가 `capabilities.imageToVideo.enabled`를 선언하고 선택된 provider/model이 공유 스윕에서 버퍼 기반 로컬 image 입력을 수용하는 경우 `imageToVideo` - - 프로바이더가 `capabilities.videoToVideo.enabled`를 선언하고 선택된 provider/model이 공유 스윕에서 버퍼 기반 로컬 video 입력을 수용하는 경우 `videoToVideo` - - 현재 공유 스윕에서 선언되었지만 건너뛰는 `imageToVideo` 프로바이더: - - `vydra`: 번들된 `veo3`는 텍스트 전용이고 번들된 `kling`은 원격 image URL이 필요하기 때문 - - 프로바이더별 Vydra 커버리지: + - 사용 가능한 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 커버리지: - `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_VYDRA_VIDEO=1 pnpm test:live -- extensions/vydra/vydra.live.test.ts` - - 이 파일은 기본적으로 원격 image URL fixture를 사용하는 `kling` 레인과 함께 `veo3` text-to-video를 실행합니다 + - 이 파일은 기본적으로 원격 이미지 URL fixture를 사용하는 `kling` lane과 함께 `veo3` 텍스트-투-비디오를 실행합니다 - 현재 `videoToVideo` live 커버리지: - - 선택된 모델이 `runway/gen4_aleph`일 때만 `runway` - - 현재 공유 스윕에서 선언되었지만 건너뛰는 `videoToVideo` 프로바이더: - - `alibaba`, `qwen`, `xai`: 이 경로들은 현재 원격 `http(s)` / MP4 참조 URL이 필요함 - - `google`: 현재 공유 Gemini/Veo 레인은 로컬 버퍼 기반 입력을 사용하며 이 경로는 공유 스윕에서 허용되지 않음 - - `openai`: 현재 공유 레인은 조직별 비디오 inpaint/remix 접근 보장을 제공하지 않음 -- 선택적 범위 축소: + - 선택된 모델이 `runway/gen4_aleph`일 때 `runway`만 + - 공유 스윕에서 현재 선언되었지만 건너뛰는 `videoToVideo` providers: + - `alibaba`, `qwen`, `xai`: 이 경로들이 현재 원격 `http(s)` / MP4 참조 URL을 필요로 하기 때문 + - `google`: 현재 공유 Gemini/Veo lane이 로컬 버퍼 기반 입력을 사용하며 이 경로는 공유 스윕에서 허용되지 않기 때문 + - `openai`: 현재 공유 lane에는 조직별 비디오 inpaint/remix 액세스 보장이 없기 때문 +- 선택적 범위 좁히기: - `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-store auth를 강제하고 env 전용 override를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` + - profile 저장소 auth를 강제하고 env 전용 재정의를 무시하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` ## 미디어 live 하니스 -- 명령: `pnpm test:live:media` +- 명령어: `pnpm test:live:media` - 목적: - - 공유 image, music, video live 스위트를 하나의 저장소 네이티브 엔트리포인트로 실행 - - `~/.profile`에서 누락된 provider env 변수를 자동 로드 - - 기본적으로 현재 사용 가능한 auth가 있는 프로바이더로 각 스위트를 자동 축소 - - `scripts/test-live.mjs`를 재사용하므로 하트비트와 조용한 모드 동작이 일관되게 유지됨 + - 공유 이미지, 음악, 비디오 live 스위트를 하나의 저장소 기본 진입점으로 실행 + - `~/.profile`에서 누락된 provider env var를 자동 로드 + - 기본적으로 현재 사용 가능한 auth가 있는 provider로 각 스위트 범위를 자동 축소 + - `scripts/test-live.mjs`를 재사용하므로 heartbeat 및 quiet-mode 동작이 일관되게 유지됨 - 예시: - `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`는 해당 profile-key live 파일만 저장소 Docker 이미지 내부에서 실행합니다(`src/agents/models.profiles.live.test.ts`와 `src/gateway/gateway-models.profiles.live.test.ts`). 로컬 config 디렉터리와 workspace를 마운트하며(마운트된 경우 `~/.profile`도 source함), 대응되는 로컬 엔트리포인트는 `test:live:models-profiles`와 `test:live:gateway-profiles`입니다. -- Docker live 러너는 전체 Docker 스윕을 실용적으로 유지하기 위해 더 작은 스모크 상한을 기본으로 사용합니다: - `test:docker:live-models`는 기본적으로 `OPENCLAW_LIVE_MAX_MODELS=12`, +- 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-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`을 사용합니다. 더 큰 전체 스캔을 명시적으로 원할 때만 해당 env 변수를 override하세요. -- `test:docker:all`은 먼저 `test:docker:live-build`를 통해 live Docker 이미지를 한 번 빌드한 뒤, 두 live Docker 레인에서 이를 재사용합니다. + `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 경로를 검증합니다. -live-model Docker 러너는 또한 필요한 CLI auth 홈만 바인드 마운트하며(또는 실행 범위가 좁혀지지 않은 경우 지원되는 모든 홈), 실행 전에 이를 컨테이너 홈으로 복사하므로 외부 CLI OAuth가 호스트 auth 저장소를 변경하지 않고 토큰을 갱신할 수 있습니다: +live-model Docker 러너는 또한 필요한 CLI auth 홈만 bind-mount합니다(실행 범위를 좁히지 않은 경우에는 지원되는 모든 홈). 그런 다음 실행 전에 이를 컨테이너 홈으로 복사하므로 외부 CLI OAuth가 호스트 auth 저장소를 변경하지 않고도 토큰을 갱신할 수 있습니다: - 직접 모델: `pnpm test:docker:live-models`(스크립트: `scripts/test-live-models-docker.sh`) -- ACP 바인드 스모크: `pnpm test:docker:live-acp-bind`(스크립트: `scripts/test-live-acp-bind-docker.sh`) +- ACP bind 스모크: `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 channel bridge(seed된 Gateway + stdio bridge + 원시 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`) +- 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`) -live-model Docker 러너는 또한 현재 체크아웃을 읽기 전용으로 바인드 마운트하고 -컨테이너 내부의 임시 workdir로 스테이징합니다. 이렇게 하면 런타임 -이미지를 가볍게 유지하면서도 정확한 로컬 소스/config로 Vitest를 실행할 수 있습니다. -스테이징 단계는 `.pnpm-store`, `.worktrees`, `__openclaw_vitest__`, 앱 로컬 `.build` 또는 -Gradle 출력 디렉터리 같은 큰 로컬 전용 캐시와 앱 빌드 출력을 건너뛰므로 -Docker live 실행이 머신별 artifact를 복사하느라 몇 분씩 쓰지 않습니다. -또한 `OPENCLAW_SKIP_CHANNELS=1`을 설정하므로 gateway live 프로브가 컨테이너 내부에서 -실제 Telegram/Discord 등의 channel 워커를 시작하지 않습니다. -`test:docker:live-models`는 여전히 `pnpm test:live`를 실행하므로, 해당 Docker 레인에서 -gateway live 커버리지를 좁히거나 제외해야 할 때는 `OPENCLAW_LIVE_GATEWAY_*`도 함께 전달하세요. -`test:docker:openwebui`는 더 높은 수준의 호환성 스모크입니다. OpenAI 호환 HTTP 엔드포인트가 -활성화된 OpenClaw gateway 컨테이너를 시작하고, 그 gateway에 연결된 고정 버전 Open WebUI 컨테이너를 시작한 뒤, -Open WebUI를 통해 로그인하고, `/api/models`가 `openclaw/default`를 노출하는지 검증한 다음, +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 이미지를 풀해야 하거나 Open WebUI 자체의 cold-start 설정을 -마쳐야 할 수 있기 때문에 눈에 띄게 더 느릴 수 있습니다. -이 레인은 사용 가능한 live 모델 키를 기대하며, `OPENCLAW_PROFILE_FILE` -(기본값: `~/.profile`)이 Dockerized 실행에서 이를 제공하는 주요 방법입니다. -성공적인 실행은 `{ "ok": true, "model": -"openclaw/default", ... }` 같은 작은 JSON payload를 출력합니다. -`test:docker:mcp-channels`는 의도적으로 결정적이며 실제 Telegram, Discord, iMessage 계정이 필요하지 않습니다. -seed된 Gateway 컨테이너를 부팅하고, `openclaw mcp serve`를 실행하는 두 번째 컨테이너를 시작한 다음, -라우팅된 대화 검색, transcript 읽기, 첨부 파일 메타데이터, -live event queue 동작, outbound send 라우팅, 그리고 실제 stdio MCP bridge를 통한 Claude 스타일 channel + -permission 알림을 검증합니다. 알림 검사는 원시 stdio MCP 프레임을 직접 검사하므로, -특정 client SDK가 우연히 표면화하는 것이 아니라 bridge가 실제로 내보내는 것을 검증합니다. +첫 실행은 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가 우연히 표면화하는 내용이 아니라 +브리지가 실제로 내보내는 내용을 검증합니다. -수동 ACP 자연어 스레드 스모크(CI 아님): +수동 ACP plain-language 스레드 스모크(CI 아님): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` -- 이 스크립트는 회귀 테스트/디버그 워크플로를 위해 유지하세요. ACP 스레드 라우팅 검증에 다시 필요할 수 있으므로 삭제하지 마세요. +- 이 스크립트는 회귀/디버그 워크플로를 위해 유지하세요. 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`에 마운트하고 테스트 실행 전에 source -- `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`)는 Docker 내부 캐시된 CLI 설치용으로 `/home/node/.npm-global`에 마운트됨 +- `$HOME` 아래의 외부 CLI auth 디렉터리/파일은 `/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`에서 추론된 필요한 디렉터리/파일만 마운트 - - 수동 override: `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none`, 또는 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 같은 쉼표 목록 + - 범위를 좁힌 provider 실행은 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS`에서 추론된 필요한 디렉터리/파일만 마운트함 + - 수동 재정의: `OPENCLAW_DOCKER_AUTH_DIRS=all`, `OPENCLAW_DOCKER_AUTH_DIRS=none`, 또는 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 같은 쉼표 목록 - 실행 범위를 좁히려면 `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` -- 컨테이너 내부의 provider를 필터링하려면 `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` -- 자격 증명이 profile store에서 오도록 보장하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` +- 컨테이너 내부 provider 필터링에는 `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` +- 자격 증명이 profile 저장소에서 오도록 보장하려면 `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` - Open WebUI 스모크용으로 gateway가 노출할 모델을 선택하려면 `OPENCLAW_OPENWEBUI_MODEL=...` -- Open WebUI 스모크에서 사용하는 nonce-check 프롬프트를 override하려면 `OPENCLAW_OPENWEBUI_PROMPT=...` -- 고정된 Open WebUI image 태그를 override하려면 `OPENWEBUI_IMAGE=...` +- Open WebUI 스모크에서 사용하는 nonce 확인 프롬프트를 재정의하려면 `OPENCLAW_OPENWEBUI_PROMPT=...` +- 고정된 Open WebUI 이미지 태그를 재정의하려면 `OPENWEBUI_IMAGE=...` ## 문서 sanity -문서 편집 후 문서 검사를 실행하세요: `pnpm check:docs`. -페이지 내 heading 검사도 필요할 때는 전체 Mintlify anchor 검증을 실행하세요: `pnpm docs:check-links:anchors`. +문서를 수정한 뒤에는 docs 체크를 실행하세요: `pnpm check:docs`. +인페이지 heading 체크까지 필요하면 전체 Mintlify anchor 검증을 실행하세요: `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") +- Gateway wizard(WS `wizard.start`/`wizard.next`, config + auth 쓰기 강제): `src/gateway/gateway.test.ts`(케이스: "runs wizard over ws and writes auth token config") -## agent 신뢰성 평가(Skills) +## 에이전트 신뢰성 평가(Skills) -이미 “agent 신뢰성 평가”처럼 동작하는 몇 가지 CI 안전 테스트가 있습니다: +우리는 이미 "에이전트 신뢰성 평가"처럼 동작하는 몇 가지 CI 안전 테스트를 가지고 있습니다: - 실제 gateway + agent 루프를 통한 mock tool-calling(`src/gateway/gateway.test.ts`). -- 세션 배선과 config 효과를 검증하는 end-to-end wizard 흐름(`src/gateway/gateway.test.ts`). +- 세션 wiring 및 config 효과를 검증하는 end-to-end wizard 플로(`src/gateway/gateway.test.ts`). -Skills에 대해 아직 부족한 부분([Skills](/ko/tools/skills) 참조): +Skills에 대해 여전히 부족한 것([Skills](/ko/tools/skills) 참고): -- **의사결정:** 프롬프트에 skills가 나열될 때 agent가 올바른 skill을 선택하는가(또는 관련 없는 것은 피하는가)? -- **준수:** agent가 사용 전에 `SKILL.md`를 읽고 필요한 단계/args를 따르는가? -- **워크플로 계약:** tool 순서, 세션 기록 이월, sandbox 경계를 검증하는 멀티턴 시나리오. +- **의사결정:** 프롬프트에 skill이 나열되었을 때 에이전트가 올바른 skill을 선택하는가(또는 관련 없는 skill을 피하는가)? +- **준수성:** 사용 전에 에이전트가 `SKILL.md`를 읽고 필수 단계/인수를 따르는가? +- **워크플로 계약:** 도구 순서, 세션 기록 이어받기, 샌드박스 경계를 검증하는 멀티턴 시나리오. -향후 평가는 먼저 결정적으로 유지되어야 합니다: +향후 평가는 우선 결정적으로 유지되어야 합니다: -- tool 호출 + 순서, skill 파일 읽기, 세션 배선을 검증하기 위해 mock 프로바이더를 사용하는 시나리오 러너. -- skill 중심 시나리오의 작은 스위트(사용 vs 회피, 게이팅, 프롬프트 인젝션). -- CI 안전 스위트가 갖춰진 후에만 선택적으로 live 평가(옵트인, env 게이트). +- tool call + 순서, skill 파일 읽기, 세션 wiring을 검증하기 위해 mock provider를 사용하는 시나리오 러너. +- skill 중심 시나리오의 소규모 스위트(사용 vs 회피, 게이팅, 프롬프트 인젝션). +- CI 안전 스위트가 준비된 뒤에만 선택적으로 live 평가(옵트인, env 게이트). ## 계약 테스트(plugin 및 channel 형태) 계약 테스트는 등록된 모든 plugin과 channel이 해당 -인터페이스 계약을 준수하는지 검증합니다. 발견된 모든 plugin을 순회하며 -형태와 동작에 대한 assertion 스위트를 실행합니다. 기본 `pnpm test` unit 레인은 -의도적으로 이러한 공유 seam 및 스모크 파일을 건너뜁니다. 공유 channel 또는 provider 표면을 건드렸다면 +인터페이스 계약을 준수하는지 검증합니다. 발견된 모든 plugin을 순회하고 +형태 및 동작 검증 스위트를 실행합니다. 기본 `pnpm test` unit lane은 의도적으로 +이 공유 seam 및 스모크 파일을 건너뛰므로, 공유 channel 또는 provider 표면을 수정할 때는 계약 명령을 명시적으로 실행하세요. -### 명령 +### 명령어 - 모든 계약: `pnpm test:contracts` -- Channel 계약만: `pnpm test:contracts:channels` -- Provider 계약만: `pnpm test:contracts:plugins` +- channel 계약만: `pnpm test:contracts:channels` +- provider 계약만: `pnpm test:contracts:plugins` ### Channel 계약 `src/channels/plugins/contracts/*.contract.test.ts`에 위치: - **plugin** - 기본 plugin 형태(id, name, capabilities) -- **setup** - 설정 마법사 계약 +- **setup** - setup wizard 계약 - **session-binding** - 세션 바인딩 동작 -- **outbound-payload** - 메시지 payload 구조 -- **inbound** - 인바운드 메시지 처리 +- **outbound-payload** - 메시지 페이로드 구조 +- **inbound** - inbound 메시지 처리 - **actions** - channel action handler - **threading** - thread ID 처리 - **directory** - 디렉터리/roster API @@ -714,39 +720,39 @@ Skills에 대해 아직 부족한 부분([Skills](/ko/tools/skills) 참조): `src/plugins/contracts/*.contract.test.ts`에 위치합니다. -- **status** - channel 상태 프로브 -- **registry** - plugin 레지스트리 형태 +- **status** - channel 상태 probe +- **registry** - plugin registry 형태 ### Provider 계약 `src/plugins/contracts/*.contract.test.ts`에 위치: -- **auth** - auth 흐름 계약 +- **auth** - auth 플로 계약 - **auth-choice** - auth 선택/선정 -- **catalog** - 모델 카탈로그 API -- **discovery** - plugin discovery -- **loader** - plugin loading +- **catalog** - 모델 catalog API +- **discovery** - plugin 탐색 +- **loader** - plugin 로딩 - **runtime** - provider 런타임 - **shape** - plugin 형태/인터페이스 -- **wizard** - 설정 마법사 +- **wizard** - setup wizard ### 실행 시점 - plugin-sdk export 또는 subpath를 변경한 후 - channel 또는 provider plugin을 추가하거나 수정한 후 -- plugin 등록 또는 discovery를 리팩터링한 후 +- plugin 등록 또는 탐색을 리팩터링한 후 계약 테스트는 CI에서 실행되며 실제 API 키가 필요하지 않습니다. ## 회귀 테스트 추가(가이드) -live에서 발견한 provider/model 이슈를 수정할 때: +live에서 발견된 provider/model 이슈를 수정할 때: -- 가능하면 CI 안전 회귀 테스트를 추가하세요(mock/stub provider 또는 정확한 request-shape 변환 캡처) -- 본질적으로 live 전용이라면(rate limit, auth 정책) live 테스트는 좁게 유지하고 env 변수로 옵트인하게 하세요 -- 버그를 잡아내는 가장 작은 계층을 타기팅하는 편이 좋습니다: - - provider 요청 변환/재생 버그 → 직접 모델 테스트 - - gateway 세션/기록/tool 파이프라인 버그 → gateway live 스모크 또는 CI 안전 gateway mock 테스트 +- 가능하면 CI 안전 회귀를 추가하세요(mock/stub provider 또는 정확한 request-shape 변환 캡처) +- 본질적으로 live 전용인 경우(rate limit, auth 정책), live 테스트 범위를 좁게 유지하고 env var로 옵트인되게 하세요 +- 버그를 잡는 가장 작은 계층을 타기팅하세요: + - provider 요청 변환/replay 버그 → 직접 모델 테스트 + - gateway 세션/히스토리/도구 파이프라인 버그 → gateway live 스모크 또는 CI 안전 gateway mock 테스트 - SecretRef 순회 가드레일: - - `src/secrets/exec-secret-ref-id-parity.test.ts`는 레지스트리 메타데이터(`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`는 registry 메타데이터(`listSecretTargetRegistryEntries()`)에서 SecretRef 클래스별 샘플 타깃 하나를 도출한 뒤, traversal-segment exec id가 거부되는지 검증합니다. + - `src/secrets/target-registry-data.ts`에 새로운 `includeInPlan` SecretRef 타깃 계열을 추가하면 해당 테스트의 `classifyTargetClass`를 업데이트하세요. 이 테스트는 새 클래스가 조용히 건너뛰어지지 않도록 분류되지 않은 타깃 id에서 의도적으로 실패합니다. diff --git a/docs/ko/plans/2026-04-05-002-refactor-real-plugin-sdk-workspace-plan.md b/docs/ko/plans/2026-04-05-002-refactor-real-plugin-sdk-workspace-plan.md deleted file mode 100644 index 015ec6633..000000000 --- a/docs/ko/plans/2026-04-05-002-refactor-real-plugin-sdk-workspace-plan.md +++ /dev/null @@ -1,507 +0,0 @@ ---- -date: 2026-04-05T00:00:00Z -status: active -title: '리팩터링: plugin-sdk를 점진적으로 실제 워크스페이스 패키지로 만들기' -type: refactor -x-i18n: - generated_at: "2026-04-07T05:58:03Z" - model: gpt-5.4 - provider: openai - source_hash: ea1ca41846363c506a0db6dbca746e840d7c71ca82bbfc5277af9e2ae7f6b070 - source_path: plans/2026-04-05-002-refactor-real-plugin-sdk-workspace-plan.md - workflow: 15 ---- - -# 리팩터링: plugin-sdk를 점진적으로 실제 워크스페이스 패키지로 만들기 - -## 개요 - -이 계획은 `packages/plugin-sdk`에 plugin SDK용 실제 워크스페이스 패키지를 도입하고, 이를 사용해 소수의 1차 확장 세트에 컴파일러 강제 패키지 경계를 옵트인 방식으로 적용합니다. 목표는 선택된 번들 제공자 확장 세트에 대해 일반적인 `tsc`에서 불법 상대 import가 실패하도록 만드는 것이며, 저장소 전체 마이그레이션이나 거대한 병합 충돌 표면을 강제하지 않는 것입니다. - -핵심적인 점진적 조치는 한동안 두 가지 모드를 병행 실행하는 것입니다. - -| 모드 | import 형태 | 사용 대상 | 강제 방식 | -| ---- | ----------- | --------- | --------- | -| 레거시 모드 | `openclaw/plugin-sdk/*` | 기존의 모든 비옵트인 확장 | 현재의 관대한 동작 유지 | -| 옵트인 모드 | `@openclaw/plugin-sdk/*` | 1차 확장만 | 패키지 로컬 `rootDir` + 프로젝트 참조 | - -## 문제 프레임 - -현재 저장소는 대규모 공개 plugin SDK 표면을 export하지만, 이는 실제 워크스페이스 패키지가 아닙니다. 대신 다음과 같습니다. - -- 루트 `tsconfig.json`은 `openclaw/plugin-sdk/*`를 - `src/plugin-sdk/*.ts`에 직접 매핑합니다. -- 이전 실험에 옵트인되지 않은 확장도 여전히 해당 - 전역 소스 별칭 동작을 공유합니다. -- 허용된 SDK import가 확장 패키지 외부의 원시 저장소 소스로 해석되지 않게 된 뒤에야 - `rootDir` 추가가 동작합니다. - -즉, 저장소는 원하는 경계 정책을 설명할 수는 있지만, TypeScript는 대부분의 확장에 대해 이를 깔끔하게 강제하지 못합니다. - -필요한 것은 다음을 만족하는 점진적 경로입니다. - -- `plugin-sdk`를 실제 패키지로 만들기 -- SDK를 `@openclaw/plugin-sdk`라는 워크스페이스 패키지로 점진적으로 이동하기 -- 첫 번째 PR에서는 약 10개의 확장만 변경하기 -- 확장 트리의 나머지는 나중에 정리할 때까지 기존 방식에 남겨두기 -- 1차 롤아웃의 주요 메커니즘으로 `tsconfig.plugin-sdk.dts.json` + postinstall 생성 선언 워크플로를 피하기 - -## 요구 사항 추적 - -- R1. `packages/` 아래에 plugin SDK용 실제 워크스페이스 패키지를 생성합니다. -- R2. 새 패키지 이름을 `@openclaw/plugin-sdk`로 지정합니다. -- R3. 새 SDK 패키지에 자체 `package.json`과 `tsconfig.json`을 부여합니다. -- R4. 마이그레이션 기간 동안 비옵트인 확장에 대해 레거시 `openclaw/plugin-sdk/*` import가 계속 동작하도록 유지합니다. -- R5. 첫 번째 PR에서는 소규모 1차 확장 세트만 옵트인합니다. -- R6. 1차 확장에서는 패키지 루트를 벗어나는 상대 import가 fail-closed 되어야 합니다. -- R7. 1차 확장은 루트 `paths` 별칭이 아니라 패키지 의존성과 TS 프로젝트 참조를 통해 SDK를 사용해야 합니다. -- R8. 이 계획은 에디터 정합성을 위해 저장소 전체에 필수적인 postinstall 생성 단계를 피해야 합니다. -- R9. 1차 롤아웃은 저장소 전체 300개 이상 파일 리팩터링이 아니라, 리뷰 가능하고 병합 가능한 중간 규모 PR이어야 합니다. - -## 범위 경계 - -- 첫 번째 PR에서 모든 번들 확장을 완전히 마이그레이션하지 않습니다. -- 첫 번째 PR에서 `src/plugin-sdk` 삭제를 요구하지 않습니다. -- 모든 루트 빌드 또는 테스트 경로를 즉시 새 패키지를 사용하도록 재배선할 필요는 없습니다. -- 모든 비옵트인 확장에 대해 VS Code squiggle을 강제하려고 하지 않습니다. -- 확장 트리 나머지 부분에 대한 광범위한 lint 정리를 하지 않습니다. -- 옵트인된 확장의 import 해석, 패키지 소유권, 경계 강제 외에 큰 런타임 동작 변경은 하지 않습니다. - -## 컨텍스트 및 조사 - -### 관련 코드 및 패턴 - -- `pnpm-workspace.yaml`은 이미 `packages/*`와 `extensions/*`를 포함하므로 - `packages/plugin-sdk` 아래의 새 워크스페이스 패키지는 기존 저장소 - 레이아웃에 맞습니다. -- `packages/memory-host-sdk/package.json` - 및 `packages/plugin-package-contract/package.json` 같은 기존 워크스페이스 패키지는 이미 - `src/*.ts`를 루트로 하는 패키지 로컬 `exports` 맵을 사용합니다. -- 루트 `package.json`은 현재 - `dist/plugin-sdk/*.js` 및 `dist/plugin-sdk/*.d.ts`를 기반으로 하는 - `./plugin-sdk` 및 `./plugin-sdk/*` export를 통해 SDK 표면을 게시합니다. -- `src/plugin-sdk/entrypoints.ts`와 `scripts/lib/plugin-sdk-entrypoints.json`은 - 이미 SDK 표면의 정식 진입점 인벤토리 역할을 합니다. -- 루트 `tsconfig.json`은 현재 다음을 매핑합니다. - - `openclaw/plugin-sdk` -> `src/plugin-sdk/index.ts` - - `openclaw/plugin-sdk/*` -> `src/plugin-sdk/*.ts` -- 이전 경계 실험은 허용된 SDK import가 확장 패키지 외부의 원시 소스로 더 이상 해석되지 않게 된 이후에야 - 패키지 로컬 `rootDir`이 불법 상대 import에 대해 동작함을 보여주었습니다. - -### 1차 확장 세트 - -이 계획은 1차 세트가 복잡한 채널 런타임 엣지 케이스를 끌어들일 가능성이 가장 적은, 제공자 중심 세트라고 가정합니다. - -- `extensions/anthropic` -- `extensions/exa` -- `extensions/firecrawl` -- `extensions/groq` -- `extensions/mistral` -- `extensions/openai` -- `extensions/perplexity` -- `extensions/tavily` -- `extensions/together` -- `extensions/xai` - -### 1차 SDK 표면 인벤토리 - -1차 확장은 현재 관리 가능한 SDK 서브패스 하위 집합을 import합니다. -초기 `@openclaw/plugin-sdk` 패키지는 다음만 포함하면 됩니다. - -- `agent-runtime` -- `cli-runtime` -- `config-runtime` -- `core` -- `image-generation` -- `media-runtime` -- `media-understanding` -- `plugin-entry` -- `plugin-runtime` -- `provider-auth` -- `provider-auth-api-key` -- `provider-auth-login` -- `provider-auth-runtime` -- `provider-catalog-shared` -- `provider-entry` -- `provider-http` -- `provider-model-shared` -- `provider-onboard` -- `provider-stream-family` -- `provider-stream-shared` -- `provider-tools` -- `provider-usage` -- `provider-web-fetch` -- `provider-web-search` -- `realtime-transcription` -- `realtime-voice` -- `runtime-env` -- `secret-input` -- `security-runtime` -- `speech` -- `testing` - -### 제도적 학습 - -- 이 작업 트리에는 관련 `docs/solutions/` 항목이 없었습니다. - -### 외부 참고 자료 - -- 이 계획에는 외부 조사가 필요하지 않았습니다. 저장소에 이미 관련 워크스페이스 패키지 및 SDK export 패턴이 포함되어 있습니다. - -## 핵심 기술 결정 - -- 새 워크스페이스 패키지로 `@openclaw/plugin-sdk`를 도입하면서 - 마이그레이션 동안 레거시 루트 `openclaw/plugin-sdk/*` 표면은 유지합니다. - 근거: 이렇게 하면 모든 확장과 모든 루트 빌드 경로를 한 번에 바꾸지 않고도 1차 확장 세트를 실제 패키지 해석으로 이동시킬 수 있습니다. - -- 모든 사람의 기존 확장 베이스를 대체하는 대신 - `extensions/tsconfig.package-boundary.base.json` 같은 전용 옵트인 경계 베이스 구성을 사용합니다. - 근거: 저장소는 마이그레이션 중 레거시 확장 모드와 옵트인 확장 모드를 동시에 지원해야 합니다. - -- 1차 확장에서 `packages/plugin-sdk/tsconfig.json`으로의 TS 프로젝트 참조를 사용하고 - 옵트인 경계 모드에 대해 `disableSourceOfProjectReferenceRedirect`를 설정합니다. - 근거: 이렇게 하면 `tsc`에 실제 패키지 그래프를 제공하면서, 에디터와 컴파일러가 원시 소스 순회로 되돌아가는 것을 억제할 수 있습니다. - -- 1차 단계에서는 `@openclaw/plugin-sdk`를 private로 유지합니다. - 근거: 즉각적인 목표는 표면이 안정되기 전 제2의 외부 SDK 계약을 게시하는 것이 아니라, 내부 경계 강제와 마이그레이션 안전성입니다. - -- 첫 구현 슬라이스에서는 1차 SDK 서브패스만 이동하고, - 나머지는 호환성 브리지를 유지합니다. - 근거: `src/plugin-sdk/*.ts`의 315개 파일 전체를 하나의 PR에서 물리적으로 이동하는 것은 - 이 계획이 피하려는 바로 그 병합 충돌 표면입니다. - -- 1차 단계에서는 `scripts/postinstall-bundled-plugins.mjs`에 의존해 - SDK 선언을 빌드하지 않습니다. - 근거: 명시적인 빌드/참조 흐름이 이해하기 쉽고 저장소 동작을 더 예측 가능하게 유지합니다. - -## 열린 질문 - -### 계획 수립 중 해결됨 - -- 어떤 확장을 1차에 포함해야 하는가? - 위에 나열된 10개의 provider/web-search 확장을 사용합니다. 더 무거운 채널 패키지보다 구조적으로 더 격리되어 있기 때문입니다. - -- 첫 번째 PR이 전체 확장 트리를 대체해야 하는가? - 아니요. 첫 번째 PR은 두 가지 모드를 병렬로 지원하고 1차 세트만 옵트인해야 합니다. - -- 1차에 postinstall 선언 빌드가 필요한가? - 아니요. 패키지/참조 그래프는 명시적이어야 하며, CI는 관련 패키지 로컬 타입체크를 의도적으로 실행해야 합니다. - -### 구현으로 연기됨 - -- 1차 패키지가 프로젝트 참조만으로 패키지 로컬 `src/*.ts`를 직접 가리킬 수 있는지, 아니면 `@openclaw/plugin-sdk` 패키지에 여전히 소규모 선언 방출 단계가 필요한지 여부 - 이는 구현이 소유하는 TS 그래프 검증 질문입니다. - -- 루트 `openclaw` 패키지가 1차 SDK 서브패스를 즉시 `packages/plugin-sdk` 출력으로 프록시해야 하는지, 아니면 계속 - `src/plugin-sdk` 아래 생성된 호환성 shim을 사용할지 여부 - 이는 CI를 녹색 상태로 유지하는 최소 구현 경로에 따라 달라지는 호환성 및 빌드 형태 세부 사항입니다. - -## 상위 수준 기술 설계 - -> 이는 의도된 접근 방식을 설명하는 것으로, 구현 명세가 아니라 리뷰를 위한 방향성 가이드입니다. 구현 에이전트는 이를 재현할 코드가 아니라 컨텍스트로 취급해야 합니다. - -```mermaid -flowchart TB - subgraph Legacy["레거시 확장(변경 없음)"] - L1["extensions/*\nopenclaw/plugin-sdk/*"] - L2["root tsconfig paths"] - L1 --> L2 - L2 --> L3["src/plugin-sdk/*"] - end - - subgraph OptIn["1차 확장"] - O1["옵트인된 10개 확장"] - O2["extensions/tsconfig.package-boundary.base.json"] - O3["rootDir = '.'\nproject reference"] - O4["@openclaw/plugin-sdk"] - O1 --> O2 - O2 --> O3 - O3 --> O4 - end - - subgraph SDK["새 워크스페이스 패키지"] - P1["packages/plugin-sdk/package.json"] - P2["packages/plugin-sdk/tsconfig.json"] - P3["packages/plugin-sdk/src/.ts"] - P1 --> P2 - P2 --> P3 - end - - O4 --> SDK -``` - -## 구현 단위 - -- [ ] **단위 1: 실제 `@openclaw/plugin-sdk` 워크스페이스 패키지 도입** - -**목표:** 저장소 전체 마이그레이션을 강제하지 않고도 1차 서브패스 표면을 소유할 수 있는 SDK용 실제 워크스페이스 패키지를 만듭니다. - -**요구 사항:** R1, R2, R3, R8, R9 - -**의존성:** 없음 - -**파일:** - -- 생성: `packages/plugin-sdk/package.json` -- 생성: `packages/plugin-sdk/tsconfig.json` -- 생성: `packages/plugin-sdk/src/index.ts` -- 생성: 1차 SDK 서브패스를 위한 `packages/plugin-sdk/src/*.ts` -- 수정: 패키지 글롭 조정이 필요한 경우에만 `pnpm-workspace.yaml` -- 수정: `package.json` -- 수정: `src/plugin-sdk/entrypoints.ts` -- 수정: `scripts/lib/plugin-sdk-entrypoints.json` -- 테스트: `src/plugins/contracts/plugin-sdk-workspace-package.contract.test.ts` - -**접근 방식:** - -- `@openclaw/plugin-sdk`라는 새 워크스페이스 패키지를 추가합니다. -- 전체 315개 파일 트리가 아니라 1차 SDK 서브패스만으로 시작합니다. -- 1차 진입점을 직접 이동하면 diff가 과도하게 커지는 경우, - 첫 번째 PR에서는 먼저 `packages/plugin-sdk/src`에 해당 서브패스를 얇은 - 패키지 래퍼로 도입한 뒤, 후속 PR에서 해당 서브패스 클러스터의 source of truth를 패키지로 전환할 수 있습니다. -- 기존 진입점 인벤토리 메커니즘을 재사용하여 1차 패키지 표면이 하나의 정식 위치에 선언되도록 합니다. -- 워크스페이스 패키지가 새로운 옵트인 계약이 되는 동안 레거시 사용자를 위한 루트 패키지 export는 유지합니다. - -**따를 패턴:** - -- `packages/memory-host-sdk/package.json` -- `packages/plugin-package-contract/package.json` -- `src/plugin-sdk/entrypoints.ts` - -**테스트 시나리오:** - -- 정상 경로: 워크스페이스 패키지가 계획에 나열된 모든 1차 서브패스를 export하며 필요한 1차 export가 누락되지 않습니다. -- 엣지 케이스: 1차 진입점 목록이 재생성되거나 정식 인벤토리와 비교될 때 패키지 export 메타데이터가 안정적으로 유지됩니다. -- 통합: 새 워크스페이스 패키지를 도입한 뒤에도 루트 패키지의 레거시 SDK export가 계속 존재합니다. - -**검증:** - -- 저장소에 안정적인 1차 export 맵을 갖춘 유효한 `@openclaw/plugin-sdk` 워크스페이스 패키지가 존재하며, 루트 `package.json`에 레거시 export 회귀가 없습니다. - -- [ ] **단위 2: 패키지 강제 확장을 위한 옵트인 TS 경계 모드 추가** - -**목표:** 옵트인된 확장이 사용할 TS 구성 모드를 정의하면서, 다른 모든 확장에 대한 기존 확장 TS 동작은 변경하지 않습니다. - -**요구 사항:** R4, R6, R7, R8, R9 - -**의존성:** 단위 1 - -**파일:** - -- 생성: `extensions/tsconfig.package-boundary.base.json` -- 생성: `tsconfig.boundary-optin.json` -- 수정: `extensions/xai/tsconfig.json` -- 수정: `extensions/openai/tsconfig.json` -- 수정: `extensions/anthropic/tsconfig.json` -- 수정: `extensions/mistral/tsconfig.json` -- 수정: `extensions/groq/tsconfig.json` -- 수정: `extensions/together/tsconfig.json` -- 수정: `extensions/perplexity/tsconfig.json` -- 수정: `extensions/tavily/tsconfig.json` -- 수정: `extensions/exa/tsconfig.json` -- 수정: `extensions/firecrawl/tsconfig.json` -- 테스트: `src/plugins/contracts/extension-package-project-boundaries.test.ts` -- 테스트: `test/extension-package-tsc-boundary.test.ts` - -**접근 방식:** - -- 레거시 확장을 위해 `extensions/tsconfig.base.json`은 그대로 둡니다. -- 다음을 수행하는 새 옵트인 베이스 구성을 추가합니다. - - `rootDir: "."` 설정 - - `packages/plugin-sdk` 참조 - - `composite` 활성화 - - 필요 시 프로젝트 참조 소스 리디렉션 비활성화 -- 같은 PR에서 루트 저장소 TS 프로젝트를 재구성하는 대신, - 1차 타입체크 그래프를 위한 전용 솔루션 구성을 추가합니다. - -**실행 참고:** 이 패턴을 10개 전체에 적용하기 전에 -옵트인된 확장 하나에 대해 실패하는 패키지 로컬 카나리 타입체크부터 시작합니다. - -**따를 패턴:** - -- 이전 경계 작업의 기존 패키지 로컬 확장 `tsconfig.json` 패턴 -- `packages/memory-host-sdk`의 워크스페이스 패키지 패턴 - -**테스트 시나리오:** - -- 정상 경로: 각 옵트인 확장이 패키지 경계 TS 구성을 통해 성공적으로 타입체크됩니다. -- 오류 경로: 옵트인된 확장에서 `../../src/cli/acp-cli.ts`로의 카나리 상대 import가 `TS6059`로 실패합니다. -- 통합: 비옵트인 확장은 영향을 받지 않으며 새 솔루션 구성에 참여할 필요가 없습니다. - -**검증:** - -- 10개의 옵트인 확장을 위한 전용 타입체크 그래프가 존재하며, 그중 하나에서 잘못된 상대 import는 일반 `tsc`를 통해 실패합니다. - -- [ ] **단위 3: 1차 확장을 `@openclaw/plugin-sdk`로 마이그레이션** - -**목표:** 1차 확장이 패키지 의존성 메타데이터, 프로젝트 참조, 패키지명 import를 통해 실제 SDK 패키지를 사용하도록 변경합니다. - -**요구 사항:** R5, R6, R7, R9 - -**의존성:** 단위 2 - -**파일:** - -- 수정: `extensions/anthropic/package.json` -- 수정: `extensions/exa/package.json` -- 수정: `extensions/firecrawl/package.json` -- 수정: `extensions/groq/package.json` -- 수정: `extensions/mistral/package.json` -- 수정: `extensions/openai/package.json` -- 수정: `extensions/perplexity/package.json` -- 수정: `extensions/tavily/package.json` -- 수정: `extensions/together/package.json` -- 수정: `extensions/xai/package.json` -- 수정: 현재 `openclaw/plugin-sdk/*`를 참조하는 각 10개 확장 루트 아래의 프로덕션 및 테스트 import - -**접근 방식:** - -- 1차 확장의 `devDependencies`에 - `@openclaw/plugin-sdk: workspace:*`를 추가합니다. -- 해당 패키지의 `openclaw/plugin-sdk/*` import를 - `@openclaw/plugin-sdk/*`로 교체합니다. -- 로컬 확장 내부 import는 `./api.ts` 및 `./runtime-api.ts` 같은 로컬 배럴에 유지합니다. -- 이 PR에서는 비옵트인 확장은 변경하지 않습니다. - -**따를 패턴:** - -- 기존 확장 로컬 import 배럴(`api.ts`, `runtime-api.ts`) -- 다른 `@openclaw/*` 워크스페이스 패키지에서 사용하는 패키지 의존성 형태 - -**테스트 시나리오:** - -- 정상 경로: 마이그레이션된 각 확장이 import 재작성 후에도 기존 플러그인 테스트를 통해 계속 등록/로드됩니다. -- 엣지 케이스: 옵트인 확장 세트의 테스트 전용 SDK import도 새 패키지를 통해 올바르게 해석됩니다. -- 통합: 마이그레이션된 확장은 타입체크를 위해 루트 `openclaw/plugin-sdk/*` 별칭 경로를 필요로 하지 않습니다. - -**검증:** - -- 1차 확장은 레거시 루트 SDK 별칭 경로 없이 `@openclaw/plugin-sdk`를 기준으로 빌드 및 테스트됩니다. - -- [ ] **단위 4: 부분 마이그레이션 중 레거시 호환성 유지** - -**목표:** 마이그레이션 중 SDK가 레거시와 새 패키지 형태로 공존하는 동안 저장소의 나머지 부분이 계속 동작하도록 유지합니다. - -**요구 사항:** R4, R8, R9 - -**의존성:** 단위 1-3 - -**파일:** - -- 수정: 필요 시 1차 호환성 shim을 위한 `src/plugin-sdk/*.ts` -- 수정: `package.json` -- 수정: SDK 아티팩트를 조립하는 빌드 또는 export 배관 -- 테스트: `src/plugins/contracts/plugin-sdk-runtime-api-guardrails.test.ts` -- 테스트: `src/plugins/contracts/plugin-sdk-index.bundle.test.ts` - -**접근 방식:** - -- 아직 이동하지 않은 레거시 확장 및 외부 소비자를 위해 - 루트 `openclaw/plugin-sdk/*`를 호환성 표면으로 유지합니다. -- `packages/plugin-sdk`로 이동한 1차 서브패스에는 생성된 shim 또는 루트 export 프록시 배선을 사용합니다. -- 이 단계에서 루트 SDK 표면을 폐기하려고 하지 않습니다. - -**따를 패턴:** - -- `src/plugin-sdk/entrypoints.ts`를 통한 기존 루트 SDK export 생성 -- 루트 `package.json`의 기존 패키지 export 호환성 - -**테스트 시나리오:** - -- 정상 경로: 새 패키지가 존재한 뒤에도 비옵트인 확장에 대해 레거시 루트 SDK import가 계속 해석됩니다. -- 엣지 케이스: 1차 서브패스가 마이그레이션 기간 동안 레거시 루트 표면과 새 패키지 표면 모두를 통해 동작합니다. -- 통합: plugin-sdk index/bundle 계약 테스트가 계속 일관된 공개 표면을 확인합니다. - -**검증:** - -- 저장소는 변경되지 않은 확장을 깨뜨리지 않으면서 레거시와 옵트인 SDK 소비 모드를 모두 지원합니다. - -- [ ] **단위 5: 범위 지정 강제 추가 및 마이그레이션 계약 문서화** - -**목표:** 전체 확장 트리가 마이그레이션되었다고 가장하지 않으면서, 1차 세트에 대한 새 동작을 강제하는 CI 및 기여자 가이드를 도입합니다. - -**요구 사항:** R5, R6, R8, R9 - -**의존성:** 단위 1-4 - -**파일:** - -- 수정: `package.json` -- 수정: 옵트인 경계 타입체크를 실행해야 하는 CI 워크플로 파일 -- 수정: `AGENTS.md` -- 수정: `docs/plugins/sdk-overview.md` -- 수정: `docs/plugins/sdk-entrypoints.md` -- 수정: `docs/plans/2026-04-05-001-refactor-extension-package-resolution-boundary-plan.md` - -**접근 방식:** - -- `packages/plugin-sdk`와 10개의 옵트인 확장에 대해 전용 `tsc -b` 솔루션 실행 같은 명시적인 1차 게이트를 추가합니다. -- 저장소가 이제 레거시와 옵트인 확장 모드를 모두 지원하며, 새 확장 경계 작업은 새 패키지 경로를 우선 사용해야 한다고 문서화합니다. -- 이후 PR이 아키텍처를 다시 논쟁하지 않고 더 많은 확장을 추가할 수 있도록 다음 웨이브 마이그레이션 규칙을 기록합니다. - -**따를 패턴:** - -- `src/plugins/contracts/` 아래의 기존 계약 테스트 -- 단계적 마이그레이션을 설명하는 기존 문서 업데이트 - -**테스트 시나리오:** - -- 정상 경로: 새 1차 타입체크 게이트가 워크스페이스 패키지와 옵트인 확장에 대해 통과합니다. -- 오류 경로: 옵트인 확장에 새 불법 상대 import를 도입하면 범위 지정 타입체크 게이트가 실패합니다. -- 통합: CI는 아직 비옵트인 확장에 대해 새 패키지 경계 모드를 요구하지 않습니다. - -**검증:** - -- 1차 강제 경로는 전체 확장 트리 마이그레이션을 강제하지 않고도 문서화되고, 테스트되며, 실행 가능합니다. - -## 시스템 전반 영향 - -- **상호작용 그래프:** 이 작업은 SDK source of truth, 루트 패키지 export, 확장 패키지 메타데이터, TS 그래프 레이아웃, CI 검증에 영향을 줍니다. -- **오류 전파:** 주요 의도된 실패 모드는 옵트인 확장에서 사용자 지정 스크립트 전용 실패가 아니라 컴파일 타임 TS 오류(`TS6059`)가 됩니다. -- **상태 수명 주기 위험:** 이중 표면 마이그레이션은 루트 호환성 export와 새 워크스페이스 패키지 사이의 드리프트 위험을 도입합니다. -- **API 표면 동등성:** 전환 중 1차 서브패스는 `openclaw/plugin-sdk/*`와 `@openclaw/plugin-sdk/*`를 통해 의미적으로 동일해야 합니다. -- **통합 범위:** 경계를 증명하려면 단위 테스트만으로는 충분하지 않으며, 범위 지정 패키지 그래프 타입체크가 필요합니다. -- **변경되지 않는 불변 조건:** 비옵트인 확장은 PR 1에서 현재 동작을 유지합니다. 이 계획은 저장소 전체 import 경계 강제를 주장하지 않습니다. - -## 위험 및 의존성 - -| 위험 | 완화책 | -| ---- | ------ | -| 1차 패키지가 여전히 원시 소스로 다시 해석되어 `rootDir`이 실제로 fail-closed 되지 않음 | 첫 구현 단계를 전체 세트로 확대하기 전에, 옵트인 확장 하나에 대한 패키지 참조 카나리로 만듭니다 | -| SDK 소스를 한 번에 너무 많이 이동하여 원래의 병합 충돌 문제가 다시 생김 | 첫 번째 PR에서는 1차 서브패스만 이동하고 루트 호환성 브리지를 유지합니다 | -| 레거시 및 새 SDK 표면이 의미적으로 드리프트함 | 단일 진입점 인벤토리를 유지하고, 호환성 계약 테스트를 추가하며, 이중 표면 동등성을 명시적으로 만듭니다 | -| 루트 저장소의 빌드/테스트 경로가 통제되지 않은 방식으로 우연히 새 패키지에 의존하기 시작함 | 전용 옵트인 솔루션 구성을 사용하고, 첫 번째 PR에서는 루트 전체 TS 토폴로지 변경을 제외합니다 | - -## 단계별 전달 - -### 1단계 - -- `@openclaw/plugin-sdk` 도입 -- 1차 서브패스 표면 정의 -- 하나의 옵트인 확장이 `rootDir`을 통해 fail-closed 될 수 있음을 증명 - -### 2단계 - -- 10개의 1차 확장을 옵트인 -- 나머지 모두를 위해 루트 호환성 유지 - -### 3단계 - -- 이후 PR에서 더 많은 확장 추가 -- 더 많은 SDK 서브패스를 워크스페이스 패키지로 이동 -- 레거시 확장 세트가 사라진 뒤에만 루트 호환성 폐기 - -## 문서 / 운영 참고 사항 - -- 첫 번째 PR은 자신을 저장소 전체 강제 완료가 아니라, 이중 모드 마이그레이션으로 명시적으로 설명해야 합니다. -- 마이그레이션 가이드는 이후 PR이 동일한 패키지/의존성/참조 패턴을 따라 더 많은 확장을 쉽게 추가할 수 있게 해야 합니다. - -## 소스 및 참고 자료 - -- 이전 계획: `docs/plans/2026-04-05-001-refactor-extension-package-resolution-boundary-plan.md` -- 워크스페이스 구성: `pnpm-workspace.yaml` -- 기존 SDK 진입점 인벤토리: `src/plugin-sdk/entrypoints.ts` -- 기존 루트 SDK export: `package.json` -- 기존 워크스페이스 패키지 패턴: - - `packages/memory-host-sdk/package.json` - - `packages/plugin-package-contract/package.json` diff --git a/docs/ko/plugins/architecture.md b/docs/ko/plugins/architecture.md index 727e65861..3ed047a0b 100644 --- a/docs/ko/plugins/architecture.md +++ b/docs/ko/plugins/architecture.md @@ -1,183 +1,148 @@ --- read_when: - - 네이티브 OpenClaw plugin을 빌드하거나 디버깅할 때 - - plugin capability 모델 또는 소유권 경계를 이해할 때 - - plugin 로드 파이프라인 또는 레지스트리 작업을 할 때 - - provider 런타임 hook 또는 channel plugin을 구현할 때 + - 네이티브 OpenClaw 플러그인을 빌드하거나 디버깅할 때 + - 플러그인 capability 모델이나 소유권 경계를 이해할 때 + - 플러그인 로드 파이프라인이나 레지스트리 작업을 할 때 + - 제공자 런타임 훅이나 채널 플러그인을 구현할 때 sidebarTitle: Internals -summary: 'Plugin 내부 구조: capability 모델, 소유권, 계약, 로드 파이프라인, 런타임 도우미' -title: Plugin 내부 구조 +summary: '플러그인 내부 구조: capability 모델, 소유권, 계약, 로드 파이프라인, 런타임 헬퍼' +title: 플러그인 내부 구조 x-i18n: - generated_at: "2026-04-08T02:19:20Z" + generated_at: "2026-04-09T01:33:22Z" model: gpt-5.4 provider: openai - source_hash: c40ecf14e2a0b2b8d332027aed939cd61fb4289a489f4cd4c076c96d707d1138 + source_hash: 2575791f835990589219bb06d8ca92e16a8c38b317f0bfe50b421682f253ef18 source_path: plugins/architecture.md workflow: 15 --- -# Plugin 내부 구조 +# 플러그인 내부 구조 - 이것은 **심층 아키텍처 참고 자료**입니다. 실용적인 가이드는 다음을 참조하세요. - - [plugin 설치 및 사용](/ko/tools/plugin) — 사용자 가이드 - - [시작하기](/ko/plugins/building-plugins) — 첫 plugin 튜토리얼 - - [Channel Plugins](/ko/plugins/sdk-channel-plugins) — 메시징 채널 빌드 - - [Provider Plugins](/ko/plugins/sdk-provider-plugins) — 모델 provider 빌드 - - [SDK 개요](/ko/plugins/sdk-overview) — import 맵과 등록 API + 이 문서는 **심층 아키텍처 참조**입니다. 실용적인 가이드는 다음을 참조하세요. + - [플러그인 설치 및 사용](/ko/tools/plugin) — 사용자 가이드 + - [시작하기](/ko/plugins/building-plugins) — 첫 플러그인 튜토리얼 + - [채널 플러그인](/ko/plugins/sdk-channel-plugins) — 메시징 채널 빌드 + - [제공자 플러그인](/ko/plugins/sdk-provider-plugins) — 모델 제공자 빌드 + - [SDK 개요](/ko/plugins/sdk-overview) — import 맵 및 등록 API -이 페이지는 OpenClaw plugin 시스템의 내부 아키텍처를 다룹니다. +이 페이지에서는 OpenClaw 플러그인 시스템의 내부 아키텍처를 다룹니다. ## 공개 capability 모델 -Capabilities는 OpenClaw 내부의 공개 **네이티브 plugin** 모델입니다. 모든 -네이티브 OpenClaw plugin은 하나 이상의 capability 유형에 대해 등록됩니다. +Capabilities는 OpenClaw 내부의 공개 **네이티브 플러그인** 모델입니다. 모든 네이티브 OpenClaw 플러그인은 하나 이상의 capability 유형에 대해 등록됩니다. -| Capability | 등록 방법 | 예시 plugin | -| ---------------------- | ------------------------------------------------ | ----------------------------------- | -| 텍스트 추론 | `api.registerProvider(...)` | `openai`, `anthropic` | -| CLI 추론 백엔드 | `api.registerCliBackend(...)` | `openai`, `anthropic` | -| 음성 | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` | -| 실시간 전사 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | -| 실시간 음성 | `api.registerRealtimeVoiceProvider(...)` | `openai` | -| 미디어 이해 | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` | +| Capability | 등록 메서드 | 예시 플러그인 | +| ---------------------- | ------------------------------------------------ | ------------------------------------ | +| 텍스트 추론 | `api.registerProvider(...)` | `openai`, `anthropic` | +| CLI 추론 백엔드 | `api.registerCliBackend(...)` | `openai`, `anthropic` | +| 음성 | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` | +| 실시간 전사 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | +| 실시간 음성 | `api.registerRealtimeVoiceProvider(...)` | `openai` | +| 미디어 이해 | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` | | 이미지 생성 | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` | -| 음악 생성 | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` | -| 비디오 생성 | `api.registerVideoGenerationProvider(...)` | `qwen` | -| 웹 가져오기 | `api.registerWebFetchProvider(...)` | `firecrawl` | -| 웹 검색 | `api.registerWebSearchProvider(...)` | `google` | -| 채널 / 메시징 | `api.registerChannel(...)` | `msteams`, `matrix` | +| 음악 생성 | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` | +| 비디오 생성 | `api.registerVideoGenerationProvider(...)` | `qwen` | +| 웹 가져오기 | `api.registerWebFetchProvider(...)` | `firecrawl` | +| 웹 검색 | `api.registerWebSearchProvider(...)` | `google` | +| 채널 / 메시징 | `api.registerChannel(...)` | `msteams`, `matrix` | -capability를 하나도 등록하지 않지만 hook, tool 또는 -service를 제공하는 plugin은 **레거시 hook-only** plugin입니다. 이 패턴도 여전히 완전히 지원됩니다. +capability를 하나도 등록하지 않고 훅, 도구 또는 서비스를 제공하는 플러그인은 **레거시 hook-only** 플러그인입니다. 이 패턴도 여전히 완전히 지원됩니다. ### 외부 호환성 입장 -capability 모델은 이미 core에 반영되어 오늘날 번들/네이티브 plugin에서 -사용되고 있지만, 외부 plugin 호환성에는 여전히 "export되었으니 고정되었다"보다 -더 엄격한 기준이 필요합니다. +capability 모델은 이미 코어에 도입되어 있고 현재 번들/네이티브 플러그인에서 사용되고 있지만, 외부 플러그인 호환성은 여전히 "export되었으니 고정되었다"보다 더 엄격한 기준이 필요합니다. 현재 가이드는 다음과 같습니다. -- **기존 외부 plugin:** hook 기반 통합이 계속 동작하도록 유지하고, - 이를 호환성 기준선으로 취급 -- **새 번들/네이티브 plugin:** 벤더별 직접 접근이나 새로운 hook-only 설계보다 - 명시적 capability 등록을 우선 -- **capability 등록을 채택하는 외부 plugin:** 허용되지만, 문서에서 계약이 안정적이라고 - 명시하지 않는 한 capability별 helper 표면은 진화 중인 것으로 취급 +- **기존 외부 플러그인:** hook 기반 통합이 계속 작동하도록 유지하며, 이를 호환성 기준선으로 취급합니다. +- **새 번들/네이티브 플러그인:** 벤더별 직접 접근이나 새로운 hook-only 설계보다 명시적인 capability 등록을 우선합니다. +- **capability 등록을 도입하는 외부 플러그인:** 허용되지만, 문서에서 계약이 안정적이라고 명시하지 않은 한 capability별 헬퍼 표면은 계속 진화하는 것으로 간주합니다. -실용적인 규칙: +실무 규칙: -- capability 등록 API가 의도된 방향입니다 -- 전환 기간 동안 레거시 hook은 외부 plugin에 가장 안전한 무중단 경로로 남습니다 -- export된 helper subpath가 모두 같은 것은 아닙니다. 우연히 노출된 helper export가 아니라 - 문서화된 좁은 계약을 우선하세요 +- capability 등록 API가 의도된 방향입니다. +- 전환 기간 동안 레거시 훅은 외부 플러그인에 가장 안전한 무중단 경로로 남아 있습니다. +- export된 헬퍼 하위 경로는 모두 동일하지 않습니다. 우연히 노출된 헬퍼 export가 아니라, 문서화된 좁은 계약을 우선하세요. -### Plugin 형태 +### 플러그인 형태 -OpenClaw는 로드된 모든 plugin을 정적 메타데이터가 아니라 실제 -등록 동작에 따라 형태로 분류합니다. +OpenClaw는 로드된 각 플러그인을 정적 메타데이터가 아니라 실제 등록 동작에 따라 형태로 분류합니다. -- **plain-capability** -- 정확히 하나의 capability 유형만 등록함(예: - `mistral` 같은 provider 전용 plugin) -- **hybrid-capability** -- 여러 capability 유형을 등록함(예: - `openai`는 텍스트 추론, 음성, 미디어 이해, 이미지 생성을 소유) -- **hook-only** -- hook만 등록하며(정형 또는 커스텀), capability, - tool, command, service는 등록하지 않음 -- **non-capability** -- tool, command, service, route는 등록하지만 - capability는 등록하지 않음 +- **plain-capability** -- 정확히 하나의 capability 유형만 등록합니다(예: `mistral` 같은 provider-only 플러그인). +- **hybrid-capability** -- 여러 capability 유형을 등록합니다(예: `openai`는 텍스트 추론, 음성, 미디어 이해, 이미지 생성을 담당함). +- **hook-only** -- 훅만 등록하며(typed 또는 custom), capabilities, 도구, 명령, 서비스는 등록하지 않습니다. +- **non-capability** -- 도구, 명령, 서비스, 라우트를 등록하지만 capabilities는 등록하지 않습니다. -plugin의 형태와 capability 분해 정보는 `openclaw plugins inspect `로 확인하세요. -자세한 내용은 [CLI reference](/cli/plugins#inspect)를 참조하세요. +플러그인의 형태와 capability 세부 구성을 보려면 `openclaw plugins inspect `를 사용하세요. 자세한 내용은 [CLI reference](/cli/plugins#inspect)를 참조하세요. -### 레거시 hook +### 레거시 훅 -`before_agent_start` hook은 여전히 hook-only plugin을 위한 -호환성 경로로 지원됩니다. 실제 레거시 plugin이 여전히 이에 의존합니다. +`before_agent_start` 훅은 hook-only 플러그인을 위한 호환성 경로로 계속 지원됩니다. 실제 레거시 플러그인들이 여전히 여기에 의존합니다. -방향은 다음과 같습니다. +방향성: -- 계속 동작하도록 유지 -- 레거시로 문서화 -- 모델/provider override 작업에는 `before_model_resolve`를 우선 -- 프롬프트 변경 작업에는 `before_prompt_build`를 우선 -- 실제 사용이 줄고 fixture 커버리지가 마이그레이션 안전성을 입증한 뒤에만 제거 +- 계속 동작하게 유지합니다. +- 레거시로 문서화합니다. +- 모델/제공자 override 작업에는 `before_model_resolve`를 우선합니다. +- 프롬프트 변경 작업에는 `before_prompt_build`를 우선합니다. +- 실제 사용량이 줄고 fixture 커버리지가 마이그레이션 안전성을 입증한 뒤에만 제거합니다. ### 호환성 신호 -`openclaw doctor` 또는 `openclaw plugins inspect `를 실행하면 -다음 레이블 중 하나를 볼 수 있습니다. +`openclaw doctor` 또는 `openclaw plugins inspect `를 실행하면 다음 레이블 중 하나가 표시될 수 있습니다. -| 신호 | 의미 | -| -------------------------- | ------------------------------------------------------------- | -| **config valid** | 구성이 잘 파싱되고 plugin이 해석됨 | -| **compatibility advisory** | plugin이 지원되지만 오래된 패턴을 사용함(예: `hook-only`) | -| **legacy warning** | plugin이 더 이상 권장되지 않는 `before_agent_start`를 사용함 | -| **hard error** | 구성이 잘못되었거나 plugin 로드에 실패함 | +| Signal | 의미 | +| -------------------------- | ------------------------------------------------------------ | +| **config valid** | 구성이 정상적으로 파싱되고 플러그인이 올바르게 해석됨 | +| **compatibility advisory** | 플러그인이 지원되지만 더 오래된 패턴을 사용함(예: `hook-only`) | +| **legacy warning** | 플러그인이 `before_agent_start`를 사용하고 있으며, 이는 deprecated됨 | +| **hard error** | 구성이 잘못되었거나 플러그인 로드에 실패함 | -`hook-only`와 `before_agent_start`는 현재 plugin을 깨뜨리지 않습니다 -- -`hook-only`는 권고 수준이고, `before_agent_start`는 경고만 발생시킵니다. 이러한 -신호는 `openclaw status --all`과 `openclaw plugins doctor`에도 표시됩니다. +현재 `hook-only`나 `before_agent_start` 때문에 플러그인이 깨지지는 않습니다. `hook-only`는 권고 수준이며, `before_agent_start`는 경고만 발생시킵니다. 이 신호들은 `openclaw status --all`과 `openclaw plugins doctor`에도 표시됩니다. ## 아키텍처 개요 -OpenClaw의 plugin 시스템에는 네 개의 계층이 있습니다. +OpenClaw의 플러그인 시스템은 네 개의 계층으로 구성됩니다. -1. **매니페스트 + 발견** - OpenClaw는 구성된 경로, workspace 루트, - 전역 확장 루트, 번들 확장에서 후보 plugin을 찾습니다. 발견 과정은 먼저 네이티브 - `openclaw.plugin.json` 매니페스트와 지원되는 번들 매니페스트를 읽습니다. +1. **매니페스트 + 디스커버리** + OpenClaw는 구성된 경로, 워크스페이스 루트, 전역 확장 루트, 번들 확장에서 후보 플러그인을 찾습니다. 디스커버리는 네이티브 `openclaw.plugin.json` 매니페스트와 지원되는 번들 매니페스트를 먼저 읽습니다. 2. **활성화 + 검증** - Core는 발견된 plugin이 활성화, 비활성화, 차단, - 또는 memory 같은 독점 슬롯에 선택되었는지 결정합니다. + 코어는 디스커버리된 플러그인이 활성화, 비활성화, 차단, 또는 메모리 같은 독점 슬롯에 선택되었는지 결정합니다. 3. **런타임 로딩** - 네이티브 OpenClaw plugin은 jiti를 통해 프로세스 내부에서 로드되어 - 중앙 레지스트리에 capability를 등록합니다. 호환 번들은 - 런타임 코드를 import하지 않고 레지스트리 레코드로 정규화됩니다. + 네이티브 OpenClaw 플러그인은 jiti를 통해 프로세스 내부에서 로드되고 중앙 레지스트리에 capabilities를 등록합니다. 호환 가능한 번들은 런타임 코드를 import하지 않고도 레지스트리 레코드로 정규화됩니다. 4. **표면 소비** - OpenClaw의 나머지 부분은 레지스트리를 읽어 tool, 채널, provider - 설정, hook, HTTP route, CLI command, service를 노출합니다. + OpenClaw의 나머지 부분은 레지스트리를 읽어 도구, 채널, 제공자 설정, 훅, HTTP 라우트, CLI 명령, 서비스를 노출합니다. -특히 plugin CLI의 경우 루트 command 발견은 두 단계로 나뉩니다. +특히 플러그인 CLI의 경우, 루트 명령 디스커버리는 두 단계로 나뉩니다. -- 파싱 시점 메타데이터는 `registerCli(..., { descriptors: [...] })`에서 옴 -- 실제 plugin CLI 모듈은 지연 로드된 상태를 유지하다가 첫 호출 시 등록될 수 있음 +- parse 시점 메타데이터는 `registerCli(..., { descriptors: [...] })`에서 옵니다. +- 실제 플러그인 CLI 모듈은 지연 로딩된 상태로 있다가 첫 호출 시 등록될 수 있습니다. -이렇게 하면 plugin 소유 CLI 코드를 plugin 내부에 두면서도 OpenClaw가 -파싱 전에 루트 command 이름을 예약할 수 있습니다. +이렇게 하면 OpenClaw가 파싱 전에 루트 명령 이름을 예약하면서도 플러그인 소유 CLI 코드는 플러그인 내부에 유지할 수 있습니다. 중요한 설계 경계: -- 발견 + 구성 검증은 plugin 코드를 실행하지 않고 **매니페스트/스키마 메타데이터**로 - 동작해야 합니다 -- 네이티브 런타임 동작은 plugin 모듈의 `register(api)` 경로에서 옵니다 +- 디스커버리 + config 검증은 플러그인 코드를 실행하지 않고 **매니페스트/스키마 메타데이터**만으로 동작해야 합니다. +- 네이티브 런타임 동작은 플러그인 모듈의 `register(api)` 경로에서 옵니다. -이 분리를 통해 OpenClaw는 전체 런타임이 활성화되기 전에 -구성을 검증하고, 누락/비활성화된 plugin을 설명하며, UI/스키마 힌트를 -구성할 수 있습니다. +이 분리는 OpenClaw가 전체 런타임이 활성화되기 전에 config를 검증하고, 누락되거나 비활성화된 플러그인을 설명하고, UI/스키마 힌트를 구성할 수 있게 합니다. -### Channel plugin과 공유 message tool +### 채널 플러그인과 공유 message 도구 -Channel plugin은 일반 채팅 작업을 위해 별도의 send/edit/react tool을 -등록할 필요가 없습니다. OpenClaw는 core에 하나의 공유 `message` tool을 유지하고, -channel plugin은 그 뒤의 채널별 발견 및 실행을 소유합니다. +채널 플러그인은 일반적인 채팅 작업을 위해 별도의 send/edit/react 도구를 등록할 필요가 없습니다. OpenClaw는 코어에 하나의 공유 `message` 도구를 유지하고, 채널 플러그인은 그 뒤의 채널별 디스커버리와 실행을 담당합니다. 현재 경계는 다음과 같습니다. -- core는 공유 `message` tool 호스트, 프롬프트 연결, 세션/스레드 - 기록 유지, 실행 디스패치를 소유 -- channel plugin은 범위 지정된 작업 발견, capability 발견, 채널별 스키마 조각을 소유 -- channel plugin은 대화 id가 스레드 id를 어떻게 인코딩하거나 부모 대화에서 상속하는지 같은 - provider별 세션 대화 문법을 소유 -- channel plugin은 자신의 작업 adapter를 통해 최종 작업을 실행 +- 코어는 공유 `message` 도구 호스트, 프롬프트 연결, 세션/스레드 bookkeeping, 실행 디스패치를 담당합니다. +- 채널 플러그인은 범위 지정된 액션 디스커버리, capability 디스커버리, 채널별 스키마 조각을 담당합니다. +- 채널 플러그인은 대화 ID가 스레드 ID를 인코딩하거나 상위 대화에서 상속하는 방식처럼, 제공자별 세션 대화 문법을 담당합니다. +- 채널 플러그인은 액션 어댑터를 통해 최종 액션을 실행합니다. -channel plugin의 SDK 표면은 -`ChannelMessageActionAdapter.describeMessageTool(...)`입니다. 이 통합 발견 -호출을 통해 plugin은 표시 가능한 작업, capability, 스키마 기여를 -함께 반환할 수 있으므로 이 조각들이 서로 어긋나지 않습니다. +채널 플러그인의 SDK 표면은 `ChannelMessageActionAdapter.describeMessageTool(...)`입니다. 이 통합 디스커버리 호출을 통해 플러그인은 노출되는 액션, capabilities, 스키마 기여를 함께 반환할 수 있으므로 이 요소들이 서로 어긋나지 않습니다. -Core는 그 발견 단계에 런타임 범위를 전달합니다. 중요한 필드는 다음과 같습니다. +코어는 런타임 범위를 이 디스커버리 단계에 전달합니다. 중요한 필드는 다음과 같습니다. - `accountId` - `currentChannelId` @@ -186,120 +151,87 @@ Core는 그 발견 단계에 런타임 범위를 전달합니다. 중요한 필 - `sessionKey` - `sessionId` - `agentId` -- 신뢰된 인바운드 `requesterSenderId` +- 신뢰된 inbound `requesterSenderId` -이것은 컨텍스트 민감 plugin에 중요합니다. 채널은 core `message` tool에 -채널별 분기를 하드코딩하지 않고도 활성 계정, 현재 방/스레드/메시지, -또는 신뢰된 요청자 ID에 따라 메시지 작업을 숨기거나 노출할 수 있습니다. +이 점은 컨텍스트 민감형 플러그인에서 중요합니다. 채널은 코어 `message` 도구에 채널별 분기를 하드코딩하지 않고도, 활성 계정, 현재 룸/스레드/메시지, 또는 신뢰된 요청자 ID에 따라 메시지 액션을 숨기거나 노출할 수 있습니다. -이 때문에 내장 러너 라우팅 변경은 여전히 plugin 작업입니다. 러너는 -현재 턴에 맞는 채널 소유 표면을 공유 `message` tool이 노출하도록 -현재 채팅/세션 ID를 plugin 발견 경계로 전달할 책임이 있습니다. +그래서 embedded-runner 라우팅 변경은 여전히 플러그인 작업입니다. 러너는 현재 채팅/세션 ID를 플러그인 디스커버리 경계로 전달해, 공유 `message` 도구가 현재 턴에 맞는 채널 소유 표면을 노출하도록 해야 합니다. -채널 소유 실행 helper의 경우 번들 plugin은 실행 -런타임을 자신의 확장 모듈 내부에 유지해야 합니다. Core는 더 이상 Discord, -Slack, Telegram, WhatsApp 메시지 작업 런타임을 `src/agents/tools` -아래에서 소유하지 않습니다. 별도의 `plugin-sdk/*-action-runtime` subpath는 -게시하지 않으며, 번들 plugin은 자신의 로컬 런타임 코드를 -확장 소유 모듈에서 직접 import해야 합니다. +채널 소유 실행 헬퍼의 경우, 번들 플러그인은 실행 런타임을 자체 확장 모듈 내부에 유지해야 합니다. 코어는 더 이상 `src/agents/tools` 아래의 Discord, Slack, Telegram, WhatsApp 메시지 액션 런타임을 소유하지 않습니다. 별도의 `plugin-sdk/*-action-runtime` 하위 경로도 공개하지 않으며, 번들 플러그인은 확장 소유 모듈에서 자체 로컬 런타임 코드를 직접 import해야 합니다. -같은 경계는 일반적인 provider 이름이 붙은 SDK seam에도 적용됩니다. Core는 -Slack, Discord, Signal, WhatsApp 또는 유사한 확장의 채널별 편의 barrel을 -import해서는 안 됩니다. Core에 어떤 동작이 필요하다면 번들 plugin 자체의 -`api.ts` / `runtime-api.ts` barrel을 소비하거나, 그 필요를 -공유 SDK의 좁은 일반 capability로 승격해야 합니다. +같은 경계는 일반적인 provider 이름 기반 SDK seam에도 적용됩니다. 코어는 Slack, Discord, Signal, WhatsApp 같은 확장의 채널별 편의 barrel을 import해서는 안 됩니다. 코어에 어떤 동작이 필요하다면 번들 플러그인 자체의 `api.ts` / `runtime-api.ts` barrel을 사용하거나, 필요 사항을 공유 SDK의 좁고 일반적인 capability로 승격해야 합니다. -특히 poll에는 두 가지 실행 경로가 있습니다. +특히 poll의 경우 실행 경로는 두 가지입니다. -- `outbound.sendPoll`은 공통 poll 모델에 맞는 채널을 위한 공유 기준선 -- `actions.handleAction("poll")`은 채널별 poll 의미론 또는 추가 poll 파라미터를 위한 - 선호 경로 +- `outbound.sendPoll`은 공통 poll 모델에 맞는 채널을 위한 공유 기준선입니다. +- `actions.handleAction("poll")`은 채널별 poll 의미론이나 추가 poll 파라미터가 있을 때 우선되는 경로입니다. -Core는 이제 plugin poll 디스패치가 작업을 거절한 뒤에야 공유 poll 파싱을 -연기하므로, plugin 소유 poll 핸들러는 일반 poll 파서에 먼저 막히지 않고 -채널별 poll 필드를 수용할 수 있습니다. +이제 코어는 플러그인 poll 디스패치가 액션을 거절한 뒤에야 공유 poll 파싱을 수행하므로, 플러그인 소유 poll 핸들러는 먼저 일반 poll 파서에 막히지 않고 채널별 poll 필드를 받을 수 있습니다. -전체 시작 순서는 [로드 파이프라인](#load-pipeline)을 참조하세요. +전체 시작 시퀀스는 [로드 파이프라인](#load-pipeline)을 참조하세요. ## capability 소유권 모델 -OpenClaw는 네이티브 plugin을 관련 없는 통합의 묶음이 아니라 **회사** 또는 -**기능**의 소유권 경계로 취급합니다. +OpenClaw는 네이티브 플러그인을 관련 없는 통합 모음이 아니라 **회사** 또는 **기능**의 소유권 경계로 취급합니다. -이는 다음을 의미합니다. +즉, 다음을 의미합니다. -- 회사 plugin은 일반적으로 해당 회사의 OpenClaw 표면 전체를 소유해야 합니다 -- 기능 plugin은 일반적으로 자신이 도입하는 전체 기능 표면을 소유해야 합니다 -- 채널은 provider 동작을 임시방편으로 재구현하기보다 공유 core capability를 소비해야 합니다 +- 회사 플러그인은 일반적으로 해당 회사의 OpenClaw 표면을 모두 소유해야 합니다. +- 기능 플러그인은 일반적으로 자신이 도입한 전체 기능 표면을 소유해야 합니다. +- 채널은 제공자 동작을 임시로 재구현하기보다 공유 코어 capabilities를 소비해야 합니다. 예시: -- 번들 `openai` plugin은 OpenAI 모델 provider 동작과 OpenAI - 음성 + 실시간 음성 + 미디어 이해 + 이미지 생성 동작을 소유 -- 번들 `elevenlabs` plugin은 ElevenLabs 음성 동작을 소유 -- 번들 `microsoft` plugin은 Microsoft 음성 동작을 소유 -- 번들 `google` plugin은 Google 모델 provider 동작과 함께 Google - 미디어 이해 + 이미지 생성 + 웹 검색 동작을 소유 -- 번들 `firecrawl` plugin은 Firecrawl 웹 가져오기 동작을 소유 -- 번들 `minimax`, `mistral`, `moonshot`, `zai` plugin은 자신의 - 미디어 이해 백엔드를 소유 -- 번들 `qwen` plugin은 Qwen 텍스트 provider 동작과 함께 - 미디어 이해 및 비디오 생성 동작을 소유 -- `voice-call` plugin은 기능 plugin입니다. 이 plugin은 통화 transport, tool, - CLI, route, Twilio 미디어 스트림 브리징을 소유하지만, 벤더 plugin을 직접 import하는 대신 - 공유 음성과 실시간 전사/실시간 음성 capability를 소비합니다 +- 번들 `openai` 플러그인은 OpenAI 모델 제공자 동작과 OpenAI 음성 + 실시간 음성 + 미디어 이해 + 이미지 생성 동작을 소유합니다. +- 번들 `elevenlabs` 플러그인은 ElevenLabs 음성 동작을 소유합니다. +- 번들 `microsoft` 플러그인은 Microsoft 음성 동작을 소유합니다. +- 번들 `google` 플러그인은 Google 모델 제공자 동작과 Google 미디어 이해 + 이미지 생성 + 웹 검색 동작을 소유합니다. +- 번들 `firecrawl` 플러그인은 Firecrawl 웹 가져오기 동작을 소유합니다. +- 번들 `minimax`, `mistral`, `moonshot`, `zai` 플러그인은 미디어 이해 백엔드를 소유합니다. +- 번들 `qwen` 플러그인은 Qwen 텍스트 제공자 동작과 미디어 이해 및 비디오 생성 동작을 소유합니다. +- `voice-call` 플러그인은 기능 플러그인입니다. 통화 전송, 도구, CLI, 라우트, Twilio 미디어 스트림 브리징을 소유하지만, 벤더 플러그인을 직접 import하는 대신 공유 음성 + 실시간 전사 + 실시간 음성 capabilities를 소비합니다. 의도된 최종 상태는 다음과 같습니다. -- OpenAI는 텍스트 모델, 음성, 이미지, 향후 비디오를 아우르더라도 하나의 plugin에 존재 -- 다른 벤더도 자신의 표면 영역에 대해 같은 방식을 취할 수 있음 -- 채널은 어떤 벤더 plugin이 provider를 소유하는지 신경 쓰지 않고, core가 노출하는 - 공유 capability 계약을 소비 +- OpenAI가 텍스트 모델, 음성, 이미지, 미래의 비디오까지 포괄하더라도 하나의 플러그인 안에 존재합니다. +- 다른 벤더도 자기 표면 전체를 같은 방식으로 소유할 수 있습니다. +- 채널은 어떤 벤더 플러그인이 제공자를 소유하는지 신경 쓰지 않고, 코어가 노출하는 공유 capability 계약을 소비합니다. 이것이 핵심 구분입니다. - **plugin** = 소유권 경계 -- **capability** = 여러 plugin이 구현하거나 소비할 수 있는 core 계약 +- **capability** = 여러 플러그인이 구현하거나 소비할 수 있는 코어 계약 -따라서 OpenClaw가 비디오 같은 새로운 도메인을 추가할 때 첫 질문은 -"어떤 provider가 비디오 처리를 하드코딩해야 하는가?"가 아닙니다. 첫 질문은 -"core 비디오 capability 계약이 무엇인가?"입니다. 그 계약이 존재하면 벤더 plugin은 -그에 대해 등록할 수 있고, 채널/기능 plugin은 그것을 소비할 수 있습니다. +따라서 OpenClaw가 비디오 같은 새 도메인을 추가할 때 첫 질문은 "어떤 제공자에 비디오 처리를 하드코딩해야 하는가?"가 아닙니다. 첫 질문은 "코어 비디오 capability 계약이 무엇인가?"입니다. 그 계약이 존재하면, 벤더 플러그인이 여기에 등록하고 채널/기능 플러그인이 이를 소비할 수 있습니다. -capability가 아직 존재하지 않는다면 일반적으로 올바른 조치는 다음과 같습니다. +아직 capability가 없다면 보통 올바른 순서는 다음과 같습니다. -1. core에서 누락된 capability를 정의 -2. 그것을 plugin API/런타임을 통해 정형 방식으로 노출 -3. 채널/기능을 그 capability에 맞게 연결 -4. 벤더 plugin이 구현을 등록하게 함 +1. 코어에 누락된 capability를 정의합니다. +2. 플러그인 API/런타임을 통해 이를 typed 방식으로 노출합니다. +3. 채널/기능을 그 capability에 연결합니다. +4. 벤더 플러그인이 구현체를 등록하도록 합니다. -이렇게 하면 소유권이 명시적으로 유지되면서도 -단일 벤더 또는 일회성 plugin별 코드 경로에 의존하는 core 동작을 피할 수 있습니다. +이렇게 하면 소유권은 명확하게 유지하면서도, 단일 벤더나 일회성 플러그인별 코드 경로에 의존하는 코어 동작을 피할 수 있습니다. -### Capability 계층 +### capability 계층화 -코드가 어디에 속하는지 결정할 때 다음과 같이 생각하세요. +코드가 어디에 속해야 하는지 결정할 때 다음 사고 모델을 사용하세요. -- **core capability 계층**: 공유 오케스트레이션, 정책, fallback, config - 병합 규칙, 전달 의미론, 정형 계약 -- **벤더 plugin 계층**: 벤더별 API, 인증, 모델 카탈로그, 음성 - 합성, 이미지 생성, 향후 비디오 백엔드, 사용량 엔드포인트 -- **채널/기능 plugin 계층**: Slack/Discord/voice-call 등 통합으로 - core capability를 소비해 표면에 제시 +- **코어 capability 계층**: 공유 orchestration, 정책, fallback, config 병합 규칙, 전달 의미론, typed 계약 +- **벤더 플러그인 계층**: 벤더별 API, 인증, 모델 카탈로그, 음성 합성, 이미지 생성, 미래의 비디오 백엔드, 사용량 엔드포인트 +- **채널/기능 플러그인 계층**: 코어 capabilities를 소비하고 이를 표면에 노출하는 Slack/Discord/voice-call 등의 통합 -예를 들어 TTS는 다음 형태를 따릅니다. +예를 들어 TTS는 다음 구조를 따릅니다. -- core는 응답 시점 TTS 정책, fallback 순서, 환경설정, 채널 전달을 소유 -- `openai`, `elevenlabs`, `microsoft`는 합성 구현을 소유 -- `voice-call`은 전화용 TTS 런타임 helper를 소비 +- 코어는 응답 시점 TTS 정책, fallback 순서, 환경설정, 채널 전달을 소유합니다. +- `openai`, `elevenlabs`, `microsoft`는 합성 구현을 소유합니다. +- `voice-call`은 전화용 TTS 런타임 헬퍼를 소비합니다. -향후 capability에도 같은 패턴을 우선해야 합니다. +이 패턴은 미래의 capabilities에도 동일하게 적용하는 것이 바람직합니다. -### 다중 capability 회사 plugin 예시 +### 다중 capability 회사 플러그인 예시 -회사 plugin은 외부에서 볼 때 응집된 느낌이어야 합니다. OpenClaw에 모델, 음성, -실시간 전사, 실시간 음성, 미디어 이해, 이미지 생성, 비디오 생성, 웹 가져오기, 웹 검색을 위한 -공유 계약이 있다면, 한 벤더는 모든 표면을 한 곳에서 소유할 수 있습니다. +회사 플러그인은 외부에서 볼 때 일관된 하나의 단위처럼 느껴져야 합니다. OpenClaw에 모델, 음성, 실시간 전사, 실시간 음성, 미디어 이해, 이미지 생성, 비디오 생성, 웹 가져오기, 웹 검색을 위한 공유 계약이 있다면, 벤더는 이 모든 표면을 한 곳에서 소유할 수 있습니다. ```ts import type { OpenClawPluginDefinition } from "openclaw/plugin-sdk/plugin-entry"; @@ -319,7 +251,7 @@ const plugin: OpenClawPluginDefinition = { api.registerSpeechProvider({ id: "exampleai", - // vendor speech config — SpeechProviderPlugin 인터페이스를 직접 구현 + // vendor speech config — implement the SpeechProviderPlugin interface directly }); api.registerMediaUnderstandingProvider({ @@ -353,218 +285,177 @@ const plugin: OpenClawPluginDefinition = { export default plugin; ``` -중요한 것은 정확한 helper 이름이 아닙니다. 중요한 것은 형태입니다. +중요한 것은 정확한 헬퍼 이름이 아닙니다. 중요한 것은 구조입니다. -- 하나의 plugin이 벤더 표면을 소유 -- core는 여전히 capability 계약을 소유 -- 채널과 기능 plugin은 벤더 코드가 아니라 `api.runtime.*` helper를 소비 -- 계약 테스트는 plugin이 자신이 소유한다고 주장하는 capability를 등록했는지 검증할 수 있음 +- 하나의 플러그인이 벤더 표면을 소유합니다. +- 코어는 여전히 capability 계약을 소유합니다. +- 채널과 기능 플러그인은 벤더 코드가 아니라 `api.runtime.*` 헬퍼를 소비합니다. +- 계약 테스트는 플러그인이 자신이 소유한다고 주장하는 capabilities를 실제로 등록했는지 검증할 수 있습니다. -### Capability 예시: 비디오 이해 +### capability 예시: 비디오 이해 -OpenClaw는 이미 이미지/오디오/비디오 이해를 하나의 공유 -capability로 취급합니다. 동일한 소유권 모델이 여기에 적용됩니다. +OpenClaw는 이미 이미지/오디오/비디오 이해를 하나의 공유 capability로 취급합니다. 동일한 소유권 모델이 여기에 적용됩니다. -1. core가 media-understanding 계약을 정의 -2. 벤더 plugin이 해당하는 경우 `describeImage`, `transcribeAudio`, - `describeVideo`를 등록 -3. 채널과 기능 plugin은 벤더 코드에 직접 연결하지 않고 공유 core 동작을 소비 +1. 코어가 media-understanding 계약을 정의합니다. +2. 벤더 플러그인은 해당되는 경우 `describeImage`, `transcribeAudio`, `describeVideo`를 등록합니다. +3. 채널과 기능 플러그인은 벤더 코드에 직접 연결하지 않고 공유 코어 동작을 소비합니다. -이렇게 하면 특정 provider의 비디오 가정을 core에 고정하지 않게 됩니다. plugin이 -벤더 표면을 소유하고, core는 capability 계약과 fallback 동작을 소유합니다. +이렇게 하면 특정 제공자의 비디오 가정을 코어에 굳혀 넣지 않게 됩니다. 플러그인은 벤더 표면을 소유하고, 코어는 capability 계약과 fallback 동작을 소유합니다. -비디오 생성도 이미 같은 순서를 따릅니다. core가 정형 -capability 계약과 런타임 helper를 소유하고, 벤더 plugin이 -`api.registerVideoGenerationProvider(...)` 구현을 등록합니다. +비디오 생성도 이미 같은 순서를 따릅니다. 코어는 typed capability 계약과 런타임 헬퍼를 소유하고, 벤더 플러그인은 여기에 대해 `api.registerVideoGenerationProvider(...)` 구현을 등록합니다. -구체적인 출시 체크리스트가 필요하신가요? [Capability Cookbook](/ko/plugins/architecture)을 -참조하세요. +구체적인 rollout 체크리스트가 필요하다면 [Capability Cookbook](/ko/plugins/architecture)를 참조하세요. ## 계약과 강제 -plugin API 표면은 의도적으로 `OpenClawPluginApi`에 정형화되어 중앙화되어 있습니다. -이 계약은 지원되는 등록 지점과 plugin이 의존할 수 있는 런타임 helper를 정의합니다. +플러그인 API 표면은 의도적으로 `OpenClawPluginApi`에 typed되고 중앙 집중화되어 있습니다. 이 계약은 지원되는 등록 지점과 플러그인이 의존할 수 있는 런타임 헬퍼를 정의합니다. 이것이 중요한 이유: -- plugin 작성자는 하나의 안정적인 내부 표준을 얻음 -- core는 두 plugin이 같은 provider id를 등록하는 것 같은 중복 소유권을 거부할 수 있음 -- 시작 시 잘못된 등록에 대해 실행 가능한 진단을 표시할 수 있음 -- 계약 테스트는 번들 plugin 소유권을 강제하고 조용한 드리프트를 방지할 수 있음 +- 플러그인 작성자는 하나의 안정적인 내부 표준을 얻게 됩니다. +- 코어는 두 플러그인이 같은 provider ID를 등록하는 중복 소유권을 거부할 수 있습니다. +- 시작 시 잘못된 등록에 대해 실행 가능한 진단을 표시할 수 있습니다. +- 계약 테스트는 번들 플러그인 소유권을 강제하고 조용한 드리프트를 방지할 수 있습니다. 강제에는 두 계층이 있습니다. 1. **런타임 등록 강제** - plugin 레지스트리는 plugin 로드 중 등록을 검증합니다. 예: - 중복 provider id, 중복 speech provider id, 잘못된 - 등록은 정의되지 않은 동작 대신 plugin 진단을 생성합니다. + 플러그인 레지스트리는 플러그인이 로드되면서 등록을 검증합니다. 예를 들어 중복 provider ID, 중복 음성 provider ID, 잘못된 등록은 정의되지 않은 동작이 아니라 플러그인 진단으로 처리됩니다. 2. **계약 테스트** - 번들 plugin은 테스트 실행 중 계약 레지스트리에 캡처되므로 - OpenClaw는 소유권을 명시적으로 검증할 수 있습니다. 현재 이는 모델 - provider, speech provider, web search provider, 번들 등록 - 소유권에 사용됩니다. + 번들 플러그인은 테스트 실행 중 계약 레지스트리에 캡처되므로, OpenClaw가 소유권을 명시적으로 검증할 수 있습니다. 현재는 모델 제공자, 음성 제공자, 웹 검색 제공자, 번들 등록 소유권에 대해 사용됩니다. -실질적인 효과는 OpenClaw가 어떤 plugin이 어떤 표면을 소유하는지 -미리 안다는 점입니다. 이것은 소유권이 암묵적인 것이 아니라 선언되고, -정형화되며, 테스트 가능하므로 core와 채널이 매끄럽게 조합될 수 있게 합니다. +실질적인 효과는 OpenClaw가 어떤 플러그인이 어떤 표면을 소유하는지 미리 알고 있다는 점입니다. 덕분에 소유권이 암묵적이지 않고 선언적이며 typed되고 테스트 가능하므로, 코어와 채널이 자연스럽게 조합될 수 있습니다. -### 계약에 포함되어야 할 것 +### 계약에 포함되어야 하는 것 -좋은 plugin 계약은 다음과 같습니다. +좋은 플러그인 계약은 다음과 같습니다. -- 정형화됨 +- typed - 작음 -- capability별 -- core가 소유 -- 여러 plugin이 재사용 가능 -- 채널/기능이 벤더 지식 없이 소비 가능 +- capability별로 분리됨 +- 코어가 소유함 +- 여러 플러그인이 재사용 가능함 +- 채널/기능이 벤더 지식 없이 소비 가능함 -나쁜 plugin 계약은 다음과 같습니다. +좋지 않은 플러그인 계약은 다음과 같습니다. -- core에 숨겨진 벤더별 정책 -- 레지스트리를 우회하는 일회성 plugin 탈출구 -- 채널 코드가 벤더 구현에 مباشرة로 접근 +- 코어에 숨겨진 벤더별 정책 +- 레지스트리를 우회하는 일회성 플러그인 탈출구 +- 벤더 구현에 직접 접근하는 채널 코드 - `OpenClawPluginApi` 또는 `api.runtime`의 일부가 아닌 임시 런타임 객체 -확실하지 않다면 추상화 수준을 올리세요. 먼저 capability를 정의하고, -그다음 plugin이 거기에 연결되게 하세요. +헷갈릴 때는 추상화 수준을 올리세요. 먼저 capability를 정의하고, 그다음 플러그인이 여기에 연결되게 하세요. ## 실행 모델 -네이티브 OpenClaw plugin은 Gateway와 **같은 프로세스 내부**에서 실행됩니다. 샌드박스되지 -않습니다. 로드된 네이티브 plugin은 core 코드와 동일한 프로세스 수준 신뢰 경계를 가집니다. +네이티브 OpenClaw 플러그인은 Gateway와 **같은 프로세스 내부**에서 실행됩니다. 샌드박스되지 않습니다. 로드된 네이티브 플러그인은 코어 코드와 같은 프로세스 수준 신뢰 경계를 가집니다. -영향: +의미하는 바: -- 네이티브 plugin은 tool, 네트워크 핸들러, hook, service를 등록할 수 있음 -- 네이티브 plugin 버그는 gateway를 크래시시키거나 불안정하게 만들 수 있음 -- 악성 네이티브 plugin은 OpenClaw 프로세스 내부의 임의 코드 실행과 동일함 +- 네이티브 플러그인은 도구, 네트워크 핸들러, 훅, 서비스를 등록할 수 있습니다. +- 네이티브 플러그인 버그는 gateway를 크래시시키거나 불안정하게 만들 수 있습니다. +- 악의적인 네이티브 플러그인은 OpenClaw 프로세스 내부의 임의 코드 실행과 동등합니다. -호환 번들은 현재 OpenClaw가 이를 메타데이터/콘텐츠 팩으로 취급하므로 -기본적으로 더 안전합니다. 현재 릴리스에서 이는 주로 번들 -Skills를 의미합니다. +호환 가능한 번들은 OpenClaw가 현재 이를 메타데이터/콘텐츠 팩으로 취급하므로 기본적으로 더 안전합니다. 현재 릴리스에서는 대체로 번들 Skills가 이에 해당합니다. -비번들 plugin에는 allowlist와 명시적 설치/로드 경로를 사용하세요. Workspace plugin은 -프로덕션 기본값이 아니라 개발 시점 코드로 취급하세요. +번들되지 않은 플러그인에는 allowlist와 명시적 install/load 경로를 사용하세요. 워크스페이스 플러그인은 프로덕션 기본값이 아니라 개발 시점 코드로 취급하세요. -번들 workspace 패키지 이름의 경우 plugin id가 npm -이름에 고정되도록 유지하세요. 기본은 `@openclaw/`이며, 또는 -패키지가 의도적으로 더 좁은 plugin 역할을 노출할 때 -`-provider`, `-plugin`, `-speech`, `-sandbox`, `-media-understanding` 같은 -승인된 typed suffix를 사용합니다. +번들 워크스페이스 패키지 이름의 경우, 플러그인 ID를 npm 이름에 고정하세요. 기본적으로 `@openclaw/`를 사용하거나, 패키지가 더 좁은 플러그인 역할을 의도적으로 노출할 때는 승인된 typed 접미사인 `-provider`, `-plugin`, `-speech`, `-sandbox`, `-media-understanding`를 사용합니다. -중요한 신뢰 참고 사항: +중요한 신뢰 메모: -- `plugins.allow`는 소스 출처가 아니라 **plugin id**를 신뢰합니다. -- 번들 plugin과 같은 id를 가진 workspace plugin은, 그 workspace plugin이 활성화/허용 목록에 있으면, - 의도적으로 번들 복사본을 가립니다. -- 이는 로컬 개발, 패치 테스트, 핫픽스에 정상적이고 유용합니다. +- `plugins.allow`는 소스 출처가 아니라 **플러그인 ID**를 신뢰합니다. +- 번들 플러그인과 같은 ID를 가진 워크스페이스 플러그인이 활성화되거나 allowlist에 들어가면 의도적으로 번들 사본을 가립니다. +- 이는 로컬 개발, 패치 테스트, 핫픽스에 유용한 정상 동작입니다. ## export 경계 -OpenClaw는 구현 편의성이 아니라 capability를 export합니다. +OpenClaw는 구현 편의성이 아니라 capabilities를 export합니다. -capability 등록은 공개 상태로 유지하세요. 계약이 아닌 helper export는 줄이세요. +capability 등록은 공개 상태로 유지하고, 계약이 아닌 헬퍼 export는 줄이세요. -- 번들 plugin 전용 helper subpath -- 공개 API가 아닌 런타임 배관 subpath -- 벤더별 편의 helper -- 구현 세부 사항인 설정/온보딩 helper +- 번들 플러그인별 헬퍼 하위 경로 +- 공개 API로 의도되지 않은 런타임 plumbing 하위 경로 +- 벤더별 편의 헬퍼 +- 구현 세부 사항인 setup/onboarding 헬퍼 -일부 번들 plugin helper subpath는 호환성과 번들 plugin 유지보수를 위해 -생성된 SDK export 맵에 여전히 남아 있습니다. 현재 예시로는 -`plugin-sdk/feishu`, `plugin-sdk/feishu-setup`, `plugin-sdk/zalo`, -`plugin-sdk/zalo-setup`, 여러 `plugin-sdk/matrix*` seam이 있습니다. 이들은 -새로운 서드파티 plugin을 위한 권장 SDK 패턴이 아니라 -예약된 구현 세부 export로 취급하세요. +일부 번들 플러그인 헬퍼 하위 경로는 호환성과 번들 플러그인 유지보수를 위해 생성된 SDK export 맵에 여전히 남아 있습니다. 현재 예로는 `plugin-sdk/feishu`, `plugin-sdk/feishu-setup`, `plugin-sdk/zalo`, `plugin-sdk/zalo-setup`, 그리고 여러 `plugin-sdk/matrix*` seam이 있습니다. 이를 새 서드파티 플러그인을 위한 권장 SDK 패턴이 아니라, 예약된 구현 세부 export로 취급하세요. ## 로드 파이프라인 시작 시 OpenClaw는 대략 다음을 수행합니다. -1. 후보 plugin 루트를 발견 -2. 네이티브 또는 호환 번들 매니페스트와 패키지 메타데이터를 읽음 -3. 안전하지 않은 후보를 거부 -4. plugin 구성(`plugins.enabled`, `allow`, `deny`, `entries`, - `slots`, `load.paths`)을 정규화 -5. 각 후보의 활성화 여부를 결정 -6. 활성화된 네이티브 모듈을 jiti로 로드 -7. 네이티브 `register(api)`(또는 레거시 별칭 `activate(api)`) hook을 호출하고 등록을 plugin 레지스트리에 수집 -8. 레지스트리를 command/런타임 표면에 노출 +1. 후보 플러그인 루트를 디스커버리합니다. +2. 네이티브 또는 호환 번들 매니페스트와 패키지 메타데이터를 읽습니다. +3. 안전하지 않은 후보를 거부합니다. +4. 플러그인 config를 정규화합니다(`plugins.enabled`, `allow`, `deny`, `entries`, `slots`, `load.paths`). +5. 각 후보의 활성화 여부를 결정합니다. +6. 활성화된 네이티브 모듈을 jiti로 로드합니다. +7. 네이티브 `register(api)`(또는 레거시 별칭인 `activate(api)`) 훅을 호출하고 등록 내용을 플러그인 레지스트리에 수집합니다. +8. 레지스트리를 명령/런타임 표면에 노출합니다. -`activate`는 `register`의 레거시 별칭입니다 — 로더는 존재하는 쪽(`def.register ?? def.activate`)을 해석하고 같은 시점에 호출합니다. 모든 번들 plugin은 `register`를 사용합니다. 새 plugin에는 `register`를 우선하세요. +`activate`는 `register`의 레거시 별칭입니다. 로더는 존재하는 쪽(`def.register ?? def.activate`)을 해석하여 같은 시점에 호출합니다. 모든 번들 플러그인은 `register`를 사용합니다. 새 플러그인에는 `register`를 우선하세요. -안전 게이트는 런타임 실행 **이전**에 발생합니다. 엔트리가 plugin 루트 밖으로 벗어나거나, -경로가 world-writable이거나, 비번들 plugin에 대해 경로 소유권이 -의심스러워 보이면 후보는 차단됩니다. +안전 게이트는 런타임 실행 **이전**에 발생합니다. 엔트리가 플러그인 루트 밖으로 벗어나거나, 경로가 world-writable이거나, 번들되지 않은 플러그인에 대해 경로 소유권이 의심스러운 경우 후보는 차단됩니다. ### 매니페스트 우선 동작 -매니페스트는 컨트롤 플레인 소스 오브 트루스입니다. OpenClaw는 이를 사용해 다음을 수행합니다. +매니페스트는 제어 평면의 기준 source of truth입니다. OpenClaw는 이를 사용해 다음을 수행합니다. -- plugin 식별 -- 선언된 채널/Skills/config 스키마 또는 번들 capability 발견 -- `plugins.entries..config` 검증 -- Control UI 라벨/placeholder 보강 -- 설치/카탈로그 메타데이터 표시 +- 플러그인을 식별합니다. +- 선언된 채널/Skills/config 스키마 또는 번들 capability를 디스커버리합니다. +- `plugins.entries..config`를 검증합니다. +- Control UI 레이블/placeholder를 보강합니다. +- 설치/카탈로그 메타데이터를 표시합니다. -네이티브 plugin의 경우 런타임 모듈은 데이터 플레인 부분입니다. 이것이 -hook, tool, command, provider 흐름 같은 실제 동작을 등록합니다. +네이티브 플러그인의 경우 런타임 모듈은 데이터 평면 부분입니다. 여기서 훅, 도구, 명령, 또는 provider 흐름 같은 실제 동작을 등록합니다. ### 로더가 캐시하는 것 -OpenClaw는 짧은 수명의 프로세스 내 캐시를 유지합니다. +OpenClaw는 다음에 대해 짧은 프로세스 내 캐시를 유지합니다. -- 발견 결과 +- 디스커버리 결과 - 매니페스트 레지스트리 데이터 -- 로드된 plugin 레지스트리 +- 로드된 플러그인 레지스트리 -이 캐시는 시작 급증과 반복 command 오버헤드를 줄여 줍니다. 이것은 -영속성이 아니라 짧은 수명의 성능 캐시로 생각하면 안전합니다. +이 캐시들은 급격한 시작 부하와 반복 명령 오버헤드를 줄여 줍니다. 이를 지속성이 아니라 짧게 유지되는 성능 캐시로 생각하면 됩니다. -성능 참고: +성능 메모: -- 이 캐시를 비활성화하려면 `OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1` 또는 - `OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1`을 설정하세요. -- `OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS`와 - `OPENCLAW_PLUGIN_MANIFEST_CACHE_MS`로 캐시 시간 창을 조정하세요. +- 캐시를 비활성화하려면 `OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1` 또는 `OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1`을 설정하세요. +- 캐시 기간은 `OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS`와 `OPENCLAW_PLUGIN_MANIFEST_CACHE_MS`로 조정합니다. ## 레지스트리 모델 -로드된 plugin은 임의의 core 전역 상태를 직접 변경하지 않습니다. 대신 -중앙 plugin 레지스트리에 등록합니다. +로드된 플러그인은 임의의 코어 전역 상태를 직접 변경하지 않습니다. 중앙 플러그인 레지스트리에 등록합니다. 레지스트리는 다음을 추적합니다. -- plugin 레코드(정체성, 소스, 출처, 상태, 진단) -- tools -- 레거시 hook과 정형 hook -- channels -- providers +- 플러그인 레코드(ID, 소스, origin, 상태, 진단) +- 도구 +- 레거시 훅과 typed 훅 +- 채널 +- 제공자 - gateway RPC 핸들러 -- HTTP routes -- CLI registrars -- 백그라운드 services -- plugin 소유 commands +- HTTP 라우트 +- CLI registrar +- 백그라운드 서비스 +- 플러그인 소유 명령 -그다음 core 기능은 plugin 모듈과 직접 대화하는 대신 그 레지스트리를 읽습니다. -이렇게 하면 로딩이 한 방향으로 유지됩니다. +그다음 코어 기능은 플러그인 모듈과 직접 대화하는 대신 이 레지스트리를 읽습니다. 이로써 로딩은 단방향으로 유지됩니다. -- plugin 모듈 -> 레지스트리 등록 -- core 런타임 -> 레지스트리 소비 +- 플러그인 모듈 -> 레지스트리 등록 +- 코어 런타임 -> 레지스트리 소비 -이 분리는 유지보수성에 중요합니다. 대부분의 core 표면이 -"모든 plugin 모듈을 특별 취급"이 아니라 "레지스트리를 읽기"라는 -하나의 통합 지점만 필요하게 됩니다. +이 분리는 유지보수성에 중요합니다. 대부분의 코어 표면은 "모든 플러그인 모듈을 특수 처리"하는 대신 "레지스트리를 읽기"라는 하나의 통합 지점만 가지면 되기 때문입니다. ## 대화 바인딩 콜백 -대화를 바인딩하는 plugin은 승인이 해결되었을 때 반응할 수 있습니다. +대화를 바인딩하는 플러그인은 승인이 해결될 때 반응할 수 있습니다. -바인드 요청이 승인되거나 거부된 후 콜백을 받으려면 -`api.onConversationBindingResolved(...)`를 사용하세요. +바인드 요청이 승인되거나 거부된 후 콜백을 받으려면 `api.onConversationBindingResolved(...)`를 사용하세요. ```ts export default { @@ -572,38 +463,34 @@ export default { register(api) { api.onConversationBindingResolved(async (event) => { if (event.status === "approved") { - // 이제 이 plugin + 대화에 대한 바인딩이 존재합니다. + // A binding now exists for this plugin + conversation. console.log(event.binding?.conversationId); return; } - // 요청이 거부되었습니다. 로컬 pending 상태를 정리합니다. + // The request was denied; clear any local pending state. console.log(event.request.conversation.conversationId); }); }, }; ``` -콜백 페이로드 필드: +콜백 payload 필드: - `status`: `"approved"` 또는 `"denied"` - `decision`: `"allow-once"`, `"allow-always"`, 또는 `"deny"` -- `binding`: 승인된 요청에 대한 해석된 바인딩 -- `request`: 원래 요청 요약, detach 힌트, sender id, 대화 메타데이터 +- `binding`: 승인된 요청에 대한 해결된 바인딩 +- `request`: 원래 요청 요약, detach 힌트, 발신자 ID, 대화 메타데이터 -이 콜백은 알림 전용입니다. 누가 대화를 바인딩할 수 있는지를 바꾸지 않으며, -core 승인 처리가 끝난 뒤 실행됩니다. +이 콜백은 알림 전용입니다. 누가 대화를 바인딩할 수 있는지는 변경하지 않으며, 코어 승인 처리가 끝난 뒤 실행됩니다. -## Provider 런타임 hook +## 제공자 런타임 훅 -Provider plugin은 이제 두 계층을 가집니다. +이제 제공자 플러그인에는 두 계층이 있습니다. -- 매니페스트 메타데이터: 런타임 로드 전 저비용 provider env-auth 조회용 `providerAuthEnvVars`, - 런타임 로드 전 저비용 채널 env/setup 조회용 `channelEnvVars`, - 런타임 로드 전 저비용 온보딩/auth-choice - 라벨과 CLI 플래그 메타데이터용 `providerAuthChoices` -- 구성 시점 hook: `catalog` / 레거시 `discovery` 와 `applyConfigDefaults` -- 런타임 hook: `normalizeModelId`, `normalizeTransport`, +- 매니페스트 메타데이터: 런타임 로드 전 저비용 provider env-auth 조회를 위한 `providerAuthEnvVars`, 인증을 공유하는 provider variant를 위한 `providerAuthAliases`, 런타임 로드 전 저비용 채널 env/setup 조회를 위한 `channelEnvVars`, 그리고 런타임 로드 전 저비용 onboarding/auth-choice 레이블 및 CLI 플래그 메타데이터를 위한 `providerAuthChoices` +- config 시점 훅: `catalog` / 레거시 `discovery`, 그리고 `applyConfigDefaults` +- 런타임 훅: `normalizeModelId`, `normalizeTransport`, `normalizeConfig`, `applyNativeStreamingUsageCompat`, `resolveConfigApiKey`, `resolveSyntheticAuth`, `resolveExternalAuthProfiles`, @@ -623,88 +510,70 @@ Provider plugin은 이제 두 계층을 가집니다. `buildReplayPolicy`, `sanitizeReplayHistory`, `validateReplayTurns`, `onModelSelected` -OpenClaw는 여전히 일반 agent 루프, failover, transcript 처리, tool 정책을 -소유합니다. 이러한 hook은 -전체 커스텀 추론 transport 없이 provider별 동작을 확장하기 위한 표면입니다. +OpenClaw는 여전히 일반적인 에이전트 루프, failover, transcript 처리, 도구 정책을 소유합니다. 이 훅들은 전체 custom 추론 transport 없이도 제공자별 동작을 확장할 수 있는 표면입니다. -provider가 env 기반 자격 증명을 가지고 있어 일반 auth/status/model-picker 경로가 -plugin 런타임 로드 없이도 이를 볼 수 있어야 한다면 매니페스트 `providerAuthEnvVars`를 사용하세요. -온보딩/auth-choice CLI 표면이 provider의 choice id, -그룹 라벨, 단순한 단일 플래그 인증 배선을 런타임 로드 없이 알아야 한다면 -매니페스트 `providerAuthChoices`를 사용하세요. 온보딩 라벨 또는 OAuth -client-id/client-secret 설정 변수 같은 운영자 대상 힌트에는 provider 런타임 -`envVars`를 유지하세요. +제공자에 env 기반 자격 증명이 있어 일반 auth/status/model-picker 경로가 플러그인 런타임을 로드하지 않고도 이를 알아야 한다면 매니페스트 `providerAuthEnvVars`를 사용하세요. 하나의 provider ID가 다른 provider ID의 env vars, auth profiles, config 기반 auth, API-key onboarding 선택지를 재사용해야 한다면 매니페스트 `providerAuthAliases`를 사용하세요. onboarding/auth-choice CLI 표면이 플러그인 런타임을 로드하지 않고도 provider의 choice ID, 그룹 레이블, 단일 플래그 인증 연결을 알아야 한다면 매니페스트 `providerAuthChoices`를 사용하세요. 제공자 런타임 `envVars`는 operator-facing 힌트(예: onboarding 레이블 또는 OAuth client-id/client-secret 설정 변수)용으로 유지하세요. -채널에 env 기반 인증 또는 설정이 있어 일반 shell-env fallback, -config/status 검사, 설정 프롬프트가 채널 런타임 로드 없이도 이를 볼 수 있어야 한다면 -매니페스트 `channelEnvVars`를 사용하세요. +채널에 env 기반 auth 또는 setup이 있어 일반 shell-env fallback, config/status 검사, setup 프롬프트가 채널 런타임을 로드하지 않고도 이를 알아야 한다면 매니페스트 `channelEnvVars`를 사용하세요. -### Hook 순서와 사용법 +### 훅 순서와 사용법 -모델/provider plugin의 경우 OpenClaw는 대략 다음 순서로 hook을 호출합니다. -"언제 사용해야 하는가" 열은 빠른 결정 가이드입니다. +모델/제공자 플러그인의 경우 OpenClaw는 대략 다음 순서로 훅을 호출합니다. +"사용 시점" 열은 빠른 판단 가이드입니다. -| # | Hook | 수행 작업 | 사용 시점 | -| --- | --------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `catalog` | `models.json` 생성 중 provider 구성을 `models.providers`에 게시 | provider가 카탈로그 또는 base URL 기본값을 소유할 때 | -| 2 | `applyConfigDefaults` | 구성 구체화 중 provider 소유 전역 기본값 적용 | 기본값이 인증 모드, env 또는 provider 모델 계열 의미론에 따라 달라질 때 | -| -- | _(내장 모델 조회)_ | OpenClaw가 먼저 일반 레지스트리/카탈로그 경로를 시도 | _(plugin hook 아님)_ | -| 3 | `normalizeModelId` | 조회 전 레거시 또는 preview 모델-id 별칭 정규화 | provider가 정식 모델 해석 전 별칭 정리를 소유할 때 | -| 4 | `normalizeTransport` | 일반 모델 조립 전 provider 계열 `api` / `baseUrl` 정규화 | provider가 같은 transport 계열의 custom provider id에 대한 transport 정리를 소유할 때 | -| 5 | `normalizeConfig` | 런타임/provider 해석 전 `models.providers.` 정규화 | provider에 속해야 하는 config 정리가 필요할 때; 번들 Google 계열 helper도 지원되는 Google config 항목을 백스톱으로 정리함 | -| 6 | `applyNativeStreamingUsageCompat` | config provider에 네이티브 streaming-usage compat 재작성 적용 | provider가 엔드포인트 기반 네이티브 streaming usage 메타데이터 수정이 필요할 때 | -| 7 | `resolveConfigApiKey` | 런타임 auth 로딩 전 config provider의 env-marker auth 해석 | provider가 provider 소유 env-marker API-key 해석을 가질 때; `amazon-bedrock`도 여기에 내장 AWS env-marker 해석기를 가짐 | -| 8 | `resolveSyntheticAuth` | 평문 저장 없이 local/self-hosted 또는 config 기반 auth를 표면화 | provider가 synthetic/local 자격 증명 마커로 동작할 수 있을 때 | -| 9 | `resolveExternalAuthProfiles` | provider 소유 외부 auth profile을 오버레이; 기본 `persistence`는 CLI/앱 소유 자격 증명에 대해 `runtime-only` | provider가 복사된 refresh token을 저장하지 않고 외부 auth 자격 증명을 재사용할 때 | -| 10 | `shouldDeferSyntheticProfileAuth` | 저장된 synthetic profile placeholder의 우선순위를 env/config 기반 auth보다 낮춤 | provider가 synthetic placeholder profile을 저장하며 이것이 우선 순위를 가져서는 안 될 때 | -| 11 | `resolveDynamicModel` | 아직 로컬 레지스트리에 없는 provider 소유 모델 id에 대한 동기 fallback | provider가 임의 업스트림 모델 id를 허용할 때 | -| 12 | `prepareDynamicModel` | 비동기 워밍업 후 `resolveDynamicModel`을 다시 실행 | provider가 알 수 없는 id를 해석하기 전에 네트워크 메타데이터가 필요할 때 | -| 13 | `normalizeResolvedModel` | 내장 러너가 해석된 모델을 사용하기 전 최종 재작성 | provider가 transport를 재작성해야 하지만 여전히 core transport를 사용할 때 | -| 14 | `contributeResolvedModelCompat` | 다른 호환 transport 뒤의 벤더 모델에 compat 플래그 기여 | provider가 provider를 인수하지 않고 프록시 transport에서 자신의 모델을 인식할 때 | -| 15 | `capabilities` | 공유 core 로직에서 사용하는 provider 소유 transcript/tooling 메타데이터 | provider가 transcript/provider-family 특이사항이 필요할 때 | -| 16 | `normalizeToolSchemas` | 내장 러너가 보기 전에 tool schema 정규화 | provider가 transport 계열 schema 정리가 필요할 때 | -| 17 | `inspectToolSchemas` | 정규화 후 provider 소유 schema 진단 노출 | provider가 core에 provider별 규칙을 가르치지 않고 키워드 경고를 원할 때 | -| 18 | `resolveReasoningOutputMode` | 네이티브 대 태그 기반 reasoning-output 계약 선택 | provider가 네이티브 필드 대신 태그 기반 reasoning/final output이 필요할 때 | -| 19 | `prepareExtraParams` | 일반 stream 옵션 래퍼 전에 요청 파라미터 정규화 | provider가 기본 요청 파라미터 또는 provider별 파라미터 정리가 필요할 때 | -| 20 | `createStreamFn` | 일반 stream 경로를 완전히 custom transport로 대체 | provider가 래퍼만이 아니라 custom wire protocol이 필요할 때 | -| 21 | `wrapStreamFn` | 일반 래퍼 적용 후 stream 래퍼 | provider가 custom transport 없이 요청 헤더/본문/모델 compat 래퍼가 필요할 때 | -| 22 | `resolveTransportTurnState` | 네이티브 턴별 transport 헤더 또는 메타데이터 첨부 | provider가 일반 transport가 provider 네이티브 turn identity를 보내길 원할 때 | -| 23 | `resolveWebSocketSessionPolicy` | 네이티브 WebSocket 헤더 또는 세션 쿨다운 정책 첨부 | provider가 일반 WS transport의 세션 헤더 또는 fallback 정책을 조정하길 원할 때 | -| 24 | `formatApiKey` | auth-profile formatter: 저장된 profile이 런타임 `apiKey` 문자열이 됨 | provider가 추가 auth 메타데이터를 저장하고 custom 런타임 토큰 형태가 필요할 때 | -| 25 | `refreshOAuth` | custom refresh 엔드포인트 또는 refresh 실패 정책을 위한 OAuth refresh override | provider가 공유 `pi-ai` refresher에 맞지 않을 때 | -| 26 | `buildAuthDoctorHint` | OAuth refresh 실패 시 추가되는 복구 힌트 | provider가 refresh 실패 후 provider 소유 auth 복구 안내가 필요할 때 | -| 27 | `matchesContextOverflowError` | provider 소유 context-window overflow 매처 | provider에 일반 휴리스틱이 놓치는 raw overflow 오류가 있을 때 | -| 28 | `classifyFailoverReason` | provider 소유 failover 이유 분류 | provider가 raw API/transport 오류를 rate-limit/overload 등으로 매핑할 수 있을 때 | -| 29 | `isCacheTtlEligible` | 프록시/백홀 provider용 prompt-cache 정책 | provider에 프록시별 cache TTL 게이팅이 필요할 때 | -| 30 | `buildMissingAuthMessage` | 일반 missing-auth 복구 메시지 대체 | provider가 provider별 missing-auth 복구 힌트가 필요할 때 | -| 31 | `suppressBuiltInModel` | 오래된 업스트림 모델 숨김과 선택적 사용자 대상 오류 힌트 | provider가 오래된 업스트림 행을 숨기거나 벤더 힌트로 대체해야 할 때 | -| 32 | `augmentModelCatalog` | 발견 후 synthetic/final 카탈로그 행 추가 | provider가 `models list`와 picker에 synthetic 전방 호환 행이 필요할 때 | -| 33 | `isBinaryThinking` | 이진 thinking provider용 on/off reasoning 토글 | provider가 이진 thinking on/off만 노출할 때 | -| 34 | `supportsXHighThinking` | 선택된 모델에 대한 `xhigh` reasoning 지원 | provider가 일부 모델에만 `xhigh`를 원할 때 | -| 35 | `resolveDefaultThinkingLevel` | 특정 모델 계열에 대한 기본 `/think` 수준 | provider가 모델 계열의 기본 `/think` 정책을 소유할 때 | -| 36 | `isModernModelRef` | live profile 필터와 smoke 선택을 위한 최신 모델 매처 | provider가 live/smoke 선호 모델 매칭을 소유할 때 | -| 37 | `prepareRuntimeAuth` | 추론 직전 구성된 자격 증명을 실제 런타임 토큰/키로 교환 | provider가 토큰 교환 또는 짧은 수명의 요청 자격 증명이 필요할 때 | -| 38 | `resolveUsageAuth` | `/usage` 및 관련 상태 표면을 위한 사용량/청구 자격 증명 해석 | provider에 custom usage/quota 토큰 파싱 또는 다른 usage 자격 증명이 필요할 때 | -| 39 | `fetchUsageSnapshot` | auth 해석 후 provider별 사용량/할당량 snapshot을 가져오고 정규화 | provider에 provider별 사용량 엔드포인트 또는 페이로드 파서가 필요할 때 | -| 40 | `createEmbeddingProvider` | memory/search용 provider 소유 임베딩 adapter 빌드 | 메모리 임베딩 동작이 provider plugin에 속해야 할 때 | -| 41 | `buildReplayPolicy` | provider의 transcript 처리 제어 replay 정책 반환 | provider가 custom transcript 정책(예: thinking-block 제거)이 필요할 때 | -| 42 | `sanitizeReplayHistory` | 일반 transcript 정리 후 replay history 재작성 | provider에 공유 compaction helper를 넘어서는 provider별 replay 재작성이 필요할 때 | -| 43 | `validateReplayTurns` | 내장 러너 전 최종 replay-turn 검증 또는 재구성 | provider transport에 일반 정리 후 더 엄격한 turn 검증이 필요할 때 | -| 44 | `onModelSelected` | provider 소유 선택 후 부작용 실행 | provider가 모델 활성화 시 텔레메트리 또는 provider 소유 상태가 필요할 때 | +| # | Hook | 역할 | 사용 시점 | +| --- | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | `catalog` | `models.json` 생성 중 provider 구성을 `models.providers`에 게시 | 제공자가 카탈로그 또는 base URL 기본값을 소유할 때 | +| 2 | `applyConfigDefaults` | config materialization 중 provider 소유 전역 config 기본값을 적용 | 기본값이 auth 모드, env, 또는 provider 모델 패밀리 의미론에 따라 달라질 때 | +| -- | _(내장 모델 조회)_ | OpenClaw가 먼저 일반 레지스트리/카탈로그 경로를 시도 | _(플러그인 훅 아님)_ | +| 3 | `normalizeModelId` | 조회 전에 레거시 또는 preview model-id 별칭을 정규화 | 제공자가 정식 모델 해석 전에 별칭 정리를 소유할 때 | +| 4 | `normalizeTransport` | 일반 모델 조립 전에 provider 패밀리의 `api` / `baseUrl`을 정규화 | 제공자가 같은 transport 패밀리 내 custom provider ID의 transport 정리를 소유할 때 | +| 5 | `normalizeConfig` | 런타임/provider 해석 전에 `models.providers.`를 정규화 | 플러그인에 속해야 하는 config 정리가 필요할 때; 번들 Google 계열 헬퍼도 지원되는 Google config 엔트리를 보완함 | +| 6 | `applyNativeStreamingUsageCompat` | config providers에 native streaming-usage 호환 재작성 적용 | 제공자가 엔드포인트 기반 native streaming usage 메타데이터 수정을 필요로 할 때 | +| 7 | `resolveConfigApiKey` | 런타임 auth 로드 전에 config providers의 env-marker auth를 해석 | 제공자가 자체 env-marker API-key 해석을 소유할 때; `amazon-bedrock`에는 내장 AWS env-marker resolver도 여기 포함됨 | +| 8 | `resolveSyntheticAuth` | 평문을 저장하지 않고 로컬/self-hosted 또는 config 기반 auth를 표면화 | 제공자가 synthetic/local 자격 증명 marker로 동작할 수 있을 때 | +| 9 | `resolveExternalAuthProfiles` | 제공자 소유 외부 auth profile을 overlay; 기본 `persistence`는 CLI/앱 소유 자격 증명에 대해 `runtime-only` | 제공자가 copied refresh token을 저장하지 않고 외부 auth 자격 증명을 재사용할 때 | +| 10 | `shouldDeferSyntheticProfileAuth` | 저장된 synthetic profile placeholder를 env/config 기반 auth 뒤로 낮춤 | 제공자가 우선 순위를 가져서는 안 되는 synthetic placeholder profile을 저장할 때 | +| 11 | `resolveDynamicModel` | 아직 로컬 레지스트리에 없는 provider 소유 model ID에 대한 동기 fallback | 제공자가 임의의 업스트림 model ID를 허용할 때 | +| 12 | `prepareDynamicModel` | 비동기 워밍업 후 `resolveDynamicModel`를 다시 실행 | 제공자가 알 수 없는 ID를 해석하기 전에 네트워크 메타데이터를 필요로 할 때 | +| 13 | `normalizeResolvedModel` | embedded runner가 해석된 모델을 사용하기 전 최종 재작성 | 제공자가 transport 재작성이 필요하지만 여전히 코어 transport를 사용할 때 | +| 14 | `contributeResolvedModelCompat` | 다른 호환 transport 뒤에 있는 벤더 모델에 대한 compat 플래그 기여 | 제공자가 provider를 직접 가져가지 않고도 proxy transport에서 자기 모델을 인식할 때 | +| 15 | `capabilities` | 공유 코어 로직이 사용하는 제공자 소유 transcript/tooling 메타데이터 | 제공자가 transcript/provider-family 특이사항을 필요로 할 때 | +| 16 | `normalizeToolSchemas` | embedded runner가 보기 전에 도구 스키마를 정규화 | 제공자가 transport-family 스키마 정리를 필요로 할 때 | +| 17 | `inspectToolSchemas` | 정규화 후 제공자 소유 스키마 진단 노출 | 제공자가 코어에 provider별 규칙을 가르치지 않고 키워드 경고를 표시하고 싶을 때 | +| 18 | `resolveReasoningOutputMode` | native vs tagged reasoning-output 계약 선택 | 제공자가 native 필드 대신 tagged reasoning/final output을 필요로 할 때 | +| 19 | `prepareExtraParams` | 일반 스트림 옵션 wrapper 전에 요청 파라미터 정규화 | 제공자가 기본 요청 파라미터 또는 provider별 파라미터 정리를 필요로 할 때 | +| 20 | `createStreamFn` | 일반 스트림 경로를 완전히 교체하여 custom transport 사용 | 제공자가 wrapper만이 아니라 custom wire protocol을 필요로 할 때 | +| 21 | `wrapStreamFn` | 일반 wrapper 적용 후 스트림 wrapper | custom transport 없이 요청 header/body/model compat wrapper가 필요할 때 | +| 22 | `resolveTransportTurnState` | native 턴별 transport header 또는 메타데이터 연결 | 제공자가 일반 transport가 provider-native 턴 ID를 전송하길 원할 때 | +| 23 | `resolveWebSocketSessionPolicy` | native WebSocket header 또는 세션 cool-down 정책 연결 | 제공자가 일반 WS transport에서 세션 header 또는 fallback 정책 조정을 원할 때 | +| 24 | `formatApiKey` | auth-profile formatter: 저장된 profile을 런타임 `apiKey` 문자열로 변환 | 제공자가 추가 auth 메타데이터를 저장하고 custom 런타임 토큰 형식이 필요할 때 | +| 25 | `refreshOAuth` | custom refresh 엔드포인트 또는 refresh 실패 정책을 위한 OAuth refresh override | 제공자가 공유 `pi-ai` refresher에 맞지 않을 때 | +| 26 | `buildAuthDoctorHint` | OAuth refresh 실패 시 추가되는 복구 힌트 | 제공자가 refresh 실패 후 제공자 소유 auth 복구 가이드를 필요로 할 때 | +| 27 | `matchesContextOverflowError` | 제공자 소유 컨텍스트 윈도 overflow matcher | 제공자에 일반 heuristic이 놓치는 raw overflow 오류가 있을 때 | +| 28 | `classifyFailoverReason` | 제공자 소유 failover 이유 분류 | 제공자가 raw API/transport 오류를 rate-limit/overload 등으로 매핑할 수 있을 때 | +| 29 | `isCacheTtlEligible` | proxy/backhaul provider를 위한 프롬프트 캐시 정책 | 제공자가 proxy별 캐시 TTL 게이팅을 필요로 할 때 | +| 30 | `buildMissingAuthMessage` | 일반 missing-auth 복구 메시지를 대체 | 제공자가 제공자별 missing-auth 복구 힌트를 필요로 할 때 | +| 31 | `suppressBuiltInModel` | 오래된 업스트림 모델 숨김과 선택적 사용자 대상 오류 힌트 | 제공자가 오래된 업스트림 행을 숨기거나 벤더 힌트로 대체해야 할 때 | +| 32 | `augmentModelCatalog` | 디스커버리 후 synthetic/final 카탈로그 행 추가 | 제공자가 `models list`와 picker에 synthetic forward-compat 행을 필요로 할 때 | +| 33 | `isBinaryThinking` | binary-thinking provider를 위한 on/off reasoning 토글 | 제공자가 binary thinking on/off만 노출할 때 | +| 34 | `supportsXHighThinking` | 선택된 모델에 대한 `xhigh` reasoning 지원 | 제공자가 일부 모델에만 `xhigh`를 원할 때 | +| 35 | `resolveDefaultThinkingLevel` | 특정 모델 패밀리의 기본 `/think` 레벨 해석 | 제공자가 모델 패밀리의 기본 `/think` 정책을 소유할 때 | +| 36 | `isModernModelRef` | 라이브 profile 필터 및 smoke 선택을 위한 modern-model matcher | 제공자가 live/smoke 선호 모델 매칭을 소유할 때 | +| 37 | `prepareRuntimeAuth` | 추론 직전 구성된 자격 증명을 실제 런타임 토큰/키로 교환 | 제공자가 토큰 교환 또는 짧은 수명의 요청 자격 증명을 필요로 할 때 | +| 38 | `resolveUsageAuth` | `/usage` 및 관련 상태 표면을 위한 사용량/과금 자격 증명 해석 | 제공자가 custom usage/quota 토큰 파싱 또는 다른 usage 자격 증명을 필요로 할 때 | +| 39 | `fetchUsageSnapshot` | auth 해석 후 제공자별 사용량/quota 스냅샷 조회 및 정규화 | 제공자가 제공자별 usage 엔드포인트 또는 payload parser를 필요로 할 때 | +| 40 | `createEmbeddingProvider` | 메모리/검색용 제공자 소유 임베딩 어댑터 생성 | 메모리 임베딩 동작이 제공자 플러그인과 함께 있어야 할 때 | +| 41 | `buildReplayPolicy` | 제공자의 transcript 처리 방식을 제어하는 replay 정책 반환 | 제공자가 custom transcript 정책(예: thinking 블록 제거)을 필요로 할 때 | +| 42 | `sanitizeReplayHistory` | 일반 transcript 정리 후 replay 기록 재작성 | 제공자가 공유 compaction 헬퍼를 넘어서는 replay 재작성을 필요로 할 때 | +| 43 | `validateReplayTurns` | embedded runner 직전 최종 replay 턴 검증 또는 형태 조정 | 제공자 transport가 일반 정리 이후 더 엄격한 턴 검증을 필요로 할 때 | +| 44 | `onModelSelected` | 모델이 활성화될 때 제공자 소유 후속 효과 실행 | 제공자가 telemetry 또는 제공자 소유 상태 처리를 필요로 할 때 | -`normalizeModelId`, `normalizeTransport`, `normalizeConfig`는 먼저 일치한 -provider plugin을 확인한 뒤, 모델 id 또는 transport/config를 실제로 -변경하는 hook 가능 provider plugin이 나올 때까지 다른 plugin으로 넘어갑니다. 이는 -호출자가 어떤 번들 plugin이 재작성을 소유하는지 알 필요 없이 -별칭/compat provider shim이 계속 동작하도록 합니다. 어떤 provider hook도 -지원되는 Google 계열 config 항목을 재작성하지 않으면 번들 Google config -normalizer가 계속 그 호환성 정리를 적용합니다. +`normalizeModelId`, `normalizeTransport`, `normalizeConfig`는 먼저 일치하는 provider 플러그인을 확인한 다음, 실제로 model ID나 transport/config를 변경하는 플러그인이 나올 때까지 다른 hook-capable provider 플러그인으로 넘깁니다. 이렇게 하면 호출자가 어느 번들 플러그인이 재작성을 소유하는지 몰라도 alias/compat provider shim이 동작합니다. 어떤 provider 훅도 지원되는 Google 계열 config 엔트리를 재작성하지 않으면, 번들 Google config normalizer가 여전히 그 호환성 정리를 적용합니다. -provider에 완전히 custom wire protocol 또는 custom 요청 실행기가 필요하다면, -그것은 다른 종류의 확장입니다. 이 hook은 여전히 -OpenClaw의 일반 추론 루프에서 실행되는 provider 동작을 위한 것입니다. +제공자에 완전히 custom wire protocol 또는 custom 요청 실행기가 필요하다면, 이는 다른 종류의 확장입니다. 이 훅들은 OpenClaw의 일반 추론 루프에서 여전히 실행되는 provider 동작을 위한 것입니다. -### Provider 예시 +### 제공자 예시 ```ts api.registerProvider({ @@ -763,121 +632,39 @@ api.registerProvider({ - Anthropic은 `resolveDynamicModel`, `capabilities`, `buildAuthDoctorHint`, `resolveUsageAuth`, `fetchUsageSnapshot`, `isCacheTtlEligible`, `resolveDefaultThinkingLevel`, `applyConfigDefaults`, `isModernModelRef`, - `wrapStreamFn`을 사용합니다. 이는 Claude 4.6 전방 호환, - provider-family 힌트, auth 복구 안내, 사용량 엔드포인트 통합, - prompt-cache 적격성, auth 인식 config 기본값, Claude - 기본/적응형 thinking 정책, beta 헤더, `/fast` / `serviceTier`, - `context1m`에 대한 Anthropic별 stream shaping을 소유하기 때문입니다. -- Anthropic의 Claude 전용 stream helper는 지금은 번들 plugin 자체의 - 공개 `api.ts` / `contract-api.ts` seam에 남아 있습니다. 이 패키지 표면은 - 한 provider의 beta-header 규칙 때문에 일반 SDK를 넓히는 대신 - `wrapAnthropicProviderStream`, `resolveAnthropicBetas`, - `resolveAnthropicFastMode`, `resolveAnthropicServiceTier`, 더 낮은 수준의 - Anthropic wrapper builder를 export합니다. -- OpenAI는 `resolveDynamicModel`, `normalizeResolvedModel`, - `capabilities`와 함께 `buildMissingAuthMessage`, `suppressBuiltInModel`, - `augmentModelCatalog`, `supportsXHighThinking`, `isModernModelRef`를 사용합니다. - 이는 GPT-5.4 전방 호환, 직접 OpenAI - `openai-completions` -> `openai-responses` 정규화, Codex 인식 auth - 힌트, Spark 숨김, synthetic OpenAI 목록 행, GPT-5 thinking / - live-model 정책을 소유하기 때문입니다. `openai-responses-defaults` stream 계열은 - attribution 헤더, `/fast`/`serviceTier`, 텍스트 장황도, 네이티브 Codex 웹 검색, - reasoning-compat 페이로드 shaping, - Responses 컨텍스트 관리를 위한 공유 네이티브 OpenAI Responses 래퍼를 소유합니다. -- OpenRouter는 provider가 패스스루이며 - OpenClaw의 정적 카탈로그가 갱신되기 전에 새 모델 id를 노출할 수 있으므로 - `catalog`와 `resolveDynamicModel`, - `prepareDynamicModel`을 사용합니다. 또한 provider별 요청 헤더, - 라우팅 메타데이터, reasoning 패치, prompt-cache 정책을 core 밖에 두기 위해 - `capabilities`, `wrapStreamFn`, `isCacheTtlEligible`를 사용합니다. - replay 정책은 `passthrough-gemini` 계열에서 오고, - `openrouter-thinking` stream 계열은 프록시 reasoning 주입과 - 미지원 모델 / `auto` 건너뛰기를 소유합니다. -- GitHub Copilot은 provider 소유 디바이스 로그인, 모델 fallback 동작, Claude transcript - 특이사항, GitHub token -> Copilot token 교환, provider 소유 사용량 엔드포인트가 필요하므로 - `catalog`, `auth`, `resolveDynamicModel`, - `capabilities`와 함께 `prepareRuntimeAuth`, `fetchUsageSnapshot`을 사용합니다. -- OpenAI Codex는 여전히 core OpenAI transport에서 실행되지만 transport/base URL - 정규화, OAuth refresh fallback 정책, 기본 transport 선택, - synthetic Codex 카탈로그 행, ChatGPT 사용량 엔드포인트 통합을 소유하므로 - `catalog`, `resolveDynamicModel`, + `wrapStreamFn`을 사용합니다. Claude 4.6 forward-compat, provider-family 힌트, auth 복구 가이드, usage 엔드포인트 통합, 프롬프트 캐시 적격성, auth 인지 config 기본값, Claude 기본/적응형 thinking 정책, beta headers, `/fast` / `serviceTier`, `context1m`을 위한 Anthropic별 스트림 shaping을 소유하기 때문입니다. +- Anthropic의 Claude 전용 스트림 헬퍼는 당분간 번들 플러그인 자체의 공개 `api.ts` / `contract-api.ts` seam에 유지됩니다. 이 패키지 표면은 한 provider의 beta-header 규칙을 위해 일반 SDK를 확장하지 않고, `wrapAnthropicProviderStream`, `resolveAnthropicBetas`, `resolveAnthropicFastMode`, `resolveAnthropicServiceTier`, 하위 수준 Anthropic wrapper builder를 export합니다. +- OpenAI는 `resolveDynamicModel`, `normalizeResolvedModel`, `capabilities`와 함께 `buildMissingAuthMessage`, `suppressBuiltInModel`, `augmentModelCatalog`, `supportsXHighThinking`, `isModernModelRef`를 사용합니다. GPT-5.4 forward-compat, 직접 OpenAI의 `openai-completions` -> `openai-responses` 정규화, Codex 인지 auth 힌트, Spark 숨김, synthetic OpenAI 목록 행, GPT-5 thinking / live-model 정책을 소유하기 때문입니다. `openai-responses-defaults` 스트림 패밀리는 attribution headers, `/fast`/`serviceTier`, 텍스트 verbosity, native Codex 웹 검색, reasoning-compat payload shaping, Responses context 관리를 위한 공유 native OpenAI Responses wrapper를 소유합니다. +- OpenRouter는 `catalog`와 함께 `resolveDynamicModel`, `prepareDynamicModel`을 사용합니다. 이 provider는 pass-through이어서 OpenClaw의 정적 카탈로그가 업데이트되기 전에 새로운 model ID를 노출할 수 있기 때문입니다. 또한 provider별 요청 headers, 라우팅 메타데이터, reasoning 패치, 프롬프트 캐시 정책을 코어 밖에 유지하기 위해 `capabilities`, `wrapStreamFn`, `isCacheTtlEligible`를 사용합니다. replay 정책은 `passthrough-gemini` 패밀리에서 오고, `openrouter-thinking` 스트림 패밀리는 proxy reasoning 주입과 미지원 모델 / `auto` 건너뛰기를 소유합니다. +- GitHub Copilot은 `catalog`, `auth`, `resolveDynamicModel`, `capabilities`와 함께 `prepareRuntimeAuth`, `fetchUsageSnapshot`을 사용합니다. provider 소유 device login, 모델 fallback 동작, Claude transcript 특이사항, GitHub token -> Copilot token 교환, provider 소유 usage 엔드포인트가 필요하기 때문입니다. +- OpenAI Codex는 `catalog`, `resolveDynamicModel`, `normalizeResolvedModel`, `refreshOAuth`, `augmentModelCatalog`와 함께 - `prepareExtraParams`, `resolveUsageAuth`, `fetchUsageSnapshot`을 사용합니다. - 직접 OpenAI와 동일한 `openai-responses-defaults` stream 계열을 공유합니다. -- Google AI Studio와 Gemini CLI OAuth는 - `google-gemini` replay 계열이 Gemini 3.1 전방 호환 fallback, - 네이티브 Gemini replay 검증, bootstrap replay 정리, - 태그 기반 reasoning-output 모드, 최신 모델 매칭을 소유하고, - `google-thinking` stream 계열이 Gemini thinking 페이로드 정규화를 소유하므로 - `resolveDynamicModel`, + `prepareExtraParams`, `resolveUsageAuth`, `fetchUsageSnapshot`을 사용합니다. 여전히 코어 OpenAI transport 위에서 실행되지만 transport/base URL 정규화, OAuth refresh fallback 정책, 기본 transport 선택, synthetic Codex 카탈로그 행, ChatGPT usage 엔드포인트 통합을 소유하기 때문입니다. direct OpenAI와 같은 `openai-responses-defaults` 스트림 패밀리를 공유합니다. +- Google AI Studio와 Gemini CLI OAuth는 `resolveDynamicModel`, `buildReplayPolicy`, `sanitizeReplayHistory`, - `resolveReasoningOutputMode`, `wrapStreamFn`, `isModernModelRef`를 사용합니다. - Gemini CLI OAuth는 또한 토큰 포맷, 토큰 파싱, quota 엔드포인트 - 연결을 위해 `formatApiKey`, `resolveUsageAuth`, - `fetchUsageSnapshot`을 사용합니다. -- Anthropic Vertex는 - `anthropic-by-model` replay 계열을 통해 `buildReplayPolicy`를 사용하므로, - Claude 전용 replay 정리가 모든 `anthropic-messages` transport가 아니라 - Claude id에만 적용됩니다. -- Amazon Bedrock은 Bedrock 전용 throttle/not-ready/context-overflow 오류 분류를 - Anthropic-on-Bedrock 트래픽에 대해 소유하므로 - `buildReplayPolicy`, `matchesContextOverflowError`, - `classifyFailoverReason`, `resolveDefaultThinkingLevel`을 사용합니다. - replay 정책은 여전히 동일한 Claude 전용 `anthropic-by-model` 가드를 공유합니다. -- OpenRouter, Kilocode, Opencode, Opencode Go는 Gemini - 모델을 OpenAI 호환 transport를 통해 프록시하며 - 네이티브 Gemini replay 검증이나 bootstrap 재작성 없이 - Gemini thought-signature 정리가 필요하므로 `passthrough-gemini` replay 계열을 통해 - `buildReplayPolicy`를 사용합니다. -- MiniMax는 한 provider가 Anthropic-message와 OpenAI 호환 의미론을 모두 소유하므로 - `hybrid-anthropic-openai` replay 계열을 통해 `buildReplayPolicy`를 사용합니다. - Anthropic 쪽에서는 Claude 전용 thinking-block 제거를 유지하면서 - reasoning output 모드를 다시 네이티브로 override하고, - `minimax-fast-mode` stream 계열은 공유 stream 경로에서 - fast-mode 모델 재작성을 소유합니다. -- Moonshot은 여전히 공유 - OpenAI transport를 사용하지만 provider 소유 thinking 페이로드 정규화가 필요하므로 - `catalog`와 `wrapStreamFn`을 사용합니다. - `moonshot-thinking` stream 계열은 config와 `/think` 상태를 - 네이티브 이진 thinking 페이로드에 매핑합니다. -- Kilocode는 provider 소유 요청 헤더, - reasoning 페이로드 정규화, Gemini transcript 힌트, Anthropic - cache-TTL 게이팅이 필요하므로 `catalog`, `capabilities`, `wrapStreamFn`, - `isCacheTtlEligible`를 사용합니다. `kilocode-thinking` stream 계열은 - 공유 프록시 stream 경로에서 Kilo thinking 주입을 유지하되, - 명시적 reasoning 페이로드를 지원하지 않는 `kilo/auto` 및 - 기타 프록시 모델 id는 건너뜁니다. -- Z.AI는 GLM-5 fallback, - `tool_stream` 기본값, 이진 thinking UX, 최신 모델 매칭, 사용량 auth + quota 가져오기를 모두 소유하므로 - `resolveDynamicModel`, `prepareExtraParams`, `wrapStreamFn`, + `resolveReasoningOutputMode`, `wrapStreamFn`, `isModernModelRef`를 사용합니다. `google-gemini` replay 패밀리가 Gemini 3.1 forward-compat fallback, native Gemini replay 검증, bootstrap replay sanitation, tagged reasoning-output 모드, modern-model 매칭을 소유하고, `google-thinking` 스트림 패밀리가 Gemini thinking payload 정규화를 소유하기 때문입니다. Gemini CLI OAuth는 token formatting, token parsing, quota 엔드포인트 연결을 위해 `formatApiKey`, `resolveUsageAuth`, `fetchUsageSnapshot`도 사용합니다. +- Anthropic Vertex는 `anthropic-by-model` replay 패밀리를 통해 `buildReplayPolicy`를 사용하므로, Claude별 replay 정리는 모든 `anthropic-messages` transport가 아니라 Claude ID에만 적용됩니다. +- Amazon Bedrock은 `buildReplayPolicy`, `matchesContextOverflowError`, + `classifyFailoverReason`, `resolveDefaultThinkingLevel`을 사용합니다. Anthropic-on-Bedrock 트래픽에 대한 Bedrock별 throttle/not-ready/context-overflow 오류 분류를 소유하기 때문입니다. replay 정책은 여전히 같은 Claude 전용 `anthropic-by-model` 가드를 공유합니다. +- OpenRouter, Kilocode, Opencode, Opencode Go는 `passthrough-gemini` replay 패밀리를 통해 `buildReplayPolicy`를 사용합니다. OpenAI 호환 transport를 통해 Gemini 모델을 프록시하고 native Gemini replay 검증이나 bootstrap 재작성 없이 Gemini thought-signature sanitation이 필요하기 때문입니다. +- MiniMax는 `hybrid-anthropic-openai` replay 패밀리를 통해 `buildReplayPolicy`를 사용합니다. 하나의 provider가 Anthropic-message와 OpenAI 호환 의미론을 모두 소유하기 때문입니다. Anthropic 쪽에서는 Claude 전용 thinking-block 제거를 유지하면서 reasoning output 모드를 다시 native로 override하고, `minimax-fast-mode` 스트림 패밀리는 공유 스트림 경로에서 fast-mode 모델 재작성을 소유합니다. +- Moonshot은 `catalog`와 `wrapStreamFn`을 사용합니다. 여전히 공유 OpenAI transport를 사용하지만 provider 소유 thinking payload 정규화가 필요하기 때문입니다. `moonshot-thinking` 스트림 패밀리는 config와 `/think` 상태를 native binary thinking payload에 매핑합니다. +- Kilocode는 `catalog`, `capabilities`, `wrapStreamFn`, + `isCacheTtlEligible`를 사용합니다. provider 소유 요청 headers, reasoning payload 정규화, Gemini transcript 힌트, Anthropic cache-TTL 게이팅이 필요하기 때문입니다. `kilocode-thinking` 스트림 패밀리는 공유 proxy 스트림 경로에서 Kilo thinking 주입을 유지하면서 명시적 reasoning payload를 지원하지 않는 `kilo/auto` 및 기타 proxy model ID를 건너뜁니다. +- Z.AI는 `resolveDynamicModel`, `prepareExtraParams`, `wrapStreamFn`, `isCacheTtlEligible`, `isBinaryThinking`, `isModernModelRef`, - `resolveUsageAuth`, `fetchUsageSnapshot`을 사용합니다. - `tool-stream-default-on` stream 계열은 기본 활성화 `tool_stream` 래퍼를 - provider별 수동 glue 밖에 둡니다. -- xAI는 네이티브 xAI Responses transport 정규화, Grok fast-mode - 별칭 재작성, 기본 `tool_stream`, 엄격한 tool / reasoning-payload - 정리, plugin 소유 tool용 fallback auth 재사용, 전방 호환 Grok - 모델 해석, xAI tool-schema - 프로필, 미지원 schema 키워드, 네이티브 `web_search`, HTML 엔티티 - tool-call 인자 디코딩 같은 provider 소유 compat 패치를 소유하므로 - `normalizeResolvedModel`, `normalizeTransport`, + `resolveUsageAuth`, `fetchUsageSnapshot`을 사용합니다. GLM-5 fallback, `tool_stream` 기본값, binary thinking UX, modern-model 매칭, usage auth + quota 조회를 모두 소유하기 때문입니다. `tool-stream-default-on` 스트림 패밀리는 기본 활성 `tool_stream` wrapper를 provider별 수기 연결 코드 밖에 유지합니다. +- xAI는 `normalizeResolvedModel`, `normalizeTransport`, `contributeResolvedModelCompat`, `prepareExtraParams`, `wrapStreamFn`, - `resolveSyntheticAuth`, `resolveDynamicModel`, `isModernModelRef` - 를 사용합니다. -- Mistral, OpenCode Zen, OpenCode Go는 - transcript/tooling 특이사항을 core 밖에 두기 위해 `capabilities`만 사용합니다. -- `byteplus`, `cloudflare-ai-gateway`, - `huggingface`, `kimi-coding`, `nvidia`, `qianfan`, - `synthetic`, `together`, `venice`, `vercel-ai-gateway`, `volcengine` 같은 - 카탈로그 전용 번들 provider는 `catalog`만 사용합니다. -- Qwen은 텍스트 provider용 `catalog`와 멀티모달 표면용 - 공유 media-understanding 및 비디오 생성 등록을 사용합니다. -- MiniMax와 Xiaomi는 추론은 여전히 공유 transport를 통해 실행되지만 - `/usage` 동작이 plugin 소유이므로 `catalog`와 사용량 hook을 함께 사용합니다. + `resolveSyntheticAuth`, `resolveDynamicModel`, `isModernModelRef`를 사용합니다. native xAI Responses transport 정규화, Grok fast-mode alias 재작성, 기본 `tool_stream`, strict-tool / reasoning-payload 정리, plugin 소유 도구를 위한 fallback auth 재사용, forward-compat Grok 모델 해석, xAI 도구 스키마 profile, 미지원 스키마 키워드, native `web_search`, HTML 엔터티 도구 호출 인자 디코딩 같은 provider 소유 compat 패치를 소유하기 때문입니다. +- Mistral, OpenCode Zen, OpenCode Go는 transcript/tooling 특이사항을 코어 밖에 유지하기 위해 `capabilities`만 사용합니다. +- `byteplus`, `cloudflare-ai-gateway`, `huggingface`, `kimi-coding`, `nvidia`, `qianfan`, `synthetic`, `together`, `venice`, `vercel-ai-gateway`, `volcengine` 같은 카탈로그 전용 번들 provider는 `catalog`만 사용합니다. +- Qwen은 텍스트 provider를 위해 `catalog`를 사용하고, 멀티모달 표면을 위해 공유 media-understanding 및 video-generation 등록도 수행합니다. +- MiniMax와 Xiaomi는 추론은 여전히 공유 transport를 통해 실행되더라도 `/usage` 동작이 플러그인 소유이므로 `catalog`와 usage 훅을 함께 사용합니다. -## 런타임 helper +## 런타임 헬퍼 -plugin은 `api.runtime`를 통해 선택된 core helper에 접근할 수 있습니다. TTS의 경우: +플러그인은 `api.runtime`를 통해 선택된 코어 헬퍼에 접근할 수 있습니다. TTS의 경우: ```ts const clip = await api.runtime.tts.textToSpeech({ @@ -898,15 +685,14 @@ const voices = await api.runtime.tts.listVoices({ 참고: -- `textToSpeech`는 파일/음성 노트 표면용 일반 core TTS 출력 페이로드를 반환합니다. -- core `messages.tts` 구성과 provider 선택을 사용합니다. -- PCM 오디오 버퍼 + 샘플 레이트를 반환합니다. plugin은 provider에 맞게 리샘플링/인코딩해야 합니다. -- `listVoices`는 provider별로 선택 사항입니다. 벤더 소유 voice picker 또는 설정 흐름에 사용하세요. -- 음성 목록에는 provider 인식 picker를 위한 locale, gender, personality 태그 같은 - 더 풍부한 메타데이터가 포함될 수 있습니다. -- 현재 telephony는 OpenAI와 ElevenLabs가 지원합니다. Microsoft는 지원하지 않습니다. +- `textToSpeech`는 파일/voice-note 표면을 위한 일반 코어 TTS 출력 payload를 반환합니다. +- 코어 `messages.tts` 구성과 provider 선택을 사용합니다. +- PCM 오디오 버퍼 + 샘플 레이트를 반환합니다. 플러그인은 provider에 맞게 resample/encode해야 합니다. +- `listVoices`는 provider별로 선택 사항입니다. 벤더 소유 voice picker 또는 setup 흐름에 사용하세요. +- 음성 목록에는 provider 인식 picker를 위한 locale, 성별, personality 태그 같은 더 풍부한 메타데이터가 포함될 수 있습니다. +- 현재 전화용 TTS는 OpenAI와 ElevenLabs를 지원합니다. Microsoft는 지원하지 않습니다. -plugin은 `api.registerSpeechProvider(...)`를 통해 speech provider를 등록할 수도 있습니다. +플러그인은 `api.registerSpeechProvider(...)`를 통해 음성 provider도 등록할 수 있습니다. ```ts api.registerSpeechProvider({ @@ -926,15 +712,12 @@ api.registerSpeechProvider({ 참고: -- TTS 정책, fallback, 응답 전달은 core에 유지하세요. -- 벤더 소유 합성 동작에는 speech provider를 사용하세요. -- 레거시 Microsoft `edge` 입력은 `microsoft` provider id로 정규화됩니다. -- 선호되는 소유권 모델은 회사 지향입니다. 하나의 벤더 plugin이 - OpenClaw가 capability 계약을 추가함에 따라 텍스트, 음성, 이미지, 향후 미디어 provider를 - 소유할 수 있습니다. +- TTS 정책, fallback, 응답 전달은 코어에 유지하세요. +- 벤더 소유 합성 동작에는 음성 provider를 사용하세요. +- 레거시 Microsoft `edge` 입력은 `microsoft` provider ID로 정규화됩니다. +- 선호되는 소유권 모델은 회사 중심입니다. OpenClaw가 capability 계약을 추가함에 따라 하나의 벤더 플러그인이 텍스트, 음성, 이미지, 미래의 미디어 provider를 모두 소유할 수 있습니다. -이미지/오디오/비디오 이해의 경우 plugin은 일반 key/value bag 대신 -하나의 정형 media-understanding provider를 등록합니다. +이미지/오디오/비디오 이해의 경우, 플러그인은 generic key/value bag 대신 하나의 typed media-understanding provider를 등록합니다. ```ts api.registerMediaUnderstandingProvider({ @@ -948,16 +731,15 @@ api.registerMediaUnderstandingProvider({ 참고: -- 오케스트레이션, fallback, config, 채널 연결은 core에 유지하세요. -- 벤더 동작은 provider plugin에 유지하세요. -- 추가 확장은 정형 상태를 유지해야 합니다. 즉, 새로운 선택적 메서드, - 새로운 선택적 결과 필드, 새로운 선택적 capability여야 합니다. -- 비디오 생성은 이미 같은 패턴을 따릅니다. - - core가 capability 계약과 런타임 helper를 소유 - - 벤더 plugin이 `api.registerVideoGenerationProvider(...)`를 등록 - - 기능/channel plugin이 `api.runtime.videoGeneration.*`를 소비 +- orchestration, fallback, config, 채널 연결은 코어에 유지하세요. +- 벤더 동작은 provider 플러그인에 유지하세요. +- 점진적 확장은 typed 상태를 유지해야 합니다. 새 optional 메서드, 새 optional 결과 필드, 새 optional capabilities처럼 확장하세요. +- 비디오 생성도 이미 같은 패턴을 따릅니다. + - 코어가 capability 계약과 런타임 헬퍼를 소유합니다. + - 벤더 플러그인이 `api.registerVideoGenerationProvider(...)`를 등록합니다. + - 기능/채널 플러그인이 `api.runtime.videoGeneration.*`를 소비합니다. -media-understanding 런타임 helper의 경우 plugin은 다음을 호출할 수 있습니다. +media-understanding 런타임 헬퍼의 경우, 플러그인은 다음을 호출할 수 있습니다. ```ts const image = await api.runtime.mediaUnderstanding.describeImageFile({ @@ -972,27 +754,25 @@ const video = await api.runtime.mediaUnderstanding.describeVideoFile({ }); ``` -오디오 전사의 경우 plugin은 media-understanding 런타임 또는 -이전 STT 별칭 중 하나를 사용할 수 있습니다. +오디오 전사의 경우, 플러그인은 media-understanding 런타임 또는 이전 STT 별칭을 사용할 수 있습니다. ```ts const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ filePath: "/tmp/inbound-audio.ogg", cfg: api.config, - // MIME을 신뢰성 있게 추론할 수 없을 때 선택 사항: + // Optional when MIME cannot be inferred reliably: mime: "audio/ogg", }); ``` 참고: -- `api.runtime.mediaUnderstanding.*`는 - 이미지/오디오/비디오 이해를 위한 선호 공유 표면입니다. -- core media-understanding 오디오 구성(`tools.media.audio`)과 provider fallback 순서를 사용합니다. -- 전사 출력이 생성되지 않을 때(예: 건너뜀/미지원 입력) `{ text: undefined }`를 반환합니다. +- `api.runtime.mediaUnderstanding.*`가 이미지/오디오/비디오 이해를 위한 선호 공유 표면입니다. +- 코어 media-understanding 오디오 구성(`tools.media.audio`)과 provider fallback 순서를 사용합니다. +- 전사 출력이 생성되지 않으면(예: 입력이 건너뛰어졌거나 지원되지 않음) `{ text: undefined }`를 반환합니다. - `api.runtime.stt.transcribeAudioFile(...)`는 호환성 별칭으로 남아 있습니다. -plugin은 `api.runtime.subagent`를 통해 백그라운드 subagent 실행을 시작할 수도 있습니다. +플러그인은 `api.runtime.subagent`를 통해 백그라운드 subagent 실행도 시작할 수 있습니다. ```ts const result = await api.runtime.subagent.run({ @@ -1006,16 +786,13 @@ const result = await api.runtime.subagent.run({ 참고: -- `provider`와 `model`은 지속적인 세션 변경이 아니라 실행별 override 선택 사항입니다. -- OpenClaw는 신뢰된 호출자에 대해서만 이러한 override 필드를 허용합니다. -- plugin 소유 fallback 실행의 경우 운영자는 `plugins.entries..subagent.allowModelOverride: true`로 opt-in해야 합니다. -- 신뢰된 plugin을 특정 정식 `provider/model` 대상으로 제한하려면 `plugins.entries..subagent.allowedModels`를 사용하거나, - 어떤 대상이든 명시적으로 허용하려면 `"*"`를 사용하세요. -- 신뢰되지 않은 plugin subagent 실행도 동작하지만, - override 요청은 조용히 fallback되지 않고 거부됩니다. +- `provider`와 `model`은 영구 세션 변경이 아니라 실행별 override입니다. +- OpenClaw는 신뢰된 호출자에 대해서만 이 override 필드를 허용합니다. +- 플러그인 소유 fallback 실행의 경우, operator는 `plugins.entries..subagent.allowModelOverride: true`로 명시적으로 opt-in해야 합니다. +- 신뢰된 플러그인을 특정 정식 `provider/model` 대상으로 제한하려면 `plugins.entries..subagent.allowedModels`를 사용하고, 모든 대상을 명시적으로 허용하려면 `"*"`를 사용하세요. +- 신뢰되지 않은 플러그인의 subagent 실행도 동작하지만, override 요청은 조용히 fallback되지 않고 거부됩니다. -웹 검색의 경우 plugin은 agent tool 배선에 직접 접근하는 대신 -공유 런타임 helper를 소비할 수 있습니다. +웹 검색의 경우, 플러그인은 에이전트 도구 연결에 직접 접근하는 대신 공유 런타임 헬퍼를 소비할 수 있습니다. ```ts const providers = api.runtime.webSearch.listProviders({ @@ -1031,15 +808,13 @@ const result = await api.runtime.webSearch.search({ }); ``` -plugin은 -`api.registerWebSearchProvider(...)`를 통해 web-search provider를 등록할 수도 있습니다. +플러그인은 `api.registerWebSearchProvider(...)`를 통해 웹 검색 provider를 등록할 수도 있습니다. 참고: -- provider 선택, 자격 증명 해석, 공유 요청 의미론은 core에 유지하세요. -- 벤더별 검색 transport에는 web-search provider를 사용하세요. -- `api.runtime.webSearch.*`는 agent tool 래퍼에 의존하지 않고 - 검색 동작이 필요한 기능/channel plugin을 위한 선호 공유 표면입니다. +- provider 선택, 자격 증명 해석, 공유 요청 의미론은 코어에 유지하세요. +- 벤더별 검색 transport에는 웹 검색 provider를 사용하세요. +- `api.runtime.webSearch.*`는 에이전트 도구 wrapper에 의존하지 않고 검색 동작이 필요한 기능/채널 플러그인을 위한 선호 공유 표면입니다. ### `api.runtime.imageGeneration` @@ -1055,11 +830,11 @@ const providers = api.runtime.imageGeneration.listProviders({ ``` - `generate(...)`: 구성된 이미지 생성 provider 체인을 사용해 이미지를 생성합니다. -- `listProviders(...)`: 사용 가능한 이미지 생성 provider와 capability를 나열합니다. +- `listProviders(...)`: 사용 가능한 이미지 생성 provider와 그 capabilities를 나열합니다. -## Gateway HTTP route +## Gateway HTTP 라우트 -plugin은 `api.registerHttpRoute(...)`로 HTTP 엔드포인트를 노출할 수 있습니다. +플러그인은 `api.registerHttpRoute(...)`로 HTTP 엔드포인트를 노출할 수 있습니다. ```ts api.registerHttpRoute({ @@ -1074,37 +849,35 @@ api.registerHttpRoute({ }); ``` -route 필드: +라우트 필드: -- `path`: gateway HTTP 서버 아래의 route 경로 -- `auth`: 필수. 일반 gateway auth를 요구하려면 `"gateway"`, plugin 관리 auth/webhook 검증에는 `"plugin"` 사용 -- `match`: 선택 사항. `"exact"`(기본값) 또는 `"prefix"` -- `replaceExisting`: 선택 사항. 같은 plugin이 자신의 기존 route 등록을 교체하도록 허용 -- `handler`: route가 요청을 처리했을 때 `true`를 반환 +- `path`: gateway HTTP 서버 아래의 라우트 경로 +- `auth`: 필수입니다. 일반 gateway auth가 필요하면 `"gateway"`를, 플러그인 관리 auth/webhook 검증이 필요하면 `"plugin"`을 사용하세요. +- `match`: 선택 사항입니다. `"exact"`(기본값) 또는 `"prefix"`. +- `replaceExisting`: 선택 사항입니다. 동일한 플러그인이 자신의 기존 라우트 등록을 대체할 수 있게 합니다. +- `handler`: 라우트가 요청을 처리했으면 `true`를 반환합니다. 참고: -- `api.registerHttpHandler(...)`는 제거되었으며 plugin 로드 오류를 발생시킵니다. 대신 `api.registerHttpRoute(...)`를 사용하세요. -- Plugin route는 `auth`를 명시적으로 선언해야 합니다. -- 정확한 `path + match` 충돌은 `replaceExisting: true`가 없는 한 거부되며, 한 plugin이 다른 plugin의 route를 교체할 수는 없습니다. -- `auth` 수준이 다른 중첩 route는 거부됩니다. `exact`/`prefix` fallthrough 체인은 같은 auth 수준에서만 유지하세요. -- `auth: "plugin"` route는 운영자 런타임 범위를 자동으로 받지 **않습니다**. 권한 있는 Gateway helper 호출이 아니라 plugin 관리 webhook/서명 검증용입니다. -- `auth: "gateway"` route는 Gateway 요청 런타임 범위 안에서 실행되지만, 그 범위는 의도적으로 보수적입니다. - - 공유 시크릿 bearer auth(`gateway.auth.mode = "token"` / `"password"`)는 호출자가 `x-openclaw-scopes`를 보내더라도 plugin-route 런타임 범위를 `operator.write`에 고정합니다 - - 신뢰된 ID 전달 HTTP 모드(예: `trusted-proxy` 또는 private ingress에서의 `gateway.auth.mode = "none"`)는 헤더가 명시적으로 있을 때만 `x-openclaw-scopes`를 존중합니다 - - 이러한 ID 전달 plugin-route 요청에서 `x-openclaw-scopes`가 없으면 런타임 범위는 `operator.write`로 fallback합니다 -- 실용적인 규칙: gateway-auth plugin route가 암묵적인 관리자 표면이라고 가정하지 마세요. route에 관리자 전용 동작이 필요하면 ID 전달 auth 모드를 요구하고 명시적 `x-openclaw-scopes` 헤더 계약을 문서화하세요. +- `api.registerHttpHandler(...)`는 제거되었으며 플러그인 로드 오류를 발생시킵니다. 대신 `api.registerHttpRoute(...)`를 사용하세요. +- 플러그인 라우트는 `auth`를 명시적으로 선언해야 합니다. +- 정확히 같은 `path + match` 충돌은 `replaceExisting: true`가 아닌 한 거부되며, 한 플러그인이 다른 플러그인의 라우트를 대체할 수는 없습니다. +- `auth` 수준이 다른 겹치는 라우트는 거부됩니다. `exact`/`prefix` fallthrough 체인은 같은 auth 수준에서만 유지하세요. +- `auth: "plugin"` 라우트는 operator 런타임 scope를 자동으로 받지 않습니다. 이는 권한 있는 Gateway 헬퍼 호출이 아니라, 플러그인 관리 webhook/서명 검증용입니다. +- `auth: "gateway"` 라우트는 Gateway 요청 런타임 scope 내부에서 실행되지만, 그 scope는 의도적으로 보수적입니다. + - 공유 시크릿 bearer auth(`gateway.auth.mode = "token"` / `"password"`)는 호출자가 `x-openclaw-scopes`를 보내더라도 plugin-route 런타임 scope를 `operator.write`에 고정합니다. + - 신뢰된 ID 포함 HTTP 모드(예: `trusted-proxy` 또는 private ingress의 `gateway.auth.mode = "none"`)는 헤더가 명시적으로 있을 때만 `x-openclaw-scopes`를 존중합니다. + - 그런 ID 포함 plugin-route 요청에 `x-openclaw-scopes`가 없으면 런타임 scope는 `operator.write`로 fallback됩니다. +- 실무 규칙: gateway-auth 플러그인 라우트를 암묵적 관리자 표면으로 가정하지 마세요. 라우트에 관리자 전용 동작이 필요하면, ID 포함 auth 모드를 요구하고 명시적인 `x-openclaw-scopes` 헤더 계약을 문서화하세요. ## Plugin SDK import 경로 -plugin 작성 시 모놀리식 `openclaw/plugin-sdk` import 대신 -SDK subpath를 사용하세요. +플러그인을 작성할 때는 단일 `openclaw/plugin-sdk` import 대신 SDK 하위 경로를 사용하세요. -- plugin 등록 기본 요소에는 `openclaw/plugin-sdk/plugin-entry` -- 일반 공유 plugin 표면 계약에는 `openclaw/plugin-sdk/core` +- 플러그인 등록 기본 요소에는 `openclaw/plugin-sdk/plugin-entry` +- 일반적인 공유 플러그인 대상 계약에는 `openclaw/plugin-sdk/core` - 루트 `openclaw.json` Zod 스키마 export(`OpenClawSchema`)에는 `openclaw/plugin-sdk/config-schema` -- 공유 설정/auth/응답/webhook - 배선에는 `openclaw/plugin-sdk/channel-setup`, +- `openclaw/plugin-sdk/channel-setup`, `openclaw/plugin-sdk/setup-runtime`, `openclaw/plugin-sdk/setup-adapter-runtime`, `openclaw/plugin-sdk/setup-tools`, @@ -1116,20 +889,12 @@ SDK subpath를 사용하세요. `openclaw/plugin-sdk/channel-reply-pipeline`, `openclaw/plugin-sdk/command-auth`, `openclaw/plugin-sdk/secret-input`, - `openclaw/plugin-sdk/webhook-ingress` 같은 안정적인 channel 기본 요소를 사용하세요. - `channel-inbound`는 debounce, mention 매칭, - 인바운드 mention-policy helper, envelope 포맷, 인바운드 envelope - context helper의 공유 홈입니다. - `channel-setup`은 좁은 선택적 설치 setup seam입니다. - `setup-runtime`은 `setupEntry` / - 지연 시작에서 사용하는 런타임 안전 setup 표면이며, - import 안전 setup patch adapter를 포함합니다. + `openclaw/plugin-sdk/webhook-ingress` 같은 안정적인 채널 기본 요소는 공유 setup/auth/reply/webhook 연결용입니다. `channel-inbound`는 debounce, mention 매칭, inbound mention-policy 헬퍼, envelope formatting, inbound envelope context 헬퍼를 위한 공유 홈입니다. + `channel-setup`은 좁은 optional-install setup seam입니다. + `setup-runtime`은 `setupEntry` / 지연 시작에서 사용되는 런타임 안전 setup 표면이며 import-safe setup patch adapter를 포함합니다. `setup-adapter-runtime`은 env 인식 account-setup adapter seam입니다. - `setup-tools`는 작은 CLI/archive/docs helper seam입니다(`formatCliCommand`, - `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, - `CONFIG_DIR`). -- 공유 런타임/config helper용 도메인 subpath로는 - `openclaw/plugin-sdk/channel-config-helpers`, + `setup-tools`는 작은 CLI/archive/docs 헬퍼 seam(`formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR`)입니다. +- `openclaw/plugin-sdk/channel-config-helpers`, `openclaw/plugin-sdk/allow-from`, `openclaw/plugin-sdk/channel-config-schema`, `openclaw/plugin-sdk/telegram-command-config`, @@ -1147,192 +912,131 @@ SDK subpath를 사용하세요. `openclaw/plugin-sdk/status-helpers`, `openclaw/plugin-sdk/text-runtime`, `openclaw/plugin-sdk/runtime-store`, - `openclaw/plugin-sdk/directory-runtime`를 사용하세요. - `telegram-command-config`는 Telegram custom - command 정규화/검증을 위한 좁은 공개 seam이며, 번들 - Telegram 계약 표면이 일시적으로 불가능하더라도 계속 사용할 수 있습니다. - `text-runtime`은 - assistant-visible-text 제거, markdown 렌더/청크 helper, redaction - helper, directive-tag helper, safe-text 유틸리티를 포함한 공유 text/markdown/logging seam입니다. -- 승인 전용 channel seam은 plugin의 하나의 `approvalCapability` - 계약을 우선해야 합니다. 그러면 core는 관련 없는 plugin 필드에 승인 동작을 섞는 대신 - 그 하나의 capability를 통해 승인 auth, 전달, 렌더, - 네이티브 라우팅, 지연 네이티브 핸들러 동작을 읽습니다. -- `openclaw/plugin-sdk/channel-runtime`은 더 이상 권장되지 않으며, - 오래된 plugin용 호환성 shim으로만 남아 있습니다. 새 코드는 대신 더 좁은 - 일반 기본 요소를 import해야 하며, 리포지토리 코드도 shim에 새 import를 추가해서는 안 됩니다. -- 번들 확장 내부 구조는 비공개로 유지됩니다. 외부 plugin은 `openclaw/plugin-sdk/*` subpath만 사용해야 합니다. - OpenClaw core/test 코드는 `index.js`, `api.js`, - `runtime-api.js`, `setup-entry.js`, `login-qr-api.js` 같은 좁게 범위가 지정된 파일 등 - plugin 패키지 루트 아래의 리포지토리 공개 엔트리 포인트를 사용할 수 있습니다. - core나 다른 확장에서는 plugin 패키지의 `src/*`를 절대 import하지 마세요. -- 리포지토리 엔트리 포인트 분리: - `/api.js`는 helper/types barrel, - `/runtime-api.js`는 런타임 전용 barrel, - `/index.js`는 번들 plugin 엔트리, - `/setup-entry.js`는 setup plugin 엔트리입니다. + `openclaw/plugin-sdk/directory-runtime` 같은 도메인 하위 경로는 공유 런타임/config 헬퍼용입니다. + `telegram-command-config`는 Telegram custom command 정규화/검증을 위한 좁은 공개 seam이며 번들 Telegram 계약 표면이 일시적으로 없더라도 계속 사용할 수 있습니다. + `text-runtime`은 assistant-visible-text 제거, markdown render/chunking 헬퍼, redaction 헬퍼, directive-tag 헬퍼, safe-text 유틸리티를 포함하는 공유 텍스트/markdown/logging seam입니다. +- 승인 전용 채널 seam은 플러그인의 하나의 `approvalCapability` 계약을 우선해야 합니다. 그러면 코어는 승인 auth, 전달, 렌더링, native-routing, 지연 native-handler 동작을 관련 없는 플러그인 필드에 섞는 대신 그 하나의 capability를 통해 읽습니다. +- `openclaw/plugin-sdk/channel-runtime`은 deprecated되었으며 오래된 플러그인을 위한 호환성 shim으로만 남아 있습니다. 새 코드는 더 좁고 일반적인 기본 요소를 import해야 하며, repo 코드에 새 shim import를 추가해서는 안 됩니다. +- 번들 확장 내부 구조는 비공개로 유지됩니다. 외부 플러그인은 `openclaw/plugin-sdk/*` 하위 경로만 사용해야 합니다. OpenClaw 코어/테스트 코드는 `index.js`, `api.js`, `runtime-api.js`, `setup-entry.js`, `login-qr-api.js` 같은 좁은 범위 파일과 같은 플러그인 패키지 루트의 repo 공개 엔트리 포인트를 사용할 수 있습니다. 코어나 다른 확장에서 플러그인 패키지의 `src/*`를 절대 import하지 마세요. +- repo 엔트리 포인트 분리: + `/api.js`는 헬퍼/타입 barrel, + `/runtime-api.js`는 runtime-only barrel, + `/index.js`는 번들 플러그인 엔트리, + `/setup-entry.js`는 setup 플러그인 엔트리입니다. - 현재 번들 provider 예시: - - Anthropic은 `api.js` / `contract-api.js`를 Claude stream helper - (`wrapAnthropicProviderStream`, beta-header helper, `service_tier` - 파싱 등)에 사용합니다. - - OpenAI는 `api.js`를 provider builder, 기본 모델 helper, - 실시간 provider builder에 사용합니다. - - OpenRouter는 `api.js`를 provider builder와 온보딩/config - helper에 사용하고, `register.runtime.js`는 여전히 리포지토리 로컬 용도로 - 일반 `plugin-sdk/provider-stream` helper를 재export할 수 있습니다. -- facade 로드 공개 엔트리 포인트는 - 활성 런타임 config snapshot이 있으면 그것을 우선하고, OpenClaw가 아직 런타임 snapshot을 제공하지 않을 때는 - 디스크의 해석된 config 파일로 fallback합니다. -- 일반 공유 기본 요소는 여전히 선호되는 공개 SDK 계약입니다. - 번들 채널 브랜드 helper seam의 작은 예약 호환성 집합은 여전히 존재합니다. - 이것은 새 서드파티 import 대상이 아니라 - 번들 유지보수/호환성 seam으로 취급하세요. 새로운 교차 채널 계약은 여전히 - 일반 `plugin-sdk/*` subpath 또는 plugin 로컬 `api.js` / - `runtime-api.js` barrel에 반영되어야 합니다. + - Anthropic은 `wrapAnthropicProviderStream`, beta-header 헬퍼, `service_tier` 파싱 같은 Claude 스트림 헬퍼를 위해 `api.js` / `contract-api.js`를 사용합니다. + - OpenAI는 provider builder, 기본 모델 헬퍼, realtime provider builder를 위해 `api.js`를 사용합니다. + - OpenRouter는 provider builder와 onboarding/config 헬퍼를 위해 `api.js`를 사용하고, `register.runtime.js`는 여전히 repo-local 용도로 일반 `plugin-sdk/provider-stream` 헬퍼를 re-export할 수 있습니다. +- facade로 로드되는 공개 엔트리 포인트는 활성 런타임 config 스냅샷이 있으면 그것을 우선하고, OpenClaw가 아직 런타임 스냅샷을 제공하지 않을 때는 디스크의 해석된 config 파일로 fallback됩니다. +- 일반적인 공유 기본 요소가 여전히 선호되는 공개 SDK 계약입니다. 번들 채널 브랜드가 붙은 일부 예약된 호환성 헬퍼 seam이 여전히 존재합니다. 이를 새 서드파티 import 대상이 아니라 번들 유지보수/호환성 seam으로 취급하고, 새로운 채널 간 계약은 여전히 일반 `plugin-sdk/*` 하위 경로나 플러그인 로컬 `api.js` / `runtime-api.js` barrel에 추가해야 합니다. -호환성 참고: +호환성 메모: -- 새 코드에는 루트 `openclaw/plugin-sdk` barrel을 피하세요. -- 먼저 더 좁고 안정적인 기본 요소를 우선하세요. 새로운 - setup/pairing/reply/feedback/contract/inbound/threading/command/secret-input/webhook/infra/ - allowlist/status/message-tool subpath는 새 - 번들 및 외부 plugin 작업을 위한 의도된 계약입니다. +- 새 코드에서는 루트 `openclaw/plugin-sdk` barrel을 피하세요. +- 먼저 좁고 안정적인 기본 요소를 우선하세요. 더 새로운 setup/pairing/reply/feedback/contract/inbound/threading/command/secret-input/webhook/infra/allowlist/status/message-tool 하위 경로가 새 번들 및 외부 플러그인 작업을 위한 의도된 계약입니다. 대상 파싱/매칭은 `openclaw/plugin-sdk/channel-targets`에 속합니다. - 메시지 action gate와 reaction message-id helper는 - `openclaw/plugin-sdk/channel-actions`에 속합니다. -- 번들 확장 전용 helper barrel은 기본적으로 안정적이지 않습니다. helper가 - 번들 확장에만 필요하다면 `openclaw/plugin-sdk/`로 승격하는 대신 - 확장 로컬 `api.js` 또는 `runtime-api.js` seam 뒤에 두세요. -- 새로운 공유 helper seam은 채널 브랜드가 아니라 일반적이어야 합니다. 공유 대상 - 파싱은 `openclaw/plugin-sdk/channel-targets`에 속하고, 채널별 - 내부 구조는 소유 plugin의 로컬 `api.js` 또는 `runtime-api.js` - seam 뒤에 유지됩니다. -- `image-generation`, - `media-understanding`, `speech` 같은 capability별 subpath는 - 번들/네이티브 plugin이 오늘 그것을 사용하기 때문에 존재합니다. 그것이 존재한다고 해서 - export된 모든 helper가 장기적으로 고정된 외부 계약이라는 뜻은 아닙니다. + 메시지 액션 게이트와 reaction message-id 헬퍼는 `openclaw/plugin-sdk/channel-actions`에 속합니다. +- 번들 확장별 헬퍼 barrel은 기본적으로 안정적이지 않습니다. 특정 번들 확장에만 필요한 헬퍼라면 `openclaw/plugin-sdk/`로 승격하지 말고 해당 확장의 로컬 `api.js` 또는 `runtime-api.js` seam 뒤에 두세요. +- 새 공유 헬퍼 seam은 채널 브랜드가 아니라 일반적이어야 합니다. 공유 대상 파싱은 `openclaw/plugin-sdk/channel-targets`에 속하고, 채널별 내부 구조는 소유 플러그인의 로컬 `api.js` 또는 `runtime-api.js` seam 뒤에 남아 있어야 합니다. +- `image-generation`, `media-understanding`, `speech` 같은 capability별 하위 경로는 현재 번들/네이티브 플러그인이 사용하기 때문에 존재합니다. 그렇다고 모든 export된 헬퍼가 장기적으로 고정된 외부 계약이라는 뜻은 아닙니다. -## Message tool 스키마 +## 메시지 도구 스키마 -plugin은 채널별 `describeMessageTool(...)` 스키마 기여를 -소유해야 합니다. provider별 필드는 공유 core가 아니라 plugin에 두세요. +플러그인은 채널별 `describeMessageTool(...)` 스키마 기여를 소유해야 합니다. 제공자별 필드는 공유 코어가 아니라 플러그인 내부에 유지하세요. -공유 가능한 이식형 스키마 조각에는 -`openclaw/plugin-sdk/channel-actions`를 통해 export되는 일반 helper를 재사용하세요. +공유 가능한 이식형 스키마 조각에는 `openclaw/plugin-sdk/channel-actions`를 통해 export되는 일반 헬퍼를 재사용하세요. -- 버튼 그리드 스타일 페이로드에는 `createMessageToolButtonsSchema()` -- 구조화된 카드 페이로드에는 `createMessageToolCardSchema()` +- 버튼 그리드 스타일 payload에는 `createMessageToolButtonsSchema()` +- 구조화된 카드 payload에는 `createMessageToolCardSchema()` -스키마 형태가 하나의 provider에만 의미가 있다면 -공유 SDK로 승격하지 말고 해당 plugin 자체 소스에 정의하세요. +어떤 스키마 형태가 한 provider에만 의미가 있다면 공유 SDK로 승격하지 말고 그 플러그인 자체 소스에 정의하세요. -## Channel 대상 해석 +## 채널 대상 해석 -Channel plugin은 채널별 대상 의미론을 소유해야 합니다. 공유 -아웃바운드 호스트는 일반 상태로 유지하고, provider 규칙에는 메시징 adapter 표면을 사용하세요. +채널 플러그인은 채널별 대상 의미론을 소유해야 합니다. 공유 outbound 호스트는 일반적으로 유지하고, provider 규칙에는 메시징 adapter 표면을 사용하세요. -- `messaging.inferTargetChatType({ to })`는 정규화된 대상을 - 디렉터리 조회 전에 `direct`, `group`, `channel` 중 무엇으로 취급할지 결정합니다. -- `messaging.targetResolver.looksLikeId(raw, normalized)`는 - 입력이 디렉터리 검색 대신 ID 형태 해석으로 바로 넘어가야 하는지 core에 알려줍니다. -- `messaging.targetResolver.resolveTarget(...)`은 - 정규화 후 또는 디렉터리 미스 후 최종 provider 소유 해석이 필요할 때의 plugin fallback입니다. -- `messaging.resolveOutboundSessionRoute(...)`는 - 대상이 해석된 후 provider별 세션 route 구성을 소유합니다. +- `messaging.inferTargetChatType({ to })`는 정규화된 대상을 디렉터리 조회 전에 `direct`, `group`, `channel` 중 무엇으로 취급할지 결정합니다. +- `messaging.targetResolver.looksLikeId(raw, normalized)`는 어떤 입력이 디렉터리 검색 대신 바로 ID 형태 해석으로 넘어가야 하는지 코어에 알려 줍니다. +- `messaging.targetResolver.resolveTarget(...)`는 정규화 후 또는 디렉터리 미스 후 코어가 최종 provider 소유 해석이 필요할 때 쓰는 플러그인 fallback입니다. +- `messaging.resolveOutboundSessionRoute(...)`는 대상이 해석된 후 provider별 세션 라우트 구성을 소유합니다. 권장 분리: -- peer/group 검색 전에 일어나야 하는 범주 결정에는 `inferTargetChatType` 사용 -- "이것을 명시적/네이티브 대상 ID로 취급" 검사에는 `looksLikeId` 사용 -- provider별 정규화 fallback에는 `resolveTarget`을 사용하고, - 광범위한 디렉터리 검색에는 사용하지 않음 -- chat id, thread id, JID, handle, room id 같은 provider 네이티브 ID는 - 일반 SDK 필드가 아니라 `target` 값 또는 provider별 파라미터 안에 유지 +- peer/group 검색 전에 일어나야 하는 범주 결정에는 `inferTargetChatType`을 사용하세요. +- "이것을 명시적/native 대상 ID로 취급하라"는 검사에는 `looksLikeId`를 사용하세요. +- `resolveTarget`은 provider별 정규화 fallback용으로 사용하고, 광범위한 디렉터리 검색용으로 사용하지 마세요. +- chat ID, thread ID, JID, handle, room ID 같은 provider-native ID는 일반 SDK 필드가 아니라 `target` 값이나 provider별 파라미터 내부에 유지하세요. -## Config 기반 디렉터리 +## config 기반 디렉터리 -config에서 디렉터리 항목을 파생하는 plugin은 그 로직을 plugin 안에 두고 -`openclaw/plugin-sdk/directory-runtime`의 공유 helper를 -재사용해야 합니다. +config에서 디렉터리 엔트리를 파생하는 플러그인은 그 로직을 플러그인 내부에 유지하고, `openclaw/plugin-sdk/directory-runtime`의 공유 헬퍼를 재사용해야 합니다. -다음과 같은 config 기반 peer/group가 필요한 채널에 사용하세요. +다음과 같은 config 기반 peer/group이 필요한 채널에서 사용하세요. - allowlist 기반 DM peer -- 구성된 channel/group 맵 -- account 범위 정적 디렉터리 fallback +- 구성된 채널/그룹 맵 +- 계정 범위의 정적 디렉터리 fallback -`directory-runtime`의 공유 helper는 일반 작업만 처리합니다. +`directory-runtime`의 공유 헬퍼는 일반 작업만 처리합니다. - 쿼리 필터링 - limit 적용 -- 중복 제거/정규화 helper +- dedupe/정규화 헬퍼 - `ChannelDirectoryEntry[]` 빌드 -채널별 account 검사와 id 정규화는 plugin 구현 안에 남겨야 합니다. +채널별 계정 검사와 ID 정규화는 플러그인 구현에 남겨 두어야 합니다. -## Provider 카탈로그 +## provider 카탈로그 -Provider plugin은 -`registerProvider({ catalog: { run(...) { ... } } })`로 추론용 모델 카탈로그를 정의할 수 있습니다. +provider 플러그인은 `registerProvider({ catalog: { run(...) { ... } } })`를 통해 추론용 모델 카탈로그를 정의할 수 있습니다. -`catalog.run(...)`은 OpenClaw가 `models.providers`에 기록하는 것과 동일한 형태를 반환합니다. +`catalog.run(...)`은 OpenClaw가 `models.providers`에 기록하는 것과 같은 형태를 반환합니다. -- 하나의 provider 항목에는 `{ provider }` -- 여러 provider 항목에는 `{ providers }` +- 하나의 provider 엔트리에는 `{ provider }` +- 여러 provider 엔트리에는 `{ providers }` -provider가 provider별 모델 id, base URL -기본값 또는 auth 게이트 모델 메타데이터를 소유할 때 `catalog`를 사용하세요. +provider별 model ID, base URL 기본값, 또는 auth-gated 모델 메타데이터를 플러그인이 소유한다면 `catalog`를 사용하세요. -`catalog.order`는 plugin의 카탈로그가 OpenClaw의 내장 암시적 provider에 대해 -언제 병합되는지 제어합니다. +`catalog.order`는 플러그인의 카탈로그가 OpenClaw의 내장 암시적 provider에 대해 언제 병합되는지 제어합니다. - `simple`: 일반 API-key 또는 env 기반 provider - `profile`: auth profile이 있을 때 나타나는 provider -- `paired`: 여러 관련 provider 항목을 synthetic 생성하는 provider -- `late`: 다른 암시적 provider 이후 마지막 단계 +- `paired`: 관련된 여러 provider 엔트리를 합성하는 provider +- `late`: 다른 암시적 provider 이후의 마지막 패스 -나중 provider가 키 충돌 시 이기므로, plugin은 의도적으로 같은 provider id를 가진 -내장 provider 항목을 override할 수 있습니다. +나중에 오는 provider가 키 충돌 시 우선하므로, 플러그인은 같은 provider ID를 가진 내장 provider 엔트리를 의도적으로 override할 수 있습니다. 호환성: -- `discovery`는 여전히 레거시 별칭으로 동작합니다 -- `catalog`와 `discovery`가 둘 다 등록되면 OpenClaw는 `catalog`를 사용합니다 +- `discovery`는 여전히 레거시 별칭으로 동작합니다. +- `catalog`와 `discovery`가 모두 등록되면 OpenClaw는 `catalog`를 사용합니다. -## 읽기 전용 channel 검사 +## 읽기 전용 채널 검사 -plugin이 채널을 등록한다면 -`resolveAccount(...)`와 함께 `plugin.config.inspectAccount(cfg, accountId)`를 구현하는 것을 우선하세요. +플러그인이 채널을 등록한다면, `resolveAccount(...)`와 함께 `plugin.config.inspectAccount(cfg, accountId)` 구현을 우선하세요. 이유: -- `resolveAccount(...)`는 런타임 경로입니다. 자격 증명이 - 완전히 구체화되었다고 가정할 수 있으며 필수 secret이 없으면 빠르게 실패해도 됩니다. -- `openclaw status`, `openclaw status --all`, - `openclaw channels status`, `openclaw channels resolve`, doctor/config - 복구 흐름 같은 읽기 전용 command 경로는 - 구성을 설명하기 위해 런타임 자격 증명을 구체화할 필요가 없어야 합니다. +- `resolveAccount(...)`는 런타임 경로입니다. 자격 증명이 완전히 materialize되었다고 가정할 수 있고, 필요한 secret이 없으면 빠르게 실패해도 됩니다. +- `openclaw status`, `openclaw status --all`, `openclaw channels status`, `openclaw channels resolve`, doctor/config repair 흐름 같은 읽기 전용 명령 경로는 단순히 구성을 설명하기 위해 런타임 자격 증명을 materialize할 필요가 없어야 합니다. 권장 `inspectAccount(...)` 동작: -- 설명적인 account 상태만 반환 -- `enabled`와 `configured` 보존 -- 관련될 때 자격 증명 source/status 필드 포함, 예: +- 설명용 계정 상태만 반환합니다. +- `enabled`와 `configured`를 유지합니다. +- 관련 있을 때 자격 증명 source/status 필드를 포함합니다. 예: - `tokenSource`, `tokenStatus` - `botTokenSource`, `botTokenStatus` - `appTokenSource`, `appTokenStatus` - `signingSecretSource`, `signingSecretStatus` -- 읽기 전용 가용성을 보고하기 위해 raw token 값을 반환할 필요는 없습니다. - 상태 스타일 command에는 `tokenStatus: "available"`(및 일치하는 source 필드)면 충분합니다. -- SecretRef를 통해 자격 증명이 구성되었지만 현재 command 경로에서는 사용할 수 없을 때 - `configured_unavailable`을 사용하세요. +- 읽기 전용 가용성을 보고하기 위해 raw token 값을 반환할 필요는 없습니다. `tokenStatus: "available"`(및 해당 source 필드)만으로 상태형 명령에는 충분합니다. +- 자격 증명이 SecretRef로 구성되었지만 현재 명령 경로에서 사용할 수 없으면 `configured_unavailable`을 사용하세요. -이렇게 하면 읽기 전용 command가 crash하거나 account를 미구성으로 잘못 보고하는 대신 -"구성되었지만 현재 command 경로에서는 사용할 수 없음"을 보고할 수 있습니다. +이렇게 하면 읽기 전용 명령이 크래시하거나 계정을 미구성으로 잘못 보고하는 대신 "구성되어 있지만 이 명령 경로에서는 사용할 수 없음"을 보고할 수 있습니다. -## Package pack +## 패키지 팩 -plugin 디렉터리에는 `openclaw.extensions`가 포함된 `package.json`이 있을 수 있습니다. +플러그인 디렉터리에는 `openclaw.extensions`를 포함한 `package.json`이 있을 수 있습니다. ```json { @@ -1344,63 +1048,38 @@ plugin 디렉터리에는 `openclaw.extensions`가 포함된 `package.json`이 } ``` -각 항목은 하나의 plugin이 됩니다. pack이 여러 확장을 나열하면 plugin id는 -`name/`가 됩니다. +각 엔트리는 하나의 플러그인이 됩니다. 팩이 여러 확장을 나열하면 플러그인 ID는 `name/`가 됩니다. -plugin이 npm 의존성을 import한다면 해당 디렉터리에 설치하여 -`node_modules`를 사용할 수 있게 하세요(`npm install` / `pnpm install`). +플러그인이 npm 의존성을 import한다면, 해당 디렉터리에 이를 설치하여 `node_modules`를 사용할 수 있도록 하세요(`npm install` / `pnpm install`). -보안 가드레일: 모든 `openclaw.extensions` 항목은 symlink 해석 후에도 plugin -디렉터리 내부에 있어야 합니다. 패키지 디렉터리 밖으로 벗어나는 항목은 -거부됩니다. +보안 가드레일: 모든 `openclaw.extensions` 엔트리는 심볼릭 링크 해석 후에도 플러그인 디렉터리 내부에 있어야 합니다. 패키지 디렉터리 밖으로 벗어나는 엔트리는 거부됩니다. -보안 참고: `openclaw plugins install`은 plugin 의존성을 -`npm install --omit=dev --ignore-scripts`로 설치합니다(라이프사이클 스크립트 없음, 런타임에 dev dependency 없음). plugin 의존성 -트리는 "순수 JS/TS"로 유지하고 `postinstall` 빌드가 필요한 패키지는 피하세요. +보안 메모: `openclaw plugins install`은 `npm install --omit=dev --ignore-scripts`로 플러그인 의존성을 설치합니다(라이프사이클 스크립트 없음, 런타임에 dev dependencies 없음). 플러그인 의존성 트리는 "순수 JS/TS"로 유지하고 `postinstall` 빌드가 필요한 패키지는 피하세요. 선택 사항: `openclaw.setupEntry`는 가벼운 setup 전용 모듈을 가리킬 수 있습니다. -OpenClaw가 비활성화된 channel plugin의 setup 표면이 필요하거나, -channel plugin이 활성화되었지만 아직 구성되지 않은 경우, 전체 plugin 엔트리 대신 -`setupEntry`를 로드합니다. 이렇게 하면 메인 plugin 엔트리가 tool, hook, -기타 런타임 전용 코드를 함께 연결하는 경우 시작과 setup이 더 가벼워집니다. +OpenClaw가 비활성화된 채널 플러그인의 setup 표면이 필요할 때, 또는 채널 플러그인이 활성화되었지만 아직 구성되지 않았을 때는 전체 플러그인 엔트리 대신 `setupEntry`를 로드합니다. 이렇게 하면 메인 플러그인 엔트리가 도구, 훅, 기타 runtime-only 코드를 연결하더라도 시작과 setup을 더 가볍게 유지할 수 있습니다. -선택 사항: `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` -은 channel plugin이 이미 구성된 경우에도 gateway의 -pre-listen 시작 단계에서 동일한 `setupEntry` 경로를 사용하도록 opt-in할 수 있습니다. +선택 사항: `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen`은 채널이 이미 구성된 경우에도 gateway의 pre-listen 시작 단계에서 채널 플러그인을 같은 `setupEntry` 경로에 opt-in시킬 수 있습니다. -이것은 `setupEntry`가 gateway가 수신을 시작하기 전에 존재해야 하는 시작 표면을 -완전히 덮을 때만 사용하세요. 실제로는 setup 엔트리가 -다음과 같이 시작이 의존하는 모든 채널 소유 capability를 등록해야 함을 의미합니다. +이 옵션은 `setupEntry`가 gateway가 수신을 시작하기 전에 반드시 존재해야 하는 시작 표면을 완전히 커버할 때만 사용하세요. 실제로는 setup 엔트리가 시작이 의존하는 모든 채널 소유 capability를 등록해야 한다는 뜻입니다. 예를 들면: - 채널 등록 자체 -- gateway가 수신을 시작하기 전에 사용 가능해야 하는 모든 HTTP route -- 같은 시간 창에 존재해야 하는 모든 gateway 메서드, tool, service +- gateway가 수신을 시작하기 전에 사용 가능해야 하는 모든 HTTP 라우트 +- 같은 시점에 존재해야 하는 모든 gateway 메서드, 도구, 서비스 -전체 엔트리가 여전히 필수 시작 capability를 소유하고 있다면 -이 플래그를 활성화하지 마세요. 기본 동작을 유지하고 OpenClaw가 -시작 중 전체 엔트리를 로드하게 하세요. +전체 엔트리가 여전히 필요한 시작 capability를 소유하고 있다면 이 플래그를 활성화하지 마세요. 기본 동작을 유지하고 OpenClaw가 시작 중 전체 엔트리를 로드하게 두세요. -번들 채널은 전체 채널 런타임이 로드되기 전에 core가 참조할 수 있는 -setup 전용 계약 표면 helper를 게시할 수도 있습니다. 현재 setup 승격 표면은 다음과 같습니다. +번들 채널은 전체 채널 런타임이 로드되기 전에 코어가 참조할 수 있는 setup 전용 계약 표면 헬퍼를 게시할 수도 있습니다. 현재 setup 승격 표면은 다음과 같습니다. - `singleAccountKeysToMove` - `namedAccountPromotionKeys` - `resolveSingleAccountPromotionTarget(...)` -Core는 레거시 단일 account 채널 config를 -전체 plugin 엔트리를 로드하지 않고 `channels..accounts.*`로 승격해야 할 때 이 표면을 사용합니다. -현재 번들 예시는 Matrix입니다. Matrix는 명명된 account가 이미 존재할 때 -auth/bootstrap 키만 명명된 승격 account로 옮기고, -항상 `accounts.default`를 생성하는 대신 구성된 비정형 기본 account 키를 보존할 수 있습니다. +코어는 레거시 단일 계정 채널 config를 전체 플러그인 엔트리를 로드하지 않고 `channels..accounts.*`로 승격해야 할 때 이 표면을 사용합니다. 현재 번들 예시는 Matrix입니다. named account가 이미 존재할 때 인증/bootstrap 키만 named 승격 계정으로 이동하고, 항상 `accounts.default`를 만드는 대신 구성된 비정규 default-account 키를 보존할 수 있습니다. -이러한 setup patch adapter는 번들 계약 표면 발견을 지연 상태로 유지합니다. -import 시점은 가볍게 유지되고, 승격 표면은 모듈 import 중에 번들 채널 시작에 재진입하는 대신 -첫 사용 시에만 로드됩니다. +이러한 setup patch adapter는 번들 계약 표면 디스커버리를 지연 상태로 유지합니다. import 시점은 가볍게 유지되고, 승격 표면은 모듈 import 중 번들 채널 시작을 다시 진입하지 않고 첫 사용 시에만 로드됩니다. -이러한 시작 표면에 gateway RPC 메서드가 포함될 때는 -plugin별 prefix를 유지하세요. Core 관리자 네임스페이스(`config.*`, -`exec.approvals.*`, `wizard.*`, `update.*`)는 예약되어 있으며, -plugin이 더 좁은 범위를 요청해도 항상 `operator.admin`으로 해석됩니다. +이러한 시작 표면에 gateway RPC 메서드가 포함될 때는 플러그인 전용 prefix 아래에 두세요. 코어 관리자 네임스페이스(`config.*`, `exec.approvals.*`, `wizard.*`, `update.*`)는 예약되어 있으며, 플러그인이 더 좁은 scope를 요청하더라도 항상 `operator.admin`으로 해석됩니다. 예시: @@ -1417,10 +1096,9 @@ plugin이 더 좁은 범위를 요청해도 항상 `operator.admin`으로 해석 } ``` -### Channel 카탈로그 메타데이터 +### 채널 카탈로그 메타데이터 -Channel plugin은 `openclaw.channel`을 통해 setup/discovery 메타데이터를, -`openclaw.install`을 통해 설치 힌트를 광고할 수 있습니다. 이렇게 하면 core 카탈로그에 데이터가 없어도 됩니다. +채널 플러그인은 `openclaw.channel`을 통해 setup/discovery 메타데이터를, `openclaw.install`을 통해 install 힌트를 광고할 수 있습니다. 이렇게 하면 코어 카탈로그를 data-free로 유지할 수 있습니다. 예시: @@ -1450,40 +1128,32 @@ Channel plugin은 `openclaw.channel`을 통해 setup/discovery 메타데이터 최소 예시 외에 유용한 `openclaw.channel` 필드: -- `detailLabel`: 더 풍부한 카탈로그/상태 표면용 보조 라벨 -- `docsLabel`: docs 링크 텍스트 override -- `preferOver`: 이 카탈로그 항목이 우선해야 하는 더 낮은 우선순위 plugin/channel id -- `selectionDocsPrefix`, `selectionDocsOmitLabel`, `selectionExtras`: 선택 표면용 복사본 제어 -- `markdownCapable`: 아웃바운드 포맷 결정에서 채널이 markdown 가능함을 표시 -- `exposure.configured`: `false`로 설정하면 구성된 채널 목록 표면에서 채널 숨김 -- `exposure.setup`: `false`로 설정하면 대화형 setup/configure picker에서 채널 숨김 -- `exposure.docs`: docs 탐색 표면에서 채널을 내부/비공개로 표시 -- `showConfigured` / `showInSetup`: 호환성을 위해 여전히 허용되는 레거시 별칭. `exposure`를 우선하세요 +- `detailLabel`: 더 풍부한 카탈로그/상태 표면을 위한 보조 레이블 +- `docsLabel`: 문서 링크 텍스트 override +- `preferOver`: 이 카탈로그 엔트리가 더 높은 우선순위를 가져야 하는 낮은 우선순위 플러그인/채널 ID +- `selectionDocsPrefix`, `selectionDocsOmitLabel`, `selectionExtras`: 선택 표면 복사 제어 +- `markdownCapable`: outbound formatting 결정용으로 해당 채널이 markdown-capable임을 표시 +- `exposure.configured`: `false`이면 구성된 채널 목록 표면에서 채널 숨김 +- `exposure.setup`: `false`이면 대화형 setup/configure picker에서 채널 숨김 +- `exposure.docs`: 문서 탐색 표면에서 채널을 내부/비공개로 표시 +- `showConfigured` / `showInSetup`: 호환성을 위해 여전히 허용되는 레거시 별칭이지만 `exposure`를 우선 - `quickstartAllowFrom`: 채널을 표준 quickstart `allowFrom` 흐름에 opt-in -- `forceAccountBinding`: 하나의 account만 있어도 명시적 account 바인딩을 요구 -- `preferSessionLookupForAnnounceTarget`: announce 대상 해석 시 session lookup을 우선 +- `forceAccountBinding`: 계정이 하나뿐이어도 명시적 계정 바인딩 요구 +- `preferSessionLookupForAnnounceTarget`: announce 대상 해석 시 세션 조회를 우선 -OpenClaw는 **외부 channel 카탈로그**도 병합할 수 있습니다(예: -MPM 레지스트리 export). 다음 위치 중 하나에 JSON 파일을 두세요. +OpenClaw는 **외부 채널 카탈로그**(예: MPM 레지스트리 export)도 병합할 수 있습니다. 다음 위치 중 하나에 JSON 파일을 두세요. - `~/.openclaw/mpm/plugins.json` - `~/.openclaw/mpm/catalog.json` - `~/.openclaw/plugins/catalog.json` -또는 `OPENCLAW_PLUGIN_CATALOG_PATHS`(또는 `OPENCLAW_MPM_CATALOG_PATHS`)를 -하나 이상의 JSON 파일로 가리키게 하세요(쉼표/세미콜론/`PATH` 구분). 각 파일에는 -`{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`가 들어 있어야 합니다. -파서는 `"entries"` 키의 레거시 별칭으로 `"packages"` 또는 `"plugins"`도 허용합니다. +또는 `OPENCLAW_PLUGIN_CATALOG_PATHS`(또는 `OPENCLAW_MPM_CATALOG_PATHS`)로 하나 이상의 JSON 파일을 지정하세요(쉼표/세미콜론/`PATH` 구분). 각 파일은 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }` 형식을 가져야 합니다. 파서는 `"entries"` 키의 레거시 별칭으로 `"packages"`나 `"plugins"`도 허용합니다. -## Context engine plugin +## 컨텍스트 엔진 플러그인 -Context engine plugin은 ingest, assemble, -compaction을 위한 세션 컨텍스트 오케스트레이션을 소유합니다. -plugin에서 `api.registerContextEngine(id, factory)`로 등록한 다음, -`plugins.slots.contextEngine`으로 활성 엔진을 선택하세요. +컨텍스트 엔진 플러그인은 ingest, assemble, compaction을 위한 세션 컨텍스트 orchestration을 소유합니다. 플러그인에서 `api.registerContextEngine(id, factory)`로 등록한 다음, 활성 엔진은 `plugins.slots.contextEngine`으로 선택합니다. -기본 context -파이프라인을 단순히 memory search나 hook으로 확장하는 것이 아니라 교체 또는 확장해야 할 때 사용하세요. +기본 컨텍스트 파이프라인을 단순히 확장하는 것이 아니라 이를 교체하거나 확장해야 한다면 이 방식을 사용하세요. ```ts import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core"; @@ -1511,8 +1181,7 @@ export default function (api) { } ``` -엔진이 compaction 알고리즘을 **소유하지 않는다면** `compact()`는 계속 -구현하되 명시적으로 위임하세요. +엔진이 compaction 알고리즘을 **소유하지 않는다면**, `compact()`를 구현한 채 명시적으로 위임하세요. ```ts import { @@ -1547,49 +1216,41 @@ export default function (api) { } ``` -## 새 capability 추가 +## 새 capability 추가하기 -plugin에 현재 API에 맞지 않는 동작이 필요하다면, -비공개 직접 접근으로 plugin 시스템을 우회하지 마세요. 누락된 capability를 추가하세요. +플러그인에 현재 API에 맞지 않는 동작이 필요하다면, 비공개 직접 접근으로 플러그인 시스템을 우회하지 마세요. 누락된 capability를 추가하세요. 권장 순서: -1. core 계약 정의 - core가 소유해야 할 공유 동작을 결정합니다. 정책, fallback, config 병합, - lifecycle, 채널 표면 의미론, 런타임 helper 형태를 정하세요. -2. 정형 plugin 등록/런타임 표면 추가 - 가장 작은 유용한 - 정형 capability 표면으로 `OpenClawPluginApi` 및/또는 `api.runtime`를 확장합니다. -3. core + channel/feature 소비자 연결 - 채널과 기능 plugin은 벤더 구현을 직접 import하지 말고, - core를 통해 새 capability를 소비해야 합니다. +1. 코어 계약 정의 + 코어가 소유해야 하는 공유 동작을 결정합니다: 정책, fallback, config 병합, 라이프사이클, 채널 대상 의미론, 런타임 헬퍼 형태. +2. typed 플러그인 등록/런타임 표면 추가 + 가장 작은 유용한 typed capability 표면으로 `OpenClawPluginApi` 및/또는 `api.runtime`를 확장합니다. +3. 코어 + 채널/기능 소비자 연결 + 채널과 기능 플러그인은 벤더 구현을 직접 import하지 말고, 코어를 통해 새 capability를 소비해야 합니다. 4. 벤더 구현 등록 - 그런 다음 벤더 plugin이 그 capability에 대해 자신의 백엔드를 등록합니다. + 그다음 벤더 플러그인이 이 capability에 대해 백엔드를 등록합니다. 5. 계약 커버리지 추가 시간이 지나도 소유권과 등록 형태가 명시적으로 유지되도록 테스트를 추가합니다. -이것이 OpenClaw가 한 provider의 세계관에 하드코딩되지 않으면서도 -의견 있는 구조를 유지하는 방식입니다. 구체적인 파일 체크리스트와 예시는 -[Capability Cookbook](/ko/plugins/architecture)을 참조하세요. +이것이 OpenClaw가 특정 제공자의 세계관에 하드코딩되지 않으면서도 명확한 방향성을 유지하는 방식입니다. 구체적인 파일 체크리스트와 예시는 [Capability Cookbook](/ko/plugins/architecture)를 참조하세요. -### Capability 체크리스트 +### capability 체크리스트 -새 capability를 추가할 때 구현은 보통 다음 표면을 함께 수정해야 합니다. +새 capability를 추가할 때 구현은 보통 다음 표면들을 함께 건드려야 합니다. -- `src//types.ts`의 core 계약 타입 -- `src//runtime.ts`의 core 러너/런타임 helper -- `src/plugins/types.ts`의 plugin API 등록 표면 -- `src/plugins/registry.ts`의 plugin 레지스트리 배선 -- 기능/channel plugin이 이를 소비해야 할 때 `src/plugins/runtime/*`의 - plugin 런타임 노출 -- `src/test-utils/plugin-registration.ts`의 캡처/테스트 helper -- `src/plugins/contracts/registry.ts`의 소유권/계약 검증 -- `docs/`의 운영자/plugin 문서 +- `src//types.ts`의 코어 계약 타입 +- `src//runtime.ts`의 코어 runner/런타임 헬퍼 +- `src/plugins/types.ts`의 플러그인 API 등록 표면 +- `src/plugins/registry.ts`의 플러그인 레지스트리 연결 +- 기능/채널 플러그인이 이를 소비해야 할 때의 `src/plugins/runtime/*` 플러그인 런타임 노출 +- `src/test-utils/plugin-registration.ts`의 capture/test 헬퍼 +- `src/plugins/contracts/registry.ts`의 소유권/계약 assertion +- `docs/`의 operator/플러그인 문서 -이 표면 중 하나가 누락되었다면 보통 그 capability가 아직 -완전히 통합되지 않았다는 신호입니다. +이 표면들 중 하나가 빠져 있다면, 보통 그 capability가 아직 완전히 통합되지 않았다는 신호입니다. -### Capability 템플릿 +### capability 템플릿 최소 패턴: @@ -1610,7 +1271,7 @@ api.registerVideoGenerationProvider({ }, }); -// 기능/channel plugin용 공유 런타임 helper +// shared runtime helper for feature/channel plugins const clip = await api.runtime.videoGeneration.generate({ prompt: "Show the robot walking through the lab.", cfg, @@ -1623,9 +1284,9 @@ const clip = await api.runtime.videoGeneration.generate({ expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]); ``` -이렇게 하면 규칙이 단순해집니다. +이렇게 규칙은 단순하게 유지됩니다. -- core가 capability 계약 + 오케스트레이션을 소유 -- 벤더 plugin이 벤더 구현을 소유 -- 기능/channel plugin이 런타임 helper를 소비 -- 계약 테스트가 소유권을 명시적으로 유지 +- 코어는 capability 계약 + orchestration을 소유합니다. +- 벤더 플러그인은 벤더 구현을 소유합니다. +- 기능/채널 플러그인은 런타임 헬퍼를 소비합니다. +- 계약 테스트는 소유권을 명시적으로 유지합니다. diff --git a/docs/ko/plugins/manifest.md b/docs/ko/plugins/manifest.md index f5f02cf06..49036bf02 100644 --- a/docs/ko/plugins/manifest.md +++ b/docs/ko/plugins/manifest.md @@ -1,73 +1,64 @@ --- read_when: - - OpenClaw plugin을 빌드할 때 - - plugin config schema를 배포하거나 plugin 검증 오류를 디버깅해야 할 때 -summary: Plugin 매니페스트 + JSON schema 요구 사항(엄격한 config 검증) + - OpenClaw plugin을 빌드하고 있습니다 + - plugin 구성 스키마를 배포하거나 plugin 검증 오류를 디버그해야 합니다 +summary: Plugin 매니페스트 + JSON Schema 요구 사항(엄격한 구성 검증) title: Plugin 매니페스트 x-i18n: - generated_at: "2026-04-07T05:58:49Z" + generated_at: "2026-04-09T01:29:23Z" model: gpt-5.4 provider: openai - source_hash: 22d41b9f8748b1b1b066ee856be4a8f41e88b9a8bc073d74fc79d2bb0982f01a + source_hash: 9a7ee4b621a801d2a8f32f8976b0e1d9433c7810eb360aca466031fc0ffb286a source_path: plugins/manifest.md workflow: 15 --- -# Plugin 매니페스트 (openclaw.plugin.json) +# Plugin 매니페스트(openclaw.plugin.json) -이 페이지는 **네이티브 OpenClaw plugin 매니페스트**만을 위한 문서입니다. +이 페이지는 **네이티브 OpenClaw plugin 매니페스트** 전용입니다. -호환되는 번들 레이아웃은 [Plugin bundles](/ko/plugins/bundles)를 참고하세요. +호환되는 번들 레이아웃은 [Plugin bundles](/ko/plugins/bundles)를 참조하세요. -호환 번들 형식은 서로 다른 매니페스트 파일을 사용합니다: +호환되는 번들 형식은 서로 다른 매니페스트 파일을 사용합니다. - Codex 번들: `.codex-plugin/plugin.json` - Claude 번들: `.claude-plugin/plugin.json` 또는 매니페스트가 없는 기본 Claude component 레이아웃 - Cursor 번들: `.cursor-plugin/plugin.json` -OpenClaw는 해당 번들 레이아웃도 자동 감지하지만, 여기서 설명하는 -`openclaw.plugin.json` schema에 대해 검증되지는 않습니다. +OpenClaw는 이러한 번들 레이아웃도 자동 감지하지만, 여기서 설명하는 `openclaw.plugin.json` 스키마에 대해서는 검증하지 않습니다. -호환 번들의 경우 OpenClaw는 현재 번들 메타데이터와 선언된 -skill 루트, Claude 명령 루트, Claude 번들 `settings.json` 기본값, -Claude 번들 LSP 기본값, 그리고 레이아웃이 -OpenClaw 런타임 기대 사항과 일치할 때 지원되는 hook pack을 읽습니다. +호환 번들의 경우, OpenClaw는 현재 레이아웃이 OpenClaw 런타임 기대 사항과 일치할 때 번들 메타데이터와 선언된 skill 루트, Claude command 루트, Claude 번들 `settings.json` 기본값, Claude 번들 LSP 기본값, 지원되는 hook pack을 읽습니다. -모든 네이티브 OpenClaw plugin은 **plugin 루트**에 `openclaw.plugin.json` 파일을 -반드시 포함해야 합니다. OpenClaw는 이 매니페스트를 사용해 plugin 코드를 -**실행하지 않고도** 구성을 검증합니다. 매니페스트가 없거나 유효하지 않으면 -plugin 오류로 처리되며 config 검증이 차단됩니다. +모든 네이티브 OpenClaw plugin은 **plugin 루트**에 `openclaw.plugin.json` 파일을 **반드시** 포함해야 합니다. OpenClaw는 이 매니페스트를 사용해 **plugin 코드를 실행하지 않고도** 구성을 검증합니다. 매니페스트가 없거나 유효하지 않으면 plugin 오류로 처리되며 구성 검증이 차단됩니다. -전체 plugin 시스템 가이드는 [Plugins](/ko/tools/plugin)를 참고하세요. -네이티브 capability 모델과 현재 외부 호환성 안내는 -[Capability model](/ko/plugins/architecture#public-capability-model)을 참고하세요. +전체 plugin 시스템 가이드는 [Plugins](/ko/tools/plugin)를 참조하세요. +네이티브 capability 모델과 현재 외부 호환성 지침은 [Capability model](/ko/plugins/architecture#public-capability-model)을 참조하세요. ## 이 파일의 역할 -`openclaw.plugin.json`은 OpenClaw가 plugin 코드를 로드하기 전에 읽는 -메타데이터입니다. +`openclaw.plugin.json`은 OpenClaw가 plugin 코드를 로드하기 전에 읽는 메타데이터입니다. -다음 용도로 사용하세요: +다음 용도로 사용하세요. - plugin 식별자 -- config 검증 -- plugin 런타임을 부팅하지 않고도 사용할 수 있어야 하는 인증 및 온보딩 메타데이터 -- plugin 런타임이 로드되기 전에 해석되어야 하는 별칭 및 자동 활성화 메타데이터 -- 런타임이 로드되기 전에 plugin을 자동 활성화해야 하는 축약형 모델 계열 소유 메타데이터 -- 번들 compat 배선과 contract 커버리지에 사용되는 정적 capability 소유 스냅샷 -- 런타임을 로드하지 않고 catalog 및 검증 표면에 병합되어야 하는 채널별 config 메타데이터 +- 구성 검증 +- plugin 런타임을 부팅하지 않고도 사용할 수 있어야 하는 auth 및 onboarding 메타데이터 +- plugin 런타임 로드 전에 해석되어야 하는 별칭 및 자동 활성화 메타데이터 +- 런타임 로드 전에 plugin을 자동 활성화해야 하는 shorthand model-family 소유 메타데이터 +- 번들 compat wiring 및 계약 커버리지에 사용되는 정적 capability 소유 스냅샷 +- 런타임을 로드하지 않고 catalog 및 검증 표면에 병합되어야 하는 채널별 구성 메타데이터 - config UI 힌트 -다음 용도로는 사용하지 마세요: +다음 용도로는 사용하지 마세요. - 런타임 동작 등록 -- 코드 엔트리포인트 선언 +- 코드 entrypoint 선언 - npm 설치 메타데이터 -이러한 항목은 plugin 코드와 `package.json`에 속합니다. +이들은 plugin 코드와 `package.json`에 속합니다. -## 최소 예시 +## 최소 예제 ```json { @@ -80,7 +71,7 @@ plugin 오류로 처리되며 config 검증이 차단됩니다. } ``` -## 상세 예시 +## 자세한 예제 ```json { @@ -96,6 +87,9 @@ plugin 오류로 처리되며 config 검증이 차단됩니다. "providerAuthEnvVars": { "openrouter": ["OPENROUTER_API_KEY"] }, + "providerAuthAliases": { + "openrouter-coding": "openrouter" + }, "channelEnvVars": { "openrouter-chatops": ["OPENROUTER_CHATOPS_TOKEN"] }, @@ -135,63 +129,64 @@ plugin 오류로 처리되며 config 검증이 차단됩니다. ## 최상위 필드 참조 -| Field | Required | Type | What it means | -| ----------------------------------- | -------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `id` | Yes | `string` | 정식 plugin id입니다. 이 id는 `plugins.entries.`에서 사용됩니다. | -| `configSchema` | Yes | `object` | 이 plugin config용 인라인 JSON Schema입니다. | -| `enabledByDefault` | No | `true` | 번들 plugin을 기본적으로 활성화된 것으로 표시합니다. 기본 비활성 상태로 두려면 생략하거나 `true`가 아닌 값을 설정하세요. | -| `legacyPluginIds` | No | `string[]` | 이 정식 plugin id로 정규화되는 레거시 id입니다. | -| `autoEnableWhenConfiguredProviders` | No | `string[]` | 인증, config 또는 모델 참조에서 해당 provider id가 언급될 때 이 plugin을 자동 활성화해야 하는 provider id입니다. | -| `kind` | No | `"memory"` \| `"context-engine"` | `plugins.slots.*`에서 사용하는 배타적 plugin kind를 선언합니다. | -| `channels` | No | `string[]` | 이 plugin이 소유하는 채널 id입니다. 검색 및 config 검증에 사용됩니다. | -| `providers` | No | `string[]` | 이 plugin이 소유하는 provider id입니다. | -| `modelSupport` | No | `object` | 런타임 전에 plugin을 자동 로드하는 데 사용되는, 매니페스트 소유 축약형 모델 계열 메타데이터입니다. | -| `cliBackends` | No | `string[]` | 이 plugin이 소유하는 CLI 추론 backend id입니다. 명시적 config 참조에 따른 시작 시 자동 활성화에 사용됩니다. | -| `providerAuthEnvVars` | No | `Record` | OpenClaw가 plugin 코드를 로드하지 않고도 확인할 수 있는 저비용 provider 인증 env 메타데이터입니다. | -| `channelEnvVars` | No | `Record` | OpenClaw가 plugin 코드를 로드하지 않고도 확인할 수 있는 저비용 채널 env 메타데이터입니다. 일반적인 시작/config 도우미가 확인해야 하는 env 기반 채널 설정 또는 인증 표면에 사용하세요. | -| `providerAuthChoices` | No | `object[]` | 온보딩 선택기, 선호 provider 해석, 간단한 CLI 플래그 연결을 위한 저비용 인증 선택 메타데이터입니다. | -| `contracts` | No | `object` | 음성, 실시간 전사, 실시간 음성, media-understanding, image-generation, music-generation, video-generation, web-fetch, 웹 검색, 도구 소유권에 대한 정적 번들 capability 스냅샷입니다. | -| `channelConfigs` | No | `Record` | 런타임 로드 전에 검색 및 검증 표면에 병합되는, 매니페스트 소유 채널 config 메타데이터입니다. | -| `skills` | No | `string[]` | plugin 루트를 기준으로 한, 로드할 skill 디렉터리입니다. | -| `name` | No | `string` | 사람이 읽을 수 있는 plugin 이름입니다. | -| `description` | No | `string` | plugin 표면에 표시되는 짧은 요약입니다. | -| `version` | No | `string` | 정보 제공용 plugin 버전입니다. | -| `uiHints` | No | `Record` | config 필드를 위한 UI 라벨, placeholder, 민감도 힌트입니다. | +| Field | Required | Type | 의미 | +| ----------------------------------- | -------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | Yes | `string` | 정식 plugin id입니다. 이 id는 `plugins.entries.`에서 사용됩니다. | +| `configSchema` | Yes | `object` | 이 plugin 구성에 대한 인라인 JSON Schema입니다. | +| `enabledByDefault` | No | `true` | 번들 plugin을 기본적으로 활성화된 것으로 표시합니다. 기본적으로 비활성화 상태로 두려면 생략하거나 `true`가 아닌 값을 설정하세요. | +| `legacyPluginIds` | No | `string[]` | 이 정식 plugin id로 정규화되는 레거시 id입니다. | +| `autoEnableWhenConfiguredProviders` | No | `string[]` | auth, config 또는 model ref에서 해당 provider id를 언급할 때 이 plugin을 자동 활성화해야 하는 provider id입니다. | +| `kind` | No | `"memory"` \| `"context-engine"` | `plugins.slots.*`에서 사용하는 배타적 plugin kind를 선언합니다. | +| `channels` | No | `string[]` | 이 plugin이 소유한 channel id입니다. 검색 및 구성 검증에 사용됩니다. | +| `providers` | No | `string[]` | 이 plugin이 소유한 provider id입니다. | +| `modelSupport` | No | `object` | 런타임 전에 plugin을 자동 로드하는 데 사용되는 매니페스트 소유 shorthand model-family 메타데이터입니다. | +| `cliBackends` | No | `string[]` | 이 plugin이 소유한 CLI inference backend id입니다. 명시적 config ref를 기준으로 시작 시 자동 활성화하는 데 사용됩니다. | +| `providerAuthEnvVars` | No | `Record` | OpenClaw가 plugin 코드를 로드하지 않고도 검사할 수 있는 저비용 provider-auth env 메타데이터입니다. | +| `providerAuthAliases` | No | `Record` | auth 조회를 위해 다른 provider id를 재사용해야 하는 provider id입니다. 예를 들어 기본 provider API 키와 auth 프로필을 공유하는 코딩 provider가 해당됩니다. | +| `channelEnvVars` | No | `Record` | OpenClaw가 plugin 코드를 로드하지 않고도 검사할 수 있는 저비용 channel env 메타데이터입니다. env 기반 channel 설정 또는 범용 startup/config helper가 확인해야 하는 auth 표면에 사용하세요. | +| `providerAuthChoices` | No | `object[]` | onboarding 선택기, 선호 provider 결정, 간단한 CLI 플래그 wiring을 위한 저비용 auth-choice 메타데이터입니다. | +| `contracts` | No | `object` | speech, realtime transcription, realtime voice, media-understanding, image-generation, music-generation, video-generation, web-fetch, web search 및 tool 소유권에 대한 정적 번들 capability 스냅샷입니다. | +| `channelConfigs` | No | `Record` | 런타임이 로드되기 전에 검색 및 검증 표면에 병합되는 매니페스트 소유 channel config 메타데이터입니다. | +| `skills` | No | `string[]` | plugin 루트를 기준으로 로드할 skill 디렉터리입니다. | +| `name` | No | `string` | 사람이 읽을 수 있는 plugin 이름입니다. | +| `description` | No | `string` | plugin 표면에 표시되는 짧은 요약입니다. | +| `version` | No | `string` | 정보 제공용 plugin 버전입니다. | +| `uiHints` | No | `Record` | 구성 필드에 대한 UI 레이블, placeholder, 민감도 힌트입니다. | ## providerAuthChoices 참조 -각 `providerAuthChoices` 항목은 하나의 온보딩 또는 인증 선택을 설명합니다. +각 `providerAuthChoices` 항목은 하나의 onboarding 또는 auth 선택지를 설명합니다. OpenClaw는 provider 런타임이 로드되기 전에 이를 읽습니다. -| Field | Required | Type | What it means | -| --------------------- | -------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -| `provider` | Yes | `string` | 이 선택이 속하는 provider id입니다. | -| `method` | Yes | `string` | 디스패치할 인증 방식 id입니다. | -| `choiceId` | Yes | `string` | 온보딩 및 CLI 흐름에서 사용되는 안정적인 인증 선택 id입니다. | -| `choiceLabel` | No | `string` | 사용자 대상 라벨입니다. 생략되면 OpenClaw는 `choiceId`로 폴백합니다. | -| `choiceHint` | No | `string` | 선택기를 위한 짧은 도움말 텍스트입니다. | -| `assistantPriority` | No | `number` | assistant 기반 대화형 선택기에서 값이 낮을수록 먼저 정렬됩니다. | -| `assistantVisibility` | No | `"visible"` \| `"manual-only"` | 수동 CLI 선택은 허용하면서 assistant 선택기에서는 이 선택을 숨깁니다. | -| `deprecatedChoiceIds` | No | `string[]` | 사용자를 이 대체 선택으로 리디렉션해야 하는 레거시 choice id입니다. | -| `groupId` | No | `string` | 관련 선택을 그룹화하기 위한 선택적 group id입니다. | -| `groupLabel` | No | `string` | 해당 그룹의 사용자 대상 라벨입니다. | -| `groupHint` | No | `string` | 그룹을 위한 짧은 도움말 텍스트입니다. | -| `optionKey` | No | `string` | 간단한 단일 플래그 인증 흐름용 내부 옵션 키입니다. | -| `cliFlag` | No | `string` | `--openrouter-api-key` 같은 CLI 플래그 이름입니다. | -| `cliOption` | No | `string` | `--openrouter-api-key ` 같은 전체 CLI 옵션 형태입니다. | -| `cliDescription` | No | `string` | CLI 도움말에 사용되는 설명입니다. | -| `onboardingScopes` | No | `Array<"text-inference" \| "image-generation">` | 이 선택이 표시되어야 하는 온보딩 표면입니다. 생략하면 기본값은 `["text-inference"]`입니다. | +| Field | Required | Type | 의미 | +| --------------------- | -------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| `provider` | Yes | `string` | 이 선택지가 속한 provider id입니다. | +| `method` | Yes | `string` | 전달할 auth method id입니다. | +| `choiceId` | Yes | `string` | onboarding 및 CLI 흐름에서 사용하는 안정적인 auth-choice id입니다. | +| `choiceLabel` | No | `string` | 사용자용 레이블입니다. 생략하면 OpenClaw는 `choiceId`로 폴백합니다. | +| `choiceHint` | No | `string` | 선택기에 표시할 짧은 도움말 텍스트입니다. | +| `assistantPriority` | No | `number` | assistant 기반 대화형 선택기에서 더 낮은 값이 먼저 정렬됩니다. | +| `assistantVisibility` | No | `"visible"` \| `"manual-only"` | assistant 선택기에서는 숨기되 수동 CLI 선택은 계속 허용합니다. | +| `deprecatedChoiceIds` | No | `string[]` | 사용자를 이 대체 선택지로 리디렉션해야 하는 레거시 choice id입니다. | +| `groupId` | No | `string` | 관련 선택지를 그룹화하기 위한 선택적 group id입니다. | +| `groupLabel` | No | `string` | 해당 그룹의 사용자용 레이블입니다. | +| `groupHint` | No | `string` | 그룹에 대한 짧은 도움말 텍스트입니다. | +| `optionKey` | No | `string` | 간단한 단일 플래그 auth 흐름을 위한 내부 option key입니다. | +| `cliFlag` | No | `string` | `--openrouter-api-key` 같은 CLI 플래그 이름입니다. | +| `cliOption` | No | `string` | `--openrouter-api-key ` 같은 전체 CLI option 형태입니다. | +| `cliDescription` | No | `string` | CLI help에 사용되는 설명입니다. | +| `onboardingScopes` | No | `Array<"text-inference" \| "image-generation">` | 이 선택지를 어떤 onboarding 표면에 표시할지 지정합니다. 생략하면 기본값은 `["text-inference"]`입니다. | ## uiHints 참조 -`uiHints`는 config 필드 이름에서 작은 렌더링 힌트로의 매핑입니다. +`uiHints`는 구성 필드 이름에서 작은 렌더링 힌트로 매핑되는 맵입니다. ```json { "uiHints": { "apiKey": { "label": "API key", - "help": "Used for OpenRouter requests", + "help": "OpenRouter 요청에 사용됨", "placeholder": "sk-or-v1-...", "sensitive": true } @@ -199,21 +194,20 @@ OpenClaw는 provider 런타임이 로드되기 전에 이를 읽습니다. } ``` -각 필드 힌트에는 다음이 포함될 수 있습니다: +각 필드 힌트는 다음을 포함할 수 있습니다. -| Field | Type | What it means | -| ------------- | ---------- | --------------------------------------- | -| `label` | `string` | 사용자 대상 필드 라벨. | -| `help` | `string` | 짧은 도움말 텍스트. | -| `tags` | `string[]` | 선택적 UI 태그. | -| `advanced` | `boolean` | 필드를 고급 항목으로 표시합니다. | -| `sensitive` | `boolean` | 필드를 비밀값 또는 민감 항목으로 표시합니다. | -| `placeholder` | `string` | 폼 입력용 placeholder 텍스트. | +| Field | Type | 의미 | +| ------------- | ---------- | ------------------------------------- | +| `label` | `string` | 사용자용 필드 레이블입니다. | +| `help` | `string` | 짧은 도움말 텍스트입니다. | +| `tags` | `string[]` | 선택적 UI 태그입니다. | +| `advanced` | `boolean` | 이 필드를 고급 항목으로 표시합니다. | +| `sensitive` | `boolean` | 이 필드를 비밀 또는 민감 정보로 표시합니다. | +| `placeholder` | `string` | 양식 입력의 placeholder 텍스트입니다. | ## contracts 참조 -`contracts`는 OpenClaw가 plugin 런타임을 import하지 않고도 -읽을 수 있는 정적 capability 소유 메타데이터에만 사용하세요. +`contracts`는 OpenClaw가 plugin 런타임을 import하지 않고도 읽을 수 있는 정적 capability 소유 메타데이터에만 사용하세요. ```json { @@ -231,24 +225,23 @@ OpenClaw는 provider 런타임이 로드되기 전에 이를 읽습니다. } ``` -각 목록은 선택 사항입니다: +각 목록은 선택 사항입니다. -| Field | Type | What it means | -| -------------------------------- | ---------- | -------------------------------------------------------------- | -| `speechProviders` | `string[]` | 이 plugin이 소유하는 음성 provider id입니다. | -| `realtimeTranscriptionProviders` | `string[]` | 이 plugin이 소유하는 실시간 전사 provider id입니다. | -| `realtimeVoiceProviders` | `string[]` | 이 plugin이 소유하는 실시간 음성 provider id입니다. | -| `mediaUnderstandingProviders` | `string[]` | 이 plugin이 소유하는 media-understanding provider id입니다. | -| `imageGenerationProviders` | `string[]` | 이 plugin이 소유하는 image-generation provider id입니다. | -| `videoGenerationProviders` | `string[]` | 이 plugin이 소유하는 video-generation provider id입니다. | -| `webFetchProviders` | `string[]` | 이 plugin이 소유하는 web-fetch provider id입니다. | -| `webSearchProviders` | `string[]` | 이 plugin이 소유하는 웹 검색 provider id입니다. | -| `tools` | `string[]` | 번들 contract 검사용으로 이 plugin이 소유하는 agent 도구 이름입니다. | +| Field | Type | 의미 | +| -------------------------------- | ---------- | ----------------------------------------------------------- | +| `speechProviders` | `string[]` | 이 plugin이 소유한 speech provider id입니다. | +| `realtimeTranscriptionProviders` | `string[]` | 이 plugin이 소유한 realtime-transcription provider id입니다. | +| `realtimeVoiceProviders` | `string[]` | 이 plugin이 소유한 realtime-voice provider id입니다. | +| `mediaUnderstandingProviders` | `string[]` | 이 plugin이 소유한 media-understanding provider id입니다. | +| `imageGenerationProviders` | `string[]` | 이 plugin이 소유한 image-generation provider id입니다. | +| `videoGenerationProviders` | `string[]` | 이 plugin이 소유한 video-generation provider id입니다. | +| `webFetchProviders` | `string[]` | 이 plugin이 소유한 web-fetch provider id입니다. | +| `webSearchProviders` | `string[]` | 이 plugin이 소유한 web-search provider id입니다. | +| `tools` | `string[]` | 번들 계약 검사에 사용하는 이 plugin 소유의 agent tool 이름입니다. | ## channelConfigs 참조 -`channelConfigs`는 채널 plugin이 런타임 로드 전에 -저비용 config 메타데이터를 필요로 할 때 사용하세요. +channel plugin이 런타임 로드 전에 저비용 config 메타데이터를 필요로 하는 경우 `channelConfigs`를 사용하세요. ```json { @@ -268,28 +261,26 @@ OpenClaw는 provider 런타임이 로드되기 전에 이를 읽습니다. } }, "label": "Matrix", - "description": "Matrix homeserver connection", + "description": "Matrix homeserver 연결", "preferOver": ["matrix-legacy"] } } } ``` -각 채널 항목에는 다음이 포함될 수 있습니다: +각 channel 항목은 다음을 포함할 수 있습니다. -| Field | Type | What it means | -| ------------- | ------------------------ | ----------------------------------------------------------------------------------------- | -| `schema` | `object` | `channels.`용 JSON Schema입니다. 선언된 각 채널 config 항목에 필요합니다. | -| `uiHints` | `Record` | 해당 채널 config 섹션을 위한 선택적 UI 라벨/placeholder/민감도 힌트입니다. | -| `label` | `string` | 런타임 메타데이터가 준비되지 않았을 때 선택기 및 검사 표면에 병합되는 채널 라벨입니다. | -| `description` | `string` | 검사 및 catalog 표면을 위한 짧은 채널 설명입니다. | -| `preferOver` | `string[]` | 선택 표면에서 이 채널이 우선해야 하는 레거시 또는 낮은 우선순위 plugin id입니다. | +| Field | Type | 의미 | +| ------------- | ------------------------ | -------------------------------------------------------------------------------------- | +| `schema` | `object` | `channels.`용 JSON Schema입니다. 선언된 각 channel config 항목에 필수입니다. | +| `uiHints` | `Record` | 해당 channel config 섹션에 대한 선택적 UI 레이블/placeholder/민감도 힌트입니다. | +| `label` | `string` | 런타임 메타데이터가 준비되지 않았을 때 선택기 및 검사 표면에 병합되는 channel 레이블입니다. | +| `description` | `string` | 검사 및 catalog 표면용 짧은 channel 설명입니다. | +| `preferOver` | `string[]` | 선택 표면에서 이 channel이 우선해야 하는 레거시 또는 낮은 우선순위 plugin id입니다. | ## modelSupport 참조 -`modelSupport`는 OpenClaw가 `gpt-5.4` 또는 `claude-sonnet-4.6` 같은 -축약형 모델 id에서 plugin 런타임이 로드되기 전에 -provider plugin을 추론해야 할 때 사용하세요. +plugin 런타임이 로드되기 전에 OpenClaw가 `gpt-5.4` 또는 `claude-sonnet-4.6` 같은 shorthand model id로부터 provider plugin을 추론해야 한다면 `modelSupport`를 사용하세요. ```json { @@ -300,76 +291,60 @@ provider plugin을 추론해야 할 때 사용하세요. } ``` -OpenClaw는 다음 우선순위를 적용합니다: +OpenClaw는 다음 우선순위를 적용합니다. -- 명시적 `provider/model` 참조는 소유 `providers` 매니페스트 메타데이터를 사용합니다 +- 명시적인 `provider/model` ref는 소유 `providers` 매니페스트 메타데이터를 사용합니다 - `modelPatterns`가 `modelPrefixes`보다 우선합니다 -- 번들되지 않은 plugin과 번들 plugin이 각각 하나씩 모두 일치하면, 번들되지 않은 - plugin이 우선합니다 -- 남은 모호성은 사용자 또는 config가 provider를 지정할 때까지 무시됩니다 +- 비번들 plugin 하나와 번들 plugin 하나가 모두 일치하면 비번들 plugin이 우선합니다 +- 그 외의 모호성은 사용자 또는 config가 provider를 지정할 때까지 무시됩니다 필드: -| Field | Type | What it means | -| --------------- | ---------- | ------------------------------------------------------------------------------- | -| `modelPrefixes` | `string[]` | 축약형 모델 id에 대해 `startsWith`로 매칭되는 접두사입니다. | -| `modelPatterns` | `string[]` | 프로필 접미사 제거 후 축약형 모델 id에 대해 매칭되는 정규식 소스입니다. | +| Field | Type | 의미 | +| --------------- | ---------- | -------------------------------------------------------------------- | +| `modelPrefixes` | `string[]` | shorthand model id에 대해 `startsWith`로 일치시키는 접두사입니다. | +| `modelPatterns` | `string[]` | 프로필 접미사를 제거한 뒤 shorthand model id에 대해 일치시키는 정규식 소스입니다. | -레거시 최상위 capability 키는 더 이상 권장되지 않습니다. `openclaw doctor --fix`를 사용해 -`speechProviders`, `realtimeTranscriptionProviders`, -`realtimeVoiceProviders`, `mediaUnderstandingProviders`, -`imageGenerationProviders`, `videoGenerationProviders`, -`webFetchProviders`, `webSearchProviders`를 `contracts` 아래로 -이동하세요. 일반 매니페스트 로딩은 더 이상 이러한 최상위 필드를 -capability 소유권으로 취급하지 않습니다. +레거시 최상위 capability 키는 더 이상 권장되지 않습니다. `openclaw doctor --fix`를 사용해 `speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders`, `webSearchProviders`를 `contracts` 아래로 이동하세요. 일반 매니페스트 로딩은 더 이상 이러한 최상위 필드를 capability 소유권으로 취급하지 않습니다. ## 매니페스트와 package.json의 차이 -두 파일은 서로 다른 역할을 합니다: +두 파일은 서로 다른 역할을 합니다. -| File | Use it for | -| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -| `openclaw.plugin.json` | 검색, config 검증, 인증 선택 메타데이터, 그리고 plugin 코드 실행 전에 존재해야 하는 UI 힌트 | -| `package.json` | npm 메타데이터, 의존성 설치, 그리고 엔트리포인트, 설치 게이팅, 설정 또는 catalog 메타데이터에 사용되는 `openclaw` 블록 | +| File | 용도 | +| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| `openclaw.plugin.json` | plugin 코드가 실행되기 전에 반드시 존재해야 하는 검색, 구성 검증, auth-choice 메타데이터, UI 힌트 | +| `package.json` | npm 메타데이터, 의존성 설치, 그리고 entrypoint, 설치 게이팅, 설정, catalog 메타데이터에 사용되는 `openclaw` 블록 | -어떤 메타데이터를 어디에 넣어야 할지 확실하지 않다면 다음 규칙을 사용하세요: +어떤 메타데이터를 어디에 둘지 확신이 없다면 이 규칙을 사용하세요. - OpenClaw가 plugin 코드를 로드하기 전에 알아야 한다면 `openclaw.plugin.json`에 넣으세요 -- 패키징, 엔트리 파일, npm 설치 동작에 관한 것이라면 `package.json`에 넣으세요 +- 패키징, entry 파일, 또는 npm 설치 동작과 관련 있다면 `package.json`에 넣으세요 ### 검색에 영향을 주는 package.json 필드 -일부 사전 런타임 plugin 메타데이터는 의도적으로 `openclaw.plugin.json`이 아니라 -`package.json`의 `openclaw` 블록 아래에 위치합니다. +일부 사전 런타임 plugin 메타데이터는 의도적으로 `openclaw.plugin.json`이 아니라 `package.json`의 `openclaw` 블록에 있습니다. -중요한 예시: +중요한 예: -| Field | What it means | +| Field | 의미 | | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -| `openclaw.extensions` | 네이티브 plugin 엔트리포인트를 선언합니다. | -| `openclaw.setupEntry` | 온보딩 및 지연 채널 시작 중에 사용하는 가벼운 setup 전용 엔트리포인트입니다. | -| `openclaw.channel` | 라벨, 문서 경로, 별칭, 선택 복사본 같은 저비용 채널 catalog 메타데이터입니다. | -| `openclaw.channel.configuredState` | 전체 채널 런타임을 로드하지 않고도 "env만으로 된 설정이 이미 존재하는가?"에 답할 수 있는 가벼운 configured-state 검사기 메타데이터입니다. | -| `openclaw.channel.persistedAuthState` | 전체 채널 런타임을 로드하지 않고도 "이미 로그인된 항목이 있는가?"에 답할 수 있는 가벼운 persisted-auth 검사기 메타데이터입니다. | -| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 번들 및 외부 게시 plugin을 위한 설치/업데이트 힌트입니다. | -| `openclaw.install.defaultChoice` | 여러 설치 소스를 사용할 수 있을 때 선호되는 설치 경로입니다. | -| `openclaw.install.minHostVersion` | `>=2026.3.22` 같은 semver 하한을 사용하는, 지원되는 최소 OpenClaw 호스트 버전입니다. | -| `openclaw.install.allowInvalidConfigRecovery` | config가 유효하지 않을 때 제한된 번들 plugin 재설치 복구 경로를 허용합니다. | -| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 시작 중 전체 채널 plugin보다 먼저 setup 전용 채널 표면이 로드되도록 합니다. | +| `openclaw.extensions` | 네이티브 plugin entrypoint를 선언합니다. | +| `openclaw.setupEntry` | onboarding 및 지연된 channel 시작 중에 사용되는 경량 setup 전용 entrypoint입니다. | +| `openclaw.channel` | 레이블, 문서 경로, 별칭, 선택용 문구 같은 저비용 channel catalog 메타데이터입니다. | +| `openclaw.channel.configuredState` | 전체 channel 런타임을 로드하지 않고도 "env만으로 된 설정이 이미 존재하는가?"에 답할 수 있는 경량 configured-state 검사기 메타데이터입니다. | +| `openclaw.channel.persistedAuthState` | 전체 channel 런타임을 로드하지 않고도 "이미 로그인된 항목이 있는가?"에 답할 수 있는 경량 persisted-auth 검사기 메타데이터입니다. | +| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 번들 및 외부 게시 plugin용 설치/업데이트 힌트입니다. | +| `openclaw.install.defaultChoice` | 여러 설치 소스를 사용할 수 있을 때 선호되는 설치 경로입니다. | +| `openclaw.install.minHostVersion` | `>=2026.3.22` 같은 semver 하한을 사용하는 최소 지원 OpenClaw 호스트 버전입니다. | +| `openclaw.install.allowInvalidConfigRecovery` | 구성이 유효하지 않을 때 제한된 번들 plugin 재설치 복구 경로를 허용합니다. | +| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 시작 중 전체 channel plugin보다 setup 전용 channel 표면을 먼저 로드할 수 있게 합니다. | -`openclaw.install.minHostVersion`은 설치와 매니페스트 -레지스트리 로드 중에 적용됩니다. 잘못된 값은 거부되며, 더 새롭지만 유효한 값은 -오래된 호스트에서 plugin을 건너뜁니다. +`openclaw.install.minHostVersion`은 설치 중과 매니페스트 레지스트리 로딩 중에 적용됩니다. 유효하지 않은 값은 거부되며, 유효하지만 더 새로운 값은 오래된 호스트에서 plugin을 건너뜁니다. -`openclaw.install.allowInvalidConfigRecovery`는 의도적으로 좁은 범위로 제한됩니다. 이것이 -임의의 깨진 config를 설치 가능하게 만들지는 않습니다. 현재는 -번들 plugin 경로 누락 또는 동일 번들 plugin에 대한 오래된 `channels.` 항목 같은, -특정한 오래된 번들 plugin 업그레이드 실패에서 설치 흐름이 복구되도록만 허용합니다. -관련 없는 config 오류는 여전히 설치를 차단하고 운영자를 -`openclaw doctor --fix`로 안내합니다. +`openclaw.install.allowInvalidConfigRecovery`는 의도적으로 범위가 좁습니다. 임의의 깨진 구성을 설치 가능하게 만들지는 않습니다. 현재는 누락된 번들 plugin 경로 또는 동일 번들 plugin에 대한 오래된 `channels.` 항목 같은 특정한 낡은 번들 plugin 업그레이드 실패에서만 설치 흐름이 복구되도록 허용합니다. 관련 없는 구성 오류는 여전히 설치를 차단하고 운영자를 `openclaw doctor --fix`로 안내합니다. -`openclaw.channel.persistedAuthState`는 작은 검사기 -모듈을 위한 패키지 메타데이터입니다: +`openclaw.channel.persistedAuthState`는 작은 검사기 모듈을 위한 package 메타데이터입니다. ```json { @@ -385,13 +360,9 @@ capability 소유권으로 취급하지 않습니다. } ``` -설정, doctor 또는 configured-state 흐름이 전체 채널 plugin이 로드되기 전에 -저비용의 예/아니오 인증 프로브를 필요로 할 때 사용하세요. 대상 export는 -저장된 상태만 읽는 작은 함수여야 하며, 전체 채널 런타임 배럴을 통해 -연결하지 마세요. +설정, doctor 또는 configured-state 흐름이 전체 channel plugin이 로드되기 전에 저비용 예/아니오 auth 프로브를 필요로 할 때 사용하세요. 대상 export는 저장된 상태만 읽는 작은 함수여야 하며, 전체 channel 런타임 barrel을 통해 연결해서는 안 됩니다. -`openclaw.channel.configuredState`는 저비용 env 전용 -구성 확인을 위한 동일한 형태를 따릅니다: +`openclaw.channel.configuredState`는 저비용 env 전용 configured 검사를 위해 같은 형태를 따릅니다. ```json { @@ -407,62 +378,43 @@ capability 소유권으로 취급하지 않습니다. } ``` -채널이 env 또는 기타 작은 비런타임 입력만으로 configured-state에 답할 수 있을 때 사용하세요. -검사에 전체 config 해석 또는 실제 -채널 런타임이 필요하다면, 그 로직은 대신 plugin `config.hasConfiguredState` -hook에 두세요. +channel이 env 또는 기타 작은 비런타임 입력만으로 configured-state에 답할 수 있을 때 사용하세요. 검사가 전체 config 해석이나 실제 channel 런타임을 필요로 한다면, 대신 그 로직을 plugin `config.hasConfiguredState` hook에 두세요. ## JSON Schema 요구 사항 -- **모든 plugin은 JSON Schema를 반드시 포함해야 하며**, config를 전혀 받지 않는 경우에도 예외가 없습니다. -- 빈 schema도 허용됩니다(예: `{ "type": "object", "additionalProperties": false }`). -- schema는 런타임이 아니라 config 읽기/쓰기 시점에 검증됩니다. +- **모든 plugin은 JSON Schema를 반드시 포함해야 하며**, 구성을 전혀 받지 않더라도 예외는 없습니다. +- 빈 스키마도 허용됩니다(예: `{ "type": "object", "additionalProperties": false }`). +- 스키마는 런타임이 아니라 구성 읽기/쓰기 시점에 검증됩니다. ## 검증 동작 -- 알 수 없는 `channels.*` 키는 **오류**입니다. 단, 해당 채널 id가 - plugin 매니페스트에 선언된 경우는 예외입니다. -- `plugins.entries.`, `plugins.allow`, `plugins.deny`, `plugins.slots.*`는 - **검색 가능한** plugin id를 참조해야 합니다. 알 수 없는 id는 **오류**입니다. -- plugin이 설치되어 있지만 매니페스트 또는 schema가 깨졌거나 없으면, - 검증이 실패하고 Doctor가 plugin 오류를 보고합니다. -- plugin config가 존재하지만 plugin이 **비활성화**되어 있으면, 해당 config는 유지되고 - Doctor + 로그에 **경고**가 표시됩니다. +- 알 수 없는 `channels.*` 키는 **오류**입니다. 단, 해당 channel id가 plugin 매니페스트에 선언된 경우는 예외입니다. +- `plugins.entries.`, `plugins.allow`, `plugins.deny`, `plugins.slots.*`는 **검색 가능한** plugin id를 참조해야 합니다. 알 수 없는 id는 **오류**입니다. +- plugin이 설치되어 있지만 매니페스트나 스키마가 깨졌거나 누락된 경우 검증이 실패하고 Doctor가 plugin 오류를 보고합니다. +- plugin 구성이 존재하지만 plugin이 **비활성화**되어 있으면 구성은 유지되며 Doctor + 로그에 **경고**가 표시됩니다. -전체 `plugins.*` schema는 [Configuration reference](/ko/gateway/configuration)를 참고하세요. +전체 `plugins.*` 스키마는 [Configuration reference](/ko/gateway/configuration)를 참조하세요. ## 참고 -- 매니페스트는 로컬 파일 시스템 로드를 포함한 **네이티브 OpenClaw plugin에 필수**입니다. -- 런타임은 여전히 plugin 모듈을 별도로 로드합니다. 매니페스트는 - 검색 + 검증 전용입니다. -- 네이티브 매니페스트는 JSON5로 파싱되므로 주석, trailing comma, - 따옴표 없는 키를 사용할 수 있으며, 최종 값이 여전히 객체이기만 하면 됩니다. -- 매니페스트 로더는 문서화된 매니페스트 필드만 읽습니다. 여기에 - 커스텀 최상위 키를 추가하지 마세요. -- `providerAuthEnvVars`는 plugin 런타임을 부팅하지 않고도 env 이름을 확인해야 하는 - 인증 프로브, env-marker 검증, 기타 유사한 provider 인증 표면을 위한 - 저비용 메타데이터 경로입니다. -- `channelEnvVars`는 plugin 런타임을 부팅하지 않고도 env 이름을 확인해야 하는 - 셸 env 폴백, setup 프롬프트, 기타 유사한 채널 표면을 위한 - 저비용 메타데이터 경로입니다. -- `providerAuthChoices`는 provider 런타임이 로드되기 전에 인증 선택기, - `--auth-choice` 해석, 선호 provider 매핑, 단순 온보딩 - CLI 플래그 등록을 위한 저비용 메타데이터 경로입니다. provider 코드가 필요한 - 런타임 wizard 메타데이터는 - [Provider runtime hooks](/ko/plugins/architecture#provider-runtime-hooks)를 참고하세요. +- 매니페스트는 로컬 파일 시스템 로드를 포함해 **네이티브 OpenClaw plugin에 필수**입니다. +- 런타임은 여전히 plugin 모듈을 별도로 로드합니다. 매니페스트는 검색 + 검증 전용입니다. +- 네이티브 매니페스트는 JSON5로 파싱되므로 최종 값이 여전히 객체이기만 하면 주석, 후행 쉼표, 따옴표 없는 키를 허용합니다. +- 매니페스트 로더는 문서화된 매니페스트 필드만 읽습니다. 여기에 사용자 정의 최상위 키를 추가하지 마세요. +- `providerAuthEnvVars`는 env 이름을 확인하기 위해 plugin 런타임을 부팅해서는 안 되는 auth 프로브, env-marker 검증 및 유사한 provider-auth 표면을 위한 저비용 메타데이터 경로입니다. +- `providerAuthAliases`는 core에 관계를 하드코딩하지 않고도 provider 변형이 다른 provider의 auth env vars, auth 프로필, config 기반 auth, API 키 onboarding 선택지를 재사용할 수 있게 합니다. +- `channelEnvVars`는 env 이름을 확인하기 위해 plugin 런타임을 부팅해서는 안 되는 shell-env 폴백, setup 프롬프트 및 유사한 channel 표면을 위한 저비용 메타데이터 경로입니다. +- `providerAuthChoices`는 provider 런타임이 로드되기 전에 auth-choice 선택기, `--auth-choice` 해석, 선호 provider 매핑, 간단한 onboarding CLI 플래그 등록을 위한 저비용 메타데이터 경로입니다. provider 코드가 필요한 런타임 wizard 메타데이터는 [Provider runtime hooks](/ko/plugins/architecture#provider-runtime-hooks)를 참조하세요. - 배타적 plugin kind는 `plugins.slots.*`를 통해 선택됩니다. - `kind: "memory"`는 `plugins.slots.memory`로 선택됩니다. - `kind: "context-engine"`는 `plugins.slots.contextEngine`으로 선택됩니다 (기본값: 내장 `legacy`). -- `channels`, `providers`, `cliBackends`, `skills`는 - plugin에 필요하지 않다면 생략할 수 있습니다. -- plugin이 네이티브 모듈에 의존한다면 빌드 단계와 - 패키지 관리자 허용 목록 요구 사항을 문서화하세요(예: pnpm `allow-build-scripts` - - `pnpm rebuild `). +- `channels`, `providers`, `cliBackends`, `skills`는 plugin에 필요하지 않다면 생략할 수 있습니다. +- plugin이 네이티브 모듈에 의존하는 경우, 빌드 단계와 package-manager 허용 목록 요구 사항(예: pnpm `allow-build-scripts` + - `pnpm rebuild `)을 문서화하세요. ## 관련 문서 -- [Building Plugins](/ko/plugins/building-plugins) — plugin 시작하기 +- [Building Plugins](/ko/plugins/building-plugins) — plugin 시작 가이드 - [Plugin Architecture](/ko/plugins/architecture) — 내부 아키텍처 - [SDK Overview](/ko/plugins/sdk-overview) — Plugin SDK 참조 diff --git a/docs/ko/plugins/sdk-migration.md b/docs/ko/plugins/sdk-migration.md index aeea78de1..af48e80e4 100644 --- a/docs/ko/plugins/sdk-migration.md +++ b/docs/ko/plugins/sdk-migration.md @@ -5,64 +5,61 @@ read_when: - plugin을 최신 plugin 아키텍처로 업데이트하는 경우 - 외부 OpenClaw plugin을 유지 관리하는 경우 sidebarTitle: Migrate to SDK -summary: 레거시 하위 호환성 레이어에서 최신 plugin SDK로 마이그레이션 +summary: 기존 하위 호환성 계층에서 최신 plugin SDK로 마이그레이션 title: Plugin SDK 마이그레이션 x-i18n: - generated_at: "2026-04-08T02:17:32Z" + generated_at: "2026-04-09T01:30:38Z" model: gpt-5.4 provider: openai - source_hash: 155a8b14bc345319c8516ebdb8a0ccdea2c5f7fa07dad343442996daee21ecad + source_hash: 60cbb6c8be30d17770887d490c14e3a4538563339a5206fb419e51e0558bbc07 source_path: plugins/sdk-migration.md workflow: 15 --- # Plugin SDK 마이그레이션 -OpenClaw는 폭넓은 하위 호환성 레이어에서 집중적이고 문서화된 import를 갖춘 최신 plugin -아키텍처로 이동했습니다. plugin이 새 아키텍처 이전에 만들어졌다면, -이 가이드가 마이그레이션에 도움이 됩니다. +OpenClaw는 광범위한 하위 호환성 계층에서 집중적이고 문서화된 import를 사용하는 최신 plugin +아키텍처로 전환했습니다. plugin이 새 아키텍처 이전에 만들어졌다면, +이 가이드는 마이그레이션에 도움이 됩니다. -## 변경 사항 +## 변경되는 내용 -이전 plugin 시스템은 plugin이 단일 엔트리 포인트에서 필요한 것을 무엇이든 import할 수 있도록 해주는 -두 개의 매우 개방된 표면을 제공했습니다. +기존 plugin 시스템은 plugin이 단일 진입점에서 필요한 거의 모든 것을 import할 수 있도록 하는 +두 개의 광범위한 표면을 제공했습니다. - **`openclaw/plugin-sdk/compat`** — 수십 개의 - helper를 다시 export하는 단일 import입니다. 새 plugin 아키텍처가 구축되는 동안 - 오래된 hook 기반 plugin이 계속 작동하도록 도입되었습니다. -- **`openclaw/extension-api`** — 내장 에이전트 실행기 같은 - 호스트 측 helper에 plugin이 직접 접근할 수 있게 해주는 브리지입니다. + helper를 다시 내보내는 단일 import입니다. 새 plugin 아키텍처가 구축되는 동안 + 기존 hook 기반 plugins가 계속 동작하도록 도입되었습니다. +- **`openclaw/extension-api`** — plugin이 내장 agent runner 같은 + 호스트 측 helper에 직접 접근할 수 있게 해주는 브리지입니다. -이제 두 표면 모두 **deprecated** 상태입니다. 런타임에서는 여전히 작동하지만, 새 -plugin은 이를 사용하면 안 되며, 기존 plugin도 다음 메이저 릴리스에서 제거되기 전에 +이제 두 표면 모두 **사용 중단됨** 상태입니다. 런타임에서는 여전히 동작하지만, 새 +plugins는 이를 사용해서는 안 되며, 기존 plugins도 다음 메이저 릴리스에서 제거되기 전에 마이그레이션해야 합니다. - 하위 호환성 레이어는 향후 메이저 릴리스에서 제거될 예정입니다. - 이 표면에서 계속 import하는 plugin은 그 시점에 작동이 중단됩니다. + 하위 호환성 계층은 향후 메이저 릴리스에서 제거될 예정입니다. + 여전히 이 표면에서 import하는 plugins는 그 시점에 동작하지 않게 됩니다. -## 왜 변경되었나 +## 왜 변경되었나요 -이전 접근 방식은 문제를 일으켰습니다. +기존 접근 방식은 다음과 같은 문제를 일으켰습니다. -- **느린 시작** — helper 하나를 import하면 관련 없는 수십 개 모듈이 로드됨 -- **순환 의존성** — 광범위한 재-export로 import 순환이 쉽게 생김 -- **불명확한 API 표면** — 어떤 export가 안정적인지, 어떤 것이 내부용인지 구분할 방법이 없음 +- **느린 시작 속도** — helper 하나를 import해도 관련 없는 수십 개 모듈이 로드됨 +- **순환 의존성** — 광범위한 재내보내기로 인해 import cycle이 쉽게 생김 +- **불명확한 API 표면** — 어떤 export가 안정적이고 어떤 것이 내부용인지 구분할 수 없음 최신 plugin SDK는 이를 해결합니다. 각 import 경로(`openclaw/plugin-sdk/\`)는 -명확한 목적과 문서화된 계약을 가진 작고 독립적인 모듈입니다. +작고 독립적인 모듈이며, 명확한 목적과 문서화된 계약을 가집니다. -번들 채널용 레거시 프로바이더 편의 seam도 사라졌습니다. 예를 들어 -`openclaw/plugin-sdk/slack`, `openclaw/plugin-sdk/discord`, -`openclaw/plugin-sdk/signal`, `openclaw/plugin-sdk/whatsapp`, -채널 브랜드 helper seam, 그리고 -`openclaw/plugin-sdk/telegram-core` 같은 import는 -안정적인 plugin 계약이 아니라 private mono-repo 지름길이었습니다. 대신 더 좁고 일반적인 SDK subpath를 사용하세요. 번들 -plugin workspace 내부에서는 프로바이더 소유 helper를 해당 plugin 자체의 -`api.ts` 또는 `runtime-api.ts`에 유지하세요. +번들 채널용 기존 provider 편의 seam도 제거되었습니다. `openclaw/plugin-sdk/slack`, `openclaw/plugin-sdk/discord`, `openclaw/plugin-sdk/signal`, `openclaw/plugin-sdk/whatsapp`, +채널 브랜딩 helper seam, 그리고 +`openclaw/plugin-sdk/telegram-core` 같은 import는 안정적인 plugin 계약이 아닌 +비공개 mono-repo 지름길이었습니다. 대신 더 좁고 일반적인 SDK 하위 경로를 사용하세요. 번들 plugin workspace 내부에서는 provider 소유 helper를 해당 plugin의 +자체 `api.ts` 또는 `runtime-api.ts`에 두세요. -현재 번들 프로바이더 예시: +현재 번들 provider 예시: - Anthropic은 Claude 전용 stream helper를 자체 `api.ts` / `contract-api.ts` seam에 유지합니다 @@ -75,36 +72,36 @@ plugin workspace 내부에서는 프로바이더 소유 helper를 해당 plugin - 승인 가능한 채널 plugin은 이제 - `approvalCapability.nativeRuntime`과 공유 runtime-context registry를 통해 + 승인 가능한 채널 plugins는 이제 + `approvalCapability.nativeRuntime`와 공유 runtime-context registry를 통해 네이티브 승인 동작을 노출합니다. 주요 변경 사항: - `approvalCapability.handler.loadRuntime(...)`를 - `approvalCapability.nativeRuntime`으로 교체 - - 승인 전용 auth/delivery를 레거시 `plugin.auth` / - `plugin.approvals` wiring에서 떼어내 `approvalCapability`로 이동 - - `ChannelPlugin.approvals`는 공개 채널-plugin - 계약에서 제거되었습니다. delivery/native/render 필드는 `approvalCapability`로 옮기세요 - - `plugin.auth`는 채널 login/logout 흐름에만 남아 있습니다. 그 안의 승인 auth - hook은 더 이상 core에서 읽지 않습니다 - - 클라이언트, 토큰, Bolt - app 같은 채널 소유 runtime 객체는 `openclaw/plugin-sdk/channel-runtime-context`를 통해 등록 - - 네이티브 승인 핸들러에서 plugin 소유 reroute notice를 보내지 마세요. - 이제 core가 실제 delivery 결과로부터 routed-elsewhere notice를 소유합니다 - - `channelRuntime`을 `createChannelManager(...)`에 전달할 때는 - 실제 `createPluginRuntime().channel` 표면을 제공하세요. 부분 stub는 거부됩니다. + `approvalCapability.nativeRuntime`로 교체 + - 승인 관련 auth/delivery를 기존 `plugin.auth` / + `plugin.approvals` 연결에서 `approvalCapability`로 이동 + - `ChannelPlugin.approvals`는 공개 채널 plugin + 계약에서 제거되었으므로, delivery/native/render 필드를 `approvalCapability`로 이동 + - `plugin.auth`는 채널 login/logout 흐름에만 남아 있으며, 그 안의 승인 auth + hook은 더 이상 core에서 읽지 않음 + - 클라이언트, 토큰 또는 Bolt + 앱 같은 채널 소유 runtime 객체는 `openclaw/plugin-sdk/channel-runtime-context`를 통해 등록 + - 네이티브 승인 핸들러에서 plugin 소유의 재라우팅 알림을 보내지 마세요. + core가 이제 실제 delivery 결과에서 발생한 다른 경로 알림을 소유합니다 + - `channelRuntime`을 `createChannelManager(...)`에 전달할 때는, + 실제 `createPluginRuntime().channel` 표면을 제공하세요. 부분 stub은 거부됩니다. 현재 승인 capability 레이아웃은 `/plugins/sdk-channel-plugins`를 참조하세요. - + plugin이 `openclaw/plugin-sdk/windows-spawn`을 사용하는 경우, - 해결되지 않은 Windows `.cmd`/`.bat` wrapper는 이제 - `allowShellFallback: true`를 명시적으로 전달하지 않으면 fail closed됩니다. + 해결되지 않는 Windows `.cmd`/`.bat` wrapper는 이제 명시적으로 + `allowShellFallback: true`를 전달하지 않으면 닫힌 상태로 실패합니다. ```typescript // 이전 @@ -113,19 +110,19 @@ plugin workspace 내부에서는 프로바이더 소유 helper를 해당 plugin // 이후 const program = applyWindowsSpawnProgramPolicy({ candidate, - // shell 매개 fallback을 의도적으로 수용하는 신뢰된 호환성 호출자에만 - // 이것을 설정하세요. + // 신뢰된 호환성 호출자만 이 값을 설정하세요. 이러한 호출자는 의도적으로 + // 셸을 통한 대체를 허용합니다. allowShellFallback: true, }); ``` - 호출자가 의도적으로 shell fallback에 의존하지 않는다면 - `allowShellFallback`을 설정하지 말고 대신 발생한 오류를 처리하세요. + 호출자가 의도적으로 셸 대체에 의존하지 않는다면, `allowShellFallback`을 설정하지 말고 + 대신 발생한 오류를 처리하세요. - - plugin에서 deprecated된 두 표면 중 하나를 import하는지 검색하세요. + + plugin에서 사용 중단된 두 표면 중 하나에서의 import를 검색하세요. ```bash grep -r "plugin-sdk/compat" my-plugin/ @@ -135,37 +132,37 @@ plugin workspace 내부에서는 프로바이더 소유 helper를 해당 plugin - 이전 표면의 각 export는 특정 최신 import 경로에 대응됩니다. + 기존 표면의 각 export는 특정 최신 import 경로에 매핑됩니다. ```typescript - // 이전(deprecated 하위 호환성 레이어) + // 이전 (사용 중단된 하위 호환성 계층) import { createChannelReplyPipeline, createPluginRuntimeStore, resolveControlCommandGate, } from "openclaw/plugin-sdk/compat"; - // 이후(최신 집중형 import) + // 이후 (최신 집중형 import) import { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline"; import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store"; import { resolveControlCommandGate } from "openclaw/plugin-sdk/command-auth"; ``` - 호스트 측 helper의 경우 직접 import하는 대신 + 호스트 측 helper의 경우 직접 import하지 말고, 주입된 plugin runtime을 사용하세요. ```typescript - // 이전(deprecated extension-api bridge) + // 이전 (사용 중단된 extension-api 브리지) import { runEmbeddedPiAgent } from "openclaw/extension-api"; const result = await runEmbeddedPiAgent({ sessionId, prompt }); - // 이후(주입된 runtime) + // 이후 (주입된 runtime) const result = await api.runtime.agent.runEmbeddedPiAgent({ sessionId, prompt }); ``` - 동일한 패턴이 다른 레거시 브리지 helper에도 적용됩니다. + 동일한 패턴이 다른 기존 브리지 helper에도 적용됩니다. - | 이전 import | 최신 대응 | + | 기존 import | 최신 대응 항목 | | --- | --- | | `resolveAgentDir` | `api.runtime.agent.resolveAgentDir` | | `resolveAgentWorkspaceDir` | `api.runtime.agent.resolveAgentWorkspaceDir` | @@ -173,7 +170,7 @@ plugin workspace 내부에서는 프로바이더 소유 helper를 해당 plugin | `resolveThinkingDefault` | `api.runtime.agent.resolveThinkingDefault` | | `resolveAgentTimeoutMs` | `api.runtime.agent.resolveAgentTimeoutMs` | | `ensureAgentWorkspace` | `api.runtime.agent.ensureAgentWorkspace` | - | session store helpers | `api.runtime.agent.session.*` | + | session 저장소 helper | `api.runtime.agent.session.*` | @@ -188,176 +185,178 @@ plugin workspace 내부에서는 프로바이더 소유 helper를 해당 plugin ## import 경로 참조 - | Import path | 용도 | 주요 export | + | import 경로 | 목적 | 주요 export | | --- | --- | --- | - | `plugin-sdk/plugin-entry` | 정식 plugin 엔트리 helper | `definePluginEntry` | - | `plugin-sdk/core` | 채널 엔트리 정의/builder용 레거시 umbrella 재-export | `defineChannelPluginEntry`, `createChatChannelPlugin` | + | `plugin-sdk/plugin-entry` | 정식 plugin 진입 helper | `definePluginEntry` | + | `plugin-sdk/core` | 채널 진입 정의/빌더를 위한 기존 umbrella 재내보내기 | `defineChannelPluginEntry`, `createChatChannelPlugin` | | `plugin-sdk/config-schema` | 루트 config 스키마 export | `OpenClawSchema` | - | `plugin-sdk/provider-entry` | 단일 프로바이더 엔트리 helper | `defineSingleProviderPluginEntry` | - | `plugin-sdk/channel-core` | 집중된 채널 엔트리 정의 및 builder | `defineChannelPluginEntry`, `defineSetupPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase` | - | `plugin-sdk/setup` | 공유 setup wizard helper | allowlist prompt, setup status builder | + | `plugin-sdk/provider-entry` | 단일 provider 진입 helper | `defineSingleProviderPluginEntry` | + | `plugin-sdk/channel-core` | 집중된 채널 진입 정의 및 빌더 | `defineChannelPluginEntry`, `defineSetupPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase` | + | `plugin-sdk/setup` | 공유 setup wizard helper | 허용 목록 프롬프트, setup 상태 빌더 | | `plugin-sdk/setup-runtime` | setup 시점 runtime helper | import-safe setup patch adapter, lookup-note helper, `promptResolvedAllowFrom`, `splitSetupEntries`, 위임 setup proxy | | `plugin-sdk/setup-adapter-runtime` | setup adapter helper | `createEnvPatchedAccountSetupAdapter` | - | `plugin-sdk/setup-tools` | setup tooling helper | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | + | `plugin-sdk/setup-tools` | setup 도구 helper | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | | `plugin-sdk/account-core` | 다중 계정 helper | 계정 목록/config/action-gate helper | | `plugin-sdk/account-id` | account-id helper | `DEFAULT_ACCOUNT_ID`, account-id 정규화 | - | `plugin-sdk/account-resolution` | 계정 조회 helper | 계정 조회 + 기본 fallback helper | - | `plugin-sdk/account-helpers` | 좁은 범위의 계정 helper | 계정 목록/계정 액션 helper | + | `plugin-sdk/account-resolution` | 계정 조회 helper | 계정 조회 + 기본값 대체 helper | + | `plugin-sdk/account-helpers` | 좁은 계정 helper | 계정 목록/계정 작업 helper | | `plugin-sdk/channel-setup` | setup wizard adapter | `createOptionalChannelSetupSurface`, `createOptionalChannelSetupAdapter`, `createOptionalChannelSetupWizard`, 그리고 `DEFAULT_ACCOUNT_ID`, `createTopLevelChannelDmPolicy`, `setSetupChannelEnabled`, `splitSetupEntries` | - | `plugin-sdk/channel-pairing` | DM pairing 기본 구성 요소 | `createChannelPairingController` | - | `plugin-sdk/channel-reply-pipeline` | 응답 접두사 + 타이핑 wiring | `createChannelReplyPipeline` | + | `plugin-sdk/channel-pairing` | DM 페어링 기본 구성 요소 | `createChannelPairingController` | + | `plugin-sdk/channel-reply-pipeline` | 답장 접두사 + 타이핑 연결 | `createChannelReplyPipeline` | | `plugin-sdk/channel-config-helpers` | config adapter 팩토리 | `createHybridChannelConfigAdapter` | - | `plugin-sdk/channel-config-schema` | config 스키마 builder | 채널 config 스키마 타입 | - | `plugin-sdk/telegram-command-config` | Telegram 명령 config helper | 명령 이름 정규화, 설명 자르기, 중복/충돌 검증 | + | `plugin-sdk/channel-config-schema` | config 스키마 빌더 | 채널 config 스키마 타입 | + | `plugin-sdk/telegram-command-config` | Telegram 명령 config helper | 명령 이름 정규화, 설명 잘라내기, 중복/충돌 검증 | | `plugin-sdk/channel-policy` | 그룹/DM 정책 해석 | `resolveChannelGroupRequireMention` | | `plugin-sdk/channel-lifecycle` | 계정 상태 추적 | `createAccountStatusSink` | - | `plugin-sdk/inbound-envelope` | 인바운드 envelope helper | 공유 route + envelope builder helper | - | `plugin-sdk/inbound-reply-dispatch` | 인바운드 응답 helper | 공유 record-and-dispatch helper | - | `plugin-sdk/messaging-targets` | 메시징 대상 파싱 | 대상 파싱/매칭 helper | + | `plugin-sdk/inbound-envelope` | 인바운드 envelope helper | 공유 route + envelope 빌더 helper | + | `plugin-sdk/inbound-reply-dispatch` | 인바운드 답장 helper | 공유 record-and-dispatch helper | + | `plugin-sdk/messaging-targets` | 메시징 대상 구문 분석 | 대상 구문 분석/매칭 helper | | `plugin-sdk/outbound-media` | 아웃바운드 미디어 helper | 공유 아웃바운드 미디어 로딩 | - | `plugin-sdk/outbound-runtime` | 아웃바운드 runtime helper | 아웃바운드 신원/send delegate helper | - | `plugin-sdk/thread-bindings-runtime` | thread-binding helper | thread-binding lifecycle 및 adapter helper | - | `plugin-sdk/agent-media-payload` | 레거시 미디어 payload helper | 레거시 필드 레이아웃용 에이전트 미디어 payload builder | - | `plugin-sdk/channel-runtime` | deprecated 호환성 shim | 레거시 채널 runtime 유틸리티 전용 | - | `plugin-sdk/channel-send-result` | send 결과 타입 | 응답 결과 타입 | + | `plugin-sdk/outbound-runtime` | 아웃바운드 runtime helper | 아웃바운드 identity/send delegate helper | + | `plugin-sdk/thread-bindings-runtime` | 스레드 바인딩 helper | 스레드 바인딩 수명 주기 및 adapter helper | + | `plugin-sdk/agent-media-payload` | 기존 미디어 payload helper | 기존 필드 레이아웃용 agent 미디어 payload 빌더 | + | `plugin-sdk/channel-runtime` | 사용 중단된 호환성 shim | 기존 채널 runtime 유틸리티 전용 | + | `plugin-sdk/channel-send-result` | 전송 결과 타입 | 답장 결과 타입 | | `plugin-sdk/runtime-store` | 영구 plugin 저장소 | `createPluginRuntimeStore` | | `plugin-sdk/runtime` | 광범위한 runtime helper | runtime/logging/backup/plugin-install helper | - | `plugin-sdk/runtime-env` | 좁은 범위의 runtime env helper | logger/runtime env, timeout, retry, backoff helper | - | `plugin-sdk/plugin-runtime` | 공유 plugin runtime helper | plugin 명령/hook/http/interactive helper | + | `plugin-sdk/runtime-env` | 좁은 runtime env helper | logger/runtime env, timeout, retry, backoff helper | + | `plugin-sdk/plugin-runtime` | 공유 plugin runtime helper | plugin commands/hooks/http/interactive helper | | `plugin-sdk/hook-runtime` | hook 파이프라인 helper | 공유 webhook/internal hook 파이프라인 helper | - | `plugin-sdk/lazy-runtime` | lazy runtime helper | `createLazyRuntimeModule`, `createLazyRuntimeMethod`, `createLazyRuntimeMethodBinder`, `createLazyRuntimeNamedExport`, `createLazyRuntimeSurface` | - | `plugin-sdk/process-runtime` | process helper | 공유 exec helper | - | `plugin-sdk/cli-runtime` | CLI runtime helper | 명령 포맷팅, waits, 버전 helper | - | `plugin-sdk/gateway-runtime` | gateway helper | gateway client 및 channel-status patch helper | - | `plugin-sdk/config-runtime` | config helper | config load/write helper | - | `plugin-sdk/telegram-command-config` | Telegram 명령 helper | 번들 Telegram 계약 표면을 사용할 수 없을 때의 fallback-stable Telegram 명령 검증 helper | - | `plugin-sdk/approval-runtime` | 승인 prompt helper | exec/plugin 승인 payload, 승인 capability/profile helper, 네이티브 승인 라우팅/runtime helper | - | `plugin-sdk/approval-auth-runtime` | 승인 auth helper | approver 해석, same-chat action auth | - | `plugin-sdk/approval-client-runtime` | 승인 클라이언트 helper | 네이티브 exec 승인 profile/filter helper | + | `plugin-sdk/lazy-runtime` | 지연 runtime helper | `createLazyRuntimeModule`, `createLazyRuntimeMethod`, `createLazyRuntimeMethodBinder`, `createLazyRuntimeNamedExport`, `createLazyRuntimeSurface` | + | `plugin-sdk/process-runtime` | 프로세스 helper | 공유 exec helper | + | `plugin-sdk/cli-runtime` | CLI runtime helper | 명령 포맷팅, 대기, 버전 helper | + | `plugin-sdk/gateway-runtime` | Gateway helper | Gateway client 및 channel-status patch helper | + | `plugin-sdk/config-runtime` | Config helper | config 로드/기록 helper | + | `plugin-sdk/telegram-command-config` | Telegram 명령 helper | 번들 Telegram 계약 표면을 사용할 수 없을 때를 위한 안정적인 대체 Telegram 명령 검증 helper | + | `plugin-sdk/approval-runtime` | 승인 프롬프트 helper | exec/plugin 승인 payload, 승인 capability/profile helper, 네이티브 승인 라우팅/runtime helper | + | `plugin-sdk/approval-auth-runtime` | 승인 auth helper | approver 해석, 동일 채팅 action auth | + | `plugin-sdk/approval-client-runtime` | 승인 client helper | 네이티브 exec 승인 profile/filter helper | | `plugin-sdk/approval-delivery-runtime` | 승인 delivery helper | 네이티브 승인 capability/delivery adapter | | `plugin-sdk/approval-gateway-runtime` | 승인 gateway helper | 공유 승인 gateway-resolution helper | - | `plugin-sdk/approval-handler-adapter-runtime` | 승인 adapter helper | hot 채널 엔트리포인트용 경량 네이티브 승인 adapter 로딩 helper | - | `plugin-sdk/approval-handler-runtime` | 승인 핸들러 helper | 더 넓은 승인 핸들러 runtime helper. 더 좁은 adapter/gateway seam으로 충분하다면 그것을 우선 사용 | + | `plugin-sdk/approval-handler-adapter-runtime` | 승인 adapter helper | 핫 채널 진입점용 경량 네이티브 승인 adapter 로딩 helper | + | `plugin-sdk/approval-handler-runtime` | 승인 핸들러 helper | 더 광범위한 승인 핸들러 runtime helper. 더 좁은 adapter/gateway seam으로 충분하다면 그것을 우선 사용하세요 | | `plugin-sdk/approval-native-runtime` | 승인 대상 helper | 네이티브 승인 대상/account binding helper | - | `plugin-sdk/approval-reply-runtime` | 승인 응답 helper | exec/plugin 승인 응답 payload helper | + | `plugin-sdk/approval-reply-runtime` | 승인 답장 helper | exec/plugin 승인 답장 payload helper | | `plugin-sdk/channel-runtime-context` | 채널 runtime-context helper | 일반 채널 runtime-context register/get/watch helper | | `plugin-sdk/security-runtime` | 보안 helper | 공유 trust, DM gating, external-content, secret-collection helper | - | `plugin-sdk/ssrf-policy` | SSRF 정책 helper | 호스트 allowlist 및 private-network 정책 helper | + | `plugin-sdk/ssrf-policy` | SSRF 정책 helper | 호스트 허용 목록 및 private-network 정책 helper | | `plugin-sdk/ssrf-runtime` | SSRF runtime helper | pinned-dispatcher, guarded fetch, SSRF 정책 helper | | `plugin-sdk/collection-runtime` | 경계가 있는 캐시 helper | `pruneMapToMaxSize` | - | `plugin-sdk/diagnostic-runtime` | 진단 gating helper | `isDiagnosticFlagEnabled`, `isDiagnosticsEnabled` | - | `plugin-sdk/error-runtime` | 오류 포맷 helper | `formatUncaughtError`, `isApprovalNotFoundError`, 오류 그래프 helper | + | `plugin-sdk/diagnostic-runtime` | 진단 게이팅 helper | `isDiagnosticFlagEnabled`, `isDiagnosticsEnabled` | + | `plugin-sdk/error-runtime` | 오류 포맷팅 helper | `formatUncaughtError`, `isApprovalNotFoundError`, 오류 그래프 helper | | `plugin-sdk/fetch-runtime` | 래핑된 fetch/proxy helper | `resolveFetch`, proxy helper | | `plugin-sdk/host-runtime` | 호스트 정규화 helper | `normalizeHostname`, `normalizeScpRemoteHost` | - | `plugin-sdk/retry-runtime` | 재시도 helper | `RetryConfig`, `retryAsync`, 정책 runner | - | `plugin-sdk/allow-from` | allowlist 포맷팅 | `formatAllowFromLowercase` | - | `plugin-sdk/allowlist-resolution` | allowlist 입력 매핑 | `mapAllowlistResolutionInputs` | - | `plugin-sdk/command-auth` | 명령 gating 및 명령 표면 helper | `resolveControlCommandGate`, sender-authorization helper, command registry helper | - | `plugin-sdk/secret-input` | secret 입력 파싱 | secret 입력 helper | + | `plugin-sdk/retry-runtime` | 재시도 helper | `RetryConfig`, `retryAsync`, 정책 실행기 | + | `plugin-sdk/allow-from` | 허용 목록 포맷팅 | `formatAllowFromLowercase` | + | `plugin-sdk/allowlist-resolution` | 허용 목록 입력 매핑 | `mapAllowlistResolutionInputs` | + | `plugin-sdk/command-auth` | 명령 게이팅 및 명령 표면 helper | `resolveControlCommandGate`, sender authorization helper, 명령 registry helper | + | `plugin-sdk/command-status` | 명령 상태/help 렌더러 | `buildCommandsMessage`, `buildCommandsMessagePaginated`, `buildHelpMessage` | + | `plugin-sdk/secret-input` | 비밀 입력 구문 분석 | 비밀 입력 helper | | `plugin-sdk/webhook-ingress` | webhook 요청 helper | webhook 대상 유틸리티 | - | `plugin-sdk/webhook-request-guards` | webhook body guard helper | 요청 본문 읽기/제한 helper | - | `plugin-sdk/reply-runtime` | 공유 응답 runtime | 인바운드 dispatch, heartbeat, 응답 planner, chunking | - | `plugin-sdk/reply-dispatch-runtime` | 좁은 범위의 응답 dispatch helper | finalize + provider dispatch helper | - | `plugin-sdk/reply-history` | 응답 기록 helper | `buildHistoryContext`, `buildPendingHistoryContextFromMap`, `recordPendingHistoryEntry`, `clearHistoryEntriesIfEnabled` | - | `plugin-sdk/reply-reference` | 응답 참조 계획 | `createReplyReferencePlanner` | - | `plugin-sdk/reply-chunking` | 응답 chunk helper | 텍스트/markdown chunking helper | - | `plugin-sdk/session-store-runtime` | session 저장소 helper | 저장소 경로 + updated-at helper | + | `plugin-sdk/webhook-request-guards` | webhook 본문 가드 helper | 요청 본문 읽기/제한 helper | + | `plugin-sdk/reply-runtime` | 공유 답장 runtime | 인바운드 디스패치, heartbeat, 답장 planner, chunking | + | `plugin-sdk/reply-dispatch-runtime` | 좁은 답장 디스패치 helper | finalize + provider dispatch helper | + | `plugin-sdk/reply-history` | 답장 기록 helper | `buildHistoryContext`, `buildPendingHistoryContextFromMap`, `recordPendingHistoryEntry`, `clearHistoryEntriesIfEnabled` | + | `plugin-sdk/reply-reference` | 답장 참조 계획 | `createReplyReferencePlanner` | + | `plugin-sdk/reply-chunking` | 답장 청크 helper | 텍스트/markdown chunking helper | + | `plugin-sdk/session-store-runtime` | 세션 저장소 helper | 저장소 경로 + updated-at helper | | `plugin-sdk/state-paths` | 상태 경로 helper | 상태 및 OAuth 디렉터리 helper | - | `plugin-sdk/routing` | 라우팅/session-key helper | `resolveAgentRoute`, `buildAgentSessionKey`, `resolveDefaultAgentBoundAccountId`, session-key 정규화 helper | - | `plugin-sdk/status-helpers` | 채널 상태 helper | 채널/계정 상태 요약 builder, runtime-state 기본값, 이슈 메타데이터 helper | + | `plugin-sdk/routing` | 라우팅/세션 키 helper | `resolveAgentRoute`, `buildAgentSessionKey`, `resolveDefaultAgentBoundAccountId`, 세션 키 정규화 helper | + | `plugin-sdk/status-helpers` | 채널 상태 helper | 채널/계정 상태 요약 빌더, runtime-state 기본값, issue 메타데이터 helper | | `plugin-sdk/target-resolver-runtime` | 대상 resolver helper | 공유 대상 resolver helper | | `plugin-sdk/string-normalization-runtime` | 문자열 정규화 helper | slug/문자열 정규화 helper | | `plugin-sdk/request-url` | 요청 URL helper | request 유사 입력에서 문자열 URL 추출 | - | `plugin-sdk/run-command` | 시간 제한 명령 helper | stdout/stderr가 정규화된 시간 제한 명령 실행기 | - | `plugin-sdk/param-readers` | param reader | 공통 도구/CLI param reader | - | `plugin-sdk/tool-send` | 도구 send 추출 | 도구 인수에서 정식 send 대상 필드 추출 | - | `plugin-sdk/temp-path` | 임시 경로 helper | 공유 temp-download 경로 helper | - | `plugin-sdk/logging-core` | logging helper | 서브시스템 logger 및 redaction helper | + | `plugin-sdk/run-command` | 시간 제한 명령 helper | 정규화된 stdout/stderr를 포함한 시간 제한 명령 실행기 | + | `plugin-sdk/param-readers` | 파라미터 리더 | 공통 tool/CLI 파라미터 리더 | + | `plugin-sdk/tool-payload` | tool payload 추출 | tool 결과 객체에서 정규화된 payload 추출 | + | `plugin-sdk/tool-send` | tool send 추출 | tool 인수에서 정식 send 대상 필드 추출 | + | `plugin-sdk/temp-path` | 임시 경로 helper | 공유 임시 다운로드 경로 helper | + | `plugin-sdk/logging-core` | logging helper | 서브시스템 logger 및 민감 정보 제거 helper | | `plugin-sdk/markdown-table-runtime` | Markdown 표 helper | Markdown 표 모드 helper | - | `plugin-sdk/reply-payload` | 메시지 응답 타입 | 응답 payload 타입 | - | `plugin-sdk/provider-setup` | 엄선된 로컬/self-hosted 프로바이더 setup helper | self-hosted 프로바이더 discovery/config helper | - | `plugin-sdk/self-hosted-provider-setup` | 집중형 OpenAI 호환 self-hosted 프로바이더 setup helper | 동일한 self-hosted 프로바이더 discovery/config helper | - | `plugin-sdk/provider-auth-runtime` | 프로바이더 runtime auth helper | runtime API-key 해석 helper | - | `plugin-sdk/provider-auth-api-key` | 프로바이더 API-key setup helper | API-key onboarding/profile-write helper | - | `plugin-sdk/provider-auth-result` | 프로바이더 auth-result helper | 표준 OAuth auth-result builder | - | `plugin-sdk/provider-auth-login` | 프로바이더 interactive login helper | 공유 interactive login helper | - | `plugin-sdk/provider-env-vars` | 프로바이더 env-var helper | 프로바이더 auth env-var 조회 helper | - | `plugin-sdk/provider-model-shared` | 공유 프로바이더 모델/replay helper | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`, 공유 replay-policy builder, provider-endpoint helper, 모델-id 정규화 helper | - | `plugin-sdk/provider-catalog-shared` | 공유 프로바이더 catalog helper | `findCatalogTemplate`, `buildSingleProviderApiKeyCatalog`, `supportsNativeStreamingUsageCompat`, `applyProviderNativeStreamingUsageCompat` | - | `plugin-sdk/provider-onboard` | 프로바이더 onboarding patch | onboarding config helper | - | `plugin-sdk/provider-http` | 프로바이더 HTTP helper | 일반 프로바이더 HTTP/endpoint capability helper | - | `plugin-sdk/provider-web-fetch` | 프로바이더 web-fetch helper | web-fetch 프로바이더 등록/캐시 helper | - | `plugin-sdk/provider-web-search-contract` | 프로바이더 web-search 계약 helper | `enablePluginInConfig`, `resolveProviderWebSearchPluginConfig`, 범위 지정 자격 증명 setter/getter 같은 좁은 web-search config/credential 계약 helper | - | `plugin-sdk/provider-web-search` | 프로바이더 web-search helper | web-search 프로바이더 등록/캐시/runtime helper | - | `plugin-sdk/provider-tools` | 프로바이더 도구/스키마 compat helper | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`, Gemini 스키마 정리 + diagnostics, 그리고 `resolveXaiModelCompatPatch` / `applyXaiModelCompat` 같은 xAI compat helper | - | `plugin-sdk/provider-usage` | 프로바이더 사용량 helper | `fetchClaudeUsage`, `fetchGeminiUsage`, `fetchGithubCopilotUsage`, 그 외 프로바이더 사용량 helper | - | `plugin-sdk/provider-stream` | 프로바이더 stream wrapper helper | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`, stream wrapper 타입, 그리고 공유 Anthropic/Bedrock/Google/Kilocode/Moonshot/OpenAI/OpenRouter/Z.A.I/MiniMax/Copilot wrapper helper | - | `plugin-sdk/keyed-async-queue` | 순서 보장 async 큐 | `KeyedAsyncQueue` | - | `plugin-sdk/media-runtime` | 공유 미디어 helper | 미디어 fetch/transform/store helper와 미디어 payload builder | - | `plugin-sdk/media-generation-runtime` | 공유 미디어 생성 helper | 공유 failover helper, 후보 선택, 이미지/비디오/음악 생성용 모델 누락 메시지 | - | `plugin-sdk/media-understanding` | media-understanding helper | media understanding 프로바이더 타입 및 프로바이더 대상 image/audio helper export | - | `plugin-sdk/text-runtime` | 공유 텍스트 helper | assistant-visible-text 제거, markdown render/chunking/table helper, redaction helper, directive-tag helper, safe-text 유틸리티, 관련 text/logging helper | + | `plugin-sdk/reply-payload` | 메시지 답장 타입 | 답장 payload 타입 | + | `plugin-sdk/provider-setup` | 엄선된 로컬/self-hosted provider setup helper | self-hosted provider 검색/config helper | + | `plugin-sdk/self-hosted-provider-setup` | 집중된 OpenAI 호환 self-hosted provider setup helper | 동일한 self-hosted provider 검색/config helper | + | `plugin-sdk/provider-auth-runtime` | provider runtime auth helper | runtime API 키 해석 helper | + | `plugin-sdk/provider-auth-api-key` | provider API 키 setup helper | API 키 온보딩/profile-write helper | + | `plugin-sdk/provider-auth-result` | provider auth-result helper | 표준 OAuth auth-result 빌더 | + | `plugin-sdk/provider-auth-login` | provider 대화형 login helper | 공유 대화형 login helper | + | `plugin-sdk/provider-env-vars` | provider env-var helper | provider auth env-var 조회 helper | + | `plugin-sdk/provider-model-shared` | 공유 provider 모델/replay helper | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`, 공유 replay-policy 빌더, provider-endpoint helper, 모델 ID 정규화 helper | + | `plugin-sdk/provider-catalog-shared` | 공유 provider 카탈로그 helper | `findCatalogTemplate`, `buildSingleProviderApiKeyCatalog`, `supportsNativeStreamingUsageCompat`, `applyProviderNativeStreamingUsageCompat` | + | `plugin-sdk/provider-onboard` | provider 온보딩 패치 | 온보딩 config helper | + | `plugin-sdk/provider-http` | provider HTTP helper | 일반 provider HTTP/endpoint capability helper | + | `plugin-sdk/provider-web-fetch` | provider web-fetch helper | web-fetch provider 등록/캐시 helper | + | `plugin-sdk/provider-web-search-config-contract` | provider web-search config helper | plugin-enable 연결이 필요하지 않은 providers를 위한 좁은 web-search config/자격 증명 helper | + | `plugin-sdk/provider-web-search-contract` | provider web-search 계약 helper | `createWebSearchProviderContractFields`, `enablePluginInConfig`, `resolveProviderWebSearchPluginConfig`, 범위가 지정된 자격 증명 setter/getter 같은 좁은 web-search config/자격 증명 계약 helper | + | `plugin-sdk/provider-web-search` | provider web-search helper | web-search provider 등록/캐시/runtime helper | + | `plugin-sdk/provider-tools` | provider tool/schema 호환 helper | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`, Gemini 스키마 정리 + 진단, 그리고 `resolveXaiModelCompatPatch` / `applyXaiModelCompat` 같은 xAI 호환 helper | + | `plugin-sdk/provider-usage` | provider 사용량 helper | `fetchClaudeUsage`, `fetchGeminiUsage`, `fetchGithubCopilotUsage` 및 기타 provider 사용량 helper | + | `plugin-sdk/provider-stream` | provider stream wrapper helper | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`, stream wrapper 타입, 그리고 공유 Anthropic/Bedrock/Google/Kilocode/Moonshot/OpenAI/OpenRouter/Z.A.I/MiniMax/Copilot wrapper helper | + | `plugin-sdk/keyed-async-queue` | 순서가 보장된 async 큐 | `KeyedAsyncQueue` | + | `plugin-sdk/media-runtime` | 공유 미디어 helper | 미디어 fetch/transform/store helper와 미디어 payload 빌더 | + | `plugin-sdk/media-generation-runtime` | 공유 media-generation helper | 공유 failover helper, 후보 선택, 이미지/비디오/음악 생성을 위한 모델 누락 메시지 | + | `plugin-sdk/media-understanding` | media-understanding helper | media understanding provider 타입과 provider 대상 image/audio helper export | + | `plugin-sdk/text-runtime` | 공유 텍스트 helper | assistant-visible-text 제거, markdown 렌더/chunking/표 helper, 민감 정보 제거 helper, directive-tag helper, safe-text 유틸리티, 기타 관련 text/logging helper | | `plugin-sdk/text-chunking` | 텍스트 chunking helper | 아웃바운드 텍스트 chunking helper | - | `plugin-sdk/speech` | speech helper | speech 프로바이더 타입 및 프로바이더 대상 directive, registry, validation helper | - | `plugin-sdk/speech-core` | 공유 speech core | speech 프로바이더 타입, registry, directive, 정규화 | - | `plugin-sdk/realtime-transcription` | realtime transcription helper | 프로바이더 타입 및 registry helper | - | `plugin-sdk/realtime-voice` | realtime voice helper | 프로바이더 타입 및 registry helper | + | `plugin-sdk/speech` | speech helper | speech provider 타입과 provider 대상 directive, registry, validation helper | + | `plugin-sdk/speech-core` | 공유 speech core | speech provider 타입, registry, directive, 정규화 | + | `plugin-sdk/realtime-transcription` | realtime transcription helper | provider 타입 및 registry helper | + | `plugin-sdk/realtime-voice` | realtime voice helper | provider 타입 및 registry helper | | `plugin-sdk/image-generation-core` | 공유 image-generation core | image-generation 타입, failover, auth, registry helper | - | `plugin-sdk/music-generation` | music-generation helper | music-generation 프로바이더/request/result 타입 | - | `plugin-sdk/music-generation-core` | 공유 music-generation core | music-generation 타입, failover helper, provider 조회, model-ref 파싱 | - | `plugin-sdk/video-generation` | video-generation helper | video-generation 프로바이더/request/result 타입 | - | `plugin-sdk/video-generation-core` | 공유 video-generation core | video-generation 타입, failover helper, provider 조회, model-ref 파싱 | - | `plugin-sdk/interactive-runtime` | interactive 응답 helper | interactive 응답 payload 정규화/축소 | + | `plugin-sdk/music-generation` | music-generation helper | music-generation provider/request/result 타입 | + | `plugin-sdk/music-generation-core` | 공유 music-generation core | music-generation 타입, failover helper, provider 조회, model-ref 구문 분석 | + | `plugin-sdk/video-generation` | video-generation helper | video-generation provider/request/result 타입 | + | `plugin-sdk/video-generation-core` | 공유 video-generation core | video-generation 타입, failover helper, provider 조회, model-ref 구문 분석 | + | `plugin-sdk/interactive-runtime` | interactive 답장 helper | interactive 답장 payload 정규화/축소 | | `plugin-sdk/channel-config-primitives` | 채널 config 기본 구성 요소 | 좁은 채널 config-schema 기본 구성 요소 | - | `plugin-sdk/channel-config-writes` | 채널 config-write helper | 채널 config-write 권한 부여 helper | + | `plugin-sdk/channel-config-writes` | 채널 config-write helper | 채널 config-write authorization helper | | `plugin-sdk/channel-plugin-common` | 공유 채널 prelude | 공유 채널 plugin prelude export | - | `plugin-sdk/channel-status` | 채널 상태 helper | 공유 채널 상태 snapshot/summary helper | - | `plugin-sdk/allowlist-config-edit` | allowlist config helper | allowlist config edit/read helper | - | `plugin-sdk/group-access` | 그룹 접근 helper | 공유 그룹 접근 결정 helper | - | `plugin-sdk/direct-dm` | Direct-DM helper | 공유 direct-DM auth/guard helper | + | `plugin-sdk/channel-status` | 채널 상태 helper | 공유 채널 상태 스냅샷/요약 helper | + | `plugin-sdk/allowlist-config-edit` | 허용 목록 config helper | 허용 목록 config edit/read helper | + | `plugin-sdk/group-access` | 그룹 접근 helper | 공유 group-access 결정 helper | + | `plugin-sdk/direct-dm` | 직접 DM helper | 공유 직접 DM auth/guard helper | | `plugin-sdk/extension-shared` | 공유 extension helper | passive-channel/status 및 ambient proxy helper 기본 구성 요소 | | `plugin-sdk/webhook-targets` | webhook 대상 helper | webhook 대상 registry 및 route-install helper | | `plugin-sdk/webhook-path` | webhook 경로 helper | webhook 경로 정규화 helper | | `plugin-sdk/web-media` | 공유 web media helper | 원격/로컬 미디어 로딩 helper | - | `plugin-sdk/zod` | Zod 재-export | plugin SDK 소비자를 위한 재-export된 `zod` | - | `plugin-sdk/memory-core` | 번들 memory-core helper | 메모리 manager/config/file/CLI helper 표면 | - | `plugin-sdk/memory-core-engine-runtime` | 메모리 엔진 runtime facade | 메모리 index/search runtime facade | - | `plugin-sdk/memory-core-host-engine-foundation` | 메모리 호스트 foundation 엔진 | 메모리 호스트 foundation 엔진 export | - | `plugin-sdk/memory-core-host-engine-embeddings` | 메모리 호스트 embedding 엔진 | 메모리 호스트 embedding 엔진 export | + | `plugin-sdk/zod` | Zod 재내보내기 | plugin SDK 소비자를 위한 재내보낸 `zod` | + | `plugin-sdk/memory-core` | 번들 memory-core helper | 메모리 관리자/config/파일/CLI helper 표면 | + | `plugin-sdk/memory-core-engine-runtime` | 메모리 엔진 runtime 파사드 | 메모리 인덱스/검색 runtime 파사드 | + | `plugin-sdk/memory-core-host-engine-foundation` | 메모리 호스트 기반 엔진 | 메모리 호스트 기반 엔진 export | + | `plugin-sdk/memory-core-host-engine-embeddings` | 메모리 호스트 임베딩 엔진 | 메모리 호스트 임베딩 엔진 export | | `plugin-sdk/memory-core-host-engine-qmd` | 메모리 호스트 QMD 엔진 | 메모리 호스트 QMD 엔진 export | - | `plugin-sdk/memory-core-host-engine-storage` | 메모리 호스트 storage 엔진 | 메모리 호스트 storage 엔진 export | - | `plugin-sdk/memory-core-host-multimodal` | 메모리 호스트 multimodal helper | 메모리 호스트 multimodal helper | - | `plugin-sdk/memory-core-host-query` | 메모리 호스트 query helper | 메모리 호스트 query helper | - | `plugin-sdk/memory-core-host-secret` | 메모리 호스트 secret helper | 메모리 호스트 secret helper | - | `plugin-sdk/memory-core-host-events` | 메모리 호스트 이벤트 journal helper | 메모리 호스트 이벤트 journal helper | + | `plugin-sdk/memory-core-host-engine-storage` | 메모리 호스트 스토리지 엔진 | 메모리 호스트 스토리지 엔진 export | + | `plugin-sdk/memory-core-host-multimodal` | 메모리 호스트 멀티모달 helper | 메모리 호스트 멀티모달 helper | + | `plugin-sdk/memory-core-host-query` | 메모리 호스트 쿼리 helper | 메모리 호스트 쿼리 helper | + | `plugin-sdk/memory-core-host-secret` | 메모리 호스트 비밀 helper | 메모리 호스트 비밀 helper | + | `plugin-sdk/memory-core-host-events` | 메모리 호스트 이벤트 저널 helper | 메모리 호스트 이벤트 저널 helper | | `plugin-sdk/memory-core-host-status` | 메모리 호스트 상태 helper | 메모리 호스트 상태 helper | | `plugin-sdk/memory-core-host-runtime-cli` | 메모리 호스트 CLI runtime | 메모리 호스트 CLI runtime helper | | `plugin-sdk/memory-core-host-runtime-core` | 메모리 호스트 core runtime | 메모리 호스트 core runtime helper | | `plugin-sdk/memory-core-host-runtime-files` | 메모리 호스트 파일/runtime helper | 메모리 호스트 파일/runtime helper | - | `plugin-sdk/memory-host-core` | 메모리 호스트 core runtime alias | 메모리 호스트 core runtime helper용 vendor-neutral alias | - | `plugin-sdk/memory-host-events` | 메모리 호스트 이벤트 journal alias | 메모리 호스트 이벤트 journal helper용 vendor-neutral alias | - | `plugin-sdk/memory-host-files` | 메모리 호스트 파일/runtime alias | 메모리 호스트 파일/runtime helper용 vendor-neutral alias | - | `plugin-sdk/memory-host-markdown` | managed markdown helper | memory 인접 plugin용 공유 managed-markdown helper | - | `plugin-sdk/memory-host-search` | 활성 메모리 검색 facade | lazy active-memory search-manager runtime facade | - | `plugin-sdk/memory-host-status` | 메모리 호스트 상태 alias | 메모리 호스트 상태 helper용 vendor-neutral alias | + | `plugin-sdk/memory-host-core` | 메모리 호스트 core runtime 별칭 | 메모리 호스트 core runtime helper를 위한 vendor-neutral 별칭 | + | `plugin-sdk/memory-host-events` | 메모리 호스트 이벤트 저널 별칭 | 메모리 호스트 이벤트 저널 helper를 위한 vendor-neutral 별칭 | + | `plugin-sdk/memory-host-files` | 메모리 호스트 파일/runtime 별칭 | 메모리 호스트 파일/runtime helper를 위한 vendor-neutral 별칭 | + | `plugin-sdk/memory-host-markdown` | 관리형 markdown helper | memory 인접 plugins를 위한 공유 관리형 markdown helper | + | `plugin-sdk/memory-host-search` | 활성 메모리 검색 파사드 | 지연 로드되는 활성 메모리 search-manager runtime 파사드 | + | `plugin-sdk/memory-host-status` | 메모리 호스트 상태 별칭 | 메모리 호스트 상태 helper를 위한 vendor-neutral 별칭 | | `plugin-sdk/memory-lancedb` | 번들 memory-lancedb helper | memory-lancedb helper 표면 | | `plugin-sdk/testing` | 테스트 유틸리티 | 테스트 helper 및 mock | 이 표는 전체 SDK -표면이 아니라 의도적으로 일반적인 마이그레이션 하위 집합만 담고 있습니다. 200개가 넘는 엔트리포인트의 전체 목록은 +표면이 아니라 의도적으로 일반적인 마이그레이션 하위 집합만 포함합니다. 200개가 넘는 전체 entrypoint 목록은 `scripts/lib/plugin-sdk-entrypoints.json`에 있습니다. -그 목록에는 여전히 +해당 목록에는 여전히 `plugin-sdk/feishu`, `plugin-sdk/feishu-setup`, `plugin-sdk/zalo`, -`plugin-sdk/zalo-setup`, `plugin-sdk/matrix*` 같은 일부 번들-plugin helper seam이 포함되어 있습니다. 이것들은 -번들-plugin 유지 관리와 호환성을 위해 계속 export되지만, -일반적인 마이그레이션 표에서는 의도적으로 생략되며 -새 plugin 코드의 권장 대상은 아닙니다. +`plugin-sdk/zalo-setup`, `plugin-sdk/matrix*` 같은 일부 번들-plugin helper seam도 포함되어 있습니다. 이들은 번들-plugin 유지 관리와 호환성을 위해 계속 export되지만, +의도적으로 일반 마이그레이션 표에서는 제외되어 있으며 +새 plugin 코드에 권장되는 대상이 아닙니다. -동일한 규칙이 다음과 같은 다른 번들-helper 계열에도 적용됩니다. +같은 규칙은 다음과 같은 다른 번들-helper 계열에도 적용됩니다. -- browser 지원 helper: `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` +- 브라우저 지원 helper: `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` - Matrix: `plugin-sdk/matrix*` - LINE: `plugin-sdk/line*` - IRC: `plugin-sdk/irc*` @@ -370,24 +369,25 @@ plugin workspace 내부에서는 프로바이더 소유 helper를 해당 plugin `plugin-sdk/diagnostics-otel`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` 같은 번들 helper/plugin 표면 -`plugin-sdk/github-copilot-token`은 현재 좁은 범위의 토큰-helper -표면인 `DEFAULT_COPILOT_API_BASE_URL`, -`deriveCopilotApiBaseUrlFromToken`, `resolveCopilotApiToken`을 노출합니다. +`plugin-sdk/github-copilot-token`은 현재 +`DEFAULT_COPILOT_API_BASE_URL`, +`deriveCopilotApiBaseUrlFromToken`, `resolveCopilotApiToken`이라는 좁은 토큰-helper +표면을 노출합니다. -작업에 맞는 가장 좁은 import를 사용하세요. export를 찾을 수 없다면 +작업에 맞는 가장 좁은 import를 사용하세요. export를 찾을 수 없다면, `src/plugin-sdk/`의 소스를 확인하거나 Discord에서 문의하세요. ## 제거 일정 -| 시점 | 발생 내용 | +| 시점 | 발생하는 일 | | ---------------------- | ----------------------------------------------------------------------- | -| **지금** | deprecated 표면이 런타임 경고를 출력 | -| **다음 메이저 릴리스** | deprecated 표면이 제거되며, 계속 사용하는 plugin은 실패 | +| **지금** | 사용 중단된 표면이 런타임 경고를 출력함 | +| **다음 메이저 릴리스** | 사용 중단된 표면이 제거되며, 여전히 이를 사용하는 plugins는 실패함 | -모든 core plugin은 이미 마이그레이션되었습니다. 외부 plugin은 -다음 메이저 릴리스 전에 마이그레이션해야 합니다. +모든 core plugins는 이미 마이그레이션되었습니다. 외부 plugins도 다음 메이저 릴리스 전에 +마이그레이션해야 합니다. -## 경고를 임시로 숨기기 +## 경고를 일시적으로 숨기기 마이그레이션 작업 중에는 다음 환경 변수를 설정하세요. @@ -396,13 +396,13 @@ OPENCLAW_SUPPRESS_PLUGIN_SDK_COMPAT_WARNING=1 openclaw gateway run OPENCLAW_SUPPRESS_EXTENSION_API_WARNING=1 openclaw gateway run ``` -이것은 임시 탈출구일 뿐이며 영구적인 해결책은 아닙니다. +이것은 임시 탈출구일 뿐, 영구적인 해결책은 아닙니다. ## 관련 문서 -- [시작하기](/ko/plugins/building-plugins) — 첫 번째 plugin 만들기 -- [SDK 개요](/ko/plugins/sdk-overview) — 전체 subpath import 참조 -- [채널 plugin](/ko/plugins/sdk-channel-plugins) — 채널 plugin 만들기 -- [프로바이더 plugin](/ko/plugins/sdk-provider-plugins) — 프로바이더 plugin 만들기 -- [Plugin 내부 구조](/ko/plugins/architecture) — 아키텍처 심층 분석 +- [시작하기](/ko/plugins/building-plugins) — 첫 plugin 만들기 +- [SDK 개요](/ko/plugins/sdk-overview) — 전체 하위 경로 import 참조 +- [채널 Plugins](/ko/plugins/sdk-channel-plugins) — 채널 plugins 만들기 +- [Provider Plugins](/ko/plugins/sdk-provider-plugins) — provider plugins 만들기 +- [Plugin 내부 구조](/ko/plugins/architecture) — 아키텍처 심화 설명 - [Plugin Manifest](/ko/plugins/manifest) — manifest 스키마 참조 diff --git a/docs/ko/plugins/sdk-overview.md b/docs/ko/plugins/sdk-overview.md index 54ac85f54..07e4572b1 100644 --- a/docs/ko/plugins/sdk-overview.md +++ b/docs/ko/plugins/sdk-overview.md @@ -1,360 +1,339 @@ --- read_when: - - 어느 SDK 하위 경로에서 import해야 하는지 알아야 할 때 - - OpenClawPluginApi의 모든 registration 메서드에 대한 참조가 필요할 때 - - 특정 SDK export를 찾고 있을 때 + - 어떤 SDK 하위 경로에서 import해야 하는지 알아야 합니다 + - OpenClawPluginApi의 모든 등록 메서드에 대한 참조가 필요합니다 + - 특정 SDK export를 찾고 있습니다 sidebarTitle: SDK Overview -summary: import map, registration API 참조, 및 SDK 아키텍처 +summary: import 맵, 등록 API 참조, SDK 아키텍처 title: Plugin SDK 개요 x-i18n: - generated_at: "2026-04-08T02:18:09Z" + generated_at: "2026-04-09T01:31:11Z" model: gpt-5.4 provider: openai - source_hash: c5a41bd82d165dfbb7fbd6e4528cf322e9133a51efe55fa8518a7a0a626d9d30 + source_hash: bf205af060971931df97dca4af5110ce173d2b7c12f56ad7c62d664a402f2381 source_path: plugins/sdk-overview.md workflow: 15 --- # Plugin SDK 개요 -plugin SDK는 plugins와 core 사이의 타입 지정 계약입니다. 이 페이지는 -**무엇을 import할지**와 **무엇을 등록할 수 있는지**에 대한 참조입니다. +Plugin SDK는 plugins와 core 사이의 타입이 지정된 계약입니다. 이 페이지는 **무엇을 import할지**와 **무엇을 등록할 수 있는지**에 대한 참조입니다. **사용 방법 가이드를 찾고 있나요?** - - 첫 plugin인가요? [Getting Started](/ko/plugins/building-plugins)부터 시작하세요 - - Channel plugin인가요? [Channel Plugins](/ko/plugins/sdk-channel-plugins)를 참조하세요 - - Provider plugin인가요? [Provider Plugins](/ko/plugins/sdk-provider-plugins)를 참조하세요 + - 첫 plugin이라면? [Getting Started](/ko/plugins/building-plugins)부터 시작하세요 + - Channel plugin이라면? [Channel Plugins](/ko/plugins/sdk-channel-plugins)를 참조하세요 + - Provider plugin이라면? [Provider Plugins](/ko/plugins/sdk-provider-plugins)를 참조하세요 ## import 규칙 -항상 특정 하위 경로에서 import하세요: +항상 특정 하위 경로에서 import하세요. ```typescript import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core"; ``` -각 하위 경로는 작고 독립적인 모듈입니다. 이렇게 하면 시작 속도를 빠르게 유지하고 -순환 의존성 문제를 방지할 수 있습니다. 채널별 entry/build helper의 경우 -`openclaw/plugin-sdk/channel-core`를 우선 사용하고, 더 넓은 umbrella 표면과 -`buildChannelConfigSchema` 같은 공통 helper에는 -`openclaw/plugin-sdk/core`를 사용하세요. +각 하위 경로는 작고 독립적인 모듈입니다. 이렇게 하면 시작 속도가 빨라지고 순환 의존성 문제를 방지할 수 있습니다. channel 전용 entry/build helper의 경우 `openclaw/plugin-sdk/channel-core`를 우선 사용하고, 더 넓은 umbrella 표면과 `buildChannelConfigSchema` 같은 공용 helper에는 `openclaw/plugin-sdk/core`를 유지하세요. -`openclaw/plugin-sdk/slack`, `openclaw/plugin-sdk/discord`, -`openclaw/plugin-sdk/signal`, `openclaw/plugin-sdk/whatsapp` 같은 -provider 이름이 붙은 편의 seam이나 채널 브랜딩 helper seam을 추가하거나 이에 의존하지 마세요. -번들 plugins는 generic -SDK 하위 경로를 자체 `api.ts` 또는 `runtime-api.ts` barrel 안에서 조합해야 하며, core는 -그런 plugin 로컬 barrel을 사용하거나, 필요가 진정으로 cross-channel일 때에만 -좁은 generic SDK 계약을 추가해야 합니다. +`openclaw/plugin-sdk/slack`, `openclaw/plugin-sdk/discord`, `openclaw/plugin-sdk/signal`, `openclaw/plugin-sdk/whatsapp` 또는 channel 브랜드 helper seam 같은 provider 이름 기반 convenience seam을 추가하거나 이에 의존하지 마세요. 번들 plugins는 자체 `api.ts` 또는 `runtime-api.ts` barrel 안에서 일반적인 SDK 하위 경로를 조합해야 하며, core는 해당 plugin 로컬 barrel을 사용하거나 필요가 진짜 cross-channel일 때 좁고 일반적인 SDK 계약을 추가해야 합니다. -생성된 export map에는 여전히 `plugin-sdk/feishu`, `plugin-sdk/feishu-setup`, -`plugin-sdk/zalo`, `plugin-sdk/zalo-setup`, `plugin-sdk/matrix*` 같은 -일부 번들 plugin helper seam이 포함되어 있습니다. 이러한 -하위 경로는 번들 plugin 유지 관리와 호환성만을 위해 존재하며, -아래의 일반 표에서는 의도적으로 생략되었고 새로운 서드파티 plugins에 권장되는 -import 경로가 아닙니다. +생성된 export 맵에는 여전히 `plugin-sdk/feishu`, `plugin-sdk/feishu-setup`, `plugin-sdk/zalo`, `plugin-sdk/zalo-setup`, `plugin-sdk/matrix*` 같은 소수의 번들 plugin helper seam이 포함되어 있습니다. 이러한 하위 경로는 번들 plugin 유지 관리 및 호환성 전용으로 존재하며, 아래 공통 표에서는 의도적으로 생략되었고 새로운 서드파티 plugins에 권장되는 import 경로도 아닙니다. ## 하위 경로 참조 -가장 자주 사용되는 하위 경로를 목적별로 그룹화했습니다. 200개가 넘는 -전체 하위 경로 목록은 생성된 `scripts/lib/plugin-sdk-entrypoints.json`에 있습니다. +가장 자주 사용하는 하위 경로를 용도별로 묶었습니다. 200개가 넘는 하위 경로의 전체 생성 목록은 `scripts/lib/plugin-sdk-entrypoints.json`에 있습니다. -예약된 번들 plugin helper 하위 경로도 이 생성 목록에 계속 표시됩니다. -문서 페이지에서 공개용으로 명시적으로 권장하지 않는 한, 이러한 경로는 -구현 세부 사항/호환성 표면으로 취급하세요. +예약된 번들 plugin helper 하위 경로도 이 생성 목록에 계속 나타납니다. 문서 페이지에서 명시적으로 public으로 권장하지 않는 한, 이를 구현 세부 사항/호환성 표면으로 취급하세요. ### Plugin entry -| 하위 경로 | 주요 exports | -| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| `plugin-sdk/plugin-entry` | `definePluginEntry` | -| `plugin-sdk/core` | `defineChannelPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase`, `defineSetupPluginEntry`, `buildChannelConfigSchema` | -| `plugin-sdk/config-schema` | `OpenClawSchema` | +| Subpath | 주요 exports | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| `plugin-sdk/plugin-entry` | `definePluginEntry` | +| `plugin-sdk/core` | `defineChannelPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase`, `defineSetupPluginEntry`, `buildChannelConfigSchema` | +| `plugin-sdk/config-schema` | `OpenClawSchema` | | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | - - | 하위 경로 | 주요 exports | + + | Subpath | 주요 exports | | --- | --- | | `plugin-sdk/channel-core` | `defineChannelPluginEntry`, `defineSetupPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase` | | `plugin-sdk/config-schema` | 루트 `openclaw.json` Zod 스키마 export (`OpenClawSchema`) | | `plugin-sdk/channel-setup` | `createOptionalChannelSetupSurface`, `createOptionalChannelSetupAdapter`, `createOptionalChannelSetupWizard`, 그리고 `DEFAULT_ACCOUNT_ID`, `createTopLevelChannelDmPolicy`, `setSetupChannelEnabled`, `splitSetupEntries` | - | `plugin-sdk/setup` | 공통 setup wizard helper, allowlist 프롬프트, setup 상태 builder | + | `plugin-sdk/setup` | 공용 setup wizard helper, 허용 목록 프롬프트, setup 상태 빌더 | | `plugin-sdk/setup-runtime` | `createPatchedAccountSetupAdapter`, `createEnvPatchedAccountSetupAdapter`, `createSetupInputPresenceValidator`, `noteChannelLookupFailure`, `noteChannelLookupSummary`, `promptResolvedAllowFrom`, `splitSetupEntries`, `createAllowlistSetupWizardProxy`, `createDelegatedSetupWizardProxy` | | `plugin-sdk/setup-adapter-runtime` | `createEnvPatchedAccountSetupAdapter` | | `plugin-sdk/setup-tools` | `formatCliCommand`, `detectBinary`, `extractArchive`, `resolveBrewExecutable`, `formatDocsLink`, `CONFIG_DIR` | - | `plugin-sdk/account-core` | 다중 계정 config/action-gate helper, 기본 계정 fallback helper | + | `plugin-sdk/account-core` | 다중 계정 config/action-gate helper, 기본 계정 폴백 helper | | `plugin-sdk/account-id` | `DEFAULT_ACCOUNT_ID`, account-id 정규화 helper | - | `plugin-sdk/account-resolution` | 계정 조회 + 기본 fallback helper | + | `plugin-sdk/account-resolution` | 계정 조회 + 기본 폴백 helper | | `plugin-sdk/account-helpers` | 좁은 범위의 account-list/account-action helper | | `plugin-sdk/channel-pairing` | `createChannelPairingController` | | `plugin-sdk/channel-reply-pipeline` | `createChannelReplyPipeline` | | `plugin-sdk/channel-config-helpers` | `createHybridChannelConfigAdapter` | - | `plugin-sdk/channel-config-schema` | 채널 config 스키마 타입 | - | `plugin-sdk/telegram-command-config` | 번들 계약 fallback이 포함된 Telegram custom-command 정규화/검증 helper | + | `plugin-sdk/channel-config-schema` | Channel config 스키마 타입 | + | `plugin-sdk/telegram-command-config` | 번들 계약 폴백이 포함된 Telegram 사용자 지정 command 정규화/검증 helper | | `plugin-sdk/channel-policy` | `resolveChannelGroupRequireMention` | | `plugin-sdk/channel-lifecycle` | `createAccountStatusSink` | - | `plugin-sdk/inbound-envelope` | 공통 인바운드 route + envelope builder helper | - | `plugin-sdk/inbound-reply-dispatch` | 공통 인바운드 record-and-dispatch helper | + | `plugin-sdk/inbound-envelope` | 공용 수신 라우트 + envelope 빌더 helper | + | `plugin-sdk/inbound-reply-dispatch` | 공용 수신 record-and-dispatch helper | | `plugin-sdk/messaging-targets` | 대상 파싱/매칭 helper | - | `plugin-sdk/outbound-media` | 공통 아웃바운드 미디어 로딩 helper | - | `plugin-sdk/outbound-runtime` | 아웃바운드 identity/send delegate helper | - | `plugin-sdk/thread-bindings-runtime` | 스레드 바인딩 수명 주기 및 adapter helper | - | `plugin-sdk/agent-media-payload` | 레거시 agent media payload builder | - | `plugin-sdk/conversation-runtime` | 대화/스레드 바인딩, 페어링, 구성된 바인딩 helper | - | `plugin-sdk/runtime-config-snapshot` | 런타임 config snapshot helper | - | `plugin-sdk/runtime-group-policy` | 런타임 그룹 정책 해석 helper | - | `plugin-sdk/channel-status` | 공통 채널 상태 snapshot/summary helper | - | `plugin-sdk/channel-config-primitives` | 좁은 범위의 채널 config-schema primitive | - | `plugin-sdk/channel-config-writes` | 채널 config 쓰기 권한 부여 helper | - | `plugin-sdk/channel-plugin-common` | 공통 채널 plugin prelude exports | - | `plugin-sdk/allowlist-config-edit` | Allowlist config 편집/읽기 helper | - | `plugin-sdk/group-access` | 공통 그룹 접근 결정 helper | - | `plugin-sdk/direct-dm` | 공통 direct-DM 인증/guard helper | - | `plugin-sdk/interactive-runtime` | interactive reply payload 정규화/축소 helper | - | `plugin-sdk/channel-inbound` | 인바운드 debounce, 멘션 매칭, mention-policy helper, 그리고 envelope helper | - | `plugin-sdk/channel-send-result` | reply 결과 타입 | + | `plugin-sdk/outbound-media` | 공용 송신 미디어 로딩 helper | + | `plugin-sdk/outbound-runtime` | 송신 identity/send delegate helper | + | `plugin-sdk/thread-bindings-runtime` | 스레드 바인딩 lifecycle 및 adapter helper | + | `plugin-sdk/agent-media-payload` | 레거시 agent 미디어 payload 빌더 | + | `plugin-sdk/conversation-runtime` | 대화/스레드 바인딩, 페어링, configured-binding helper | + | `plugin-sdk/runtime-config-snapshot` | 런타임 config 스냅샷 helper | + | `plugin-sdk/runtime-group-policy` | 런타임 group-policy 해석 helper | + | `plugin-sdk/channel-status` | 공용 channel 상태 스냅샷/요약 helper | + | `plugin-sdk/channel-config-primitives` | 좁은 범위의 channel config-schema primitives | + | `plugin-sdk/channel-config-writes` | Channel config-write 권한 부여 helper | + | `plugin-sdk/channel-plugin-common` | 공용 channel plugin prelude exports | + | `plugin-sdk/allowlist-config-edit` | 허용 목록 config 편집/읽기 helper | + | `plugin-sdk/group-access` | 공용 group-access 결정 helper | + | `plugin-sdk/direct-dm` | 공용 direct-DM auth/guard helper | + | `plugin-sdk/interactive-runtime` | 대화형 reply payload 정규화/축소 helper | + | `plugin-sdk/channel-inbound` | 수신 debounce, mention 매칭, mention-policy helper 및 envelope helper | + | `plugin-sdk/channel-send-result` | Reply 결과 타입 | | `plugin-sdk/channel-actions` | `createMessageToolButtonsSchema`, `createMessageToolCardSchema` | | `plugin-sdk/channel-targets` | 대상 파싱/매칭 helper | - | `plugin-sdk/channel-contract` | 채널 계약 타입 | - | `plugin-sdk/channel-feedback` | 피드백/반응 연결 | - | `plugin-sdk/channel-secret-runtime` | `collectSimpleChannelFieldAssignments`, `getChannelSurface`, `pushAssignment`, secret 대상 타입 같은 좁은 secret 계약 helper | + | `plugin-sdk/channel-contract` | Channel 계약 타입 | + | `plugin-sdk/channel-feedback` | 피드백/reaction wiring | + | `plugin-sdk/channel-secret-runtime` | `collectSimpleChannelFieldAssignments`, `getChannelSurface`, `pushAssignment` 및 secret 대상 타입 같은 좁은 범위의 secret-contract helper | - | 하위 경로 | 주요 exports | + | Subpath | 주요 exports | | --- | --- | | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | - | `plugin-sdk/provider-setup` | 엄선된 로컬/자체 호스팅 provider setup helper | - | `plugin-sdk/self-hosted-provider-setup` | 집중된 OpenAI 호환 자체 호스팅 provider setup helper | + | `plugin-sdk/provider-setup` | 선별된 local/self-hosted provider setup helper | + | `plugin-sdk/self-hosted-provider-setup` | 집중된 OpenAI 호환 self-hosted provider setup helper | | `plugin-sdk/cli-backend` | CLI backend 기본값 + watchdog 상수 | | `plugin-sdk/provider-auth-runtime` | provider plugins용 런타임 API 키 해석 helper | | `plugin-sdk/provider-auth-api-key` | `upsertApiKeyProfile` 같은 API 키 onboarding/profile-write helper | - | `plugin-sdk/provider-auth-result` | 표준 OAuth auth-result builder | - | `plugin-sdk/provider-auth-login` | provider plugins용 공통 interactive login helper | - | `plugin-sdk/provider-env-vars` | provider 인증 env-var 조회 helper | + | `plugin-sdk/provider-auth-result` | 표준 OAuth auth-result 빌더 | + | `plugin-sdk/provider-auth-login` | provider plugins용 공용 대화형 로그인 helper | + | `plugin-sdk/provider-env-vars` | Provider auth env-var 조회 helper | | `plugin-sdk/provider-auth` | `createProviderApiKeyAuthMethod`, `ensureApiKeyFromOptionEnvOrPrompt`, `upsertAuthProfile`, `upsertApiKeyProfile`, `writeOAuthCredentials` | - | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`, 공통 replay-policy builder, provider-endpoint helper, 그리고 `normalizeNativeXaiModelId` 같은 model-id 정규화 helper | + | `plugin-sdk/provider-model-shared` | `ProviderReplayFamily`, `buildProviderReplayFamilyHooks`, `normalizeModelCompat`, 공용 replay-policy 빌더, provider-endpoint helper, `normalizeNativeXaiModelId` 같은 model-id 정규화 helper | | `plugin-sdk/provider-catalog-shared` | `findCatalogTemplate`, `buildSingleProviderApiKeyCatalog`, `supportsNativeStreamingUsageCompat`, `applyProviderNativeStreamingUsageCompat` | - | `plugin-sdk/provider-http` | generic provider HTTP/endpoint capability helper | - | `plugin-sdk/provider-web-fetch-contract` | `enablePluginInConfig`, `WebFetchProviderPlugin` 같은 좁은 web-fetch config/selection 계약 helper | - | `plugin-sdk/provider-web-fetch` | web-fetch provider 등록/캐시 helper | - | `plugin-sdk/provider-web-search-contract` | `enablePluginInConfig`, `resolveProviderWebSearchPluginConfig`, 범위 지정된 자격 증명 setter/getter 같은 좁은 web-search config/credential 계약 helper | - | `plugin-sdk/provider-web-search` | web-search provider 등록/캐시/런타임 helper | - | `plugin-sdk/provider-tools` | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`, Gemini 스키마 정리 + 진단, 그리고 `resolveXaiModelCompatPatch` / `applyXaiModelCompat` 같은 xAI 호환 helper | + | `plugin-sdk/provider-http` | 일반적인 provider HTTP/endpoint capability helper | + | `plugin-sdk/provider-web-fetch-contract` | `enablePluginInConfig` 및 `WebFetchProviderPlugin` 같은 좁은 범위의 web-fetch config/selection 계약 helper | + | `plugin-sdk/provider-web-fetch` | Web-fetch provider 등록/cache helper | + | `plugin-sdk/provider-web-search-config-contract` | plugin-enable wiring이 필요 없는 provider를 위한 좁은 범위의 web-search config/credential helper | + | `plugin-sdk/provider-web-search-contract` | `createWebSearchProviderContractFields`, `enablePluginInConfig`, `resolveProviderWebSearchPluginConfig`, 범위가 지정된 credential setter/getter 같은 좁은 범위의 web-search config/credential 계약 helper | + | `plugin-sdk/provider-web-search` | Web-search provider 등록/cache/런타임 helper | + | `plugin-sdk/provider-tools` | `ProviderToolCompatFamily`, `buildProviderToolCompatFamilyHooks`, Gemini 스키마 정리 + 진단, `resolveXaiModelCompatPatch` / `applyXaiModelCompat` 같은 xAI 호환 helper | | `plugin-sdk/provider-usage` | `fetchClaudeUsage` 등 | - | `plugin-sdk/provider-stream` | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`, 스트림 wrapper 타입, 그리고 공통 Anthropic/Bedrock/Google/Kilocode/Moonshot/OpenAI/OpenRouter/Z.A.I/MiniMax/Copilot wrapper helper | - | `plugin-sdk/provider-onboard` | onboarding config patch helper | + | `plugin-sdk/provider-stream` | `ProviderStreamFamily`, `buildProviderStreamFamilyHooks`, `composeProviderStreamWrappers`, stream wrapper 타입, 공용 Anthropic/Bedrock/Google/Kilocode/Moonshot/OpenAI/OpenRouter/Z.A.I/MiniMax/Copilot wrapper helper | + | `plugin-sdk/provider-onboard` | Onboarding config patch helper | | `plugin-sdk/global-singleton` | 프로세스 로컬 singleton/map/cache helper | - - | 하위 경로 | 주요 exports | + + | Subpath | 주요 exports | | --- | --- | - | `plugin-sdk/command-auth` | `resolveControlCommandGate`, command registry helper, sender-authorization helper | + | `plugin-sdk/command-auth` | `resolveControlCommandGate`, command 레지스트리 helper, sender-authorization helper | + | `plugin-sdk/command-status` | `buildCommandsMessagePaginated`, `buildHelpMessage` 같은 command/help 메시지 빌더 | | `plugin-sdk/approval-auth-runtime` | 승인자 해석 및 same-chat action-auth helper | | `plugin-sdk/approval-client-runtime` | 네이티브 exec 승인 profile/filter helper | | `plugin-sdk/approval-delivery-runtime` | 네이티브 승인 capability/delivery adapter | - | `plugin-sdk/approval-gateway-runtime` | 공통 승인 gateway-resolution helper | - | `plugin-sdk/approval-handler-adapter-runtime` | hot 채널 entrypoint용 경량 네이티브 승인 adapter 로딩 helper | - | `plugin-sdk/approval-handler-runtime` | 더 넓은 승인 handler 런타임 helper; 좁은 adapter/gateway seam으로 충분하다면 그것들을 우선 사용하세요 | + | `plugin-sdk/approval-gateway-runtime` | 공용 승인 gateway-resolution helper | + | `plugin-sdk/approval-handler-adapter-runtime` | 핫 channel entrypoint용 경량 네이티브 승인 adapter 로딩 helper | + | `plugin-sdk/approval-handler-runtime` | 더 넓은 범위의 승인 handler 런타임 helper. 좁은 adapter/gateway seam으로 충분하면 그것을 우선 사용하세요 | | `plugin-sdk/approval-native-runtime` | 네이티브 승인 대상 + account-binding helper | - | `plugin-sdk/approval-reply-runtime` | exec/plugin 승인 reply payload helper | + | `plugin-sdk/approval-reply-runtime` | Exec/plugin 승인 reply payload helper | | `plugin-sdk/command-auth-native` | 네이티브 command auth + 네이티브 session-target helper | - | `plugin-sdk/command-detection` | 공통 command 감지 helper | - | `plugin-sdk/command-surface` | command-body 정규화 및 command-surface helper | + | `plugin-sdk/command-detection` | 공용 command 감지 helper | + | `plugin-sdk/command-surface` | Command-body 정규화 및 command-surface helper | | `plugin-sdk/allow-from` | `formatAllowFromLowercase` | - | `plugin-sdk/channel-secret-runtime` | 채널/plugin secret 표면용 좁은 secret 계약 수집 helper | - | `plugin-sdk/secret-ref-runtime` | secret-contract/config 파싱용 좁은 `coerceSecretRef` 및 SecretRef 타이핑 helper | - | `plugin-sdk/security-runtime` | 공통 신뢰, DM gating, external-content, secret-collection helper | - | `plugin-sdk/ssrf-policy` | 호스트 allowlist 및 private-network SSRF policy helper | - | `plugin-sdk/ssrf-runtime` | pinned-dispatcher, SSRF 보호 fetch, SSRF policy helper | - | `plugin-sdk/secret-input` | secret 입력 파싱 helper | - | `plugin-sdk/webhook-ingress` | webhook 요청/대상 helper | - | `plugin-sdk/webhook-request-guards` | 요청 본문 크기/timeout helper | + | `plugin-sdk/channel-secret-runtime` | channel/plugin secret 표면용 좁은 범위의 secret-contract 수집 helper | + | `plugin-sdk/secret-ref-runtime` | secret-contract/config 파싱용 좁은 범위의 `coerceSecretRef` 및 SecretRef 타입 helper | + | `plugin-sdk/security-runtime` | 공용 신뢰, DM 게이팅, 외부 콘텐츠, secret 수집 helper | + | `plugin-sdk/ssrf-policy` | 호스트 허용 목록 및 private-network SSRF 정책 helper | + | `plugin-sdk/ssrf-runtime` | pinned-dispatcher, SSRF 보호 fetch, SSRF 정책 helper | + | `plugin-sdk/secret-input` | Secret 입력 파싱 helper | + | `plugin-sdk/webhook-ingress` | Webhook 요청/대상 helper | + | `plugin-sdk/webhook-request-guards` | 요청 본문 크기/시간 초과 helper | - | 하위 경로 | 주요 exports | + | Subpath | 주요 exports | | --- | --- | - | `plugin-sdk/runtime` | 넓은 범위의 런타임/로깅/백업/plugin-install helper | + | `plugin-sdk/runtime` | 폭넓은 런타임/로깅/백업/plugin 설치 helper | | `plugin-sdk/runtime-env` | 좁은 범위의 런타임 env, logger, timeout, retry, backoff helper | - | `plugin-sdk/channel-runtime-context` | generic 채널 runtime-context 등록 및 조회 helper | + | `plugin-sdk/channel-runtime-context` | 일반적인 channel runtime-context 등록 및 조회 helper | | `plugin-sdk/runtime-store` | `createPluginRuntimeStore` | - | `plugin-sdk/plugin-runtime` | 공통 plugin command/hook/http/interactive helper | - | `plugin-sdk/hook-runtime` | 공통 webhook/internal hook 파이프라인 helper | - | `plugin-sdk/lazy-runtime` | `createLazyRuntimeModule`, `createLazyRuntimeMethod`, `createLazyRuntimeSurface` 같은 lazy 런타임 import/binding helper | + | `plugin-sdk/plugin-runtime` | 공용 plugin command/hook/http/interactive helper | + | `plugin-sdk/hook-runtime` | 공용 webhook/internal hook 파이프라인 helper | + | `plugin-sdk/lazy-runtime` | `createLazyRuntimeModule`, `createLazyRuntimeMethod`, `createLazyRuntimeSurface` 같은 지연 런타임 import/binding helper | | `plugin-sdk/process-runtime` | 프로세스 exec helper | - | `plugin-sdk/cli-runtime` | CLI formatting, wait, version helper | - | `plugin-sdk/gateway-runtime` | Gateway 클라이언트 및 채널 상태 patch helper | + | `plugin-sdk/cli-runtime` | CLI 서식 지정, 대기, 버전 helper | + | `plugin-sdk/gateway-runtime` | Gateway client 및 channel-status patch helper | | `plugin-sdk/config-runtime` | Config 로드/쓰기 helper | - | `plugin-sdk/telegram-command-config` | 번들 Telegram 계약 표면을 사용할 수 없더라도 Telegram command-name/description 정규화 및 중복/충돌 검사 | - | `plugin-sdk/approval-runtime` | exec/plugin 승인 helper, 승인 capability builder, auth/profile helper, 네이티브 라우팅/런타임 helper | - | `plugin-sdk/reply-runtime` | 공통 인바운드/reply 런타임 helper, 청킹, 디스패치, heartbeat, reply planner | - | `plugin-sdk/reply-dispatch-runtime` | 좁은 reply dispatch/finalize helper | - | `plugin-sdk/reply-history` | `buildHistoryContext`, `recordPendingHistoryEntry`, `clearHistoryEntriesIfEnabled` 같은 공통 짧은 창 reply-history helper | + | `plugin-sdk/telegram-command-config` | 번들 Telegram 계약 표면을 사용할 수 없을 때도 Telegram command-name/description 정규화 및 중복/충돌 검사 | + | `plugin-sdk/approval-runtime` | Exec/plugin 승인 helper, 승인-capability 빌더, auth/profile helper, 네이티브 라우팅/런타임 helper | + | `plugin-sdk/reply-runtime` | 공용 수신/reply 런타임 helper, chunking, dispatch, heartbeat, reply planner | + | `plugin-sdk/reply-dispatch-runtime` | 좁은 범위의 reply dispatch/finalize helper | + | `plugin-sdk/reply-history` | `buildHistoryContext`, `recordPendingHistoryEntry`, `clearHistoryEntriesIfEnabled` 같은 공용 짧은 기간 reply-history helper | | `plugin-sdk/reply-reference` | `createReplyReferencePlanner` | - | `plugin-sdk/reply-chunking` | 좁은 텍스트/Markdown 청킹 helper | + | `plugin-sdk/reply-chunking` | 좁은 범위의 텍스트/markdown chunking helper | | `plugin-sdk/session-store-runtime` | 세션 저장소 경로 + updated-at helper | | `plugin-sdk/state-paths` | 상태/OAuth 디렉터리 경로 helper | - | `plugin-sdk/routing` | `resolveAgentRoute`, `buildAgentSessionKey`, `resolveDefaultAgentBoundAccountId` 같은 route/session-key/account binding helper | - | `plugin-sdk/status-helpers` | 공통 채널/계정 상태 summary helper, runtime-state 기본값, issue 메타데이터 helper | - | `plugin-sdk/target-resolver-runtime` | 공통 대상 resolver helper | + | `plugin-sdk/routing` | `resolveAgentRoute`, `buildAgentSessionKey`, `resolveDefaultAgentBoundAccountId` 같은 route/session-key/account 바인딩 helper | + | `plugin-sdk/status-helpers` | 공용 channel/account 상태 요약 helper, 런타임 상태 기본값, issue 메타데이터 helper | + | `plugin-sdk/target-resolver-runtime` | 공용 대상 해석 helper | | `plugin-sdk/string-normalization-runtime` | slug/string 정규화 helper | | `plugin-sdk/request-url` | fetch/request 유사 입력에서 문자열 URL 추출 | - | `plugin-sdk/run-command` | 정규화된 stdout/stderr 결과를 포함하는 timed command runner | - | `plugin-sdk/param-readers` | 공통 tool/CLI param reader | - | `plugin-sdk/tool-send` | tool 인수에서 canonical send target 필드 추출 | - | `plugin-sdk/temp-path` | 공통 임시 다운로드 경로 helper | - | `plugin-sdk/logging-core` | subsystem logger 및 redaction helper | - | `plugin-sdk/markdown-table-runtime` | Markdown 테이블 모드 helper | - | `plugin-sdk/json-store` | 소규모 JSON 상태 읽기/쓰기 helper | - | `plugin-sdk/file-lock` | 재진입 가능 파일 잠금 helper | - | `plugin-sdk/persistent-dedupe` | 디스크 기반 dedupe 캐시 helper | + | `plugin-sdk/run-command` | 정규화된 stdout/stderr 결과를 반환하는 시간 제한 command 실행기 | + | `plugin-sdk/param-readers` | 공용 tool/CLI 매개변수 리더 | + | `plugin-sdk/tool-payload` | tool 결과 객체에서 정규화된 payload 추출 | + | `plugin-sdk/tool-send` | tool args에서 정식 send 대상 필드 추출 | + | `plugin-sdk/temp-path` | 공용 임시 다운로드 경로 helper | + | `plugin-sdk/logging-core` | 서브시스템 logger 및 redaction helper | + | `plugin-sdk/markdown-table-runtime` | Markdown 표 모드 helper | + | `plugin-sdk/json-store` | 작은 JSON 상태 읽기/쓰기 helper | + | `plugin-sdk/file-lock` | 재진입 가능한 파일 잠금 helper | + | `plugin-sdk/persistent-dedupe` | 디스크 기반 dedupe cache helper | | `plugin-sdk/acp-runtime` | ACP 런타임/세션 및 reply-dispatch helper | - | `plugin-sdk/agent-config-primitives` | 좁은 범위의 agent 런타임 config-schema primitive | - | `plugin-sdk/boolean-param` | 느슨한 boolean param reader | + | `plugin-sdk/agent-config-primitives` | 좁은 범위의 agent 런타임 config-schema primitives | + | `plugin-sdk/boolean-param` | 느슨한 boolean 매개변수 리더 | | `plugin-sdk/dangerous-name-runtime` | 위험한 이름 매칭 해석 helper | | `plugin-sdk/device-bootstrap` | 디바이스 bootstrap 및 페어링 토큰 helper | - | `plugin-sdk/extension-shared` | 공통 passive-channel, 상태, ambient proxy helper primitive | + | `plugin-sdk/extension-shared` | 공용 passive-channel, 상태, ambient proxy helper primitives | | `plugin-sdk/models-provider-runtime` | `/models` command/provider reply helper | | `plugin-sdk/skill-commands-runtime` | Skills command 목록 helper | - | `plugin-sdk/native-command-registry` | 네이티브 command registry/build/serialize helper | + | `plugin-sdk/native-command-registry` | 네이티브 command 레지스트리/build/serialize helper | | `plugin-sdk/provider-zai-endpoint` | Z.AI endpoint 감지 helper | | `plugin-sdk/infra-runtime` | 시스템 이벤트/heartbeat helper | - | `plugin-sdk/collection-runtime` | 소형 bounded cache helper | + | `plugin-sdk/collection-runtime` | 작은 bounded cache helper | | `plugin-sdk/diagnostic-runtime` | 진단 플래그 및 이벤트 helper | - | `plugin-sdk/error-runtime` | 오류 그래프, formatting, 공통 오류 분류 helper, `isApprovalNotFoundError` | + | `plugin-sdk/error-runtime` | 오류 그래프, 서식 지정, 공용 오류 분류 helper, `isApprovalNotFoundError` | | `plugin-sdk/fetch-runtime` | 래핑된 fetch, proxy, pinned lookup helper | | `plugin-sdk/host-runtime` | 호스트명 및 SCP 호스트 정규화 helper | - | `plugin-sdk/retry-runtime` | retry config 및 retry runner helper | - | `plugin-sdk/agent-runtime` | agent 디렉터리/identity/workspace helper | - | `plugin-sdk/directory-runtime` | config 기반 디렉터리 query/dedup | + | `plugin-sdk/retry-runtime` | Retry config 및 retry 실행 helper | + | `plugin-sdk/agent-runtime` | agent 디렉터리/식별자/워크스페이스 helper | + | `plugin-sdk/directory-runtime` | config 기반 디렉터리 질의/dedup | | `plugin-sdk/keyed-async-queue` | `KeyedAsyncQueue` | - | 하위 경로 | 주요 exports | + | Subpath | 주요 exports | | --- | --- | - | `plugin-sdk/media-runtime` | 공통 미디어 fetch/transform/store helper와 media payload builder | - | `plugin-sdk/media-generation-runtime` | 공통 media-generation failover helper, 후보 선택, 누락된 모델 메시지 처리 | - | `plugin-sdk/media-understanding` | media understanding provider 타입과 provider 대상 이미지/오디오 helper export | - | `plugin-sdk/text-runtime` | assistant-visible-text 제거, Markdown render/chunking/table helper, redaction helper, directive-tag helper, safe-text utility 같은 공통 텍스트/Markdown/로깅 helper | - | `plugin-sdk/text-chunking` | 아웃바운드 텍스트 청킹 helper | - | `plugin-sdk/speech` | speech provider 타입과 provider 대상 directive, registry, validation helper | - | `plugin-sdk/speech-core` | 공통 speech provider 타입, registry, directive, 정규화 helper | - | `plugin-sdk/realtime-transcription` | realtime transcription provider 타입 및 registry helper | - | `plugin-sdk/realtime-voice` | realtime voice provider 타입 및 registry helper | - | `plugin-sdk/image-generation` | image generation provider 타입 | - | `plugin-sdk/image-generation-core` | 공통 image-generation 타입, failover, auth, registry helper | - | `plugin-sdk/music-generation` | music generation provider/request/result 타입 | - | `plugin-sdk/music-generation-core` | 공통 music-generation 타입, failover helper, provider lookup, model-ref 파싱 | - | `plugin-sdk/video-generation` | video generation provider/request/result 타입 | - | `plugin-sdk/video-generation-core` | 공통 video-generation 타입, failover helper, provider lookup, model-ref 파싱 | - | `plugin-sdk/webhook-targets` | webhook 대상 registry 및 route-install helper | - | `plugin-sdk/webhook-path` | webhook 경로 정규화 helper | - | `plugin-sdk/web-media` | 공통 원격/로컬 미디어 로딩 helper | - | `plugin-sdk/zod` | plugin SDK 소비자를 위한 재export된 `zod` | + | `plugin-sdk/media-runtime` | 공용 미디어 fetch/transform/store helper 및 미디어 payload 빌더 | + | `plugin-sdk/media-generation-runtime` | 공용 media-generation failover helper, 후보 선택, 모델 누락 메시지 처리 | + | `plugin-sdk/media-understanding` | Media understanding provider 타입 및 provider용 이미지/오디오 helper export | + | `plugin-sdk/text-runtime` | assistant-visible-text 제거, markdown render/chunking/table helper, redaction helper, directive-tag helper, safe-text 유틸리티 같은 공용 텍스트/markdown/로깅 helper | + | `plugin-sdk/text-chunking` | 송신 텍스트 chunking helper | + | `plugin-sdk/speech` | Speech provider 타입 및 provider용 directive, 레지스트리, 검증 helper | + | `plugin-sdk/speech-core` | 공용 speech provider 타입, 레지스트리, directive, 정규화 helper | + | `plugin-sdk/realtime-transcription` | Realtime transcription provider 타입 및 레지스트리 helper | + | `plugin-sdk/realtime-voice` | Realtime voice provider 타입 및 레지스트리 helper | + | `plugin-sdk/image-generation` | Image generation provider 타입 | + | `plugin-sdk/image-generation-core` | 공용 image-generation 타입, failover, auth, 레지스트리 helper | + | `plugin-sdk/music-generation` | Music generation provider/request/result 타입 | + | `plugin-sdk/music-generation-core` | 공용 music-generation 타입, failover helper, provider 조회, model-ref 파싱 | + | `plugin-sdk/video-generation` | Video generation provider/request/result 타입 | + | `plugin-sdk/video-generation-core` | 공용 video-generation 타입, failover helper, provider 조회, model-ref 파싱 | + | `plugin-sdk/webhook-targets` | Webhook 대상 레지스트리 및 route-install helper | + | `plugin-sdk/webhook-path` | Webhook 경로 정규화 helper | + | `plugin-sdk/web-media` | 공용 원격/로컬 미디어 로딩 helper | + | `plugin-sdk/zod` | Plugin SDK 소비자를 위한 재export된 `zod` | | `plugin-sdk/testing` | `installCommonResolveTargetErrorCases`, `shouldAckReaction` | - - | 하위 경로 | 주요 exports | + + | Subpath | 주요 exports | | --- | --- | | `plugin-sdk/memory-core` | manager/config/file/CLI helper를 위한 번들 memory-core helper 표면 | - | `plugin-sdk/memory-core-engine-runtime` | 메모리 index/search 런타임 facade | - | `plugin-sdk/memory-core-host-engine-foundation` | 메모리 호스트 foundation engine exports | - | `plugin-sdk/memory-core-host-engine-embeddings` | 메모리 호스트 embedding engine exports | - | `plugin-sdk/memory-core-host-engine-qmd` | 메모리 호스트 QMD engine exports | - | `plugin-sdk/memory-core-host-engine-storage` | 메모리 호스트 storage engine exports | - | `plugin-sdk/memory-core-host-multimodal` | 메모리 호스트 multimodal helper | - | `plugin-sdk/memory-core-host-query` | 메모리 호스트 query helper | - | `plugin-sdk/memory-core-host-secret` | 메모리 호스트 secret helper | - | `plugin-sdk/memory-core-host-events` | 메모리 호스트 event journal helper | - | `plugin-sdk/memory-core-host-status` | 메모리 호스트 상태 helper | - | `plugin-sdk/memory-core-host-runtime-cli` | 메모리 호스트 CLI 런타임 helper | - | `plugin-sdk/memory-core-host-runtime-core` | 메모리 호스트 core 런타임 helper | - | `plugin-sdk/memory-core-host-runtime-files` | 메모리 호스트 파일/런타임 helper | - | `plugin-sdk/memory-host-core` | 메모리 호스트 core 런타임 helper를 위한 vendor-neutral 별칭 | - | `plugin-sdk/memory-host-events` | 메모리 호스트 event journal helper를 위한 vendor-neutral 별칭 | - | `plugin-sdk/memory-host-files` | 메모리 호스트 파일/런타임 helper를 위한 vendor-neutral 별칭 | - | `plugin-sdk/memory-host-markdown` | 메모리 인접 plugins용 공통 managed-markdown helper | - | `plugin-sdk/memory-host-search` | search-manager 접근용 활성 메모리 런타임 facade | - | `plugin-sdk/memory-host-status` | 메모리 호스트 상태 helper를 위한 vendor-neutral 별칭 | + | `plugin-sdk/memory-core-engine-runtime` | Memory index/search 런타임 파사드 | + | `plugin-sdk/memory-core-host-engine-foundation` | Memory host foundation engine exports | + | `plugin-sdk/memory-core-host-engine-embeddings` | Memory host embedding engine exports | + | `plugin-sdk/memory-core-host-engine-qmd` | Memory host QMD engine exports | + | `plugin-sdk/memory-core-host-engine-storage` | Memory host storage engine exports | + | `plugin-sdk/memory-core-host-multimodal` | Memory host multimodal helper | + | `plugin-sdk/memory-core-host-query` | Memory host query helper | + | `plugin-sdk/memory-core-host-secret` | Memory host secret helper | + | `plugin-sdk/memory-core-host-events` | Memory host 이벤트 저널 helper | + | `plugin-sdk/memory-core-host-status` | Memory host 상태 helper | + | `plugin-sdk/memory-core-host-runtime-cli` | Memory host CLI 런타임 helper | + | `plugin-sdk/memory-core-host-runtime-core` | Memory host core 런타임 helper | + | `plugin-sdk/memory-core-host-runtime-files` | Memory host 파일/런타임 helper | + | `plugin-sdk/memory-host-core` | 메모리 host core 런타임 helper를 위한 vendor-neutral 별칭 | + | `plugin-sdk/memory-host-events` | 메모리 host 이벤트 저널 helper를 위한 vendor-neutral 별칭 | + | `plugin-sdk/memory-host-files` | 메모리 host 파일/런타임 helper를 위한 vendor-neutral 별칭 | + | `plugin-sdk/memory-host-markdown` | 메모리 인접 plugins를 위한 공용 managed-markdown helper | + | `plugin-sdk/memory-host-search` | search-manager 접근을 위한 활성 메모리 런타임 파사드 | + | `plugin-sdk/memory-host-status` | 메모리 host 상태 helper를 위한 vendor-neutral 별칭 | | `plugin-sdk/memory-lancedb` | 번들 memory-lancedb helper 표면 | - - | 계열 | 현재 하위 경로 | 의도된 용도 | + + | Family | 현재 하위 경로 | 의도된 용도 | | --- | --- | --- | - | Browser | `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` | 번들 browser plugin 지원 helper (`browser-support`는 호환성 barrel로 유지됨) | + | Browser | `plugin-sdk/browser-cdp`, `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-control-auth`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-profiles`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/browser-support` | 번들 browser plugin 지원 helper(`browser-support`는 호환성 barrel로 유지됨) | | Matrix | `plugin-sdk/matrix`, `plugin-sdk/matrix-helper`, `plugin-sdk/matrix-runtime-heavy`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/matrix-runtime-surface`, `plugin-sdk/matrix-surface`, `plugin-sdk/matrix-thread-bindings` | 번들 Matrix helper/런타임 표면 | | Line | `plugin-sdk/line`, `plugin-sdk/line-core`, `plugin-sdk/line-runtime`, `plugin-sdk/line-surface` | 번들 LINE helper/런타임 표면 | | IRC | `plugin-sdk/irc`, `plugin-sdk/irc-surface` | 번들 IRC helper 표면 | - | 채널별 helper | `plugin-sdk/googlechat`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu-conversation`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/tlon`, `plugin-sdk/twitch` | 번들 채널 호환성/helper seam | - | 인증/plugin별 helper | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | 번들 기능/plugin helper seam; `plugin-sdk/github-copilot-token`은 현재 `DEFAULT_COPILOT_API_BASE_URL`, `deriveCopilotApiBaseUrlFromToken`, `resolveCopilotApiToken`을 export함 | + | Channel 전용 helper | `plugin-sdk/googlechat`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu-conversation`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/tlon`, `plugin-sdk/twitch` | 번들 channel 호환성/helper seam | + | Auth/plugin 전용 helper | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | 번들 기능/plugin helper seam; `plugin-sdk/github-copilot-token`은 현재 `DEFAULT_COPILOT_API_BASE_URL`, `deriveCopilotApiBaseUrlFromToken`, `resolveCopilotApiToken`을 export합니다 | -## Registration API +## 등록 API -`register(api)` 콜백은 다음 메서드를 가진 `OpenClawPluginApi` 객체를 받습니다: +`register(api)` 콜백은 다음 메서드를 가진 `OpenClawPluginApi` 객체를 받습니다. ### Capability 등록 -| 메서드 | 등록되는 항목 | -| ------------------------------------------------ | ---------------------------- | -| `api.registerProvider(...)` | 텍스트 추론 (LLM) | -| `api.registerCliBackend(...)` | 로컬 CLI 추론 backend | -| `api.registerChannel(...)` | 메시징 채널 | -| `api.registerSpeechProvider(...)` | 텍스트 음성 변환 / STT 합성 | -| `api.registerRealtimeTranscriptionProvider(...)` | 스트리밍 realtime transcription | -| `api.registerRealtimeVoiceProvider(...)` | 양방향 realtime voice 세션 | -| `api.registerMediaUnderstandingProvider(...)` | 이미지/오디오/비디오 분석 | -| `api.registerImageGenerationProvider(...)` | 이미지 생성 | -| `api.registerMusicGenerationProvider(...)` | 음악 생성 | -| `api.registerVideoGenerationProvider(...)` | 비디오 생성 | -| `api.registerWebFetchProvider(...)` | 웹 fetch / scrape provider | -| `api.registerWebSearchProvider(...)` | 웹 검색 | +| Method | 등록되는 항목 | +| ------------------------------------------------ | -------------------------------- | +| `api.registerProvider(...)` | 텍스트 추론(LLM) | +| `api.registerCliBackend(...)` | 로컬 CLI 추론 backend | +| `api.registerChannel(...)` | 메시징 channel | +| `api.registerSpeechProvider(...)` | 텍스트 음성 변환 / STT 합성 | +| `api.registerRealtimeTranscriptionProvider(...)` | 스트리밍 realtime transcription | +| `api.registerRealtimeVoiceProvider(...)` | 양방향 realtime 음성 세션 | +| `api.registerMediaUnderstandingProvider(...)` | 이미지/오디오/비디오 분석 | +| `api.registerImageGenerationProvider(...)` | 이미지 생성 | +| `api.registerMusicGenerationProvider(...)` | 음악 생성 | +| `api.registerVideoGenerationProvider(...)` | 비디오 생성 | +| `api.registerWebFetchProvider(...)` | 웹 fetch / scrape provider | +| `api.registerWebSearchProvider(...)` | 웹 검색 | -### Tools 및 commands +### 도구 및 commands -| 메서드 | 등록되는 항목 | -| ------------------------------- | -------------------------------------------- | -| `api.registerTool(tool, opts?)` | agent tool (필수 또는 `{ optional: true }`) | -| `api.registerCommand(def)` | custom command (LLM 우회) | +| Method | 등록되는 항목 | +| ------------------------------- | ---------------------------------------------- | +| `api.registerTool(tool, opts?)` | agent 도구(필수 또는 `{ optional: true }`) | +| `api.registerCommand(def)` | 사용자 지정 command(LLM 우회) | ### 인프라 -| 메서드 | 등록되는 항목 | -| ---------------------------------------------- | --------------------------------------- | -| `api.registerHook(events, handler, opts?)` | 이벤트 hook | -| `api.registerHttpRoute(params)` | Gateway HTTP endpoint | -| `api.registerGatewayMethod(name, handler)` | Gateway RPC method | -| `api.registerCli(registrar, opts?)` | CLI 하위 명령 | -| `api.registerService(service)` | 백그라운드 서비스 | -| `api.registerInteractiveHandler(registration)` | interactive handler | -| `api.registerMemoryPromptSupplement(builder)` | 추가형 메모리 인접 prompt 섹션 | -| `api.registerMemoryCorpusSupplement(adapter)` | 추가형 메모리 검색/읽기 corpus | +| Method | 등록되는 항목 | +| ---------------------------------------------- | ---------------------------------------- | +| `api.registerHook(events, handler, opts?)` | 이벤트 hook | +| `api.registerHttpRoute(params)` | Gateway HTTP endpoint | +| `api.registerGatewayMethod(name, handler)` | Gateway RPC 메서드 | +| `api.registerCli(registrar, opts?)` | CLI 하위 명령 | +| `api.registerService(service)` | 백그라운드 서비스 | +| `api.registerInteractiveHandler(registration)` | 대화형 handler | +| `api.registerMemoryPromptSupplement(builder)` | 추가형 memory 인접 프롬프트 섹션 | +| `api.registerMemoryCorpusSupplement(adapter)` | 추가형 memory 검색/읽기 corpus | -예약된 core admin namespace(`config.*`, `exec.approvals.*`, `wizard.*`, -`update.*`)는 plugin이 더 좁은 gateway method 범위를 -할당하려고 해도 항상 `operator.admin`으로 유지됩니다. plugin 소유 method에는 -plugin별 접두사를 사용하는 것이 좋습니다. +예약된 core 관리자 네임스페이스(`config.*`, `exec.approvals.*`, `wizard.*`, `update.*`)는 plugin이 더 좁은 gateway 메서드 범위를 할당하려고 해도 항상 `operator.admin`으로 유지됩니다. plugin 소유 메서드에는 plugin 전용 접두사를 사용하는 것이 좋습니다. ### CLI 등록 메타데이터 -`api.registerCli(registrar, opts?)`는 두 종류의 최상위 메타데이터를 받습니다: +`api.registerCli(registrar, opts?)`는 두 가지 종류의 최상위 메타데이터를 받습니다. -- `commands`: registrar가 소유하는 명시적인 command 루트 -- `descriptors`: 루트 CLI 도움말, - 라우팅, lazy plugin CLI 등록에 사용되는 parse 시점 command descriptor +- `commands`: registrar가 소유한 명시적 command 루트 +- `descriptors`: 루트 CLI help, 라우팅, 지연 plugin CLI 등록에 사용되는 파싱 시점 command descriptor -plugin command가 일반 루트 CLI 경로에서 lazy-loaded 상태로 유지되게 하려면, -해당 registrar가 노출하는 모든 최상위 command 루트를 포괄하는 `descriptors`를 제공하세요. +plugin command를 일반 루트 CLI 경로에서 지연 로드 상태로 유지하려면, 해당 registrar가 노출하는 모든 최상위 command 루트를 포괄하는 `descriptors`를 제공하세요. ```typescript api.registerCli( @@ -366,7 +345,7 @@ api.registerCli( descriptors: [ { name: "matrix", - description: "Matrix 계정, 검증, 디바이스, 프로필 상태 관리", + description: "Matrix 계정, 검증, 디바이스 및 프로필 상태 관리", hasSubcommands: true, }, ], @@ -374,135 +353,107 @@ api.registerCli( ); ``` -일반 루트 CLI 등록에 lazy 로딩이 필요하지 않은 경우에만 `commands`를 단독으로 사용하세요. -이 eager 호환성 경로는 계속 지원되지만, parse 시점 lazy 로딩을 위한 -descriptor 기반 placeholder는 설치하지 않습니다. +지연 루트 CLI 등록이 필요하지 않을 때만 `commands`를 단독으로 사용하세요. 이 eager 호환성 경로는 여전히 지원되지만, 파싱 시점 지연 로드를 위한 descriptor 기반 placeholder는 설치하지 않습니다. ### CLI backend 등록 -`api.registerCliBackend(...)`를 사용하면 plugin이 `codex-cli` 같은 로컬 -AI CLI backend의 기본 config를 소유할 수 있습니다. +`api.registerCliBackend(...)`를 사용하면 plugin이 `codex-cli` 같은 로컬 AI CLI backend의 기본 config를 소유할 수 있습니다. - backend `id`는 `codex-cli/gpt-5` 같은 model ref의 provider 접두사가 됩니다. -- backend `config`는 `agents.defaults.cliBackends.`와 같은 형태를 사용합니다. -- 사용자 config가 여전히 우선합니다. OpenClaw는 CLI를 실행하기 전에 - `agents.defaults.cliBackends.`를 plugin 기본값 위에 병합합니다. -- backend가 병합 후 호환성 재작성 작업을 필요로 하는 경우 - (예: 오래된 플래그 형태 정규화) `normalizeConfig`를 사용하세요. +- backend `config`는 `agents.defaults.cliBackends.`와 동일한 형태를 사용합니다. +- 사용자 config가 여전히 우선합니다. OpenClaw는 CLI를 실행하기 전에 plugin 기본값 위에 `agents.defaults.cliBackends.`를 병합합니다. +- 병합 후 backend에 호환성 재작성(예: 이전 플래그 형태 정규화)이 필요하다면 `normalizeConfig`를 사용하세요. -### 독점 슬롯 +### 배타적 슬롯 -| 메서드 | 등록되는 항목 | -| ------------------------------------------ | ------------------------------------- | -| `api.registerContextEngine(id, factory)` | 컨텍스트 엔진 (한 번에 하나만 활성) | -| `api.registerMemoryCapability(capability)` | 통합 메모리 capability | -| `api.registerMemoryPromptSection(builder)` | 메모리 prompt 섹션 builder | -| `api.registerMemoryFlushPlan(resolver)` | 메모리 flush plan resolver | -| `api.registerMemoryRuntime(runtime)` | 메모리 런타임 adapter | +| Method | 등록되는 항목 | +| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `api.registerContextEngine(id, factory)` | 컨텍스트 엔진(한 번에 하나만 활성). `assemble()` 콜백은 `availableTools`와 `citationsMode`를 받아 엔진이 프롬프트 추가 내용을 맞춤 조정할 수 있게 합니다. | +| `api.registerMemoryCapability(capability)` | 통합 memory capability | +| `api.registerMemoryPromptSection(builder)` | Memory 프롬프트 섹션 빌더 | +| `api.registerMemoryFlushPlan(resolver)` | Memory flush plan resolver | +| `api.registerMemoryRuntime(runtime)` | Memory 런타임 adapter | -### 메모리 임베딩 adapter +### Memory embedding adapters -| 메서드 | 등록되는 항목 | +| Method | 등록되는 항목 | | ---------------------------------------------- | -------------------------------------------------- | -| `api.registerMemoryEmbeddingProvider(adapter)` | 활성 plugin용 메모리 임베딩 adapter | +| `api.registerMemoryEmbeddingProvider(adapter)` | 활성 plugin용 memory embedding adapter | -- `registerMemoryCapability`가 권장되는 독점 메모리 plugin API입니다. -- `registerMemoryCapability`는 companion plugins가 특정 - 메모리 plugin의 비공개 레이아웃에 접근하지 않고 - `openclaw/plugin-sdk/memory-host-core`를 통해 export된 메모리 artifact를 소비할 수 있도록 - `publicArtifacts.listArtifacts(...)`도 노출할 수 있습니다. -- `registerMemoryPromptSection`, `registerMemoryFlushPlan`, - `registerMemoryRuntime`는 레거시 호환용 독점 메모리 plugin API입니다. -- `registerMemoryEmbeddingProvider`를 사용하면 활성 메모리 plugin이 - 하나 이상의 임베딩 adapter id(예: `openai`, `gemini`, 또는 사용자 정의 - plugin 정의 id)를 등록할 수 있습니다. -- `agents.defaults.memorySearch.provider`, - `agents.defaults.memorySearch.fallback` 같은 사용자 config는 - 등록된 adapter id를 기준으로 해석됩니다. +- `registerMemoryCapability`가 권장되는 배타적 memory-plugin API입니다. +- `registerMemoryCapability`는 companion plugins가 특정 memory plugin의 private 레이아웃에 직접 접근하지 않고 `openclaw/plugin-sdk/memory-host-core`를 통해 export된 memory artifact를 사용할 수 있도록 `publicArtifacts.listArtifacts(...)`도 노출할 수 있습니다. +- `registerMemoryPromptSection`, `registerMemoryFlushPlan`, `registerMemoryRuntime`는 레거시 호환용 배타적 memory-plugin API입니다. +- `registerMemoryEmbeddingProvider`를 사용하면 활성 memory plugin이 하나 이상의 embedding adapter id(예: `openai`, `gemini`, 또는 plugin이 정의한 사용자 지정 id)를 등록할 수 있습니다. +- `agents.defaults.memorySearch.provider` 및 `agents.defaults.memorySearch.fallback` 같은 사용자 config는 이러한 등록된 adapter id를 기준으로 해석됩니다. -### 이벤트 및 수명 주기 +### 이벤트 및 lifecycle -| 메서드 | 수행하는 작업 | -| -------------------------------------------- | -------------------------- | -| `api.on(hookName, handler, opts?)` | 타입 지정 lifecycle hook | -| `api.onConversationBindingResolved(handler)` | 대화 바인딩 콜백 | +| Method | 동작 | +| -------------------------------------------- | ---------------------------- | +| `api.on(hookName, handler, opts?)` | 타입 지정된 lifecycle hook | +| `api.onConversationBindingResolved(handler)` | 대화 바인딩 콜백 | ### Hook 결정 의미 -- `before_tool_call`: `{ block: true }`를 반환하면 최종 결정입니다. 어떤 handler든 이를 설정하면 더 낮은 우선순위 handler는 건너뜁니다. -- `before_tool_call`: `{ block: false }`를 반환하면 결정 없음으로 처리됩니다(`block`을 생략한 것과 동일). override로 처리되지 않습니다. -- `before_install`: `{ block: true }`를 반환하면 최종 결정입니다. 어떤 handler든 이를 설정하면 더 낮은 우선순위 handler는 건너뜁니다. -- `before_install`: `{ block: false }`를 반환하면 결정 없음으로 처리됩니다(`block`을 생략한 것과 동일). override로 처리되지 않습니다. -- `reply_dispatch`: `{ handled: true, ... }`를 반환하면 최종 결정입니다. 어떤 handler든 디스패치를 가져가면 더 낮은 우선순위 handler와 기본 모델 디스패치 경로는 건너뜁니다. -- `message_sending`: `{ cancel: true }`를 반환하면 최종 결정입니다. 어떤 handler든 이를 설정하면 더 낮은 우선순위 handler는 건너뜁니다. -- `message_sending`: `{ cancel: false }`를 반환하면 결정 없음으로 처리됩니다(`cancel`을 생략한 것과 동일). override로 처리되지 않습니다. +- `before_tool_call`: `{ block: true }`를 반환하면 종료됩니다. 어떤 handler든 이를 설정하면 더 낮은 우선순위 handler는 건너뜁니다. +- `before_tool_call`: `{ block: false }`를 반환하면 결정 없음(`block` 생략과 동일)으로 처리되며, override가 아닙니다. +- `before_install`: `{ block: true }`를 반환하면 종료됩니다. 어떤 handler든 이를 설정하면 더 낮은 우선순위 handler는 건너뜁니다. +- `before_install`: `{ block: false }`를 반환하면 결정 없음(`block` 생략과 동일)으로 처리되며, override가 아닙니다. +- `reply_dispatch`: `{ handled: true, ... }`를 반환하면 종료됩니다. 어떤 handler든 dispatch를 처리했다고 선언하면 더 낮은 우선순위 handler와 기본 모델 dispatch 경로를 건너뜁니다. +- `message_sending`: `{ cancel: true }`를 반환하면 종료됩니다. 어떤 handler든 이를 설정하면 더 낮은 우선순위 handler는 건너뜁니다. +- `message_sending`: `{ cancel: false }`를 반환하면 결정 없음(`cancel` 생략과 동일)으로 처리되며, override가 아닙니다. ### API 객체 필드 -| 필드 | 타입 | 설명 | -| ------------------------ | ------------------------- | ------------------------------------------------------------------------------------ | -| `api.id` | `string` | Plugin id | -| `api.name` | `string` | 표시 이름 | -| `api.version` | `string?` | Plugin 버전 (선택 사항) | -| `api.description` | `string?` | Plugin 설명 (선택 사항) | -| `api.source` | `string` | Plugin 소스 경로 | -| `api.rootDir` | `string?` | Plugin 루트 디렉터리 (선택 사항) | -| `api.config` | `OpenClawConfig` | 현재 config snapshot (가능한 경우 활성 메모리 내 런타임 snapshot) | -| `api.pluginConfig` | `Record` | `plugins.entries..config`의 plugin별 config | -| `api.runtime` | `PluginRuntime` | [Runtime helpers](/ko/plugins/sdk-runtime) | -| `api.logger` | `PluginLogger` | 범위 지정 logger (`debug`, `info`, `warn`, `error`) | -| `api.registrationMode` | `PluginRegistrationMode` | 현재 로드 모드; `"setup-runtime"`은 전체 entry 이전의 경량 시작/setup 구간입니다 | -| `api.resolvePath(input)` | `(string) => string` | plugin 루트를 기준으로 경로 해석 | +| Field | Type | 설명 | +| ------------------------ | ------------------------- | -------------------------------------------------------------------------------------------- | +| `api.id` | `string` | Plugin id | +| `api.name` | `string` | 표시 이름 | +| `api.version` | `string?` | Plugin 버전(선택 사항) | +| `api.description` | `string?` | Plugin 설명(선택 사항) | +| `api.source` | `string` | Plugin 소스 경로 | +| `api.rootDir` | `string?` | Plugin 루트 디렉터리(선택 사항) | +| `api.config` | `OpenClawConfig` | 현재 config 스냅샷(사용 가능할 경우 활성 in-memory 런타임 스냅샷) | +| `api.pluginConfig` | `Record` | `plugins.entries..config`의 plugin 전용 config | +| `api.runtime` | `PluginRuntime` | [Runtime helpers](/ko/plugins/sdk-runtime) | +| `api.logger` | `PluginLogger` | 범위가 지정된 logger(`debug`, `info`, `warn`, `error`) | +| `api.registrationMode` | `PluginRegistrationMode` | 현재 로드 모드. `"setup-runtime"`은 가벼운 전체 entry 이전 시작/setup 구간입니다 | +| `api.resolvePath(input)` | `(string) => string` | plugin 루트를 기준으로 경로 해석 | ## 내부 모듈 규칙 -plugin 내부에서는 내부 import에 로컬 barrel 파일을 사용하세요: +plugin 내부에서는 내부 import에 로컬 barrel 파일을 사용하세요. ``` my-plugin/ - api.ts # 외부 소비자를 위한 공개 exports + api.ts # 외부 소비자를 위한 public exports runtime-api.ts # 내부 전용 런타임 exports index.ts # Plugin entry point - setup-entry.ts # 경량 setup 전용 entry (선택 사항) + setup-entry.ts # 가벼운 setup 전용 entry(선택 사항) ``` - 프로덕션 코드에서 자신의 plugin을 `openclaw/plugin-sdk/`을 통해 - import하지 마세요. 내부 import는 `./api.ts` 또는 - `./runtime-api.ts`를 통해 처리하세요. SDK 경로는 외부 계약 전용입니다. + 프로덕션 코드에서 `openclaw/plugin-sdk/`을 통해 자신의 plugin을 절대 import하지 마세요. 내부 import는 `./api.ts` 또는 `./runtime-api.ts`를 통해 처리하세요. SDK 경로는 외부 계약 전용입니다. -Facade로 로드되는 번들 plugin 공개 표면(`api.ts`, `runtime-api.ts`, -`index.ts`, `setup-entry.ts`, 및 유사한 공개 entry 파일)은 이제 -OpenClaw가 이미 실행 중인 경우 활성 런타임 config snapshot을 우선 사용합니다. 아직 런타임 -snapshot이 없으면, 디스크에서 해석된 config 파일로 대체합니다. +파사드로 로드되는 번들 plugin public 표면(`api.ts`, `runtime-api.ts`, `index.ts`, `setup-entry.ts` 및 유사한 public entry 파일)은 이제 OpenClaw가 이미 실행 중일 때 활성 런타임 config 스냅샷을 우선 사용합니다. 아직 런타임 스냅샷이 없으면 디스크의 해석된 config 파일로 폴백합니다. -Provider plugins는 helper가 의도적으로 provider 전용이며 아직 generic SDK -하위 경로에 속하지 않을 때, 좁은 범위의 plugin 로컬 계약 barrel을 노출할 수도 있습니다. 현재 번들 예시: -Anthropic provider는 Anthropic beta-header와 `service_tier` 로직을 generic -`plugin-sdk/*` 계약으로 승격하는 대신 자체 공개 `api.ts` / `contract-api.ts` seam에 -Claude stream helper를 유지합니다. +Provider plugins는 helper가 의도적으로 provider 전용이고 아직 일반적인 SDK 하위 경로에 속하지 않을 경우 좁은 범위의 plugin 로컬 계약 barrel도 노출할 수 있습니다. 현재 번들 예시: Anthropic provider는 Anthropic 베타 헤더와 `service_tier` 로직을 일반적인 `plugin-sdk/*` 계약으로 올리는 대신 Claude stream helper를 자체 public `api.ts` / `contract-api.ts` seam에 유지합니다. -기타 현재 번들 예시: +그 밖의 현재 번들 예시: -- `@openclaw/openai-provider`: `api.ts`는 provider builder, - default-model helper, realtime provider builder를 export합니다 -- `@openclaw/openrouter-provider`: `api.ts`는 provider builder와 - onboarding/config helper를 export합니다 +- `@openclaw/openai-provider`: `api.ts`는 provider 빌더, 기본 model helper, realtime provider 빌더를 export합니다 +- `@openclaw/openrouter-provider`: `api.ts`는 provider 빌더와 onboarding/config helper를 export합니다 - extension 프로덕션 코드도 `openclaw/plugin-sdk/` - import를 피해야 합니다. helper가 진정으로 공유되어야 한다면, - 두 plugins를 결합시키는 대신 - `openclaw/plugin-sdk/speech`, `.../provider-model-shared`, 또는 다른 - capability 지향 표면 같은 중립적인 SDK 하위 경로로 승격하세요. + 확장 프로덕션 코드도 `openclaw/plugin-sdk/` import를 피해야 합니다. helper가 정말 공용이어야 한다면 두 plugins를 결합하는 대신 `openclaw/plugin-sdk/speech`, `.../provider-model-shared` 또는 다른 capability 지향 표면 같은 중립적인 SDK 하위 경로로 승격하세요. -## 관련 항목 +## 관련 문서 - [Entry Points](/ko/plugins/sdk-entrypoints) — `definePluginEntry` 및 `defineChannelPluginEntry` 옵션 -- [Runtime Helpers](/ko/plugins/sdk-runtime) — 전체 `api.runtime` namespace 참조 -- [Setup and Config](/ko/plugins/sdk-setup) — 패키징, manifest, config 스키마 +- [Runtime Helpers](/ko/plugins/sdk-runtime) — 전체 `api.runtime` 네임스페이스 참조 +- [Setup and Config](/ko/plugins/sdk-setup) — 패키징, 매니페스트, config 스키마 - [Testing](/ko/plugins/sdk-testing) — 테스트 유틸리티 및 lint 규칙 -- [SDK Migration](/ko/plugins/sdk-migration) — deprecated 표면에서 마이그레이션 -- [Plugin Internals](/ko/plugins/architecture) — 심층 아키텍처 및 capability 모델 +- [SDK Migration](/ko/plugins/sdk-migration) — 더 이상 권장되지 않는 표면에서 마이그레이션 +- [Plugin Internals](/ko/plugins/architecture) — 심화 아키텍처 및 capability 모델 diff --git a/docs/ko/plugins/sdk-provider-plugins.md b/docs/ko/plugins/sdk-provider-plugins.md index 4290a49a5..56a2c2336 100644 --- a/docs/ko/plugins/sdk-provider-plugins.md +++ b/docs/ko/plugins/sdk-provider-plugins.md @@ -1,33 +1,33 @@ --- read_when: - 새 모델 제공자 플러그인을 구축하고 있습니다 - - OpenAI 호환 프록시 또는 사용자 지정 LLM을 OpenClaw에 추가하려고 합니다 - - 제공자 인증, 카탈로그, 런타임 훅을 이해해야 합니다 + - OpenAI 호환 프록시나 커스텀 LLM을 OpenClaw에 추가하려고 합니다 + - 제공자 인증, 카탈로그, 런타임 hook을 이해해야 합니다 sidebarTitle: Provider Plugins summary: OpenClaw용 모델 제공자 플러그인을 구축하는 단계별 가이드 title: 제공자 플러그인 구축하기 x-i18n: - generated_at: "2026-04-07T06:02:12Z" + generated_at: "2026-04-09T01:31:20Z" model: gpt-5.4 provider: openai - source_hash: 4da82a353e1bf4fe6dc09e14b8614133ac96565679627de51415926014bd3990 + source_hash: 38d9af522dc19e49c81203a83a4096f01c2398b1df771c848a30ad98f251e9e1 source_path: plugins/sdk-provider-plugins.md workflow: 15 --- # 제공자 플러그인 구축하기 -이 가이드는 OpenClaw에 모델 제공자(LLM)를 추가하는 제공자 플러그인을 -구축하는 과정을 안내합니다. 이 과정을 마치면 모델 카탈로그, +이 가이드는 OpenClaw에 모델 제공자 +(LLM)를 추가하는 제공자 플러그인을 구축하는 과정을 설명합니다. 끝까지 따라가면 모델 카탈로그, API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니다. - 아직 OpenClaw 플러그인을 한 번도 만들어본 적이 없다면, - 먼저 [시작하기](/ko/plugins/building-plugins)를 읽고 기본 패키지 구조와 - 매니페스트 설정을 확인하세요. + 아직 OpenClaw 플러그인을 한 번도 만들어 본 적이 없다면, + 먼저 [시작하기](/ko/plugins/building-plugins)를 읽고 기본 패키지 + 구조와 매니페스트 설정을 확인하세요. -## 단계별 안내 +## 따라 하기 @@ -65,6 +65,9 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 "providerAuthEnvVars": { "acme-ai": ["ACME_AI_API_KEY"] }, + "providerAuthAliases": { + "acme-ai-coding": "acme-ai" + }, "providerAuthChoices": [ { "provider": "acme-ai", @@ -86,13 +89,12 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 ``` - 매니페스트는 `providerAuthEnvVars`를 선언하여 OpenClaw가 - 플러그인 런타임을 로드하지 않고도 자격 증명을 감지할 수 있게 합니다. - `modelSupport`는 선택 사항이며, 런타임 훅이 존재하기 전에도 - `acme-large` 같은 축약형 모델 id로부터 OpenClaw가 제공자 플러그인을 - 자동 로드할 수 있게 합니다. 제공자를 ClawHub에 게시하는 경우, - `package.json`의 `openclaw.compat`와 `openclaw.build` 필드는 - 필수입니다. + 매니페스트는 `providerAuthEnvVars`를 선언하므로 OpenClaw가 + 플러그인 런타임을 로드하지 않고도 자격 증명을 감지할 수 있습니다. 제공자 변형이 다른 제공자 id의 인증을 재사용해야 하는 경우 + `providerAuthAliases`를 추가하세요. `modelSupport`는 선택 사항이며, 런타임 hook이 생기기 전에 + `acme-large` 같은 축약형 모델 id에서 OpenClaw가 제공자 플러그인을 자동 로드하도록 해줍니다. + 제공자를 ClawHub에 게시하는 경우 `package.json`의 + `openclaw.compat` 및 `openclaw.build` 필드는 필수입니다. @@ -168,12 +170,12 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 }); ``` - 이것만으로 동작하는 제공자가 됩니다. 이제 사용자는 + 이것으로 동작하는 제공자가 완성됩니다. 이제 사용자는 `openclaw onboard --acme-ai-api-key `를 실행하고 - `acme-ai/acme-large`를 모델로 선택할 수 있습니다. + 모델로 `acme-ai/acme-large`를 선택할 수 있습니다. - API 키 인증과 단일 카탈로그 기반 런타임만 등록하는 텍스트 제공자 하나로 - 구성된 번들 제공자의 경우, 더 좁은 범위의 + API 키 인증이 있는 텍스트 제공자 하나와 카탈로그 기반 런타임 하나만 등록하는 번들 제공자의 경우, + 더 좁은 범위의 `defineSingleProviderPluginEntry(...)` 헬퍼를 사용하는 것이 좋습니다: ```typescript @@ -209,26 +211,24 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 }); ``` - 인증 흐름이 온보딩 중에 `models.providers.*`, 별칭, 에이전트 기본 모델까지 - 함께 패치해야 한다면 - `openclaw/plugin-sdk/provider-onboard`의 프리셋 헬퍼를 사용하세요. - 가장 좁은 범위의 헬퍼는 + 인증 흐름이 온보딩 중 `models.providers.*`, 별칭, 에이전트 기본 모델도 함께 수정해야 한다면 + `openclaw/plugin-sdk/provider-onboard`의 프리셋 헬퍼를 사용하세요. 가장 범위가 좁은 헬퍼는 `createDefaultModelPresetAppliers(...)`, - `createDefaultModelsPresetAppliers(...)`, + `createDefaultModelsPresetAppliers(...)`, 그리고 `createModelCatalogPresetAppliers(...)`입니다. - 제공자의 네이티브 엔드포인트가 일반 `openai-completions` 전송에서 - 스트리밍 사용량 블록을 지원하는 경우, 제공자 id 검사 코드를 하드코딩하는 대신 - `openclaw/plugin-sdk/provider-catalog-shared`의 공용 카탈로그 헬퍼를 - 사용하는 것이 좋습니다. `supportsNativeStreamingUsageCompat(...)`와 - `applyProviderNativeStreamingUsageCompat(...)`는 엔드포인트 기능 맵에서 - 지원 여부를 감지하므로, 사용자 지정 제공자 id를 사용하는 플러그인이라도 - 네이티브 Moonshot/DashScope 스타일 엔드포인트는 여전히 옵트인할 수 있습니다. + 제공자의 네이티브 엔드포인트가 일반 `openai-completions` 전송에서 스트리밍된 사용량 블록을 지원한다면, + 제공자 id 검사를 하드코딩하는 대신 + `openclaw/plugin-sdk/provider-catalog-shared`의 공유 카탈로그 헬퍼를 사용하는 것이 좋습니다. + `supportsNativeStreamingUsageCompat(...)`와 + `applyProviderNativeStreamingUsageCompat(...)`는 엔드포인트 capability 맵에서 지원 여부를 감지하므로, + 플러그인이 커스텀 제공자 id를 사용하더라도 네이티브 Moonshot/DashScope 스타일 엔드포인트를 계속 + opt in할 수 있습니다. - 제공자가 임의의 모델 ID(프록시나 라우터처럼)를 허용하는 경우, + 제공자가 프록시나 라우터처럼 임의의 모델 ID를 허용한다면 `resolveDynamicModel`을 추가하세요: ```typescript @@ -251,17 +251,16 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 ``` 해석에 네트워크 호출이 필요하다면 비동기 워밍업을 위해 - `prepareDynamicModel`을 사용하세요. 완료 후 `resolveDynamicModel`이 - 다시 실행됩니다. + `prepareDynamicModel`을 사용하세요. 완료되면 `resolveDynamicModel`이 다시 실행됩니다. - - 대부분의 제공자는 `catalog`와 `resolveDynamicModel`만 필요합니다. - 제공자에 필요한 만큼 훅을 점진적으로 추가하세요. + + 대부분의 제공자는 `catalog` + `resolveDynamicModel`만 있으면 됩니다. 제공자에 필요해질 때만 + 점진적으로 hook을 추가하세요. - 이제 공용 헬퍼 빌더가 가장 흔한 replay/tool-compat 계열을 다루므로, - 플러그인은 보통 각 훅을 하나씩 직접 연결할 필요가 없습니다: + 이제 공유 헬퍼 빌더가 가장 일반적인 replay/tool-compat + 계열을 다루므로, 보통 플러그인에서 각 hook을 하나씩 직접 연결할 필요가 없습니다: ```typescript import { buildProviderReplayFamilyHooks } from "openclaw/plugin-sdk/provider-model-shared"; @@ -283,113 +282,115 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 현재 사용 가능한 replay 계열: - | 계열 | 연결되는 항목 | + | Family | 연결되는 항목 | | --- | --- | - | `openai-compatible` | OpenAI 호환 전송을 위한 공용 OpenAI 스타일 replay 정책. tool-call-id 정리, assistant-first 순서 수정, 그리고 전송 계층에서 필요할 때의 일반적인 Gemini 턴 검증을 포함합니다 | - | `anthropic-by-model` | `modelId`로 선택되는 Claude 인지 replay 정책. Anthropic 메시지 전송은 해석된 모델이 실제 Claude id일 때만 Claude 전용 thinking 블록 정리를 적용합니다 | - | `google-gemini` | 네이티브 Gemini replay 정책과 bootstrap replay 정리, 태그된 reasoning-output 모드 | - | `passthrough-gemini` | OpenAI 호환 프록시 전송을 통해 실행되는 Gemini 모델용 Gemini thought-signature 정리. 네이티브 Gemini replay 검증이나 bootstrap 재작성은 활성화하지 않습니다 | - | `hybrid-anthropic-openai` | 하나의 플러그인에서 Anthropic 메시지와 OpenAI 호환 모델 표면을 함께 제공하는 제공자를 위한 하이브리드 정책. 선택적인 Claude 전용 thinking 블록 제거는 Anthropic 쪽에만 한정됩니다 | + | `openai-compatible` | 도구 호출 ID 정리, assistant-first 순서 수정, 전송에 필요할 때의 일반 Gemini 턴 검증을 포함한 공유 OpenAI 스타일 replay 정책 | + | `anthropic-by-model` | `modelId`로 선택되는 Claude 인식 replay 정책으로, Anthropic-message 전송이 실제 해석된 모델이 Claude id일 때만 Claude 전용 thinking 블록 정리를 받도록 함 | + | `google-gemini` | 네이티브 Gemini replay 정책, bootstrap replay 정리, 태그형 추론 출력 모드 | + | `passthrough-gemini` | OpenAI 호환 프록시 전송을 통해 실행되는 Gemini 모델의 Gemini thought-signature 정리; 네이티브 Gemini replay 검증이나 bootstrap 재작성을 활성화하지 않음 | + | `hybrid-anthropic-openai` | 하나의 플러그인 안에서 Anthropic-message와 OpenAI 호환 모델 표면을 혼합하는 제공자를 위한 하이브리드 정책; 선택적인 Claude 전용 thinking 블록 제거는 Anthropic 쪽에만 한정됨 | 실제 번들 예시: - - `google`, `google-gemini-cli`: `google-gemini` + - `google` 및 `google-gemini-cli`: `google-gemini` - `openrouter`, `kilocode`, `opencode`, `opencode-go`: `passthrough-gemini` - - `amazon-bedrock`, `anthropic-vertex`: `anthropic-by-model` + - `amazon-bedrock` 및 `anthropic-vertex`: `anthropic-by-model` - `minimax`: `hybrid-anthropic-openai` - `moonshot`, `ollama`, `xai`, `zai`: `openai-compatible` - 현재 사용 가능한 스트림 계열: + 현재 사용 가능한 stream 계열: - | 계열 | 연결되는 항목 | + | Family | 연결되는 항목 | | --- | --- | - | `google-thinking` | 공용 스트림 경로에서의 Gemini thinking 페이로드 정규화 | - | `kilocode-thinking` | 공용 프록시 스트림 경로에서의 Kilo reasoning 래퍼. `kilo/auto`와 지원되지 않는 프록시 reasoning id는 주입된 thinking을 건너뜁니다 | - | `moonshot-thinking` | 설정 + `/think` 수준에서의 Moonshot 바이너리 native-thinking 페이로드 매핑 | - | `minimax-fast-mode` | 공용 스트림 경로에서의 MiniMax fast-mode 모델 재작성 | - | `openai-responses-defaults` | 공용 네이티브 OpenAI/Codex Responses 래퍼: attribution 헤더, `/fast`/`serviceTier`, 텍스트 verbosity, 네이티브 Codex 웹 검색, reasoning-compat 페이로드 형성, Responses 컨텍스트 관리 | - | `openrouter-thinking` | 프록시 라우트용 OpenRouter reasoning 래퍼. 지원되지 않는 모델과 `auto` 건너뛰기를 중앙에서 처리합니다 | - | `tool-stream-default-on` | Z.AI 같은 제공자를 위한 기본 활성화 `tool_stream` 래퍼. 명시적으로 비활성화하지 않는 한 tool streaming을 사용합니다 | + | `google-thinking` | 공유 stream 경로에서 Gemini thinking 페이로드 정규화 | + | `kilocode-thinking` | 공유 프록시 stream 경로에서 Kilo 추론 래퍼를 적용하며, `kilo/auto`와 지원되지 않는 프록시 추론 id는 주입된 thinking을 건너뜀 | + | `moonshot-thinking` | config + `/think` 수준에서 Moonshot 이진 네이티브 thinking 페이로드 매핑 | + | `minimax-fast-mode` | 공유 stream 경로에서 MiniMax fast-mode 모델 재작성 | + | `openai-responses-defaults` | 공유 네이티브 OpenAI/Codex Responses 래퍼: attribution 헤더, `/fast`/`serviceTier`, 텍스트 verbosity, 네이티브 Codex 웹 검색, 추론 호환 페이로드 형성, Responses 컨텍스트 관리 | + | `openrouter-thinking` | 프록시 경로를 위한 OpenRouter 추론 래퍼로, 지원되지 않는 모델/`auto` 건너뛰기를 중앙에서 처리 | + | `tool-stream-default-on` | Z.AI 같은 제공자를 위한 기본 활성화 `tool_stream` 래퍼로, 명시적으로 비활성화되지 않는 한 도구 스트리밍을 사용함 | 실제 번들 예시: - - `google`, `google-gemini-cli`: `google-thinking` + - `google` 및 `google-gemini-cli`: `google-thinking` - `kilocode`: `kilocode-thinking` - `moonshot`: `moonshot-thinking` - - `minimax`, `minimax-portal`: `minimax-fast-mode` - - `openai`, `openai-codex`: `openai-responses-defaults` + - `minimax` 및 `minimax-portal`: `minimax-fast-mode` + - `openai` 및 `openai-codex`: `openai-responses-defaults` - `openrouter`: `openrouter-thinking` - `zai`: `tool-stream-default-on` - `openclaw/plugin-sdk/provider-model-shared`는 replay 계열 enum과 - 해당 계열이 기반으로 하는 공용 헬퍼도 내보냅니다. 일반적인 공개 export는 - 다음과 같습니다: + `openclaw/plugin-sdk/provider-model-shared`는 replay-family + enum과 해당 계열이 기반으로 하는 공유 헬퍼도 내보냅니다. 일반적인 공개 export에는 다음이 포함됩니다: - `ProviderReplayFamily` - `buildProviderReplayFamilyHooks(...)` - `buildOpenAICompatibleReplayPolicy(...)`, `buildAnthropicReplayPolicyForModel(...)`, - `buildGoogleGeminiReplayPolicy(...)`, - `buildHybridAnthropicOrOpenAIReplayPolicy(...)` 같은 공용 replay 빌더 - - `sanitizeGoogleGeminiReplayHistory(...)`, - `resolveTaggedReasoningOutputMode()` 같은 Gemini replay 헬퍼 + `buildGoogleGeminiReplayPolicy(...)`, 그리고 + `buildHybridAnthropicOrOpenAIReplayPolicy(...)` 같은 공유 replay 빌더 + - `sanitizeGoogleGeminiReplayHistory(...)` + 및 `resolveTaggedReasoningOutputMode()` 같은 Gemini replay 헬퍼 - `resolveProviderEndpoint(...)`, - `normalizeProviderId(...)`, `normalizeGooglePreviewModelId(...)`, + `normalizeProviderId(...)`, `normalizeGooglePreviewModelId(...)`, 그리고 `normalizeNativeXaiModelId(...)` 같은 엔드포인트/모델 헬퍼 - `openclaw/plugin-sdk/provider-stream`는 계열 빌더와 해당 계열이 재사용하는 - 공개 래퍼 헬퍼를 모두 노출합니다. 일반적인 공개 export는 - 다음과 같습니다: + `openclaw/plugin-sdk/provider-stream`은 family 빌더와 + 해당 family가 재사용하는 공개 래퍼 헬퍼를 모두 제공합니다. 일반적인 공개 export에는 다음이 포함됩니다: - `ProviderStreamFamily` - `buildProviderStreamFamilyHooks(...)` - `composeProviderStreamWrappers(...)` - - `createOpenAIAttributionHeadersWrapper(...)`, + - 다음과 같은 공유 OpenAI/Codex 래퍼: + `createOpenAIAttributionHeadersWrapper(...)`, `createOpenAIFastModeWrapper(...)`, `createOpenAIServiceTierWrapper(...)`, - `createOpenAIResponsesContextManagementWrapper(...)`, - `createCodexNativeWebSearchWrapper(...)` 같은 공용 OpenAI/Codex 래퍼 + `createOpenAIResponsesContextManagementWrapper(...)`, 그리고 + `createCodexNativeWebSearchWrapper(...)` - `createOpenRouterWrapper(...)`, `createToolStreamWrapper(...)`, `createMinimaxFastModeWrapper(...)` 같은 - 공용 프록시/제공자 래퍼 + 공유 프록시/제공자 래퍼 - 일부 스트림 헬퍼는 의도적으로 제공자 로컬에 유지됩니다. 현재 번들 예시로 - `@openclaw/anthropic-provider`는 공개 `api.ts` / - `contract-api.ts` 경계에서 `wrapAnthropicProviderStream`, - `resolveAnthropicBetas`, `resolveAnthropicFastMode`, - `resolveAnthropicServiceTier`, 그리고 더 낮은 수준의 Anthropic 래퍼 빌더를 - export합니다. 이 헬퍼들은 Claude OAuth 베타 처리와 `context1m` 게이팅도 - 인코딩하기 때문에 Anthropic 전용으로 남아 있습니다. + 일부 stream 헬퍼는 의도적으로 provider-local로 유지됩니다. 현재 번들 + 예시: `@openclaw/anthropic-provider`는 + 공개 `api.ts` / + `contract-api.ts` 경계에서 `wrapAnthropicProviderStream`, `resolveAnthropicBetas`, + `resolveAnthropicFastMode`, `resolveAnthropicServiceTier`, 그리고 + 더 낮은 수준의 Anthropic 래퍼 빌더를 export합니다. 이 헬퍼들은 + Claude OAuth 베타 처리와 `context1m` 게이팅도 함께 인코딩하므로 + Anthropic 전용으로 유지됩니다. - 다른 번들 제공자들도 동작을 계열 전반에 깔끔하게 공유하기 어려운 경우 - 전송 계층별 래퍼를 로컬에 유지합니다. 현재 예시로 번들 xAI 플러그인은 - 네이티브 xAI Responses 형성을 자체 `wrapStreamFn` 안에 유지하며, - 여기에는 `/fast` 별칭 재작성, 기본 `tool_stream`, - 지원되지 않는 strict-tool 정리, xAI 전용 reasoning 페이로드 제거가 - 포함됩니다. + 다른 번들 제공자들도 동작이 계열 전체에 깔끔하게 공유되지 않는 경우 + 전송 전용 래퍼를 로컬에 유지합니다. 현재 예시: 번들 xAI 플러그인은 + 네이티브 xAI Responses 형성을 자체 + `wrapStreamFn` 안에 유지하며, 여기에는 `/fast` 별칭 재작성, 기본 `tool_stream`, + 지원되지 않는 strict-tool 정리, xAI 전용 추론 페이로드 + 제거가 포함됩니다. - `openclaw/plugin-sdk/provider-tools`는 현재 하나의 공용 도구 스키마 계열과 - 공용 스키마/호환성 헬퍼를 노출합니다: + `openclaw/plugin-sdk/provider-tools`는 현재 하나의 공유 + tool-schema 계열과 공유 스키마/호환성 헬퍼를 노출합니다: - - `ProviderToolCompatFamily`는 현재 공용 계열 목록을 문서화합니다. - - `buildProviderToolCompatFamilyHooks("gemini")`는 Gemini에 안전한 도구 스키마가 필요한 제공자를 위해 Gemini 스키마 정리와 진단을 연결합니다. - - `normalizeGeminiToolSchemas(...)`와 `inspectGeminiToolSchemas(...)`는 기반이 되는 공개 Gemini 스키마 헬퍼입니다. + - `ProviderToolCompatFamily`는 현재의 공유 계열 목록을 문서화합니다. + - `buildProviderToolCompatFamilyHooks("gemini")`는 Gemini 안전 도구 스키마가 필요한 제공자를 위해 + Gemini 스키마 정리 + 진단을 연결합니다. + - `normalizeGeminiToolSchemas(...)`와 `inspectGeminiToolSchemas(...)`는 + 그 기반이 되는 공개 Gemini 스키마 헬퍼입니다. - `resolveXaiModelCompatPatch()`는 번들 xAI 호환성 패치를 반환합니다: `toolSchemaProfile: "xai"`, 지원되지 않는 스키마 키워드, 네이티브 - `web_search` 지원, HTML 엔티티 도구 호출 인수 디코딩. - - `applyXaiModelCompat(model)`은 실행기에 도달하기 전에 해석된 모델에 - 동일한 xAI 호환성 패치를 적용합니다. + `web_search` 지원, HTML 엔터티 도구 호출 인자 디코딩. + - `applyXaiModelCompat(model)`은 실행기에 도달하기 전에 + 동일한 xAI 호환성 패치를 해석된 모델에 적용합니다. - 실제 번들 예시: xAI 플러그인은 `normalizeResolvedModel`과 - `contributeResolvedModelCompat`를 사용해 이 호환성 메타데이터를 - 코어에 xAI 규칙을 하드코딩하는 대신 제공자 소유로 유지합니다. + 실제 번들 예시: xAI 플러그인은 + 코어에 xAI 규칙을 하드코딩하는 대신 + `normalizeResolvedModel`과 `contributeResolvedModelCompat`를 사용해 해당 호환성 메타데이터의 소유권을 제공자에 둡니다. 동일한 패키지 루트 패턴은 다른 번들 제공자에도 적용됩니다: - - `@openclaw/openai-provider`: `api.ts`는 제공자 빌더, - 기본 모델 헬퍼, 실시간 제공자 빌더를 export합니다 - - `@openclaw/openrouter-provider`: `api.ts`는 제공자 빌더와 - 온보딩/설정 헬퍼를 export합니다 + - `@openclaw/openai-provider`: `api.ts`가 제공자 빌더, + 기본 모델 헬퍼, realtime 제공자 빌더를 export + - `@openclaw/openrouter-provider`: `api.ts`가 제공자 빌더와 + 온보딩/config 헬퍼를 export @@ -406,8 +407,8 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 }, ``` - - 사용자 지정 요청 헤더 또는 본문 수정이 필요한 제공자의 경우: + + 커스텀 요청 헤더나 본문 수정이 필요한 제공자의 경우: ```typescript // wrapStreamFn은 ctx.streamFn에서 파생된 StreamFn을 반환합니다 @@ -424,9 +425,8 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 }, ``` - - 일반 HTTP 또는 WebSocket 전송에서 네이티브 요청/세션 헤더나 - 메타데이터가 필요한 제공자의 경우: + + 일반 HTTP 또는 WebSocket 전송에서 네이티브 요청/세션 헤더나 메타데이터가 필요한 제공자의 경우: ```typescript resolveTransportTurnState: (ctx) => ({ @@ -447,7 +447,7 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 ``` - 사용량/과금 데이터를 제공하는 제공자의 경우: + 사용량/과금 데이터를 노출하는 제공자의 경우: ```typescript resolveUsageAuth: async (ctx) => { @@ -461,84 +461,83 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 - - OpenClaw는 다음 순서로 훅을 호출합니다. 대부분의 제공자는 2~3개만 사용합니다: + + OpenClaw는 다음 순서로 hook을 호출합니다. 대부분의 제공자는 2~3개만 사용합니다: - | # | 훅 | 사용 시점 | + | # | Hook | 사용 시점 | | --- | --- | --- | - | 1 | `catalog` | 모델 카탈로그 또는 기본 `baseUrl` | - | 2 | `applyConfigDefaults` | 설정 구체화 중 제공자 소유 전역 기본값 | + | 1 | `catalog` | 모델 카탈로그 또는 base URL 기본값 | + | 2 | `applyConfigDefaults` | config materialization 중 제공자 소유 전역 기본값 | | 3 | `normalizeModelId` | 조회 전 레거시/프리뷰 모델 id 별칭 정리 | | 4 | `normalizeTransport` | 일반 모델 조립 전 제공자 계열 `api` / `baseUrl` 정리 | - | 5 | `normalizeConfig` | `models.providers.` 설정 정규화 | - | 6 | `applyNativeStreamingUsageCompat` | 설정 제공자를 위한 네이티브 streaming-usage 호환성 재작성 | + | 5 | `normalizeConfig` | `models.providers.` config 정규화 | + | 6 | `applyNativeStreamingUsageCompat` | config 제공자용 네이티브 스트리밍 사용량 호환성 재작성 | | 7 | `resolveConfigApiKey` | 제공자 소유 env-marker 인증 해석 | - | 8 | `resolveSyntheticAuth` | 로컬/자체 호스팅 또는 설정 기반 synthetic auth | - | 9 | `shouldDeferSyntheticProfileAuth` | synthetic 저장 프로필 플레이스홀더를 env/config 인증보다 뒤로 미루기 | + | 8 | `resolveSyntheticAuth` | 로컬/셀프호스트형 또는 config 기반 synthetic 인증 | + | 9 | `shouldDeferSyntheticProfileAuth` | synthetic 저장 프로필 플레이스홀더를 env/config 인증보다 뒤로 낮춤 | | 10 | `resolveDynamicModel` | 임의의 업스트림 모델 ID 허용 | - | 11 | `prepareDynamicModel` | 해석 전 비동기 메타데이터 가져오기 | - | 12 | `normalizeResolvedModel` | 실행기 전 transport 재작성 | + | 11 | `prepareDynamicModel` | 해석 전 비동기 메타데이터 조회 | + | 12 | `normalizeResolvedModel` | 실행기 이전의 전송 재작성 | - 런타임 폴백 참고 사항: + 런타임 폴백 참고: - - `normalizeConfig`는 먼저 일치하는 제공자를 확인하고, 실제로 설정을 변경하는 - 훅 지원 제공자 플러그인이 나올 때까지 다른 훅 지원 제공자 플러그인을 - 확인합니다. 어떤 제공자 훅도 지원되는 Google 계열 설정 항목을 - 재작성하지 않으면 번들 Google 설정 정규화가 여전히 적용됩니다. - - `resolveConfigApiKey`는 제공자 훅이 노출된 경우 해당 훅을 사용합니다. - 번들 `amazon-bedrock` 경로도 여기서 AWS env-marker 해석기를 - 내장하고 있지만, Bedrock 런타임 인증 자체는 여전히 AWS SDK 기본 체인을 - 사용합니다. - | 13 | `contributeResolvedModelCompat` | 다른 호환 전송 뒤에 있는 벤더 모델용 호환성 플래그 | - | 14 | `capabilities` | 레거시 정적 기능 가방; 호환성 전용 | + - `normalizeConfig`는 먼저 일치한 제공자를 확인한 다음, + 실제로 config를 변경할 때까지 다른 hook 지원 제공자 플러그인을 확인합니다. + 지원되는 Google 계열 config 항목을 어떤 제공자 hook도 재작성하지 않으면 + 번들된 Google config 정규화기가 계속 적용됩니다. + - `resolveConfigApiKey`는 노출된 경우 제공자 hook을 사용합니다. 번들된 + `amazon-bedrock` 경로도 여기에서 내장 AWS env-marker 해석기를 가지지만, + Bedrock 런타임 인증 자체는 여전히 AWS SDK 기본 체인을 사용합니다. + | 13 | `contributeResolvedModelCompat` | 다른 호환 전송 뒤에 있는 공급업체 모델용 호환성 플래그 | + | 14 | `capabilities` | 레거시 정적 capability bag; 호환성 전용 | | 15 | `normalizeToolSchemas` | 등록 전 제공자 소유 도구 스키마 정리 | | 16 | `inspectToolSchemas` | 제공자 소유 도구 스키마 진단 | - | 17 | `resolveReasoningOutputMode` | 태그형 vs 네이티브 reasoning-output 계약 | + | 17 | `resolveReasoningOutputMode` | 태그형 대 네이티브 추론 출력 계약 | | 18 | `prepareExtraParams` | 기본 요청 파라미터 | - | 19 | `createStreamFn` | 완전한 사용자 지정 StreamFn 전송 | - | 20 | `wrapStreamFn` | 일반 스트림 경로의 사용자 지정 헤더/본문 래퍼 | + | 19 | `createStreamFn` | 완전히 커스텀 StreamFn 전송 | + | 20 | `wrapStreamFn` | 일반 stream 경로의 커스텀 헤더/본문 래퍼 | | 21 | `resolveTransportTurnState` | 네이티브 턴별 헤더/메타데이터 | | 22 | `resolveWebSocketSessionPolicy` | 네이티브 WS 세션 헤더/쿨다운 | - | 23 | `formatApiKey` | 사용자 지정 런타임 토큰 형식 | - | 24 | `refreshOAuth` | 사용자 지정 OAuth 갱신 | + | 23 | `formatApiKey` | 커스텀 런타임 토큰 형태 | + | 24 | `refreshOAuth` | 커스텀 OAuth 갱신 | | 25 | `buildAuthDoctorHint` | 인증 복구 안내 | - | 26 | `matchesContextOverflowError` | 제공자 소유 overflow 감지 | + | 26 | `matchesContextOverflowError` | 제공자 소유 오버플로 감지 | | 27 | `classifyFailoverReason` | 제공자 소유 rate-limit/overload 분류 | | 28 | `isCacheTtlEligible` | 프롬프트 캐시 TTL 게이팅 | - | 29 | `buildMissingAuthMessage` | 사용자 지정 누락 인증 힌트 | + | 29 | `buildMissingAuthMessage` | 커스텀 누락 인증 힌트 | | 30 | `suppressBuiltInModel` | 오래된 업스트림 행 숨기기 | - | 31 | `augmentModelCatalog` | synthetic forward-compat 행 | - | 32 | `isBinaryThinking` | 바이너리 thinking 켜기/끄기 | - | 33 | `supportsXHighThinking` | `xhigh` reasoning 지원 | + | 31 | `augmentModelCatalog` | synthetic 순방향 호환 행 | + | 32 | `isBinaryThinking` | 이진 thinking on/off | + | 33 | `supportsXHighThinking` | `xhigh` 추론 지원 | | 34 | `resolveDefaultThinkingLevel` | 기본 `/think` 정책 | - | 35 | `isModernModelRef` | 라이브/스모크 모델 매칭 | + | 35 | `isModernModelRef` | live/smoke 모델 매칭 | | 36 | `prepareRuntimeAuth` | 추론 전 토큰 교환 | - | 37 | `resolveUsageAuth` | 사용자 지정 사용량 자격 증명 파싱 | - | 38 | `fetchUsageSnapshot` | 사용자 지정 사용량 엔드포인트 | + | 37 | `resolveUsageAuth` | 커스텀 사용량 자격 증명 파싱 | + | 38 | `fetchUsageSnapshot` | 커스텀 사용량 엔드포인트 | | 39 | `createEmbeddingProvider` | 메모리/검색용 제공자 소유 임베딩 어댑터 | - | 40 | `buildReplayPolicy` | 사용자 지정 대화 기록 replay/압축 정책 | + | 40 | `buildReplayPolicy` | 커스텀 전사 기록 replay/압축 정책 | | 41 | `sanitizeReplayHistory` | 일반 정리 후 제공자 전용 replay 재작성 | - | 42 | `validateReplayTurns` | 임베디드 실행기 전 엄격한 replay 턴 검증 | + | 42 | `validateReplayTurns` | 내장 실행기 전 엄격한 replay-turn 검증 | | 43 | `onModelSelected` | 선택 후 콜백(예: 텔레메트리) | 프롬프트 튜닝 참고: - - `resolveSystemPromptContribution`은 제공자가 모델 계열용 캐시 인식 - 시스템 프롬프트 안내를 주입할 수 있게 합니다. 동작이 특정 - 제공자/모델 계열에 속하고 안정적/동적 캐시 분할을 유지해야 한다면 + - `resolveSystemPromptContribution`을 사용하면 제공자가 모델 계열에 대한 캐시 인식 + 시스템 프롬프트 지침을 주입할 수 있습니다. 동작이 특정 제공자/모델 + 계열에 속하고 안정/동적 캐시 분리를 유지해야 한다면 `before_prompt_build`보다 이것을 사용하는 것이 좋습니다. 자세한 설명과 실제 예시는 - [내부 구조: 제공자 런타임 훅](/ko/plugins/architecture#provider-runtime-hooks)을 - 참고하세요. + [내부 구조: 제공자 런타임 Hooks](/ko/plugins/architecture#provider-runtime-hooks)를 참조하세요. - + - 제공자 플러그인은 텍스트 추론과 함께 음성, 실시간 전사, 실시간 음성, - 미디어 이해, 이미지 생성, 비디오 생성, 웹 가져오기, 웹 검색도 등록할 수 있습니다: + 제공자 플러그인은 텍스트 추론과 함께 음성, realtime 전사, realtime + 음성, 미디어 이해, 이미지 생성, 비디오 생성, 웹 가져오기, + 웹 검색을 등록할 수 있습니다: ```typescript register(api) { @@ -646,21 +645,21 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 } ``` - OpenClaw는 이를 **hybrid-capability** 플러그인으로 분류합니다. - 이것은 회사용 플러그인(벤더당 하나의 플러그인)에 권장되는 패턴입니다. - [내부 구조: 기능 소유권](/ko/plugins/architecture#capability-ownership-model)을 - 참고하세요. + OpenClaw는 이를 **하이브리드 capability** 플러그인으로 분류합니다. 이것이 + 회사 플러그인(공급업체당 플러그인 하나)에 권장되는 패턴입니다. + [내부 구조: Capability 소유권](/ko/plugins/architecture#capability-ownership-model)을 참조하세요. - 비디오 생성의 경우 위에 나온 모드 인식 기능 형태를 사용하는 것이 좋습니다: - `generate`, `imageToVideo`, `videoToVideo`. `maxInputImages`, - `maxInputVideos`, `maxDurationSeconds` 같은 평면 집계 필드만으로는 - 변환 모드 지원이나 비활성화된 모드를 명확하게 알리기에 충분하지 않습니다. + 비디오 생성의 경우 위에 나온 모드 인식 capability 형태를 사용하는 것이 좋습니다: + `generate`, `imageToVideo`, `videoToVideo`. `maxInputImages`, `maxInputVideos`, `maxDurationSeconds` 같은 + 평평한 집계 필드만으로는 + 변환 모드 지원이나 비활성화된 모드를 깔끔하게 알리기에 충분하지 않습니다. - 음악 생성 제공자도 동일한 패턴을 따라야 합니다: - 프롬프트만 사용하는 생성에는 `generate`, 참조 이미지 기반 생성에는 - `edit`를 사용합니다. `maxInputImages`, `supportsLyrics`, - `supportsFormat` 같은 평면 집계 필드만으로는 edit 지원을 알리기에 - 충분하지 않으며, 명시적인 `generate` / `edit` 블록이 기대되는 계약입니다. + 음악 생성 제공자도 같은 패턴을 따라야 합니다: + 프롬프트 전용 생성에는 `generate`, 참조 이미지 기반 + 생성에는 `edit`를 사용합니다. `maxInputImages`, + `supportsLyrics`, `supportsFormat` 같은 평평한 집계 필드만으로는 편집 + 지원을 알리기에 충분하지 않으며, 명시적인 `generate` / `edit` 블록이 + 기대되는 계약입니다. @@ -668,11 +667,11 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 ```typescript src/provider.test.ts import { describe, it, expect } from "vitest"; - // index.ts 또는 전용 파일에서 제공자 설정 객체를 export하세요 + // index.ts 또는 전용 파일에서 제공자 config 객체를 export하세요 import { acmeProvider } from "./provider.js"; describe("acme-ai provider", () => { - it("동적 모델을 해석한다", () => { + it("resolves dynamic models", () => { const model = acmeProvider.resolveDynamicModel!({ modelId: "acme-beta-v3", } as any); @@ -680,14 +679,14 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 expect(model.provider).toBe("acme-ai"); }); - it("키가 있으면 카탈로그를 반환한다", async () => { + it("returns catalog when key is available", async () => { const result = await acmeProvider.catalog!.run({ resolveProviderApiKey: () => ({ apiKey: "test-key" }), } as any); expect(result?.provider?.models).toHaveLength(2); }); - it("키가 없으면 null 카탈로그를 반환한다", async () => { + it("returns null catalog when no key", async () => { const result = await acmeProvider.catalog!.run({ resolveProviderApiKey: () => ({ apiKey: undefined }), } as any); @@ -699,16 +698,16 @@ API 키 인증, 동적 모델 해석을 갖춘 제공자를 만들 수 있습니 -## ClawHub에 게시하기 +## ClawHub에 게시 -제공자 플러그인은 다른 외부 코드 플러그인과 동일한 방식으로 게시합니다: +제공자 플러그인은 다른 외부 코드 플러그인과 같은 방식으로 게시합니다: ```bash clawhub package publish your-org/your-plugin --dry-run clawhub package publish your-org/your-plugin ``` -여기서는 레거시 skill 전용 게시 별칭을 사용하지 마세요. 플러그인 패키지는 +여기서는 레거시 skill-only 게시 별칭을 사용하지 마세요. 플러그인 패키지는 `clawhub package publish`를 사용해야 합니다. ## 파일 구조 @@ -716,7 +715,7 @@ clawhub package publish your-org/your-plugin ``` /acme-ai/ ├── package.json # openclaw.providers 메타데이터 -├── openclaw.plugin.json # providerAuthEnvVars가 포함된 매니페스트 +├── openclaw.plugin.json # 제공자 인증 메타데이터가 있는 매니페스트 ├── index.ts # definePluginEntry + registerProvider └── src/ ├── provider.test.ts # 테스트 @@ -725,18 +724,19 @@ clawhub package publish your-org/your-plugin ## 카탈로그 순서 참고 -`catalog.order`는 내장 제공자에 비해 카탈로그가 언제 병합되는지 제어합니다: +`catalog.order`는 기본 제공 +제공자에 비해 카탈로그가 언제 병합되는지를 제어합니다: -| 순서 | 시점 | 사용 사례 | +| Order | 시점 | 사용 사례 | | --------- | ------------- | ----------------------------------------------- | -| `simple` | 첫 번째 패스 | 일반 API 키 제공자 | -| `profile` | simple 이후 | 인증 프로필에 따라 결정되는 제공자 | -| `paired` | profile 이후 | 여러 관련 항목을 합성 | -| `late` | 마지막 패스 | 기존 제공자를 덮어씀(충돌 시 우선) | +| `simple` | 첫 번째 패스 | 일반 API 키 제공자 | +| `profile` | simple 이후 | 인증 프로필에 의해 제한되는 제공자 | +| `paired` | profile 이후 | 여러 관련 항목 합성 | +| `late` | 마지막 패스 | 기존 제공자 재정의(충돌 시 우선 적용) | ## 다음 단계 - [채널 플러그인](/ko/plugins/sdk-channel-plugins) — 플러그인이 채널도 제공하는 경우 -- [SDK 런타임](/ko/plugins/sdk-runtime) — `api.runtime` 헬퍼(TTS, 검색, 서브에이전트) -- [SDK 개요](/ko/plugins/sdk-overview) — 전체 하위 경로 import 참조 -- [플러그인 내부 구조](/ko/plugins/architecture#provider-runtime-hooks) — 훅 세부 정보와 번들 예시 +- [SDK Runtime](/ko/plugins/sdk-runtime) — `api.runtime` 헬퍼(TTS, 검색, 하위 에이전트) +- [SDK 개요](/ko/plugins/sdk-overview) — 전체 하위 경로 import 참고 +- [플러그인 내부 구조](/ko/plugins/architecture#provider-runtime-hooks) — hook 세부 사항 및 번들 예시 diff --git a/docs/ko/providers/google.md b/docs/ko/providers/google.md index f13d6740c..7f87c5c24 100644 --- a/docs/ko/providers/google.md +++ b/docs/ko/providers/google.md @@ -1,14 +1,14 @@ --- read_when: - - OpenClaw와 함께 Google Gemini 모델을 사용하려는 경우 + - OpenClaw에서 Google Gemini 모델을 사용하려는 경우 - API 키 또는 OAuth 인증 흐름이 필요한 경우 summary: Google Gemini 설정(API 키 + OAuth, 이미지 생성, 미디어 이해, 웹 검색) title: Google (Gemini) x-i18n: - generated_at: "2026-04-08T02:17:36Z" + generated_at: "2026-04-09T01:30:29Z" model: gpt-5.4 provider: openai - source_hash: e9e558f5ce35c853e0240350be9a1890460c5f7f7fd30b05813a656497dee516 + source_hash: fad2ff68987301bd86145fa6e10de8c7b38d5bd5dbcd13db9c883f7f5b9a4e01 source_path: providers/google.md workflow: 15 --- @@ -19,19 +19,19 @@ Google plugin은 Google AI Studio를 통해 Gemini 모델에 대한 액세스를 Gemini Grounding을 통한 이미지 생성, 미디어 이해(이미지/오디오/비디오), 웹 검색도 지원합니다. - Provider: `google` -- Auth: `GEMINI_API_KEY` 또는 `GOOGLE_API_KEY` +- 인증: `GEMINI_API_KEY` 또는 `GOOGLE_API_KEY` - API: Google Gemini API - 대체 provider: `google-gemini-cli` (OAuth) ## 빠른 시작 -1. API 키를 설정합니다: +1. API 키를 설정합니다. ```bash openclaw onboard --auth-choice gemini-api-key ``` -2. 기본 모델을 설정합니다: +2. 기본 모델을 설정합니다. ```json5 { @@ -54,13 +54,13 @@ openclaw onboard --non-interactive \ ## OAuth (Gemini CLI) -대체 provider인 `google-gemini-cli`는 API -키 대신 PKCE OAuth를 사용합니다. 이것은 비공식 통합이며, 일부 사용자는 계정 -제한을 보고했습니다. 사용에 따른 책임은 본인에게 있습니다. +대체 provider인 `google-gemini-cli`는 API 키 대신 PKCE OAuth를 사용합니다. +이 통합은 비공식이며, 일부 사용자는 계정 제한을 +보고했습니다. 사용에 따른 책임은 사용자에게 있습니다. - 기본 모델: `google-gemini-cli/gemini-3-flash-preview` - 별칭: `gemini-cli` -- 설치 선행 조건: 로컬 Gemini CLI를 `gemini`로 사용할 수 있어야 함 +- 설치 전제 조건: 로컬 Gemini CLI를 `gemini`로 사용할 수 있어야 함 - Homebrew: `brew install gemini-cli` - npm: `npm install -g @google/gemini-cli` - 로그인: @@ -74,44 +74,47 @@ openclaw models auth login --provider google-gemini-cli --set-default - `OPENCLAW_GEMINI_OAUTH_CLIENT_ID` - `OPENCLAW_GEMINI_OAUTH_CLIENT_SECRET` -(`GEMINI_CLI_*` 변형도 가능) +(`GEMINI_CLI_*` 변형도 사용 가능) 로그인 후 Gemini CLI OAuth 요청이 실패하면 -gateway 호스트에 `GOOGLE_CLOUD_PROJECT` 또는 `GOOGLE_CLOUD_PROJECT_ID`를 설정하고 +게이트웨이 호스트에 `GOOGLE_CLOUD_PROJECT` 또는 `GOOGLE_CLOUD_PROJECT_ID`를 설정한 다음 다시 시도하세요. -브라우저 흐름이 시작되기 전에 로그인이 실패하면 로컬 `gemini` -명령이 설치되어 있고 `PATH`에 있는지 확인하세요. OpenClaw는 Homebrew 설치와 +브라우저 흐름이 시작되기 전에 로그인이 실패하면, 로컬 `gemini` +명령이 설치되어 있고 `PATH`에 포함되어 있는지 확인하세요. OpenClaw는 Homebrew 설치와 전역 npm 설치를 모두 지원하며, 일반적인 Windows/npm 레이아웃도 포함합니다. Gemini CLI JSON 사용 참고 사항: - 응답 텍스트는 CLI JSON `response` 필드에서 가져옵니다. - CLI가 `usage`를 비워 두면 사용량은 `stats`로 대체됩니다. -- `stats.cached`는 업스트림 `cacheRead`로 정규화됩니다. +- `stats.cached`는 OpenClaw `cacheRead`로 정규화됩니다. - `stats.input`이 없으면 OpenClaw는 - `stats.input_tokens - stats.cached`로부터 입력 토큰을 계산합니다. + `stats.input_tokens - stats.cached`에서 입력 토큰 수를 계산합니다. ## 기능 -| Capability | Supported | -| ---------------------- | ---------------- | -| Chat completions | 예 | -| Image generation | 예 | -| Music generation | 예 | -| Image understanding | 예 | -| Audio transcription | 예 | -| Video understanding | 예 | -| Web search (Grounding) | 예 | +| 기능 | 지원 여부 | +| ---------------------- | ----------------- | +| 채팅 completions | 예 | +| 이미지 생성 | 예 | +| 음악 생성 | 예 | +| 이미지 이해 | 예 | +| 오디오 전사 | 예 | +| 비디오 이해 | 예 | +| 웹 검색 (Grounding) | 예 | | Thinking/reasoning | 예 (Gemini 3.1+) | +| Gemma 4 모델 | 예 | + +Gemma 4 모델(예: `gemma-4-26b-a4b-it`)은 thinking 모드를 지원합니다. OpenClaw는 Gemma 4에 대해 `thinkingBudget`을 지원되는 Google `thinkingLevel`로 재작성합니다. thinking을 `off`로 설정하면 `MINIMAL`로 매핑되지 않고 thinking 비활성화가 유지됩니다. ## 직접 Gemini 캐시 재사용 직접 Gemini API 실행(`api: "google-generative-ai"`)의 경우, OpenClaw는 이제 구성된 `cachedContent` 핸들을 Gemini 요청에 그대로 전달합니다. -- 모델별 또는 전역 `params`는 - `cachedContent` 또는 레거시 `cached_content` 중 하나로 구성할 수 있습니다 +- 모델별 또는 전역 params에 + `cachedContent` 또는 레거시 `cached_content` 중 하나를 구성할 수 있습니다 - 둘 다 존재하면 `cachedContent`가 우선합니다 - 예시 값: `cachedContents/prebuilt-context` - Gemini 캐시 적중 사용량은 업스트림 `cachedContentTokenCount`에서 @@ -137,19 +140,19 @@ Gemini CLI JSON 사용 참고 사항: ## 이미지 생성 -번들 `google` 이미지 생성 provider의 기본값은 +번들된 `google` 이미지 생성 provider의 기본값은 `google/gemini-3.1-flash-image-preview`입니다. -- `google/gemini-3-pro-image-preview`도 지원 +- `google/gemini-3-pro-image-preview`도 지원합니다 - 생성: 요청당 최대 4개 이미지 -- 편집 모드: 활성화됨, 입력 이미지는 최대 5개 -- 기하 제어: `size`, `aspectRatio`, `resolution` +- 편집 모드: 활성화됨, 입력 이미지 최대 5개 +- Geometry 제어: `size`, `aspectRatio`, `resolution` OAuth 전용 `google-gemini-cli` provider는 별도의 텍스트 추론 표면입니다. 이미지 생성, 미디어 이해, Gemini Grounding은 계속 `google` provider id에 유지됩니다. -Google을 기본 이미지 provider로 사용하려면: +Google을 기본 이미지 provider로 사용하려면 다음과 같이 설정합니다. ```json5 { @@ -163,20 +166,20 @@ Google을 기본 이미지 provider로 사용하려면: } ``` -공통 도구 매개변수, provider 선택, 장애 조치 동작은 -[Image Generation](/ko/tools/image-generation)을 참조하세요. +공용 도구 매개변수, +provider 선택, 장애 조치 동작은 [Image Generation](/ko/tools/image-generation)을 참고하세요. ## 비디오 생성 -번들 `google` plugin은 공통 +번들된 `google` plugin은 공용 `video_generate` 도구를 통해 비디오 생성도 등록합니다. - 기본 비디오 모델: `google/veo-3.1-fast-generate-preview` -- 모드: 텍스트-비디오, 이미지-비디오, 단일 비디오 참조 흐름 +- 모드: text-to-video, image-to-video, 단일 비디오 참조 흐름 - `aspectRatio`, `resolution`, `audio` 지원 -- 현재 길이 제한: **4~8초** +- 현재 duration 제한: **4~8초** -Google을 기본 비디오 provider로 사용하려면: +Google을 기본 비디오 provider로 사용하려면 다음과 같이 설정합니다. ```json5 { @@ -190,22 +193,22 @@ Google을 기본 비디오 provider로 사용하려면: } ``` -공통 도구 매개변수, provider 선택, 장애 조치 동작은 -[Video Generation](/ko/tools/video-generation)을 참조하세요. +공용 도구 매개변수, +provider 선택, 장애 조치 동작은 [Video Generation](/ko/tools/video-generation)을 참고하세요. ## 음악 생성 -번들 `google` plugin은 공통 +번들된 `google` plugin은 공용 `music_generate` 도구를 통해 음악 생성도 등록합니다. - 기본 음악 모델: `google/lyria-3-clip-preview` - `google/lyria-3-pro-preview`도 지원 - 프롬프트 제어: `lyrics` 및 `instrumental` -- 출력 형식: 기본적으로 `mp3`, `google/lyria-3-pro-preview`에서는 `wav`도 지원 -- 참조 입력: 최대 10개 이미지 -- 세션 기반 실행은 공통 작업/상태 흐름을 통해 분리되며, `action: "status"`도 포함합니다 +- 출력 형식: 기본값 `mp3`, `google/lyria-3-pro-preview`에서는 `wav`도 지원 +- 참조 입력: 이미지 최대 10개 +- 세션 기반 실행은 `action: "status"`를 포함한 공용 task/status 흐름을 통해 분리 실행됩니다 -Google을 기본 음악 provider로 사용하려면: +Google을 기본 음악 provider로 사용하려면 다음과 같이 설정합니다. ```json5 { @@ -219,11 +222,11 @@ Google을 기본 음악 provider로 사용하려면: } ``` -공통 도구 매개변수, provider 선택, 장애 조치 동작은 -[Music Generation](/ko/tools/music-generation)을 참조하세요. +공용 도구 매개변수, +provider 선택, 장애 조치 동작은 [Music Generation](/ko/tools/music-generation)을 참고하세요. ## 환경 참고 -Gateway가 데몬(launchd/systemd)으로 실행되는 경우 `GEMINI_API_KEY`가 +Gateway가 데몬(launchd/systemd)으로 실행되는 경우, `GEMINI_API_KEY`가 해당 프로세스에서 사용 가능해야 합니다(예: `~/.openclaw/.env` 또는 `env.shellEnv`를 통해). diff --git a/docs/ko/providers/inferrs.md b/docs/ko/providers/inferrs.md index a745fdea6..32739725e 100644 --- a/docs/ko/providers/inferrs.md +++ b/docs/ko/providers/inferrs.md @@ -1,43 +1,39 @@ --- read_when: - 로컬 inferrs 서버에 대해 OpenClaw를 실행하려는 경우 - - inferrs를 통해 Gemma 또는 다른 모델을 서빙하는 경우 - - inferrs에 필요한 정확한 OpenClaw compat 플래그가 필요한 경우 -summary: inferrs(OpenAI 호환 로컬 서버)를 통해 OpenClaw 실행 + - inferrs를 통해 Gemma 또는 다른 모델을 제공하는 경우 + - inferrs용 정확한 OpenClaw 호환 플래그가 필요한 경우 +summary: inferrs(OpenAI 호환 로컬 서버)를 통해 OpenClaw 실행하기 title: inferrs x-i18n: - generated_at: "2026-04-08T02:17:50Z" + generated_at: "2026-04-09T01:30:27Z" model: gpt-5.4 provider: openai - source_hash: d84f660d49a682d0c0878707eebe1bc1e83dd115850687076ea3938b9f9c86c6 + source_hash: 03b9d5a9935c75fd369068bacb7807a5308cd0bd74303b664227fb664c3a2098 source_path: providers/inferrs.md workflow: 15 --- # inferrs -[inferrs](https://github.com/ericcurtin/inferrs)는 -OpenAI 호환 `/v1` API 뒤에서 로컬 모델을 서빙할 수 있습니다. OpenClaw는 일반적인 -`openai-completions` 경로를 통해 `inferrs`와 함께 동작합니다. +[inferrs](https://github.com/ericcurtin/inferrs)는 OpenAI 호환 `/v1` API 뒤에서 로컬 모델을 제공할 수 있습니다. OpenClaw는 일반 `openai-completions` 경로를 통해 `inferrs`와 함께 동작합니다. -현재 `inferrs`는 전용 OpenClaw provider plugin이라기보다 -사용자 지정 self-hosted OpenAI 호환 -백엔드로 취급하는 것이 가장 적절합니다. +현재 `inferrs`는 전용 OpenClaw provider plugin이 아니라 사용자 지정 자체 호스팅 OpenAI 호환 백엔드로 취급하는 것이 가장 적절합니다. ## 빠른 시작 -1. 모델과 함께 `inferrs`를 시작합니다. +1. 모델로 `inferrs`를 시작합니다. -예시: +예: ```bash -inferrs serve gg-hf-gg/gemma-4-E2B-it \ +inferrs serve google/gemma-4-E2B-it \ --host 127.0.0.1 \ --port 8080 \ --device metal ``` -2. 서버에 연결 가능한지 확인합니다. +2. 서버에 연결할 수 있는지 확인합니다. ```bash curl http://127.0.0.1:8080/health @@ -46,17 +42,17 @@ curl http://127.0.0.1:8080/v1/models 3. 명시적인 OpenClaw provider 항목을 추가하고 기본 모델이 이를 가리키도록 설정합니다. -## 전체 구성 예시 +## 전체 구성 예제 -이 예시는 로컬 `inferrs` 서버에서 Gemma 4를 사용합니다. +이 예제는 로컬 `inferrs` 서버에서 Gemma 4를 사용합니다. ```json5 { agents: { defaults: { - model: { primary: "inferrs/gg-hf-gg/gemma-4-E2B-it" }, + model: { primary: "inferrs/google/gemma-4-E2B-it" }, models: { - "inferrs/gg-hf-gg/gemma-4-E2B-it": { + "inferrs/google/gemma-4-E2B-it": { alias: "Gemma 4 (inferrs)", }, }, @@ -71,7 +67,7 @@ curl http://127.0.0.1:8080/v1/models api: "openai-completions", models: [ { - id: "gg-hf-gg/gemma-4-E2B-it", + id: "google/gemma-4-E2B-it", name: "Gemma 4 E2B (inferrs)", reasoning: false, input: ["text"], @@ -91,10 +87,9 @@ curl http://127.0.0.1:8080/v1/models ## `requiresStringContent`가 중요한 이유 -일부 `inferrs` Chat Completions 경로는 구조화된 content-part 배열이 아니라 -문자열 형태의 `messages[].content`만 허용합니다. +일부 `inferrs` Chat Completions 경로는 구조화된 content-part 배열이 아니라 문자열 `messages[].content`만 허용합니다. -OpenClaw 실행이 다음과 같은 오류로 실패한다면: +OpenClaw 실행 시 다음과 같은 오류가 발생하면: ```text messages[1].content: invalid type: sequence, expected a string @@ -108,14 +103,11 @@ compat: { } ``` -OpenClaw는 요청을 보내기 전에 순수 텍스트 content part를 -일반 문자열로 평탄화합니다. +OpenClaw는 요청을 보내기 전에 순수 텍스트 content part를 일반 문자열로 평탄화합니다. -## Gemma 및 도구 스키마 주의 사항 +## Gemma 및 tool-schema 주의 사항 -현재의 일부 `inferrs` + Gemma 조합은 작은 직접 -`/v1/chat/completions` 요청은 허용하지만 전체 OpenClaw 에이전트 런타임 -턴에서는 여전히 실패합니다. +현재 일부 `inferrs` + Gemma 조합은 작은 직접 `/v1/chat/completions` 요청은 수락하지만 전체 OpenClaw agent-runtime 턴에서는 여전히 실패합니다. 이 경우 먼저 다음을 시도하세요: @@ -126,53 +118,44 @@ compat: { } ``` -이렇게 하면 해당 모델에 대해 OpenClaw의 도구 스키마 표면이 비활성화되며, -더 엄격한 로컬 백엔드에서 프롬프트 부담을 줄일 수 있습니다. +이 설정은 해당 모델에 대한 OpenClaw의 tool schema 표면을 비활성화하며, 더 엄격한 로컬 백엔드에서 prompt 부담을 줄일 수 있습니다. -작은 직접 요청은 계속 동작하지만 일반적인 OpenClaw 에이전트 턴이 계속 -`inferrs` 내부에서 크래시한다면, 남은 문제는 보통 OpenClaw의 전송 계층보다는 -업스트림 모델/서버 동작입니다. +작은 직접 요청은 여전히 동작하지만 일반 OpenClaw agent 턴이 `inferrs` 내부에서 계속 충돌한다면, 남아 있는 문제는 보통 OpenClaw의 전송 계층보다는 업스트림 모델/서버 동작에 있습니다. ## 수동 스모크 테스트 -구성한 뒤에는 두 계층을 모두 테스트하세요. +구성한 후에는 두 계층을 모두 테스트하세요: ```bash curl http://127.0.0.1:8080/v1/chat/completions \ -H 'content-type: application/json' \ - -d '{"model":"gg-hf-gg/gemma-4-E2B-it","messages":[{"role":"user","content":"What is 2 + 2?"}],"stream":false}' + -d '{"model":"google/gemma-4-E2B-it","messages":[{"role":"user","content":"What is 2 + 2?"}],"stream":false}' openclaw infer model run \ - --model inferrs/gg-hf-gg/gemma-4-E2B-it \ + --model inferrs/google/gemma-4-E2B-it \ --prompt "What is 2 + 2? Reply with one short sentence." \ --json ``` -첫 번째 명령은 동작하지만 두 번째가 실패한다면, 아래의 문제 해결 참고 사항을 사용하세요. +첫 번째 명령은 동작하지만 두 번째가 실패하면 아래 문제 해결 참고 사항을 사용하세요. ## 문제 해결 -- `curl /v1/models`가 실패함: `inferrs`가 실행 중이 아니거나, 연결할 수 없거나, - 예상한 호스트/포트에 바인딩되지 않았습니다. +- `curl /v1/models` 실패: `inferrs`가 실행 중이 아니거나, 연결할 수 없거나, 예상한 host/port에 바인딩되지 않았습니다. - `messages[].content ... expected a string`: `compat.requiresStringContent: true`를 설정하세요. -- 작은 직접 `/v1/chat/completions` 호출은 통과하지만 `openclaw infer model run`이 - 실패함: `compat.supportsTools: false`를 시도하세요. -- OpenClaw에서 더 이상 스키마 오류는 나지 않지만 `inferrs`가 더 큰 - 에이전트 턴에서 여전히 크래시함: 이를 업스트림 `inferrs` 또는 모델 한계로 보고 - 프롬프트 부담을 줄이거나 로컬 백엔드/모델을 바꾸세요. +- 직접적인 작은 `/v1/chat/completions` 호출은 통과하지만 `openclaw infer model run`은 실패: `compat.supportsTools: false`를 시도하세요. +- OpenClaw에서 더 이상 스키마 오류는 발생하지 않지만 `inferrs`가 더 큰 agent 턴에서 여전히 충돌: 이를 업스트림 `inferrs` 또는 모델의 제한으로 보고 prompt 부담을 줄이거나 로컬 백엔드/모델을 전환하세요. ## 프록시 스타일 동작 -`inferrs`는 네이티브 -OpenAI 엔드포인트가 아니라 프록시 스타일 OpenAI 호환 `/v1` 백엔드로 취급됩니다. +`inferrs`는 네이티브 OpenAI 엔드포인트가 아니라 프록시 스타일 OpenAI 호환 `/v1` 백엔드로 취급됩니다. -- 네이티브 OpenAI 전용 요청 셰이핑은 여기에 적용되지 않습니다 -- `service_tier`, Responses `store`, 프롬프트 캐시 힌트, OpenAI 추론 호환 페이로드 셰이핑이 없습니다 -- 숨겨진 OpenClaw attribution 헤더(`originator`, `version`, `User-Agent`)는 - 사용자 지정 `inferrs` base URL에 주입되지 않습니다 +- 네이티브 OpenAI 전용 요청 형태 조정은 여기에는 적용되지 않음 +- `service_tier`, Responses `store`, prompt-cache 힌트, OpenAI reasoning-compat 페이로드 형태 조정이 없음 +- 숨겨진 OpenClaw attribution 헤더(`originator`, `version`, `User-Agent`)는 사용자 지정 `inferrs` base URL에 주입되지 않음 ## 함께 보기 -- [로컬 모델](/ko/gateway/local-models) -- [게이트웨이 문제 해결](/ko/gateway/troubleshooting#local-openai-compatible-backend-passes-direct-probes-but-agent-runs-fail) -- [모델 프로바이더](/ko/concepts/model-providers) +- [Local models](/ko/gateway/local-models) +- [Gateway troubleshooting](/ko/gateway/troubleshooting#local-openai-compatible-backend-passes-direct-probes-but-agent-runs-fail) +- [Model providers](/ko/concepts/model-providers) diff --git a/docs/ko/providers/ollama.md b/docs/ko/providers/ollama.md index 436f72ec7..433c3efb0 100644 --- a/docs/ko/providers/ollama.md +++ b/docs/ko/providers/ollama.md @@ -1,24 +1,24 @@ --- read_when: - - Ollama를 통해 클라우드 또는 로컬 모델로 OpenClaw를 실행하고 싶을 때 - - Ollama 설정 및 구성 가이드가 필요할 때 -summary: Ollama를 통해 OpenClaw를 실행합니다(클라우드 및 로컬 모델) + - Ollama를 통해 클라우드 또는 로컬 모델로 OpenClaw를 실행하려는 경우 + - Ollama 설정 및 구성 가이드가 필요한 경우 +summary: Ollama로 OpenClaw 실행하기(클라우드 및 로컬 모델) title: Ollama x-i18n: - generated_at: "2026-04-08T02:18:23Z" + generated_at: "2026-04-09T01:31:04Z" model: gpt-5.4 provider: openai - source_hash: 222ec68f7d4bb29cc7796559ddef1d5059f5159e7a51e2baa3a271ddb3abb716 + source_hash: d3295a7c879d3636a2ffdec05aea6e670e54a990ef52bd9b0cae253bc24aa3f7 source_path: providers/ollama.md workflow: 15 --- # Ollama -Ollama는 머신에서 오픈 소스 모델을 쉽게 실행할 수 있게 해주는 로컬 LLM 런타임입니다. OpenClaw는 Ollama의 네이티브 API(`/api/chat`)와 통합되며, 스트리밍과 도구 호출을 지원하고, `OLLAMA_API_KEY`(또는 인증 프로필)로 opt in하고 명시적인 `models.providers.ollama` 항목을 정의하지 않으면 로컬 Ollama 모델을 자동으로 검색할 수 있습니다. +Ollama는 머신에서 오픈 소스 모델을 쉽게 실행할 수 있게 해 주는 로컬 LLM 런타임입니다. OpenClaw는 Ollama의 네이티브 API(`/api/chat`)와 통합되며, 스트리밍과 tool calling을 지원하고, `OLLAMA_API_KEY`(또는 auth profile)로 옵트인하고 명시적인 `models.providers.ollama` 항목을 정의하지 않으면 로컬 Ollama 모델을 자동으로 검색할 수 있습니다. -**원격 Ollama 사용자**: OpenClaw에서 `/v1` OpenAI 호환 URL(`http://host:11434/v1`)을 사용하지 마세요. 이렇게 하면 도구 호출이 깨지고 모델이 원시 도구 JSON을 일반 텍스트로 출력할 수 있습니다. 대신 네이티브 Ollama API URL을 사용하세요: `baseUrl: "http://host:11434"` (`/v1` 없음). +**원격 Ollama 사용자**: OpenClaw와 함께 `/v1` OpenAI 호환 URL(`http://host:11434/v1`)을 사용하지 마세요. 이렇게 하면 tool calling이 깨지고 모델이 원시 tool JSON을 일반 텍스트로 출력할 수 있습니다. 대신 네이티브 Ollama API URL을 사용하세요: `baseUrl: "http://host:11434"` (`/v1` 없음). ## 빠른 시작 @@ -31,13 +31,13 @@ Ollama를 설정하는 가장 빠른 방법은 온보딩을 사용하는 것입 openclaw onboard ``` -제공자 목록에서 **Ollama**를 선택하세요. 온보딩은 다음을 수행합니다: +provider 목록에서 **Ollama**를 선택하세요. 온보딩은 다음을 수행합니다: -1. 인스턴스에 접근할 수 있는 Ollama base URL을 묻습니다(기본값 `http://127.0.0.1:11434`). -2. **Cloud + Local**(클라우드 모델과 로컬 모델) 또는 **Local**(로컬 모델만)을 선택하게 합니다. -3. **Cloud + Local**을 선택했고 ollama.com에 로그인되어 있지 않다면 브라우저 로그인 흐름을 엽니다. +1. 인스턴스에 접근할 수 있는 Ollama 기본 URL을 묻습니다(기본값 `http://127.0.0.1:11434`). +2. **Cloud + Local**(클라우드 모델 및 로컬 모델) 또는 **Local**(로컬 모델만)을 선택하게 합니다. +3. **Cloud + Local**을 선택했고 `ollama.com`에 로그인되어 있지 않으면 브라우저 로그인 흐름을 엽니다. 4. 사용 가능한 모델을 검색하고 기본값을 제안합니다. -5. 선택한 모델이 로컬에 없다면 자동으로 pull합니다. +5. 선택한 모델이 로컬에 없으면 자동으로 pull합니다. 비대화형 모드도 지원됩니다: @@ -47,7 +47,7 @@ openclaw onboard --non-interactive \ --accept-risk ``` -선택적으로 커스텀 base URL 또는 모델을 지정할 수 있습니다: +선택적으로 사용자 지정 base URL 또는 모델을 지정할 수 있습니다: ```bash openclaw onboard --non-interactive \ @@ -59,15 +59,15 @@ openclaw onboard --non-interactive \ ### 수동 설정 -1. Ollama를 설치합니다: [https://ollama.com/download](https://ollama.com/download) +1. Ollama 설치: [https://ollama.com/download](https://ollama.com/download) -2. 로컬 추론을 원한다면 로컬 모델을 pull합니다: +2. 로컬 추론을 원하면 로컬 모델을 pull합니다: ```bash ollama pull gemma4 -# or +# 또는 ollama pull gpt-oss:20b -# or +# 또는 ollama pull llama3.3 ``` @@ -84,21 +84,21 @@ openclaw onboard ``` - `Local`: 로컬 모델만 -- `Cloud + Local`: 로컬 모델 + 클라우드 모델 +- `Cloud + Local`: 로컬 모델과 클라우드 모델 - `kimi-k2.5:cloud`, `minimax-m2.7:cloud`, `glm-5.1:cloud` 같은 클라우드 모델은 로컬 `ollama pull`이 **필요하지 않습니다** -현재 OpenClaw는 다음을 제안합니다: +OpenClaw는 현재 다음을 제안합니다: - 로컬 기본값: `gemma4` - 클라우드 기본값: `kimi-k2.5:cloud`, `minimax-m2.7:cloud`, `glm-5.1:cloud` -5. 수동 설정을 선호한다면 OpenClaw용 Ollama를 직접 활성화하세요(아무 값이나 동작합니다. Ollama는 실제 키를 요구하지 않습니다): +5. 수동 설정을 선호한다면 OpenClaw에서 Ollama를 직접 활성화하세요(아무 값이나 동작하며, Ollama는 실제 키가 필요하지 않습니다): ```bash -# Set environment variable +# 환경 변수 설정 export OLLAMA_API_KEY="ollama-local" -# Or configure in your config file +# 또는 config 파일에 설정 openclaw config set models.providers.ollama.apiKey "ollama-local" ``` @@ -121,26 +121,27 @@ openclaw models set ollama/gemma4 } ``` -## 모델 검색(암시적 제공자) +## 모델 검색(암시적 provider) -`OLLAMA_API_KEY`(또는 인증 프로필)를 설정하고 **`models.providers.ollama`를 정의하지 않으면**, OpenClaw는 `http://127.0.0.1:11434`의 로컬 Ollama 인스턴스에서 모델을 검색합니다: +`OLLAMA_API_KEY`(또는 auth profile)를 설정하고 `models.providers.ollama`를 **정의하지 않으면**, OpenClaw는 `http://127.0.0.1:11434`의 로컬 Ollama 인스턴스에서 모델을 검색합니다: -- `/api/tags`를 조회 -- 가능할 때 `contextWindow`를 읽기 위해 최선의 노력으로 `/api/show` 조회 사용 +- `/api/tags` 조회 +- 가능할 때 `contextWindow`를 읽고 기능(비전 포함)을 감지하기 위해 최선의 노력 방식으로 `/api/show` 조회 사용 +- `/api/show`가 보고한 `vision` 기능이 있는 모델은 이미지 입력 가능 모델(`input: ["text", "image"]`)로 표시되므로 OpenClaw가 해당 모델의 프롬프트에 이미지를 자동 주입함 - 모델 이름 휴리스틱(`r1`, `reasoning`, `think`)으로 `reasoning` 표시 -- `maxTokens`를 OpenClaw가 사용하는 기본 Ollama 최대 토큰 상한으로 설정 +- OpenClaw가 사용하는 기본 Ollama max-token 제한으로 `maxTokens` 설정 - 모든 비용을 `0`으로 설정 이렇게 하면 수동 모델 항목 없이도 카탈로그를 로컬 Ollama 인스턴스와 맞춘 상태로 유지할 수 있습니다. -사용 가능한 모델을 보려면: +사용 가능한 모델을 확인하려면: ```bash ollama list openclaw models list ``` -새 모델을 추가하려면 Ollama로 pull하면 됩니다: +새 모델을 추가하려면 Ollama로 pull하기만 하면 됩니다: ```bash ollama pull mistral @@ -148,7 +149,7 @@ ollama pull mistral 새 모델은 자동으로 검색되어 사용할 수 있게 됩니다. -`models.providers.ollama`를 명시적으로 설정하면 자동 검색은 건너뛰며 모델을 수동으로 정의해야 합니다(아래 참고). +`models.providers.ollama`를 명시적으로 설정하면 자동 검색은 건너뛰며 모델을 수동으로 정의해야 합니다(아래 참조). ## 구성 @@ -164,9 +165,9 @@ export OLLAMA_API_KEY="ollama-local" 다음 경우에는 명시적 config를 사용하세요: -- Ollama가 다른 호스트/포트에서 실행될 때 -- 특정 컨텍스트 윈도우나 모델 목록을 강제로 지정하고 싶을 때 -- 모델 정의를 완전히 수동으로 관리하고 싶을 때 +- Ollama가 다른 host/port에서 실행되는 경우 +- 특정 컨텍스트 윈도우나 모델 목록을 강제하고 싶은 경우 +- 완전히 수동으로 모델을 정의하고 싶은 경우 ```json5 { @@ -193,11 +194,11 @@ export OLLAMA_API_KEY="ollama-local" } ``` -`OLLAMA_API_KEY`가 설정되어 있다면 provider 항목의 `apiKey`는 생략할 수 있으며, OpenClaw가 가용성 확인을 위해 이를 채워 넣습니다. +`OLLAMA_API_KEY`가 설정되어 있으면 provider 항목에서 `apiKey`를 생략해도 되며 OpenClaw가 가용성 확인을 위해 이를 채웁니다. -### 커스텀 base URL(명시적 config) +### 사용자 지정 base URL(명시적 config) -Ollama가 다른 호스트나 포트에서 실행 중이라면(명시적 config는 자동 검색을 비활성화하므로 모델을 수동으로 정의해야 함): +Ollama가 다른 host 또는 port에서 실행 중인 경우(명시적 config는 자동 검색을 비활성화하므로 모델을 수동 정의해야 함): ```json5 { @@ -205,8 +206,8 @@ Ollama가 다른 호스트나 포트에서 실행 중이라면(명시적 config providers: { ollama: { apiKey: "ollama-local", - baseUrl: "http://ollama-host:11434", // No /v1 - use native Ollama API URL - api: "ollama", // Set explicitly to guarantee native tool-calling behavior + baseUrl: "http://ollama-host:11434", // /v1 없음 - 네이티브 Ollama API URL 사용 + api: "ollama", // 네이티브 tool-calling 동작을 보장하려면 명시적으로 설정 }, }, }, @@ -214,12 +215,12 @@ Ollama가 다른 호스트나 포트에서 실행 중이라면(명시적 config ``` -URL에 `/v1`을 추가하지 마세요. `/v1` 경로는 OpenAI 호환 모드를 사용하며, 여기서는 도구 호출이 신뢰할 수 없습니다. 경로 접미사 없이 기본 Ollama URL을 사용하세요. +URL에 `/v1`을 추가하지 마세요. `/v1` 경로는 OpenAI 호환 모드를 사용하며 tool calling이 신뢰할 수 없습니다. 경로 접미사가 없는 기본 Ollama URL을 사용하세요. ### 모델 선택 -구성이 끝나면 모든 Ollama 모델을 사용할 수 있습니다: +구성되면 모든 Ollama 모델을 사용할 수 있습니다: ```json5 { @@ -236,24 +237,21 @@ URL에 `/v1`을 추가하지 마세요. `/v1` 경로는 OpenAI 호환 모드를 ## 클라우드 모델 -클라우드 모델을 사용하면 로컬 모델과 함께 클라우드 호스팅 모델(예: `kimi-k2.5:cloud`, `minimax-m2.7:cloud`, `glm-5.1:cloud`)도 실행할 수 있습니다. +클라우드 모델을 사용하면 로컬 모델과 함께 클라우드 호스팅 모델(예: `kimi-k2.5:cloud`, `minimax-m2.7:cloud`, `glm-5.1:cloud`)을 실행할 수 있습니다. -클라우드 모델을 사용하려면 설정 중에 **Cloud + Local** 모드를 선택하세요. wizard는 로그인 상태를 확인하고 필요할 때 브라우저 로그인 흐름을 엽니다. 인증을 확인할 수 없으면 wizard는 로컬 모델 기본값으로 대체합니다. +클라우드 모델을 사용하려면 설정 중에 **Cloud + Local** 모드를 선택하세요. 마법사는 로그인 상태를 확인하고 필요하면 브라우저 로그인 흐름을 엽니다. 인증을 확인할 수 없으면 마법사는 로컬 모델 기본값으로 대체합니다. -직접 [ollama.com/signin](https://ollama.com/signin)에서 로그인할 수도 있습니다. +[ollama.com/signin](https://ollama.com/signin)에서 직접 로그인할 수도 있습니다. -## Ollama 웹 검색 +## Ollama Web Search -OpenClaw는 번들된 `web_search` -제공자로 **Ollama 웹 검색**도 지원합니다. +OpenClaw는 번들된 `web_search` provider로 **Ollama Web Search**도 지원합니다. -- 설정된 Ollama 호스트를 사용합니다(`models.providers.ollama.baseUrl`이 - 설정되어 있으면 그 값을 사용하고, 아니면 `http://127.0.0.1:11434` 사용). +- 구성된 Ollama host를 사용합니다(`models.providers.ollama.baseUrl`가 설정된 경우 그 값, 아니면 `http://127.0.0.1:11434`). - 키가 필요 없습니다. - Ollama가 실행 중이어야 하고 `ollama signin`으로 로그인되어 있어야 합니다. -`openclaw onboard` 또는 -`openclaw configure --section web` 중에 **Ollama 웹 검색**을 선택하거나, 다음과 같이 설정하세요: +`openclaw onboard` 또는 `openclaw configure --section web` 중에 **Ollama Web Search**를 선택하거나 다음을 설정하세요: ```json5 { @@ -267,13 +265,13 @@ OpenClaw는 번들된 `web_search` } ``` -전체 설정 및 동작 상세 정보는 [Ollama 웹 검색](/ko/tools/ollama-search)을 참고하세요. +전체 설정 및 동작 세부 정보는 [Ollama Web Search](/ko/tools/ollama-search)를 참조하세요. ## 고급 -### 추론 모델 +### reasoning 모델 -OpenClaw는 기본적으로 `deepseek-r1`, `reasoning`, `think` 같은 이름이 포함된 모델을 추론 가능 모델로 취급합니다: +OpenClaw는 기본적으로 `deepseek-r1`, `reasoning`, `think` 같은 이름의 모델을 reasoning 가능 모델로 취급합니다: ```bash ollama pull deepseek-r1:32b @@ -281,19 +279,19 @@ ollama pull deepseek-r1:32b ### 모델 비용 -Ollama는 무료이며 로컬에서 실행되므로, 모든 모델 비용은 $0으로 설정됩니다. +Ollama는 무료이며 로컬에서 실행되므로 모든 모델 비용은 $0으로 설정됩니다. ### 스트리밍 구성 -OpenClaw의 Ollama 통합은 기본적으로 **네이티브 Ollama API**(`/api/chat`)를 사용하며, 스트리밍과 도구 호출을 동시에 완전히 지원합니다. 별도의 특별한 설정은 필요하지 않습니다. +OpenClaw의 Ollama 통합은 기본적으로 **네이티브 Ollama API**(`/api/chat`)를 사용하며, 스트리밍과 tool calling을 동시에 완전히 지원합니다. 별도의 특별한 설정은 필요하지 않습니다. #### 레거시 OpenAI 호환 모드 -**OpenAI 호환 모드에서는 도구 호출이 신뢰할 수 없습니다.** 프록시에 OpenAI 형식이 필요하고 네이티브 도구 호출 동작에 의존하지 않을 때만 이 모드를 사용하세요. +**OpenAI 호환 모드에서는 tool calling이 신뢰할 수 없습니다.** 프록시 때문에 OpenAI 형식이 필요하고 네이티브 tool calling 동작에 의존하지 않는 경우에만 이 모드를 사용하세요. -대신 OpenAI 호환 엔드포인트를 사용해야 한다면(예: OpenAI 형식만 지원하는 프록시 뒤에 있는 경우), `api: "openai-completions"`를 명시적으로 설정하세요: +대신 OpenAI 호환 엔드포인트를 사용해야 하는 경우(예: OpenAI 형식만 지원하는 프록시 뒤에 있는 경우) `api: "openai-completions"`를 명시적으로 설정하세요: ```json5 { @@ -302,7 +300,7 @@ OpenClaw의 Ollama 통합은 기본적으로 **네이티브 Ollama API**(`/api/c ollama: { baseUrl: "http://ollama-host:11434/v1", api: "openai-completions", - injectNumCtxForOpenAICompat: true, // default: true + injectNumCtxForOpenAICompat: true, // 기본값: true apiKey: "ollama-local", models: [...] } @@ -311,9 +309,9 @@ OpenClaw의 Ollama 통합은 기본적으로 **네이티브 Ollama API**(`/api/c } ``` -이 모드는 스트리밍 + 도구 호출을 동시에 지원하지 않을 수 있습니다. 모델 config의 `params: { streaming: false }`로 스트리밍을 비활성화해야 할 수도 있습니다. +이 모드는 스트리밍과 tool calling을 동시에 지원하지 않을 수 있습니다. 모델 config에서 `params: { streaming: false }`로 스트리밍을 비활성화해야 할 수 있습니다. -Ollama에서 `api: "openai-completions"`를 사용할 때 OpenClaw는 기본적으로 `options.num_ctx`를 주입하므로 Ollama가 조용히 4096 컨텍스트 윈도우로 대체되지 않습니다. 프록시/업스트림이 알 수 없는 `options` 필드를 거부한다면 이 동작을 비활성화하세요: +Ollama와 함께 `api: "openai-completions"`를 사용하면 OpenClaw는 Ollama가 조용히 4096 컨텍스트 윈도우로 되돌아가지 않도록 기본적으로 `options.num_ctx`를 주입합니다. 프록시/업스트림이 알 수 없는 `options` 필드를 거부하면 이 동작을 비활성화하세요: ```json5 { @@ -333,19 +331,19 @@ Ollama에서 `api: "openai-completions"`를 사용할 때 OpenClaw는 기본적 ### 컨텍스트 윈도우 -자동 검색된 모델의 경우 OpenClaw는 가능하면 Ollama가 보고한 컨텍스트 윈도우를 사용하고, 그렇지 않으면 OpenClaw가 사용하는 기본 Ollama 컨텍스트 윈도우로 대체합니다. 명시적 provider config에서 `contextWindow`와 `maxTokens`를 재정의할 수 있습니다. +자동 검색된 모델의 경우 OpenClaw는 가능한 경우 Ollama가 보고한 컨텍스트 윈도우를 사용하고, 그렇지 않으면 OpenClaw가 사용하는 기본 Ollama 컨텍스트 윈도우로 대체합니다. 명시적 provider config에서 `contextWindow`와 `maxTokens`를 재정의할 수 있습니다. ## 문제 해결 ### Ollama가 감지되지 않음 -Ollama가 실행 중인지, `OLLAMA_API_KEY`(또는 인증 프로필)를 설정했는지, 그리고 **명시적인** `models.providers.ollama` 항목을 정의하지 않았는지 확인하세요: +Ollama가 실행 중인지, `OLLAMA_API_KEY`(또는 auth profile)를 설정했는지, 그리고 명시적인 `models.providers.ollama` 항목을 **정의하지 않았는지** 확인하세요: ```bash ollama serve ``` -또한 API에 접근 가능한지도 확인하세요: +또한 API에 접근 가능한지 확인하세요: ```bash curl http://localhost:11434/api/tags @@ -353,34 +351,34 @@ curl http://localhost:11434/api/tags ### 사용 가능한 모델이 없음 -모델이 목록에 없다면 다음 중 하나입니다: +모델이 목록에 없으면 다음 중 하나입니다: -- 로컬에서 모델을 pull하거나 -- `models.providers.ollama`에 모델을 명시적으로 정의해야 합니다 +- 모델을 로컬에 pull하거나 +- `models.providers.ollama`에 모델을 명시적으로 정의하세요. -모델을 추가하려면: +모델 추가 방법: ```bash -ollama list # See what's installed +ollama list # 설치된 항목 확인 ollama pull gemma4 ollama pull gpt-oss:20b -ollama pull llama3.3 # Or another model +ollama pull llama3.3 # 또는 다른 모델 ``` ### 연결 거부됨 -Ollama가 올바른 포트에서 실행 중인지 확인하세요: +Ollama가 올바른 port에서 실행 중인지 확인하세요: ```bash -# Check if Ollama is running +# Ollama 실행 여부 확인 ps aux | grep ollama -# Or restart Ollama +# 또는 Ollama 재시작 ollama serve ``` -## 참고 항목 +## 함께 보기 -- [모델 제공자](/ko/concepts/model-providers) - 모든 제공자 개요 -- [모델 선택](/ko/concepts/models) - 모델 선택 방법 -- [구성](/ko/gateway/configuration) - 전체 config 참조 +- [Model Providers](/ko/concepts/model-providers) - 모든 provider 개요 +- [Model Selection](/ko/concepts/models) - 모델 선택 방법 +- [Configuration](/ko/gateway/configuration) - 전체 config 참조 diff --git a/docs/ko/providers/qwen.md b/docs/ko/providers/qwen.md index d9c536ad4..bf0b1a43d 100644 --- a/docs/ko/providers/qwen.md +++ b/docs/ko/providers/qwen.md @@ -1,14 +1,14 @@ --- read_when: - - OpenClaw에서 Qwen을 사용하려고 합니다 - - 이전에 Qwen OAuth를 사용했습니다 -summary: OpenClaw의 번들 qwen provider를 통해 Qwen Cloud 사용하기 + - OpenClaw에서 Qwen을 사용하려는 경우 + - 이전에 Qwen OAuth를 사용한 적이 있는 경우 +summary: OpenClaw의 번들된 qwen provider를 통해 Qwen Cloud 사용 title: Qwen x-i18n: - generated_at: "2026-04-06T03:11:41Z" + generated_at: "2026-04-09T01:30:59Z" model: gpt-5.4 provider: openai - source_hash: f175793693ab6a4c3f1f4d42040e673c15faf7603a500757423e9e06977c989d + source_hash: 4786df2cb6ec1ab29d191d012c61dcb0e5468bf0f8561fbbb50eed741efad325 source_path: providers/qwen.md workflow: 15 --- @@ -20,44 +20,44 @@ x-i18n: **Qwen OAuth는 제거되었습니다.** `portal.qwen.ai` 엔드포인트를 사용하던 무료 등급 OAuth 통합(`qwen-portal`)은 더 이상 사용할 수 없습니다. 배경은 [Issue #49557](https://github.com/openclaw/openclaw/issues/49557)를 -참조하세요. +참고하세요. ## 권장: Qwen Cloud -이제 OpenClaw는 Qwen을 정식 번들 provider로 취급하며 정식 ID는 -`qwen`입니다. 번들 provider는 Qwen Cloud / Alibaba DashScope 및 -Coding Plan 엔드포인트를 대상으로 하며, 레거시 `modelstudio` ID도 +OpenClaw는 이제 Qwen을 정식 canonical id +`qwen`을 가진 1급 번들 provider로 취급합니다. 번들 provider는 Qwen Cloud / Alibaba DashScope 및 +Coding Plan 엔드포인트를 대상으로 하며, 레거시 `modelstudio` id도 호환성 별칭으로 계속 작동합니다. - Provider: `qwen` - 권장 env var: `QWEN_API_KEY` -- 호환성을 위해 다음도 허용: `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` +- 호환성을 위해 추가 지원: `MODELSTUDIO_API_KEY`, `DASHSCOPE_API_KEY` - API 스타일: OpenAI 호환 `qwen3.6-plus`를 사용하려면 **Standard (pay-as-you-go)** 엔드포인트를 권장합니다. Coding Plan 지원은 공개 카탈로그보다 늦을 수 있습니다. ```bash -# 전역 Coding Plan 엔드포인트 +# Global Coding Plan endpoint openclaw onboard --auth-choice qwen-api-key -# 중국 Coding Plan 엔드포인트 +# China Coding Plan endpoint openclaw onboard --auth-choice qwen-api-key-cn -# 전역 Standard (pay-as-you-go) 엔드포인트 +# Global Standard (pay-as-you-go) endpoint openclaw onboard --auth-choice qwen-standard-api-key -# 중국 Standard (pay-as-you-go) 엔드포인트 +# China Standard (pay-as-you-go) endpoint openclaw onboard --auth-choice qwen-standard-api-key-cn ``` -레거시 `modelstudio-*` auth-choice ID와 `modelstudio/...` 모델 ref도 -호환성 별칭으로 계속 작동하지만, 새로운 setup 흐름에서는 정식 -`qwen-*` auth-choice ID와 `qwen/...` 모델 ref를 사용하는 것이 좋습니다. +레거시 `modelstudio-*` auth-choice id와 `modelstudio/...` 모델 참조도 +호환성 별칭으로 계속 작동하지만, 새 설정 흐름에서는 canonical +`qwen-*` auth-choice id와 `qwen/...` 모델 참조를 사용하는 것이 좋습니다. -온보딩 후 기본 모델을 설정하세요: +온보딩 후 기본 모델을 설정하세요. ```json5 { @@ -69,83 +69,84 @@ openclaw onboard --auth-choice qwen-standard-api-key-cn } ``` -## 플랜 유형과 엔드포인트 +## 플랜 유형 및 엔드포인트 -| 플랜 | 리전 | Auth choice | 엔드포인트 | -| --------------------------- | ---- | -------------------------- | ---------------------------------------------- | -| Standard (pay-as-you-go) | 중국 | `qwen-standard-api-key-cn` | `dashscope.aliyuncs.com/compatible-mode/v1` | -| Standard (pay-as-you-go) | 전역 | `qwen-standard-api-key` | `dashscope-intl.aliyuncs.com/compatible-mode/v1` | -| Coding Plan (구독) | 중국 | `qwen-api-key-cn` | `coding.dashscope.aliyuncs.com/v1` | -| Coding Plan (구독) | 전역 | `qwen-api-key` | `coding-intl.dashscope.aliyuncs.com/v1` | +| 플랜 | 지역 | Auth choice | 엔드포인트 | +| -------------------------- | ------ | -------------------------- | ----------------------------------------------- | +| Standard (pay-as-you-go) | China | `qwen-standard-api-key-cn` | `dashscope.aliyuncs.com/compatible-mode/v1` | +| Standard (pay-as-you-go) | Global | `qwen-standard-api-key` | `dashscope-intl.aliyuncs.com/compatible-mode/v1` | +| Coding Plan (subscription) | China | `qwen-api-key-cn` | `coding.dashscope.aliyuncs.com/v1` | +| Coding Plan (subscription) | Global | `qwen-api-key` | `coding-intl.dashscope.aliyuncs.com/v1` | -provider는 auth choice를 기반으로 엔드포인트를 자동 선택합니다. 정식 -choice는 `qwen-*` 계열을 사용하며, `modelstudio-*`는 호환성 전용으로 유지됩니다. -config에서 사용자 지정 `baseUrl`로 재정의할 수 있습니다. +provider는 auth choice에 따라 엔드포인트를 자동 선택합니다. canonical +선택지는 `qwen-*` 계열을 사용하며, `modelstudio-*`는 호환성 전용입니다. +config에서 커스텀 `baseUrl`로 재정의할 수 있습니다. -기본 Model Studio 엔드포인트는 공유 -`openai-completions` 전송에서 스트리밍 사용량 호환성을 알립니다. OpenClaw는 이제 이를 엔드포인트 -capability를 기준으로 처리하므로, 동일한 기본 호스트를 대상으로 하는 DashScope 호환 -사용자 지정 provider ID도 내장 `qwen` provider ID를 특별히 요구하지 않고 -동일한 스트리밍 사용량 동작을 상속합니다. +기본 Model Studio 엔드포인트는 공용 +`openai-completions` 전송에서 스트리밍 사용량 호환성을 알립니다. OpenClaw는 이제 이를 엔드포인트 기능 기준으로 처리하므로, 동일한 기본 호스트를 대상으로 하는 DashScope 호환 커스텀 provider id도 +내장 `qwen` provider id를 특별히 요구하지 않고 동일한 스트리밍 사용량 동작을 상속합니다. -## API key 받기 +## API 키 받기 - **키 관리**: [home.qwencloud.com/api-keys](https://home.qwencloud.com/api-keys) - **문서**: [docs.qwencloud.com](https://docs.qwencloud.com/developer-guides/getting-started/introduction) ## 내장 카탈로그 -OpenClaw는 현재 다음 번들 Qwen 카탈로그를 제공합니다: +OpenClaw는 현재 다음 번들 Qwen 카탈로그를 제공합니다. 구성된 카탈로그는 +엔드포인트 인식형입니다. Coding Plan config에서는 Standard 엔드포인트에서만 +작동하는 것으로 알려진 모델이 제외됩니다. -| Model ref | 입력 | 컨텍스트 | 참고사항 | -| --------------------------- | ----------- | --------- | -------------------------------------------------- | +| 모델 참조 | 입력 | 컨텍스트 | 참고 | +| -------------------------- | ----------- | --------- | -------------------------------------------------- | | `qwen/qwen3.5-plus` | text, image | 1,000,000 | 기본 모델 | | `qwen/qwen3.6-plus` | text, image | 1,000,000 | 이 모델이 필요하면 Standard 엔드포인트 권장 | -| `qwen/qwen3-max-2026-01-23` | text | 262,144 | Qwen Max 라인 | +| `qwen/qwen3-max-2026-01-23` | text | 262,144 | Qwen Max 계열 | | `qwen/qwen3-coder-next` | text | 262,144 | 코딩 | | `qwen/qwen3-coder-plus` | text | 1,000,000 | 코딩 | -| `qwen/MiniMax-M2.5` | text | 1,000,000 | 추론 활성화 | +| `qwen/MiniMax-M2.5` | text | 1,000,000 | reasoning 활성화됨 | | `qwen/glm-5` | text | 202,752 | GLM | | `qwen/glm-4.7` | text | 202,752 | GLM | | `qwen/kimi-k2.5` | text, image | 262,144 | Alibaba를 통한 Moonshot AI | -모델이 번들 카탈로그에 있더라도 엔드포인트와 과금 플랜에 따라 사용 가능 여부는 달라질 수 있습니다. +모델이 번들 카탈로그에 있더라도, 실제 사용 가능 여부는 엔드포인트와 결제 플랜에 따라 달라질 수 있습니다. 기본 스트리밍 사용량 호환성은 Coding Plan 호스트와 -Standard DashScope 호환 호스트 모두에 적용됩니다: +Standard DashScope 호환 호스트 모두에 적용됩니다. - `https://coding.dashscope.aliyuncs.com/v1` - `https://coding-intl.dashscope.aliyuncs.com/v1` - `https://dashscope.aliyuncs.com/compatible-mode/v1` - `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` -## Qwen 3.6 Plus 가용성 +## Qwen 3.6 Plus 사용 가능 여부 `qwen3.6-plus`는 Standard (pay-as-you-go) Model Studio -엔드포인트에서 사용할 수 있습니다: +엔드포인트에서 사용할 수 있습니다. -- 중국: `dashscope.aliyuncs.com/compatible-mode/v1` -- 전역: `dashscope-intl.aliyuncs.com/compatible-mode/v1` +- China: `dashscope.aliyuncs.com/compatible-mode/v1` +- Global: `dashscope-intl.aliyuncs.com/compatible-mode/v1` -Coding Plan 엔드포인트가 `qwen3.6-plus`에 대해 "unsupported model" 오류를 반환하면, -Coding Plan 엔드포인트/key 조합 대신 Standard (pay-as-you-go)로 전환하세요. +Coding Plan 엔드포인트에서 `qwen3.6-plus`에 대해 +"unsupported model" 오류가 반환되면, Coding Plan +엔드포인트/키 조합 대신 Standard (pay-as-you-go)로 전환하세요. -## capability 계획 +## 기능 계획 -`qwen` extension은 단지 coding/text 모델만이 아니라 -전체 Qwen Cloud 표면을 위한 벤더 홈으로 자리 잡고 있습니다. +`qwen` 확장은 단순한 코딩/텍스트 모델뿐 아니라 전체 Qwen +Cloud 표면의 벤더 홈으로 자리 잡고 있습니다. - 텍스트/채팅 모델: 현재 번들 제공 -- tool calling, 구조화 출력, thinking: OpenAI 호환 전송에서 상속 -- 이미지 생성: provider-plugin 계층에서 계획 중 +- Tool calling, structured output, thinking: OpenAI 호환 전송에서 상속 +- 이미지 생성: provider-plugin 계층에서 예정 - 이미지/비디오 이해: 현재 Standard 엔드포인트에서 번들 제공 -- speech/오디오: provider-plugin 계층에서 계획 중 -- 메모리 임베딩/리랭킹: 임베딩 adapter 표면을 통해 계획 중 -- 비디오 생성: 공유 video-generation capability를 통해 현재 번들 제공 +- 음성/오디오: provider-plugin 계층에서 예정 +- 메모리 임베딩/reranking: 임베딩 어댑터 표면을 통해 예정 +- 비디오 생성: 공용 비디오 생성 기능을 통해 현재 번들 제공 ## 멀티모달 추가 기능 -이제 `qwen` extension은 다음도 제공합니다: +`qwen` 확장은 이제 다음도 제공합니다. - `qwen-vl-max-latest`를 통한 비디오 이해 - 다음을 통한 Wan 비디오 생성: @@ -158,20 +159,20 @@ Coding Plan 엔드포인트/key 조합 대신 Standard (pay-as-you-go)로 전환 이 멀티모달 표면은 Coding Plan 엔드포인트가 아니라 **Standard** DashScope 엔드포인트를 사용합니다. -- 전역/국제 Standard base URL: `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` -- 중국 Standard base URL: `https://dashscope.aliyuncs.com/compatible-mode/v1` +- Global/Intl Standard base URL: `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` +- China Standard base URL: `https://dashscope.aliyuncs.com/compatible-mode/v1` -비디오 생성의 경우 OpenClaw는 작업 제출 전에 구성된 Qwen 리전을 -일치하는 DashScope AIGC 호스트로 매핑합니다: +비디오 생성의 경우, OpenClaw는 작업 제출 전에 구성된 Qwen 지역을 일치하는 +DashScope AIGC 호스트에 매핑합니다. -- 전역/국제: `https://dashscope-intl.aliyuncs.com` -- 중국: `https://dashscope.aliyuncs.com` +- Global/Intl: `https://dashscope-intl.aliyuncs.com` +- China: `https://dashscope.aliyuncs.com` -즉, Coding Plan 또는 Standard Qwen 호스트 중 하나를 가리키는 일반적인 -`models.providers.qwen.baseUrl`을 사용해도 비디오 생성은 계속 올바른 -리전 DashScope 비디오 엔드포인트를 사용하게 됩니다. +즉, Coding Plan 또는 Standard Qwen 호스트를 가리키는 일반적인 +`models.providers.qwen.baseUrl`을 사용하더라도 비디오 생성은 올바른 +지역 DashScope 비디오 엔드포인트를 계속 사용합니다. -비디오 생성의 경우 기본 모델을 명시적으로 설정하세요: +비디오 생성의 경우 기본 모델을 명시적으로 설정하세요. ```json5 { @@ -185,20 +186,20 @@ Coding Plan 엔드포인트/key 조합 대신 Standard (pay-as-you-go)로 전환 현재 번들 Qwen 비디오 생성 제한: -- 요청당 출력 비디오는 최대 **1개** -- 입력 이미지는 최대 **1개** -- 입력 비디오는 최대 **4개** -- 길이는 최대 **10초** +- 요청당 최대 **1**개 출력 비디오 +- 최대 **1**개 입력 이미지 +- 최대 **4**개 입력 비디오 +- 최대 **10초** duration - `size`, `aspectRatio`, `resolution`, `audio`, `watermark` 지원 -- 참조 이미지/비디오 모드는 현재 **원격 http(s) URL**이 필요합니다. DashScope 비디오 엔드포인트가 - 해당 참조에 대해 업로드된 로컬 버퍼를 허용하지 않기 때문에 로컬 - 파일 경로는 초기에 거부됩니다. +- 참조 이미지/비디오 모드는 현재 **원격 http(s) URL**이 필요합니다. 로컬 + 파일 경로는 DashScope 비디오 엔드포인트가 해당 참조에 대해 업로드된 로컬 버퍼를 + 허용하지 않기 때문에 사전에 거부됩니다. -공유 도구 파라미터, provider 선택, failover 동작은 -[Video Generation](/tools/video-generation)을 참조하세요. +공용 도구 매개변수, +provider 선택, 장애 조치 동작은 [Video Generation](/ko/tools/video-generation)을 참고하세요. ## 환경 참고 -Gateway가 데몬(launchd/systemd)으로 실행되는 경우 `QWEN_API_KEY`가 +Gateway가 데몬(launchd/systemd)으로 실행되는 경우, `QWEN_API_KEY`가 해당 프로세스에서 사용 가능해야 합니다(예: `~/.openclaw/.env` 또는 `env.shellEnv`를 통해).