From 02dd5e55f5ea1b425589ad323840c1063f347b71 Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Sun, 12 Apr 2026 00:21:04 +0000 Subject: [PATCH] chore(i18n): refresh ko translations --- docs/ko/channels/msteams.md | 684 ++++++++++++++++----------- docs/ko/plugins/sdk-agent-harness.md | 140 +++--- docs/ko/providers/openai.md | 318 +++++++------ 3 files changed, 661 insertions(+), 481 deletions(-) diff --git a/docs/ko/channels/msteams.md b/docs/ko/channels/msteams.md index 534444907..812e631df 100644 --- a/docs/ko/channels/msteams.md +++ b/docs/ko/channels/msteams.md @@ -1,56 +1,54 @@ --- read_when: - - Microsoft Teams 채널 기능을 작업할 때 + - Microsoft Teams 채널 기능 작업 중 summary: Microsoft Teams 봇 지원 상태, 기능 및 구성 title: Microsoft Teams x-i18n: - generated_at: "2026-04-05T12:37:02Z" + generated_at: "2026-04-12T00:18:56Z" model: gpt-5.4 provider: openai - source_hash: 99fc6e136893ec65dc85d3bc0c0d92134069a2f3b8cb4fcf66c14674399b3eaf + source_hash: 3e6841a618fb030e4c2029b3652d45dedd516392e2ae17309ff46b93648ffb79 source_path: channels/msteams.md workflow: 15 --- # Microsoft Teams -> "이곳에 들어오는 자여, 모든 희망을 버려라." +> "여기 들어오는 자여, 모든 희망을 버려라." -업데이트: 2026-01-21 +업데이트됨: 2026-03-25 -상태: 텍스트 + DM 첨부파일이 지원되며, 채널/그룹 파일 전송에는 `sharePointSiteId` + Graph 권한이 필요합니다([그룹 채팅에서 파일 보내기](#sending-files-in-group-chats) 참조). Polls는 Adaptive Cards를 통해 전송됩니다. 메시지 작업은 파일 우선 전송을 위한 명시적 `upload-file`을 노출합니다. +상태: 텍스트 + DM 첨부 파일이 지원됩니다. 채널/그룹 파일 전송에는 `sharePointSiteId` + Graph 권한이 필요합니다([그룹 채팅에서 파일 보내기](#sending-files-in-group-chats) 참조). Polls는 Adaptive Cards를 통해 전송됩니다. 메시지 작업은 파일 우선 전송을 위한 명시적 `upload-file`을 노출합니다. -## 번들 플러그인 +## 번들 plugin -Microsoft Teams는 현재 OpenClaw 릴리스에 번들 플러그인으로 포함되어 있으므로, -일반적인 패키지 빌드에서는 별도 설치가 필요하지 않습니다. +Microsoft Teams는 현재 OpenClaw 릴리스에서 번들 plugin으로 제공되므로, 일반적인 패키지형 빌드에서는 별도 설치가 필요하지 않습니다. -이전 빌드이거나 번들 Teams가 제외된 사용자 지정 설치를 사용하는 경우, -수동으로 설치하세요. +이전 빌드이거나 번들 Teams가 제외된 커스텀 설치를 사용하는 경우 수동으로 설치하세요: ```bash openclaw plugins install @openclaw/msteams ``` -로컬 체크아웃(깃 리포지토리에서 실행할 때): +로컬 체크아웃( git 저장소에서 실행하는 경우): ```bash openclaw plugins install ./path/to/local/msteams-plugin ``` -자세한 내용: [Plugins](/tools/plugin) +자세한 내용: [Plugins](/ko/tools/plugin) ## 빠른 설정(초보자용) -1. Microsoft Teams 플러그인을 사용할 수 있는지 확인합니다. +1. Microsoft Teams plugin을 사용할 수 있는지 확인합니다. - 현재 패키지형 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다. - - 이전/사용자 지정 설치에서는 위 명령으로 수동 추가할 수 있습니다. -2. **Azure Bot**(App ID + client secret + tenant ID)을 생성합니다. + - 이전/커스텀 설치에서는 위 명령으로 수동 추가할 수 있습니다. +2. **Azure Bot**(App ID + 클라이언트 시크릿 + 테넌트 ID)을 만듭니다. 3. 해당 자격 증명으로 OpenClaw를 구성합니다. 4. 공개 URL 또는 터널을 통해 `/api/messages`(기본 포트 3978)를 노출합니다. -5. Teams 앱 패키지를 설치하고 게이트웨이를 시작합니다. +5. Teams 앱 패키지를 설치하고 gateway를 시작합니다. -최소 config: +최소 구성(클라이언트 시크릿): ```json5 { @@ -66,19 +64,21 @@ openclaw plugins install ./path/to/local/msteams-plugin } ``` -참고: 그룹 채팅은 기본적으로 차단됩니다(`channels.msteams.groupPolicy: "allowlist"`). 그룹 응답을 허용하려면 `channels.msteams.groupAllowFrom`을 설정하세요(또는 어떤 멤버든 허용하되 기본적으로 멘션 게이팅이 적용되도록 `groupPolicy: "open"`을 사용하세요). +프로덕션 배포에서는 클라이언트 시크릿 대신 [federated authentication](#federated-authentication-certificate--managed-identity)(인증서 또는 managed identity) 사용을 고려하세요. + +참고: 그룹 채팅은 기본적으로 차단됩니다(`channels.msteams.groupPolicy: "allowlist"`). 그룹 답장을 허용하려면 `channels.msteams.groupAllowFrom`을 설정하세요(또는 모든 구성원이 허용되도록 `groupPolicy: "open"`을 사용하세요. 멘션 게이트는 유지됩니다). ## 목표 - Teams DM, 그룹 채팅 또는 채널을 통해 OpenClaw와 대화합니다. -- 라우팅을 결정적으로 유지합니다. 응답은 항상 수신된 채널로 돌아갑니다. +- 라우팅의 결정성을 유지합니다. 답장은 항상 수신된 채널로 돌아갑니다. - 안전한 채널 동작을 기본값으로 사용합니다(별도 구성하지 않으면 멘션 필요). -## config 쓰기 +## 구성 쓰기 -기본적으로 Microsoft Teams는 `/config set|unset`에 의해 트리거된 config 업데이트 쓰기를 허용합니다(`commands.config: true` 필요). +기본적으로 Microsoft Teams는 `/config set|unset`에 의해 트리거된 구성 업데이트를 쓸 수 있습니다(`commands.config: true` 필요). -다음으로 비활성화할 수 있습니다. +다음과 같이 비활성화할 수 있습니다: ```json5 { @@ -90,17 +90,17 @@ openclaw plugins install ./path/to/local/msteams-plugin **DM 액세스** -- 기본값: `channels.msteams.dmPolicy = "pairing"`입니다. 알 수 없는 발신자는 승인될 때까지 무시됩니다. -- `channels.msteams.allowFrom`에는 안정적인 AAD object ID를 사용하는 것이 좋습니다. -- UPN/표시 이름은 변경 가능하므로 직접 일치는 기본적으로 비활성화되어 있으며 `channels.msteams.dangerouslyAllowNameMatching: true`일 때만 활성화됩니다. -- 자격 증명이 허용되면 마법사가 Microsoft Graph를 통해 이름을 ID로 확인할 수 있습니다. +- 기본값: `channels.msteams.dmPolicy = "pairing"`. 승인되기 전까지 알 수 없는 발신자는 무시됩니다. +- `channels.msteams.allowFrom`에는 안정적인 AAD 객체 ID를 사용해야 합니다. +- UPN/표시 이름은 변경될 수 있습니다. 직접 매칭은 기본적으로 비활성화되어 있으며 `channels.msteams.dangerouslyAllowNameMatching: true`일 때만 활성화됩니다. +- 마법사는 자격 증명이 허용하면 Microsoft Graph를 통해 이름을 ID로 확인할 수 있습니다. **그룹 액세스** -- 기본값: `channels.msteams.groupPolicy = "allowlist"`입니다(`groupAllowFrom`을 추가하지 않으면 차단됨). 설정되지 않았을 때 기본값을 재정의하려면 `channels.defaults.groupPolicy`를 사용하세요. +- 기본값: `channels.msteams.groupPolicy = "allowlist"`(`groupAllowFrom`을 추가하지 않으면 차단됨). 설정되지 않은 경우 기본값을 재정의하려면 `channels.defaults.groupPolicy`를 사용하세요. - `channels.msteams.groupAllowFrom`은 그룹 채팅/채널에서 어떤 발신자가 트리거할 수 있는지 제어합니다(`channels.msteams.allowFrom`으로 대체됨). -- 어떤 멤버든 허용하려면 `groupPolicy: "open"`을 설정하세요(그래도 기본적으로 멘션 게이팅 적용). -- **어떤 채널도 허용하지 않으려면** `channels.msteams.groupPolicy: "disabled"`를 설정하세요. +- `groupPolicy: "open"`을 설정하면 모든 구성원을 허용합니다(기본적으로는 여전히 멘션 게이트 적용). +- **채널을 전혀 허용하지 않으려면** `channels.msteams.groupPolicy: "disabled"`를 설정하세요. 예시: @@ -115,14 +115,14 @@ openclaw plugins install ./path/to/local/msteams-plugin } ``` -**Teams + 채널 허용 목록** +**Teams + 채널 allowlist** -- `channels.msteams.teams` 아래에 팀과 채널을 나열해 그룹/채널 응답 범위를 지정합니다. -- 키에는 안정적인 팀 ID와 채널 conversation ID를 사용해야 합니다. -- `groupPolicy="allowlist"`이고 teams 허용 목록이 있으면 나열된 팀/채널만 허용됩니다(멘션 게이팅 적용). -- 구성 마법사는 `Team/Channel` 항목을 받아 대신 저장해 줍니다. -- 시작 시 OpenClaw는 팀/채널 및 사용자 허용 목록 이름을 ID로 확인하고(Graph 권한이 허용될 때) - 매핑을 로그에 남깁니다. 확인되지 않은 팀/채널 이름은 입력된 그대로 유지되지만, `channels.msteams.dangerouslyAllowNameMatching: true`가 활성화되지 않는 한 기본적으로 라우팅에서는 무시됩니다. +- `channels.msteams.teams` 아래에 teams와 채널을 나열하여 그룹/채널 답장 범위를 지정합니다. +- 키에는 안정적인 팀 ID와 채널 대화 ID를 사용해야 합니다. +- `groupPolicy="allowlist"`이고 teams allowlist가 있으면, 나열된 teams/채널만 허용됩니다(멘션 게이트 적용). +- 구성 마법사는 `Team/Channel` 항목을 받아 이를 대신 저장해 줍니다. +- 시작 시 OpenClaw는 team/channel 및 사용자 allowlist 이름을 ID로 확인하고(Graph 권한이 허용하는 경우) + 매핑을 로그에 기록합니다. 확인되지 않은 team/channel 이름은 입력된 그대로 유지되지만, 기본적으로 라우팅에서는 무시됩니다. `channels.msteams.dangerouslyAllowNameMatching: true`가 활성화된 경우는 예외입니다. 예시: @@ -145,67 +145,209 @@ openclaw plugins install ./path/to/local/msteams-plugin ## 작동 방식 -1. Microsoft Teams 플러그인을 사용할 수 있는지 확인합니다. +1. Microsoft Teams plugin을 사용할 수 있는지 확인합니다. - 현재 패키지형 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다. - - 이전/사용자 지정 설치에서는 위 명령으로 수동 추가할 수 있습니다. -2. **Azure Bot**(App ID + secret + tenant ID)을 생성합니다. + - 이전/커스텀 설치에서는 위 명령으로 수동 추가할 수 있습니다. +2. **Azure Bot**(App ID + 시크릿 + 테넌트 ID)을 만듭니다. 3. 봇을 참조하고 아래 RSC 권한을 포함하는 **Teams 앱 패키지**를 빌드합니다. -4. Teams 앱을 팀에 업로드/설치합니다(DM용 개인 범위도 가능). -5. `~/.openclaw/openclaw.json`(또는 env vars)에서 `msteams`를 구성하고 게이트웨이를 시작합니다. -6. 게이트웨이는 기본적으로 `/api/messages`에서 Bot Framework 웹훅 트래픽을 수신 대기합니다. +4. Teams 앱을 팀에 업로드/설치합니다(또는 DM용 개인 범위). +5. `~/.openclaw/openclaw.json`(또는 env vars)에서 `msteams`를 구성하고 gateway를 시작합니다. +6. gateway는 기본적으로 `/api/messages`에서 Bot Framework webhook 트래픽을 수신 대기합니다. ## Azure Bot 설정(사전 요구 사항) -OpenClaw를 구성하기 전에 Azure Bot 리소스를 생성해야 합니다. +OpenClaw를 구성하기 전에 Azure Bot 리소스를 만들어야 합니다. -### 1단계: Azure Bot 생성 +### 1단계: Azure Bot 만들기 -1. [Create Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot)으로 이동합니다. -2. **Basics** 탭을 채웁니다. +1. [Create Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot)로 이동합니다. +2. **Basics** 탭을 다음과 같이 입력합니다: - | Field | Value | + | 필드 | 값 | | ------------------ | -------------------------------------------------------- | - | **Bot handle** | 봇 이름(예: `openclaw-msteams`)이며 고유해야 함 | - | **Subscription** | Azure 구독 선택 | - | **Resource group** | 새로 만들거나 기존 것 사용 | - | **Pricing tier** | 개발/테스트용 **Free** | - | **Type of App** | **Single Tenant**(권장 - 아래 참고 참조) | - | **Creation type** | **Create new Microsoft App ID** | + | **Bot handle** | 봇 이름(예: `openclaw-msteams`) (고유해야 함) | + | **Subscription** | Azure 구독 선택 | + | **Resource group** | 새로 만들거나 기존 항목 사용 | + | **Pricing tier** | 개발/테스트용 **Free** | + | **Type of App** | **Single Tenant**(권장 - 아래 참고) | + | **Creation type** | **Create new Microsoft App ID** | -> **지원 중단 안내:** 새 멀티 테넌트 봇 생성은 2025-07-31 이후 지원 중단되었습니다. 새 봇에는 **Single Tenant**를 사용하세요. +> **지원 중단 안내:** 새 multi-tenant bot 생성은 2025-07-31 이후 지원 중단되었습니다. 새 bot에는 **Single Tenant**를 사용하세요. -3. **Review + create** → **Create**를 클릭합니다(약 1~2분 대기) +3. **Review + create** → **Create**를 클릭합니다(약 1-2분 대기) ### 2단계: 자격 증명 가져오기 -1. Azure Bot 리소스로 이동 → **Configuration** -2. **Microsoft App ID**를 복사 → 이것이 `appId`입니다 -3. **Manage Password**를 클릭 → App Registration으로 이동 -4. **Certificates & secrets** → **New client secret** → **Value**를 복사 → 이것이 `appPassword`입니다 -5. **Overview**로 이동 → **Directory (tenant) ID**를 복사 → 이것이 `tenantId`입니다 +1. Azure Bot 리소스 → **Configuration**으로 이동합니다. +2. **Microsoft App ID**를 복사합니다 → 이것이 `appId`입니다. +3. **Manage Password**를 클릭합니다 → App Registration으로 이동합니다. +4. **Certificates & secrets** → **New client secret**에서 **Value**를 복사합니다 → 이것이 `appPassword`입니다. +5. **Overview**로 이동합니다 → **Directory (tenant) ID**를 복사합니다 → 이것이 `tenantId`입니다. ### 3단계: 메시징 엔드포인트 구성 1. Azure Bot → **Configuration** -2. **Messaging endpoint**를 웹훅 URL로 설정합니다. +2. **Messaging endpoint**를 webhook URL로 설정합니다: - 프로덕션: `https://your-domain.com/api/messages` - 로컬 개발: 터널 사용([로컬 개발](#local-development-tunneling) 참조) ### 4단계: Teams 채널 활성화 -1. Azure Bot → **Channels** -2. **Microsoft Teams** → Configure → Save를 클릭 -3. 서비스 약관에 동의합니다 +1. Azure Bot → **Channels**로 이동합니다. +2. **Microsoft Teams** → Configure → Save를 클릭합니다. +3. 서비스 약관에 동의합니다. + +## Federated Authentication(인증서 + Managed Identity) + +> 2026.3.24에 추가됨 + +프로덕션 배포에서 OpenClaw는 클라이언트 시크릿보다 더 안전한 대안으로 **federated authentication**을 지원합니다. 두 가지 방법을 사용할 수 있습니다: + +### 옵션 A: 인증서 기반 인증 + +Entra ID 앱 등록에 등록된 PEM 인증서를 사용합니다. + +**설정:** + +1. 인증서를 생성하거나 준비합니다(개인 키가 포함된 PEM 형식). +2. Entra ID → App Registration → **Certificates & secrets** → **Certificates** → 공개 인증서를 업로드합니다. + +**구성:** + +```json5 +{ + channels: { + msteams: { + enabled: true, + appId: "", + tenantId: "", + authType: "federated", + certificatePath: "/path/to/cert.pem", + webhook: { port: 3978, path: "/api/messages" }, + }, + }, +} +``` + +**Env vars:** + +- `MSTEAMS_AUTH_TYPE=federated` +- `MSTEAMS_CERTIFICATE_PATH=/path/to/cert.pem` + +### 옵션 B: Azure Managed Identity + +암호 없는 인증을 위해 Azure Managed Identity를 사용합니다. 이는 managed identity를 사용할 수 있는 Azure 인프라(AKS, App Service, Azure VM) 배포에 이상적입니다. + +**작동 방식:** + +1. bot pod/VM에 managed identity(시스템 할당 또는 사용자 할당)가 있습니다. +2. **federated identity credential**이 managed identity를 Entra ID 앱 등록에 연결합니다. +3. 런타임에 OpenClaw는 `@azure/identity`를 사용해 Azure IMDS 엔드포인트(`169.254.169.254`)에서 토큰을 획득합니다. +4. 이 토큰이 bot 인증을 위해 Teams SDK에 전달됩니다. + +**사전 요구 사항:** + +- managed identity가 활성화된 Azure 인프라(AKS workload identity, App Service, VM) +- Entra ID 앱 등록에 생성된 federated identity credential +- pod/VM에서 IMDS(`169.254.169.254:80`)로의 네트워크 액세스 + +**구성(시스템 할당 managed identity):** + +```json5 +{ + channels: { + msteams: { + enabled: true, + appId: "", + tenantId: "", + authType: "federated", + useManagedIdentity: true, + webhook: { port: 3978, path: "/api/messages" }, + }, + }, +} +``` + +**구성(사용자 할당 managed identity):** + +```json5 +{ + channels: { + msteams: { + enabled: true, + appId: "", + tenantId: "", + authType: "federated", + useManagedIdentity: true, + managedIdentityClientId: "", + webhook: { port: 3978, path: "/api/messages" }, + }, + }, +} +``` + +**Env vars:** + +- `MSTEAMS_AUTH_TYPE=federated` +- `MSTEAMS_USE_MANAGED_IDENTITY=true` +- `MSTEAMS_MANAGED_IDENTITY_CLIENT_ID=`(사용자 할당인 경우에만) + +### AKS Workload Identity 설정 + +workload identity를 사용하는 AKS 배포의 경우: + +1. AKS 클러스터에서 **workload identity**를 활성화합니다. +2. Entra ID 앱 등록에 **federated identity credential**을 생성합니다: + + ```bash + az ad app federated-credential create --id --parameters '{ + "name": "my-bot-workload-identity", + "issuer": "", + "subject": "system:serviceaccount::", + "audiences": ["api://AzureADTokenExchange"] + }' + ``` + +3. 앱 클라이언트 ID로 **Kubernetes 서비스 계정에 주석을 추가**합니다: + + ```yaml + apiVersion: v1 + kind: ServiceAccount + metadata: + name: my-bot-sa + annotations: + azure.workload.identity/client-id: "" + ``` + +4. **workload identity 주입**을 위해 pod에 레이블을 추가합니다: + + ```yaml + metadata: + labels: + azure.workload.identity/use: "true" + ``` + +5. IMDS(`169.254.169.254`)에 대한 **네트워크 액세스**를 보장합니다. NetworkPolicy를 사용하는 경우 `169.254.169.254/32`의 80번 포트로 가는 트래픽을 허용하는 egress 규칙을 추가하세요. + +### 인증 유형 비교 + +| 방법 | 구성 | 장점 | 단점 | +| -------------------- | ---------------------------------------------- | ---------------------------------- | ------------------------------------- | +| **클라이언트 시크릿** | `appPassword` | 설정이 단순함 | 시크릿 회전 필요, 보안성 낮음 | +| **인증서** | `authType: "federated"` + `certificatePath` | 네트워크를 통한 공유 시크릿이 없음 | 인증서 관리 오버헤드 | +| **Managed Identity** | `authType: "federated"` + `useManagedIdentity` | 암호 없음, 관리할 시크릿 없음 | Azure 인프라 필요 | + +**기본 동작:** `authType`이 설정되지 않으면 OpenClaw는 기본적으로 클라이언트 시크릿 인증을 사용합니다. 기존 구성은 변경 없이 계속 동작합니다. ## 로컬 개발(터널링) -Teams는 `localhost`에 접근할 수 없습니다. 로컬 개발에는 터널을 사용하세요. +Teams는 `localhost`에 접근할 수 없습니다. 로컬 개발에는 터널을 사용하세요: **옵션 A: ngrok** ```bash ngrok http 3978 -# https URL을 복사합니다. 예: https://abc123.ngrok.io +# https URL을 복사하세요. 예: https://abc123.ngrok.io # 메시징 엔드포인트를 다음으로 설정: https://abc123.ngrok.io/api/messages ``` @@ -218,53 +360,53 @@ tailscale funnel 3978 ## Teams Developer Portal(대안) -manifest ZIP를 수동 생성하는 대신 [Teams Developer Portal](https://dev.teams.microsoft.com/apps)을 사용할 수 있습니다. +manifest ZIP를 수동으로 만드는 대신 [Teams Developer Portal](https://dev.teams.microsoft.com/apps)을 사용할 수 있습니다: -1. **+ New app** 클릭 -2. 기본 정보(이름, 설명, 개발자 정보) 입력 -3. **App features** → **Bot**으로 이동 -4. **Enter a bot ID manually**를 선택하고 Azure Bot App ID를 붙여넣기 -5. 범위 선택: **Personal**, **Team**, **Group Chat** -6. **Distribute** → **Download app package** 클릭 -7. Teams에서 **Apps** → **Manage your apps** → **Upload a custom app** → ZIP 선택 +1. **+ New app**을 클릭합니다. +2. 기본 정보(이름, 설명, 개발자 정보)를 입력합니다. +3. **App features** → **Bot**으로 이동합니다. +4. **Enter a bot ID manually**를 선택하고 Azure Bot App ID를 붙여넣습니다. +5. 범위를 선택합니다: **Personal**, **Team**, **Group Chat** +6. **Distribute** → **Download app package**를 클릭합니다. +7. Teams에서 **Apps** → **Manage your apps** → **Upload a custom app** → ZIP 파일을 선택합니다. -이 방식은 JSON manifest를 직접 편집하는 것보다 더 쉬운 경우가 많습니다. +이 방법이 JSON manifest를 직접 편집하는 것보다 더 쉬운 경우가 많습니다. -## 봇 테스트 +## Bot 테스트 -**옵션 A: Azure Web Chat(먼저 웹훅 확인)** +**옵션 A: Azure Web Chat(먼저 webhook 확인)** 1. Azure Portal → Azure Bot 리소스 → **Test in Web Chat** -2. 메시지를 전송하면 응답이 보여야 합니다 -3. 이를 통해 Teams 설정 전에 웹훅 엔드포인트가 동작하는지 확인할 수 있습니다 +2. 메시지를 보내면 응답이 보여야 합니다. +3. 이를 통해 Teams 설정 전에 webhook 엔드포인트가 정상 동작하는지 확인할 수 있습니다. **옵션 B: Teams(앱 설치 후)** -1. Teams 앱 설치(사이드로드 또는 조직 카탈로그) -2. Teams에서 봇을 찾고 DM 전송 -3. 게이트웨이 로그에서 들어오는 activity 확인 +1. Teams 앱을 설치합니다(사이드로드 또는 조직 카탈로그). +2. Teams에서 bot을 찾아 DM을 보냅니다. +3. 수신 activity가 있는지 gateway 로그를 확인합니다. ## 설정(최소 텍스트 전용) -1. **Microsoft Teams 플러그인을 사용할 수 있는지 확인** +1. **Microsoft Teams plugin을 사용할 수 있는지 확인** - 현재 패키지형 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다. - - 이전/사용자 지정 설치에서는 수동으로 추가할 수 있습니다. + - 이전/커스텀 설치에서는 수동으로 추가할 수 있습니다: - npm에서: `openclaw plugins install @openclaw/msteams` - 로컬 체크아웃에서: `openclaw plugins install ./path/to/local/msteams-plugin` -2. **봇 등록** - - Azure Bot을 생성하고(위 참조) 다음을 기록합니다. +2. **Bot 등록** + - Azure Bot을 만들고(위 참조) 다음 값을 기록합니다: - App ID - - Client secret(App password) - - Tenant ID(single-tenant) + - 클라이언트 시크릿(App password) + - 테넌트 ID(single-tenant) 3. **Teams 앱 manifest** - - `botId = `인 `bot` 항목을 포함합니다. + - `botId = `를 사용하는 `bot` 항목을 포함합니다. - 범위: `personal`, `team`, `groupChat`. - `supportsFiles: true`(개인 범위 파일 처리에 필요). - - RSC 권한(아래)을 추가합니다. - - 아이콘 생성: `outline.png` (32x32), `color.png` (192x192). - - 세 파일을 함께 zip으로 묶습니다: `manifest.json`, `outline.png`, `color.png`. + - RSC 권한을 추가합니다(아래 참조). + - 아이콘을 만듭니다: `outline.png`(32x32) 및 `color.png`(192x192). + - 세 파일을 함께 압축합니다: `manifest.json`, `outline.png`, `color.png`. 4. **OpenClaw 구성** @@ -282,45 +424,50 @@ manifest ZIP를 수동 생성하는 대신 [Teams Developer Portal](https://dev. } ``` - config 키 대신 환경 변수를 사용할 수도 있습니다. + 구성 키 대신 환경 변수를 사용할 수도 있습니다: - `MSTEAMS_APP_ID` - `MSTEAMS_APP_PASSWORD` - `MSTEAMS_TENANT_ID` + - `MSTEAMS_AUTH_TYPE`(선택 사항: `"secret"` 또는 `"federated"`) + - `MSTEAMS_CERTIFICATE_PATH`(federated + 인증서) + - `MSTEAMS_CERTIFICATE_THUMBPRINT`(선택 사항, 인증에 필수는 아님) + - `MSTEAMS_USE_MANAGED_IDENTITY`(federated + managed identity) + - `MSTEAMS_MANAGED_IDENTITY_CLIENT_ID`(사용자 할당 MI 전용) -5. **봇 엔드포인트** - - Azure Bot Messaging Endpoint를 다음으로 설정합니다. - - `https://:3978/api/messages`(또는 선택한 path/port). +5. **Bot 엔드포인트** + - Azure Bot Messaging Endpoint를 다음으로 설정합니다: + - `https://:3978/api/messages`(또는 선택한 경로/포트). -6. **게이트웨이 실행** - - 번들 또는 수동 설치된 플러그인을 사용할 수 있고 자격 증명이 포함된 `msteams` config가 존재하면 Teams 채널이 자동으로 시작됩니다. +6. **Gateway 실행** + - 번들 또는 수동 설치된 plugin을 사용할 수 있고 자격 증명이 포함된 `msteams` 구성이 존재하면 Teams 채널이 자동으로 시작됩니다. ## 멤버 정보 작업 -OpenClaw는 Microsoft Teams용 Graph 기반 `member-info` 작업을 노출하므로 에이전트와 자동화가 Microsoft Graph에서 직접 채널 멤버 정보(표시 이름, 이메일, 역할)를 확인할 수 있습니다. +OpenClaw는 Microsoft Teams용으로 Graph 기반 `member-info` 작업을 노출하므로, 에이전트와 자동화가 Microsoft Graph에서 직접 채널 멤버 세부 정보(표시 이름, 이메일, 역할)를 확인할 수 있습니다. 요구 사항: - `Member.Read.Group` RSC 권한(권장 manifest에 이미 포함됨) -- 팀 간 조회용: 관리자 동의가 포함된 `User.Read.All` Graph Application 권한 +- 팀 간 조회의 경우: 관리자 동의가 포함된 `User.Read.All` Graph Application 권한 이 작업은 `channels.msteams.actions.memberInfo`로 제어됩니다(기본값: Graph 자격 증명을 사용할 수 있을 때 활성화). ## 기록 컨텍스트 -- `channels.msteams.historyLimit`은 프롬프트에 포함할 최근 채널/그룹 메시지 수를 제어합니다. -- `messages.groupChat.historyLimit`로 대체됩니다. `0`으로 설정하면 비활성화됩니다(기본값 50). -- 가져온 스레드 기록은 발신자 허용 목록(`allowFrom` / `groupAllowFrom`)으로 필터링되므로 스레드 컨텍스트 시드는 허용된 발신자의 메시지만 포함합니다. -- 인용된 첨부파일 컨텍스트(`ReplyTo*`에서 파생된 Teams reply HTML)는 현재 수신된 그대로 전달됩니다. -- 즉, 허용 목록은 누가 에이전트를 트리거할 수 있는지를 제어하며, 현재는 특정 보조 컨텍스트 경로만 필터링됩니다. -- DM 기록은 `channels.msteams.dmHistoryLimit`(사용자 턴 수)로 제한할 수 있습니다. 사용자별 재정의: `channels.msteams.dms[""].historyLimit`. +- `channels.msteams.historyLimit`은 최근 채널/그룹 메시지 중 프롬프트에 포함할 개수를 제어합니다. +- `messages.groupChat.historyLimit`으로 대체됩니다. 비활성화하려면 `0`으로 설정하세요(기본값 50). +- 가져온 스레드 기록은 발신자 allowlist(`allowFrom` / `groupAllowFrom`)로 필터링되므로, 스레드 컨텍스트 시드는 허용된 발신자의 메시지만 포함합니다. +- 인용된 첨부 파일 컨텍스트(`Teams` 응답 HTML에서 파생된 `ReplyTo*`)는 현재 수신된 형태 그대로 전달됩니다. +- 즉, allowlist는 누가 에이전트를 트리거할 수 있는지 제어하며, 현재는 특정 보조 컨텍스트 경로만 필터링됩니다. +- DM 기록은 `channels.msteams.dmHistoryLimit`(사용자 턴)으로 제한할 수 있습니다. 사용자별 재정의: `channels.msteams.dms[""].historyLimit`. ## 현재 Teams RSC 권한(Manifest) -다음은 Teams 앱 manifest의 **기존 resourceSpecific 권한**입니다. 이는 앱이 설치된 팀/채팅 내부에서만 적용됩니다. +다음은 Teams 앱 manifest의 **기존 resourceSpecific 권한**입니다. 이 권한은 앱이 설치된 팀/채팅 내부에서만 적용됩니다. -**채널(팀 범위)의 경우:** +**채널(team 범위)용:** -- `ChannelMessage.Read.Group` (Application) - @멘션 없이 모든 채널 메시지 수신 +- `ChannelMessage.Read.Group` (Application) - @mention 없이 모든 채널 메시지 수신 - `ChannelMessage.Send.Group` (Application) - `Member.Read.Group` (Application) - `Owner.Read.Group` (Application) @@ -328,13 +475,13 @@ OpenClaw는 Microsoft Teams용 Graph 기반 `member-info` 작업을 노출하므 - `TeamMember.Read.Group` (Application) - `TeamSettings.Read.Group` (Application) -**그룹 채팅의 경우:** +**그룹 채팅용:** -- `ChatMessage.Read.Chat` (Application) - @멘션 없이 모든 그룹 채팅 메시지 수신 +- `ChatMessage.Read.Chat` (Application) - @mention 없이 모든 그룹 채팅 메시지 수신 -## 예시 Teams Manifest(일부 가림) +## 예시 Teams Manifest(민감 정보 제거) -필수 필드를 포함한 최소한의 유효한 예시입니다. ID와 URL을 바꿔 사용하세요. +필수 필드를 포함한 최소 유효 예시입니다. ID와 URL을 바꿔 넣으세요. ```json5 { @@ -384,146 +531,151 @@ OpenClaw는 Microsoft Teams용 Graph 기반 `member-info` 작업을 노출하므 ### Manifest 주의 사항(필수 필드) -- `bots[].botId`는 Azure Bot App ID와 **반드시** 일치해야 합니다. -- `webApplicationInfo.id`는 Azure Bot App ID와 **반드시** 일치해야 합니다. +- `bots[].botId`는 Azure Bot App ID와 반드시 일치해야 합니다. +- `webApplicationInfo.id`는 Azure Bot App ID와 반드시 일치해야 합니다. - `bots[].scopes`에는 사용할 표면(`personal`, `team`, `groupChat`)이 포함되어야 합니다. - `bots[].supportsFiles: true`는 개인 범위 파일 처리에 필요합니다. -- 채널 트래픽을 원한다면 `authorization.permissions.resourceSpecific`에 채널 읽기/보내기가 포함되어야 합니다. +- 채널 트래픽을 원한다면 `authorization.permissions.resourceSpecific`에 채널 읽기/전송 권한이 포함되어야 합니다. ### 기존 앱 업데이트 -이미 설치된 Teams 앱을 업데이트하려면(예: RSC 권한 추가): +이미 설치된 Teams 앱을 업데이트하려는 경우(예: RSC 권한 추가): -1. 새 설정으로 `manifest.json`을 업데이트합니다 -2. **`version` 필드를 증가**시킵니다(예: `1.0.0` → `1.1.0`) -3. 아이콘과 함께 manifest를 **다시 zip으로 묶습니다**(`manifest.json`, `outline.png`, `color.png`) -4. 새 zip을 업로드합니다. - - **옵션 A (Teams Admin Center):** Teams Admin Center → Teams apps → Manage apps → 앱 찾기 → Upload new version - - **옵션 B (Sideload):** Teams → Apps → Manage your apps → Upload a custom app -5. **팀 채널의 경우:** 새 권한이 적용되도록 각 팀에 앱을 다시 설치합니다 -6. 캐시된 앱 메타데이터를 지우기 위해 Teams를 **완전히 종료 후 다시 실행**합니다(창만 닫지 말 것) +1. 새 설정으로 `manifest.json`을 업데이트합니다. +2. **`version` 필드를 증가**시킵니다(예: `1.0.0` → `1.1.0`). +3. 아이콘과 함께 manifest를 **다시 압축**합니다(`manifest.json`, `outline.png`, `color.png`). +4. 새 zip을 업로드합니다: + - **옵션 A(Teams Admin Center):** Teams Admin Center → Teams apps → Manage apps → 앱 찾기 → Upload new version + - **옵션 B(사이드로드):** Teams에서 → Apps → Manage your apps → Upload a custom app +5. **팀 채널의 경우:** 새 권한이 적용되도록 각 팀에 앱을 다시 설치합니다. +6. 캐시된 앱 메타데이터를 지우기 위해 Teams를 **완전히 종료한 뒤 다시 실행**합니다(창만 닫지 마세요). ## 기능: RSC 전용 vs Graph -### **Teams RSC만 사용**하는 경우(앱 설치됨, Graph API 권한 없음) +### **Teams RSC만** 있는 경우(앱 설치됨, Graph API 권한 없음) 작동함: -- 채널 메시지 **텍스트** 콘텐츠 읽기. -- 채널 메시지 **텍스트** 콘텐츠 보내기. -- **개인(DM)** 파일 첨부 수신. +- 채널 메시지 **텍스트** 콘텐츠 읽기 +- 채널 메시지 **텍스트** 콘텐츠 전송 +- **개인(DM)** 파일 첨부 수신 작동하지 않음: -- 채널/그룹 **이미지 또는 파일 콘텐츠**(payload에는 HTML stub만 포함됨). -- SharePoint/OneDrive에 저장된 첨부파일 다운로드. -- 메시지 기록 읽기(실시간 웹훅 이벤트 범위 초과). +- 채널/그룹 **이미지 또는 파일 콘텐츠**(페이로드에 HTML 스텁만 포함됨) +- SharePoint/OneDrive에 저장된 첨부 파일 다운로드 +- 메시지 기록 읽기(실시간 webhook 이벤트를 초과하는 범위) -### **Teams RSC + Microsoft Graph Application 권한** 사용 시 +### **Teams RSC + Microsoft Graph Application 권한**이 있는 경우 추가됨: -- 호스팅된 콘텐츠 다운로드(메시지에 붙여넣은 이미지). -- SharePoint/OneDrive에 저장된 파일 첨부 다운로드. -- Graph를 통한 채널/채팅 메시지 기록 읽기. +- 호스팅된 콘텐츠 다운로드(메시지에 붙여넣은 이미지) +- SharePoint/OneDrive에 저장된 파일 첨부 다운로드 +- Graph를 통한 채널/채팅 메시지 기록 읽기 ### RSC vs Graph API -| Capability | RSC Permissions | Graph API | +| 기능 | RSC 권한 | Graph API | | ----------------------- | -------------------- | ----------------------------------- | -| **실시간 메시지** | 예(웹훅을 통해) | 아니요(폴링만 가능) | -| **과거 메시지** | 아니요 | 예(기록 조회 가능) | -| **설정 복잡도** | 앱 manifest만 필요 | 관리자 동의 + 토큰 흐름 필요 | -| **오프라인 동작** | 아니요(실행 중이어야 함) | 예(언제든 조회 가능) | +| **실시간 메시지** | 예(webhook 경유) | 아니요(폴링만 가능) | +| **이전 메시지** | 아니요 | 예(기록 조회 가능) | +| **설정 복잡도** | 앱 manifest만 필요 | 관리자 동의 + 토큰 흐름 필요 | +| **오프라인 동작** | 아니요(실행 중이어야 함) | 예(언제든 조회 가능) | -**요약:** RSC는 실시간 수신용이고, Graph API는 과거 기록 접근용입니다. 오프라인 동안 놓친 메시지를 따라잡으려면 Graph API와 `ChannelMessage.Read.All`이 필요합니다(관리자 동의 필요). +**핵심:** RSC는 실시간 수신용이고, Graph API는 과거 기록 접근용입니다. 오프라인 상태에서 놓친 메시지를 따라잡으려면 Graph API와 `ChannelMessage.Read.All`이 필요합니다(관리자 동의 필요). -## Graph 기반 미디어 + 기록(채널에 필요) +## Graph 사용 미디어 + 기록(채널에 필요) -**채널**에서 이미지/파일이 필요하거나 **메시지 기록**을 가져오려면 Microsoft Graph 권한을 활성화하고 관리자 동의를 받아야 합니다. +**채널**에서 이미지/파일이 필요하거나 **메시지 기록**을 가져오려면 Microsoft Graph 권한을 활성화하고 관리자 동의를 부여해야 합니다. -1. Entra ID (Azure AD) **App Registration**에서 Microsoft Graph **Application permissions**를 추가합니다. - - `ChannelMessage.Read.All` (채널 첨부파일 + 기록) - - `Chat.Read.All` 또는 `ChatMessage.Read.All` (그룹 채팅) -2. 테넌트에 대해 **관리자 동의**를 부여합니다. -3. Teams 앱 **manifest 버전**을 올리고, 다시 업로드한 뒤, **Teams에 앱을 재설치**합니다. -4. 캐시된 앱 메타데이터를 지우기 위해 Teams를 **완전히 종료 후 다시 실행**합니다. +1. Entra ID(Azure AD) **App Registration**에서 Microsoft Graph **Application 권한**을 추가합니다: + - `ChannelMessage.Read.All`(채널 첨부 파일 + 기록) + - `Chat.Read.All` 또는 `ChatMessage.Read.All`(그룹 채팅) +2. 테넌트에 대해 **관리자 동의 부여**를 수행합니다. +3. Teams 앱 **manifest 버전**을 올리고, 다시 업로드한 뒤, Teams에서 **앱을 다시 설치**합니다. +4. 캐시된 앱 메타데이터를 지우기 위해 Teams를 **완전히 종료한 뒤 다시 실행**합니다. -**사용자 멘션을 위한 추가 권한:** 사용자 @멘션은 대화에 있는 사용자에 대해서는 기본적으로 작동합니다. 하지만 현재 대화에 **없는** 사용자를 동적으로 검색하고 멘션하려면 `User.Read.All` (Application) 권한을 추가하고 관리자 동의를 부여하세요. +**사용자 멘션을 위한 추가 권한:** 대화에 포함된 사용자에 대한 @mention은 기본적으로 바로 동작합니다. 하지만 **현재 대화에 없는** 사용자를 동적으로 검색하고 멘션하려면 `User.Read.All`(Application) 권한을 추가하고 관리자 동의를 부여하세요. ## 알려진 제한 사항 -### 웹훅 시간 초과 +### Webhook 시간 초과 -Teams는 HTTP 웹훅을 통해 메시지를 전달합니다. 처리가 너무 오래 걸리면(예: 느린 LLM 응답) 다음이 발생할 수 있습니다. +Teams는 HTTP webhook을 통해 메시지를 전달합니다. 처리에 너무 오래 걸리면(예: 느린 LLM 응답) 다음이 발생할 수 있습니다: -- 게이트웨이 시간 초과 -- Teams가 메시지를 재시도함(중복 발생) -- 응답 누락 +- Gateway 시간 초과 +- Teams의 메시지 재시도(중복 발생) +- 답장 누락 -OpenClaw는 빠르게 응답을 반환하고 적극적으로 답장을 보내 이 문제를 처리하지만, 응답이 매우 느리면 여전히 문제가 발생할 수 있습니다. +OpenClaw는 빠르게 응답을 반환하고 능동적으로 답장을 전송하는 방식으로 이를 처리하지만, 응답이 매우 느리면 여전히 문제가 발생할 수 있습니다. ### 서식 -Teams 마크다운은 Slack이나 Discord보다 제한적입니다. +Teams markdown은 Slack 또는 Discord보다 더 제한적입니다: -- 기본 서식은 작동합니다: **굵게**, _기울임_, `code`, 링크 -- 복잡한 마크다운(표, 중첩 목록)은 올바르게 렌더링되지 않을 수 있습니다 -- Polls 및 임의 카드 전송에는 Adaptive Cards가 지원됩니다(아래 참조) +- 기본 서식은 동작합니다: **bold**, _italic_, `code`, 링크 +- 복잡한 markdown(테이블, 중첩 목록)은 올바르게 렌더링되지 않을 수 있습니다. +- Polls 및 임의 카드 전송에는 Adaptive Cards가 지원됩니다(아래 참조). ## 구성 주요 설정(공유 채널 패턴은 `/gateway/configuration` 참조): - `channels.msteams.enabled`: 채널 활성화/비활성화. -- `channels.msteams.appId`, `channels.msteams.appPassword`, `channels.msteams.tenantId`: 봇 자격 증명. -- `channels.msteams.webhook.port` (기본값 `3978`) -- `channels.msteams.webhook.path` (기본값 `/api/messages`) -- `channels.msteams.dmPolicy`: `pairing | allowlist | open | disabled` (기본값: pairing) -- `channels.msteams.allowFrom`: DM 허용 목록(AAD object ID 권장). Graph 액세스를 사용할 수 있을 때 마법사가 설정 중 이름을 ID로 확인합니다. -- `channels.msteams.dangerouslyAllowNameMatching`: 변경 가능한 UPN/표시 이름 일치 및 직접 팀/채널 이름 라우팅을 다시 활성화하는 비상 토글. +- `channels.msteams.appId`, `channels.msteams.appPassword`, `channels.msteams.tenantId`: bot 자격 증명. +- `channels.msteams.webhook.port`(기본값 `3978`) +- `channels.msteams.webhook.path`(기본값 `/api/messages`) +- `channels.msteams.dmPolicy`: `pairing | allowlist | open | disabled`(기본값: pairing) +- `channels.msteams.allowFrom`: DM allowlist(AAD 객체 ID 권장). Graph 액세스를 사용할 수 있으면 마법사가 설정 중 이름을 ID로 확인합니다. +- `channels.msteams.dangerouslyAllowNameMatching`: 변경 가능한 UPN/표시 이름 매칭과 직접적인 팀/채널 이름 라우팅을 다시 활성화하는 비상용 토글. - `channels.msteams.textChunkLimit`: 아웃바운드 텍스트 청크 크기. -- `channels.msteams.chunkMode`: `length`(기본값) 또는 `newline`으로, 길이 기준 청킹 전에 빈 줄(문단 경계)에서 분할합니다. -- `channels.msteams.mediaAllowHosts`: 인바운드 첨부파일 호스트 허용 목록(기본값은 Microsoft/Teams 도메인). -- `channels.msteams.mediaAuthAllowHosts`: 미디어 재시도 시 Authorization 헤더를 붙일 호스트 허용 목록(기본값은 Graph + Bot Framework 호스트). -- `channels.msteams.requireMention`: 채널/그룹에서 @멘션 필요 여부(기본값 true). -- `channels.msteams.replyStyle`: `thread | top-level`([응답 스타일](#reply-style-threads-vs-posts) 참조). +- `channels.msteams.chunkMode`: 길이 기반 청크 분할 전에 빈 줄(문단 경계)을 기준으로 분할하는 `length`(기본값) 또는 `newline`. +- `channels.msteams.mediaAllowHosts`: 인바운드 첨부 파일 호스트용 allowlist(기본값은 Microsoft/Teams 도메인). +- `channels.msteams.mediaAuthAllowHosts`: 미디어 재시도 시 Authorization 헤더를 첨부할 호스트용 allowlist(기본값은 Graph + Bot Framework 호스트). +- `channels.msteams.requireMention`: 채널/그룹에서 @mention 필요 여부(기본값 true). +- `channels.msteams.replyStyle`: `thread | top-level`([답장 스타일](#reply-style-threads-vs-posts) 참조). - `channels.msteams.teams..replyStyle`: 팀별 재정의. - `channels.msteams.teams..requireMention`: 팀별 재정의. -- `channels.msteams.teams..tools`: 채널 재정의가 없을 때 사용하는 기본 팀별 도구 정책 재정의(`allow`/`deny`/`alsoAllow`). -- `channels.msteams.teams..toolsBySender`: 기본 팀별 발신자별 도구 정책 재정의(`"*"` 와일드카드 지원). +- `channels.msteams.teams..tools`: 채널 재정의가 없을 때 사용되는 팀별 기본 도구 정책 재정의(`allow`/`deny`/`alsoAllow`). +- `channels.msteams.teams..toolsBySender`: 팀별 기본 발신자별 도구 정책 재정의(`"*"` 와일드카드 지원). - `channels.msteams.teams..channels..replyStyle`: 채널별 재정의. - `channels.msteams.teams..channels..requireMention`: 채널별 재정의. - `channels.msteams.teams..channels..tools`: 채널별 도구 정책 재정의(`allow`/`deny`/`alsoAllow`). - `channels.msteams.teams..channels..toolsBySender`: 채널별 발신자별 도구 정책 재정의(`"*"` 와일드카드 지원). -- `toolsBySender` 키는 명시적 접두사를 사용해야 합니다. - `id:`, `e164:`, `username:`, `name:` (기존의 접두사 없는 키는 여전히 `id:`로만 매핑됨). -- `channels.msteams.actions.memberInfo`: Graph 기반 멤버 정보 작업 활성화/비활성화(기본값: Graph 자격 증명을 사용할 수 있으면 활성화). -- `channels.msteams.sharePointSiteId`: 그룹 채팅/채널의 파일 업로드용 SharePoint site ID([그룹 채팅에서 파일 보내기](#sending-files-in-group-chats) 참조). +- `toolsBySender` 키는 명시적 접두사를 사용해야 합니다: + `id:`, `e164:`, `username:`, `name:`(기존의 접두사 없는 키도 여전히 `id:`에만 매핑됨). +- `channels.msteams.actions.memberInfo`: Graph 기반 멤버 정보 작업의 활성화/비활성화(기본값: Graph 자격 증명을 사용할 수 있으면 활성화). +- `channels.msteams.authType`: 인증 유형 — `"secret"`(기본값) 또는 `"federated"`. +- `channels.msteams.certificatePath`: PEM 인증서 파일 경로(federated + 인증서 인증). +- `channels.msteams.certificateThumbprint`: 인증서 지문(선택 사항, 인증에 필수는 아님). +- `channels.msteams.useManagedIdentity`: managed identity 인증 활성화(federated 모드). +- `channels.msteams.managedIdentityClientId`: 사용자 할당 managed identity용 클라이언트 ID. +- `channels.msteams.sharePointSiteId`: 그룹 채팅/채널에서 파일 업로드용 SharePoint 사이트 ID([그룹 채팅에서 파일 보내기](#sending-files-in-group-chats) 참조). ## 라우팅 및 세션 -- 세션 키는 표준 에이전트 형식을 따릅니다([/concepts/session](/concepts/session) 참조). +- 세션 키는 표준 에이전트 형식을 따릅니다([/concepts/session](/ko/concepts/session) 참조): - 다이렉트 메시지는 기본 세션을 공유합니다(`agent::`). - - 채널/그룹 메시지는 conversation id를 사용합니다. + - 채널/그룹 메시지는 대화 ID를 사용합니다: - `agent::msteams:channel:` - `agent::msteams:group:` -## 응답 스타일: 스레드 vs 게시물 +## 답장 스타일: 스레드 vs 게시물 -Teams는 최근 동일한 기본 데이터 모델 위에서 두 가지 채널 UI 스타일을 도입했습니다. +Teams는 최근 동일한 기본 데이터 모델 위에 두 가지 채널 UI 스타일을 도입했습니다: -| Style | Description | 권장 `replyStyle` | +| 스타일 | 설명 | 권장 `replyStyle` | | ------------------------ | --------------------------------------------------------- | ------------------------ | -| **Posts** (클래식) | 메시지가 카드로 표시되고 그 아래에 스레드 응답이 달림 | `thread` (기본값) | -| **Threads** (Slack 유사) | 메시지가 더 Slack처럼 선형으로 흐름 | `top-level` | +| **Posts**(클래식) | 메시지가 카드로 표시되고 그 아래에 스레드 답장이 달림 | `thread`(기본값) | +| **Threads**(Slack 유사) | 메시지가 Slack처럼 선형으로 흐름 | `top-level` | -**문제:** Teams API는 채널이 어떤 UI 스타일을 사용하는지 노출하지 않습니다. 잘못된 `replyStyle`을 사용하면 다음과 같습니다. +**문제:** Teams API는 채널이 어떤 UI 스타일을 사용하는지 노출하지 않습니다. 잘못된 `replyStyle`을 사용하면 다음과 같습니다: -- Threads 스타일 채널에서 `thread` 사용 → 응답이 어색하게 중첩되어 표시됨 -- Posts 스타일 채널에서 `top-level` 사용 → 응답이 스레드 내부가 아니라 별도 최상위 게시물로 표시됨 +- Threads 스타일 채널에서 `thread` 사용 → 답장이 어색하게 중첩되어 표시됨 +- Posts 스타일 채널에서 `top-level` 사용 → 답장이 스레드 내부가 아니라 별도의 최상위 게시물로 표시됨 -**해결책:** 채널이 어떻게 설정되어 있는지에 따라 채널별로 `replyStyle`을 구성하세요. +**해결 방법:** 채널 설정 방식에 따라 채널별로 `replyStyle`을 구성합니다: ```json5 { @@ -544,44 +696,44 @@ Teams는 최근 동일한 기본 데이터 모델 위에서 두 가지 채널 UI } ``` -## 첨부파일 및 이미지 +## 첨부 파일 및 이미지 **현재 제한 사항:** -- **DM:** Teams 봇 파일 API를 통해 이미지와 파일 첨부가 동작합니다. -- **채널/그룹:** 첨부파일은 M365 스토리지(SharePoint/OneDrive)에 저장됩니다. 웹훅 payload에는 실제 파일 바이트가 아닌 HTML stub만 포함됩니다. 채널 첨부파일을 다운로드하려면 **Graph API 권한이 필요합니다**. -- 명시적 파일 우선 전송에는 `media` / `filePath` / `path`와 함께 `action=upload-file`을 사용하세요. 선택적 `message`는 함께 전송되는 텍스트/주석이 되며, `filename`은 업로드 이름을 재정의합니다. +- **DM:** Teams bot 파일 API를 통해 이미지 및 파일 첨부가 동작합니다. +- **채널/그룹:** 첨부 파일은 M365 스토리지(SharePoint/OneDrive)에 저장됩니다. webhook 페이로드에는 실제 파일 바이트가 아니라 HTML 스텁만 포함됩니다. 채널 첨부 파일을 다운로드하려면 **Graph API 권한이 필요합니다**. +- 명시적인 파일 우선 전송에는 `action=upload-file`과 `media` / `filePath` / `path`를 사용하세요. 선택 사항인 `message`는 함께 보내는 텍스트/코멘트가 되며, `filename`은 업로드된 이름을 재정의합니다. -Graph 권한이 없으면 이미지가 포함된 채널 메시지는 텍스트 전용으로 수신됩니다(이미지 콘텐츠에는 봇이 접근할 수 없음). +Graph 권한이 없으면, 이미지가 포함된 채널 메시지는 텍스트 전용으로 수신됩니다(이미지 콘텐츠는 bot이 액세스할 수 없음). 기본적으로 OpenClaw는 Microsoft/Teams 호스트명에서만 미디어를 다운로드합니다. `channels.msteams.mediaAllowHosts`로 재정의하세요(모든 호스트를 허용하려면 `["*"]` 사용). -Authorization 헤더는 `channels.msteams.mediaAuthAllowHosts`에 포함된 호스트에만 첨부됩니다(기본값은 Graph + Bot Framework 호스트). 이 목록은 엄격하게 유지하세요(멀티 테넌트 접미사는 피함). +Authorization 헤더는 `channels.msteams.mediaAuthAllowHosts`에 포함된 호스트에만 첨부됩니다(기본값은 Graph + Bot Framework 호스트). 이 목록은 엄격하게 유지하세요(멀티테넌트 접미사는 피하세요). ## 그룹 채팅에서 파일 보내기 -봇은 DM에서 FileConsentCard 흐름(기본 제공)을 사용해 파일을 보낼 수 있습니다. 그러나 **그룹 채팅/채널에서 파일 보내기**에는 추가 설정이 필요합니다. +bot은 FileConsentCard 흐름(내장됨)을 사용해 DM에서 파일을 보낼 수 있습니다. 하지만 **그룹 채팅/채널에서 파일 보내기**에는 추가 설정이 필요합니다: -| Context | 파일 전송 방식 | 필요한 설정 | +| 컨텍스트 | 파일 전송 방식 | 필요한 설정 | | ------------------------ | -------------------------------------------- | ----------------------------------------------- | -| **DM** | FileConsentCard → 사용자가 수락 → 봇이 업로드 | 기본적으로 동작 | -| **그룹 채팅/채널** | SharePoint에 업로드 → 링크 공유 | `sharePointSiteId` + Graph 권한 필요 | -| **이미지(모든 컨텍스트)** | Base64 인라인 인코딩 | 기본적으로 동작 | +| **DM** | FileConsentCard → 사용자가 수락 → bot 업로드 | 별도 설정 없이 동작 | +| **그룹 채팅/채널** | SharePoint에 업로드 → 링크 공유 | `sharePointSiteId` + Graph 권한 필요 | +| **이미지(모든 컨텍스트)** | Base64 인코딩 인라인 | 별도 설정 없이 동작 | ### 그룹 채팅에 SharePoint가 필요한 이유 -봇에는 개인 OneDrive 드라이브가 없습니다(`/me/drive` Graph API 엔드포인트는 애플리케이션 ID에서 동작하지 않음). 그룹 채팅/채널로 파일을 보내려면 봇이 **SharePoint 사이트**에 업로드하고 공유 링크를 생성해야 합니다. +bot에는 개인 OneDrive 드라이브가 없습니다(애플리케이션 ID에는 `/me/drive` Graph API 엔드포인트가 동작하지 않음). 그룹 채팅/채널에서 파일을 보내려면 bot이 **SharePoint 사이트**에 업로드하고 공유 링크를 만들어야 합니다. ### 설정 -1. Entra ID (Azure AD) → App Registration에서 **Graph API 권한**을 추가합니다. +1. Entra ID(Azure AD) → App Registration에서 **Graph API 권한**을 추가합니다: - `Sites.ReadWrite.All` (Application) - SharePoint에 파일 업로드 - `Chat.Read.All` (Application) - 선택 사항, 사용자별 공유 링크 활성화 -2. 테넌트에 대해 **관리자 동의**를 부여합니다. +2. 테넌트에 대해 **관리자 동의 부여**를 수행합니다. -3. **SharePoint site ID 가져오기:** +3. **SharePoint 사이트 ID 가져오기:** ```bash - # Graph Explorer 또는 유효한 토큰이 포함된 curl 사용: + # Graph Explorer 또는 유효한 토큰을 포함한 curl 사용: curl -H "Authorization: Bearer $TOKEN" \ "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}" @@ -598,7 +750,7 @@ Authorization 헤더는 `channels.msteams.mediaAuthAllowHosts`에 포함된 호 { channels: { msteams: { - // ... other config ... + // ... 기타 구성 ... sharePointSiteId: "contoso.sharepoint.com,guid1,guid2", }, }, @@ -607,38 +759,38 @@ Authorization 헤더는 `channels.msteams.mediaAuthAllowHosts`에 포함된 호 ### 공유 동작 -| Permission | 공유 동작 | +| 권한 | 공유 동작 | | --------------------------------------- | --------------------------------------------------------- | -| `Sites.ReadWrite.All`만 | 조직 전체 공유 링크(조직 내 누구나 접근 가능) | -| `Sites.ReadWrite.All` + `Chat.Read.All` | 사용자별 공유 링크(채팅 멤버만 접근 가능) | +| `Sites.ReadWrite.All`만 | 조직 전체 공유 링크(조직 내 누구나 액세스 가능) | +| `Sites.ReadWrite.All` + `Chat.Read.All` | 사용자별 공유 링크(채팅 구성원만 액세스 가능) | -사용자별 공유는 채팅 참여자만 파일에 접근할 수 있으므로 더 안전합니다. `Chat.Read.All` 권한이 없으면 봇은 조직 전체 공유로 대체합니다. +사용자별 공유가 더 안전합니다. 채팅 참여자만 파일에 액세스할 수 있기 때문입니다. `Chat.Read.All` 권한이 없으면 bot은 조직 전체 공유로 대체합니다. ### 대체 동작 -| Scenario | 결과 | +| 시나리오 | 결과 | | ------------------------------------------------- | -------------------------------------------------- | -| 그룹 채팅 + 파일 + `sharePointSiteId` 구성됨 | SharePoint에 업로드, 공유 링크 전송 | -| 그룹 채팅 + 파일 + `sharePointSiteId` 없음 | OneDrive 업로드 시도(실패 가능), 텍스트만 전송 | -| 개인 채팅 + 파일 | FileConsentCard 흐름(SharePoint 없이 동작) | -| 모든 컨텍스트 + 이미지 | Base64 인라인 인코딩(SharePoint 없이 동작) | +| 그룹 채팅 + 파일 + `sharePointSiteId` 구성됨 | SharePoint에 업로드하고 공유 링크 전송 | +| 그룹 채팅 + 파일 + `sharePointSiteId` 없음 | OneDrive 업로드 시도(실패할 수 있음), 텍스트만 전송 | +| 개인 채팅 + 파일 | FileConsentCard 흐름(`SharePoint` 없이 동작) | +| 모든 컨텍스트 + 이미지 | Base64 인코딩 인라인(`SharePoint` 없이 동작) | ### 파일 저장 위치 업로드된 파일은 구성된 SharePoint 사이트의 기본 문서 라이브러리 내 `/OpenClawShared/` 폴더에 저장됩니다. -## Polls (Adaptive Cards) +## Polls(Adaptive Cards) -OpenClaw는 Teams Polls를 Adaptive Cards로 보냅니다(Teams에는 기본 Poll API가 없음). +OpenClaw는 Teams polls를 Adaptive Cards로 전송합니다(Teams에는 네이티브 poll API가 없음). - CLI: `openclaw message poll --channel msteams --target conversation: ...` -- 투표는 게이트웨이가 `~/.openclaw/msteams-polls.json`에 기록합니다. -- 투표 기록을 위해 게이트웨이는 계속 온라인 상태여야 합니다. +- 투표는 gateway가 `~/.openclaw/msteams-polls.json`에 기록합니다. +- 투표를 기록하려면 gateway가 계속 온라인 상태여야 합니다. - Polls는 아직 결과 요약을 자동 게시하지 않습니다(필요하면 저장 파일을 확인하세요). ## Adaptive Cards(임의) -`message` 도구 또는 CLI를 사용해 임의의 Adaptive Card JSON을 Teams 사용자나 대화에 보낼 수 있습니다. +`message` 도구 또는 CLI를 사용해 모든 Adaptive Card JSON을 Teams 사용자 또는 대화에 보낼 수 있습니다. `card` 매개변수는 Adaptive Card JSON 객체를 받습니다. `card`가 제공되면 메시지 텍스트는 선택 사항입니다. @@ -665,18 +817,18 @@ openclaw message send --channel msteams \ --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}' ``` -카드 스키마와 예시는 [Adaptive Cards documentation](https://adaptivecards.io/)을 참조하세요. 대상 형식 세부 정보는 아래 [대상 형식](#target-formats)을 참조하세요. +카드 스키마와 예시는 [Adaptive Cards documentation](https://adaptivecards.io/)를 참조하세요. 대상 형식에 대한 자세한 내용은 아래 [대상 형식](#target-formats)을 참조하세요. ## 대상 형식 -MSTeams 대상은 사용자와 대화를 구분하기 위해 접두사를 사용합니다. +MSTeams 대상은 사용자와 대화를 구분하기 위해 접두사를 사용합니다: -| Target type | Format | Example | +| 대상 유형 | 형식 | 예시 | | ------------------- | -------------------------------- | --------------------------------------------------- | -| 사용자(ID 기준) | `user:` | `user:40a1a0ed-4ff2-4164-a219-55518990c197` | -| 사용자(이름 기준) | `user:` | `user:John Smith` (Graph API 필요) | -| 그룹/채널 | `conversation:` | `conversation:19:abc123...@thread.tacv2` | -| 그룹/채널(raw) | `` | `19:abc123...@thread.tacv2` (`@thread`가 포함된 경우) | +| 사용자(ID 기준) | `user:` | `user:40a1a0ed-4ff2-4164-a219-55518990c197` | +| 사용자(이름 기준) | `user:` | `user:John Smith`(Graph API 필요) | +| 그룹/채널 | `conversation:` | `conversation:19:abc123...@thread.tacv2` | +| 그룹/채널(원시) | `` | `19:abc123...@thread.tacv2`(`@thread`가 포함된 경우) | **CLI 예시:** @@ -687,7 +839,7 @@ openclaw message send --channel msteams --target "user:40a1a0ed-..." --message " # 표시 이름으로 사용자에게 전송(Graph API 조회 트리거) openclaw message send --channel msteams --target "user:John Smith" --message "Hello" -# 그룹 채팅 또는 채널로 전송 +# 그룹 채팅 또는 채널에 전송 openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello" # 대화에 Adaptive Card 전송 @@ -719,23 +871,23 @@ openclaw message send --channel msteams --target "conversation:19:abc...@thread. } ``` -참고: `user:` 접두사가 없으면 이름은 기본적으로 그룹/팀 확인으로 처리됩니다. 표시 이름으로 사람을 지정할 때는 항상 `user:`를 사용하세요. +참고: `user:` 접두사가 없으면 이름은 기본적으로 그룹/팀 확인 대상으로 처리됩니다. 표시 이름으로 사람을 지정할 때는 항상 `user:`를 사용하세요. -## Proactive messaging +## 능동적 메시지 전송 -- Proactive 메시지는 사용자가 상호작용한 **이후에만** 가능합니다. 그 시점에 대화 참조를 저장하기 때문입니다. -- `dmPolicy`와 허용 목록 게이팅은 `/gateway/configuration`을 참조하세요. +- 능동적 메시지는 사용자가 상호작용한 **이후에만** 가능합니다. 그 시점에 대화 참조를 저장하기 때문입니다. +- `dmPolicy` 및 allowlist 게이트는 `/gateway/configuration`을 참조하세요. ## 팀 및 채널 ID(흔한 함정) -Teams URL의 `groupId` 쿼리 매개변수는 구성에 사용하는 팀 ID가 **아닙니다**. 대신 URL 경로에서 ID를 추출하세요. +Teams URL의 `groupId` 쿼리 매개변수는 구성에 사용하는 팀 ID가 **아닙니다**. 대신 URL 경로에서 ID를 추출하세요: **팀 URL:** ``` https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=... └────────────────────────────┘ - 팀 ID(URL 디코딩 필요) + 팀 ID(이를 URL 디코딩) ``` **채널 URL:** @@ -743,10 +895,10 @@ https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?gro ``` https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=... └─────────────────────────┘ - 채널 ID(URL 디코딩 필요) + 채널 ID(이를 URL 디코딩) ``` -**config용:** +**구성용:** - 팀 ID = `/team/` 뒤의 경로 세그먼트(URL 디코딩됨, 예: `19:Bk4j...@thread.tacv2`) - 채널 ID = `/channel/` 뒤의 경로 세그먼트(URL 디코딩됨) @@ -754,44 +906,44 @@ https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?gr ## 비공개 채널 -봇은 비공개 채널에서 제한적으로 지원됩니다. +bot은 비공개 채널에서 지원이 제한적입니다: -| Feature | Standard Channels | Private Channels | +| 기능 | 표준 채널 | 비공개 채널 | | ---------------------------- | ----------------- | ---------------------- | -| 봇 설치 | 예 | 제한적 | -| 실시간 메시지(웹훅) | 예 | 동작하지 않을 수 있음 | -| RSC 권한 | 예 | 다르게 동작할 수 있음 | -| @mentions | 예 | 봇에 접근 가능할 경우 | -| Graph API 기록 | 예 | 예(권한 필요) | +| Bot 설치 | 예 | 제한적 | +| 실시간 메시지(webhook) | 예 | 동작하지 않을 수 있음 | +| RSC 권한 | 예 | 다르게 동작할 수 있음 | +| @mentions | 예 | bot에 접근 가능하면 가능 | +| Graph API 기록 | 예 | 예(권한 필요) | -**비공개 채널이 동작하지 않을 때의 우회 방법:** +**비공개 채널에서 동작하지 않을 때의 해결 방법:** -1. 봇 상호작용에는 표준 채널 사용 -2. DM 사용 - 사용자는 항상 봇에 직접 메시지를 보낼 수 있음 +1. bot 상호작용에는 표준 채널을 사용 +2. DM 사용 - 사용자는 언제든 bot에 직접 메시지를 보낼 수 있음 3. 과거 접근에는 Graph API 사용(`ChannelMessage.Read.All` 필요) ## 문제 해결 ### 일반적인 문제 -- **채널에 이미지가 표시되지 않음:** Graph 권한 또는 관리자 동의가 누락되었습니다. Teams 앱을 재설치하고 Teams를 완전히 종료 후 다시 여세요. -- **채널에서 응답 없음:** 기본적으로 멘션이 필요합니다. `channels.msteams.requireMention=false`를 설정하거나 팀/채널별로 구성하세요. -- **버전 불일치(Teams에 이전 manifest가 계속 표시됨):** 앱을 제거 후 다시 추가하고 Teams를 완전히 종료해 새로고침하세요. -- **웹훅에서 401 Unauthorized:** Azure JWT 없이 수동 테스트할 때는 정상입니다. 엔드포인트에 도달했지만 인증에 실패했다는 뜻입니다. 올바른 테스트에는 Azure Web Chat을 사용하세요. +- **채널에서 이미지가 표시되지 않음:** Graph 권한 또는 관리자 동의가 없습니다. Teams 앱을 다시 설치하고 Teams를 완전히 종료한 뒤 다시 여세요. +- **채널에서 응답이 없음:** 기본적으로 멘션이 필요합니다. `channels.msteams.requireMention=false`로 설정하거나 팀/채널별로 구성하세요. +- **버전 불일치(Teams에 여전히 이전 manifest가 표시됨):** 앱을 제거 후 다시 추가하고 Teams를 완전히 종료해 새로고침하세요. +- **webhook에서 401 Unauthorized:** Azure JWT 없이 수동 테스트할 때는 정상입니다. 엔드포인트에 도달했지만 인증에 실패했다는 뜻입니다. 올바른 테스트에는 Azure Web Chat을 사용하세요. ### Manifest 업로드 오류 -- **"Icon file cannot be empty":** manifest가 참조하는 아이콘 파일이 0바이트입니다. 유효한 PNG 아이콘을 만드세요(`outline.png`는 32x32, `color.png`는 192x192). -- **"webApplicationInfo.Id already in use":** 앱이 다른 팀/채팅에 아직 설치되어 있습니다. 먼저 찾아 제거하거나 전파를 위해 5~10분 기다리세요. -- **업로드 시 "Something went wrong":** 대신 [https://admin.teams.microsoft.com](https://admin.teams.microsoft.com)을 통해 업로드하고, 브라우저 DevTools(F12) → Network 탭에서 실제 응답 본문 오류를 확인하세요. -- **사이드로드 실패:** "Upload a custom app" 대신 "Upload an app to your org's app catalog"를 시도하세요. 이 방식이 사이드로드 제한을 우회하는 경우가 많습니다. +- **"Icon file cannot be empty":** manifest가 0바이트인 아이콘 파일을 참조합니다. 유효한 PNG 아이콘을 만드세요(`outline.png`는 32x32, `color.png`는 192x192). +- **"webApplicationInfo.Id already in use":** 앱이 다른 팀/채팅에 아직 설치되어 있습니다. 먼저 찾아서 제거하거나 전파가 완료될 때까지 5-10분 기다리세요. +- **업로드 시 "Something went wrong":** 대신 [https://admin.teams.microsoft.com](https://admin.teams.microsoft.com)을 통해 업로드하고, 브라우저 DevTools(F12) → Network 탭을 열어 실제 오류가 포함된 응답 본문을 확인하세요. +- **사이드로드 실패:** "Upload a custom app" 대신 "Upload an app to your org's app catalog"를 시도하세요. 이 방법이 사이드로드 제한을 우회하는 경우가 많습니다. -### RSC 권한이 작동하지 않음 +### RSC 권한이 동작하지 않음 -1. `webApplicationInfo.id`가 봇의 App ID와 정확히 일치하는지 확인하세요 -2. 앱을 다시 업로드하고 팀/채팅에 재설치하세요 -3. 조직 관리자가 RSC 권한을 차단했는지 확인하세요 -4. 올바른 범위를 사용 중인지 확인하세요: 팀에는 `ChannelMessage.Read.Group`, 그룹 채팅에는 `ChatMessage.Read.Chat` +1. `webApplicationInfo.id`가 봇의 App ID와 정확히 일치하는지 확인 +2. 앱을 다시 업로드하고 팀/채팅에 다시 설치 +3. 조직 관리자가 RSC 권한을 차단했는지 확인 +4. 올바른 범위를 사용 중인지 확인: 팀은 `ChannelMessage.Read.Group`, 그룹 채팅은 `ChatMessage.Read.Chat` ## 참고 자료 @@ -803,10 +955,10 @@ https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?gr - [Teams bot file handling](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4) (채널/그룹에는 Graph 필요) - [Proactive messaging](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages) -## 관련 +## 관련 항목 -- [Channels Overview](/channels) — 지원되는 모든 채널 -- [Pairing](/channels/pairing) — DM 인증 및 pairing 흐름 -- [Groups](/channels/groups) — 그룹 채팅 동작 및 멘션 게이팅 -- [Channel Routing](/channels/channel-routing) — 메시지 세션 라우팅 -- [Security](/gateway/security) — 액세스 모델 및 보안 강화 +- [Channels Overview](/ko/channels) — 지원되는 모든 채널 +- [Pairing](/ko/channels/pairing) — DM 인증 및 페어링 흐름 +- [Groups](/ko/channels/groups) — 그룹 채팅 동작 및 멘션 게이트 +- [Channel Routing](/ko/channels/channel-routing) — 메시지용 세션 라우팅 +- [Security](/ko/gateway/security) — 액세스 모델 및 강화 방법 diff --git a/docs/ko/plugins/sdk-agent-harness.md b/docs/ko/plugins/sdk-agent-harness.md index a3f0594da..365727584 100644 --- a/docs/ko/plugins/sdk-agent-harness.md +++ b/docs/ko/plugins/sdk-agent-harness.md @@ -1,53 +1,53 @@ --- read_when: - - 임베디드 에이전트 런타임 또는 하니스 레지스트리를 변경하고 있습니다 - - 번들되었거나 신뢰할 수 있는 플러그인에서 에이전트 하니스를 등록하고 있습니다 - - Codex 플러그인이 모델 제공자와 어떻게 연결되는지 이해해야 합니다 + - 내장 에이전트 런타임 또는 하네스 레지스트리를 변경하고 있습니다 + - 번들되었거나 신뢰할 수 있는 플러그인에서 에이전트 하네스를 등록하고 있습니다 + - Codex 플러그인이 모델 제공자와 어떤 관련이 있는지 이해해야 합니다 sidebarTitle: Agent Harness -summary: 저수준 임베디드 에이전트 실행기를 대체하는 플러그인을 위한 실험적 SDK 표면 -title: 에이전트 하니스 플러그인 +summary: 낮은 수준의 내장 에이전트 실행기를 대체하는 플러그인을 위한 실험적 SDK 표면 +title: 에이전트 하네스 플러그인 x-i18n: - generated_at: "2026-04-11T02:46:14Z" + generated_at: "2026-04-12T00:18:56Z" model: gpt-5.4 provider: openai - source_hash: 43c1f2c087230398b0162ed98449f239c8db1e822e51c7dcd40c54fa6c3374e1 + source_hash: 62b88fd24ce8b600179db27e16e8d764a2cd7a14e5c5df76374c33121aa5e365 source_path: plugins/sdk-agent-harness.md workflow: 15 --- -# 에이전트 하니스 플러그인 +# 에이전트 하네스 플러그인 -**에이전트 하니스**는 준비된 OpenClaw 에이전트 턴 하나를 실행하는 저수준 실행기입니다. 이것은 모델 제공자도, 채널도, 도구 레지스트리도 아닙니다. +**에이전트 하네스**는 준비된 OpenClaw 에이전트 턴 하나를 위한 낮은 수준의 실행기입니다. 이는 모델 제공자도, 채널도, 도구 레지스트리도 아닙니다. -이 표면은 번들되었거나 신뢰할 수 있는 네이티브 플러그인에만 사용하세요. 매개변수 타입이 의도적으로 현재 임베디드 러너를 반영하기 때문에, 이 계약은 아직 실험적입니다. +이 표면은 번들되었거나 신뢰할 수 있는 네이티브 플러그인에만 사용하세요. 이 계약은 매개변수 타입이 의도적으로 현재 내장 러너를 그대로 반영하므로 아직 실험적입니다. -## 하니스를 사용해야 하는 경우 +## 하네스를 사용하는 경우 -모델 계열이 자체 네이티브 세션 런타임을 갖고 있고, 일반적인 OpenClaw 제공자 전송이 잘못된 추상화일 때 에이전트 하니스를 등록하세요. +모델 계열이 자체 네이티브 세션 런타임을 가지고 있고 일반적인 OpenClaw 제공자 전송이 잘못된 추상화일 때 에이전트 하네스를 등록하세요. 예시: -- 스레드와 compaction을 자체적으로 관리하는 네이티브 코딩 에이전트 서버 +- 스레드와 compaction을 직접 관리하는 네이티브 코딩 에이전트 서버 - 네이티브 plan/reasoning/tool 이벤트를 스트리밍해야 하는 로컬 CLI 또는 데몬 -- OpenClaw 세션 transcript 외에 자체 resume id가 필요한 모델 런타임 +- 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)을 빌드하세요. -## 여전히 core가 담당하는 것 +## 코어가 계속 소유하는 것 -하니스가 선택되기 전에 OpenClaw는 이미 다음을 결정했습니다. +하네스가 선택되기 전에 OpenClaw는 이미 다음을 해석합니다: -- provider와 model +- 제공자와 모델 - 런타임 인증 상태 -- thinking level과 컨텍스트 예산 +- thinking level과 context budget - OpenClaw transcript/session 파일 - workspace, sandbox, 도구 정책 - 채널 응답 콜백과 스트리밍 콜백 -- 모델 폴백 및 live model switching 정책 +- 모델 폴백과 라이브 모델 전환 정책 -이 분리는 의도된 것입니다. 하니스는 준비된 시도를 실행할 뿐이며, 제공자를 선택하거나, 채널 전달을 대체하거나, 모델을 몰래 전환하지 않습니다. +이 분리는 의도된 것입니다. 하네스는 준비된 시도를 실행할 뿐이며, 제공자를 선택하거나, 채널 전달을 대체하거나, 모델을 조용히 전환하지 않습니다. -## 하니스 등록 +## 하네스 등록 **가져오기:** `openclaw/plugin-sdk/agent-harness` @@ -57,7 +57,7 @@ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; const myHarness: AgentHarness = { id: "my-harness", - label: "내 네이티브 에이전트 하니스", + label: "My native agent harness", supports(ctx) { return ctx.provider === "my-provider" @@ -66,9 +66,9 @@ const myHarness: AgentHarness = { }, async runAttempt(params) { - // 네이티브 스레드를 시작하거나 재개합니다. - // params.prompt, params.tools, params.images, params.onPartialReply, - // params.onAgentEvent 및 기타 준비된 시도 필드를 사용하세요. + // Start or resume your native thread. + // Use params.prompt, params.tools, params.images, params.onPartialReply, + // params.onAgentEvent, and the other prepared attempt fields. return await runMyNativeTurn(params); }, }; @@ -76,7 +76,7 @@ const myHarness: AgentHarness = { export default definePluginEntry({ id: "my-native-agent", name: "My Native Agent", - description: "선택한 모델을 네이티브 에이전트 데몬을 통해 실행합니다.", + description: "Runs selected models through a native agent daemon.", register(api) { api.registerAgentHarness(myHarness); }, @@ -85,43 +85,51 @@ export default definePluginEntry({ ## 선택 정책 -OpenClaw는 provider/model을 결정한 뒤 하니스를 선택합니다. +OpenClaw는 제공자/모델 해석 후 하네스를 선택합니다: -1. `OPENCLAW_AGENT_RUNTIME=`는 해당 id의 등록된 하니스를 강제합니다. -2. `OPENCLAW_AGENT_RUNTIME=pi`는 내장 PI 하니스를 강제합니다. -3. `OPENCLAW_AGENT_RUNTIME=auto`는 등록된 하니스에, 결정된 provider/model을 지원하는지 묻습니다. -4. 일치하는 등록된 하니스가 없으면, PI 폴백이 비활성화되지 않은 한 OpenClaw는 PI를 사용합니다. +1. `OPENCLAW_AGENT_RUNTIME=`는 해당 id를 가진 등록된 하네스를 강제합니다. +2. `OPENCLAW_AGENT_RUNTIME=pi`는 내장 PI 하네스를 강제합니다. +3. `OPENCLAW_AGENT_RUNTIME=auto`는 등록된 하네스에 해석된 제공자/모델을 지원하는지 묻습니다. +4. 등록된 하네스가 일치하지 않으면, PI 폴백이 비활성화되지 않은 한 OpenClaw는 PI를 사용합니다. -강제된 플러그인 하니스 실패는 실행 실패로 드러납니다. `auto` 모드에서는 선택된 플러그인 하니스가 턴의 부작용을 만들기 전에 실패하면 OpenClaw가 PI로 폴백할 수 있습니다. 대신 그 폴백을 즉시 실패로 처리하려면 `OPENCLAW_AGENT_HARNESS_FALLBACK=none` 또는 `embeddedHarness.fallback: "none"`을 설정하세요. +강제된 플러그인 하네스 실패는 실행 실패로 표시됩니다. `auto` 모드에서는 선택된 플러그인 하네스가 턴이 부작용을 만들기 전에 실패하면 OpenClaw가 PI로 폴백할 수 있습니다. 대신 그 폴백을 하드 실패로 만들려면 `OPENCLAW_AGENT_HARNESS_FALLBACK=none` 또는 `embeddedHarness.fallback: "none"`을 설정하세요. -번들된 Codex 플러그인은 `codex`를 하니스 id로 등록합니다. Core는 이를 일반적인 플러그인 하니스 id로 취급합니다. Codex 전용 별칭은 공유 런타임 선택기가 아니라 플러그인 또는 운영자 config에 속해야 합니다. +번들된 Codex 플러그인은 `codex`를 하네스 id로 등록합니다. 코어는 이를 일반적인 플러그인 하네스 id로 취급합니다. Codex 전용 별칭은 공유 런타임 선택기가 아니라 플러그인 또는 운영자 설정에 속해야 합니다. -## provider와 harness의 페어링 +## 제공자와 하네스 페어링 -대부분의 하니스는 provider도 함께 등록해야 합니다. provider는 모델 ref, 인증 상태, 모델 메타데이터, `/model` 선택을 OpenClaw의 나머지 부분에 노출합니다. 그런 다음 하니스는 `supports(...)`에서 해당 provider를 주장합니다. +대부분의 하네스는 제공자도 함께 등록해야 합니다. 제공자는 모델 ref, 인증 상태, 모델 메타데이터, `/model` 선택을 OpenClaw의 나머지 부분에서 볼 수 있게 합니다. 그런 다음 하네스는 `supports(...)`에서 해당 제공자를 claim합니다. -번들된 Codex 플러그인은 이 패턴을 따릅니다. +번들된 Codex 플러그인은 이 패턴을 따릅니다: - 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 app server가 반환하는 다른 모델 - harness id: `codex` -- auth: 합성 provider 가용성, Codex 하니스가 네이티브 Codex 로그인/세션을 관리하기 때문 -- app-server 요청: OpenClaw는 Codex에 순수 모델 id를 보내고, 하니스가 네이티브 app-server 프로토콜과 통신하게 합니다. +- auth: 합성 제공자 가용성. Codex 하네스가 네이티브 Codex 로그인/세션을 소유하기 때문입니다 +- app-server request: OpenClaw는 bare model 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 플러그인은 추가적입니다. 일반 `openai/gpt-*` ref는 계속 OpenAI provider ref로 남으며 일반 OpenClaw provider 경로를 계속 사용합니다. Codex 관리 인증, Codex 모델 검색, 네이티브 스레드, Codex app-server 실행을 원할 때는 `codex/gpt-*`를 선택하세요. `/model`은 OpenAI provider 자격 증명이 없어도 Codex app server가 반환한 Codex 모델들 사이를 전환할 수 있습니다. -운영자 설정, 모델 접두사 예시, Codex 전용 config는 -[Codex Harness](/ko/plugins/codex-harness)를 참조하세요. +운영자 설정, 모델 접두사 예시, Codex 전용 구성은 [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 플러그인은 app-server initialize 핸드셰이크를 검사하고 더 오래되었거나 버전이 없는 서버를 차단하여 OpenClaw가 테스트된 프로토콜 표면에 대해서만 실행되도록 합니다. + +### 네이티브 Codex 하네스 모드 + +번들된 `codex` 하네스는 내장 OpenClaw 에이전트 턴을 위한 네이티브 Codex 모드입니다. 먼저 번들된 `codex` 플러그인을 활성화하고, 구성이 제한적인 allowlist를 사용한다면 `plugins.allow`에 `codex`를 포함하세요. 이것은 `openai-codex/*`와 다릅니다: + +- `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"`을 사용하세요. ## PI 폴백 비활성화 -기본적으로 OpenClaw는 임베디드 에이전트를 `agents.defaults.embeddedHarness`가 `{ runtime: "auto", fallback: "pi" }`로 설정된 상태로 실행합니다. `auto` 모드에서 등록된 플러그인 하니스는 provider/model 쌍을 주장할 수 있습니다. 일치하는 것이 없거나, 자동 선택된 플러그인 하니스가 출력을 만들기 전에 실패하면 OpenClaw는 PI로 폴백합니다. +기본적으로 OpenClaw는 `agents.defaults.embeddedHarness`를 `{ runtime: "auto", fallback: "pi" }`로 설정하여 내장 에이전트를 실행합니다. `auto` 모드에서 등록된 플러그인 하네스는 제공자/모델 쌍을 claim할 수 있습니다. 일치하는 것이 없거나 자동 선택된 플러그인 하네스가 출력을 만들기 전에 실패하면 OpenClaw는 PI로 폴백합니다. -플러그인 하니스만 실행되고 있음을 증명해야 할 때는 `fallback: "none"`을 설정하세요. 이렇게 하면 자동 PI 폴백이 비활성화되지만, 명시적인 `runtime: "pi"` 또는 `OPENCLAW_AGENT_RUNTIME=pi`까지 막지는 않습니다. +플러그인 하네스가 유일하게 실행되는 런타임임을 증명해야 할 때는 `fallback: "none"`을 설정하세요. 이렇게 하면 자동 PI 폴백이 비활성화됩니다. 명시적인 `runtime: "pi"` 또는 `OPENCLAW_AGENT_RUNTIME=pi`는 차단하지 않습니다. -Codex 전용 임베디드 실행의 경우: +Codex 전용 내장 실행의 경우: ```json { @@ -137,7 +145,7 @@ Codex 전용 임베디드 실행의 경우: } ``` -등록된 어떤 플러그인 하니스든 일치하는 모델을 주장할 수 있게 하되, OpenClaw가 절대로 조용히 PI로 폴백하지 않게 하려면 `runtime: "auto"`를 유지하고 폴백을 비활성화하세요. +등록된 어떤 플러그인 하네스라도 일치하는 모델을 claim하게 하되 OpenClaw가 절대로 조용히 PI로 폴백하지 않게 하려면 `runtime: "auto"`를 유지하고 폴백을 비활성화하세요: ```json { @@ -152,7 +160,7 @@ Codex 전용 임베디드 실행의 경우: } ``` -에이전트별 재정의도 같은 형태를 사용합니다. +에이전트별 재정의도 같은 형태를 사용합니다: ```json { @@ -177,7 +185,7 @@ Codex 전용 임베디드 실행의 경우: } ``` -`OPENCLAW_AGENT_RUNTIME`는 여전히 구성된 런타임을 재정의합니다. 환경에서 PI 폴백을 비활성화하려면 `OPENCLAW_AGENT_HARNESS_FALLBACK=none`을 사용하세요. +`OPENCLAW_AGENT_RUNTIME`는 여전히 구성된 runtime보다 우선합니다. 환경에서 PI 폴백을 비활성화하려면 `OPENCLAW_AGENT_HARNESS_FALLBACK=none`을 사용하세요. ```bash OPENCLAW_AGENT_RUNTIME=codex \ @@ -185,39 +193,39 @@ OPENCLAW_AGENT_HARNESS_FALLBACK=none \ openclaw gateway run ``` -폴백이 비활성화되면, 요청된 하니스가 등록되지 않았거나, 결정된 provider/model을 지원하지 않거나, 턴의 부작용을 만들기 전에 실패할 경우 세션이 초기에 실패합니다. 이는 Codex 전용 배포와 Codex app-server 경로가 실제로 사용 중임을 증명해야 하는 live test를 위한 의도된 동작입니다. +폴백이 비활성화되면 요청된 하네스가 등록되지 않았거나, 해석된 제공자/모델을 지원하지 않거나, 턴 부작용을 만들기 전에 실패할 때 세션은 초기에 실패합니다. 이는 Codex 전용 배포와 Codex app-server 경로가 실제로 사용 중임을 증명해야 하는 라이브 테스트를 위한 의도된 동작입니다. -이 설정은 임베디드 에이전트 하니스만 제어합니다. image, video, music, TTS, PDF 또는 기타 provider별 모델 라우팅은 비활성화하지 않습니다. +이 설정은 내장 에이전트 하네스만 제어합니다. 이미지, 비디오, 음악, TTS, PDF 또는 다른 제공자별 모델 라우팅은 비활성화하지 않습니다. -## 네이티브 세션과 transcript 미러링 +## 네이티브 세션과 transcript mirror -하니스는 네이티브 session id, thread id 또는 데몬 측 resume token을 유지할 수 있습니다. 이 바인딩을 OpenClaw 세션과 명시적으로 연결된 상태로 유지하고, 사용자에게 보이는 assistant/tool 출력을 OpenClaw transcript에도 계속 미러링하세요. +하네스는 네이티브 session id, thread id 또는 데몬 측 resume token을 유지할 수 있습니다. 그 바인딩을 OpenClaw 세션과 명시적으로 연결해 두고, 사용자에게 보이는 assistant/tool 출력을 OpenClaw transcript에 계속 미러링하세요. -OpenClaw transcript는 다음을 위한 호환성 계층으로 남아 있습니다. +OpenClaw transcript는 다음을 위한 호환성 계층으로 남아 있습니다: -- 채널에 보이는 세션 기록 +- 채널에 표시되는 세션 기록 - transcript 검색 및 인덱싱 -- 이후 턴에서 내장 PI 하니스로 다시 전환 -- 일반적인 `/new`, `/reset`, 세션 삭제 동작 +- 이후 턴에서 내장 PI 하네스로 다시 전환 +- 일반 `/new`, `/reset`, 세션 삭제 동작 -하니스가 사이드카 바인딩을 저장한다면, 소유한 OpenClaw 세션이 재설정될 때 이를 지울 수 있도록 `reset(...)`을 구현하세요. +하네스가 사이드카 바인딩을 저장한다면 소유한 OpenClaw 세션이 재설정될 때 OpenClaw가 이를 지울 수 있도록 `reset(...)`을 구현하세요. ## 도구 및 미디어 결과 -Core는 OpenClaw 도구 목록을 구성하고 이를 준비된 시도에 전달합니다. 하니스가 동적 도구 호출을 실행할 때는, 채널 미디어를 직접 보내는 대신 하니스 결과 형태를 통해 도구 결과를 반환하세요. +코어는 OpenClaw 도구 목록을 구성하고 이를 준비된 시도에 전달합니다. 하네스가 동적 도구 호출을 실행할 때는 채널 미디어를 직접 보내는 대신 하네스 결과 형태를 통해 도구 결과를 반환하세요. -이렇게 하면 텍스트, image, video, music, TTS, 승인, 메시징 도구 출력이 PI 기반 실행과 동일한 전달 경로를 유지합니다. +이렇게 하면 텍스트, 이미지, 비디오, 음악, TTS, 승인, 메시징 도구 출력이 PI 기반 실행과 동일한 전달 경로를 유지합니다. ## 현재 제한 사항 -- 공개 import 경로는 일반적이지만, 일부 시도/결과 타입 별칭은 호환성을 위해 여전히 `Pi` 이름을 사용합니다. -- 서드파티 하니스 설치는 실험적입니다. 네이티브 세션 런타임이 꼭 필요해질 때까지는 provider plugin을 우선 사용하세요. -- 턴 간 하니스 전환은 지원됩니다. 네이티브 도구, 승인, assistant 텍스트 또는 메시지 전송이 시작된 뒤 턴 중간에 하니스를 전환하지 마세요. +- 공개 import 경로는 일반적이지만, 일부 attempt/result 타입 별칭은 호환성을 위해 여전히 `Pi` 이름을 사용합니다. +- 서드파티 하네스 설치는 실험적입니다. 네이티브 세션 런타임이 필요해질 때까지는 provider plugin을 우선 사용하세요. +- 턴 간 하네스 전환은 지원됩니다. 네이티브 도구, 승인, assistant 텍스트 또는 메시지 전송이 시작된 뒤에는 턴 중간에 하네스를 전환하지 마세요. -## 관련 문서 +## 관련 항목 - [SDK 개요](/ko/plugins/sdk-overview) - [런타임 헬퍼](/ko/plugins/sdk-runtime) -- [Provider Plugins](/ko/plugins/sdk-provider-plugins) +- [제공자 플러그인](/ko/plugins/sdk-provider-plugins) - [Codex Harness](/ko/plugins/codex-harness) - [모델 제공자](/ko/concepts/model-providers) diff --git a/docs/ko/providers/openai.md b/docs/ko/providers/openai.md index 1db0c419b..933244e30 100644 --- a/docs/ko/providers/openai.md +++ b/docs/ko/providers/openai.md @@ -1,39 +1,37 @@ --- read_when: - - OpenClaw에서 OpenAI 모델을 사용하려는 경우 - - API 키 대신 Codex 구독 인증을 사용하려는 경우 -summary: OpenClaw에서 API 키 또는 Codex 구독으로 OpenAI 사용 + - OpenClaw에서 OpenAI 모델을 사용하려고 합니다 + - API 키 대신 Codex 구독 인증을 사용하려고 합니다 + - 더 엄격한 GPT-5 에이전트 실행 동작이 필요합니다 +summary: OpenClaw에서 API 키 또는 Codex 구독을 사용해 OpenAI를 이용하세요 title: OpenAI x-i18n: - generated_at: "2026-04-07T06:01:33Z" + generated_at: "2026-04-12T00:19:00Z" model: gpt-5.4 provider: openai - source_hash: 6a2ce1ce5f085fe55ec50b8d20359180b9002c9730820cd5b0e011c3bf807b64 + source_hash: 7aa06fba9ac901e663685a6b26443a2f6aeb6ec3589d939522dc87cbb43497b4 source_path: providers/openai.md workflow: 15 --- # OpenAI -OpenAI는 GPT 모델용 개발자 API를 제공합니다. Codex는 구독 기반 액세스를 위한 **ChatGPT 로그인** 또는 사용량 기반 액세스를 위한 **API 키** 로그인을 지원합니다. Codex cloud에는 ChatGPT 로그인이 필요합니다. -OpenAI는 OpenClaw와 같은 외부 도구/워크플로에서의 구독 OAuth 사용을 명시적으로 지원합니다. +OpenAI는 GPT 모델용 개발자 API를 제공합니다. Codex는 구독 기반 액세스를 위한 **ChatGPT sign-in** 또는 사용량 기반 액세스를 위한 **API key** sign-in을 지원합니다. Codex cloud는 ChatGPT sign-in이 필요합니다. +OpenAI는 OpenClaw 같은 외부 도구/워크플로에서 구독 OAuth 사용을 명시적으로 지원합니다. ## 기본 상호작용 스타일 -OpenClaw는 `openai/*` 및 -`openai-codex/*` 실행 모두에 대해 OpenAI 전용 프롬프트 오버레이를 소량 추가할 수 있습니다. 기본적으로 이 오버레이는 기본 OpenClaw 시스템 프롬프트를 대체하지 않으면서, -어시스턴트가 따뜻하고, -협업적이며, 간결하고, 직접적이고, 약간 더 감정 표현이 풍부하도록 -유지합니다. 이 친화적 오버레이는 전체 -출력을 간결하게 유지하면서, 자연스럽게 어울릴 때 가끔 이모지도 허용합니다. +OpenClaw는 `openai/*` 및 `openai-codex/*` 실행 모두에 대해 작은 OpenAI 전용 프롬프트 오버레이를 추가할 수 있습니다. 기본적으로 이 오버레이는 기본 OpenClaw 시스템 프롬프트를 대체하지 않으면서도 어시스턴트를 따뜻하고, +협력적이며, 간결하고, 직접적이고, 감정 표현이 약간 더 풍부하게 유지합니다. 이 친화적 오버레이는 +전체 출력은 간결하게 유지하면서 자연스럽게 어울릴 때 가끔 이모지도 허용합니다. 구성 키: `plugins.entries.openai.config.personality` -허용 값: +허용되는 값: -- `"friendly"`: 기본값, OpenAI 전용 오버레이를 활성화합니다. +- `"friendly"`: 기본값; OpenAI 전용 오버레이를 활성화합니다. - `"on"`: `"friendly"`의 별칭입니다. - `"off"`: 오버레이를 비활성화하고 기본 OpenClaw 프롬프트만 사용합니다. @@ -43,8 +41,8 @@ OpenClaw는 `openai/*` 및 - `openai-codex/*` 모델에 적용됩니다. - 다른 provider에는 영향을 주지 않습니다. -이 동작은 기본적으로 활성화되어 있습니다. 향후 로컬 구성 변경이 있더라도 -이 설정을 유지하려면 `"friendly"`를 명시적으로 유지하세요. +이 동작은 기본적으로 활성화되어 있습니다. 향후 로컬 구성 변경에도 유지되도록 하려면 +`"friendly"`를 명시적으로 유지하세요: ```json5 { @@ -62,7 +60,7 @@ OpenClaw는 `openai/*` 및 ### OpenAI 프롬프트 오버레이 비활성화 -수정되지 않은 기본 OpenClaw 프롬프트를 원하면 오버레이를 `"off"`로 설정하세요. +수정되지 않은 기본 OpenClaw 프롬프트를 원한다면 오버레이를 `"off"`로 설정하세요: ```json5 { @@ -78,25 +76,25 @@ OpenClaw는 `openai/*` 및 } ``` -config CLI로 직접 설정할 수도 있습니다. +구성 CLI로 직접 설정할 수도 있습니다: ```bash openclaw config set plugins.entries.openai.config.personality off ``` -OpenClaw는 런타임에 이 설정을 대소문자를 구분하지 않고 정규화하므로, +OpenClaw는 런타임에 이 설정을 대소문자를 구분하지 않고 정규화하므로 `"Off"` 같은 값도 친화적 오버레이를 비활성화합니다. -## 옵션 A: OpenAI API 키 (OpenAI Platform) +## 옵션 A: OpenAI API key (OpenAI Platform) **가장 적합한 경우:** 직접 API 액세스 및 사용량 기반 과금. -OpenAI 대시보드에서 API 키를 가져오세요. +OpenAI 대시보드에서 API key를 받으세요. -라우트 요약: +경로 요약: -- `openai/gpt-5.4` = 직접 OpenAI Platform API 라우트 +- `openai/gpt-5.4` = 직접 OpenAI Platform API 경로 - `OPENAI_API_KEY`(또는 동등한 OpenAI provider 구성)가 필요합니다 -- OpenClaw에서 ChatGPT/Codex 로그인은 `openai/*`가 아니라 `openai-codex/*`를 통해 라우팅됩니다 +- OpenClaw에서 ChatGPT/Codex sign-in은 `openai/*`가 아니라 `openai-codex/*`를 통해 라우팅됩니다 ### CLI 설정 @@ -106,7 +104,7 @@ openclaw onboard --auth-choice openai-api-key openclaw onboard --openai-api-key "$OPENAI_API_KEY" ``` -### 구성 스니펫 +### 구성 예시 ```json5 { @@ -115,25 +113,24 @@ openclaw onboard --openai-api-key "$OPENAI_API_KEY" } ``` -OpenAI의 현재 API 모델 문서는 직접 -OpenAI API 사용을 위해 `gpt-5.4` 및 `gpt-5.4-pro`를 나열합니다. OpenClaw는 둘 다 `openai/*` Responses 경로를 통해 전달합니다. -OpenClaw는 오래된 `openai/gpt-5.3-codex-spark` 항목을 의도적으로 숨깁니다. -직접 OpenAI API 호출이 실제 트래픽에서 이를 거부하기 때문입니다. +OpenAI의 현재 API 모델 문서는 직접 OpenAI API 사용을 위해 `gpt-5.4` 및 `gpt-5.4-pro`를 나열합니다. +OpenClaw는 둘 다 `openai/*` Responses 경로를 통해 전달합니다. +OpenClaw는 오래된 `openai/gpt-5.3-codex-spark` 항목을 의도적으로 숨기는데, +이는 직접 OpenAI API 호출에서 실제 트래픽 기준으로 거부되기 때문입니다. -OpenClaw는 직접 OpenAI -API 경로에서 `openai/gpt-5.3-codex-spark`를 노출하지 않습니다. `pi-ai`는 여전히 해당 모델에 대한 기본 제공 항목을 포함하지만, 실제 OpenAI API -요청은 현재 이를 거부합니다. OpenClaw에서는 Spark를 Codex 전용으로 취급합니다. +OpenClaw는 직접 OpenAI API 경로에서 `openai/gpt-5.3-codex-spark`를 **노출하지 않습니다**. +`pi-ai`는 여전히 해당 모델에 대한 기본 제공 항목을 포함하지만, 실제 OpenAI API +요청은 현재 이를 거부합니다. Spark는 OpenClaw에서 Codex 전용으로 처리됩니다. ## 이미지 생성 -번들된 `openai` plugin은 공유 -`image_generate` 도구를 통해 이미지 생성도 등록합니다. +번들된 `openai` plugin은 공유 `image_generate` 도구를 통해 이미지 생성도 등록합니다. - 기본 이미지 모델: `openai/gpt-image-1` - 생성: 요청당 최대 4개 이미지 - 편집 모드: 활성화됨, 최대 5개의 참조 이미지 - `size` 지원 -- 현재 OpenAI 전용 주의사항: OpenClaw는 현재 `aspectRatio` 또는 +- 현재 OpenAI 전용 주의 사항: OpenClaw는 현재 `aspectRatio` 또는 `resolution` 재정의를 OpenAI Images API로 전달하지 않습니다 OpenAI를 기본 이미지 provider로 사용하려면: @@ -150,20 +147,19 @@ OpenAI를 기본 이미지 provider로 사용하려면: } ``` -공유 도구 -매개변수, provider 선택, 장애 조치 동작은 [이미지 생성](/ko/tools/image-generation)을 참고하세요. +공유 도구 매개변수, +provider 선택, failover 동작은 [Image Generation](/ko/tools/image-generation)을 참조하세요. ## 비디오 생성 -번들된 `openai` plugin은 공유 -`video_generate` 도구를 통해 비디오 생성도 등록합니다. +번들된 `openai` plugin은 공유 `video_generate` 도구를 통해 비디오 생성도 등록합니다. - 기본 비디오 모델: `openai/sora-2` -- 모드: 텍스트-투-비디오, 이미지-투-비디오, 단일 비디오 참조/편집 흐름 -- 현재 제한: 이미지 1개 또는 비디오 참조 입력 1개 -- 현재 OpenAI 전용 주의사항: OpenClaw는 현재 네이티브 OpenAI 비디오 생성을 위해 `size` - 재정의만 전달합니다. `aspectRatio`, `resolution`, `audio`, `watermark`와 같은 지원되지 않는 선택적 재정의는 무시되며 - 도구 경고로 다시 보고됩니다. +- 모드: 텍스트-비디오, 이미지-비디오, 단일 비디오 참조/편집 흐름 +- 현재 제한: 참조 입력으로 이미지 1개 또는 비디오 1개 +- 현재 OpenAI 전용 주의 사항: OpenClaw는 현재 기본 OpenAI 비디오 생성에 대해 `size` + 재정의만 전달합니다. `aspectRatio`, `resolution`, `audio`, `watermark` 같은 + 지원되지 않는 선택적 재정의는 무시되며 도구 경고로 다시 보고됩니다. OpenAI를 기본 비디오 provider로 사용하려면: @@ -179,18 +175,18 @@ OpenAI를 기본 비디오 provider로 사용하려면: } ``` -공유 도구 -매개변수, provider 선택, 장애 조치 동작은 [비디오 생성](/ko/tools/video-generation)을 참고하세요. +공유 도구 매개변수, +provider 선택, failover 동작은 [Video Generation](/ko/tools/video-generation)을 참조하세요. ## 옵션 B: OpenAI Code (Codex) 구독 -**가장 적합한 경우:** API 키 대신 ChatGPT/Codex 구독 액세스를 사용하는 경우. -Codex cloud에는 ChatGPT 로그인이 필요하며, Codex CLI는 ChatGPT 또는 API 키 로그인을 지원합니다. +**가장 적합한 경우:** API key 대신 ChatGPT/Codex 구독 액세스를 사용하는 경우. +Codex cloud는 ChatGPT sign-in이 필요하고, Codex CLI는 ChatGPT 또는 API key sign-in을 지원합니다. -라우트 요약: +경로 요약: -- `openai-codex/gpt-5.4` = ChatGPT/Codex OAuth 라우트 -- 직접 OpenAI Platform API 키가 아니라 ChatGPT/Codex 로그인을 사용합니다 +- `openai-codex/gpt-5.4` = ChatGPT/Codex OAuth 경로 +- 직접 OpenAI Platform API key가 아니라 ChatGPT/Codex sign-in을 사용합니다 - `openai-codex/*`의 provider 측 제한은 ChatGPT 웹/앱 경험과 다를 수 있습니다 ### CLI 설정 (Codex OAuth) @@ -199,11 +195,11 @@ Codex cloud에는 ChatGPT 로그인이 필요하며, Codex CLI는 ChatGPT 또는 # 마법사에서 Codex OAuth 실행 openclaw onboard --auth-choice openai-codex -# 또는 OAuth를 직접 실행 +# 또는 OAuth 직접 실행 openclaw models auth login --provider openai-codex ``` -### 구성 스니펫 (Codex 구독) +### 구성 예시 (Codex 구독) ```json5 { @@ -212,43 +208,41 @@ openclaw models auth login --provider openai-codex ``` OpenAI의 현재 Codex 문서는 현재 Codex 모델로 `gpt-5.4`를 나열합니다. OpenClaw는 -ChatGPT/Codex OAuth 사용을 위해 이를 `openai-codex/gpt-5.4`에 매핑합니다. +이를 ChatGPT/Codex OAuth 사용을 위한 `openai-codex/gpt-5.4`에 매핑합니다. -이 경로는 `openai/gpt-5.4`와 의도적으로 분리되어 있습니다. 직접 -OpenAI Platform API 경로를 원하면 API 키와 함께 `openai/*`를 사용하세요. ChatGPT/Codex 로그인 -을 원하면 `openai-codex/*`를 사용하세요. +이 경로는 `openai/gpt-5.4`와 의도적으로 분리되어 있습니다. 직접 OpenAI Platform API 경로를 원하면 +API key와 함께 `openai/*`를 사용하세요. ChatGPT/Codex sign-in을 원하면 +`openai-codex/*`를 사용하세요. -온보딩이 기존 Codex CLI 로그인을 재사용하는 경우, 해당 자격 증명은 계속 -Codex CLI에서 관리됩니다. 만료되면 OpenClaw는 먼저 외부 Codex 소스를 다시 읽고, -provider가 이를 새로 고칠 수 있는 경우 별도의 OpenClaw 전용 -복사본에서 소유권을 가져오는 대신 새로 고친 자격 증명을 다시 Codex 저장소에 기록합니다. +온보딩이 기존 Codex CLI 로그인을 재사용하는 경우 해당 자격 증명은 +Codex CLI에서 계속 관리됩니다. 만료 시 OpenClaw는 먼저 외부 Codex 소스를 다시 읽고, +provider가 이를 갱신할 수 있으면 별도의 OpenClaw 전용 사본을 소유하는 대신 +갱신된 자격 증명을 다시 Codex 저장소에 기록합니다. -Codex Spark에 대한 권한이 있는 Codex 계정이라면 OpenClaw는 다음도 지원합니다. +Codex 계정에 Codex Spark 사용 권한이 있다면 OpenClaw는 다음도 지원합니다: - `openai-codex/gpt-5.3-codex-spark` OpenClaw는 Codex Spark를 Codex 전용으로 취급합니다. 직접 -`openai/gpt-5.3-codex-spark` API 키 경로는 노출하지 않습니다. +`openai/gpt-5.3-codex-spark` API-key 경로는 노출하지 않습니다. -OpenClaw는 `pi-ai`가 -`openai-codex/gpt-5.3-codex-spark`를 발견했을 때도 이를 유지합니다. 이를 권한 의존적이고 실험적인 것으로 취급하세요. Codex Spark는 -GPT-5.4 `/fast`와 별개이며, 사용 가능 여부는 로그인한 Codex / -ChatGPT 계정에 따라 달라집니다. +OpenClaw는 또한 `pi-ai`가 이를 발견할 때 `openai-codex/gpt-5.3-codex-spark`를 유지합니다. +이는 사용 권한 의존적이고 실험적인 것으로 취급하세요. Codex Spark는 GPT-5.4 `/fast`와는 +별개이며, 사용 가능 여부는 sign-in된 Codex / ChatGPT 계정에 따라 달라집니다. ### Codex 컨텍스트 창 상한 -OpenClaw는 Codex 모델 메타데이터와 런타임 컨텍스트 상한을 별도의 -값으로 취급합니다. +OpenClaw는 Codex 모델 메타데이터와 런타임 컨텍스트 상한을 별도의 값으로 취급합니다. `openai-codex/gpt-5.4`의 경우: -- 네이티브 `contextWindow`: `1050000` +- 기본 `contextWindow`: `1050000` - 기본 런타임 `contextTokens` 상한: `272000` -이렇게 하면 모델 메타데이터는 사실대로 유지하면서 실제로 더 나은 지연 시간과 품질 특성을 보이는 더 작은 기본 런타임 -창을 유지할 수 있습니다. +이렇게 하면 모델 메타데이터는 사실대로 유지하면서도 실제로 더 나은 지연 시간과 품질 특성을 가진 +더 작은 기본 런타임 창을 유지할 수 있습니다. -다른 유효 상한을 원하면 `models.providers..models[].contextTokens`를 설정하세요. +다른 유효 상한을 원하면 `models.providers..models[].contextTokens`를 설정하세요: ```json5 { @@ -267,49 +261,50 @@ OpenClaw는 Codex 모델 메타데이터와 런타임 컨텍스트 상한을 별 } ``` -네이티브 모델 -메타데이터를 선언하거나 재정의할 때만 `contextWindow`를 사용하세요. 런타임 컨텍스트 예산을 제한하려면 `contextTokens`를 사용하세요. +기본 모델 메타데이터를 선언하거나 재정의할 때만 `contextWindow`를 사용하세요. +런타임 컨텍스트 예산을 제한하려면 `contextTokens`를 사용하세요. -### 기본 전송 방식 +### 전송 기본값 OpenClaw는 모델 스트리밍에 `pi-ai`를 사용합니다. `openai/*`와 -`openai-codex/*` 모두에서 기본 전송 방식은 `"auto"`입니다(먼저 WebSocket, 이후 SSE -대체). +`openai-codex/*` 모두에서 기본 전송은 `"auto"`입니다(우선 WebSocket, 이후 SSE +fallback). -`"auto"` 모드에서 OpenClaw는 SSE로 대체하기 전에 -초기 단계의 재시도 가능한 WebSocket 실패도 한 번 재시도합니다. 강제 `"websocket"` 모드는 여전히 대체 뒤에 숨기지 않고 전송 오류를 직접 표시합니다. +`"auto"` 모드에서 OpenClaw는 SSE로 fallback하기 전에 초기의 재시도 가능한 +WebSocket 실패 1회를 추가로 재시도합니다. 강제 `"websocket"` 모드는 여전히 +fallback 뒤로 숨기지 않고 전송 오류를 직접 노출합니다. -`"auto"` 모드에서 연결 또는 초기 턴 WebSocket 실패가 발생한 후 OpenClaw는 +`"auto"` 모드에서 연결 실패 또는 초기 턴 WebSocket 실패 후 OpenClaw는 약 60초 동안 해당 세션의 WebSocket 경로를 성능 저하 상태로 표시하고, -전송 방식 사이를 반복 전환하는 대신 냉각 시간 동안 이후 턴을 SSE로 전송합니다. +전송 방식 사이를 반복적으로 오가는 대신 쿨다운 동안 후속 턴을 SSE로 보냅니다. -네이티브 OpenAI 계열 엔드포인트(`openai/*`, `openai-codex/*`, 그리고 Azure +기본 OpenAI 계열 엔드포인트(`openai/*`, `openai-codex/*`, 및 Azure OpenAI Responses)의 경우 OpenClaw는 요청에 안정적인 세션 및 턴 식별 상태도 첨부하여 -재시도, 재연결, SSE 대체가 동일한 -대화 식별성에 맞춰 유지되도록 합니다. 네이티브 OpenAI 계열 라우트에서는 여기에 안정적인 -세션/턴 요청 식별 헤더와 일치하는 전송 메타데이터가 포함됩니다. +재시도, 재연결, SSE fallback이 동일한 대화 식별자에 맞춰 유지되도록 합니다. 기본 OpenAI 계열 경로에서는 +여기에 안정적인 세션/턴 요청 식별 헤더와 일치하는 전송 메타데이터가 포함됩니다. -OpenClaw는 또한 전송 방식 변형 전반에서 OpenAI 사용량 카운터를 -세션/상태 표시 영역에 도달하기 전에 정규화합니다. 네이티브 OpenAI/Codex Responses 트래픽은 +OpenClaw는 또한 OpenAI 사용량 카운터가 세션/상태 표면에 도달하기 전에 +전송 변형 전반에서 이를 정규화합니다. 기본 OpenAI/Codex Responses 트래픽은 사용량을 `input_tokens` / `output_tokens` 또는 -`prompt_tokens` / `completion_tokens`로 보고할 수 있습니다. OpenClaw는 이를 `/status`, `/usage`, 세션 로그에 대해 동일한 입력 -및 출력 카운터로 취급합니다. 네이티브 -WebSocket 트래픽에서 `total_tokens`가 누락되거나(`0`으로 보고되거나) 하면, OpenClaw는 -정규화된 입력 + 출력 합계로 대체하여 세션/상태 표시가 계속 채워지도록 합니다. +`prompt_tokens` / `completion_tokens`로 보고할 수 있으며, +OpenClaw는 이를 `/status`, `/usage`, 및 세션 로그에서 동일한 입력 및 +출력 카운터로 취급합니다. 기본 WebSocket 트래픽이 `total_tokens`를 생략하거나 +(`0`으로 보고하거나) 하는 경우 OpenClaw는 정규화된 입력 + 출력 합계를 사용해 +세션/상태 표시가 채워진 상태로 유지되도록 합니다. -`agents.defaults.models..params.transport`를 설정할 수 있습니다. +`agents.defaults.models..params.transport`를 설정할 수 있습니다: - `"sse"`: SSE 강제 사용 - `"websocket"`: WebSocket 강제 사용 -- `"auto"`: WebSocket을 시도한 뒤 SSE로 대체 +- `"auto"`: WebSocket을 시도한 다음 SSE로 fallback -`openai/*`(Responses API)의 경우 WebSocket 전송이 사용되면 OpenClaw는 -기본적으로 WebSocket 워밍업도 활성화합니다(`openaiWsWarmup: true`). +`openai/*`(Responses API)의 경우 OpenClaw는 WebSocket 전송 사용 시 +기본적으로 WebSocket warm-up도 활성화합니다(`openaiWsWarmup: true`). 관련 OpenAI 문서: -- [WebSocket을 사용한 Realtime API](https://platform.openai.com/docs/guides/realtime-websocket) -- [스트리밍 API 응답(SSE)](https://platform.openai.com/docs/guides/streaming-responses) +- [Realtime API with WebSocket](https://platform.openai.com/docs/guides/realtime-websocket) +- [Streaming API responses (SSE)](https://platform.openai.com/docs/guides/streaming-responses) ```json5 { @@ -328,12 +323,12 @@ WebSocket 트래픽에서 `total_tokens`가 누락되거나(`0`으로 보고되 } ``` -### OpenAI WebSocket 워밍업 +### OpenAI WebSocket warm-up -OpenAI 문서는 워밍업을 선택 사항으로 설명합니다. OpenClaw는 +OpenAI 문서는 warm-up을 선택 사항으로 설명합니다. OpenClaw는 WebSocket 전송 사용 시 첫 턴 지연 시간을 줄이기 위해 `openai/*`에 대해 기본적으로 이를 활성화합니다. -### 워밍업 비활성화 +### warm-up 비활성화 ```json5 { @@ -351,7 +346,7 @@ WebSocket 전송 사용 시 첫 턴 지연 시간을 줄이기 위해 `openai/*` } ``` -### 워밍업 명시적 활성화 +### warm-up 명시적으로 활성화 ```json5 { @@ -371,9 +366,9 @@ WebSocket 전송 사용 시 첫 턴 지연 시간을 줄이기 위해 `openai/*` ### OpenAI 및 Codex 우선 처리 -OpenAI의 API는 `service_tier=priority`를 통해 우선 처리를 노출합니다. OpenClaw에서는 -네이티브 OpenAI/Codex Responses 엔드포인트에서 이 필드를 전달하려면 `agents.defaults.models["/"].params.serviceTier` -를 설정하세요. +OpenAI의 API는 `service_tier=priority`를 통해 우선 처리를 노출합니다. +OpenClaw에서는 `agents.defaults.models["/"].params.serviceTier` +를 설정하여 기본 OpenAI/Codex Responses 엔드포인트에서 해당 필드를 전달합니다. ```json5 { @@ -399,35 +394,35 @@ OpenAI의 API는 `service_tier=priority`를 통해 우선 처리를 노출합니 지원되는 값은 `auto`, `default`, `flex`, `priority`입니다. OpenClaw는 `params.serviceTier`를 직접 `openai/*` Responses -요청과 `openai-codex/*` Codex Responses 요청 모두에 전달합니다. 해당 모델이 -네이티브 OpenAI/Codex 엔드포인트를 가리킬 때 적용됩니다. +요청과 `openai-codex/*` Codex Responses 요청 모두에 전달합니다. 단, 해당 모델이 +기본 OpenAI/Codex 엔드포인트를 가리키는 경우에만 해당합니다. 중요한 동작: -- 직접 `openai/*`는 `api.openai.com`을 대상으로 해야 합니다 -- `openai-codex/*`는 `chatgpt.com/backend-api`를 대상으로 해야 합니다 -- 다른 기본 URL 또는 프록시를 통해 두 provider 중 하나를 라우팅하면, OpenClaw는 `service_tier`를 그대로 둡니다 +- 직접 `openai/*`는 `api.openai.com`을 대상이어야 합니다 +- `openai-codex/*`는 `chatgpt.com/backend-api`를 대상이어야 합니다 +- 둘 중 어느 provider든 다른 base URL 또는 프록시를 통해 라우팅하면 OpenClaw는 `service_tier`를 그대로 둡니다 -### OpenAI fast 모드 +### OpenAI fast mode -OpenClaw는 `openai/*`와 -`openai-codex/*` 세션 모두에 대해 공유 fast-mode 토글을 노출합니다. +OpenClaw는 `openai/*` 및 +`openai-codex/*` 세션 모두에 대해 공유 fast-mode 토글을 제공합니다: - Chat/UI: `/fast status|on|off` - 구성: `agents.defaults.models["/"].params.fastMode` -fast 모드가 활성화되면 OpenClaw는 이를 OpenAI 우선 처리로 매핑합니다. +fast mode가 활성화되면 OpenClaw는 이를 OpenAI 우선 처리로 매핑합니다: - `api.openai.com`으로 가는 직접 `openai/*` Responses 호출은 `service_tier = "priority"`를 전송합니다 - `chatgpt.com/backend-api`로 가는 `openai-codex/*` Responses 호출도 `service_tier = "priority"`를 전송합니다 - 기존 페이로드 `service_tier` 값은 유지됩니다 -- fast 모드는 `reasoning` 또는 `text.verbosity`를 재작성하지 않습니다 +- fast mode는 `reasoning` 또는 `text.verbosity`를 다시 쓰지 않습니다 -특히 GPT 5.4의 경우 가장 일반적인 설정은 다음과 같습니다. +GPT 5.4에 한정하면, 가장 일반적인 설정은 다음과 같습니다: -- `openai/gpt-5.4` 또는 `openai-codex/gpt-5.4`를 사용하는 세션에서 `/fast on` 전송 -- 또는 `agents.defaults.models["openai/gpt-5.4"].params.fastMode = true` 설정 -- Codex OAuth도 사용하는 경우 `agents.defaults.models["openai-codex/gpt-5.4"].params.fastMode = true`도 함께 설정 +- `openai/gpt-5.4` 또는 `openai-codex/gpt-5.4`를 사용하는 세션에서 `/fast on`을 전송합니다 +- 또는 `agents.defaults.models["openai/gpt-5.4"].params.fastMode = true`를 설정합니다 +- Codex OAuth도 함께 사용하는 경우 `agents.defaults.models["openai-codex/gpt-5.4"].params.fastMode = true`도 설정합니다 예시: @@ -453,45 +448,70 @@ fast 모드가 활성화되면 OpenClaw는 이를 OpenAI 우선 처리로 매핑 ``` 세션 재정의가 구성보다 우선합니다. Sessions UI에서 세션 재정의를 지우면 -세션은 구성된 기본값으로 돌아갑니다. +해당 세션은 구성된 기본값으로 돌아갑니다. -### 네이티브 OpenAI와 OpenAI 호환 라우트 비교 +### 기본 OpenAI 경로와 OpenAI-compatible 경로 비교 OpenClaw는 직접 OpenAI, Codex, Azure OpenAI 엔드포인트를 -일반적인 OpenAI 호환 `/v1` 프록시와 다르게 취급합니다. +일반적인 OpenAI-compatible `/v1` 프록시와 다르게 처리합니다: -- 네이티브 `openai/*`, `openai-codex/*`, Azure OpenAI 라우트는 - 사용자가 명시적으로 reasoning을 비활성화할 때 `reasoning: { effort: "none" }`를 그대로 유지합니다 -- 네이티브 OpenAI 계열 라우트는 도구 스키마를 기본적으로 strict 모드로 설정합니다 -- 숨겨진 OpenClaw attribution 헤더(`originator`, `version`, `User-Agent`)는 검증된 네이티브 OpenAI 호스트 - (`api.openai.com`) 및 네이티브 Codex 호스트(`chatgpt.com/backend-api`)에만 첨부됩니다 -- 네이티브 OpenAI/Codex 라우트는 - `service_tier`, Responses `store`, OpenAI reasoning 호환 페이로드, - 프롬프트 캐시 힌트와 같은 OpenAI 전용 요청 형성을 유지합니다 -- 프록시 스타일 OpenAI 호환 라우트는 더 느슨한 호환 동작을 유지하며 - strict 도구 스키마, 네이티브 전용 요청 형성, 숨겨진 - OpenAI/Codex attribution 헤더를 강제하지 않습니다 +- 기본 `openai/*`, `openai-codex/*`, Azure OpenAI 경로는 + reasoning을 명시적으로 비활성화했을 때 `reasoning: { effort: "none" }`를 그대로 유지합니다 +- 기본 OpenAI 계열 경로는 tool schema를 기본적으로 strict 모드로 설정합니다 +- 숨겨진 OpenClaw attribution header(`originator`, `version`, 및 + `User-Agent`)는 검증된 기본 OpenAI 호스트 + (`api.openai.com`) 및 기본 Codex 호스트 (`chatgpt.com/backend-api`)에만 첨부됩니다 +- 기본 OpenAI/Codex 경로는 `service_tier`, Responses `store`, OpenAI reasoning-compat payload, 및 + prompt-cache 힌트 같은 OpenAI 전용 요청 shaping을 유지합니다 +- 프록시 스타일 OpenAI-compatible 경로는 더 느슨한 compat 동작을 유지하며 + strict tool schema, 기본 전용 요청 shaping, 또는 숨겨진 + OpenAI/Codex attribution header를 강제하지 않습니다 -Azure OpenAI는 전송 및 호환 -동작 측면에서는 네이티브 라우팅 범주에 남아 있지만, 숨겨진 OpenAI/Codex attribution 헤더는 받지 않습니다. +Azure OpenAI는 전송 및 compat +동작 측면에서는 기본 라우팅 범주에 남아 있지만, 숨겨진 OpenAI/Codex attribution header는 받지 않습니다. -이렇게 하면 현재 네이티브 OpenAI Responses 동작을 유지하면서도, -오래된 OpenAI 호환 shim을 서드파티 `/v1` 백엔드에 강제하지 않습니다. +이렇게 하면 현재의 기본 OpenAI Responses 동작은 유지하면서 +오래된 OpenAI-compatible shim을 서드파티 `/v1` 백엔드에 강제하지 않습니다. -### OpenAI Responses 서버 측 압축 +### Strict-agentic GPT 모드 -직접 OpenAI Responses 모델(`api.openai.com`의 `api: "openai-responses"`를 사용하는 `openai/*`)의 경우 OpenClaw는 이제 OpenAI 서버 측 -압축 페이로드 힌트를 자동 활성화합니다. +`openai/*` 및 `openai-codex/*` GPT-5 계열 실행의 경우, OpenClaw는 +더 엄격한 내장 Pi 실행 계약을 사용할 수 있습니다: -- `store: true`를 강제합니다(`model compat`가 `supportsStore: false`를 설정하지 않는 한) +```json5 +{ + agents: { + defaults: { + embeddedPi: { + executionContract: "strict-agentic", + }, + }, + }, +} +``` + +`strict-agentic`에서는 구체적인 tool 작업이 가능한 경우 OpenClaw가 +더 이상 계획만 있는 어시스턴트 턴을 성공적인 진행으로 간주하지 않습니다. 대신 +즉시 행동하라는 steer와 함께 턴을 재시도하고, 상당한 작업에 대해서는 구조화된 `update_plan` tool을 자동 활성화하며, +모델이 계속 행동 없이 계획만 세우면 명시적인 차단 상태를 표시합니다. + +이 모드는 OpenAI 및 OpenAI Codex GPT-5 계열 실행에만 적용됩니다. 다른 provider와 +이전 모델 계열은 별도의 런타임 설정으로 명시적으로 opt-in하지 않는 한 기본 내장 Pi 동작을 유지합니다. + +### OpenAI Responses 서버 측 compaction + +직접 OpenAI Responses 모델(`api.openai.com`의 `baseUrl`과 함께 `api: "openai-responses"`를 사용하는 `openai/*`)의 경우, +OpenClaw는 이제 OpenAI 서버 측 compaction payload 힌트를 자동으로 활성화합니다: + +- `store: true`를 강제합니다(`model compat`이 `supportsStore: false`로 설정한 경우 제외) - `context_management: [{ type: "compaction", compact_threshold: ... }]`를 주입합니다 -기본적으로 `compact_threshold`는 모델 `contextWindow`의 `70%`입니다(없을 경우 `80000`). +기본적으로 `compact_threshold`는 모델 `contextWindow`의 `70%`이며(없으면 `80000` 사용), -### 서버 측 압축 명시적 활성화 +### 서버 측 compaction 명시적 활성화 -호환되는 -Responses 모델(예: Azure OpenAI Responses)에 `context_management` 주입을 강제하려는 경우 사용하세요. +호환 가능한 +Responses 모델(예: Azure OpenAI Responses)에 대해 `context_management` 주입을 강제로 사용하려면 다음을 사용하세요: ```json5 { @@ -528,7 +548,7 @@ Responses 모델(예: Azure OpenAI Responses)에 `context_management` 주입을 } ``` -### 서버 측 압축 비활성화 +### 서버 측 compaction 비활성화 ```json5 { @@ -547,10 +567,10 @@ Responses 모델(예: Azure OpenAI Responses)에 `context_management` 주입을 ``` `responsesServerCompaction`은 `context_management` 주입만 제어합니다. -직접 OpenAI Responses 모델은 `compat`가 +직접 OpenAI Responses 모델은 compat에서 `supportsStore: false`를 설정하지 않는 한 여전히 `store: true`를 강제합니다. ## 참고 -- 모델 ref는 항상 `provider/model`을 사용합니다([/concepts/models](/ko/concepts/models) 참고). +- 모델 ref는 항상 `provider/model`을 사용합니다([/concepts/models](/ko/concepts/models) 참조). - 인증 세부 정보 및 재사용 규칙은 [/concepts/oauth](/ko/concepts/oauth)에 있습니다.