chore(i18n): refresh ko translations

This commit is contained in:
openclaw-docs-i18n[bot] 2026-04-22 06:09:08 +00:00
parent 5313e0a066
commit 3188678a32
10 changed files with 2564 additions and 1790 deletions

View File

@ -1,81 +1,82 @@
---
read_when:
- 어떤 CI 작업이 실행되었거나 실행되지 않은 이유를 이해해야 합니다
- 실패한 GitHub Actions 검사를 디버깅하고 있습니다
summary: CI 작업 그래프, 범위 게이트, 그리고 로컬 명령 대응 항목
- CI 작업이 실행되었거나 실행되지 않은 이유를 이해해야 합니다.
- 실패한 GitHub Actions 검사를 디버깅하고 있습니다.
summary: CI 작업 그래프, 범위 게이트, 그리고 로컬 명령 대응 항목
title: CI 파이프라인
x-i18n:
generated_at: "2026-04-22T04:21:25Z"
generated_at: "2026-04-22T06:00:32Z"
model: gpt-5.4
provider: openai
source_hash: ae08bad6cbd0f2eced6c88a792a11bc1c2b1a2bfb003a56f70ff328a2739d3fc
source_hash: fc7ec59123aee65634736320dbf1cf5cdfb08786a78cca82ce9596fedc68b3cc
source_path: ci.md
workflow: 15
---
# CI 파이프라인
CI는 `main`에 대한 모든 푸시와 모든 pull request에서 실행됩니다. 관련 없는 영역만 변경된 경우 비용이 큰 작업을 건너뛰기 위해 스마트 범위 지정을 사용합니다.
CI는 `main`에 대한 모든 푸시와 모든 pull request에서 실행됩니다. 스마트 범위 지정 기능을 사용해 관련 없는 영역만 변경된 경우 비용이 큰 작업을 건너니다.
## 작업 개요
| 작업 | 목적 | 실행 시점 |
| -------------------------------- | -------------------------------------------------------------------------------------------- | ----------------------------------- |
| `preflight` | docs 전용 변경, 변경된 범위, 변경된 extensions를 감지하고 CI 매니페스트를 빌드 | 드래프트가 아닌 모든 푸시 및 PR에서 항상 실행 |
| `security-scm-fast` | `zizmor`를 통한 개인 키 감지 및 워크플로 감사 | 드래프트가 아닌 모든 푸시 및 PR에서 항상 실행 |
| `security-dependency-audit` | npm advisory 기준의 의존성 없는 프로덕션 lockfile 감사 | 드래프트가 아닌 모든 푸시 및 PR에서 항상 실행 |
| `security-fast` | 빠른 보안 작업을 위한 필수 집계 작업 | 드래프트가 아닌 모든 푸시 및 PR에서 항상 실행 |
| `build-artifacts` | `dist/`와 Control UI를 한 번 빌드하고, 하위 작업이 재사용할 수 있는 아티팩트를 업로드 | Node 관련 변경 시 |
| `checks-fast-core` | bundled/plugin-contract/protocol 검사와 같은 빠른 Linux 정확성 레인 | Node 관련 변경 시 |
| `checks-fast-contracts-channels` | 안정적인 집계 검사 결과를 제공하는 샤딩된 채널 contract 검사 | Node 관련 변경 시 |
| `checks-node-extensions` | extension 전반에서 bundled-plugin 전체 테스트 샤드 실행 | Node 관련 변경 시 |
| `checks-node-core-test` | 채널, bundled, contract, extension 레인을 제외한 코어 Node 테스트 샤드 | Node 관련 변경 시 |
| `extension-fast` | 변경된 bundled plugin만 대상으로 하는 집중 테스트 | extension 변경이 감지될 때 |
| `check` | 샤딩된 메인 로컬 게이트 대응 항목: 프로덕션 타입, lint, 가드, 테스트 타입, 엄격한 스모크 | Node 관련 변경 시 |
| `check-additional` | 아키텍처, 경계, extension-surface 가드, package-boundary, gateway-watch 샤드 | Node 관련 변경 시 |
| `build-smoke` | 빌드된 CLI 스모크 테스트 및 시작 메모리 스모크 | Node 관련 변경 시 |
| `checks` | 나머지 Linux Node 레인: 채널 테스트 및 푸시 전용 Node 22 호환성 | Node 관련 변경 시 |
| `check-docs` | docs 포맷팅, lint, 깨진 링크 검사 | docs 변경 시 |
| `skills-python` | Python 기반 Skills에 대한 Ruff + pytest | Python-skill 관련 변경 시 |
| `checks-windows` | Windows 전용 테스트 레인 | Windows 관련 변경 시 |
| `macos-node` | 공유 빌드 아티팩트를 사용하는 macOS TypeScript 테스트 레인 | macOS 관련 변경 시 |
| `macos-swift` | macOS 앱용 Swift lint, 빌드, 테스트 | macOS 관련 변경 시 |
| `android` | Android 빌드 및 테스트 매트릭스 | Android 관련 변경 시 |
| 작업 | 목적 | 실행 시점 |
| -------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------ |
| `preflight` | docs 전용 변경, 변경된 범위, 변경된 extensions를 감지하고 CI 매니페스트를 빌드합니다 | 초안이 아닌 모든 푸시와 PR에서 항상 실행 |
| `security-scm-fast` | `zizmor`를 통한 private key 탐지 및 워크플로 감사 | 초안이 아닌 모든 푸시와 PR에서 항상 실행 |
| `security-dependency-audit` | npm advisory를 기준으로 한 의존성 없는 프로덕션 lockfile 감사 | 초안이 아닌 모든 푸시와 PR에서 항상 실행 |
| `security-fast` | 빠른 보안 작업들을 위한 필수 집계 작업 | 초안이 아닌 모든 푸시와 PR에서 항상 실행 |
| `build-artifacts` | `dist/`와 Control UI를 한 번 빌드하고, 이후 작업에서 재사용할 수 있도록 아티팩트를 업로드합니다 | Node 관련 변경 |
| `checks-fast-core` | 번들/plugin-contract/protocol 검사와 같은 빠른 Linux 정확성 레인 | Node 관련 변경 |
| `checks-fast-contracts-channels` | 안정적인 집계 검사 결과를 갖는 샤딩된 channel contract 검사 | Node 관련 변경 |
| `checks-node-extensions` | extension 제품군 전반에 걸친 전체 번들-plugin 테스트 샤드 | Node 관련 변경 |
| `checks-node-core-test` | channel, 번들, contract, extension 레인을 제외한 Core Node 테스트 샤드 | Node 관련 변경 |
| `extension-fast` | 변경된 번들 plugins만 대상으로 하는 집중 테스트 | extension 변경이 감지된 경우 |
| `check` | 샤딩된 메인 로컬 게이트 대응 항목: 프로덕션 타입, lint, guard, 테스트 타입, 엄격한 smoke | Node 관련 변경 |
| `check-additional` | 아키텍처, 경계, extension-surface guard, package-boundary, gateway-watch 샤드 | Node 관련 변경 |
| `build-smoke` | 빌드된 CLI smoke 테스트와 startup-memory smoke | Node 관련 변경 |
| `checks` | 나머지 Linux Node 레인: channel 테스트와 푸시 전용 Node 22 호환성 | Node 관련 변경 |
| `check-docs` | docs 포맷팅, lint, 깨진 링크 검사 | Docs 변경 |
| `skills-python` | Python 기반 Skills에 대한 Ruff + pytest | Python-skill 관련 변경 |
| `checks-windows` | Windows 전용 테스트 레인 | Windows 관련 변경 |
| `macos-node` | 공유 빌드 아티팩트를 사용하는 macOS TypeScript 테스트 레인 | macOS 관련 변경 |
| `macos-swift` | macOS 앱용 Swift lint, 빌드, 테스트 | macOS 관련 변경 |
| `android` | Android 빌드 및 테스트 매트릭스 | Android 관련 변경 |
## Fail-Fast 순서
작업은 비용이 큰 작업이 실행되기 전에 저렴한 검사가 먼저 실패하도록 정렬됩니다.
작업은 비용이 큰 작업이 실행되기 전에 저렴한 검사가 먼저 실패하도록 순서가 정해져 있습니다.
1. `preflight`가 어떤 레인이 존재하는지 자체를 결정합니다. `docs-scope``changed-scope` 로직은 독립 작업이 아니라 이 작업 내부의 단계입니다.
2. `security-scm-fast`, `security-dependency-audit`, `security-fast`, `check`, `check-additional`, `check-docs`, `skills-python`은 더 무거운 아티팩트 및 플랫폼 매트릭스 작업을 기다리지 않고 빠르게 실패합니다.
3. `build-artifacts`는 빠른 Linux 레인과 겹쳐 실행되므로, 공유 빌드가 준비되는 즉시 하위 소비자가 시작할 수 있습니다.
4. 이후 더 무거운 플랫폼 및 런타임 레인이 분기됩니다: `checks-fast-core`, `checks-fast-contracts-channels`, `checks-node-extensions`, `checks-node-core-test`, `extension-fast`, `checks`, `checks-windows`, `macos-node`, `macos-swift`, `android`.
1. `preflight`가 어떤 레인이 실제로 존재하는지 결정합니다. `docs-scope``changed-scope` 로직은 독립 작업이 아니라 이 작업 내부의 단계입니다.
2. `security-scm-fast`, `security-dependency-audit`, `security-fast`, `check`, `check-additional`, `check-docs`, `skills-python`은 더 무거운 artifact 및 플랫폼 매트릭스 작업을 기다리지 않고 빠르게 실패합니다.
3. `build-artifacts`는 빠른 Linux 레인과 병렬로 실행되므로, 공유 빌드가 준비되는 즉시 downstream 소비자가 시작할 수 있습니다.
4. 이후 더 무거운 플랫폼 및 런타임 레인이 분기됩니다: `checks-fast-core`, `checks-fast-contracts-channels`, `checks-node-extensions`, `checks-node-core-test`, `extension-fast`, `checks`, `checks-windows`, `macos-node`, `macos-swift`, `android`.
범위 로직은 `scripts/ci-changed-scope.mjs`에 있으며 `src/scripts/ci-changed-scope.test.ts`의 단위 테스트로 검증됩니다.
별도의 `install-smoke` 워크플로는 자체 `preflight` 작업을 통해 같은 범위 스크립트를 재사용합니다. 더 좁은 changed-smoke 신호에서 `run_install_smoke`를 계산하므로, Docker/install smoke는 설치, 패키징, 컨테이너 관련 변경에 대해서만 실행됩니다.
범위 로직은 `scripts/ci-changed-scope.mjs`에 있으며, `src/scripts/ci-changed-scope.test.ts`의 단위 테스트로 검증됩니다.
별도의 `install-smoke` 워크플로는 자체 `preflight` 작업을 통해 같은 범위 스크립트를 재사용합니다. 더 좁은 changed-smoke 신호에서 `run_install_smoke`를 계산하므로, Docker/install smoke는 install, packaging, container 관련 변경에 대해서만 실행됩니다.
로컬 changed-lane 로직은 `scripts/changed-lanes.mjs`에 있으며 `scripts/check-changed.mjs`에서 실행됩니다. 이 로컬 게이트는 광범위한 CI 플랫폼 범위보다 아키텍처 경계에 더 엄격합니다. 코어 프로덕션 변경은 코어 프로덕션 타입체크와 코어 테스트를 실행하고, 코어 테스트 전용 변경은 코어 테스트 타입체크/테스트만 실행하며, extension 프로덕션 변경은 extension 프로덕션 타입체크와 extension 테스트를 실행하고, extension 테스트 전용 변경은 extension 테스트 타입체크/테스트만 실행합니다. 공개 Plugin SDK 또는 plugin-contract 변경은 extension이 이러한 코어 contract에 의존하므로 extension 검증까지 확장됩니다. 릴리스 메타데이터 전용 버전 범프는 버전/구성/루트 의존성 검사만 대상으로 실행합니다. 알 수 없는 루트/구성 변경은 안전하게 모든 레인으로 확장됩니다.
로컬 변경 레인 로직은 `scripts/changed-lanes.mjs`에 있으며 `scripts/check-changed.mjs`가 이를 실행합니다. 이 로컬 게이트는 광범위한 CI 플랫폼 범위보다 아키텍처 경계에 대해 더 엄격합니다. core 프로덕션 변경은 core 프로덕션 typecheck와 core 테스트를 실행하고, core 테스트 전용 변경은 core 테스트 typecheck/tests만 실행하며, extension 프로덕션 변경은 extension 프로덕션 typecheck와 extension 테스트를 실행하고, extension 테스트 전용 변경은 extension 테스트 typecheck/tests만 실행합니다. 공개 Plugin SDK 또는 plugin-contract 변경은 extension이 그 core contract에 의존하므로 extension 검증까지 확장됩니다. 릴리스 메타데이터 전용 버전 범프는 대상이 제한된 version/config/root-dependency 검사를 실행합니다. 알 수 없는 root/config 변경은 안전하게 모든 레인으로 실패 처리됩니다.
푸시에서는 `checks` 매트릭스에 푸시 전용 `compat-node22` 레인이 추가됩니다. pull request에서는 이 레인이 건너뛰어지고, 매트릭스는 일반 테스트/채널 레인에 집중된 상태를 유지합니다.
푸시에서는 `checks` 매트릭스가 푸시 전용 `compat-node22` 레인을 추가합니다. pull request에서는 이 레인이 건너뛰어지고 매트릭스는 일반 테스트/channel 레인에 집중된 상태를 유지합니다.
가장 느린 Node 테스트 계열은 각 작업을 작게 유지하기 위해 include-file 샤드로 분할됩니다. 채널 contract는 registry와 코어 커버리지를 각각 8개의 가중 샤드로 분할하고, auto-reply reply command 테스트는 4개의 include-pattern 샤드로 분할하며, 그 외 큰 auto-reply reply prefix 그룹은 각각 2개의 샤드로 분할합니다. `check-additional`도 package-boundary compile/canary 작업과 런타임 topology gateway/architecture 작업을 분리합니다.
가장 느린 Node 테스트 계열은 각 작업이 작게 유지되도록 include-file 샤드로 분할됩니다. channel contract는 registry와 core 커버리지를 각각 8개의 가중 샤드로 분할하고, auto-reply reply command 테스트는 4개의 include-pattern 샤드로 분할하며, 그 외 큰 auto-reply reply prefix 그룹은 각각 2개의 샤드로 분할합니다. `check-additional`도 package-boundary compile/canary 작업을 runtime topology gateway/architecture 작업과 분리합니다.
같은 PR 또는 `main` ref에 더 새로운 푸시가 들어오면 GitHub는 대체된 작업을 `cancelled`로 표시할 수 있습니다. 같은 ref의 최신 실행도 실패하고 있지 않다면 이것은 CI 노이즈로 간주하세요. 집계 샤드 검사는 이 취소 사례를 명시적으로 표시하므로 테스트 실패와 더 쉽게 구분할 수 있습니다.
같은 PR 또는 `main` ref에 새 푸시가 도착하면 GitHub는 대체된 작업을 `cancelled`로 표시할 수 있습니다. 같은 ref의 최신 실행도 실패 중이 아닌 한, 이것은 CI 잡음으로 취급하세요. 집계 샤드 검사는 이 취소 사례를 명시적으로 알려 주므로 테스트 실패와 더 쉽게 구분할 수 있습니다.
## 러너
| 러너 | 작업 |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `blacksmith-16vcpu-ubuntu-2404` | `preflight`, `security-scm-fast`, `security-dependency-audit`, `security-fast`, `build-artifacts`, Linux 검사, docs 검사, Python Skills, `android` |
| `blacksmith-32vcpu-windows-2025` | `checks-windows` |
| `blacksmith-12vcpu-macos-latest` | `openclaw/openclaw``macos-node`, `macos-swift`; 포크는 `macos-latest`로 대체 |
| 러너 | 작업 |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `ubuntu-24.04` | `preflight`; install-smoke preflight도 GitHub 호스팅 Ubuntu를 사용하므로 Blacksmith 매트릭스가 더 일찍 큐에 들어갈 수 있습니다 |
| `blacksmith-16vcpu-ubuntu-2404` | `security-scm-fast`, `security-dependency-audit`, `security-fast`, `build-artifacts`, Linux 검사, docs 검사, Python Skills, `android` |
| `blacksmith-32vcpu-windows-2025` | `checks-windows` |
| `blacksmith-12vcpu-macos-latest` | `macos-node`, `macos-swift` on `openclaw/openclaw`; 포크는 `macos-latest`로 대체됩니다 |
## 로컬 대응 항목
```bash
pnpm changed:lanes # origin/main...HEAD에 대한 로컬 changed-lane 분류기 확인
pnpm check:changed # 스마트 로컬 게이트: 경계 레인별 변경된 타입체크/lint/테스트
pnpm check # 빠른 로컬 게이트: 프로덕션 tsgo + 샤딩된 lint + 병렬 빠른 가드
pnpm changed:lanes # origin/main...HEAD에 대한 로컬 변경 레인 분류기 검사
pnpm check:changed # 스마트 로컬 게이트: 경계 레인별 변경 typecheck/lint/tests
pnpm check # 빠른 로컬 게이트: 프로덕션 tsgo + 샤딩된 lint + 병렬 빠른 guard
pnpm check:test-types
pnpm check:timed # 단계별 시간 측정이 포함된 동일 게이트
pnpm build:strict-smoke
@ -85,5 +86,5 @@ pnpm test # vitest 테스트
pnpm test:channels
pnpm test:contracts:channels
pnpm check:docs # docs 포맷 + lint + 깨진 링크
pnpm build # CI 아티팩트/build-smoke 레인이 중요할 때 dist 빌드
pnpm build # CI artifact/build-smoke 레인이 중요할 때 dist 빌드
```

View File

