chore(i18n): refresh ko translations
This commit is contained in:
parent
5313e0a066
commit
3188678a32
@ -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 빌드
|
||||
```
|
||||
|
||||
@ -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
@ -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 it’s 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) — 자동화 문제 디버깅
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 참조
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 스키마
|
||||
|
||||
@ -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">
|
||||
전체 구성 참조.
|
||||
|
||||
64
docs/ko/providers/tencent.md
Normal file
64
docs/ko/providers/tencent.md
Normal 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)
|
||||
Loading…
Reference in New Issue
Block a user