@ -1,41 +1,41 @@
---
read_when:
- 타이핑 표시 동작이나 기본값을 변경하는 경우
summary: OpenClaw가 타이핑 표시를 보여주는 시점과 이를 조정하는 방법
title: 타이핑 표시
- 입력 중 표시 동작 또는 기본값 변경하기
summary: OpenClaw가 입력 중 표시를 보여주는 경우와 이를 조정하는 방법
title: 입력 중 표시
x-i18n:
generated_at: "2026-04-05T12:41:15Z"
generated_at: "2026-04-22T06:00:33Z"
model: gpt-5.4
provider: openai
source_hash: 28c8c395a135fc0745181aab66a93582177e6acd0b3496debcbb98159a4f11dc
source_hash: 2e7e8ca448b6706b6f53fcb6a582be6d4a84715c82dfde3d53abe4268af3ae0d
source_path: concepts/typing-indicators.md
workflow: 15
---
# 타이핑 표시
# 입력 중 표시
실행이 활성 상태인 동안 타이핑 표시는 채팅 채널로 전송됩니다. 타이핑이 **언제** 시작되는지는
`agents.defaults.typingMode`로 제어하고, **얼마나 자주** 새로 고쳐지는지는 `typingIntervalSeconds`로 제어합니다.
실행이 활성화되어 있는 동안 입력 중 표시는 채팅 채널로 전송됩니다.
입력이 **언제** 시작되는지는 `agents.defaults.typingMode`로 제어하고, **얼마나 자주** 새로 고침되는지는 `typingIntervalSeconds`로 제어합니다.
## 기본값
`agents.defaults.typingMode`**설정되지 않은 경우**, OpenClaw는 레거시 동작을 유지합니다.
`agents.defaults.typingMode`**설정되지 않은 경우**, OpenClaw는 기존 동작을 유지합니다.
- **다이렉트 채팅**: 모델 루프가 시작되면 즉시 타이핑이 시작됩니다.
- **멘션이 있는 그룹 채팅**: 즉시 타이핑이 시작됩니다.
- **멘션이 없는 그룹 채팅**: 메시지 텍스트 스트리밍이 시작될 때만 타이핑이 시작됩니다.
- **Heartbeat 실행**: 타이핑이 비활성화됩니다.
- **개인 채팅**: 모델 루프가 시작되면 즉시 입력이 시작됩니다.
- **멘션이 있는 그룹 채팅**: 즉시 입력이 시작됩니다.
- **멘션이 없는 그룹 채팅**: 메시지 텍스트 스트리밍이 시작될 때만 입력이 시작됩니다.
- **Heartbeat 실행**: 확인된 Heartbeat 대상이 입력 중 표시를 지원하는 채팅이고 입력 중 표시가 비활성화되어 있지 않으면, Heartbeat 실행이 시작될 때 입력이 시작됩니다.
## 모드
`agents.defaults.typingMode`를 다음 중 하나로 설정하세요.
`agents.defaults.typingMode`를 다음 중 하나로 설정합니다.
- `never`어떤 경우에도 타이핑 표시를 보내지 않습니다.
- `instant` — 실행이 나중에 무음 응답 토큰만 반환하더라도, **모델 루프가 시작되자마자** 타이핑을 시작합니다.
- `thinking` — **첫 reasoning delta**에서 타이핑을 시작합니다(실행에 `reasoningLevel: "stream"` 필요).
- `message` — **첫 번째 무음이 아닌 텍스트 delta**에서 타이핑을 시작합니다(`NO_REPLY` 무음 토큰은 무시).
- `never`입력 중 표시를 전혀 보내지 않습니다.
- `instant` — 실행이 나중에 무음 응답 토큰만 반환하더라도, **모델 루프가 시작되자마자** 입력을 시작합니다.
- `thinking` — **첫 번째 reasoning delta**에서 입력을 시작합니다(이 실행에 `reasoningLevel: "stream"` 필요).
- `message` — **첫 번째 비무음 텍스트 delta**에서 입력을 시작합니다(`NO_REPLY` 무음 토큰은 무시).
“얼마나 일찍 시작되는지”의 순서는 다음과 같습니다:
“얼마나 빨리 시작되는지” 순서:
`never``message``thinking``instant`
## 구성
@ -49,7 +49,7 @@ x-i18n:
}
```
세션별로 모드 또는 주기를 재정의할 수 있습니다.
세션별로 모드 주기를 재정의할 수 있습니다.
```json5
{
@ -62,9 +62,8 @@ x-i18n:
## 참고
- `message` 모드는 전체 페이로드가 정확히 무음 토큰일 때(예: `NO_REPLY` / `no_reply`, 대소문자 무시 일치) 무음 전용 응답에 대해 타이핑을 표시하지 않습니다.
- `thinking`은 실행이 reasoning을 스트리밍할 때만 동작합니다(`reasoningLevel: "stream"`).
모델이 reasoning delta를 내보내지 않으면 타이핑은 시작되지 않습니다.
- Heartbeat는 모드와 관계없이 타이핑을 표시하지 않습니다.
- `typingIntervalSeconds`는 시작 시간이 아니라 **새로 고침 주기**를 제어합니다.
기본값은 6초입니다.
- `message` 모드에서는 전체 페이로드가 정확히 무음 토큰인 경우 무음 전용 응답에 대해 입력 중 표시가 나타나지 않습니다(예: `NO_REPLY` / `no_reply`, 대소문자 구분 없이 일치).
- `thinking`은 실행이 reasoning을 스트리밍하는 경우에만 작동합니다(`reasoningLevel: "stream"`). 모델이 reasoning delta를 내보내지 않으면 입력이 시작되지 않습니다.
- Heartbeat 입력 중 표시는 확인된 전송 대상에 대한 활성 상태 신호입니다. `message` 또는 `thinking` 스트림 타이밍을 따르지 않고 Heartbeat 실행 시작 시 시작됩니다. 이를 비활성화하려면 `typingMode: "never"`로 설정하세요.
- `target: "none"`인 경우, 대상을 확인할 수 없는 경우, Heartbeat에 대해 채팅 전송이 비활성화된 경우, 또는 채널이 입력 중 표시를 지원하지 않는 경우 Heartbeat는 입력 중 표시를 보여주지 않습니다.
- `typingIntervalSeconds`는 시작 시간이 아니라 **새로 고침 주기**를 제어합니다. 기본값은 6초입니다.

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +1,41 @@
---
read_when:
- 하트비트 주기 또는 메시지 조정
- 예약 작업에 대해 하트비트와 cron 중 무엇을 사용할지 결정하기
summary: 하트비트 폴링 메시지 및 알림 규칙
title: 하트비트
- Heartbeat 주기 또는 메시지 조정
- 예약된 작업에 대해 Heartbeat와 Cron 중에서 결정하기
summary: Heartbeat 폴링 메시지 및 알림 규칙
title: Heartbeat
x-i18n:
generated_at: "2026-04-11T02:44:53Z"
generated_at: "2026-04-22T06:00:32Z"
model: gpt-5.4
provider: openai
source_hash: e4485072148753076d909867a623696829bf4a82dcd0479b95d5d0cae43100b0
source_hash: 13004e4e20b02b08aaf16f22cdf664d0b59da69446ecb30453db51ffdfd1d267
source_path: gateway/heartbeat.md
workflow: 15
---
# 하트비트 (Gateway)
# Heartbeat (Gateway)
> **하트비트와 Cron 중 무엇을 써야 하나요?** 언제 무엇을 사용할지에 대한 안내는 [Automation & Tasks](/ko/automation)를 참고하세요.
> **Heartbeat vs Cron?** 각각을 언제 사용해야 하는지에 대한 안내는 [자동화 및 작업](/ko/automation)을 참고하세요.
하트비트는 **주기적인 에이전트 턴**을 메인 세션에서 실행하여,
모델이 사용자에게 과도한 메시지를 보내지 않으면서 주의가 필요한 사항을 알려줄 수 있게 합니다.
Heartbeat는 메인 세션에서 **주기적인 에이전트 턴**을 실행하여,
모델이 과도하게 메시지를 보내지 않으면서 주의가 필요한 사항을 알려줄 수 있게 합니다.
하트비트는 예약된 메인 세션 턴이며, [background task](/ko/automation/tasks) 레코드를 생성하지 **않습니다**.
작업 레코드는 분리된 작업(ACP 실행, 서브에이전트, 격리된 cron 작업)을 위한 것입니다.
Heartbeat는 예약된 메인 세션 턴이며, [백그라운드 작업](/ko/automation/tasks) 레코드를 생성하지 **않습니다**.
작업 레코드는 분리된 작업(ACP 실행, 서브에이전트, 격리된 Cron 작업)에 사용됩니다.
문제 해결: [Scheduled Tasks](/ko/automation/cron-jobs#troubleshooting)
문제 해결: [예약된 작업](/ko/automation/cron-jobs#troubleshooting)
## 빠른 시작 (초보자)
1. 하트비트를 활성화된 상태로 둡니다(기본값은 `30m`, Anthropic OAuth/token 인증(Claude CLI 재사용 포함)일 때는 `1h`) 또는 원하는 주기를 설정합니다.
2. 에이전트 워크스페이스에 작은 `HEARTBEAT.md` 체크리스트 또는 `tasks:` 블록을 만듭니다(선택 사항이지만 권장).
3. 하트비트 메시지를 어디로 보낼지 결정합니다(`target: "none"`이 기본값이며, 마지막 연락처로 라우팅하려면 `target: "last"`로 설정).
4. 선택 사항: 투명성을 위해 하트비트 reasoning 전달을 활성화합니다.
5. 선택 사항: 하트비트 실행에 `HEARTBEAT.md`만 필요하다면 가벼운 bootstrap 컨텍스트를 사용합니다.
6. 선택 사항: 매 하트비트마다 전체 대화 기록을 보내지 않도록 격리 세션을 활성화합니다.
7. 선택 사항: 하트비트를 활성 시간대로 제한합니다(로컬 시간).
1. Heartbeat를 활성화된 상태로 두세요(기본값은 `30m`, Anthropic OAuth/토큰 인증(Claude CLI 재사용 포함)의 경우 `1h`) 또는 원하는 주기를 직접 설정하세요.
2. 에이전트 작업 공간에 작은 `HEARTBEAT.md` 체크리스트 또는 `tasks:` 블록을 만드세요(선택 사항이지만 권장).
3. Heartbeat 메시지를 어디로 보낼지 결정하세요(기본값은 `target: "none"`이며, 마지막 연락처로 보내려면 `target: "last"`로 설정).
4. 선택 사항: 투명성을 위해 heartbeat reasoning 전달을 활성화하세요.
5. 선택 사항: heartbeat 실행에 `HEARTBEAT.md`만 필요하다면 경량 부트스트랩 컨텍스트를 사용하세요.
6. 선택 사항: 각 heartbeat마다 전체 대화 기록을 보내지 않도록 격리된 세션을 활성화하세요.
7. 선택 사항: heartbeat를 활성 시간대(로컬 시간)로 제한하세요.
예시 구성:
예시 config:
```json5
{
@ -43,10 +43,10 @@ x-i18n:
defaults: {
heartbeat: {
every: "30m",
target: "last", // 마지막 연락처로 명시적으로 전달 (기본값은 "none")
directPolicy: "allow", // 기본값: direct/DM 대상 허용; 억제하려면 "block"으로 설정
lightContext: true, // 선택 사항: bootstrap 파일에서 HEARTBEAT.md만 주입
isolatedSession: true, // 선택 사항: 매 실행마다 새 세션 사용(대화 기록 없음)
target: "last", // 마지막 연락처로 명시적 전달 (기본값은 "none")
directPolicy: "allow", // 기본값: 직접/DM 대상 허용; 억제하려면 "block"으로 설정
lightContext: true, // 선택 사항: 부트스트랩 파일에서 HEARTBEAT.md만 주입
isolatedSession: true, // 선택 사항: 매 실행마다 새 세션 사용 (대화 기록 없음)
// activeHours: { start: "08:00", end: "24:00" },
// includeReasoning: true, // 선택 사항: 별도의 `Reasoning:` 메시지도 전송
},
@ -57,61 +57,62 @@ x-i18n:
## 기본값
- 간격: `30m` (또는 감지된 인증 모드가 Anthropic OAuth/token 인증인 경우 `1h`, Claude CLI 재사용 포함). `agents.defaults.heartbeat.every` 또는 에이전트별 `agents.list[].heartbeat.every`를 설정하세요. 비활성화하려면 `0m`을 사용합니다.
- 간격: `30m` (Anthropic OAuth/토큰 인증이 감지된 인증 모드이고 Claude CLI 재사용을 포함하는 경우 `1h`). `agents.defaults.heartbeat.every` 또는 에이전트별 `agents.list[].heartbeat.every`를 설정하세요. 비활성화하려면 `0m`을 사용합니다.
- 프롬프트 본문(`agents.defaults.heartbeat.prompt`로 구성 가능):
`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`
- 하트비트 프롬프트는 사용자 메시지로 **그대로** 전송됩니다. 시스템
프롬프트에는 기본 에이전트에 대해 하트비트가 활성화되어 있고
실행이 내부적으로 하트비트로 표시된 경우에만 “Heartbeat” 섹션이 포함됩니다.
- `0m`으로 하트비트를 비활성화하면 일반 실행도 bootstrap 컨텍스트에서
`HEARTBEAT.md`를 제외하므로 모델이 하트비트 전용 지침을 보지 않습니다.
- 활성 시간(`heartbeat.activeHours`)은 구성된 시간대에서 검사됩니다.
시간대 밖에서는 다음 유효 시간대의 틱까지 하트비트를 건너뜁니다.
- heartbeat 프롬프트는 사용자 메시지로 **있는 그대로** 전송됩니다. 시스템
프롬프트에는 기본 에이전트에 대해 heartbeat가 활성화되어 있고,
실행에 내부 플래그가 설정된 경우에만 “Heartbeat” 섹션이 포함됩니다.
- heartbeat가 `0m`으로 비활성화되면 일반 실행에서도 부트스트랩 컨텍스트에서 `HEARTBEAT.md`가 제외되어
모델이 heartbeat 전용 지침을 보지 않게 됩니다.
- 활성 시간(`heartbeat.activeHours`)은 구성된 시간대에서 확인됩니다.
시간 창 밖에서는 창 안의 다음 틱까지 heartbeat가 건너뛰어집니다.
## 하트비트 프롬프트의 목적
## heartbeat 프롬프트의 용도
기본 프롬프트는 의도적으로 폭넓게 설계되어 있습니다:
- **백그라운드 작업**: “Consider outstanding tasks”는 에이전트가
후속 작업(받은편지함, 캘린더, 리마인더, 대기 중인 작업)을 검토하고 긴급한 사항을 알리도록 유도합니다.
- **사람 확인**: “Checkup sometimes on your human during day time”는
가벼운 “필요한 것 있나요?” 메시지를 가끔 보내도록 유도하지만, 설정된 로컬 시간대를 사용해
야간 스팸은 피합니다([/concepts/timezone](/ko/concepts/timezone) 참고).
후속 조치(받은편지함, 캘린더, 미리 알림, 대기 중인 작업)를 검토하고
긴급한 사항을 알려주도록 유도합니다.
- **사람 체크인**: “Checkup sometimes on your human during day time”은
가벼운 “필요한 것 있으세요?” 메시지를 때때로 보내도록 유도하지만,
구성된 로컬 시간대를 사용해 야간 스팸은 피합니다([/concepts/timezone](/ko/concepts/timezone) 참고).
하트비트는 완료된 [background tasks](/ko/automation/tasks)에 반응할 수 있지만, 하트비트 실행 자체는 작업 레코드를 생성하지 않습니다.
Heartbeat는 완료된 [백그라운드 작업](/ko/automation/tasks)에 반응할 수 있지만, heartbeat 실행 자체가 작업 레코드를 생성하지는 않습니다.
하트비트가 매우 구체적인 작업(예: “Gmail PubSub
Heartbeat가 매우 구체적인 작업(예: “Gmail PubSub
통계 확인” 또는 “gateway 상태 검증”)을 하도록 하려면 `agents.defaults.heartbeat.prompt`(또는
`agents.list[].heartbeat.prompt`)를 사용자 정 본문으로 설정하세요(그대로 전송됨).
`agents.list[].heartbeat.prompt`)를 사용자 정 본문으로 설정하세요(있는 그대로 전송됨).
## 응답 계약
- 주의가 필요한 것이 없으면 **`HEARTBEAT_OK`**로 응답합니다.
- 하트비트 실행 중 OpenClaw는 응답의 **시작 또는 끝**에 `HEARTBEAT_OK`가 있으면
이를 ack로 처리합니다. 토큰은 제거되며, 남은 내용이
**`ackMaxChars` 이하**(기본값: 300)면 응답은 폐기됩니다.
- `HEARTBEAT_OK`가 응답의 **중간**에 있으면 특별하게 처리되지
않습니다.
- 경고의 경우 **`HEARTBEAT_OK`를 포함하지 말고** 경고 텍스트만 반환하세요.
- 주의가 필요한 사항이 없으면 **`HEARTBEAT_OK`**로 응답하세요.
- heartbeat 실행 중 OpenClaw는 응답의 **시작 또는 끝**에
`HEARTBEAT_OK`가 나타나면 이를 ack로 처리합니다. 토큰은 제거되며,
남은 내용이 **`ackMaxChars`**(기본값: 300)인 경우 응답은 폐기됩니다.
- `HEARTBEAT_OK`가 응답의 **중간**에 나타나면 특별히
처리되지 않습니다.
- 알림의 경우 **`HEARTBEAT_OK`를 포함하지 말고** 알림 텍스트만 반환하세요.
하트비트 외 실행에서는 메시지 시작/끝의 의도치 않은 `HEARTBEAT_OK`가 제거되고
로그에 기록됩니다. 메시지가 `HEARTBEAT_OK`만으로 이루어져 있으면 폐기됩니다.
heartbeat 외부에서는 메시지 시작/끝의 의도치 않은 `HEARTBEAT_OK`가 제거되어
로그에 기록되며, 메시지가 `HEARTBEAT_OK`만으로 이루어진 경우 폐기됩니다.
## 구성
## Config
```json5
{
agents: {
defaults: {
heartbeat: {
every: "30m", // 기본값: 30m (0m이면 비활성화)
every: "30m", // 기본값: 30m (`0m`은 비활성화)
model: "anthropic/claude-opus-4-6",
includeReasoning: false, // 기본값: false (가능할 때 별도의 Reasoning: 메시지 전달)
lightContext: false, // 기본값: false; true이면 워크스페이스 bootstrap 파일에서 HEARTBEAT.md만 유지
isolatedSession: false, // 기본값: false; true이면 매 하트비트를 새 세션에서 실행(대화 기록 없음)
target: "last", // 기본값: none | 옵션: last | none | <channel id> (core 또는 plugin, 예: "bluebubbles")
includeReasoning: false, // 기본값: false (사용 가능할 때 별도의 Reasoning: 메시지 전달)
lightContext: false, // 기본값: false; true이면 작업 공간 부트스트랩 파일에서 HEARTBEAT.md만 유지
isolatedSession: false, // 기본값: false; true이면 각 heartbeat를 새 세션에서 실행 (대화 기록 없음)
target: "last", // 기본값: none | 옵션: last | none | <channel id> (코어 또는 Plugin, 예: "bluebubbles")
to: "+15551234567", // 선택적 채널별 override
accountId: "ops-bot", // 선택적 멀티 계정 채널 id
accountId: "ops-bot", // 선택적 다중 계정 채널 id
prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.",
ackMaxChars: 300, // HEARTBEAT_OK 뒤에 허용되는 최대 문자 수
},
@ -120,21 +121,21 @@ x-i18n:
}
```
### 범위 우선순위
### 범위 우선순위
- `agents.defaults.heartbeat`는 전역 하트비트 동작을 설정합니다.
- `agents.list[].heartbeat`는 그 위에 병합되며, 어떤 에이전트든 `heartbeat` 블록이 있으면 **그 에이전트들만** 하트비트를 실행합니다.
- `agents.defaults.heartbeat`는 전역 heartbeat 동작을 설정합니다.
- `agents.list[].heartbeat`는 그 위에 병합됩니다. 어떤 에이전트든 `heartbeat` 블록이 있으면 **해당 에이전트들만** heartbeat를 실행합니다.
- `channels.defaults.heartbeat`는 모든 채널의 가시성 기본값을 설정합니다.
- `channels.<channel>.heartbeat`는 채널 기본값을 override합니다.
- `channels.<channel>.accounts.<id>.heartbeat`(멀티 계정 채널)는 채널별 설정을 override합니다.
- `channels.<channel>.accounts.<id>.heartbeat`(다중 계정 채널)는 채널별 설정을 override합니다.
### 에이전트별 하트비트
### 에이전트별 heartbeat
어떤 `agents.list[]` 항목이든 `heartbeat` 블록을 포함하면 **그 에이전트들만**
하트비트를 실행합니다. 에이전트별 블록은 `agents.defaults.heartbeat`
위에 병합되므로 공통 기본값을 한 번만 설정하고 에이전트별로 override할 수 있습니다.
어떤 `agents.list[]` 항목에든 `heartbeat` 블록이 포함되면 **해당 에이전트들만**
heartbeat를 실행합니다. 에이전트별 블록은 `agents.defaults.heartbeat`
위에 병합되므로, 공통 기본값을 한 번만 설정하고 에이전트별로 override할 수 있습니다.
예시: 에이전트가 두 개이고, 두 번째 에이전트만 하트비트를 실행합니다.
예시: 에이전트 두 개 중 두 번째 에이전트만 heartbeat를 실행합니다.
```json5
{
@ -142,7 +143,7 @@ x-i18n:
defaults: {
heartbeat: {
every: "30m",
target: "last", // 마지막 연락처로 명시적으로 전달 (기본값은 "none")
target: "last", // 마지막 연락처로 명시적 전달 (기본값은 "none")
},
},
list: [
@ -164,7 +165,7 @@ x-i18n:
### 활성 시간 예시
특정 시간대의 업무 시간으로 하트비트를 제한합니다:
특정 시간대의 업무 시간으로 heartbeat를 제한합니다:
```json5
{
@ -172,7 +173,7 @@ x-i18n:
defaults: {
heartbeat: {
every: "30m",
target: "last", // 마지막 연락처로 명시적으로 전달 (기본값은 "none")
target: "last", // 마지막 연락처로 명시적 전달 (기본값은 "none")
activeHours: {
start: "09:00",
end: "22:00",
@ -184,21 +185,21 @@ x-i18n:
}
```
이 시간대(동부 시간 기준 오전 9시 이전 또는 오후 10시 이후) 밖에서는 하트비트를 건너뜁니다. 창 안의 다음 예약 틱은 정상적으로 실행됩니다.
이 시간 창 밖(동부 표준시 기준 오전 9시 이전 또는 오후 10시 이후)에서는 heartbeat가 건너뛰어집니다. 창 안의 다음 예약 틱은 정상적으로 실행됩니다.
### 24/7 설정
하트비트를 하루 종일 실행하려면 다음 패턴 중 하나를 사용하세요:
Heartbeat를 하루 종일 실행하려면 다음 패턴 중 하나를 사용하세요:
- `activeHours`아예 생략합니다(시간대 제한 없음, 기본 동작).
- `activeHours`완전히 생략합니다(시간 창 제한 없음; 이것이 기본 동작입니다).
- 하루 전체 창을 설정합니다: `activeHours: { start: "00:00", end: "24:00" }`.
같은 `start``end` 시간을 설정하지 마세요(예: `08:00`에서 `08:00`).
이 경우 너비가 0인 창으로 처리되어 하트비트가 항상 건너뛰어집니다.
`start``end`를 같은 시간(예: `08:00`에서 `08:00`)으로 설정하지 마세요.
이 경우 너비가 0인 창으로 처리되어 heartbeat가 항상 건너뛰어집니다.
### 멀티 계정 예시
### 다중 계정 예시
Telegram과 같은 멀티 계정 채널에서 특정 계정을 대상으로 하려면 `accountId`를 사용합니다:
Telegram 같은 다중 계정 채널에서 특정 계정을 대상으로 하려면 `accountId`를 사용하세요:
```json5
{
@ -227,64 +228,67 @@ Telegram과 같은 멀티 계정 채널에서 특정 계정을 대상으로 하
### 필드 참고
- `every`: 하트비트 간격(duration 문자열, 기본 단위 = 분).
- `model`: 하트비트 실행용 선택적 모델 override (`provider/model`).
- `includeReasoning`: 활성화하면 가능할 때 별도의 `Reasoning:` 메시지도 전달합니다(`/reasoning on`과 동일한 형).
- `lightContext`: true이면 하트비트 실행은 가벼운 bootstrap 컨텍스트를 사용하고 워크스페이스 bootstrap 파일에서 `HEARTBEAT.md`만 유지합니다.
- `isolatedSession`: true이면 각 하트비트는 이전 대화 기록이 없는 새 세션에서 실행됩니다. cron의 `sessionTarget: "isolated"`와 동일한 격리 패턴을 사용합니다. 하트비트당 토큰 비용을 크게 줄여줍니다. 최대 절감을 위해 `lightContext: true`와 함께 사용하세요. 전달 라우팅은 여전히 메인 세션 컨텍스트를 사용합니다.
- `session`: 하트비트 실행용 선택적 세션 키.
- `main` (기본값): 에이전트 메인 세션.
- `every`: heartbeat 간격(기간 문자열, 기본 단위 = 분).
- `model`: heartbeat 실행용 선택적 모델 override (`provider/model`).
- `includeReasoning`: 활성화되면 사용 가능할 때 별도의 `Reasoning:` 메시지도 전달합니다(`/reasoning on`과 동일한 형).
- `lightContext`: true이면 heartbeat 실행은 경량 부트스트랩 컨텍스트를 사용하고 작업 공간 부트스트랩 파일에서는 `HEARTBEAT.md`만 유지합니다.
- `isolatedSession`: true이면 각 heartbeat는 이전 대화 기록 없이 새 세션에서 실행됩니다. Cron의 `sessionTarget: "isolated"`와 동일한 격리 패턴을 사용합니다. heartbeat당 토큰 비용을 크게 줄입니다. 최대 절감을 위해 `lightContext: true`와 함께 사용하세요. 전달 라우팅은 여전히 메인 세션 컨텍스트를 사용합니다.
- `session`: heartbeat 실행용 선택적 세션 키.
- `main`(기본값): 에이전트 메인 세션.
- 명시적 세션 키(`openclaw sessions --json` 또는 [sessions CLI](/cli/sessions)에서 복사).
- 세션 키 형식 [Sessions](/ko/concepts/session) 및 [Groups](/ko/channels/groups)를 참고하세요.
- 세션 키 형식: [Sessions](/ko/concepts/session) 및 [Groups](/ko/channels/groups)를 참고하세요.
- `target`:
- `last`: 마지막으로 사용한 외부 채널로 전달.
- 명시적 채널: 구성된 모든 채널 또는 plugin id(예: `discord`, `matrix`, `telegram`, `whatsapp`).
- `none` (기본값): 하트비트를 실행하지만 외부로는 **전달하지 않음**.
- `directPolicy`: direct/DM 전달 동작을 제어합니다:
- `allow` (기본값): direct/DM 하트비트 전달 허용.
- `block`: direct/DM 전달 억제(`reason=dm-blocked`).
- `to`: 선택적 수신자 override(채널별 id, 예: WhatsApp의 E.164 또는 Telegram chat id). Telegram topic/thread에는 `<chatId>:topic:<messageThreadId>`를 사용하세요.
- `accountId`: 멀티 계정 채널용 선택적 계정 id. `target: "last"`일 때, 마지막으로 확인된 채널이 계정을 지원하면 그 채널에 적용되고, 그렇지 않으면 무시됩니다. 계정 id가 확인된 채널에 구성된 계정과 일치하지 않으면 전달은 건너뜁니다.
- 명시적 채널: 구성된 모든 채널 또는 Plugin id(예: `discord`, `matrix`, `telegram`, `whatsapp`).
- `none`(기본값): heartbeat는 실행하지만 외부로는 **전달하지 않음**.
- `directPolicy`: 직접/DM 전달 동작을 제어합니다.
- `allow`(기본값): 직접/DM heartbeat 전달 허용.
- `block`: 직접/DM 전달 억제(`reason=dm-blocked`).
- `to`: 선택적 수신자 override(채널별 id, 예: WhatsApp용 E.164 또는 Telegram chat id). Telegram topic/thread의 경우 `<chatId>:topic:<messageThreadId>`를 사용하세요.
- `accountId`: 다중 계정 채널용 선택적 계정 id. `target: "last"`일 때 resolved된 마지막 채널이 계정을 지원하면 account id가 적용되고, 아니면 무시됩니다. account id가 resolved된 채널의 구성된 계정과 일치하지 않으면 전달이 건너뛰어집니다.
- `prompt`: 기본 프롬프트 본문을 override합니다(병합되지 않음).
- `ackMaxChars`: `HEARTBEAT_OK` 뒤에 허용되는 최대 문자 수.
- `suppressToolErrorWarnings`: true이면 하트비트 실행 중 도구 오류 경고 payload를 억제합니다.
- `activeHours`: 하트비트 실행을 특정 시간 창으로 제한합니다. `start`(HH:MM, 포함, 하루 시작은 `00:00` 사용), `end`(HH:MM, 제외, 하루 끝`24:00` 허용), 선택적 `timezone`이 있는 객체입니다.
- 생략 또는 `"user"`: `agents.defaults.userTimezone`이 설정되어 있으면 그것을 사용하고, 아니면 호스트 시스템 시간대로 대체합니다.
- `ackMaxChars`: 전달 전에 `HEARTBEAT_OK` 뒤에 허용되는 최대 문자 수.
- `suppressToolErrorWarnings`: true이면 heartbeat 실행 중 도구 오류 경고 payload를 억제합니다.
- `activeHours`: heartbeat 실행을 시간 창으로 제한합니다. `start`(HH:MM, 포함, 하루 시작은 `00:00` 사용), `end`(HH:MM, 제외, 하루 끝으로 `24:00` 허용), 선택적 `timezone`을 포함하는 객체입니다.
- 생략되었거나 `"user"`인 경우: `agents.defaults.userTimezone`이 설정되어 있으면 이를 사용하고, 아니면 호스트 시스템 시간대로 대체합니다.
- `"local"`: 항상 호스트 시스템 시간대를 사용합니다.
- 모든 IANA 식별자(예: `America/New_York`): 직접 사용하며, 유효하지 않으면 위 `"user"` 동작으로 대체됩니다.
- 활성 창에서는 `start``end`가 같아서는 안 됩니다. 같으면 너비가 0인 창(항상 창 밖)으로 처리됩니다.
- 활성 시간 창 밖에서는 창 안의 다음 틱까지 하트비트를 건너뜁니다.
- 모든 IANA 식별자(예: `America/New_York`): 직접 사용되며, 유효하지 않으면 위의 `"user"` 동작으로 대체됩니다.
- 활성 시간 창으로 간주되려면 `start``end`가 같아서는 안 됩니다. 같은 값은 너비가 0인 창(항상 창 밖)으로 처리됩니다.
- 활성 시간 창 밖에서는 창 안의 다음 틱까지 heartbeat가 건너뛰어집니다.
## 전달 동작
- 하트비트는 기본적으로 에이전트의 메인 세션(`agent:<id>:<mainKey>`)에서 실행되며,
`session.scope = "global"`일 때는 `global`에서 실행됩니다. 특정 채널 세션(Discord/WhatsApp 등)으로
- Heartbeat는 기본적으로 에이전트의 메인 세션(`agent:<id>:<mainKey>`)에서 실행되며,
`session.scope = "global"`이면 `global`에서 실행됩니다. 특정 채널 세션(Discord/WhatsApp 등)으로
override하려면 `session`을 설정하세요.
- `session`은 실행 컨텍스트에만 영향을 주며, 전달은 `target``to`로 제어됩니다.
- 특정 채널/수신자에게 전달하려면 `target` + `to`를 설정하세요.
`target: "last"`를 사용하면 전달은 해당 세션의 마지막 외부 채널을 사용합니다.
- 하트비트 전달은 기본적으로 direct/DM 대상을 허용합니다. direct 대상 전송은 억제하면서 하트비트 턴은 계속 실행하려면 `directPolicy: "block"`을 설정하세요.
- 메인 큐가 바쁘면 하트비트는 건너뛰고 나중에 다시 시도합니다.
- `target`이 외부 대상이 없는 것으로 확인되면 실행은 계속되지만
발신 메시지는 전송되지 않습니다.
- `showOk`, `showAlerts`, `useIndicator`가 모두 비활성화되면 실행은 사전에 `reason=alerts-disabled`로 건너뜁니다.
- 경고 전달만 비활성화된 경우에도 OpenClaw는 하트비트를 실행하고, 기한이 된 작업 타임스탬프를 갱신하고, 세션 idle 타임스탬프를 복원하고, 외부 경고 payload는 억제할 수 있습니다.
- 하트비트 전용 응답은 세션을 활성 상태로 유지하지 않습니다. 마지막 `updatedAt`
`target: "last"`일 때는 해당 세션의 마지막 외부 채널을 사용해 전달합니다.
- Heartbeat 전달은 기본적으로 직접/DM 대상을 허용합니다. 직접 대상 전송을 억제하면서 heartbeat 턴은 계속 실행하려면 `directPolicy: "block"`을 설정하세요.
- 메인 큐가 바쁘면 heartbeat는 건너뛰어지고 나중에 다시 시도됩니다.
- `target`이 외부 대상으로 resolve되지 않으면 실행은 계속되지만
외부로 보내는 메시지는 전송되지 않습니다.
- `showOk`, `showAlerts`, `useIndicator`가 모두 비활성화되어 있으면 실행은 사전에 `reason=alerts-disabled`로 건너뛰어집니다.
- 알림 전달만 비활성화된 경우에도 OpenClaw는 heartbeat를 실행하고, due-task 타임스탬프를 업데이트하고, 세션 idle 타임스탬프를 복원하며, 외부 알림 payload는 억제할 수 있습니다.
- resolve된 heartbeat 대상이 타이핑을 지원하면 OpenClaw는
heartbeat 실행이 활성 상태인 동안 타이핑 표시를 보여줍니다. 이는 heartbeat가
채팅 출력을 보낼 것과 동일한 대상을 사용하며, `typingMode: "never"`로 비활성화됩니다.
- Heartbeat 전용 응답은 세션을 활성 상태로 유지하지 않습니다. 마지막 `updatedAt`
값이 복원되므로 idle 만료는 정상적으로 동작합니다.
- 분리된 [background tasks](/ko/automation/tasks)는 시스템 이벤트를 큐에 넣고 메인 세션이 무언가를 빨리 인지해야 할 때 하트비트를 깨울 수 있습니다. 이 깨우기 동작이 하트비트 실행을 background task로 만들지는 않습니다.
- 분리된 [백그라운드 작업](/ko/automation/tasks)은 시스템 이벤트를 큐에 넣어 메인 세션이 무언가를 빠르게 알아차려야 할 때 heartbeat를 깨울 수 있습니다. 이 wake는 heartbeat 실행을 백그라운드 작업으로 만들지는 않습니다.
## 가시성 제어
기본적으로 `HEARTBEAT_OK` 확인 응답은 숨겨지고 경고 콘텐츠는
전달됩니다. 채널별 또는 계정별로 이를 조정할 수 있습니다:
기본적으로 `HEARTBEAT_OK` 확인 응답은 숨겨지고, 알림 콘텐츠는
전달됩니다. 이를 채널별 또는 계정별로 조정할 수 있습니다:
```yaml
channels:
defaults:
heartbeat:
showOk: false # HEARTBEAT_OK 숨기기 (기본값)
showAlerts: true # 경고 메시지 표시 (기본값)
useIndicator: true # 인디케이터 이벤트 내보내기 (기본값)
showAlerts: true # 알림 메시지 표시 (기본값)
useIndicator: true # indicator 이벤트 발생 (기본값)
telegram:
heartbeat:
showOk: true # Telegram에서 OK 확인 응답 표시
@ -292,7 +296,7 @@ channels:
accounts:
work:
heartbeat:
showAlerts: false # 이 계정에 대한 경고 전달 억제
showAlerts: false # 이 계정의 알림 전달 억제
```
우선순위: 계정별 → 채널별 → 채널 기본값 → 내장 기본값.
@ -300,10 +304,10 @@ channels:
### 각 플래그의 역할
- `showOk`: 모델이 OK 전용 응답을 반환할 때 `HEARTBEAT_OK` 확인 응답을 전송합니다.
- `showAlerts`: 모델이 OK가 아닌 응답을 반환할 때 경고 콘텐츠를 전송합니다.
- `useIndicator`: UI 상태 화면용 인디케이터 이벤트를 내보냅니다.
- `showAlerts`: 모델이 비-OK 응답을 반환할 때 알림 콘텐츠를 전송합니다.
- `useIndicator`: UI 상태 표시 영역용 indicator 이벤트를 발생시킵니다.
**세 값이 모두** false이면 OpenClaw는 하트비트 실행 자체를 건너뜁니다(모델 호출 없음).
**세 가지가 모두** false이면 OpenClaw는 heartbeat 실행 자체를 건너뜁니다(모델 호출 없음).
### 채널별 vs 계정별 예시
@ -320,7 +324,7 @@ channels:
accounts:
ops:
heartbeat:
showAlerts: false # ops 계정에 대해서만 경고 억제
showAlerts: false # ops 계정에 대해서만 알림 억제
telegram:
heartbeat:
showOk: true
@ -328,44 +332,45 @@ channels:
### 일반적인 패턴
| 목표 | 구성 |
| --- | --- |
| 기본 동작 (OK는 숨김, 경고는 표시) | _(구성 불필요)_ |
| 완전히 무음 (메시지 없음, 인디케이터 없음) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: false }` |
| 인디케이터만 사용 (메시지 없음) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: true }` |
| 목표 | Config |
| ---------------------------------------- | ---------------------------------------------------------------------------------------- |
| 기본 동작 (조용한 OK, 알림 켜짐) | _(config 불필요)_ |
| 완전히 조용하게 (메시지 없음, indicator 없음) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: false }` |
| indicator만 사용 (메시지 없음) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: true }` |
| 한 채널에서만 OK 표시 | `channels.telegram.heartbeat: { showOk: true }` |
## HEARTBEAT.md (선택 사항)
워크스페이스`HEARTBEAT.md` 파일이 있으면 기본 프롬프트는
에이전트가 이를 읽도록 지시합니다. 이를 “하트비트 체크리스트”라고 생각하면 됩니다: 작고, 안정적이며,
작업 공간`HEARTBEAT.md` 파일이 있으면 기본 프롬프트는
에이전트에게 해당 파일을 읽으라고 지시합니다. 이를 “heartbeat 체크리스트”로 생각하세요: 작고, 안정적이며,
30분마다 포함해도 안전한 내용입니다.
일반 실행에서는 기본 에이전트에 대해 하트비트 지침이
활성화된 경우에만 `HEARTBEAT.md`가 주입됩니다. `0m`으로 하트비트 주기를 비활성화하거나
`includeSystemPromptSection: false`를 설정하면 일반 bootstrap
일반 실행에서는 기본 에이전트에 대해 heartbeat 지침이
활성화된 경우에만 `HEARTBEAT.md`가 주입됩니다. heartbeat 주기를 `0m`으로 비활성화하거나
`includeSystemPromptSection: false`를 설정하면 일반 부트스트랩
컨텍스트에서 제외됩니다.
`HEARTBEAT.md`가 존재하지만 사실상 비어 있는 경우(빈 줄과 `# Heading` 같은 markdown
헤더만 있는 경우), OpenClaw는 API 호출을 절약하기 위해 하트비트 실행을 건너뜁니다.
이 건너뜀은 `reason=empty-heartbeat-file`로 보고됩니다.
파일이 없으면 하트비트는 계속 실행되며 모델이 무엇을 할지 결정합니다.
헤더만 있는 경우), OpenClaw는 API 호출을 절약하기 위해 heartbeat 실행을 건너뜁니다.
이 건너뛰기는 `reason=empty-heartbeat-file`로 보고됩니다.
파일이 없으면 heartbeat는 여전히 실행되며 모델이 무엇을 할지 결정합니다.
프롬프트 팽창을 피하려면 작게 유지하세요(짧은 체크리스트 또는 리마인더).
프롬프트가 불필요하게 커지지 않도록 작게 유지하세요(짧은 체크리스트나 미리 알림).
예시 `HEARTBEAT.md`:
```md
# Heartbeat checklist
# Heartbeat 체크리스트
- Quick scan: anything urgent in inboxes?
- If its daytime, do a lightweight check-in if nothing else is pending.
- If a task is blocked, write down _what is missing_ and ask Peter next time.
- 빠른 확인: 받은편지함에 긴급한 것이 있나요?
- 낮 시간이라면 다른 일이 없을 때 가볍게 안부를 확인하세요.
- 작업이 막혀 있으면 _무엇이 부족한지_ 적어두고 다음에 Peter에게 물어보세요.
```
### `tasks:` 블록
`HEARTBEAT.md`는 하트비트 내부에서 간격 기반 점검을 수행하기 위한 작은 구조화된 `tasks:` 블록도 지원합니다.
`HEARTBEAT.md`는 heartbeat 내부의 간격 기반
확인을 위한 작은 구조화된 `tasks:` 블록도 지원합니다.
예시:
@ -374,84 +379,85 @@ tasks:
- name: inbox-triage
interval: 30m
prompt: "Check for urgent unread emails and flag anything time sensitive."
prompt: "긴급한 읽지 않은 이메일이 있는지 확인하고 시간에 민감한 항목에 표시를 하세요."
- name: calendar-scan
interval: 2h
prompt: "Check for upcoming meetings that need prep or follow-up."
prompt: "준비나 후속 조치가 필요한 예정된 회의가 있는지 확인하세요."
# Additional instructions
# 추가 지침
- Keep alerts short.
- If nothing needs attention after all due tasks, reply HEARTBEAT_OK.
- 알림은 짧게 유지하세요.
- 기한이 지난 모든 작업을 확인한 뒤에도 주의가 필요한 것이 없으면 HEARTBEAT_OK로 응답하세요.
```
동작:
동작 방식:
- OpenClaw는 `tasks:` 블록을 파싱하고 각 작업을 자체 `interval`에 따라 검사합니다.
- 해당 틱에서 **기한이 된** 작업만 하트비트 프롬프트에 포함됩니다.
- 기한이 된 작업이 없으면 하트비트는 낭비되는 모델 호출을 피하기 위해 완전히 건너뜁니다(`reason=no-tasks-due`).
- `HEARTBEAT.md`의 작업 외 콘텐츠는 유지되며 기한이 된 작업 목록 뒤에 추가 컨텍스트로 덧붙여집니다.
- 작업 마지막 실행 타임스탬프는 세션 상태(`heartbeatTaskState`)에 저장되므로 일반적인 재시작 후에도 간격이 유지됩니다.
- 작업 타임스탬프는 하트비트 실행이 정상 응답 경로를 완료한 뒤에만 갱신됩니다. 건너뛴 `empty-heartbeat-file` / `no-tasks-due` 실행은 작업을 완료된 것으로 표시하지 않습니다.
- OpenClaw는 `tasks:` 블록을 파싱하고 각 작업을 자체 `interval` 기준으로 확인합니다.
- 해당 틱에서 **기한이 지난** 작업만 heartbeat 프롬프트에 포함됩니다.
- 기한이 지난 작업이 없으면 불필요한 모델 호출을 피하기 위해 heartbeat 전체가 건너뛰어집니다(`reason=no-tasks-due`).
- `HEARTBEAT.md`의 작업이 아닌 콘텐츠는 보존되며, 기한이 지난 작업 목록 뒤에 추가 컨텍스트로 덧붙여집니다.
- 작업 마지막 실행 타임스탬프는 세션 상태(`heartbeatTaskState`)에 저장되므로 간격 정보는 일반적인 재시작 후에도 유지됩니다.
- 작업 타임스탬프는 heartbeat 실행이 정상 응답 경로를 완료한 뒤에만 갱신됩니다. 건너뛴 `empty-heartbeat-file` / `no-tasks-due` 실행은 작업을 완료로 표시하지 않습니다.
작업 모드는 모든 틱에서 비용을 지불하지 않으면서 하나의 하트비트 파일에 여러 주기적 점검을 담고 싶을 때 유용합니다.
작업 모드는 하나의 heartbeat 파일에 여러 주기적 확인을 담고 싶지만, 매 틱마다 그 전부에 대한 비용을 지불하고 싶지 않을 때 유용합니다.
### 에이전트가 HEARTBEAT.md를 업데이트할 수 있나요?
네 — 그렇게 하라고 요청하면 가능합니다.
네 — 그렇게 하라고 요청하면 니다.
`HEARTBEAT.md`는 에이전트 워크스페이스에 있는 일반 파일일 뿐이므로,
일반 채팅에서 에이전트에게 다음과 같이 말할 수 있습니다:
`HEARTBEAT.md`는 에이전트 작업 공간의 일반 파일일 뿐이므로, 일반 채팅에서
에이전트에게 다음과 같이 말할 수 있습니다:
- “매일 캘린더 확인을 추가하도록 `HEARTBEAT.md`를 업데이트해.”
- “더 짧고 받은편지함 후속 작업에 집중되도록 `HEARTBEAT.md`를 다시 작성해.”
- “매일 캘린더 확인을 추가하도록 `HEARTBEAT.md`를 업데이트해.”
- “더 짧고 받은편지함 후속 조치에 집중하도록 `HEARTBEAT.md`를 다시 작성해줘.”
이를 더 능동적으로 수행하게 하려면 하트비트 프롬프트에 다음과 같은 명시적 문장을 포함할 수도 있습니다:
“체크리스트가 오래되면 더 나은 것으로 HEARTBEAT.md를 업데이트해.”
이를 선제적으로 수행하게 하고 싶다면, heartbeat 프롬프트에
“체크리스트가 오래되면 더 나은 내용으로 HEARTBEAT.md를 업데이트하라”
같은 명시적 문장을 포함할 수도 있습니다.
안전 참고: `HEARTBEAT.md`에는 비밀 정보(API 키, 전화번호, 개인 토큰)를 넣지 마세요.
이 파일은 프롬프트 컨텍스트의 일부가 됩니다.
안전 참고: 비밀 정보(API 키, 전화번호, 비공개 토큰)는
`HEARTBEAT.md`에 넣지 마세요. 프롬프트 컨텍스트의 일부가 됩니다.
## 수동 깨우기 (온디맨드)
## 수동 wake(온디맨드)
다음 명령으로 시스템 이벤트를 큐에 넣고 즉시 하트비트를 트리거할 수 있습니다:
다음 명령으로 시스템 이벤트를 큐에 넣고 즉시 heartbeat를 트리거할 수 있습니다:
```bash
openclaw system event --text "Check for urgent follow-ups" --mode now
openclaw system event --text "긴급한 후속 조치가 있는지 확인" --mode now
```
여러 에이전트에 `heartbeat`가 구성되어 있으면 수동 깨우기는 그 에이전트들의
하트비트를 즉시 각각 실행합니다.
여러 에이전트에 `heartbeat`가 구성되어 있으면 수동 wake는 해당
에이전트들의 heartbeat를 즉시 각각 실행합니다.
다음 예약 틱까지 기다리려면 `--mode next-heartbeat`를 사용하세요.
## reasoning 전달 (선택 사항)
## Reasoning 전달 (선택 사항)
기본적으로 하트비트는 최종 “응답” payload만 전달합니다.
기본적으로 heartbeat는 최종 “answer” payload만 전달합니다.
투명성을 원한다면 다음을 활성화하세요:
투명성이 필요하다면 다음을 활성화하세요:
- `agents.defaults.heartbeat.includeReasoning: true`
활성화하면 하트비트`Reasoning:` 접두사가 붙은 별도 메시지도 전달합니다
(`reasoning on`과 동일한 형태). 이는 에이전트가 여러 세션/codex를 관리하고 있을 때
사용자에게 알림을 보내기로 결정했는지 보고 싶을 때 유용할 수 있습니다.
하지만 원하지 않는 더 많은 내부 세부 정보가 드러날 수도 있습니다. 그룹 채팅에서는
끄는 편이 좋습니다.
활성화되면 heartbeat`Reasoning:` 접두사가 붙은 별도 메시지도 전달합니다
(` /reasoning on`과 동일한 형식). 에이전트가 여러 세션/codex를 관리하고 있어
나에게 ping을 보내기로 결정했는지 보고 싶을 때 유용할 수 있습니다.
하지만 원치 않는 내부 세부 정보가 더 많이 노출될 수도 있습니다. 그룹 채팅에서는
끄는 것을 권장합니다.
## 비용 고려
하트비트는 전체 에이전트 턴을 실행합니다. 간격이 짧을수록 토큰을 더 많이 사용합니다. 비용을 줄이려면:
Heartbeat는 전체 에이전트 턴을 실행합니다. 간격이 짧을수록 더 많은 토큰이 소모됩니다. 비용을 줄이려면:
- 전체 대화 기록 전송을 피하기 위해 `isolatedSession: true`를 사용하세요(실행당 약 100K 토큰에서 약 2~5K로 감소).
- bootstrap 파일을 `HEARTBEAT.md`로만 제한하려면 `lightContext: true`를 사용하세요.
- 전체 대화 기록 전송을 피하려면 `isolatedSession: true`를 사용하세요(실행당 약 100K 토큰에서 약 2-5K로 감소).
- 부트스트랩 파일을 `HEARTBEAT.md`만으로 제한하려면 `lightContext: true`를 사용하세요.
- 더 저렴한 `model`을 설정하세요(예: `ollama/llama3.2:1b`).
- `HEARTBEAT.md`를 작게 유지하세요.
- 내부 상태 업데이트만 원한다면 `target: "none"`을 사용하세요.
## 관련 항목
- [Automation & Tasks](/ko/automation) — 모든 자동화 메커니즘 한눈에 보기
- [Background Tasks](/ko/automation/tasks) — 분리된 작업이 추적되는 방식
- [Timezone](/ko/concepts/timezone) — 시간대가 하트비트 예약에 미치는 영향
- [Troubleshooting](/ko/automation/cron-jobs#troubleshooting) — 자동화 문제 디버깅
- [자동화 및 작업](/ko/automation) — 모든 자동화 메커니즘 한눈에 보기
- [백그라운드 작업](/ko/automation/tasks) — 분리된 작업이 추적되는 방식
- [시간대](/ko/concepts/timezone) — 시간대가 heartbeat 일정에 미치는 영향
- [문제 해결](/ko/automation/cron-jobs#troubleshooting) — 자동화 문제 디버깅

View File

@ -1,65 +1,68 @@
---
read_when:
- 번들 Codex app-server 하네스를 사용하려고 함
- Codex 모델 참조와 구성 예제가 필요
- Codex 전용 배포를 위해 Pi fallback을 비활성화하려고 함
summary: 번들 Codex app-server 하네스를 통해 OpenClaw 임베디드 에이전트 턴 실행
title: Codex 하
- 번들된 Codex 앱-서버 하니스를 사용하려고 합니다.
- Codex 모델 참조와 구성 예제가 필요합니다.
- Codex 전용 배포를 위해 Pi 폴백을 비활성화하려고 합니다.
summary: 번들된 Codex 앱-서버 하니스를 통해 OpenClaw 임베디드 에이전트 턴 실행합니다
title: Codex 하
x-i18n:
generated_at: "2026-04-21T06:05:03Z"
generated_at: "2026-04-22T06:00:35Z"
model: gpt-5.4
provider: openai
source_hash: 3f0cdaf68be3b2257de1046103ff04f53f9d3a65ffc15ab7af5ab1f425643d6c
source_hash: d45dbd39a7d8ebb3a39d8dca3a5125c07b7168d1658ca07b85792645fb98613c
source_path: plugins/codex-harness.md
workflow: 15
---
# Codex 하
# Codex 하
번들 `codex` Plugin을 사용하면 OpenClaw가 내장 PI 하네스 대신
Codex app-server를 통해 임베디드 에이전트 턴을 실행할 수 있습니다.
번들 `codex` Plugin을 사용하면 OpenClaw가 내장된 PI 하니스 대신
Codex 앱-서버를 통해 임베디드 에이전트 턴을 실행할 수 있습니다.
이는 Codex가 하위 수준 에이전트 세션을 직접 관리하도록 하고 싶을 때 사용합니다: 모델
검색, 네이티브 스레드 재개, 네이티브 Compaction, 그리고 app-server 실행입니다.
OpenClaw는 여전히 채팅 채널, 세션 파일, 모델 선택, 도구,
승인, 미디어 전달, 그리고 표시되는 transcript 미러를 관리합니다.
이는 Codex가 저수준 에이전트 세션, 즉 모델 검색, 네이티브 스레드 재개,
네이티브 Compaction, 앱-서버 실행을 담당하도록 하려는 경우에 사용합니다.
OpenClaw는 여전히 채팅 채널, 세션 파일, 모델 선택, 도구, 승인,
미디어 전달, 그리고 사용자에게 보이는 트랜스크립트 미러를 담당합니다.
이 하네스는 기본적으로 꺼져 있습니다. `codex` Plugin이
활성화되어 있고 해석된 모델이 `codex/*` 모델일 때, 또는 `embeddedHarness.runtime: "codex"``OPENCLAW_AGENT_RUNTIME=codex`를 명시적으로 강제했을 때만 선택됩니다.
`codex/*`를 전혀 구성하지 않으면 기존 PI, OpenAI, Anthropic, Gemini, 로컬,
그리고 custom-provider 실행은 현재 동작을 유지합니다.
하니스는 기본적으로 꺼져 있습니다. `codex` Plugin이 활성화되어 있고
해결된 모델이 `codex/*` 모델일 때만 선택되며, 또는
`embeddedHarness.runtime: "codex"``OPENCLAW_AGENT_RUNTIME=codex`
명시적으로 강제한 경우에 선택됩니다.
`codex/*`를 전혀 구성하지 않으면, 기존 PI, OpenAI, Anthropic, Gemini, local,
custom-provider 실행은 현재 동작을 그대로 유지합니다.
## 올바른 모델 접두사 선택
OpenClaw는 OpenAI 접근과 Codex 형태 접근에 대해 별도의 경로를 가집니다:
OpenClaw는 OpenAI 접근과 Codex 형태 접근에 대해 별도의 경로를 가집니다.
| 모델 ref | 런타임 경로 | 사용 시점 |
| ---------------------- | -------------------------------------------- | ----------------------------------------------------------------------- |
| `openai/gpt-5.4` | OpenClaw/PI 경유 OpenAI provider 경로 | `OPENAI_API_KEY`로 직접 OpenAI Platform API에 접근하려는 경우 |
| `openai-codex/gpt-5.4` | PI 경유 OpenAI Codex OAuth provider | Codex app-server 하네스 없이 ChatGPT/Codex OAuth를 사용하려는 경우 |
| `codex/gpt-5.4` | 번들 Codex provider + Codex 하네스 | 임베디드 에이전트 턴에 네이티브 Codex app-server 실행을 사용하려는 경우 |
| 모델 참조 | 런타임 경로 | 사용 시점 |
| ---------------------- | ----------------------------------------- | ----------------------------------------------------------------------- |
| `openai/gpt-5.4` | OpenClaw/PI 플로우를 통한 OpenAI provider | `OPENAI_API_KEY`로 OpenAI Platform API에 직접 접근하려는 경우입니다. |
| `openai-codex/gpt-5.4` | PI를 통한 OpenAI Codex OAuth provider | Codex 앱-서버 하니스 없이 ChatGPT/Codex OAuth를 사용하려는 경우입니다. |
| `codex/gpt-5.4` | 번들된 Codex provider 및 Codex 하니스 | 임베디드 에이전트 턴에 네이티브 Codex 앱-서버 실행을 사용하려는 경우입니다. |
Codex 하네스는 `codex/*` 모델 ref만 처리합니다. 기존 `openai/*`,
`openai-codex/*`, Anthropic, Gemini, xAI, 로컬, 그리고 custom provider ref
정상 경로를 그대로 유지합니다.
Codex 하니스는 `codex/*` 모델 참조만 처리합니다. 기존 `openai/*`,
`openai-codex/*`, Anthropic, Gemini, xAI, local, custom provider 참조
기존의 일반 경로를 유지합니다.
## 요구 사항
- 번들 `codex` Plugin을 사용할 수 있는 OpenClaw
- Codex app-server `0.118.0` 이상
- app-server 프로세스에서 사용할 수 있는 Codex 인증
- 번들 `codex` Plugin을 사용할 수 있는 OpenClaw.
- Codex 앱-서버 `0.118.0` 이상.
- 앱-서버 프로세스에서 사용할 수 있는 Codex 인증.
이 Plugin은 더 오래되었거나 버전이 없는 app-server 핸드셰이크를 차단합니다. 이렇게 하면
OpenClaw가 검증된 프로토콜 surface 위에서만 동작하도록 유지할 수 있습니다.
이 Plugin은 버전이 없거나 더 오래된 앱-서버 핸드셰이크를 차단합니다.
이를 통해 OpenClaw가 검증된 프로토콜 표면에서만 동작하도록 유지합니다.
실제 환경 및 Docker 스모크 테스트에서는 인증이 보통 `OPENAI_API_KEY`와,
선택적으로 `~/.codex/auth.json`
`~/.codex/config.toml` 같은 Codex CLI 파일에서 제공됩니다. 로컬 Codex app-server가
사용하는 것과 동일한 인증 자료를 사용하세요.
라이브 및 Docker 스모크 테스트에서는 인증이 일반적으로 `OPENAI_API_KEY`
선택적 Codex CLI 파일(예: `~/.codex/auth.json`,
`~/.codex/config.toml`)에서 제공됩니다. 로컬 Codex 앱-서버가 사용하는 것과
같은 인증 자료를 사용하세요.
## 최소 구성
`codex/gpt-5.4`를 사용하고, 번들 Plugin을 활성화하고, `codex` 하네스를 강제합니다:
`codex/gpt-5.4`를 사용하고, 번들된 Plugin을 활성화하고, `codex` 하니스를
강제합니다.
```json5
{
@ -82,7 +85,7 @@ OpenClaw가 검증된 프로토콜 surface 위에서만 동작하도록 유지
}
```
구성에서 `plugins.allow`를 사용한다면, 거기에도 `codex`를 포함하세요:
구성에서 `plugins.allow`를 사용한다면, 거기에도 `codex`를 포함하세요.
```json5
{
@ -97,13 +100,14 @@ OpenClaw가 검증된 프로토콜 surface 위에서만 동작하도록 유지
}
```
`agents.defaults.model` 또는 에이전트 모델을 `codex/<model>`로 설정하면
번들 `codex` Plugin도 자동 활성화됩니다. 명시적인 Plugin 항목은
공유 구성에서 여전히 유용한데, 배포 의도를 더 명확하게 보여주기 때문입니다.
`agents.defaults.model` 또는 에이전트 모델을 `codex/<model>`로 설정해도
번들`codex` Plugin이 자동으로 활성화됩니다. 그래도 명시적인 Plugin 항목은
공유 구성에서 배포 의도를 분명히 드러내므로 여전히 유용합니다.
## 다른 모델을 대체하지 않고 Codex 추가
`codex/*` 모델에는 Codex를, 그 외 모든 경우에는 PI를 사용하려면 `runtime: "auto"`를 유지하세요:
`codex/*` 모델에는 Codex를 사용하고, 나머지에는 PI를 사용하려면
`runtime: "auto"`를 유지하세요.
```json5
{
@ -135,17 +139,17 @@ OpenClaw가 검증된 프로토콜 surface 위에서만 동작하도록 유지
}
```
형태에서는:
구성에서는 다음과 같습니다.
- `/model codex` 또는 `/model codex/gpt-5.4`는 Codex app-server 하네스를 사용합니다.
- `/model codex` 또는 `/model codex/gpt-5.4`는 Codex 앱-서버 하니스를 사용합니다.
- `/model gpt` 또는 `/model openai/gpt-5.4`는 OpenAI provider 경로를 사용합니다.
- `/model opus`는 Anthropic provider 경로를 사용합니다.
- Codex가 아닌 모델이 선택되면 PI가 호환성 하네스로 유지됩니다.
- Codex가 아닌 모델이 선택되면, PI가 호환성 하니스로 유지됩니다.
## Codex 전용 배포
모든 임베디드 에이전트 턴이 Codex 하네스를 사용한다는 점을 보장해야 한다면
PI fallback을 비활성화하세요:
모든 임베디드 에이전트 턴이 Codex 하니스를 사용한다는 점을 증명해야 한다면
PI 폴백을 비활성화하세요.
```json5
{
@ -161,7 +165,7 @@ PI fallback을 비활성화하세요:
}
```
환경 변수 override:
환경 변수 재정의:
```bash
OPENCLAW_AGENT_RUNTIME=codex \
@ -169,14 +173,14 @@ OPENCLAW_AGENT_HARNESS_FALLBACK=none \
openclaw gateway run
```
fallback이 비활성화되면, `codex` Plugin이 비활성화되어 있거나,
요청한 모델이 `codex/*` ref가 아니거나, app-server가 너무 오래되었거나,
app-server를 시작할 수 없는 경우 OpenClaw는 초기에 실패합니다.
폴백이 비활성화되면, Codex Plugin이 비활성화되어 있거나,
요청된 모델이 `codex/*` 참조가 아니거나, 앱-서버가 너무 오래되었거나,
앱-서버를 시작할 수 없는 경우 OpenClaw는 초기에 실패합니다.
## 에이전트별 Codex
기본 에이전트는 일반 auto-selection을 유지하면서 특정 에이전트 하나만
Codex 전용으로 만들 수 있습니다:
기본 에이전트는 일반적인 자동 선택을 유지하면서, 특정 에이전트 하나만
Codex 전용으로 만들 수 있습니다.
```json5
{
@ -207,20 +211,21 @@ Codex 전용으로 만들 수 있습니다:
}
```
일반 세션 명령으로 에이전트와 모델을 전환하세요. `/new`는 새
OpenClaw 세션을 만들고, Codex 하네스는 필요에 따라 sidecar app-server
스레드를 생성하거나 재개합니다. `/reset`은 해당 스레드에 대한 OpenClaw 세션 바인딩을 지웁니다.
일반적인 세션 명령으로 에이전트와 모델을 전환하세요. `/new`는 새로운
OpenClaw 세션을 만들고, Codex 하니스는 필요에 따라 해당 사이드카 앱-서버
스레드를 생성하거나 재개합니다. `/reset`은 해당 스레드에 대한 OpenClaw 세션
바인딩을 지웁니다.
## 모델 검색
기본적으로 Codex Plugin은 app-server에 사용 가능한 모델을 요청합니다. 검색이
실패하거나 시간 초과되면 번들 fallback 카탈로그를 사용합니다:
기본적으로 Codex Plugin은 앱-서버에 사용 가능한 모델을 요청합니다.
검색이 실패하거나 시간 초과되면, 번들된 폴백 카탈로그를 사용합니다.
- `codex/gpt-5.4`
- `codex/gpt-5.4-mini`
- `codex/gpt-5.2`
`plugins.entries.codex.config.discovery` 아래에서 검색을 조정할 수 있습니다:
`plugins.entries.codex.config.discovery` 아래에서 검색 동작을 조정할 수 있습니다.
```json5
{
@ -240,8 +245,7 @@ OpenClaw 세션을 만들고, Codex 하네스는 필요에 따라 sidecar app-se
}
```
시작 시 Codex 프로브를 피하고
fallback 카탈로그만 사용하려면 검색을 비활성화하세요:
시작 시 Codex 탐지를 피하고 폴백 카탈로그만 사용하려면 검색을 비활성화하세요.
```json5
{
@ -260,17 +264,17 @@ fallback 카탈로그만 사용하려면 검색을 비활성화하세요:
}
```
## App-server 연결 및 정책
## 앱-서버 연결 및 정책
기본적으로 Plugin은 다음과 같이 로컬에서 Codex를 시작합니다:
기본적으로 Plugin은 다음과 같이 로컬에서 Codex를 시작합니다.
```bash
codex app-server --listen stdio://
```
기본적으로 OpenClaw는 Codex에 네이티브 승인을 요청하도록 지시합니다.
정책은 더 세부적으로 조정할 수 있으며, 예를 들어 더 엄격하게 만들고 검토를
guardian을 통해 라우팅할 수 있습니다:
기본적으로 OpenClaw는 Codex에 네이티브 승인을 요청하도록 지시합니다.
예를 들어 정책을 더 엄격하게 하고 검토를 guardian으로 라우팅하는 등,
이 정책을 추가로 조정할 수 있습니다.
```json5
{
@ -292,7 +296,7 @@ guardian을 통해 라우팅할 수 있습니다:
}
```
이미 실행 중인 app-server에는 WebSocket 전송을 사용하세요:
이미 실행 중인 앱-서버에는 WebSocket 전송을 사용하세요.
```json5
{
@ -316,22 +320,22 @@ guardian을 통해 라우팅할 수 있습니다:
지원되는 `appServer` 필드:
| 필드 | 기본값 | 의미 |
| 필드 | 기본값 | 의미 |
| ------------------- | ---------------------------------------- | ------------------------------------------------------------------------ |
| `transport` | `"stdio"` | `"stdio"`는 Codex를 시작하고, `"websocket"``url`에 연결합니다. |
| `command` | `"codex"` | stdio 전송용 실행 파일 |
| `args` | `["app-server", "--listen", "stdio://"]` | stdio 전송용 인수 |
| `url` | unset | WebSocket app-server URL |
| `authToken` | unset | WebSocket 전송용 Bearer 토큰 |
| `headers` | `{}` | 추가 WebSocket 헤더 |
| `requestTimeoutMs` | `60000` | app-server control-plane 호출 시간 제한 |
| `approvalPolicy` | `"on-request"` | 스레드 시작/재개/턴에 전송되는 네이티브 Codex 승인 정책 |
| `sandbox` | `"workspace-write"` | 스레드 시작/재개 시 전송되는 네이티브 Codex 샌드박스 모드 |
| `approvalsReviewer` | `"user"` | 네이티브 승인을 Codex guardian이 검토하게 하려면 `"guardian_subagent"` 사용 |
| `serviceTier` | unset | 선택적 Codex 서비스 계층, 예: `"priority"` |
| `transport` | `"stdio"` | `"stdio"`는 Codex를 시작하고, `"websocket"``url`에 연결합니다. |
| `command` | `"codex"` | stdio 전송용 실행 파일입니다. |
| `args` | `["app-server", "--listen", "stdio://"]` | stdio 전송용 인수입니다. |
| `url` | unset | WebSocket 앱-서버 URL입니다. |
| `authToken` | unset | WebSocket 전송용 Bearer 토큰입니다. |
| `headers` | `{}` | 추가 WebSocket 헤더입니다. |
| `requestTimeoutMs` | `60000` | 앱-서버 제어 플레인 호출의 시간 초과입니다. |
| `approvalPolicy` | `"on-request"` | 스레드 시작/재개/턴 시 전송되는 네이티브 Codex 승인 정책입니다. |
| `sandbox` | `"workspace-write"` | 스레드 시작/재개 시 전송되는 네이티브 Codex 샌드박스 모드입니다. |
| `approvalsReviewer` | `"user"` | Codex guardian이 네이티브 승인을 검토하도록 하려면 `"guardian_subagent"`를 사용합니다. |
| `serviceTier` | unset | 선택적 Codex 서비스 등급입니다. 예: `"priority"`. |
기존 환경 변수도 일치하는 구성 필드가 설정되지 않은 경우
로컬 테스트용 fallback으로 계속 작동합니다:
이전 환경 변수도, 일치하는 구성 필드가 설정되지 않은 경우 로컬 테스트용 폴백으로
계속 사용할 수 있습니다.
- `OPENCLAW_CODEX_APP_SERVER_BIN`
- `OPENCLAW_CODEX_APP_SERVER_ARGS`
@ -339,7 +343,7 @@ guardian을 통해 라우팅할 수 있습니다:
- `OPENCLAW_CODEX_APP_SERVER_SANDBOX`
- `OPENCLAW_CODEX_APP_SERVER_GUARDIAN=1`
반복 가능한 배포에는 구성이 더 적합합니다.
반복 가능한 배포를 위해서는 구성을 사용하는 것이 좋습니다.
## 일반적인 레시피
@ -357,7 +361,7 @@ guardian을 통해 라우팅할 수 있습니다:
}
```
PI fallback이 비활성화된 Codex 전용 하네스 검증:
PI 폴백을 비활성화한 Codex 전용 하니스 검증:
```json5
{
@ -395,7 +399,7 @@ guardian이 검토하는 Codex 승인:
}
```
명시적 헤더를 사용하는 원격 app-server:
명시적 헤더를 사용하는 원격 앱-서버:
```json5
{
@ -418,78 +422,85 @@ guardian이 검토하는 Codex 승인:
}
```
모델 전환은 계속 OpenClaw가 제어합니다. OpenClaw 세션이
기존 Codex 스레드에 연결된 경우, 다음 턴은 현재 선택된
`codex/*` 모델, provider, 승인 정책, 샌드박스, 그리고 서비스 계층을 다시
app-server로 전송합니다. `codex/gpt-5.4`에서 `codex/gpt-5.2`로 전환해도
스레드 바인딩은 유지되지만, Codex에는 새로 선택된 모델로 계속 진행하라고 요청합니다.
모델 전환은 계속 OpenClaw가 제어합니다. OpenClaw 세션이 기존 Codex 스레드에
연결되어 있을 때, 다음 턴은 현재 선택된 `codex/*` 모델, provider, 승인 정책,
sandbox, service tier를 다시 앱-서버로 보냅니다.
`codex/gpt-5.4`에서 `codex/gpt-5.2`로 전환하면 스레드 바인딩은 유지되지만,
Codex에는 새로 선택된 모델로 계속 진행하도록 요청합니다.
## Codex 명령
번들 Plugin은 인된 슬래시 명령으로 `/codex`등록합니다. 이 명령은
범용이며 OpenClaw 텍스트 명령을 지원하는 모든 채널에서 동작합니다.
번들 Plugin은 `/codex`를 승인된 슬래시 명령으로 등록합니다.
이는 일반적이며 OpenClaw 텍스트 명령을 지원하는 모든 채널에서 동작합니다.
일반적인 형:
일반적인 형:
- `/codex status`app-server 실시간 연결 상태, 모델, account, rate limit, MCP 서버, 그리고 Skills를 표시합니다.
- `/codex models`는 실시간 Codex app-server 모델을 나열합니다.
- `/codex status`실시간 앱-서버 연결 상태, 모델, 계정, rate limit, MCP 서버, Skills를 표시합니다.
- `/codex models`는 실시간 Codex 앱-서버 모델 목록을 표시합니다.
- `/codex threads [filter]`는 최근 Codex 스레드를 나열합니다.
- `/codex resume <thread-id>`는 현재 OpenClaw 세션을 기존 Codex 스레드에 연결합니다.
- `/codex compact`Codex app-server에 연결된 스레드의 Compaction을 요청합니다.
- `/codex compact`연결된 스레드에 대해 Codex 앱-서버에 Compaction을 요청합니다.
- `/codex review`는 연결된 스레드에 대해 Codex 네이티브 검토를 시작합니다.
- `/codex account`account 및 rate-limit 상태를 표시합니다.
- `/codex mcp`는 Codex app-server MCP 서버 상태를 나열합니다.
- `/codex skills`는 Codex app-server Skills를 나열합니다.
- `/codex account`계정 및 rate-limit 상태를 표시합니다.
- `/codex mcp`는 Codex 앱-서버 MCP 서버 상태를 나열합니다.
- `/codex skills`는 Codex 앱-서버 Skills를 나열합니다.
`/codex resume`는 하네스가 일반 턴에 사용하는 것과 동일한 sidecar 바인딩 파일을 기록합니다.
다음 메시지에서 OpenClaw는 해당 Codex 스레드를 재개하고, 현재 선택된 OpenClaw `codex/*` 모델을 app-server에 전달하며,
확장 기록을 계속 활성화된 상태로 유지합니다.
`/codex resume`는 하니스가 일반 턴에 사용하는 것과 동일한 사이드카 바인딩 파일을
씁니다. 다음 메시지에서 OpenClaw는 해당 Codex 스레드를 재개하고, 현재 선택된
OpenClaw `codex/*` 모델을 앱-서버에 전달하며, 확장된 기록을 계속 활성화된
상태로 유지합니다.
이 명령 surface는 Codex app-server `0.118.0` 이상이 필요합니다. 개별
제어 메서드는 미래 버전 또는 custom app-server가 해당 JSON-RPC 메서드를 노출하지 않는 경우
이 명령 표면은 Codex 앱-서버 `0.118.0` 이상이 필요합니다. 향후 버전 또는
커스텀 앱-서버가 해당 JSON-RPC 메서드를 노출하지 않는 경우, 개별 제어 메서드는
`unsupported by this Codex app-server`로 보고됩니다.
## 도구, 미디어, 그리고 Compaction
## 도구, 미디어, Compaction
Codex 하네스는 하위 수준 임베디드 에이전트 실행기만 변경합니다.
Codex 하니스는 저수준 임베디드 에이전트 실행기만 변경합니다.
OpenClaw는 여전히 도구 목록을 구성하고 하네스로부터 동적 도구 결과를 받습니다.
텍스트, 이미지, 비디오, 음악, TTS, 승인, 그리고 메시징 도구 출력은
계속 일반 OpenClaw 전달 경로를 통해 처리됩니다.
OpenClaw는 여전히 도구 목록을 만들고 하니스로부터 동적 도구 결과를 받습니다.
텍스트, 이미지, 비디오, 음악, TTS, 승인, 메시징 도구 출력은 계속해서 일반적인
OpenClaw 전달 경로를 통해 처리됩니다.
선택된 모델이 Codex 하네스를 사용할 때, 네이티브 스레드 Compaction은
Codex app-server에 위임됩니다. OpenClaw는 채널 기록, 검색, `/new`, `/reset`,
그리고 향후 모델 또는 하네스 전환을 위해 transcript 미러를 유지합니다. 이
미러에는 사용자 프롬프트, 최종 assistant 텍스트, 그리고 app-server가 이를 내보낼 경우
가벼운 Codex 추론 또는 계획 기록이 포함됩니다.
선택된 모델이 Codex 하니스를 사용하는 경우, 네이티브 스레드 Compaction은
Codex 앱-서버에 위임됩니다. OpenClaw는 채널 기록, 검색, `/new`, `/reset`,
그리고 향후 모델 또는 하니스 전환을 위해 트랜스크립트 미러를 유지합니다.
이 미러에는 사용자 프롬프트, 최종 어시스턴트 텍스트, 그리고 앱-서버가 이를
내보낼 때 경량 Codex 추론 또는 계획 기록이 포함됩니다.
미디어 생성에는 PI가 필요하지 않습니다. 이미지, 비디오, 음악, PDF, TTS, 그리고 미디어
이해는 계속 `agents.defaults.imageGenerationModel`, `videoGenerationModel`, `pdfModel`,
그리고 `messages.tts` 같은 해당 provider/모델 설정을 사용합니다.
미디어 생성에는 PI가 필요하지 않습니다. 이미지, 비디오, 음악, PDF, TTS,
미디어 이해는 계속해서 `agents.defaults.imageGenerationModel`,
`videoGenerationModel`, `pdfModel`, `messages.tts` 같은 해당 provider/모델
설정을 사용합니다.
## 문제 해결
**`/model`에 Codex가 표시되지 않음:** `plugins.entries.codex.enabled`를 활성화하고,
`codex/*` 모델 ref를 설정하거나, `plugins.allow``codex`를 제외하고 있는지 확인하세요.
**`/model`에 Codex가 표시되지 않음:** `plugins.entries.codex.enabled`
활성화하고, `codex/*` 모델 참조를 설정하거나, `plugins.allow`에서 `codex`
제외되어 있는지 확인하세요.
**OpenClaw가 PI로 fallback함:** 테스트 중에는 `embeddedHarness.fallback: "none"` 또는
`OPENCLAW_AGENT_HARNESS_FALLBACK=none`을 설정하세요.
**OpenClaw가 Codex 대신 PI를 사용함:** Codex 하니스가 실행을 처리하지 않으면,
OpenClaw는 호환성 백엔드로 PI를 사용할 수 있습니다. 테스트 중 Codex 선택을
강제하려면 `embeddedHarness.runtime: "codex"`를 설정하고, 일치하는 Plugin
하니스가 없을 때 실패하게 하려면 `embeddedHarness.fallback: "none"`
설정하세요. Codex 앱-서버가 선택되면, 해당 실패는 추가 폴백 구성 없이 직접
표면화됩니다.
**app-server가 거부됨:** app-server 핸드셰이크가
버전 `0.118.0` 이상을 보고하도록 Codex를 업그레이드하세요.
**앱-서버가 거부됨:** 앱-서버 핸드셰이크가 버전 `0.118.0` 이상을 보고하도록
Codex를 업그레이드하세요.
**모델 검색이 느림:** `plugins.entries.codex.config.discovery.timeoutMs` 낮추거나
검색을 비활성화하세요.
**모델 검색이 느림:** `plugins.entries.codex.config.discovery.timeoutMs`
낮추거나 검색을 비활성화하세요.
**WebSocket 전송이 즉시 실패함:** `appServer.url`, `authToken`,
그리고 원격 app-server가 동일한 Codex app-server 프로토콜 버전을 사용하는지 확인하세요.
**WebSocket 전송이 즉시 실패함:** `appServer.url`, `authToken`, 그리고 원격
앱-서버가 동일한 Codex 앱-서버 프로토콜 버전을 사용하는지 확인하세요.
**Codex가 아닌 모델이 PI를 사용함:** 이는 예상된 동작입니다. Codex 하스는
`codex/*` 모델 ref만 처리합니다.
**Codex가 아닌 모델이 PI를 사용함:** 이는 예상된 동작입니다. Codex 하스는
`codex/*` 모델 참조만 처리합니다.
## 관련 항목
- [Agent Harness Plugins](/ko/plugins/sdk-agent-harness)
- [Model Providers](/ko/concepts/model-providers)
- [Configuration Reference](/ko/gateway/configuration-reference)
- [Testing](/ko/help/testing#live-codex-app-server-harness-smoke)
- [에이전트 하니스 Plugin](/ko/plugins/sdk-agent-harness)
- [모델 provider](/ko/concepts/model-providers)
- [구성 참조](/ko/gateway/configuration-reference)
- [테스트](/ko/help/testing#live-codex-app-server-harness-smoke)

View File

@ -1,76 +1,75 @@
---
read_when:
- OpenClaw Plugin을 빌드하고 있습니다
- Plugin 구성 스키마를 제공하거나 Plugin 검증 오류를 디버깅해야 합니다
- Plugin 구성 스키마를 배포하거나 Plugin 검증 오류를 디버그해야 합니다
summary: Plugin 매니페스트 + JSON 스키마 요구 사항(엄격한 구성 검증)
title: Plugin 매니페스트
x-i18n:
generated_at: "2026-04-22T04:24:10Z"
generated_at: "2026-04-22T06:00:34Z"
model: gpt-5.4
provider: openai
source_hash: 52a52f7e2c78bbef2cc51ade6eb12b6edc950237bdfc478f6e82248374c687bf
source_hash: b80735690799682939e8c8c27b6a364caa3ceadcf6319155ddeb20eb0538c313
source_path: plugins/manifest.md
workflow: 15
---
# Plugin 매니페스트 (`openclaw.plugin.json`)
이 페이지는 **기본 OpenClaw Plugin 매니페스트**만 다룹니다.
이 페이지는 **네이티브 OpenClaw Plugin 매니페스트**만을 다룹니다.
호환되는 번들 레이아웃은 [Plugin bundles](/ko/plugins/bundles)를 참조하세요.
호환 번들 레이아웃은 [Plugin 번들](/ko/plugins/bundles)을 참조하세요.
호환되는 번들 형식은 서로 다른 매니페스트 파일을 사용합니다:
호환 번들 형식은 서로 다른 매니페스트 파일을 사용합니다.
- Codex bundle: `.codex-plugin/plugin.json`
- Claude bundle: `.claude-plugin/plugin.json` 또는 매니페스트가 없는 기본 Claude 컴포넌트
- Codex 번들: `.codex-plugin/plugin.json`
- Claude 번들: `.claude-plugin/plugin.json` 또는 매니페스트가 없는 기본 Claude 컴포넌트
레이아웃
- Cursor bundle: `.cursor-plugin/plugin.json`
- Cursor 번들: `.cursor-plugin/plugin.json`
OpenClaw는 이러한 번들 레이아웃도 자동 감지하지만, 여기서 설명하는
`openclaw.plugin.json` 스키마에 대해 검증되지는 않습니다.
`openclaw.plugin.json` 스키마를 기준으로 검증되지는 않습니다.
호환 번들의 경우, OpenClaw는 현재 번들 메타데이터와 선언된
skill 루트, Claude 명령 루트, Claude 번들 `settings.json` 기본값,
Claude 번들 LSP 기본값, 그리고 레이아웃이 OpenClaw 런타임 기대와 일치할 때
지원되는 hook pack을 읽습니다.
호환 번들의 경우, OpenClaw는 현재 레이아웃이 OpenClaw 런타임 기대사항과 일치하면
번들 메타데이터와 선언된 skill 루트, Claude 명령 루트, Claude 번들
`settings.json` 기본값, Claude 번들 LSP 기본값, 지원되는 hook pack을 읽습니다.
모든 기본 OpenClaw Plugin은 **반드시** **Plugin 루트**에 `openclaw.plugin.json`
파일을 포함해야 합니다. OpenClaw는 이 매니페스트를 사용해 Plugin 코드를 **실행하지 않고도**
구성을 검증합니다. 매니페스트가 없거나 유효하지 않으면 Plugin 오류로 처리되며
구성 검증이 차단됩니다.
모든 네이티브 OpenClaw Plugin은 **반드시**
**Plugin 루트**에 `openclaw.plugin.json` 파일을 포함해야 합니다. OpenClaw는 이 매니페스트를 사용해
**Plugin 코드를 실행하지 않고도** 구성을 검증합니다. 매니페스트가 없거나 유효하지 않으면
Plugin 오류로 처리되며 구성 검증이 차단됩니다.
전체 Plugin 시스템 가이드는 [Plugins](/ko/tools/plugin)를 참조하세요.
기본 capability 모델과 현재 외부 호환성 가이드는
[Capability model](/ko/plugins/architecture#public-capability-model)을 참조하세요.
네이티브 capability 모델과 현재 외부 호환성 지침은
[Capability 모델](/ko/plugins/architecture#public-capability-model)을 참조하세요.
## 이 파일의 역할
## 이 파일이 하는 일
`openclaw.plugin.json`은 OpenClaw가 Plugin 코드를 로드하기 전에 읽는
메타데이터입니다.
다음 용도로 사용하세요:
용도는 다음과 같습니다.
- Plugin ID
- Plugin 식별
- 구성 검증
- Plugin 런타임을 부팅하지 않고도 사용할 수 있어야 하는 인증 및 온보딩 메타데이터
- 런타임이 로드되기 전에 제어 플레인 표면이 검사할 수 있는 저비용 활성화 힌트
- 런타임이 로드되기 전에 설정/온보딩 표면이 검사할 수 있는 저비용 설정 설명자
- Plugin 런타임이 로드되기 전에 확인되어야 하는 별칭 및 자동 활성화 메타데이터
- 런타임 로드되기 전에 Plugin을 자동 활성화해야 하는 축약형 모델 패밀리 소유 메타데이터
- 번들 호환 wiring 및 계약 커버리지에 사용되는 정적 capability 소유 스냅샷
- 공유 `openclaw qa` 호스트가 Plugin 런타임을 로드하기 전에 검사할 수 있는 저비용 QA 러너 메타데이터
- 런타임을 로드하지 않고 카탈로그 및 검증 표면에 병합되어야 하는 채널별 구성 메타데이터
- 제어면 표면이 런타임 로드 전에 확인할 수 있는 저비용 활성화 힌트
- 설정/온보딩 표면이 런타임 로드 전에 확인할 수 있는 저비용 설정 설명자
- Plugin 런타임 로드 전에 해석되어야 하는 별칭 및 자동 활성화 메타데이터
- 런타임 로드 전에 Plugin을 자동 활성화해야 하는 축약형 모델 패밀리 소유 메타데이터
- 번들 호환 wiring 및 계약 커버리지에 사용되는 정적 capability 소유 스냅샷
- 공유 `openclaw qa` 호스트가 Plugin 런타임 로드 전에 확인할 수 있는 저비용 QA 러너 메타데이터
- 런타임을 로드하지 않고 카탈로그 및 검증 표면에 병합되어야 하는 채널별 구성 메타데이터
- 구성 UI 힌트
다음 용도로는 사용하지 마세요:
다음 용도로는 사용하지 마세요.
- 런타임 동작 등록
- 코드 entrypoint 선언
- 코드 엔트리포인트 선언
- npm 설치 메타데이터
이들은 Plugin 코드와 `package.json`에 속합니다.
## 최소 예
## 최소 예
```json
{
@ -83,13 +82,13 @@ Claude 번들 LSP 기본값, 그리고 레이아웃이 OpenClaw 런타임 기대
}
```
## 확장 예
## 확장 예
```json
{
"id": "openrouter",
"name": "OpenRouter",
"description": "OpenRouter provider Plugin",
"description": "OpenRouter provider plugin",
"version": "1.0.0",
"providers": ["openrouter"],
"modelSupport": {
@ -117,13 +116,13 @@ Claude 번들 LSP 기본값, 그리고 레이아웃이 OpenClaw 런타임 기대
"provider": "openrouter",
"method": "api-key",
"choiceId": "openrouter-api-key",
"choiceLabel": "OpenRouter API ",
"choiceLabel": "OpenRouter API key",
"groupId": "openrouter",
"groupLabel": "OpenRouter",
"optionKey": "openrouterApiKey",
"cliFlag": "--openrouter-api-key",
"cliOption": "--openrouter-api-key <key>",
"cliDescription": "OpenRouter API ",
"cliDescription": "OpenRouter API key",
"onboardingScopes": ["text-inference"]
}
],
@ -148,66 +147,67 @@ Claude 번들 LSP 기본값, 그리고 레이아웃이 OpenClaw 런타임 기대
## 최상위 필드 참조
| 필드 | 필수 여부 | 타입 | 의미 |
| ---------------------------------- | --------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `id` | 예 | `string` | 정식 Plugin ID입니다. 이 ID는 `plugins.entries.<id>`에서 사용됩니다. |
| `configSchema` | 예 | `object` | 이 Plugin 구성용 인라인 JSON 스키마입니다. |
| `enabledByDefault` | 아니요 | `true` | 번들 Plugin이 기본적으로 활성화됨을 표시합니다. 생략하거나 `true`가 아닌 값을 설정하면 Plugin은 기본적으로 비활성화된 상태로 유지됩니다. |
| `legacyPluginIds` | 아니요 | `string[]` | 이 정식 Plugin ID로 정규화되는 레거시 ID입니다. |
| `autoEnableWhenConfiguredProviders`| 아니요 | `string[]` | 인증, 구성 또는 모델 참조에서 이 provider ID가 언급될 때 이 Plugin을 자동 활성화해야 하는 경우를 지정합니다. |
| `kind` | 아니요 | `"memory"` \| `"context-engine"` | `plugins.slots.*`에서 사용되는 배타적 Plugin 종류를 선언합니다. |
| `channels` | 아니요 | `string[]` | 이 Plugin이 소유한 채널 ID입니다. 탐지 및 구성 검증에 사용됩니다. |
| `providers` | 아니요 | `string[]` | 이 Plugin이 소유한 provider ID입니다. |
| `modelSupport` | 아니요 | `object` | 런타임 전에 Plugin을 자동 로드하는 데 사용되는 매니페스트 소유 축약형 모델 패밀리 메타데이터입니다. |
| `providerEndpoints` | 아니요 | `object[]` | 코어가 provider 런타임이 로드되기 전에 분류해야 하는 provider 경로용 매니페스트 소유 endpoint host/baseUrl 메타데이터입니다. |
| `cliBackends` | 아니요 | `string[]` | 이 Plugin이 소유한 CLI 추론 백엔드 ID입니다. 명시적 구성 참조에서 시작 시 자동 활성화하는 데 사용됩니다. |
| `syntheticAuthRefs` | 아니요 | `string[]` | 런타임이 로드되기 전에 cold 모델 탐색 중 Plugin 소유 synthetic 인증 hook를 프로브해야 하는 provider 또는 CLI backend 참조입니다. |
| `nonSecretAuthMarkers` | 아니요 | `string[]` | 비밀이 아닌 로컬, OAuth 또는 주변 자격 증명 상태를 나타내는 번들 Plugin 소유 placeholder API 키 값입니다. |
| `commandAliases` | 아니요 | `object[]` | 런타임이 로드되기 전에 Plugin 인식 구성 및 CLI 진단을 생성해야 하는, 이 Plugin이 소유한 명령 이름입니다. |
| `providerAuthEnvVars` | 아니요 | `Record<string, string[]>` | OpenClaw가 Plugin 코드를 로드하지 않고도 검사할 수 있는 저비용 provider 인증 env 메타데이터입니다. |
| `providerAuthAliases` | 아니요 | `Record<string, string>` | 인증 조회에 다른 provider ID를 재사용해야 하는 provider ID입니다. 예: 기본 provider API 키와 인증 프로필을 공유하는 coding provider. |
| `channelEnvVars` | 아니요 | `Record<string, string[]>` | OpenClaw가 Plugin 코드를 로드하지 않고도 검사할 수 있는 저비용 채널 env 메타데이터입니다. env 기반 채널 설정이나 일반적인 시작/구성 helper가 확인해야 하는 인증 표면에는 이것을 사용하세요. |
| `providerAuthChoices` | 아니요 | `object[]` | 온보딩 선택기, 선호 provider 확인, 단순 CLI 플래그 wiring을 위한 저비용 인증 선택 메타데이터입니다. |
| `activation` | 아니요 | `object` | provider, 명령, 채널, 경로, capability 트리거 로드를 위한 저비용 활성화 힌트입니다. 메타데이터 전용이며, 실제 동작은 여전히 Plugin 런타임이 소유합니다. |
| `setup` | 아니요 | `object` | 탐색 및 설정 표면이 Plugin 런타임을 로드하지 않고도 검사할 수 있는 저비용 설정/온보딩 설명자입니다. |
| `qaRunners` | 아니요 | `object[]` | 공유 `openclaw qa` 호스트가 Plugin 런타임이 로드되기 전에 사용하는 저비용 QA 러너 설명자입니다. |
| `contracts` | 아니요 | `object` | 음성, 실시간 전사, 실시간 음성, 미디어 이해, 이미지 생성, 음악 생성, 비디오 생성, 웹 가져오기, 웹 검색, 도구 소유권을 위한 정적 번들 capability 스냅샷입니다. |
| `channelConfigs` | 아니요 | `Record<string, object>` | 런타임이 로드되기 전에 탐색 및 검증 표면에 병합되는 매니페스트 소유 채널 구성 메타데이터입니다. |
| `skills` | 아니요 | `string[]` | Plugin 루트를 기준으로 한, 로드할 skill 디렉터리입니다. |
| `name` | 아니요 | `string` | 사람이 읽을 수 있는 Plugin 이름입니다. |
| `description` | 아니요 | `string` | Plugin 표면에 표시되는 짧은 요약입니다. |
| `version` | 아니요 | `string` | 정보 제공용 Plugin 버전입니다. |
| `uiHints` | 아니요 | `Record<string, object>` | 구성 필드용 UI 라벨, placeholder, 민감도 힌트입니다. |
| 필드 | 필수 여부 | 유형 | 의미 |
| ------------------------------------ | --------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | 예 | `string` | 정식 Plugin ID입니다. `plugins.entries.<id>`에서 사용하는 ID입니다. |
| `configSchema` | 예 | `object` | 이 Plugin 구성에 대한 인라인 JSON 스키마입니다. |
| `enabledByDefault` | 아니요 | `true` | 번들된 Plugin을 기본적으로 활성화된 상태로 표시합니다. Plugin을 기본 비활성 상태로 두려면 이 필드를 생략하거나 `true`가 아닌 값을 설정하세요. |
| `legacyPluginIds` | 아니요 | `string[]` | 이 정식 Plugin ID로 정규화되는 레거시 ID입니다. |
| `autoEnableWhenConfiguredProviders` | 아니요 | `string[]` | 인증, 구성 또는 모델 참조에서 이들을 언급할 때 이 Plugin을 자동 활성화해야 하는 provider ID입니다. |
| `kind` | 아니요 | `"memory"` \| `"context-engine"` | `plugins.slots.*`에서 사용되는 배타적 Plugin 종류를 선언합니다. |
| `channels` | 아니요 | `string[]` | 이 Plugin이 소유하는 채널 ID입니다. 검색 및 구성 검증에 사용됩니다. |
| `providers` | 아니요 | `string[]` | 이 Plugin이 소유하는 provider ID입니다. |
| `modelSupport` | 아니요 | `object` | 런타임 전에 Plugin을 자동 로드하는 데 사용되는, 매니페스트 소유의 축약형 모델 패밀리 메타데이터입니다. |
| `providerEndpoints` | 아니요 | `object[]` | provider 런타임이 로드되기 전에 코어가 분류해야 하는 provider 경로용, 매니페스트 소유의 endpoint host/baseUrl 메타데이터입니다. |
| `cliBackends` | 아니요 | `string[]` | 이 Plugin이 소유하는 CLI 추론 백엔드 ID입니다. 명시적 구성 참조로부터 시작 시 자동 활성화하는 데 사용됩니다. |
| `syntheticAuthRefs` | 아니요 | `string[]` | 런타임이 로드되기 전에 콜드 모델 검색 중 Plugin 소유의 synthetic auth hook을 프로브해야 하는 provider 또는 CLI 백엔드 참조입니다. |
| `nonSecretAuthMarkers` | 아니요 | `string[]` | 비밀이 아닌 local, OAuth 또는 ambient credential 상태를 나타내는, 번들된 Plugin 소유의 플레이스홀더 API 키 값입니다. |
| `commandAliases` | 아니요 | `object[]` | 런타임이 로드되기 전에 Plugin 인지형 구성 및 CLI 진단을 생성해야 하는, 이 Plugin이 소유하는 명령 이름입니다. |
| `providerAuthEnvVars` | 아니요 | `Record<string, string[]>` | OpenClaw가 Plugin 코드를 로드하지 않고도 확인할 수 있는 저비용 provider 인증 env 메타데이터입니다. |
| `providerAuthAliases` | 아니요 | `Record<string, string>` | 다른 provider ID를 인증 조회에 재사용해야 하는 provider ID입니다. 예를 들어 기본 provider API 키와 인증 프로필을 공유하는 coding provider가 이에 해당합니다. |
| `channelEnvVars` | 아니요 | `Record<string, string[]>` | OpenClaw가 Plugin 코드를 로드하지 않고도 확인할 수 있는 저비용 채널 env 메타데이터입니다. 일반적인 시작/구성 헬퍼가 확인해야 하는 env 기반 채널 설정 또는 인증 표면에 사용하세요. |
| `providerAuthChoices` | 아니요 | `object[]` | 온보딩 선택기, 선호 provider 결정, 단순 CLI 플래그 연결을 위한 저비용 인증 선택 메타데이터입니다. |
| `activation` | 아니요 | `object` | provider, 명령, 채널, 경로 및 capability 트리거 로딩을 위한 저비용 활성화 힌트입니다. 메타데이터 전용이며, 실제 동작은 여전히 Plugin 런타임이 소유합니다. |
| `setup` | 아니요 | `object` | Plugin 런타임을 로드하지 않고도 검색 및 설정 표면이 확인할 수 있는 저비용 설정/온보딩 설명자입니다. |
| `qaRunners` | 아니요 | `object[]` | Plugin 런타임이 로드되기 전에 공유 `openclaw qa` 호스트가 사용하는 저비용 QA 러너 설명자입니다. |
| `contracts` | 아니요 | `object` | 음성, 실시간 전사, 실시간 음성, 미디어 이해, 이미지 생성, 음악 생성, 비디오 생성, 웹 가져오기, 웹 검색, 도구 소유권에 대한 정적 번들 capability 스냅샷입니다. |
| `mediaUnderstandingProviderMetadata` | 아니요 | `Record<string, object>` | `contracts.mediaUnderstandingProviders`에 선언된 provider ID를 위한 저비용 미디어 이해 기본값입니다. |
| `channelConfigs` | 아니요 | `Record<string, object>` | 런타임이 로드되기 전에 검색 및 검증 표면에 병합되는, 매니페스트 소유의 채널 구성 메타데이터입니다. |
| `skills` | 아니요 | `string[]` | Plugin 루트를 기준으로 한 Skills 디렉터리입니다. |
| `name` | 아니요 | `string` | 사람이 읽을 수 있는 Plugin 이름입니다. |
| `description` | 아니요 | `string` | Plugin 표면에 표시되는 짧은 요약입니다. |
| `version` | 아니요 | `string` | 정보 제공용 Plugin 버전입니다. |
| `uiHints` | 아니요 | `Record<string, object>` | 구성 필드를 위한 UI 레이블, 플레이스홀더, 민감도 힌트입니다. |
## providerAuthChoices 참조
## `providerAuthChoices` 참조
`providerAuthChoices` 항목은 하나의 온보딩 또는 인증 선택을 설명합니다.
OpenClaw는 provider 런타임이 로드되기 전에 이를 읽습니다.
| 필드 | 필수 여부 | 타입 | 의미 |
| -------------------- | --------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `provider` | 예 | `string` | 이 선택이 속한 provider ID입니다. |
| `method` | 예 | `string` | 디스패치할 인증 메서드 ID입니다. |
| `choiceId` | 예 | `string` | 온보딩 및 CLI 흐름에서 사용하는 안정적인 인증 선택 ID입니다. |
| `choiceLabel` | 아니요 | `string` | 사용자에게 표시되는 라벨입니다. 생략하면 OpenClaw는 `choiceId`로 폴백합니다. |
| `choiceHint` | 아니요 | `string` | 선택기용 짧은 도움말 텍스트입니다. |
| `assistantPriority` | 아니요 | `number` | assistant 기반 인터랙티브 선택기에서 값이 낮을수록 먼저 정렬됩니다. |
| `assistantVisibility`| 아니요 | `"visible"` \| `"manual-only"` | assistant 선택기에서는 이 선택을 숨기되, 수동 CLI 선택은 계속 허용합니다. |
| `deprecatedChoiceIds`| 아니요 | `string[]` | 사용자를 이 대체 선택으로 리디렉션해야 하는 레거시 선택 ID입니다. |
| `groupId` | 아니요 | `string` | 관련 선택을 그룹화하기 위한 선택적 그룹 ID입니다. |
| `groupLabel` | 아니요 | `string` | 해당 그룹의 사용자 대상 라벨입니다. |
| `groupHint` | 아니요 | `string` | 그룹용 짧은 도움말 텍스트입니다. |
| `optionKey` | 아니요 | `string` | 단일 플래그 기반의 단순 인증 흐름용 내부 옵션 키입니다. |
| `cliFlag` | 아니요 | `string` | `--openrouter-api-key` 같은 CLI 플래그 이름입니다. |
| `cliOption` | 아니요 | `string` | `--openrouter-api-key <key>` 같은 전체 CLI 옵션 형태입니다. |
| `cliDescription` | 아니요 | `string` | CLI 도움말에 사용되는 설명입니다. |
| `onboardingScopes` | 아니요 | `Array<"text-inference" \| "image-generation">` | 이 선택이 표시되어야 하는 온보딩 표면입니다. 생략하면 기본값은 `["text-inference"]`입니다. |
| 필드 | 필수 여부 | 유형 | 의미 |
| -------------------- | --------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `provider` | 예 | `string` | 이 선택이 속한 provider ID입니다. |
| `method` | 예 | `string` | 디스패치할 인증 방식 ID입니다. |
| `choiceId` | 예 | `string` | 온보딩 및 CLI 흐름에서 사용하는 안정적인 auth-choice ID입니다. |
| `choiceLabel` | 아니요 | `string` | 사용자에게 표시되는 레이블입니다. 생략하면 OpenClaw는 `choiceId`를 대신 사용합니다. |
| `choiceHint` | 아니요 | `string` | 선택기에 표시되는 짧은 도움말 텍스트입니다. |
| `assistantPriority` | 아니요 | `number` | assistant 기반 대화형 선택기에서 값이 낮을수록 먼저 정렬됩니다. |
| `assistantVisibility`| 아니요 | `"visible"` \| `"manual-only"` | assistant 선택기에서는 이 선택을 숨기되, 수동 CLI 선택은 계속 허용합니다. |
| `deprecatedChoiceIds`| 아니요 | `string[]` | 사용자를 이 대체 선택으로 리디렉션해야 하는 레거시 choice ID입니다. |
| `groupId` | 아니요 | `string` | 관련 선택을 묶기 위한 선택적 그룹 ID입니다. |
| `groupLabel` | 아니요 | `string` | 해당 그룹의 사용자 표시용 레이블입니다. |
| `groupHint` | 아니요 | `string` | 그룹용 짧은 도움말 텍스트입니다. |
| `optionKey` | 아니요 | `string` | 단일 플래그 기반의 단순 인증 흐름을 위한 내부 옵션 키입니다. |
| `cliFlag` | 아니요 | `string` | `--openrouter-api-key` 같은 CLI 플래그 이름입니다. |
| `cliOption` | 아니요 | `string` | `--openrouter-api-key <key>` 같은 전체 CLI 옵션 형태입니다. |
| `cliDescription` | 아니요 | `string` | CLI 도움말에 사용되는 설명입니다. |
| `onboardingScopes` | 아니요 | `Array<"text-inference" \| "image-generation">` | 이 선택이 나타나야 하는 온보딩 표면입니다. 생략하면 기본값은 `["text-inference"]`입니다. |
## commandAliases 참조
## `commandAliases` 참조
사용자가 실수로 런타임 명령 이름을 `plugins.allow`에 넣거나 루트 CLI 명령으로 실행하려고 할 수 있고,
그 명령을 Plugin이 소유하는 경우 `commandAliases`를 사용하세요. OpenClaw는
Plugin 런타임 코드를 가져오지 않고도 진단에 이 메타데이터를 사용합니다.
사용자가 플러그인이 소유한 런타임 명령 이름을 실수로 `plugins.allow`에 넣거나
루트 CLI 명령으로 실행하려고 할 수 있다면 `commandAliases`를 사용하세요. OpenClaw는
Plugin 런타임 코드를 import하지 않고도 진단을 위해 이 메타데이터를 사용합니다.
```json
{
@ -221,23 +221,23 @@ Plugin 런타임 코드를 가져오지 않고도 진단에 이 메타데이터
}
```
| 필드 | 필수 여부 | 타입 | 의미 |
| ------------ | --------- | ----------------- | ------------------------------------------------------------------------ |
| `name` | 예 | `string` | 이 Plugin에 속한 명령 이름입니다. |
| `kind` | 아니요 | `"runtime-slash"` | 루트 CLI 명령이 아니라 chat 슬래시 명령으로 이 별칭을 표시합니다. |
| `cliCommand` | 아니요 | `string` | 존재하는 경우, CLI 작업에 대해 제안할 관련 루트 CLI 명령입니다. |
| 필드 | 필수 여부 | 유형 | 의미 |
| ------------ | --------- | ----------------- | ----------------------------------------------------------------------- |
| `name` | 예 | `string` | 이 Plugin에 속한 명령 이름입니다. |
| `kind` | 아니요 | `"runtime-slash"` | 별칭을 루트 CLI 명령이 아니라 채팅 슬래시 명령으로 표시합니다. |
| `cliCommand` | 아니요 | `string` | 존재하는 경우, CLI 작업에 대해 제안할 관련 루트 CLI 명령입니다. |
## activation 참조
## `activation` 참조
Plugin이 나중에 자신을 활성화해야 하는 제어 플레인 이벤트를 저비용으로 선언할 수 있을 때
`activation`을 사용하세요.
Plugin이 나중에 무엇이 활성화되어야 하는지 제어면 이벤트를 저비용으로
선언할 수 있다면 `activation`을 사용하세요.
## qaRunners 참조
## `qaRunners` 참조
Plugin이 공유 `openclaw qa` 루트 아래에 하나 이상의 전송 러너를 기여하는 경우
`qaRunners`를 사용하세요. 이 메타데이터는 저비용이고 정적으로 유지하세요. 실제 CLI 등록은 여전히 Plugin
런타임이 `qaRunnerCliRegistrations`를 export하는 경량
`runtime-api.ts` 표면을 통해 소유합니다.
Plugin이 공유 `openclaw qa` 루트 아래에 하나 이상의 전송 러너를 제공하는 경우
`qaRunners`를 사용하세요. 이 메타데이터는 저비용이고 정적으로 유지해야 합니다. 실제
CLI 등록은 여전히 `qaRunnerCliRegistrations`를 export하는 경량
`runtime-api.ts` 표면을 통해 Plugin 런타임이 소유합니다.
```json
{
@ -250,16 +250,16 @@ Plugin이 공유 `openclaw qa` 루트 아래에 하나 이상의 전송 러너
}
```
| 필드 | 필수 여부 | 타입 | 의미 |
| ------------- | --------- | -------- | -------------------------------------------------------------------- |
| `commandName` | 예 | `string` | `openclaw qa` 아래에 마운트되는 하위 명령입니다. 예: `matrix`. |
| `description` | 아니요 | `string` | 공유 호스트에 스텁 명령이 필요할 때 사용되는 폴백 도움말 텍스트입니다. |
| 필드 | 필수 여부 | 유형 | 의미 |
| ------------- | --------- | -------- | ------------------------------------------------------------------ |
| `commandName` | 예 | `string` | `openclaw qa` 아래에 마운트되는 하위 명령입니다. 예: `matrix`. |
| `description` | 아니요 | `string` | 공유 호스트에 stub 명령이 필요할 때 사용하는 대체 도움말 텍스트입니다. |
이 블록은 메타데이터 전용입니다. 런타임 동작을 등록하지 않으며,
`register(...)`, `setupEntry` 또는 다른 런타임/Plugin entrypoint를 대체하지도 않습니다.
현재 소비자는 더 넓은 Plugin 로드 전에 이를 좁히기 힌트로 사용하므로,
activation 메타데이터가 없으면 일반적으로 성능 비용만 발생하며,
레거시 매니페스트 소유권 폴백이 여전히 존재하는 동안에는 정확성이 바뀌면 안 됩니다.
`register(...)`, `setupEntry` 또는 다른 런타임/Plugin 엔트리포인트를 대체하지도 않습니다.
현재 소비자는 이를 더 넓은 Plugin 로딩 전에 범위를 좁히는 힌트로 사용하므로,
활성화 메타데이터가 없으면 보통 성능 비용만 발생합니다. 레거시 매니페스트 소유권 폴백이
여전히 존재하는 동안에는 정확성이 바뀌지 않아야 합니다.
```json
{
@ -273,28 +273,27 @@ activation 메타데이터가 없으면 일반적으로 성능 비용만 발생
}
```
| 필드 | 필수 여부 | 타입 | 의미 |
| 필드 | 필수 여부 | 유형 | 의미 |
| ---------------- | --------- | ---------------------------------------------------- | ----------------------------------------------------------------- |
| `onProviders` | 아니요 | `string[]` | 요청될 때 이 Plugin을 활성화해야 하는 provider ID입니다. |
| `onCommands` | 아니요 | `string[]` | 이 Plugin을 활성화해야 하는 명령 ID입니다. |
| `onChannels` | 아니요 | `string[]` | 이 Plugin을 활성화해야 하는 채널 ID입니다. |
| `onRoutes` | 아니요 | `string[]` | 이 Plugin을 활성화해야 하는 경로 종류입니다. |
| `onCapabilities` | 아니요 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 제어 플레인 활성화 계획에 사용되는 광범위한 capability 힌트입니다. |
| `onCapabilities` | 아니요 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 제어 활성화 계획에 사용되는 광범위한 capability 힌트입니다. |
현재 실제 소비자:
- 명령 트리거 CLI 계획은 레거시
`commandAliases[].cliCommand` 또는 `commandAliases[].name`으로 폴백합니다
- 채널 트리거 설정/채널 계획은 명시적 채널 activation 메타데이터가 없을 때
- 채널 트리거 설정/채널 계획은 명시적 채널 활성화 메타데이터가 없을 때
레거시 `channels[]` 소유권으로 폴백합니다
- provider 트리거 설정/런타임 계획은 명시적 provider
activation 메타데이터가 없을 때 레거시
`providers[]` 및 최상위 `cliBackends[]` 소유권으로 폴백합니다
- provider 트리거 설정/런타임 계획은 명시적 provider 활성화 메타데이터가 없을 때
레거시 `providers[]` 및 최상위 `cliBackends[]` 소유권으로 폴백합니다
## setup 참조
## `setup` 참조
런타임이 로드되기 전에 설정 및 온보딩 표면에 저비용 Plugin 소유 메타데이터가 필요할 때
`setup`을 사용하세요.
런타임이 로드되기 전에 설정 및 온보딩 표면에 저비용 Plugin 소유 메타데이터가
필요한 경우 `setup`을 사용하세요.
```json
{
@ -314,39 +313,40 @@ activation 메타데이터가 없으면 일반적으로 성능 비용만 발생
```
최상위 `cliBackends`는 계속 유효하며 CLI 추론
백엔드를 계속 설명합니다. `setup.cliBackends`는 메타데이터 전용으로 유지되어야 하는
제어 플레인/설정 흐름용 설정 전용 설명자 표면입니다.
백엔드를 설명합니다. `setup.cliBackends`는 메타데이터 전용으로 유지되어야 하는
제어면/설정 흐름을 위한 설정 전용 설명자 표면입니다.
존재하는 경우 `setup.providers``setup.cliBackends`
설정 탐색을 위한 선호되는 설명자 우선 lookup 표면입니다. 설명자가 후보 Plugin만 좁히고
설정에 여전히 더 풍부한 설정 시점 런타임 hook가 필요하면 `requiresRuntime: true`를 설정하고
폴백 실행 경로로 `setup-api`를 유지하세요.
설정 검색을 위한 우선 설명자 우선 조회 표면입니다. 설명자가 후보 Plugin만
좁히고 설정에 더 풍부한 설정 시점 런타임 hook이 여전히 필요하다면
`requiresRuntime: true`로 설정하고 폴백 실행 경로로 `setup-api`
유지하세요.
설정 lookup은 Plugin 소유 `setup-api` 코드를 실행할 수 있으므로,
정규화된 `setup.providers[].id` `setup.cliBackends[]` 값은
탐지된 Plugin 전체에서 고유해야 합니다. 소유권이 모호하면 탐지 순서에서 승자를 고르는 대신
fail-closed합니다.
설정 조회는 Plugin 소유의 `setup-api` 코드를 실행할 수 있으므로,
정규화된 `setup.providers[].id` `setup.cliBackends[]` 값은
검색된 Plugin 전체에서 고유해야 합니다. 소유권이 모호하면 검색 순서에서
승자를 고르는 대신 닫힌 방식으로 실패합니다.
### setup.providers 참조
### `setup.providers` 참조
| 필드 | 필수 여부 | 타입 | 의미 |
| ------------- | --------- | ---------- | -------------------------------------------------------------------- |
| 필드 | 필수 여부 | 유형 | 의미 |
| ------------- | --------- | ---------- | ------------------------------------------------------------------------------------ |
| `id` | 예 | `string` | 설정 또는 온보딩 중 노출되는 provider ID입니다. 정규화된 ID는 전역적으로 고유하게 유지하세요. |
| `authMethods` | 아니요 | `string[]` | 전체 런타임을 로드하지 않고도 이 provider가 지원하는 설정/인증 메서드 ID입니다. |
| `envVars` | 아니요 | `string[]` | 일반적인 설정/상태 표면이 Plugin 런타임이 로드되기 전에 확인할 수 있는 env 변수입니다. |
| `authMethods` | 아니요 | `string[]` | 전체 런타임을 로드하지 않고도 이 provider가 지원하는 설정/인증 방식 ID입니다. |
| `envVars` | 아니요 | `string[]` | Plugin 런타임이 로드되기 전에 일반 설정/상태 표면이 확인할 수 있는 env var입니다. |
### setup 필드
### `setup` 필드
| 필드 | 필수 여부 | 타입 | 의미 |
| 필드 | 필수 여부 | 유형 | 의미 |
| ------------------ | --------- | ---------- | --------------------------------------------------------------------------------------------- |
| `providers` | 아니요 | `object[]` | 설정 및 온보딩 중 노출되는 provider 설정 설명자입니다. |
| `cliBackends` | 아니요 | `string[]` | 설명자 우선 설정 lookup에 사용되는 설정 시점 backend ID입니다. 정규화된 ID는 전역적으로 고유하게 유지하세요. |
| `configMigrations` | 아니요 | `string[]` | 이 Plugin의 설정 표면이 소유한 구성 마이그레이션 ID입니다. |
| `requiresRuntime` | 아니요 | `boolean` | 설명자 lookup 후에도 설정에 `setup-api` 실행이 필요한지 여부입니다. |
| `cliBackends` | 아니요 | `string[]` | 설명자 우선 설정 조회에 사용되는 설정 시점 백엔드 ID입니다. 정규화된 ID는 전역적으로 고유하게 유지하세요. |
| `configMigrations` | 아니요 | `string[]` | 이 Plugin의 설정 표면이 소유하는 구성 마이그레이션 ID입니다. |
| `requiresRuntime` | 아니요 | `boolean` | 설명자 조회 후에도 설정에 `setup-api` 실행이 여전히 필요한지 여부입니다. |
## uiHints 참조
## `uiHints` 참조
`uiHints`는 구성 필드 이름에서 작은 렌더링 힌트로의 입니다.
`uiHints`는 구성 필드 이름에서 작은 렌더링 힌트로의 매핑입니다.
```json
{
@ -361,21 +361,21 @@ fail-closed합니다.
}
```
각 필드 힌트에는 다음이 포함될 수 있습니다:
각 필드 힌트에는 다음이 포함될 수 있습니다.
| 필드 | 타입 | 의미 |
| ------------- | ---------- | ------------------------------------- |
| `label` | `string` | 사용자 대상 필드 라벨입니다. |
| 필드 | 유형 | 의미 |
| ------------- | ---------- | ----------------------------------- |
| `label` | `string` | 사용자에게 표시되는 필드 레이블입니다. |
| `help` | `string` | 짧은 도움말 텍스트입니다. |
| `tags` | `string[]` | 선택적 UI 태그입니다. |
| `advanced` | `boolean` | 필드를 고급 항목으로 표시합니다. |
| `sensitive` | `boolean` | 이 필드를 비밀 또는 민감 항목으로 표시합니다. |
| `placeholder` | `string` | 폼 입력용 placeholder 텍스트입니다. |
| `advanced` | `boolean` | 필드를 고급 항목으로 표시합니다. |
| `sensitive` | `boolean` | 필드를 비밀 또는 민감 정보로 표시합니다. |
| `placeholder` | `string` | 폼 입력용 플레이스홀더 텍스트입니다. |
## contracts 참조
## `contracts` 참조
OpenClaw가 Plugin 런타임을 가져오지 않고도 읽을 수 있는
정적 capability 소유 메타데이터에만 `contracts`를 사용하세요.
OpenClaw가 Plugin 런타임을 import하지 않고도 읽을 수 있는 정적 capability
소유 메타데이터에만 `contracts`를 사용하세요.
```json
{
@ -393,23 +393,60 @@ OpenClaw가 Plugin 런타임을 가져오지 않고도 읽을 수 있는
}
```
각 목록은 모두 선택 사항입니다:
각 목록은 선택 사항입니다.
| 필드 | 타입 | 의미 |
| ------------------------------- | ---------- | ---------------------------------------------------------------- |
| `speechProviders` | `string[]` | 이 Plugin이 소유한 음성 provider ID입니다. |
| `realtimeTranscriptionProviders`| `string[]` | 이 Plugin이 소유한 실시간 전사 provider ID입니다. |
| `realtimeVoiceProviders` | `string[]` | 이 Plugin이 소유한 실시간 음성 provider ID입니다. |
| `mediaUnderstandingProviders` | `string[]` | 이 Plugin이 소유한 미디어 이해 provider ID입니다. |
| `imageGenerationProviders` | `string[]` | 이 Plugin이 소유한 이미지 생성 provider ID입니다. |
| `videoGenerationProviders` | `string[]` | 이 Plugin이 소유한 비디오 생성 provider ID입니다. |
| `webFetchProviders` | `string[]` | 이 Plugin이 소유한 웹 가져오기 provider ID입니다. |
| `webSearchProviders` | `string[]` | 이 Plugin이 소유한 웹 검색 provider ID입니다. |
| `tools` | `string[]` | 번들 계약 검사에 사용되는, 이 Plugin이 소유한 에이전트 도구 이름입니다. |
| 필드 | 유형 | 의미 |
| -------------------------------- | ---------- | -------------------------------------------------------------- |
| `speechProviders` | `string[]` | 이 Plugin이 소유하는 음성 provider ID입니다. |
| `realtimeTranscriptionProviders` | `string[]` | 이 Plugin이 소유하는 실시간 전사 provider ID입니다. |
| `realtimeVoiceProviders` | `string[]` | 이 Plugin이 소유하는 실시간 음성 provider ID입니다. |
| `mediaUnderstandingProviders` | `string[]` | 이 Plugin이 소유하는 미디어 이해 provider ID입니다. |
| `imageGenerationProviders` | `string[]` | 이 Plugin이 소유하는 이미지 생성 provider ID입니다. |
| `videoGenerationProviders` | `string[]` | 이 Plugin이 소유하는 비디오 생성 provider ID입니다. |
| `webFetchProviders` | `string[]` | 이 Plugin이 소유하는 웹 가져오기 provider ID입니다. |
| `webSearchProviders` | `string[]` | 이 Plugin이 소유하는 웹 검색 provider ID입니다. |
| `tools` | `string[]` | 번들 계약 검사에서 이 Plugin이 소유하는 에이전트 도구 이름입니다. |
## channelConfigs 참조
## `mediaUnderstandingProviderMetadata` 참조
채널 Plugin이 런타임이 로드되기 전에 저비용 구성 메타데이터를 필요로 할 때
미디어 이해 provider에 기본 모델, 자동 인증 폴백 우선순위 또는 네이티브 문서 지원이 있어
일반 코어 헬퍼가 런타임 로드 전에 이를 필요로 하는 경우
`mediaUnderstandingProviderMetadata`를 사용하세요. 키는 반드시
`contracts.mediaUnderstandingProviders`에도 선언되어야 합니다.
```json
{
"contracts": {
"mediaUnderstandingProviders": ["example"]
},
"mediaUnderstandingProviderMetadata": {
"example": {
"capabilities": ["image", "audio"],
"defaultModels": {
"image": "example-vision-latest",
"audio": "example-transcribe-latest"
},
"autoPriority": {
"image": 40
},
"nativeDocumentInputs": ["pdf"]
}
}
}
```
각 provider 항목에는 다음이 포함될 수 있습니다.
| 필드 | 유형 | 의미 |
| ---------------------- | ----------------------------------- | ----------------------------------------------------------------------- |
| `capabilities` | `("image" \| "audio" \| "video")[]` | 이 provider가 노출하는 미디어 capability입니다. |
| `defaultModels` | `Record<string, string>` | 구성에서 모델을 지정하지 않았을 때 사용하는 capability-대-모델 기본값입니다. |
| `autoPriority` | `Record<string, number>` | 자격 증명 기반 provider 자동 폴백에서 숫자가 낮을수록 먼저 정렬됩니다. |
| `nativeDocumentInputs` | `"pdf"[]` | provider가 지원하는 네이티브 문서 입력입니다. |
## `channelConfigs` 참조
채널 Plugin이 런타임 로드 전에 저비용 구성 메타데이터를 필요로 하는 경우
`channelConfigs`를 사용하세요.
```json
@ -430,28 +467,28 @@ OpenClaw가 Plugin 런타임을 가져오지 않고도 읽을 수 있는
}
},
"label": "Matrix",
"description": "Matrix homeserver 연결",
"description": "Matrix 홈서버 연결",
"preferOver": ["matrix-legacy"]
}
}
}
```
각 채널 항목에는 다음이 포함될 수 있습니다:
각 채널 항목에는 다음이 포함될 수 있습니다.
| 필드 | 타입 | 의미 |
| ------------- | ------------------------ | ------------------------------------------------------------------------------------- |
| `schema` | `object` | `channels.<id>`용 JSON 스키마입니다. 선언된 각 채널 구성 항목에 필수입니다. |
| `uiHints` | `Record<string, object>` | 해당 채널 구성 섹션용 선택적 UI 라벨/placeholder/민감도 힌트입니다. |
| `label` | `string` | 런타임 메타데이터가 준비되지 않았을 때 선택기 및 검사 표면에 병합되는 채널 라벨입니다. |
| `description` | `string` | 검사 및 카탈로그 표면용 짧은 채널 설명입니다. |
| `preferOver` | `string[]` | 선택 표면에서 이 채널이 우선해야 하는 레거시 또는 낮은 우선순위 Plugin ID입니다. |
| 필드 | 유형 | 의미 |
| ------------- | ------------------------ | ---------------------------------------------------------------------------------------- |
| `schema` | `object` | `channels.<id>`용 JSON 스키마입니다. 선언된 각 채널 구성 항목에 필수입니다. |
| `uiHints` | `Record<string, object>` | 해당 채널 구성 섹션에 대한 선택적 UI 레이블/플레이스홀더/민감도 힌트입니다. |
| `label` | `string` | 런타임 메타데이터가 준비되지 않았을 때 선택기와 검사 표면에 병합되는 채널 레이블입니다. |
| `description` | `string` | 검사 및 카탈로그 표면용 짧은 채널 설명입니다. |
| `preferOver` | `string[]` | 선택 표면에서 이 채널이 우선해야 하는 레거시 또는 낮은 우선순위 Plugin ID입니다. |
## modelSupport 참조
## `modelSupport` 참조
OpenClaw가 `gpt-5.4` 또는 `claude-sonnet-4.6` 같은
축약형 모델 ID에서 Plugin 런타임이 로드되기 전에
provider Plugin을 추론해야 하는 경우 `modelSupport`를 사용하세요.
Plugin 런타임이 로드되기 전에 OpenClaw가 `gpt-5.4` 또는 `claude-sonnet-4.6` 같은
축약형 모델 ID에서 provider Plugin을 추론해야 하는 경우
`modelSupport`를 사용하세요.
```json
{
@ -462,17 +499,17 @@ provider Plugin을 추론해야 하는 경우 `modelSupport`를 사용하세요.
}
```
OpenClaw는 다음 우선순위를 적용합니다:
OpenClaw는 다음 우선순위를 적용합니다.
- 명시적 `provider/model` 참조는 소유 `providers` 매니페스트 메타데이터를 사용합니다
- `modelPatterns``modelPrefixes`보다 우선합니다
- 번들되지 않은 Plugin 하나와 번들 Plugin 하나가 모두 일치하면 번들되지 않은
- 번들되지 않은 Plugin 하나와 번들 Plugin 하나가 모두 일치하면 번들되지 않은
Plugin이 우선합니다
- 남은 모호성은 사용자가 또는 구성이 provider를 지정할 때까지 무시됩니다
- 남은 모호성은 사용자가 provider를 지정하거나 구성이 provider를 지정할 때까지 무시됩니다
필드:
| 필드 | 타입 | 의미 |
| 필드 | 유형 | 의미 |
| --------------- | ---------- | ----------------------------------------------------------------------------- |
| `modelPrefixes` | `string[]` | 축약형 모델 ID에 대해 `startsWith`로 일치시키는 접두사입니다. |
| `modelPatterns` | `string[]` | 프로필 접미사 제거 후 축약형 모델 ID에 대해 일치시키는 정규식 소스입니다. |
@ -481,69 +518,70 @@ OpenClaw는 다음 우선순위를 적용합니다:
`speechProviders`, `realtimeTranscriptionProviders`,
`realtimeVoiceProviders`, `mediaUnderstandingProviders`,
`imageGenerationProviders`, `videoGenerationProviders`,
`webFetchProviders`, `webSearchProviders``contracts` 아래로 이동하세요.
일반 매니페스트 로드는 더 이상 이러한 최상위 필드를 capability
소유권으로 취급하지 않습니다.
`webFetchProviders`, `webSearchProviders``contracts` 아래로
이동하세요. 일반 매니페스트 로딩은 더 이상 이러한 최상위 필드를 capability
소유권으로 처리하지 않습니다.
## 매니페스트와 package.json 비교
## 매니페스트와 `package.json`
두 파일은 서로 다른 역할을 합니다:
두 파일은 서로 다른 역할을 합니다.
| 파일 | 용도 |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `openclaw.plugin.json` | Plugin 코드가 실행되기 전에 존재해야 하는 탐지, 구성 검증, 인증 선택 메타데이터, UI 힌트 |
| `package.json` | npm 메타데이터, 의존성 설치, entrypoint, 설치 게이트, 설정, 카탈로그 메타데이터에 사용되는 `openclaw` 블록 |
| `openclaw.plugin.json` | Plugin 코드가 실행되기 전에 반드시 존재해야 하는 검색, 구성 검증, 인증 선택 메타데이터, UI 힌트 |
| `package.json` | npm 메타데이터, 의존성 설치, 엔트리포인트, 설치 게이팅, 설정 또는 카탈로그 메타데이터에 사용되는 `openclaw` 블록 |
어떤 메타데이터를 어디에 넣어야 할지 확실하지 않다면 다음 규칙을 사용하세요:
어떤 메타데이터를 어디에 둘지 확실하지 않다면 다음 규칙을 사용하세요.
- OpenClaw가 Plugin 코드를 로드하기 전에 알아야 하면 `openclaw.plugin.json`에 넣으세요
- 패키징, 엔트리 파일, npm 설치 동작에 관한 것이`package.json`에 넣으세요
- OpenClaw가 Plugin 코드를 로드하기 전에 반드시 알아야 하면 `openclaw.plugin.json`에 넣으세요
- 패키징, 엔트리 파일 또는 npm 설치 동작에 관한 것이라`package.json`에 넣으세요
### 탐지에 영향을 주는 package.json 필드
### 검색에 영향을 주는 `package.json` 필드
일부 사전 런타임 Plugin 메타데이터는 의도적으로 `openclaw.plugin.json`이 아니라
`package.json``openclaw` 블록 아래에 있습니다.
중요한 예시:
| 필드 | 의미 |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `openclaw.extensions` | 기본 Plugin entrypoint를 선언합니다. Plugin 패키지 디렉터리 내부에 있어야 합니다. |
| `openclaw.runtimeExtensions` | 설치된 패키지용 빌드된 JavaScript 런타임 entrypoint를 선언합니다. Plugin 패키지 디렉터리 내부에 있어야 합니다. |
| `openclaw.setupEntry` | 온보딩, 지연 채널 시작, 읽기 전용 채널 상태/SecretRef 탐지 중에 사용하는 경량 설정 전용 entrypoint입니다. Plugin 패키지 디렉터리 내부에 있어야 합니다. |
| `openclaw.runtimeSetupEntry` | 설치된 패키지용 빌드된 JavaScript 설정 entrypoint를 선언합니다. Plugin 패키지 디렉터리 내부에 있어야 합니다. |
| `openclaw.channel` | 라벨, 문서 경로, 별칭, 선택용 문구 같은 저비용 채널 카탈로그 메타데이터입니다. |
| `openclaw.channel.configuredState` | 전체 채널 런타임을 로드하지 않고도 "환경 변수 전용 설정이 이미 존재하는가?"를 답할 수 있는 경량 configured-state 검사기 메타데이터입니다. |
| `openclaw.channel.persistedAuthState` | 전체 채널 런타임을 로드하지 않고도 "이미 로그인된 항목이 있는가?"를 답할 수 있는 경량 persisted-auth 검사기 메타데이터입니다. |
| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 번들 Plugin 및 외부 게시 Plugin용 설치/업데이트 힌트입니다. |
| `openclaw.install.defaultChoice` | 여러 설치 소스를 사용할 수 있을 때 선호되는 설치 경로입니다. |
| `openclaw.install.minHostVersion` | `>=2026.3.22` 같은 semver 하한을 사용하는 최소 지원 OpenClaw 호스트 버전입니다. |
| `openclaw.install.allowInvalidConfigRecovery` | 구성이 유효하지 않을 때 제한적인 번들 Plugin 재설치 복구 경로를 허용합니다. |
| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen`| 시작 중 전체 채널 Plugin보다 먼저 설정 전용 채널 표면이 로드되도록 합니다. |
| 필드 | 의미 |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `openclaw.extensions` | 네이티브 Plugin 엔트리포인트를 선언합니다. 반드시 Plugin 패키지 디렉터리 내부에 있어야 합니다. |
| `openclaw.runtimeExtensions` | 설치된 패키지에 대한 빌드된 JavaScript 런타임 엔트리포인트를 선언합니다. 반드시 Plugin 패키지 디렉터리 내부에 있어야 합니다. |
| `openclaw.setupEntry` | 온보딩, 지연 채널 시작, 읽기 전용 채널 상태/SecretRef 검색 중 사용되는 경량 설정 전용 엔트리포인트입니다. 반드시 Plugin 패키지 디렉터리 내부에 있어야 합니다. |
| `openclaw.runtimeSetupEntry` | 설치된 패키지에 대한 빌드된 JavaScript 설정 엔트리포인트를 선언합니다. 반드시 Plugin 패키지 디렉터리 내부에 있어야 합니다. |
| `openclaw.channel` | 레이블, 문서 경로, 별칭, 선택용 설명문 같은 저비용 채널 카탈로그 메타데이터입니다. |
| `openclaw.channel.configuredState` | 전체 채널 런타임을 로드하지 않고도 "env 전용 설정이 이미 존재하는가?"에 답할 수 있는 경량 configured-state 검사기 메타데이터입니다. |
| `openclaw.channel.persistedAuthState` | 전체 채널 런타임을 로드하지 않고도 "이미 로그인된 것이 있는가?"에 답할 수 있는 경량 persisted-auth 검사기 메타데이터입니다. |
| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 번들된 Plugin과 외부 게시 Plugin을 위한 설치/업데이트 힌트입니다. |
| `openclaw.install.defaultChoice` | 여러 설치 소스를 사용할 수 있을 때 선호되는 설치 경로입니다. |
| `openclaw.install.minHostVersion` | `>=2026.3.22` 같은 semver 하한을 사용하는 최소 지원 OpenClaw 호스트 버전입니다. |
| `openclaw.install.allowInvalidConfigRecovery` | 구성이 유효하지 않을 때 제한적인 번들 Plugin 재설치 복구 경로를 허용합니다. |
| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 시작 중 전체 채널 Plugin보다 먼저 설정 전용 채널 표면이 로드되도록 합니다. |
`openclaw.install.minHostVersion`은 설치 매니페스트
레지스트리 로드 중에 강제됩니다. 잘못된 값은 거부되며, 더 새롭지만 유효한 값은
오래된 호스트에서 Plugin을 건너뜁니다.
`openclaw.install.minHostVersion`은 설치 매니페스트
레지스트리 로딩 중에 적용됩니다. 유효하지 않은 값은 거부되며, 더 최신이지만 유효한 값은
구형 호스트에서 Plugin을 건너뜁니다.
채널 Plugin은 상태, 채널 목록,
또는 SecretRef 스캔이 전체 런타임을 로드하지 않고도 구성된 계정을 식별해야 하는 경우 `openclaw.setupEntry`를 제공해야 합니다.
setup entry는 채널 메타데이터와 setup-safe 구성,
상태, secrets 어댑터를 노출해야 하며, 네트워크 클라이언트, gateway 리스너,
전송 런타임은 메인 extension entrypoint에 유지하세요.
채널 Plugin은 상태, 채널 목록 또는 SecretRef 스캔에서 전체
런타임을 로드하지 않고도 구성된 계정을 식별해야 하는 경우 `openclaw.setupEntry`를 제공해야 합니다.
설정 엔트리는 채널 메타데이터와 설정에 안전한 구성,
상태, 시크릿 어댑터를 노출해야 합니다. 네트워크 클라이언트, Gateway 리스너,
전송 런타임은 메인 extension 엔트리포인트에 유지하세요.
런타임 entrypoint 필드는 소스
entrypoint 필드에 대한 패키지 경계 검사를 재정의하지 않습니다. 예를 들어, `openclaw.runtimeExtensions`
경계를 벗어나는 `openclaw.extensions` 경로를 로드 가능하게 만들 수 없습니다.
런타임 엔트리포인트 필드는 소스
엔트리포인트 필드에 대한 패키지 경계 검사를 무시하지 않습니다. 예를 들어
`openclaw.runtimeExtensions`는 경계를 벗어나는 `openclaw.extensions` 경로를
로드 가능하게 만들 수 없습니다.
`openclaw.install.allowInvalidConfigRecovery`는 의도적으로 제한적입니다. 이 설정이
임의의 깨진 구성을 설치 가능하게 만들지는 않습니다. 현재는
누락된 번들 Plugin 경로나 동일한
번들 Plugin에 대한 오래된 `channels.<id>` 항목 같은 특정한 오래된 번들 Plugin 업그레이드 실패에서만
설치 흐름이 복구되도록 허용합니다. 관련 없는 구성 오류는 여전히 설치를 차단하고 운영자를
`openclaw doctor --fix`안내합니다.
`openclaw.install.allowInvalidConfigRecovery`는 의도적으로 범위가 좁습니다.
임의의 손상된 구성을 설치 가능하게 만들지는 않습니다. 현재는 특정 오래된 번들 Plugin
업그레이드 실패(예: 누락된 번들 Plugin 경로나 동일한 번들 Plugin에 대한 오래된
`channels.<id>` 항목)에서만 설치 흐름이 복구되도록 허용합니다.
관련 없는 구성 오류는 여전히 설치를 차단하며 운영자를 `openclaw doctor --fix`
안내합니다.
`openclaw.channel.persistedAuthState`는 작은 검사기
모듈을 위한 패키지 메타데이터입니다:
`openclaw.channel.persistedAuthState`아주 작은 검사기
모듈을 위한 패키지 메타데이터입니다.
```json
{
@ -559,13 +597,13 @@ entrypoint 필드에 대한 패키지 경계 검사를 재정의하지 않습니
}
```
설정, doctor, 또는 configured-state 흐름이 전체
채널 Plugin이 로드되기 전에 저비용 yes/no 인증 프로브를 필요로 할 때 사용하세요. 대상 export는
지속된 상태만 읽는 작은 함수여야 하며, 전체
채널 런타임 배럴을 통해 연결하지 마세요.
전체 채널 Plugin이 로드되기 전에 설정, doctor 또는 configured-state 흐름에
저비용의 yes/no 인증 프로브가 필요한 경우 이것을 사용하세요. 대상 export는
저장된 상태만 읽는 작은 함수여야 하며, 전체 채널 런타임 배럴을 통해
라우팅하지 마세요.
`openclaw.channel.configuredState`는 저비용 환경 변수 전용
configured-state 검사를 위한 동일한 형태를 따릅니다:
`openclaw.channel.configuredState`는 저비용 env 전용
configured 검사에 대해 같은 형태를 따릅니다.
```json
{
@ -581,31 +619,31 @@ configured-state 검사를 위한 동일한 형태를 따릅니다:
}
```
채널이 환경 변수 또는 기타 작은
비런타임 입력에서 configured-state를 답할 수 있을 때 사용하세요. 검사가 전체 구성 확인 또는 실제
채널 런타임을 필요로 한다면, 그 로직은 대신 Plugin `config.hasConfiguredState`
hook에 유지하세요.
채널이 env 또는 기타 작은
비런타임 입력만으로 configured-state에 응답할 수 있는 경우 이것을 사용하세요. 검사에 전체
구성 해석이나 실제 채널 런타임이 필요하다면, 그 로직은 대신 Plugin `config.hasConfiguredState`
hook에 세요.
## 탐지 우선순위(중복 Plugin ID)
## 검색 우선순위(중복 Plugin ID)
OpenClaw는 여러 루트(번들, 전역 설치, 워크스페이스, 명시적 구성 선택 경로)에서 Plugin을 탐지합니다. 두 탐지 항목이 동일한 `id`를 공유하면, **가장 높은 우선순위**의 매니페스트만 유지되고 더 낮은 우선순위의 중복 항목은 나란히 로드되지 않고 제거됩니다.
OpenClaw는 여러 루트(번들, 전역 설치, 워크스페이스, 명시적으로 구성에서 선택된 경로)에서 Plugin을 검색합니다. 두 검색 결과가 같은 `id`를 공유하면 **가장 높은 우선순위**의 매니페스트만 유지되고, 더 낮은 우선순위의 중복 항목은 나란히 로드되는 대신 제거됩니다.
우선순위, 높은 순서부터 낮은 순서까지:
우선순위, 높은 순서에서 낮은 순서:
1. **구성 선택됨**`plugins.entries.<id>`에 명시적으로 고정된 경로
2. **번들됨** — OpenClaw와 함께 제공되는 Plugin
3. **전역 설치** — 전역 OpenClaw Plugin 루트에 설치된 Plugin
4. **워크스페이스** — 현재 워크스페이스를 기준으로 탐지된 Plugin
4. **워크스페이스** — 현재 워크스페이스를 기준으로 검색된 Plugin
의미:
영향:
- 워크스페이스에 있는 번들 Plugin의 포크 또는 오래된 복사본은 번들 빌드를 가리지 못합니다.
- 번들 Plugin을 실제로 로컬 Plugin으로 재정의하려면, 워크스페이스 탐지에 의존하지 말고 `plugins.entries.<id>`를 통해 고정하여 우선순위로 이기도록 하세요.
- 중복 제거는 로그에 기록되므로 Doctor 및 시작 진단이 제거된 복사본을 가리킬 수 있습니다.
- 번들 Plugin을 로컬 Plugin으로 실제로 재정의하려면 워크스페이스 검색에 의존하지 말고 `plugins.entries.<id>`를 통해 고정해 우선순위에서 이기게 하세요.
- 제거된 중복 항목은 로그에 기록되므로 Doctor와 시작 진단이 버려진 복사본을 가리킬 수 있습니다.
## JSON 스키마 요구 사항
- **모든 Plugin은 JSON 스키마를 포함해야 하며**, 구성을 전혀 받지 않는 경우에도 마찬가지입니다.
- **모든 Plugin은 JSON 스키마를 반드시 포함해야 하며**, 구성을 전혀 받지 않는 경우도 예외가 아닙니다.
- 빈 스키마도 허용됩니다(예: `{ "type": "object", "additionalProperties": false }`).
- 스키마는 런타임이 아니라 구성 읽기/쓰기 시점에 검증됩니다.
@ -614,62 +652,62 @@ OpenClaw는 여러 루트(번들, 전역 설치, 워크스페이스, 명시적
- 알 수 없는 `channels.*` 키는 **오류**입니다. 단, 해당 채널 ID가
Plugin 매니페스트에 선언된 경우는 예외입니다.
- `plugins.entries.<id>`, `plugins.allow`, `plugins.deny`, `plugins.slots.*`
**탐지 가능한** Plugin ID를 참조해야 합니다. 알 수 없는 ID는 **오류**입니다.
- Plugin이 설치되어 있지만 매니페스트나 스키마가 손상되었거나 없으면,
**검색 가능한** Plugin ID를 참조해야 합니다. 알 수 없는 ID는 **오류**입니다.
- Plugin이 설치되어 있지만 매니페스트나 스키마가 손상되었거나 없으면
검증이 실패하고 Doctor가 Plugin 오류를 보고합니다.
- Plugin 구성이 존재하지만 Plugin이 **비활성화**되어 있으면, 구성은 유지되고
- Plugin 구성이 존재하지만 Plugin이 **비활성화**되어 있으면 해당 구성은 유지되며
Doctor + 로그에 **경고**가 표시됩니다.
전체 `plugins.*` 스키마는 [구성 참조](/ko/gateway/configuration)를 참조하세요.
## 참고
- 매니페스트는 로컬 파일 시스템 로드를 포함한 **기본 OpenClaw Plugin에 필수**입니다.
- 런타임은 여전히 Plugin 모듈을 별도로 로드하며, 매니페스트는
탐지 + 검증 전용입니다.
- 기본 매니페스트는 JSON5로 파싱되므로, 최종 값이 여전히 객체이기만 하면
주석, 후행 쉼표, 따옴표 없는 키를 사용할 수 있습니다.
- 매니페스트 로더는 문서화된 매니페스트 필드만 읽습니다. 여기에
사용자 정의 최상위 키를 추가하지 마세요.
- 매니페스트는 로컬 파일시스템 로드를 포함해 **네이티브 OpenClaw Plugin에 필수**입니다.
- 런타임은 여전히 Plugin 모듈을 별도로 로드합니다. 매니페스트는
검색 + 검증 전용입니다.
- 네이티브 매니페스트는 JSON5로 파싱되므로, 최종 값이 여전히 객체이기만 하면
주석, 후행 쉼표, 따옴표 없는 키가 허용됩니다.
- 매니페스트 로더는 문서화된 매니페스트 필드만 읽습니다. 여기에 사용자 정의
최상위 키를 추가하지 마세요.
- `providerAuthEnvVars`는 인증 프로브, env-marker
검증 및 env 이름을 검사하기 위해 Plugin
런타임을 부팅해서는 안 되는 유사 provider 인증 표면을 위한 저비용 메타데이터 경로입니다.
검증 및 유사한 provider 인증 표면을 위한 저비용 메타데이터 경로이며,
env 이름을 확인하기 위해 Plugin 런타임을 부팅하지 않아야 하는 경우에 사용합니다.
- `providerAuthAliases`는 provider 변형이 다른 provider의 인증
env 변수, 인증 프로필, 구성 기반 인증, API 키 온보딩 선택을
코어에 해당 관계를 하드코딩하지 않고 재사용할 수 있게 합니다.
env var, 인증 프로필, config 기반 인증, API 키 온보딩 선택을
코어에 관계를 하드코딩하지 않고 재사용할 수 있게 합니다.
- `providerEndpoints`는 provider Plugin이 단순 endpoint host/baseUrl
일치 메타데이터를 소유할 수 있게 합니다. 코어가 이미 지원하는 endpoint 클래스에만
사용하세요. 런타임 동작은 여전히 Plugin이 소유합니다.
매칭 메타데이터를 소유할 수 있게 합니다. 코어가 이미 지원하는 endpoint class에만
사용하세요. 실제 런타임 동작은 여전히 Plugin이 소유합니다.
- `syntheticAuthRefs`는 provider 소유 synthetic
인증 hook를 위한 저비용 메타데이터 경로이며, 런타임
레지스트리가 존재하기 전에 cold 모델 탐색에서 보여야 합니다. 런타임 provider 또는 CLI backend가 실제로
auth hook을 위한 저비용 메타데이터 경로이며, 런타임
레지스트리가 존재하기 전에 콜드 모델 검색에서 보여야 하는 경우에 사용합니다. 런타임 provider 또는 CLI 백엔드가 실제로
`resolveSyntheticAuth`를 구현하는 참조만 나열하세요.
- `nonSecretAuthMarkers`는 번들 Plugin 소유
placeholder API 키(예: 로컬, OAuth 또는 주변 자격 증명 마커)를 위한 저비용 메타데이터 경로입니다.
코어는 소유 provider를 하드코딩하지 않고도
인증 표시와 비밀 감사에서 이를 비비밀로 취급합니다.
- `channelEnvVars`쉘 환경 변수 폴백, 설정
프롬프트 및 env 이름을 검사하기 위해 Plugin 런타임을 부팅해서는 안 되는 유사 채널 표면을 위한 저비용 메타데이터 경로입니다.
환경 변수 이름은 메타데이터이며, 그 자체로 활성화는 아닙니다. 상태, 감사, Cron 전달 검증 및 기타 읽기 전용
표면은 여전히 Plugin 신뢰 및 유효 활성화 정책을 적용한 후에야
환경 변수를 구성된 채널로 취급합니다.
- `nonSecretAuthMarkers`는 번들 Plugin 소유
local, OAuth 또는 ambient credential marker 같은 플레이스홀더 API 키를 위한 저비용 메타데이터 경로입니다.
코어는 소유 provider를 하드코딩하지 않고도 인증 표시 및 시크릿 감사에서
이를 비시크릿으로 처리합니다.
- `channelEnvVars`셸 env 폴백, 설정
프롬프트 및 env 이름을 확인하기 위해 Plugin 런타임을 부팅하지 않아야 하는 유사한 채널 표면을 위한 저비용 메타데이터 경로입니다.
env 이름은 메타데이터일 뿐, 그 자체로 활성화는 아닙니다.
상태, 감사, Cron 전달 검증 및 기타 읽기 전용
표면은 여전히 env var를 구성된 채널로 처리하기 전에 Plugin 신뢰와 유효 활성화 정책을 적용합니다.
- `providerAuthChoices`는 인증 선택 선택기,
`--auth-choice` 확인, 선호 provider 매핑, 단순 온보딩
CLI 플래그 등록을 위한 저비용 메타데이터 경로이며 provider 런타임이 로드되기 전에 사용됩니다. provider 코드가 필요한 런타임 wizard
`--auth-choice` 해석, 선호 provider 매핑, 단순 온보딩
CLI 플래그 등록을 provider 런타임 로드 전에 처리하기 위한 저비용 메타데이터 경로입니다. provider 코드가 필요한 런타임 wizard
메타데이터는
[Provider runtime hooks](/ko/plugins/architecture#provider-runtime-hooks)를 참조하세요.
[Provider 런타임 hooks](/ko/plugins/architecture#provider-runtime-hooks)를 참조하세요.
- 배타적 Plugin 종류는 `plugins.slots.*`를 통해 선택됩니다.
- `kind: "memory"``plugins.slots.memory`로 선택됩니다.
- `kind: "context-engine"``plugins.slots.contextEngine`으로 선택됩니다
(기본값: 내장 `legacy`).
- Plugin에 필요하지 않다면 `channels`, `providers`, `cliBackends`, `skills`
생략할 수 있습니다.
- Plugin이 기본 모듈에 의존하는 경우 빌드 단계와
패키지 관리자 허용 목록 요구 사항(예: pnpm `allow-build-scripts`
- `pnpm rebuild <package>`)을 문서화하세요.
- `channels`, `providers`, `cliBackends`, `skills`
Plugin에 필요하지 않으면 생략할 수 있습니다.
- Plugin이 네이티브 모듈에 의존한다면 빌드 단계와
패키지 관리자 허용 목록 요구 사항을 문서화하세요(예: pnpm `allow-build-scripts`
- `pnpm rebuild <package>`).
## 관련 항목
- [Plugin 빌드하기](/ko/plugins/building-plugins) — Plugin 시작하기
- [Plugin 빌드하기](/ko/plugins/building-plugins) — Plugin 시작 가이드
- [Plugin 아키텍처](/ko/plugins/architecture) — 내부 아키텍처
- [SDK 개요](/ko/plugins/sdk-overview) — Plugin SDK 참조

View File

@ -1,55 +1,55 @@
---
read_when:
- 내장 에이전트 런타임 또는 하네스 레지스트리를 변경하고 있습니다
- 번들되었거나 신뢰할 수 있는 플러그인에서 에이전트 하네스를 등록하고 있습니다
- Codex 플러그인이 모델 제공자와 어떤 관련이 있는지 이해해야 합니다
- 번들되었거나 신뢰할 수 있는 Plugin에서 에이전트 하네스를 등록하고 있습니다
- Codex Plugin이 모델 provider와 어떤 관련이 있는지 이해해야 합니다
sidebarTitle: Agent Harness
summary: 낮은 수준의 내장 에이전트 실행기를 대체하는 플러그인을 위한 실험적 SDK 표면
title: 에이전트 하네스 플러그인
summary: 저수준 내장 에이전트 실행기를 대체하는 Plugin용 실험적 SDK 표면
title: 에이전트 하네스 Plugin
x-i18n:
generated_at: "2026-04-12T00:18:56Z"
generated_at: "2026-04-22T06:00:30Z"
model: gpt-5.4
provider: openai
source_hash: 62b88fd24ce8b600179db27e16e8d764a2cd7a14e5c5df76374c33121aa5e365
source_hash: 728fef59ae3cce29a3348842820f1f71a2eac98ae6b276179bce6c85d16613df
source_path: plugins/sdk-agent-harness.md
workflow: 15
---
# 에이전트 하네스 플러그인
# 에이전트 하네스 Plugin
**에이전트 하네스**는 준비된 OpenClaw 에이전트 턴 하나를 위한 낮은 수준의 실행기입니다. 이는 모델 제공자도, 채널도, 도구 레지스트리도 아닙니다.
**에이전트 하네스**는 준비된 OpenClaw 에이전트 한 턴을 위한 저수준 실행기입니다. 이것은 모델 provider도, channel도, tool registry도 아닙니다.
이 표면은 번들되었거나 신뢰할 수 있는 네이티브 플러그인에만 사용하세요. 이 계약은 매개변수 타입이 의도적으로 현재 내장 러너를 그대로 반영하므로 아직 실험적입니다.
이 표면은 번들되었거나 신뢰할 수 있는 네이티브 Plugin에만 사용하세요. 이 계약은 여전히 실험적이며, 그 이유는 파라미터 타입이 의도적으로 현재 내장 러너를 반영하기 때문입니다.
## 하네스를 사용하는 경우
## 하네스를 사용해야 하는 경우
모델 계열이 자체 네이티브 세션 런타임을 가지고 있고 일반적인 OpenClaw 제공자 전송이 잘못된 추상화일 때 에이전트 하네스를 등록하세요.
모델 패밀리에 자체 네이티브 세션 런타임이 있고 일반적인 OpenClaw provider 전송이 잘못된 추상화인 경우 에이전트 하네스를 등록하세요.
예시:
- 스레드와 compaction을 직접 관리하는 네이티브 코딩 에이전트 서버
- 네이티브 plan/reasoning/tool 이벤트를 스트리밍해야 하는 로컬 CLI 또는 데몬
- OpenClaw 세션 transcript에 더해 자체 resume id가 필요한 모델 런타임
- 스레드와 Compaction을 자체적으로 관리하는 네이티브 코딩 에이전트 서버
- 네이티브 계획/추론/tool 이벤트를 스트리밍해야 하는 로컬 CLI 또는 데몬
- OpenClaw 세션 transcript에 자체 resume id가 필요한 모델 런타임
새 LLM API를 추가하기 위해 하네스를 등록해서는 **안 됩니다**. 일반적인 HTTP 또는 WebSocket 모델 API의 경우 [provider plugin](/ko/plugins/sdk-provider-plugins)을 빌드하세요.
로운 LLM API를 추가하기 위해 하네스를 등록해서는 **안 됩니다**. 일반적인 HTTP 또는 WebSocket 모델 API의 경우 [provider Plugin](/ko/plugins/sdk-provider-plugins)을 만드세요.
## 코어가 계속 소유하는 것
## 여전히 코어가 담당하는 것
하네스가 선택되기 전에 OpenClaw는 이미 다음을 해석합니다:
하네스가 선택되기 전에 OpenClaw는 이미 다음을 해결했습니다:
- 제공자와 모델
- 런타임 인증 상태
- provider와 모델
- 런타임 auth 상태
- thinking level과 context budget
- OpenClaw transcript/session 파일
- workspace, sandbox, 도구 정책
- 채널 응답 콜백과 스트리밍 콜백
- 모델 폴백과 라이브 모델 전환 정책
- workspace, sandbox, 그리고 tool 정책
- channel reply callback과 streaming callback
- 모델 fallback 및 live 모델 전환 정책
이 분리는 의도된 것입니다. 하네스는 준비된 시도를 실행할 뿐이며, 제공자를 선택하거나, 채널 전달을 대체하거나, 모델을 조용히 전환하지 않습니다.
이 분리는 의도된 것입니다. 하네스는 준비된 시도를 실행하며, provider를 선택하거나, channel 전달을 대체하거나, 모델을 조용히 전환하지 않습니다.
## 하네스 등록
## 하네스 등록하기
**가져오기:** `openclaw/plugin-sdk/agent-harness`
**Import:** `openclaw/plugin-sdk/agent-harness`
```typescript
import type { AgentHarness } from "openclaw/plugin-sdk/agent-harness";
@ -85,49 +85,49 @@ export default definePluginEntry({
## 선택 정책
OpenClaw는 제공자/모델 해석 후 하네스를 선택합니다:
OpenClaw는 provider/모델 해석 후 하네스를 선택합니다:
1. `OPENCLAW_AGENT_RUNTIME=<id>`는 해당 id를 가진 등록된 하네스를 강제합니다.
2. `OPENCLAW_AGENT_RUNTIME=pi`는 내장 PI 하네스를 강제합니다.
3. `OPENCLAW_AGENT_RUNTIME=auto`는 등록된 하네스에 해석된 제공자/모델을 지원하는지 묻습니다.
4. 등록된 하네스가 일치하지 않으면, PI 폴백이 비활성화되지 않은 한 OpenClaw는 PI를 사용합니다.
3. `OPENCLAW_AGENT_RUNTIME=auto`는 등록된 하네스들에 해석된 provider/모델을 지원하는지 질의합니다.
4. 일치하는 등록된 하네스가 없으면, PI fallback이 비활성화되지 않은 한 OpenClaw는 PI를 사용합니다.
강제된 플러그인 하네스 실패는 실행 실패로 표시됩니다. `auto` 모드에서는 선택된 플러그인 하네스가 턴이 부작용을 만들기 전에 실패하면 OpenClaw가 PI로 폴백할 수 있습니다. 대신 그 폴백을 하드 실패로 만들려면 `OPENCLAW_AGENT_HARNESS_FALLBACK=none` 또는 `embeddedHarness.fallback: "none"`을 설정하세요.
Plugin 하네스 실패는 실행 실패로 표면화됩니다. `auto` 모드에서 PI fallback은 해석된 provider/모델을 지원하는 등록된 Plugin 하네스가 없을 때만 사용됩니다. Plugin 하네스가 한번 실행을 맡으면, OpenClaw는 같은 턴을 PI를 통해 다시 실행하지 않습니다. 그렇게 하면 auth/런타임 의미가 바뀌거나 부작용이 중복될 수 있기 때문입니다.
번들된 Codex 플러그인은 `codex`를 하네스 id로 등록합니다. 코어는 이를 일반적인 플러그인 하네스 id로 취급합니다. Codex 전용 별칭은 공유 런타임 선택기가 아니라 플러그인 또는 운영자 설정에 속해야 합니다.
번들된 Codex Plugin은 `codex`를 하네스 id로 등록합니다. 코어는 이를 일반적인 Plugin 하네스 id로 취급합니다. Codex 전용 alias는 공유 런타임 선택자가 아니라 Plugin 또는 운영자 config에 속합니다.
## 제공자와 하네스 페어링
## provider와 하네스 페어링
대부분의 하네스는 제공자도 함께 등록해야 합니다. 제공자는 모델 ref, 인증 상태, 모델 메타데이터, `/model` 선택을 OpenClaw의 나머지 부분에서 볼 수 있게 합니다. 그런 다음 하네스는 `supports(...)`에서 해당 제공자를 claim합니다.
대부분의 하네스는 provider도 함께 등록해야 합니다. provider는 모델 ref, auth 상태, 모델 메타데이터, 그리고 `/model` 선택을 OpenClaw의 나머지 부분에 보이게 합니다. 그 다음 하네스는 `supports(...)`에서 해당 provider를 맡습니다.
번들된 Codex 플러그인은 이 패턴을 따릅니다:
번들된 Codex Plugin은 이 패턴을 따릅니다:
- provider id: `codex`
- 사용자 모델 ref: `codex/gpt-5.4`, `codex/gpt-5.2`, 또는 Codex app server가 반환하는 다른 모델
- 사용자 모델 ref: `codex/gpt-5.4`, `codex/gpt-5.2`, 또는 Codex 앱 서버가 반환한 다른 모델
- harness id: `codex`
- auth: 합성 제공자 가용성. Codex 하네스가 네이티브 Codex 로그인/세션을 소유하기 때문입니다
- app-server request: OpenClaw는 bare model id를 Codex에 보내고 하네스가 네이티브 app-server 프로토콜과 통신하도록 둡니다
- auth: 합성된 provider 가용성. Codex 하네스가 네이티브 Codex 로그인/세션을 관리하기 때문입니다
- app-server 요청: OpenClaw는 순수 모델 id를 Codex에 보내고, 하네스가 네이티브 app-server 프로토콜과 통신하도록 둡니다
Codex 플러그인은 추가적입니다. 일반 `openai/gpt-*` ref는 계속 OpenAI provider ref로 남으며 일반 OpenClaw provider 경로를 계속 사용합니다. Codex 관리 인증, Codex 모델 검색, 네이티브 스레드, Codex app-server 실행을 원할 때는 `codex/gpt-*`를 선택하세요. `/model`은 OpenAI provider 자격 증명이 없어도 Codex app server가 반환한 Codex 모델들 사이를 전환할 수 있습니다.
Codex Plugin은 가산적입니다. 일반 `openai/gpt-*` ref는 여전히 OpenAI provider ref이며 정상적인 OpenClaw provider 경로를 계속 사용합니다. Codex가 관리하는 auth, Codex 모델 검색, 네이티브 스레드, 그리고 Codex app-server 실행을 원할 때 `codex/gpt-*`를 선택하세요. `/model`은 OpenAI provider 자격 증명을 요구하지 않고도 Codex 앱 서버가 반환한 Codex 모델 사이를 전환할 수 있습니다.
운영자 설정, 모델 접두사 예시, Codex 전용 구성은 [Codex Harness](/ko/plugins/codex-harness)를 참조하세요.
운영자 설정, 모델 prefix 예시, 그리고 Codex 전용 config는 [Codex Harness](/ko/plugins/codex-harness)를 참고하세요.
OpenClaw는 Codex app-server `0.118.0` 이상을 요구합니다. Codex 플러그인은 app-server initialize 핸드셰이크를 검사하고 더 오래되었거나 버전이 없는 서버를 차단하여 OpenClaw가 테스트된 프로토콜 표면에 대해서만 실행되도록 합니다.
OpenClaw는 Codex app-server `0.118.0` 이상을 요구합니다. Codex Plugin은 app-server 초기화 handshake를 확인하고, 버전이 더 낮거나 버전 정보가 없는 서버를 차단하여 OpenClaw가 테스트된 프로토콜 표면에서만 실행되도록 합니다.
### 네이티브 Codex 하네스 모드
번들된 `codex` 하네스는 내장 OpenClaw 에이전트 턴을 위한 네이티브 Codex 모드입니다. 먼저 번들된 `codex` 플러그인을 활성화하고, 구성이 제한적인 allowlist를 사용한다면 `plugins.allow``codex`를 포함하세요. 이것은 `openai-codex/*`와 다릅니다:
번들된 `codex` 하네스는 내장 OpenClaw 에이전트 턴을 위한 네이티브 Codex 모드입니다. 먼저 번들된 `codex` Plugin을 활성화하고, config에서 제한적인 allowlist를 사용한다면 `plugins.allow``codex`를 포함하세요. 이것은 `openai-codex/*`와 다릅니다:
- `openai-codex/*`는 일반 OpenClaw provider 경로를 통해 ChatGPT/Codex OAuth를 사용합니다.
- `openai-codex/*`는 일반적인 OpenClaw provider 경로를 통해 ChatGPT/Codex OAuth를 사용합니다.
- `codex/*`는 번들된 Codex provider를 사용하고 턴을 Codex app-server를 통해 라우팅합니다.
이 모드가 실행되면 Codex는 네이티브 thread id, resume 동작, compaction, app-server 실행을 소유합니다. OpenClaw는 여전히 채팅 채널, 표시되는 transcript mirror, 도구 정책, 승인, 미디어 전달, 세션 선택을 소유합니다. Codex app-server 경로가 사용되고 있고 PI 폴백이 고장 난 네이티브 하네스를 숨기지 않음을 증명해야 한다면 `embeddedHarness.runtime: "codex"``embeddedHarness.fallback: "none"`을 사용하세요.
이 모드가 실행되면 Codex는 네이티브 thread id, resume 동작, Compaction, 그리고 app-server 실행을 관리합니다. OpenClaw는 여전히 chat channel, 표시되는 transcript 미러, tool 정책, 승인, media 전달, 그리고 session 선택을 관리합니다. 오직 Codex app-server 경로만 실행을 맡을 수 있음을 증명해야 한다면 `embeddedHarness.runtime: "codex"``embeddedHarness.fallback: "none"`을 사용하세요. 이 config는 선택 가드일 뿐입니다. Codex app-server 실패는 이미 PI를 통해 재시도하지 않고 직접 실패하기 때문입니다.
## PI 폴백 비활성화
## PI fallback 비활성화
기본적으로 OpenClaw는 `agents.defaults.embeddedHarness``{ runtime: "auto", fallback: "pi" }`로 설정하여 내장 에이전트를 실행합니다. `auto` 모드에서 등록된 플러그인 하네스는 제공자/모델 쌍을 claim할 수 있습니다. 일치하는 것이 없거나 자동 선택된 플러그인 하네스가 출력을 만들기 전에 실패하면 OpenClaw는 PI로 폴백합니다.
기본적으로 OpenClaw는 `agents.defaults.embeddedHarness``{ runtime: "auto", fallback: "pi" }`로 설정하여 내장 에이전트를 실행합니다. `auto` 모드에서는 등록된 Plugin 하네스가 provider/모델 쌍을 맡을 수 있습니다. 일치하는 것이 없으면 OpenClaw는 PI로 fallback합니다.
플러그인 하네스가 유일하게 실행되는 런타임임을 증명해야 할 때는 `fallback: "none"`을 설정하세요. 이렇게 하면 자동 PI 폴백이 비활성화됩니다. 명시적인 `runtime: "pi"` 또는 `OPENCLAW_AGENT_RUNTIME=pi`는 차단하지 않습니다.
Plugin 하네스 선택이 누락됐을 때 PI를 사용하는 대신 실패하도록 해야 한다면 `fallback: "none"`을 설정하세요. 선택된 Plugin 하네스의 실패는 이미 즉시 실패합니다. 이것은 명시적인 `runtime: "pi"` 또는 `OPENCLAW_AGENT_RUNTIME=pi`를 막지 않습니다.
Codex 전용 내장 실행의 경우:
@ -145,7 +145,7 @@ Codex 전용 내장 실행의 경우:
}
```
등록된 어떤 플러그인 하네스라도 일치하는 모델을 claim하게 하되 OpenClaw가 절대로 조용히 PI로 폴백하지 않게 하려면 `runtime: "auto"`를 유지하고 폴백을 비활성화하세요:
등록된 어떤 Plugin 하네스든 일치하는 모델을 맡게 하고 싶지만 OpenClaw가 절대로 조용히 PI로 fallback하지 않게 하려면 `runtime: "auto"`를 유지하고 fallback을 비활성화하세요:
```json
{
@ -160,7 +160,7 @@ Codex 전용 내장 실행의 경우:
}
```
에이전트별 재정의도 같은 형태를 사용합니다:
에이전트별 override도 같은 형태를 사용합니다:
```json
{
@ -185,7 +185,7 @@ Codex 전용 내장 실행의 경우:
}
```
`OPENCLAW_AGENT_RUNTIME`는 여전히 구성된 runtime보다 우선합니다. 환경에서 PI 폴백을 비활성화하려면 `OPENCLAW_AGENT_HARNESS_FALLBACK=none`을 사용하세요.
`OPENCLAW_AGENT_RUNTIME`는 여전히 config된 runtime을 override합니다. 환경에서 PI fallback을 비활성화하려면 `OPENCLAW_AGENT_HARNESS_FALLBACK=none`을 사용하세요.
```bash
OPENCLAW_AGENT_RUNTIME=codex \
@ -193,39 +193,39 @@ OPENCLAW_AGENT_HARNESS_FALLBACK=none \
openclaw gateway run
```
폴백이 비활성화되면 요청된 하네스가 등록되지 않았거나, 해석된 제공자/모델을 지원하지 않거나, 턴 부작용을 만들기 전에 실패할 때 세션은 초기에 실패합니다. 이는 Codex 전용 배포와 Codex app-server 경로가 실제로 사용 중임을 증명해야 하는 라이브 테스트를 위한 의도된 동작입니다.
fallback이 비활성화되면 요청된 하네스가 등록되지 않았거나, 해석된 provider/모델을 지원하지 않거나, 턴 부작용을 생성하기 전에 실패하는 경우 session은 조기에 실패합니다. 이것은 Codex 전용 배포와 실제로 Codex app-server 경로가 사용 중임을 증명해야 하는 live 테스트를 위한 의도된 동작입니다.
이 설정은 내장 에이전트 하네스만 제어합니다. 이미지, 비디오, 음악, TTS, PDF 또는 다른 제공자별 모델 라우팅은 비활성화하지 않습니다.
이 설정은 내장 에이전트 하네스만 제어합니다. image, video, music, TTS, PDF, 또는 기타 provider별 모델 라우팅은 비활성화하지 않습니다.
## 네이티브 세션과 transcript mirror
## 네이티브 세션과 transcript 미러
하네스는 네이티브 session id, thread id 또는 데몬 측 resume token을 유지할 수 있습니다. 그 바인딩을 OpenClaw 세션과 명시적으로 연결해 두고, 사용자에게 보이는 assistant/tool 출력을 OpenClaw transcript에 계속 미러링하세요.
하네스는 네이티브 session id, thread id, 또는 데몬 측 resume token을 유지할 수 있습니다. 그 바인딩을 OpenClaw session과 명시적으로 연결된 상태로 유지하고, 사용자에게 보이는 assistant/tool 출력을 계속 OpenClaw transcript에 미러링하세요.
OpenClaw transcript는 다음을 위한 호환성 계층으로 남아 있습니다:
- 채널에 표시되는 세션 기록
- channel에 보이는 session 기록
- transcript 검색 및 인덱싱
- 이후 턴에서 내장 PI 하네스로 다시 전환
- 일반 `/new`, `/reset`, 세션 삭제 동작
- 일반적인 `/new`, `/reset`, 그리고 session 삭제 동작
하네스가 사이드카 바인딩을 저장한다면 소유한 OpenClaw 세션이 재설정될 때 OpenClaw가 이를 지울 수 있도록 `reset(...)`을 구현하세요.
하네스가 사이드카 바인딩을 저장한다면, 소유한 OpenClaw session이 reset될 때 OpenClaw가 이를 지울 수 있도록 `reset(...)`을 구현하세요.
## 도구 및 미디어 결과
## tool 및 media 결과
코어는 OpenClaw 도구 목록을 구성하고 이를 준비된 시도에 전달합니다. 하네스가 동적 도구 호출을 실행할 때는 채널 미디어를 직접 보내는 대신 하네스 결과 형태를 통해 도구 결과를 반환하세요.
코어는 OpenClaw tool 목록을 구성하고 이를 준비된 시도에 전달합니다. 하네스가 동적 tool 호출을 실행할 때는 channel media를 직접 보내지 말고, 하네스 결과 shape를 통해 tool 결과를 반환하세요.
이렇게 하면 텍스트, 이미지, 비디오, 음악, TTS, 승인, 메시징 도구 출력이 PI 기반 실행과 동일한 전달 경로를 유지합니다.
이렇게 하면 text, image, video, music, TTS, 승인, 그리고 메시징 tool 출력이 PI 기반 실행과 동일한 전달 경로를 유지할 수 있습니다.
## 현재 제한 사항
- 공개 import 경로는 일반적이지만, 일부 attempt/result 타입 별칭은 호환성을 위해 여전히 `Pi` 이름을 사용합니다.
- 서드파티 하네스 설치는 실험적입니다. 네이티브 세션 런타임이 필요해질 때까지는 provider plugin을 우선 사용하세요.
- 턴 간 하네스 전환은 지원됩니다. 네이티브 도구, 승인, assistant 텍스트 또는 메시지 전송이 시작된 뒤에는 턴 중간에 하네스를 전환하지 마세요.
- 공개 import 경로는 일반적이지만, 일부 시도/결과 타입 alias는 호환성을 위해 여전히 `Pi` 이름을 갖고 있습니다.
- 서드파티 하네스 설치는 실험적입니다. 네이티브 세션 런타임이 필요해질 때까지는 provider Plugin을 선호하세요.
- 턴 간 하네스 전환은 지원됩니다. 네이티브 tool, 승인, assistant 텍스트, 또는 메시지 전송이 시작된 후에는 턴 도중 하네스를 전환하지 마세요.
## 관련 항목
- [SDK 개요](/ko/plugins/sdk-overview)
- [런타임 헬퍼](/ko/plugins/sdk-runtime)
- [제공자 플러그인](/ko/plugins/sdk-provider-plugins)
- [provider Plugin](/ko/plugins/sdk-provider-plugins)
- [Codex Harness](/ko/plugins/codex-harness)
- [모델 제공자](/ko/concepts/model-providers)
- [모델 provider](/ko/concepts/model-providers)

View File

@ -1,114 +1,94 @@
---
read_when:
- 새 메시징 채널 Plugin을 구축하고 있습니다
- OpenClaw 메시징 플랫폼에 연결하려고 합니다
- 새 메시징 채널 Plugin을 빌드하고 있습니다
- OpenClaw 메시징 플랫폼에 연결하려고 합니다
- ChannelPlugin 어댑터 표면을 이해해야 합니다
sidebarTitle: Channel Plugins
summary: OpenClaw용 메시징 채널 Plugin 구축 단계별 가이드
title: 채널 Plugin 구축
summary: OpenClaw용 메시징 채널 Plugin을 빌드하는 단계별 가이드
title: 채널 Plugin 빌드하기
x-i18n:
generated_at: "2026-04-22T04:24:43Z"
generated_at: "2026-04-22T06:00:33Z"
model: gpt-5.4
provider: openai
source_hash: f08bf785cd2e16ed6ce0317f4fd55c9eccecf7476d84148ad47e7be516dd71fb
source_hash: e67d8c4be8cc4a312e5480545497b139c27bed828304de251e6258a3630dd9b5
source_path: plugins/sdk-channel-plugins.md
workflow: 15
---
# 채널 Plugin 구축
# 채널 Plugin 빌드하기
이 가이드는 OpenClaw을 메시징 플랫폼에 연결하는 채널 Plugin을 구축하는 과정을 안내합니다. 이 가이드를 마치면 DM 보안, pairing, 답장 스레딩, 아웃바운드 메시징을 갖춘 작동하는 채널을 만들 수 있습니다.
이 가이드는 OpenClaw를 메시징 플랫폼에 연결하는 채널 Plugin을 빌드하는 과정을 안내합니다. 이 가이드를 마치면 DM 보안, 페어링, 답장 스레딩, 아웃바운드 메시징을 갖춘 작동하는 채널을 만들 수 있습니다.
<Info>
아직 OpenClaw Plugin을 한 번도 만들어 본 적이 없다면, 먼저
기본 패키지 구조와 manifest 설정을 다루는
아직 OpenClaw Plugin을 한 번도 만들어본 적이 없다면, 기본 패키지
구조와 manifest 설정을 위해 먼저
[시작하기](/ko/plugins/building-plugins)를 읽으세요.
</Info>
## 채널 Plugin의 작동 방식
채널 Plugin은 자체 send/edit/react 도구가 필요하지 않습니다. OpenClaw는
코어에 하나의 공통 `message` 도구를 유지합니다. Plugin이 담당하는 영역은 다음과 같습니다:
채널 Plugin에는 자체 send/edit/react 도구가 필요하지 않습니다. OpenClaw는 코어에 공유 `message` 도구 하나를 유지합니다. Plugin은 다음을 담당합니다.
- **Config** — 계정 확인 및 설정 마법사
- **보안** — DM 정책 및 허용 목록
- **Security** — DM 정책 및 허용 목록
- **Pairing** — DM 승인 흐름
- **세션 문법** — provider별 대화 ID를 기본 채팅, 스레드 ID, 부모 대체 경로에 매핑하는 방식
- **아웃바운드** — 플랫폼으로 텍스트, 미디어, poll 보내기
- **스레딩** — 답장을 스레드로 연결하는 방식
- **Session grammar** — provider별 대화 ID가 기본 채팅, 스레드 ID, 부모 대체 경로에 어떻게 매핑되는지
- **Outbound** — 플랫폼으로 텍스트, 미디어, 투표 보내기
- **Threading** — 답장이 어떻게 스레드로 연결되는지
- **Heartbeat typing** — heartbeat 전달 대상에 대한 선택적 typing/busy 신호
코어는 공통 메시지 도구, prompt 연결, 바깥쪽 세션 키 형태,
일반적인 `:thread:` bookkeeping, dispatch를 소유합니다.
코어는 공유 메시지 도구, 프롬프트 연결, 바깥쪽 세션 키 형태, 일반적인 `:thread:` 기록 관리, 그리고 디스패치를 담당합니다.
채널이 미디어 소스를 담는 message-tool 파라미터를 추가한다면, 해당
파라미터 이름을 `describeMessageTool(...).mediaSourceParams`를 통해 노출하세요.
코어는 sandbox 경로 정규화와 아웃바운드 미디어 액세스
정책을 위해 이 명시적 목록을 사용하므로, Plugin은 provider별
avatar, attachment, cover-image 파라미터에 대해 공유 코어 특수 처리가 필요하지 않습니다.
채널이 인바운드 답장 외부에서 typing indicator를 지원한다면, 채널 Plugin에 `heartbeat.sendTyping(...)`을 노출하세요. 코어는 heartbeat 모델 실행이 시작되기 전에 확인된 heartbeat 전달 대상과 함께 이를 호출하고, 공유 typing keepalive/cleanup 수명주기를 사용합니다. 플랫폼에 명시적인 중지 신호가 필요하다면 `heartbeat.clearTyping(...)`도 추가하세요.
채널이 미디어 소스를 전달하는 message-tool 파라미터를 추가한다면, 해당 파라미터 이름을 `describeMessageTool(...).mediaSourceParams`를 통해 노출하세요. 코어는 이 명시적 목록을 sandbox 경로 정규화와 아웃바운드 미디어 접근 정책에 사용하므로, Plugin에 provider별 avatar, attachment, cover-image 파라미터를 위한 공유 코어 특수 처리가 필요하지 않습니다.
가능하면
`{ "set-profile": ["avatarUrl", "avatarPath"] }`처럼 action 키 기반 맵을 반환하여,
관련 없는 action이 다른 action의 미디어 인수를 상속하지 않도록 하세요. 평면 배열도
의도적으로 모든 노출 action에서 공유되는 파라미터에는 여전히 사용할 수 있습니다.
`{ "set-profile": ["avatarUrl", "avatarPath"] }`
처럼 action 키 기반 맵을 반환하여 관련 없는 action이 다른 action의 미디어 인자를 상속하지 않도록 하세요. 모든 노출된 action에서 의도적으로 공유되는 파라미터라면 flat array도 여전히 사용할 수 있습니다.
플랫폼이 대화 ID 안에 추가 scope를 저장한다면, 해당 파싱은
`messaging.resolveSessionConversation(...)`을 통해 Plugin 내부에 유지하세요. 이것이
`rawId`를 기본 대화 ID, 선택적 스레드
ID, 명시적 `baseConversationId`, 그리고 `parentConversationCandidates`에 매핑하는
정식 훅입니다.
`parentConversationCandidates`를 반환할 때는,
가장 좁은 부모에서 가장 넓은/기본 대화 순으로 정렬해 유지하세요.
플랫폼이 대화 ID 내부에 추가 범위를 저장한다면, 그 파싱은 Plugin 안에서 `messaging.resolveSessionConversation(...)`으로 처리하세요. 이는 `rawId`를 기본 대화 ID, 선택적 스레드 ID, 명시적 `baseConversationId`, 그리고 모든 `parentConversationCandidates`에 매핑하기 위한 표준 hook입니다.
`parentConversationCandidates`를 반환할 때는 가장 좁은 부모부터 가장 넓은/기본 대화 순서로 정렬하세요.
채널 레지스트리가 부팅되기 전에 동일한 파싱이 필요한 번들 Plugin은
일치하는
`resolveSessionConversation(...)` export가 있는 최상위 `session-key-api.ts` 파일도 노출할 수 있습니다.
코어는 런타임 Plugin 레지스트리를 아직 사용할 수 없을 때만
이 bootstrap-safe 표면을 사용합니다.
채널 레지스트리가 부팅되기 전에 동일한 파싱이 필요한 번들 Plugin은 일치하는 `resolveSessionConversation(...)` export가 있는 최상위 `session-key-api.ts` 파일도 노출할 수 있습니다. 코어는 런타임 Plugin 레지스트리를 아직 사용할 수 없을 때만 이 bootstrap-safe 표면을 사용합니다.
`messaging.resolveParentConversationCandidates(...)`
Plugin이 일반/raw ID 위에 부모 대체 경로만 필요로 하는 경우를 위한 레거시 호환성 대체 수단으로
여전히 사용할 수 있습니다. 두 훅이 모두 존재하면 코어는
먼저 `resolveSessionConversation(...).parentConversationCandidates`를 사용하고,
정식 훅이 이를 생략한 경우에만 `resolveParentConversationCandidates(...)`
대체합니다.
`messaging.resolveParentConversationCandidates(...)`는 Plugin이 generic/raw ID 위에 부모 대체 경로만 필요로 하는 경우를 위한 레거시 호환성 대체 수단으로 계속 사용할 수 있습니다. 두 hook이 모두 존재하면, 코어는 먼저
`resolveSessionConversation(...).parentConversationCandidates`를 사용하고, 표준 hook이 이를 생략한 경우에만 `resolveParentConversationCandidates(...)`로 대체합니다.
## 승인 채널 기능
## 승인과 채널 기능
대부분의 채널 Plugin 승인 전용 코드가 필요하지 않습니다.
대부분의 채널 Plugin에는 승인 전용 코드가 필요하지 않습니다.
- 코어는 동일 채팅 `/approve`, 공통 승인 버튼 payload, 일반적인 대체 전송을 소유합니다.
- 채널에 승인 전용 동작이 필요할 때는 채널 Plugin에 하나의 `approvalCapability` 객체를 두는 방식을 선하세요.
- `ChannelPlugin.approvals`는 제거되었습니다. 승인 전송/기본 동작/렌더링/인증 관련 사실은 `approvalCapability`에 두세요.
- `plugin.auth`는 login/logout 전용이며, 코어는 더 이상 그 객체에서 승인 인증 훅을 읽지 않습니다.
- `approvalCapability.authorizeActorAction``approvalCapability.getActionAvailabilityState`가 정식 승인 인증 seam입니다.
- 코어는 동일 채팅 `/approve`, 공유 승인 버튼 payload, 일반적인 대체 전달을 담당합니다.
- 채널에 승인 전용 동작이 필요할 때는 채널 Plugin에 `approvalCapability` 객체 하나를 두는 방식을 선하세요.
- `ChannelPlugin.approvals`는 제거되었습니다. 승인 전달/네이티브/렌더링/인증 관련 정보는 `approvalCapability`에 넣으세요.
- `plugin.auth`는 login/logout 전용입니다. 코어는 더 이상 그 객체에서 승인 인증 hook을 읽지 않습니다.
- `approvalCapability.authorizeActorAction``approvalCapability.getActionAvailabilityState`가 표준 승인 인증 seam입니다.
- 동일 채팅 승인 인증 가용성에는 `approvalCapability.getActionAvailabilityState`를 사용하세요.
- 채널이 기본 exec 승인을 노출한다면, 동일 채팅 승인 인증과 시작 표면/기본 클라이언트 상태가 다를 때 `approvalCapability.getExecInitiatingSurfaceState`를 사용하세요. 코어는 이 exec 전용 훅을 사용해 `enabled``disabled`를 구분하고, 시작 채널이 기본 exec 승인을 지원하는지 판단하며, 기본 클라이언트 대체 안내에 해당 채널을 포함합니다. `createApproverRestrictedNativeApprovalCapability(...)`는 일반적인 경우 이를 채워 줍니다.
- 중복된 로컬 승인 프롬프트 숨김이나 전송 전 타이핑 표시 같은 채널별 payload 수명주기 동작에는 `outbound.shouldSuppressLocalPayloadPrompt` 또는 `outbound.beforeDeliverPayload`를 사용하세요.
- `approvalCapability.delivery`는 기본 승인 라우팅 또는 대체 억제에만 사용하세요.
- 채널 소유 기본 승인 관련 사실에는 `approvalCapability.nativeRuntime`을 사용하세요. 핫 채널 엔트리포인트에서는 `createLazyChannelApprovalNativeRuntimeAdapter(...)`로 이를 지연 로드 상태로 유지하세요. 이 어댑터는 필요 시 런타임 모듈을 import하면서도 코어가 승인 수명주기를 조립할 수 있게 해 줍니다.
- 채널이 공통 렌더러 대신 정말로 사용자 지정 승인 payload가 필요한 경우에`approvalCapability.render`를 사용하세요.
- 채널이 비활성화 경로 답장에서 기본 exec 승인을 활성화하는 데 필요한 정확한 config 노브를 설명하려면 `approvalCapability.describeExecApprovalSetup`을 사용하세요. 이 훅은 `{ channel, channelLabel, accountId }`를 받습니다. 이름이 지정된 계정 채널은 최상위 기본값 대신 `channels.<channel>.accounts.<id>.execApprovals.*` 같은 계정 범위 경로를 렌더링해야 합니다.
- 채널이 기존 config에서 안정적인 소유자 유사 DM identity를 추론할 수 있다면, 승인 전용 코어 로직을 추가하지 말고 `openclaw/plugin-sdk/approval-runtime``createResolvedApproverActionAuthAdapter`를 사용해 동일 채팅 `/approve`를 제한하세요.
- 채널에 기본 승인 전송이 필요하다면, 채널 코드는 대상 정규화와 전송/표시 관련 사실에 집중하세요. `openclaw/plugin-sdk/approval-runtime``createChannelExecApprovalProfile`, `createChannelNativeOriginTargetResolver`, `createChannelApproverDmTargetResolver`, `createApproverRestrictedNativeApprovalCapability`를 사용하세요. 채널별 사실은 `approvalCapability.nativeRuntime` 뒤에 두고, 가능하면 `createChannelApprovalNativeRuntimeAdapter(...)` 또는 `createLazyChannelApprovalNativeRuntimeAdapter(...)`사용해 코어가 핸들러를 조립하고 요청 필터링, 라우팅, dedupe, 만료, Gateway 구독, 다른 곳으로 라우팅됨 알림을 소유하게 하세요. `nativeRuntime`은 몇 개의 더 작은 seam으로 나뉩니다:
- 채널이 네이티브 exec 승인을 노출한다면, 시작 표면/네이티브 클라이언트 상태가 동일 채팅 승인 인증과 다를 때 `approvalCapability.getExecInitiatingSurfaceState`를 사용하세요. 코어는 이 exec 전용 hook을 사용해 `enabled``disabled`를 구분하고, 시작 채널이 네이티브 exec 승인을 지원하는지 판단하며, 네이티브 클라이언트 대체 안내에 해당 채널을 포함합니다. `createApproverRestrictedNativeApprovalCapability(...)`는 일반적인 경우 이를 채워줍니다.
- 중복 로컬 승인 프롬프트 숨기기 또는 전달 전 typing indicator 보내기 같은 채널 전용 payload 수명주기 동작에는 `outbound.shouldSuppressLocalPayloadPrompt` 또는 `outbound.beforeDeliverPayload`를 사용하세요.
- 네이티브 승인 라우팅 또는 대체 전달 억제에만 `approvalCapability.delivery` 사용하세요.
- 채널 소유의 네이티브 승인 관련 정보에는 `approvalCapability.nativeRuntime`을 사용하세요. 핫 채널 진입점에서는 `createLazyChannelApprovalNativeRuntimeAdapter(...)`로 이를 lazy하게 유지하세요. 그러면 런타임 모듈을 필요 시 import하면서도 코어가 승인 수명주기를 조합할 수 있습니다.
- 채널에 공유 렌더러 대신 진짜로 커스텀 승인 payload가 필요할 때`approvalCapability.render`를 사용하세요.
- 채널이 비활성 경로 응답에서 네이티브 exec 승인을 활성화하는 데 필요한 정확한 config knob을 설명하고 싶다면 `approvalCapability.describeExecApprovalSetup`을 사용하세요. 이 hook은 `{ channel, channelLabel, accountId }`를 받습니다. 이름 있는 계정 채널은 최상위 기본값 대신 `channels.<channel>.accounts.<id>.execApprovals.*` 같은 계정 범위 경로를 렌더링해야 합니다.
- 채널이 기존 config에서 안정적인 owner 유사 DM 신원을 추론할 수 있다면, 승인 전용 코어 로직을 추가하지 않고 동일 채팅 `/approve`를 제한하기 위해 `openclaw/plugin-sdk/approval-runtime``createResolvedApproverActionAuthAdapter`를 사용하세요.
- 채널에 네이티브 승인 전달이 필요하다면, 채널 코드는 대상 정규화와 전송/표시 관련 사실에 집중하도록 유지하세요. `openclaw/plugin-sdk/approval-runtime``createChannelExecApprovalProfile`, `createChannelNativeOriginTargetResolver`, `createChannelApproverDmTargetResolver`, `createApproverRestrictedNativeApprovalCapability`를 사용하세요. 채널별 사실은 `approvalCapability.nativeRuntime` 뒤에 두고, 이상적으로는 `createChannelApprovalNativeRuntimeAdapter(...)` 또는 `createLazyChannelApprovalNativeRuntimeAdapter(...)`통해 노출하세요. 그러면 코어가 핸들러를 조합하고 요청 필터링, 라우팅, 중복 제거, 만료, gateway 구독, 다른 곳으로 라우팅되었음 알림을 담당할 수 있습니다. `nativeRuntime`은 몇 개의 더 작은 seam으로 나뉩니다.
- `availability` — 계정이 구성되었는지, 요청을 처리해야 하는지 여부
- `presentation` — 공통 승인 view model을 pending/resolved/expired 기본 payload 또는 최종 action으로 매핑
- `transport` — 대상 준비 및 기본 승인 메시지 send/update/delete
- `interactions` — 기본 버튼 또는 반응을 위한 선택적 bind/unbind/clear-action 훅
- `observe` — 선택적 전송 진단 훅
- 채널에 client, token, Bolt app, Webhook receiver 같은 런타임 소유 객체가 필요하다면 `openclaw/plugin-sdk/channel-runtime-context`를 통해 등록하세요. 일반적인 runtime-context 레지스트리를 사용하면 코어가 승인 전용 wrapper glue를 추가하지 않고도 채널 시작 상태에서 capability 기반 핸들러를 bootstrap할 수 있습니다.
- capability 기반 seam이 아직 충분히 표현력이 없을 때만 더 저수준인 `createChannelApprovalHandler` 또는 `createChannelNativeApprovalRuntime`을 사용하세요.
- 기본 승인 채널은 `accountId``approvalKind`를 모두 이 헬퍼들을 통해 라우팅해야 합니다. `accountId`는 다중 계정 승인 정책을 올바른 bot 계정 범위로 유지하고, `approvalKind`는 코어에 하드코딩된 분기 없이 채널에서 exec 대 plugin 승인 동작을 사용할 수 있게 합니다.
- 이제 코어가 승인 재라우팅 알림도 소유합니다. 채널 Plugin은 `createChannelNativeApprovalRuntime`에서 자체적으로 "승인이 DM / 다른 채널로 이동했다" 같은 후속 메시지를 보내지 말고, 공통 승인 capability 헬퍼를 통해 정확한 origin + 승인자 DM 라우팅을 노출한 뒤, 코어가 실제 전송 결과를 집계하여 시작 채팅으로 알림을 게시하게 하세요.
- 전달된 승인 ID 종류를 끝까지 보존하세요. 기본 클라이언트는
채널 로컬 상태를 바탕으로 exec 대 plugin 승인 라우팅을
추측하거나 다시 쓰면 안 됩니다.
- 서로 다른 승인 종류는 의도적으로 서로 다른 기본 표면을 노출할 수 있습니다.
현재 번들 예시:
- Slack은 exec 및 plugin ID 모두에 대해 기본 승인 라우팅을 유지합니다.
- Matrix는 exec 및 plugin 승인 모두에 대해 동일한 기본 DM/채널 라우팅과 반응 UX를 유지하면서도, 승인 종류별로 인증은 다르게 둘 수 있습니다.
- `createApproverRestrictedNativeApprovalAdapter`는 여전히 호환성 wrapper로 존재하지만, 새 코드는 capability builder를 우선 사용하고 Plugin에 `approvalCapability`를 노출해야 합니다.
- `presentation` — 공유 승인 뷰 모델을 대기 중/해결됨/만료됨 네이티브 payload 또는 최종 action으로 매핑
- `transport` — 대상 준비 및 네이티브 승인 메시지 전송/업데이트/삭제
- `interactions` — 네이티브 버튼 또는 reaction을 위한 선택적 bind/unbind/clear-action hook
- `observe` — 선택적 전달 진단 hook
- 채널에 client, token, Bolt app, Webhook receiver 같은 런타임 소유 객체가 필요하다면, `openclaw/plugin-sdk/channel-runtime-context`를 통해 등록하세요. 일반적인 runtime-context 레지스트리는 코어가 승인 전용 wrapper glue를 추가하지 않고도 채널 시작 상태에서 capability 기반 핸들러를 bootstrap할 수 있게 해줍니다.
- capability 기반 seam이 아직 충분히 표현력이 없을 때만 더 저수준의 `createChannelApprovalHandler` 또는 `createChannelNativeApprovalRuntime`을 사용하세요.
- 네이티브 승인 채널은 `accountId``approvalKind`를 모두 그 helper들을 통해 라우팅해야 합니다. `accountId`는 멀티 계정 승인 정책이 올바른 bot 계정 범위로 유지되도록 하고, `approvalKind`는 코어의 하드코딩된 분기 없이 채널이 exec와 Plugin 승인 동작을 사용할 수 있도록 합니다.
- 이제 코어가 승인 재라우팅 알림도 담당합니다. 채널 Plugin은 `createChannelNativeApprovalRuntime`에서 자체적인 "승인이 DM / 다른 채널로 갔습니다" 후속 메시지를 보내지 말고, 대신 공유 승인 capability helper를 통해 정확한 origin + approver-DM 라우팅을 노출하고, 시작 채팅으로 알림을 게시하기 전에 코어가 실제 전달을 집계하도록 하세요.
- 전달된 승인 ID 종류를 처음부터 끝까지 보존하세요. 네이티브 클라이언트는 채널 로컬 상태에서 exec와 Plugin 승인 라우팅을 추측하거나 다시 작성해서는 안 됩니다.
- 서로 다른 승인 종류는 의도적으로 서로 다른 네이티브 표면을 노출할 수 있습니다.
현재 번들 예시는 다음과 같습니다.
- Slack은 exec와 Plugin ID 모두에 대해 네이티브 승인 라우팅을 계속 사용할 수 있게 유지합니다.
- Matrix는 exec와 Plugin 승인 모두에 대해 동일한 네이티브 DM/채널 라우팅과 reaction UX를 유지하면서도, 승인 종류별로 auth가 달라지도록 허용합니다.
- `createApproverRestrictedNativeApprovalAdapter`는 여전히 호환성 wrapper로 존재하지만, 새 코드는 capability builder를 선호하고 Plugin에 `approvalCapability`를 노출해야 합니다.
핫 채널 엔트리포인트에서는 이 계열 전체가 아니라 한 부분만
필요할 때 더 좁은 런타임 하위 경로를 우선 사용하세요:
핫 채널 진입점의 경우, 그 계열 중 한 부분만 필요하다면 더 좁은 런타임 하위 경로를 선호하세요.
- `openclaw/plugin-sdk/approval-auth-runtime`
- `openclaw/plugin-sdk/approval-client-runtime`
@ -120,104 +100,92 @@ Plugin이 일반/raw ID 위에 부모 대체 경로만 필요로 하는 경우
- `openclaw/plugin-sdk/approval-reply-runtime`
- `openclaw/plugin-sdk/channel-runtime-context`
마찬가지로, 더 넓은 umbrella
표면이 필요하지 않을 때는 `openclaw/plugin-sdk/setup-runtime`,
마찬가지로, 더 넓은 umbrella 표면이 필요하지 않다면
`openclaw/plugin-sdk/setup-runtime`,
`openclaw/plugin-sdk/setup-adapter-runtime`,
`openclaw/plugin-sdk/reply-runtime`,
`openclaw/plugin-sdk/reply-dispatch-runtime`,
`openclaw/plugin-sdk/reply-reference`,
`openclaw/plugin-sdk/reply-chunking`우선 사용하세요.
`openclaw/plugin-sdk/reply-reference`, 그리고
`openclaw/plugin-sdk/reply-chunking`선호하세요.
설정 관련으로는 구체적으로:
설정과 관련해서는 특히 다음과 같습니다.
- `openclaw/plugin-sdk/setup-runtime`은 런타임 안전 설정 헬퍼를 다룹니다:
- `openclaw/plugin-sdk/setup-runtime`은 런타임 안전 설정 helper를 다룹니다:
import-safe setup patch adapter (`createPatchedAccountSetupAdapter`,
`createEnvPatchedAccountSetupAdapter`,
`createSetupInputPresenceValidator`), lookup-note 출력,
`promptResolvedAllowFrom`, `splitSetupEntries`, 위임된
`promptResolvedAllowFrom`, `splitSetupEntries`, 그리고 위임된
setup-proxy builder
- `openclaw/plugin-sdk/setup-adapter-runtime`
`createEnvPatchedAccountSetupAdapter`를 위한 좁은 env 인식 adapter
- `openclaw/plugin-sdk/setup-adapter-runtime``createEnvPatchedAccountSetupAdapter`를 위한 좁은 env 인식 adapter
seam입니다
- `openclaw/plugin-sdk/channel-setup`은 선택적 설치 setup
- `openclaw/plugin-sdk/channel-setup`은 선택적 설치 설정
builder와 몇 가지 setup-safe 기본 요소를 다룹니다:
`createOptionalChannelSetupSurface`, `createOptionalChannelSetupAdapter`,
채널이 env 기반 설정이나 인증을 지원하고, 일반적인 시작/config
흐름이 런타임 로드 전에 해당 env 이름을 알아야 한다면,
Plugin manifest에 `channelEnvVars`로 선언하세요. 채널 런타임 `envVars`나 로컬
상수는 운영자 대상 복사용으로만 유지하세요.
채널이 env 기반 설정 또는 auth를 지원하고, 일반적인 시작/config 흐름이 런타임이 로드되기 전에 해당 env 이름을 알아야 한다면, Plugin manifest에 `channelEnvVars`로 선언하세요. 채널 런타임 `envVars` 또는 로컬 상수는 운영자 대상 복사용으로만 유지하세요.
채널이 Plugin 런타임이 시작되기 전에 `status`, `channels list`, `channels status`, 또는
SecretRef 스캔에 나타날 수 있다면 `package.json``openclaw.setupEntry`를 추가하세요.
이 엔트리포인트는 읽기 전용 명령 경로에서 안전하게 import될 수 있어야 하며,
채널 메타데이터, setup-safe config adapter, status
adapter, 채널 secret target 메타데이터를 반환해야 합니다. setup 엔트리에서는
client, listener, transport runtime을 시작하지 마세요.
채널이 Plugin 런타임이 시작되기 전에 `status`, `channels list`, `channels status`, 또는 SecretRef 스캔에 나타날 수 있다면, `package.json``openclaw.setupEntry`를 추가하세요. 이 진입점은 읽기 전용 명령 경로에서 안전하게 import할 수 있어야 하며, 해당 요약에 필요한 채널 메타데이터, setup-safe config adapter, status adapter, 채널 secret target 메타데이터를 반환해야 합니다. 설정 진입점에서 client, listener, transport runtime을 시작하지 마세요.
`createOptionalChannelSetupWizard`, `DEFAULT_ACCOUNT_ID`,
`createTopLevelChannelDmPolicy`, `setSetupChannelEnabled`, 그리고
`splitSetupEntries`
- 다음과 같은 더 무거운 공통 설정/config 헬퍼도 함께 필요할 때만
더 넓은 `openclaw/plugin-sdk/setup` seam을 사용하세요:
- 더 무거운 공유 설정/config helper도 함께 필요할 때만 더 넓은
`openclaw/plugin-sdk/setup` seam을 사용하세요. 예:
`moveSingleAccountChannelSectionToDefaultAccount(...)`
채널이 설정 표면에 "먼저 이 Plugin을 설치하세요"만
광고하려는 경우에는 `createOptionalChannelSetupSurface(...)`를 우선 사용하세요.
생성된 adapter/wizard는 config 쓰기와 finalize에서 fail-closed로 동작하며,
검증, finalize, docs-link 복사 전반에서 동일한 설치 필요 메시지를 재사용합니다.
채널이 설정 표면에서 단지 "먼저 이 Plugin을 설치하세요"만 안내하려는 경우라면, `createOptionalChannelSetupSurface(...)`를 선호하세요. 생성된 adapter/wizard는 config 쓰기와 마무리에서 fail closed 방식으로 동작하며, 검증, finalize, docs-link 복사 전반에서 동일한 설치 필요 메시지를 재사용합니다.
다른 핫 채널 경로에서도, 더 넓은 레거시 표면보다는 좁은 헬퍼를 우선 사용하세요:
다른 핫 채널 경로에서도 더 넓은 레거시 표면보다 좁은 helper를 선호하세요:
- 다중 계정 config 및
기본 계정 대체 경로에는 `openclaw/plugin-sdk/account-core`,
- 멀티 계정 config와 기본 계정 대체 경로에는
`openclaw/plugin-sdk/account-core`,
`openclaw/plugin-sdk/account-id`,
`openclaw/plugin-sdk/account-resolution`,
`openclaw/plugin-sdk/account-resolution`, 그리고
`openclaw/plugin-sdk/account-helpers`를 사용하세요
- 인바운드 route/envelope 및
record-and-dispatch 연결에는 `openclaw/plugin-sdk/inbound-envelope`
- 인바운드 route/envelope와
record-and-dispatch 연결에는
`openclaw/plugin-sdk/inbound-envelope`
`openclaw/plugin-sdk/inbound-reply-dispatch`를 사용하세요
- 대상 파싱/매칭에는 `openclaw/plugin-sdk/messaging-targets`를 사용하세요
- 미디어 로딩과 아웃바운드
identity/send delegate 및 payload planning에는 `openclaw/plugin-sdk/outbound-media`
- 미디어 로딩과 아웃바운드 신원/전송 delegate 및 payload 계획에는
`openclaw/plugin-sdk/outbound-media`
`openclaw/plugin-sdk/outbound-runtime`을 사용하세요
- 명시적 `replyToId`/`threadId`를 유지하거나,
기본 세션 키가 여전히 일치한 뒤 현재 `:thread:` 세션을 복구해야 하는 아웃바운드 route에는
- 아웃바운드 route가 명시적 `replyToId`/`threadId`를 보존하거나,
기본 세션 키가 여전히 일치한 뒤 현재 `:thread:` 세션을 복구해야 한다면
`openclaw/plugin-sdk/channel-core`
`buildThreadAwareOutboundSessionRoute(...)`를 사용하세요.
Provider Plugin은 플랫폼에 기본 스레드 전송 의미 체계가 있을 경우
provider Plugin은 플랫폼에 네이티브 스레드 전달 의미 체계가 있을 때
우선순위, suffix 동작, 스레드 ID 정규화를 재정의할 수 있습니다.
- 스레드 바인딩 수명주기
및 adapter 등록에는 `openclaw/plugin-sdk/thread-bindings-runtime`을 사용하세요
- 레거시 agent/media
payload 필드 레이아웃이 여전히 필요할 때만 `openclaw/plugin-sdk/agent-media-payload`를 사용하세요
- Telegram 사용자 지정 명령
정규화, 중복/충돌 검증, 대체 경로 안정 명령
- thread-binding 수명주기와 adapter 등록에는
`openclaw/plugin-sdk/thread-bindings-runtime`을 사용하세요
- 레거시 agent/media payload 필드 레이아웃이 여전히 필요할 때만
`openclaw/plugin-sdk/agent-media-payload`를 사용하세요
- Telegram 커스텀 명령 정규화, 중복/충돌 검증, 대체 경로 안정적 명령
config 계약에는 `openclaw/plugin-sdk/telegram-command-config`를 사용하세요
인증 전용 채널은 보통 기본 경로에서 멈출 수 있습니다. 코어가 승인을 처리하고 Plugin은 아웃바운드/인증 기능만 노출하면 됩니다. Matrix, Slack, Telegram, 사용자 지정 채팅 전송 계층처럼 기본 승인을 지원하는 채널은 자체 승인 수명주기를 구현하지 말고 공통 기본 헬퍼를 사용해야 합니다.
인증 전용 채널은 보통 기본 경로에서 멈출 수 있습니다. 코어가 승인을 처리하고 Plugin은 아웃바운드/인증 기능만 노출하면 됩니다. Matrix, Slack, Telegram, 커스텀 채팅 전송 같은 네이티브 승인 채널은 자체 승인 수명주기를 구현하지 말고 공유 네이티브 helper를 사용해야 합니다.
## 인바운드 멘션 정책
인바운드 멘션 처리는 두 계층으로 나누어 유지하세요:
인바운드 멘션 처리는 두 계층으로 나누어 유지하세요.
- Plugin이 소유하는 증거 수집
- 공 정책 평가
- 공 정책 평가
멘션 정책 결정에는 `openclaw/plugin-sdk/channel-mention-gating`을 사용하세요.
더 넓은 인바운드
헬퍼 barrel이 필요할 때만 `openclaw/plugin-sdk/channel-inbound`를 사용하세요.
더 넓은 인바운드 helper barrel이 필요할 때만
`openclaw/plugin-sdk/channel-inbound`를 사용하세요.
Plugin 로컬 로직에 잘 맞는 항목:
Plugin 로컬 로직에 잘 맞는 경우:
- bot에 대한 답장 감지
- bot에 대한 reply 감지
- bot 인용 감지
- 스레드 참여 여부 확인
- 서비스/시스템 메시지 제외
- bot 참여를 증명하는 데 필요한 플랫폼 기본 캐시
- bot 참여를 입증하는 데 필요한 플랫폼 네이티브 캐시
통 헬퍼에 잘 맞는 항목:
유 helper에 잘 맞는 경우:
- `requireMention`
- 명시적 멘션 결과
@ -228,7 +196,7 @@ Plugin 로컬 로직에 잘 맞는 항목:
권장 흐름:
1. 로컬 멘션 사실을 계산합니다.
2. 해당 사실을 `resolveInboundMentionDecision({ facts, policy })`에 전달합니다.
2. 사실을 `resolveInboundMentionDecision({ facts, policy })`에 전달합니다.
3. 인바운드 게이트에서 `decision.effectiveWasMentioned`, `decision.shouldBypassMention`, `decision.shouldSkip`를 사용합니다.
```typescript
@ -268,8 +236,8 @@ const decision = resolveInboundMentionDecision({
if (decision.shouldSkip) return;
```
`api.runtime.channel.mentions`이미 런타임 주입에 의존하는
번들 채널 Plugin을 위해 동일한 공통 멘션 헬퍼를 노출합니다:
`api.runtime.channel.mentions`는 런타임 주입에 이미 의존하는
번들 채널 Plugin을 위해 동일한 공유 멘션 helper를 노출합니다.
- `buildMentionRegexes`
- `matchesMentionPatterns`
@ -279,21 +247,22 @@ if (decision.shouldSkip) return;
`implicitMentionKindWhen`
`resolveInboundMentionDecision`만 필요하다면,
관련 없는 인바운드
런타임 헬퍼를 로드하지 않도록 `openclaw/plugin-sdk/channel-mention-gating`에서 import하세요.
관련 없는 인바운드 런타임 helper까지 로드하지 않도록
`openclaw/plugin-sdk/channel-mention-gating`에서 import하세요.
이전 `resolveMentionGating*` 헬퍼
`openclaw/plugin-sdk/channel-inbound`에 호환성 export로만 남아 있습니다. 새 코드는
`resolveInboundMentionDecision({ facts, policy })`를 사용해야 합니다.
이전`resolveMentionGating*` helper
`openclaw/plugin-sdk/channel-inbound`에 호환성 export로만 남아 있습니다.
새 코드는 `resolveInboundMentionDecision({ facts, policy })`를 사용해야 합니다.
## 단계별 안내
<Steps>
<a id="step-1-package-and-manifest"></a>
<Step title="패키지 manifest">
<Step title="패키지 manifest">
표준 Plugin 파일을 만드세요. `package.json``channel` 필드는
이 패키지가 채널 Plugin임을 나타냅니다. 전체 패키지 메타데이터 표면은
[Plugin 설정 및 config](/ko/plugins/sdk-setup#openclaw-channel)를 참고하세요:
이것이 채널 Plugin임을 나타냅니다. 전체 패키지 메타데이터 표면은
[Plugin 설정 및 Config](/ko/plugins/sdk-setup#openclaw-channel)를
참고하세요.
<CodeGroup>
```json package.json
@ -342,9 +311,8 @@ if (decision.shouldSkip) return;
</Step>
<Step title="채널 Plugin 객체 구축">
`ChannelPlugin` 인터페이스에는 많은 선택적 adapter 표면이 있습니다. 먼저
최소 구성인 `id``setup`부터 시작하고, 필요에 따라 adapter를 추가하세요.
<Step title="채널 Plugin 객체 빌드하기">
`ChannelPlugin` 인터페이스에는 선택적인 adapter 표면이 많이 있습니다. 최소 구성인 `id``setup`부터 시작해서 필요할 때 adapter를 추가하세요.
`src/channel.ts`를 만드세요:
@ -439,23 +407,23 @@ if (decision.shouldSkip) return;
});
```
<Accordion title="createChatChannelPlugin이 제공하는 기능">
저수준 adapter 인터페이스를 직접 구현하는 대신
선언형 옵션을 전달하면 builder가 이를 조합합니다:
<Accordion title="createChatChannelPlugin이 대신 해주는 일">
저수준 adapter 인터페이스를 수동으로 구현하는 대신,
선언적 옵션을 전달하면 builder가 이를 조합합니다.
| 옵션 | 연결되는 항목 |
| Option | 연결되는 항목 |
| --- | --- |
| `security.dm` | config 필드 기반 범위 지정 DM 보안 resolver |
| `pairing.text` | 코드 교환이 있는 텍스트 기반 DM pairing 흐름 |
| `threading` | reply-to-mode resolver(고정, 계정 범위, 또는 사용자 지정) |
| `outbound.attachedResults` | 결과 메타데이터(message ID)를 반환하는 send 함수 |
| `security.dm` | config 필드에서 범위가 지정된 DM 보안 resolver |
| `pairing.text` | 코드 교환이 있는 텍스트 기반 DM 페어링 흐름 |
| `threading` | reply-to-mode resolver(고정, 계정 범위, 또는 커스텀) |
| `outbound.attachedResults` | 결과 메타데이터(메시지 ID)를 반환하는 send 함수 |
완전한 제어가 필요하면 선언형 옵션 대신 원시 adapter 객체를 전달할 수도 있습니다.
완전한 제어가 필요하다면 선언적 옵션 대신 원시 adapter 객체를 전달할 수도 있습니다.
</Accordion>
</Step>
<Step title="엔트리포인트 연결">
<Step title="진입점 연결하기">
`index.ts`를 만드세요:
```typescript index.ts
@ -491,21 +459,21 @@ if (decision.shouldSkip) return;
});
```
채널 소유 CLI descriptor는 `registerCliMetadata(...)`에 두세요. 이렇게 하면 OpenClaw가
전체 채널 런타임을 활성화하지 않고도 루트 도움말에 이를 표시할 수 있으며,
일반적인 전체 로드에서는 실제 명령
등록을 위해 동일한 descriptor를 계속 가져올 수 있습니다. `registerFull(...)`은 런타임 전용 작업에 유지하세요.
`registerFull(...)`Gateway RPC 메서드를 등록한다면,
Plugin 전용 접두사를 사용하세요. 코어 관리자 네임스페이스(`config.*`,
`exec.approvals.*`, `wizard.*`, `update.*`)는 예약되어 있으며 항상
`operator.admin`으로 확인됩니다.
`defineChannelPluginEntry`는 등록 모드 분기를 자동으로 처리합니다.
전체 옵션은 [엔트리포인트](/ko/plugins/sdk-entrypoints#definechannelpluginentry)를 참고하세요.
채널 소유하는 CLI descriptor는 `registerCliMetadata(...)`에 두어,
OpenClaw가 전체 채널 런타임을 활성화하지 않고도 루트 도움말에 이를 표시할 수 있게 하세요.
일반적인 전체 로드에서도 실제 명령 등록을 위해 동일한 descriptor를 계속 가져옵니다.
`registerFull(...)`은 런타임 전용 작업에 유지하세요.
`registerFull(...)`gateway RPC 메서드를 등록한다면,
Plugin 전용 prefix를 사용하세요. 코어 관리 네임스페이스
(`config.*`, `exec.approvals.*`, `wizard.*`, `update.*`)는 예약되어 있으며
항상 `operator.admin`으로 확인됩니다.
`defineChannelPluginEntry`는 등록 모드 분리를 자동으로 처리합니다. 모든
옵션은 [진입점](/ko/plugins/sdk-entrypoints#definechannelpluginentry)을 참고하세요.
</Step>
<Step title="setup 엔트리 추가">
온보딩 중 경량 로드를 위해 `setup-entry.ts`를 만드세요:
<Step title="setup entry 추가하기">
온보딩 중 경량 로딩을 위해 `setup-entry.ts`를 만드세요:
```typescript setup-entry.ts
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
@ -514,34 +482,33 @@ if (decision.shouldSkip) return;
export default defineSetupPluginEntry(acmeChatPlugin);
```
채널이 비활성화되었거나 구성되지 않았을 때 OpenClaw는
전체 엔트리 대신 이를 로드합니다. 설정 흐름 중 무거운 런타임 코드를 불러오는 것을 방지합니다.
자세한 내용은 [설정 및 config](/ko/plugins/sdk-setup#setup-entry)를 참고하세요.
OpenClaw는 채널이 비활성화되었거나 설정되지 않았을 때 전체 진입점 대신 이것을 로드합니다.
이렇게 하면 설정 흐름 중에 무거운 런타임 코드를 끌어오지 않게 됩니다.
자세한 내용은 [설정 및 Config](/ko/plugins/sdk-setup#setup-entry)를 참고하세요.
setup-safe export를 sidecar
모듈로 분리하는 번들 workspace 채널은,
명시적인 setup 시점 런타임 setter도 필요할 경우
setup-safe export를 사이드카 모듈로 분리하는 번들 워크스페이스 채널은
`openclaw/plugin-sdk/channel-entry-contract`
`defineBundledChannelSetupEntry(...)`를 사용할 수 있습니다.
이는 설정 시점의 명시적 runtime setter도 함께 필요할 때 유용합니다.
</Step>
<Step title="인바운드 메시지 처리">
Plugin은 플랫폼에서 메시지를 수신해 이를
OpenClaw로 전달해야 합니다. 일반적인 패턴은 요청을 검증하고
채널의 인바운드 핸들러를 통해 dispatch하는 Webhook입니다:
<Step title="인바운드 메시지 처리하기">
Plugin은 플랫폼에서 메시지를 받아 OpenClaw로 전달해야 합니다.
일반적인 패턴은 요청을 검증하고 채널의 인바운드 핸들러를 통해
디스패치하는 Webhook입니다:
```typescript
registerFull(api) {
api.registerHttpRoute({
path: "/acme-chat/webhook",
auth: "plugin", // plugin-managed auth (verify signatures yourself)
auth: "plugin", // plugin-managed auth (서명 검증은 직접 수행)
handler: async (req, res) => {
const event = parseWebhookPayload(req);
// Your inbound handler dispatches the message to OpenClaw.
// The exact wiring depends on your platform SDK
// see a real example in the bundled Microsoft Teams or Google Chat plugin package.
// 인바운드 핸들러가 메시지를 OpenClaw로 디스패치합니다.
// 정확한 연결 방식은 플랫폼 SDK에 따라 다릅니다
// 실제 예시는 번들 Microsoft Teams 또는 Google Chat Plugin 패키지를 참고하세요.
await handleAcmeChatInbound(api, event);
res.statusCode = 200;
@ -553,7 +520,7 @@ if (decision.shouldSkip) return;
```
<Note>
인바운드 메시지 처리는 채널별로 다릅니다. 각 채널 Plugin은
인바운드 메시지 처리는 채널마다 다릅니다. 각 채널 Plugin은
자체 인바운드 파이프라인을 소유합니다. 실제 패턴은 번들 채널 Plugin
(예: Microsoft Teams 또는 Google Chat Plugin 패키지)을 참고하세요.
</Note>
@ -562,14 +529,14 @@ if (decision.shouldSkip) return;
<a id="step-6-test"></a>
<Step title="테스트">
`src/channel.test.ts`colocated 테스트를 작성하세요:
`src/channel.test.ts`에 테스트를 함께 작성하세요:
```typescript src/channel.test.ts
import { describe, it, expect } from "vitest";
import { acmeChatPlugin } from "./channel.js";
describe("acme-chat plugin", () => {
it("resolves account from config", () => {
it("config에서 계정을 확인한다", () => {
const cfg = {
channels: {
"acme-chat": { token: "test-token", allowFrom: ["user1"] },
@ -579,7 +546,7 @@ if (decision.shouldSkip) return;
expect(account.token).toBe("test-token");
});
it("inspects account without materializing secrets", () => {
it("보안 정보를 구체화하지 않고 계정을 검사한다", () => {
const cfg = {
channels: { "acme-chat": { token: "test-token" } },
} as any;
@ -588,7 +555,7 @@ if (decision.shouldSkip) return;
expect(result.tokenStatus).toBe("available");
});
it("reports missing config", () => {
it("누락된 config를 보고한다", () => {
const cfg = { channels: {} } as any;
const result = acmeChatPlugin.setup!.inspectAccount!(cfg, undefined);
expect(result.configured).toBe(false);
@ -600,7 +567,7 @@ if (decision.shouldSkip) return;
pnpm test -- <bundled-plugin-root>/acme-chat/
```
통 테스트 헬퍼는 [테스트](/ko/plugins/sdk-testing)를 참고하세요.
유 테스트 helper는 [테스트](/ko/plugins/sdk-testing)를 참고하세요.
</Step>
</Steps>
@ -609,8 +576,8 @@ if (decision.shouldSkip) return;
```
<bundled-plugin-root>/acme-chat/
├── package.json # openclaw.channel metadata
├── openclaw.plugin.json # config schema가 포함된 Manifest
├── package.json # openclaw.channel 메타데이터
├── openclaw.plugin.json # config 스키마가 포함된 Manifest
├── index.ts # defineChannelPluginEntry
├── setup-entry.ts # defineSetupPluginEntry
├── api.ts # 공개 export (선택 사항)
@ -618,7 +585,7 @@ if (decision.shouldSkip) return;
└── src/
├── channel.ts # createChatChannelPlugin을 통한 ChannelPlugin
├── channel.test.ts # 테스트
├── client.ts # 플랫폼 API client
├── client.ts # 플랫폼 API 클라이언트
└── runtime.ts # 런타임 저장소(필요한 경우)
```
@ -626,29 +593,29 @@ if (decision.shouldSkip) return;
<CardGroup cols={2}>
<Card title="스레딩 옵션" icon="git-branch" href="/ko/plugins/sdk-entrypoints#registration-mode">
고정, 계정 범위, 또는 사용자 지정 답장 모드
고정, 계정 범위, 또는 커스텀 reply 모드
</Card>
<Card title="메시지 도구 통합" icon="puzzle" href="/ko/plugins/architecture#channel-plugins-and-the-shared-message-tool">
describeMessageTool action 검색
describeMessageTool action 검색
</Card>
<Card title="대상 확인" icon="crosshair" href="/ko/plugins/architecture#channel-target-resolution">
inferTargetChatType, looksLikeId, resolveTarget
</Card>
<Card title="런타임 헬퍼" icon="settings" href="/ko/plugins/sdk-runtime">
api.runtime를 통한 TTS, STT, 미디어, 하위 에이전트
<Card title="런타임 helper" icon="settings" href="/ko/plugins/sdk-runtime">
api.runtime를 통한 TTS, STT, 미디어, 하위 agent
</Card>
</CardGroup>
<Note>
일부 번들 헬퍼 seam은 번들 Plugin 유지 관리
호환성을 위해 여전히 존재합니다. 하지만 새 채널 Plugin에 권장되는 패턴은 아닙니다.
해당 번들 Plugin 계열을 직접 유지 관리하는 경우가 아니라면,
일반 SDK 표면의 공통 channel/setup/reply/runtime 하위 경로를 우선 사용하세요.
일부 번들 helper seam은 번들 Plugin 유지보수
호환성을 위해 여전히 존재합니다. 이는 새 채널 Plugin에 권장되는 패턴이 아닙니다.
해당 번들 Plugin 계열을 직접 유지보수하는 경우가 아니라면,
공통 SDK 표면의 일반적인 channel/setup/reply/runtime 하위 경로를 우선 사용하세요.
</Note>
## 다음 단계
- [Provider Plugin](/ko/plugins/sdk-provider-plugins) — Plugin이 모델도 제공하는 경우
- [SDK 개요](/ko/plugins/sdk-overview) — 전체 하위 경로 import 참
- [SDK 테스트](/ko/plugins/sdk-testing) — 테스트 유틸리티 계약 테스트
- [Plugin Manifest](/ko/plugins/manifest) — 전체 manifest schema
- [Provider Plugins](/ko/plugins/sdk-provider-plugins) — Plugin이 모델도 제공하는 경우
- [SDK 개요](/ko/plugins/sdk-overview) — 전체 하위 경로 import 참고 자료
- [SDK 테스트](/ko/plugins/sdk-testing) — 테스트 유틸리티 계약 테스트
- [Plugin Manifest](/ko/plugins/manifest) — 전체 manifest 스키마

View File

@ -1,25 +1,25 @@
---
read_when:
- Ollama를 통해 클라우드 또는 로컬 모델로 OpenClaw를 실행하려고 합니다
- Ollama 설정 및 구성 안내가 필요합니다
- 이미지 이해를 위한 Ollama 비전 모델을 원합니다
- Ollama를 통해 클라우드 또는 로컬 모델로 OpenClaw를 실행하려고 합니다.
- Ollama 설정 및 구성 안내가 필요합니다.
- 이미지 이해를 위해 Ollama 비전 모델을 사용하려고 합니다.
summary: Ollama로 OpenClaw 실행하기(클라우드 및 로컬 모델)
title: Ollama
x-i18n:
generated_at: "2026-04-22T04:26:57Z"
generated_at: "2026-04-22T06:00:54Z"
model: gpt-5.4
provider: openai
source_hash: 32623b6523f22930a5987fb22d2074f1e9bb274cc01ae1ad1837825cc04ec179
source_hash: 704beed3bf988d6c2ad50b2a1533f6dcef655e44b34f23104827d2acb71b8655
source_path: providers/ollama.md
workflow: 15
---
# Ollama
OpenClaw는 호스팅된 클라우드 모델과 로컬/자체 호스팅 Ollama 서버를 위해 Ollama의 네이티브 API(`/api/chat`)와 통합됩니다. Ollama는 세 가지 모드로 사용할 수 있습니다. 도달 가능한 Ollama 호스트를 통한 `Cloud + Local`, `https://ollama.com`에 대한 `Cloud only`, 도달 가능한 Ollama 호스트에 대한 `Local only`입니다.
OpenClaw는 Ollama의 네이티브 API(`/api/chat`)와 통합되어, 호스팅된 클라우드 모델과 로컬/자체 호스팅 Ollama 서버를 모두 사용할 수 있습니다. Ollama는 세 가지 모드로 사용할 수 있습니다: 연결 가능한 Ollama 호스트를 통한 `Cloud + Local`, `https://ollama.com`에 대한 `Cloud only`, 또는 연결 가능한 Ollama 호스트에 대한 `Local only`.
<Warning>
**원격 Ollama 사용자**: OpenClaw에서 `/v1` OpenAI 호환 URL(`http://host:11434/v1`)을 사용하지 마세요. 이렇게 하면 tool calling이 깨지고 모델이 원시 도구 JSON을 일반 텍스트로 출력할 수 있습니다. 대신 네이티브 Ollama API URL을 사용하세요: `baseUrl: "http://host:11434"` (`/v1` 없음).
**원격 Ollama 사용자**: OpenClaw에서 `/v1` OpenAI 호환 URL(`http://host:11434/v1`)을 사용하지 마세요. 이렇게 하면 도구 호출이 깨지고 모델이 원시 도구 JSON을 일반 텍스트로 출력할 수 있습니다. 대신 네이티브 Ollama API URL을 사용하세요: `baseUrl: "http://host:11434"` (`/v1` 없음).
</Warning>
## 시작하기
@ -28,7 +28,7 @@ OpenClaw는 호스팅된 클라우드 모델과 로컬/자체 호스팅 Ollama
<Tabs>
<Tab title="온보딩(권장)">
**가장 적합한 경우:** 작동하는 Ollama 클라우드 또는 로컬 설정까지 가는 가장 빠른 경로.
**적합한 경우:** 작동하는 Ollama 클라우드 또는 로컬 설정으로 가장 빠르게 시작하고 싶을 때.
<Steps>
<Step title="온보딩 실행">
@ -36,7 +36,7 @@ OpenClaw는 호스팅된 클라우드 모델과 로컬/자체 호스팅 Ollama
openclaw onboard
```
프로바이더 목록에서 **Ollama**를 선택하세요.
제공자 목록에서 **Ollama**를 선택하세요.
</Step>
<Step title="모드 선택">
- **Cloud + Local** — 로컬 Ollama 호스트와, 해당 호스트를 통해 라우팅되는 클라우드 모델
@ -44,7 +44,7 @@ OpenClaw는 호스팅된 클라우드 모델과 로컬/자체 호스팅 Ollama
- **Local only** — 로컬 모델만 사용
</Step>
<Step title="모델 선택">
`Cloud only``OLLAMA_API_KEY`를 요청하고 호스팅된 클라우드 기본값을 제안합니다. `Cloud + Local``Local only`는 Ollama 기본 URL을 요청하고, 사용 가능한 모델을 검색하며, 아직 사용할 수 없는 경우 선택한 로컬 모델을 자동으로 pull합니다. `Cloud + Local`은 해당 Ollama 호스트가 클라우드 액세스를 위해 로그인되어 있는지도 확인합니다.
`Cloud only``OLLAMA_API_KEY`를 요청하고 호스팅된 클라우드 기본값을 제안합니다. `Cloud + Local``Local only`는 Ollama 기본 URL을 요청하고, 사용 가능한 모델을 검색하며, 선택한 로컬 모델이 아직 없으면 자동으로 pull합니다. `Cloud + Local`은 해당 Ollama 호스트가 클라우드 액세스를 위해 로그인되어 있는지도 확인합니다.
</Step>
<Step title="모델 사용 가능 여부 확인">
```bash
@ -74,11 +74,11 @@ OpenClaw는 호스팅된 클라우드 모델과 로컬/자체 호스팅 Ollama
</Tab>
<Tab title="수동 설정">
**가장 적합한 경우:** 클라우드 또는 로컬 설정을 완전히 제어하고 싶은 경우.
**적합한 경우:** 클라우드 또는 로컬 설정을 완전히 제어하고 싶을 때.
<Steps>
<Step title="클라우드 또는 로컬 선택">
- **Cloud + Local**: Ollama를 설치하고 `ollama signin`으로 로그인한 뒤, 해당 호스트를 통해 클라우드 요청을 라우팅
- **Cloud + Local**: Ollama를 설치하고, `ollama signin`으로 로그인한 뒤, 해당 호스트를 통해 클라우드 요청을 라우팅
- **Cloud only**: `OLLAMA_API_KEY`와 함께 `https://ollama.com` 사용
- **Local only**: [ollama.com/download](https://ollama.com/download)에서 Ollama 설치
</Step>
@ -92,7 +92,7 @@ OpenClaw는 호스팅된 클라우드 모델과 로컬/자체 호스팅 Ollama
```
</Step>
<Step title="OpenClaw에서 Ollama 활성화">
`Cloud only`에는 실제 `OLLAMA_API_KEY`를 사용하세요. 호스트 기반 설정에서는 아무 플레이스홀더 값이나 동작합니다.
`Cloud only`는 실제 `OLLAMA_API_KEY`를 사용하세요. 호스트 기반 설정에서는 아무 자리표시자 값이나 작동합니다.
```bash
# Cloud
@ -132,9 +132,9 @@ OpenClaw는 호스팅된 클라우드 모델과 로컬/자체 호스팅 Ollama
<Tabs>
<Tab title="Cloud + Local">
`Cloud + Local`로컬 모델과 클라우드 모델 모두에 대해 도달 가능한 Ollama 호스트를 제어 지점으로 사용합니다. 이것이 Ollama가 권장하는 하이브리드 흐름입니다.
`Cloud + Local`연결 가능한 Ollama 호스트를 로컬 모델과 클라우드 모델 모두의 제어 지점으로 사용합니다. 이것이 Ollama에서 권장하는 하이브리드 흐름입니다.
설정 중에 **Cloud + Local**을 사용하세요. OpenClaw는 Ollama 기본 URL을 요청하고, 해당 호스트에서 로컬 모델을 검색하며, 호스트가 `ollama signin`으로 클라우드 액세스에 로그인되어 있는지 확인합니다. 호스트가 로그인되어 있으면 OpenClaw는 `kimi-k2.5:cloud`, `minimax-m2.7:cloud`, `glm-5.1:cloud` 같은 호스팅된 클라우드 기본값도 제안합니다.
설정 중에 **Cloud + Local**을 사용하세요. OpenClaw는 Ollama 기본 URL을 요청하고, 해당 호스트에서 로컬 모델을 검색하며, 호스트가 `ollama signin`으로 클라우드 액세스에 로그인되어 있는지 확인합니다. 호스트가 로그인되어 있으면 OpenClaw는 `kimi-k2.5:cloud`, `minimax-m2.7:cloud`, `glm-5.1:cloud` 같은 호스팅된 클라우드 기본값도 제안합니다.
호스트가 아직 로그인되어 있지 않으면, `ollama signin`을 실행할 때까지 OpenClaw는 설정을 로컬 전용으로 유지합니다.
@ -143,56 +143,56 @@ OpenClaw는 호스팅된 클라우드 모델과 로컬/자체 호스팅 Ollama
<Tab title="Cloud only">
`Cloud only``https://ollama.com`의 Ollama 호스팅 API를 대상으로 실행됩니다.
설정 중에 **Cloud only**를 사용하세요. OpenClaw는 `OLLAMA_API_KEY`를 요청하고, `baseUrl: "https://ollama.com"`을 설정하며, 호스팅된 클라우드 모델 목록을 시드합니다. 이 경로는 로컬 Ollama 서버나 `ollama signin`을 **필요로 하지 않습니다**.
설정 중에 **Cloud only**를 사용하세요. OpenClaw는 `OLLAMA_API_KEY`를 요청하고, `baseUrl: "https://ollama.com"`을 설정하며, 호스팅된 클라우드 모델 목록을 시드합니다. 이 경로는 로컬 Ollama 서버나 `ollama signin`이 **필요하지 않습니다**.
`openclaw onboard` 중 표시되는 클라우드 모델 목록은 `https://ollama.com/api/tags`에서 실시간으로 채워지며, 최대 500개 항목으로 제한되므로 선택기는 정적 시드가 아니라 현재 호스팅 카탈로그를 반영합니다. 설정 시점에 `ollama.com`도달할 수 없거나 모델이 반환되지 않으면, OpenClaw는 이전의 하드코딩된 제안으로 폴백하여 온보딩이 계속 완료되도록 합니다.
`openclaw onboard` 표시되는 클라우드 모델 목록은 `https://ollama.com/api/tags`에서 실시간으로 채워지며, 최대 500개 항목으로 제한되므로 선택기는 정적 시드가 아니라 현재 호스팅 카탈로그를 반영합니다. 설정 시점에 `ollama.com`연결할 수 없거나 모델이 반환되지 않으면, 온보딩이 계속 완료되도록 OpenClaw는 이전 하드코딩된 제안값으로 대체합니다.
</Tab>
<Tab title="Local only">
로컬 전용 모드에서 OpenClaw는 구성된 Ollama 인스턴스에서 모델을 검색합니다. 이 경로는 로컬 또는 자체 호스팅 Ollama 서버용입니다.
OpenClaw는 현재 로컬 기본값으로 `gemma4`를 제안합니다.
현재 OpenClaw는 로컬 기본값으로 `gemma4`를 제안합니다.
</Tab>
</Tabs>
## 모델 검색(암시적 프로바이더)
## 모델 검색(암시적 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` 쿼리 |
| 기능 감지 | 최선 노력 방식의 `/api/show` 조회를 사용해 `contextWindow`를 읽고 기능(비전 포함)을 감지 |
| 비전 모델 | `/api/show``vision` 기능을 보고하는 모델은 이미지 가능(`input: ["text", "image"]`)으로 표시되므로, OpenClaw가 프롬프트에 이미지를 자동 주입 |
| 추론 감지 | 모델 이름 휴리스틱(`r1`, `reasoning`, `think`)으로 `reasoning` 표시 |
| 토큰 제한 | OpenClaw가 사용하는 기본 Ollama 최대 토큰 한으로 `maxTokens` 설정 |
| 카탈로그 조회 | `/api/tags` 조회 |
| 기능 감지 | 최선 `/api/show` 조회를 사용해 `contextWindow`를 읽고 기능(비전 포함)을 감지 |
| 비전 모델 | `/api/show`에서 `vision` 기능이 보고되는 모델은 이미지 지원(`input: ["text", "image"]`)으로 표시되므로, OpenClaw가 프롬프트에 이미지를 자동 주입 |
| reasoning 감지 | 모델 이름 휴리스틱(`r1`, `reasoning`, `think`)으로 `reasoning` 표시 |
| 토큰 제한 | OpenClaw가 사용하는 기본 Ollama 최대 토큰 한으로 `maxTokens` 설정 |
| 비용 | 모든 비용을 `0`으로 설정 |
이렇게 하면 카탈로그를 로컬 Ollama 인스턴스와 정렬된 상태로 유지하면서도 수동 모델 항목 입력을 피할 수 있습니다.
이렇게 하면 수동 모델 항목 없이도 카탈로그를 로컬 Ollama 인스턴스와 일치된 상태로 유지할 수 있습니다.
```bash
# 사용 가능한 모델 보기
# 사용 가능한 모델 확인
ollama list
openclaw models list
```
새 모델을 추가하려면 Ollama로 pull하기만 하면 됩니다.
새 모델을 추가하려면 Ollama로 간단히 pull하면 됩니다.
```bash
ollama pull mistral
```
새 모델은 자동으로 검색되어 바로 사용할 수 있습니다.
새 모델은 자동으로 검색되어 사용할 수 있게 됩니다.
<Note>
`models.providers.ollama`를 명시적으로 설정하면 자동 검색은 건너뛰어지며, 모델을 수동으로 정의해야 합니다. 아래의 명시적 구성 섹션을 참고하세요.
`models.providers.ollama`를 명시적으로 설정하면 자동 검색은 건너뛰며, 모델을 수동으로 정의해야 합니다. 아래의 명시적 구성 섹션을 참고하세요.
</Note>
## 비전 및 이미지 설명
번들 Ollama Plugin은 Ollama를 이미지 가능 미디어 이해 프로바이더로 등록합니다. 이를 통해 OpenClaw는 명시적 이미지 설명 요청과 구성된 이미지 모델 기본값을 로컬 또는 호스팅된 Ollama 비전 모델을 통해 라우팅할 수 있습니다.
번들된 Ollama Plugin은 Ollama를 이미지 지원 미디어 이해 provider로 등록합니다. 이를 통해 OpenClaw는 명시적 이미지 설명 요청과 구성된 이미지 모델 기본값을 로컬 또는 호스팅된 Ollama 비전 모델 라우팅할 수 있습니다.
로컬 비전의 경우 이미지를 지원하는 모델을 pull하세요.
@ -201,7 +201,7 @@ ollama pull qwen2.5vl:7b
export OLLAMA_API_KEY="ollama-local"
```
다음 infer CLI로 확인하세요.
그다음 infer CLI로 확인하세요.
```bash
openclaw infer image describe \
@ -210,9 +210,9 @@ openclaw infer image describe \
--json
```
`--model`은 전체 `<provider/model>` ref여야 합니다. 이 값을 설정하면 `openclaw infer image describe`는 해당 모델이 네이티브 비전을 지원한다는 이유로 설명을 건너뛰지 않고, 그 모델을 직접 실행합니다.
`--model`은 전체 `<provider/model>` 참조여야 합니다. 이 값이 설정되면 `openclaw infer image describe`는 해당 모델이 네이티브 비전을 지원해서 설명을 건너뛰는 대신, 그 모델을 직접 실행합니다.
인바운드 미디어의 기본 이미지 이해 모델로 Ollama를 사용하려면 `agents.defaults.imageModel`을 구성하세요.
수신 미디어에 대한 기본 이미지 이해 모델로 Ollama를 사용하려면 `agents.defaults.imageModel`을 구성하세요.
```json5
{
@ -238,7 +238,7 @@ openclaw infer image describe \
}
```
OpenClaw는 이미지 가능으로 표시되지 않은 모델에 대한 이미지 설명 요청을 거부합니다. 암시적 검색에서는 `/api/show`가 비전 기능을 보고할 때 OpenClaw가 이를 Ollama에서 읽어옵니다.
OpenClaw는 이미지 지원으로 표시되지 않은 모델에 대한 이미지 설명 요청을 거부합니다. 암시적 검색을 사용할 때는 `/api/show`가 비전 기능을 보고하면 OpenClaw가 이를 Ollama에서 읽어옵니다.
## 구성
@ -251,13 +251,13 @@ OpenClaw는 이미지 가능으로 표시되지 않은 모델에 대한 이미
```
<Tip>
`OLLAMA_API_KEY`가 설정되어 있으면 프로바이더 항목에서 `apiKey`를 생략할 수 있으며, OpenClaw가 가용성 확인을 위해 이를 채워 넣습니다.
`OLLAMA_API_KEY`가 설정되어 있으면 provider 항목에서 `apiKey`를 생략할 수 있으며, OpenClaw가 사용 가능 여부 확인을 위해 이를 채웁니다.
</Tip>
</Tab>
<Tab title="명시적(수동 모델)">
호스팅된 클라우드 설정이 필요하거나, Ollama가 다른 호스트/포트에서 실행되거나, 특정 컨텍스트 윈도우 또는 모델 목록을 강제하고 싶거나, 완전 수동 모델 정의를 원할 때는 명시적 구성을 사용하세요.
호스팅된 클라우드 설정을 원하거나, Ollama가 다른 호스트/포트에서 실행되거나, 특정 컨텍스트 윈도우 또는 모델 목록을 강제하고 싶거나, 완전 수동 모델 정의를 원할 때는 명시적 구성을 사용하세요.
```json5
{
@ -287,7 +287,7 @@ OpenClaw는 이미지 가능으로 표시되지 않은 모델에 대한 이미
</Tab>
<Tab title="사용자 지정 기본 URL">
Ollama가 다른 호스트 또는 포트에서 실행 중인 경우(명시적 구성은 자동 검색을 비활성화하므로 모델을 수동으로 정의해야 함):
Ollama가 다른 호스트 포트에서 실행 중인 경우(명시적 구성은 자동 검색을 비활성화하므로 모델을 수동으로 정의해야 함):
```json5
{
@ -296,7 +296,7 @@ OpenClaw는 이미지 가능으로 표시되지 않은 모델에 대한 이미
ollama: {
apiKey: "ollama-local",
baseUrl: "http://ollama-host:11434", // /v1 없음 - 네이티브 Ollama API URL 사용
api: "ollama", // 네이티브 tool-calling 동작을 보장하기 위해 명시적으로 설정
api: "ollama", // 네이티브 도구 호출 동작을 보장하려면 명시적으로 설정
},
},
},
@ -304,7 +304,7 @@ OpenClaw는 이미지 가능으로 표시되지 않은 모델에 대한 이미
```
<Warning>
URL에 `/v1`을 추가하지 마세요. `/v1` 경로는 OpenAI 호환 모드를 사용하므로 tool calling이 신뢰할 수 없습니다. 경로 접미사 없이 기본 Ollama URL을 사용하세요.
URL에 `/v1`을 추가하지 마세요. `/v1` 경로는 OpenAI 호환 모드를 사용하므로 도구 호출이 안정적이지 않습니다. 경로 접미사 없이 기본 Ollama URL을 사용하세요.
</Warning>
</Tab>
@ -312,7 +312,7 @@ OpenClaw는 이미지 가능으로 표시되지 않은 모델에 대한 이미
### 모델 선택
구성되면 모든 Ollama 모델을 사용할 수 있습니다.
구성이 완료되면 모든 Ollama 모델을 사용할 수 있습니다.
```json5
{
@ -329,15 +329,15 @@ OpenClaw는 이미지 가능으로 표시되지 않은 모델에 대한 이미
## Ollama Web Search
OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지원합니다.
OpenClaw는 번들`web_search` provider로 **Ollama Web Search**를 지원합니다.
| 속성 | 세부사항 |
| 속성 | 세 |
| ----------- | ----------------------------------------------------------------------------------------------------------------- |
| 호스트 | 구성된 Ollama 호스트 사용(`models.providers.ollama.baseUrl`이 설정된 경우 해당 값, 아니`http://127.0.0.1:11434`) |
| 호스트 | 구성된 Ollama 호스트 사용(`models.providers.ollama.baseUrl`이 설정된 경우 해당 값, 그렇지 않으`http://127.0.0.1:11434`) |
| 인증 | 키 불필요 |
| 요구 사항 | Ollama가 실행 중이어야 하며 `ollama signin`으로 로그인되어 있어야 함 |
`openclaw onboard` 또는 `openclaw configure --section web` 중에 **Ollama Web Search**를 선택하거나 다음을 설정하세요.
`openclaw onboard` 또는 `openclaw configure --section web` 중에 **Ollama Web Search**를 선택하거나, 다음을 설정하세요:
```json5
{
@ -352,7 +352,7 @@ OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지
```
<Note>
전체 설정 및 동작 세부사항은 [Ollama Web Search](/ko/tools/ollama-search)를 참고하세요.
전체 설정 및 동작 세부 정보는 [Ollama Web Search](/ko/tools/ollama-search)를 참고하세요.
</Note>
## 고급 구성
@ -360,10 +360,10 @@ OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지
<AccordionGroup>
<Accordion title="레거시 OpenAI 호환 모드">
<Warning>
**OpenAI 호환 모드에서는 tool calling이 신뢰할 수 없습니다.** 프록시에 OpenAI 형식이 필요하고 네이티브 tool calling 동작에 의존하지 않는 경우에만 이 모드를 사용하세요.
**OpenAI 호환 모드에서는 도구 호출이 안정적이지 않습니다.** 프록시에 OpenAI 형식이 필요한 경우에만 이 모드를 사용하고, 네이티브 도구 호출 동작에 의존하지 마세요.
</Warning>
대신 OpenAI 호환 엔드포인트를 사용해야 한다면(예: OpenAI 형식만 지원하는 프록시 뒤에 있는 경우), `api: "openai-completions"`를 명시적으로 설정하세요.
대신 OpenAI 호환 엔드포인트를 사용해야 하는 경우(예: OpenAI 형식만 지원하는 프록시 뒤에 있는 경우), `api: "openai-completions"`를 명시적으로 설정하세요.
```json5
{
@ -381,9 +381,9 @@ OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지
}
```
이 모드는 스트리밍과 tool calling을 동시에 지원하지 않을 수 있습니다. 모델 구성의 `params: { streaming: false }`로 스트리밍을 비활성화해야 할 수 있습니다.
이 모드에서는 스트리밍과 도구 호출을 동시에 지원하지 않을 수 있습니다. 모델 구성에서 `params: { streaming: false }`로 스트리밍을 비활성화해야 할 수 있습니다.
Ollama에서 `api: "openai-completions"`를 사용할 때, OpenClaw는 기본적으로 `options.num_ctx`를 주입하여 Ollama가 조용히 4096 컨텍스트 윈도우로 폴백하지 않도록 합니다. 프록시/업스트림이 알 수 없는 `options` 필드를 거부한다면 이 동작을 비활성화하세요.
Ollama와 함께 `api: "openai-completions"`를 사용할 때 OpenClaw는 기본적으로 `options.num_ctx`를 주입하여 Ollama가 조용히 4096 컨텍스트 윈도우로 대체되지 않도록 합니다. 프록시/업스트림이 알 수 없는 `options` 필드를 거부한다면 이 동작을 비활성화하세요.
```json5
{
@ -404,9 +404,9 @@ OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지
</Accordion>
<Accordion title="컨텍스트 윈도우">
자동 검색된 모델의 경우, OpenClaw는 가능하면 Ollama가 보고한 컨텍스트 윈도우를 사용하고, 그렇지 않으면 OpenClaw가 사용하는 기본 Ollama 컨텍스트 윈도우로 폴백합니다.
자동 검색된 모델의 경우 OpenClaw는 가능하면 Ollama가 보고한 컨텍스트 윈도우를 사용하고, 그렇지 않으면 OpenClaw가 사용하는 기본 Ollama 컨텍스트 윈도우로 대체합니다.
명시적 프로바이더 구성에서는 `contextWindow``maxTokens`를 재정의할 수 있습니다.
명시적 provider 구성에서 `contextWindow``maxTokens`를 재정의할 수 있습니다.
```json5
{
@ -428,32 +428,30 @@ OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지
</Accordion>
<Accordion title="추론 모델">
OpenClaw는 기본적으로 `deepseek-r1`, `reasoning`, `think` 같은 이름을 가진 모델을 추론 가능 모델로 처리합니다.
<Accordion title="reasoning 모델">
OpenClaw는 기본적으로 `deepseek-r1`, `reasoning`, `think` 같은 이름을 가진 모델을 reasoning 지원 모델로 취급합니다.
```bash
ollama pull deepseek-r1:32b
```
추가 구성은 필요하지 않습니다. OpenClaw가 자동으로 이를 표시합니다.
추가 구성은 필요하지 않습니다. OpenClaw가 자동으로 표시합니다.
</Accordion>
<Accordion title="모델 비용">
Ollama는 무료이며 로컬에서 실행되므로, 모든 모델 비용은 $0으로 설정됩니다. 이는 자동 검색 모델과 수동 정의 모델 모두에 적용됩니다.
Ollama는 무료이며 로컬에서 실행되므로 모든 모델 비용은 $0으로 설정됩니다. 이는 자동 검색 모델과 수동으로 정의 모델 모두에 적용됩니다.
</Accordion>
<Accordion title="메모리 임베딩">
번들 Ollama Plugin은
[메모리 검색](/ko/concepts/memory)을 위한 메모리 임베딩 프로바이더를 등록합니다. 구성된 Ollama 기본 URL
및 API 키를 사용합니다.
번들된 Ollama Plugin은 [메모리 검색](/ko/concepts/memory)을 위한 메모리 임베딩 provider를 등록합니다. 구성된 Ollama 기본 URL과 API 키를 사용합니다.
| 속성 | 값 |
| ------------- | ------------------- |
| 기본 모델 | `nomic-embed-text` |
| 자동 pull | 예 — 임베딩 모델이 로컬에 없으면 자동으로 pull됩니다 |
| 자동 pull | 예 — 로컬에 없으면 임베딩 모델을 자동으로 pull합니다 |
메모리 검색 임베딩 프로바이더로 Ollama를 선택하려면:
메모리 검색 임베딩 provider로 Ollama를 선택하려면 다음과 같이 설정하세요.
```json5
{
@ -468,10 +466,12 @@ OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지
</Accordion>
<Accordion title="스트리밍 구성">
OpenClaw의 Ollama 통합은 기본적으로 **네이티브 Ollama API**(`/api/chat`)를 사용하며, 이 API는 스트리밍과 tool calling을 동시에 완전히 지원합니다. 특별한 구성이 필요하지 않습니다.
OpenClaw의 Ollama 통합은 기본적으로 **네이티브 Ollama API**(`/api/chat`)를 사용하며, 이 API는 스트리밍과 도구 호출을 동시에 완전히 지원합니다. 별도의 특별한 구성은 필요하지 않습니다.
네이티브 `/api/chat` 요청의 경우 OpenClaw는 thinking 제어도 Ollama에 직접 전달합니다. `/think off``openclaw agent --thinking off`는 최상위 `think: false`를 보내고, `off`가 아닌 thinking 수준은 `think: true`를 보냅니다.
<Tip>
OpenAI 호환 엔드포인트를 사용해야 한다면 위의 "레거시 OpenAI 호환 모드" 섹션을 참고하세요. 해당 모드에서는 스트리밍과 tool calling이 동시에 작동하지 않을 수 있습니다.
OpenAI 호환 엔드포인트를 사용해야 한다면 위의 "레거시 OpenAI 호환 모드" 섹션을 참고하세요. 해당 모드에서는 스트리밍과 도구 호출이 동시에 작동하지 않을 수 있습니다.
</Tip>
</Accordion>
@ -481,7 +481,7 @@ OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지
<AccordionGroup>
<Accordion title="Ollama가 감지되지 않음">
Ollama가 실행 중인지, `OLLAMA_API_KEY`(또는 인증 프로필)를 설정했는지, 그리고 명시적인 `models.providers.ollama` 항목을 **정의하지 않았는지** 확인하세요.
Ollama가 실행 중인지, `OLLAMA_API_KEY`(또는 auth profile)를 설정했는지, 그리고 명시적인 `models.providers.ollama` 항목을 정의하지 **않았는지** 확인하세요.
```bash
ollama serve
@ -496,10 +496,10 @@ OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지
</Accordion>
<Accordion title="사용 가능한 모델이 없음">
모델이 목록에 없다면, 해당 모델을 로컬에서 pull하거나 `models.providers.ollama`에 명시적으로 정의하세요.
모델이 목록에 없으면 로컬에서 해당 모델을 pull하거나 `models.providers.ollama`에 명시적으로 정의하세요.
```bash
ollama list # 설치된 항목 보기
ollama list # 설치된 항목 확인
ollama pull gemma4
ollama pull gpt-oss:20b
ollama pull llama3.3 # 또는 다른 모델
@ -522,20 +522,20 @@ OpenClaw는 번들 `web_search` 프로바이더로 **Ollama Web Search**를 지
</AccordionGroup>
<Note>
추가 도움말: [Troubleshooting](/ko/help/troubleshooting) 및 [FAQ](/ko/help/faq).
추가 도움말: [문제 해결](/ko/help/troubleshooting) 및 [FAQ](/ko/help/faq).
</Note>
## 관련 항목
<CardGroup cols={2}>
<Card title="모델 프로바이더" href="/ko/concepts/model-providers" icon="layers">
모든 프로바이더, 모델 ref, failover 동작 개요.
<Card title="모델 provider" href="/ko/concepts/model-providers" icon="layers">
모든 provider, 모델 참조, 장애 조치 동작 개요.
</Card>
<Card title="모델 선택" href="/ko/concepts/models" icon="brain">
모델 선택 및 구성 방법.
</Card>
<Card title="Ollama Web Search" href="/ko/tools/ollama-search" icon="magnifying-glass">
Ollama 기반 웹 검색의 전체 설정 및 동작 세부사항.
Ollama 기반 웹 검색의 전체 설정 및 동작 세부 정보.
</Card>
<Card title="구성" href="/ko/gateway/configuration" icon="gear">
전체 구성 참조.

View File

@ -0,0 +1,64 @@
---
read_when:
- OpenClaw에서 Tencent Hy 모델을 사용하려고 합니다.
- TokenHub API 키 설정이 필요합니다.
summary: Tencent Cloud TokenHub 설정
title: Tencent Cloud (TokenHub)
x-i18n:
generated_at: "2026-04-22T06:01:08Z"
model: gpt-5.4
provider: openai
source_hash: 04da073973792c55dc0c2d287bfc51187bb2128bbbd5c4a483f850adeea50ab5
source_path: providers/tencent.md
workflow: 15
---
# Tencent Cloud (TokenHub)
Tencent Cloud provider는 TokenHub 엔드포인트(`tencent-tokenhub`)를 통해 Tencent Hy 모델에 접근할 수 있게 해줍니다.
이 provider는 OpenAI 호환 API를 사용합니다.
## 빠른 시작
```bash
openclaw onboard --auth-choice tokenhub-api-key
```
## 비대화형 예시
```bash
openclaw onboard --non-interactive \
--mode local \
--auth-choice tokenhub-api-key \
--tokenhub-api-key "$TOKENHUB_API_KEY" \
--skip-health \
--accept-risk
```
## Provider 및 엔드포인트
| Provider | 엔드포인트 | 사용 사례 |
| ------------------ | ----------------------------- | ------------------------ |
| `tencent-tokenhub` | `tokenhub.tencentmaas.com/v1` | Tencent TokenHub를 통한 Hy |
## 사용 가능한 모델
### tencent-tokenhub
- **hy3-preview** — Hy3 프리뷰(256K 컨텍스트, 추론, 기본값)
## 참고
- TokenHub 모델 ref는 `tencent-tokenhub/<modelId>`를 사용합니다.
- 필요한 경우 `models.providers`에서 가격 및 컨텍스트 메타데이터를 재정의하세요.
## 환경 참고
Gateway가 데몬(launchd/systemd)으로 실행되는 경우, `TOKENHUB_API_KEY`가 해당 프로세스에서 사용 가능하도록 해야 합니다(예: `~/.openclaw/.env` 또는 `env.shellEnv`를 통해).
## 관련 문서
- [OpenClaw Configuration](/ko/gateway/configuration)
- [Model Providers](/ko/concepts/model-providers)
- [Tencent TokenHub](https://cloud.tencent.com/document/product/1823/130050)