콘텐츠로 이동

OpenClaw 설정 가이드: 채널 및 DM 정책 완벽 구성

각 채널은 해당 설정 섹션이 존재하면 자동으로 시작돼요 (enabled: false인 경우는 제외).

모든 채널은 DM 정책과 그룹 정책을 지원해요.

DM 정책동작
pairing (기본값)알 수 없는 발신자에게 일회용 페어링 코드를 전송하며, 소유자가 승인해야 해요.
allowlistallowFrom에 포함된 발신자(또는 페어링된 허용 저장소)만 허용해요.
open모든 인바운드 DM을 허용해요 (allowFrom: ["*"] 설정 필요).
disabled모든 인바운드 DM을 무시해요.
그룹 정책동작
allowlist (기본값)설정된 allowlist와 일치하는 그룹만 허용해요.
open그룹 allowlist를 우회해요 (mention-gating은 여전히 적용돼요).
disabled모든 그룹/방 메시지를 차단해요.

channels.modelByChannel을 사용하여 특정 채널 ID를 특정 모델에 고정할 수 있어요. 값은 provider/model 형식이나 설정된 모델 alias를 사용할 수 있어요. 이 채널 매핑은 세션에 모델 오버라이드(예: /model로 설정된 경우)가 없을 때 적용돼요.

{
channels: {
modelByChannel: {
discord: {
"123456789012345678": "anthropic/claude-opus-4-6",
},
slack: {
C1234567890: "openai/gpt-4.1",
},
telegram: {
"-1001234567890": "openai/gpt-4.1-mini",
"-1001234567890:topic:99": "anthropic/claude-sonnet-4-6",
},
},
},
}

여러 프로바이더에 걸쳐 공유되는 그룹 정책 및 heartbeat 동작을 위해 channels.defaults를 사용하세요.

{
channels: {
defaults: {
groupPolicy: "allowlist", // open | allowlist | disabled
heartbeat: {
showOk: false,
showAlerts: true,
useIndicator: true,
},
},
},
}
  • channels.defaults.groupPolicy: 프로바이더 레벨의 groupPolicy가 설정되지 않았을 때의 폴백 그룹 정책이에요.
  • channels.defaults.heartbeat.showOk: heartbeat 출력에 정상 상태인 채널 상태를 포함해요.
  • channels.defaults.heartbeat.showAlerts: heartbeat 출력에 성능 저하/에러 상태를 포함해요.
  • channels.defaults.heartbeat.useIndicator: 간결한 인디케이터 스타일로 heartbeat를 출력해요.

WhatsApp은 Gateway의 웹 채널(Baileys Web)을 통해 실행돼요. 연결된 세션이 있으면 자동으로 시작돼요.

{
channels: {
whatsapp: {
dmPolicy: "pairing", // pairing | allowlist | open | disabled
allowFrom: ["+15555550123", "+447700900123"],
textChunkLimit: 4000,
chunkMode: "length", // length | newline
mediaMaxMb: 50,
sendReadReceipts: true, // blue ticks (false in self-chat mode)
groups: {
"*": { requireMention: true },
},
groupPolicy: "allowlist",
groupAllowFrom: ["+15551234567"],
},
},
web: {
enabled: true,
heartbeatSeconds: 60,
reconnect: {
initialMs: 2000,
maxMs: 120000,
factor: 1.4,
jitter: 0.2,
maxAttempts: 0,
},
},
}

다중 계정 WhatsApp

{
channels: {
whatsapp: {
accounts: {
default: {},
personal: {},
biz: {
// authDir: "~/.openclaw/credentials/whatsapp/biz",
},
},
},
},
}
  • 아웃바운드 명령은 default 계정이 있으면 해당 계정을 기본으로 사용하며, 없으면 설정된 첫 번째 계정 ID(정렬 기준)를 사용해요.
  • 선택 사항인 channels.whatsapp.defaultAccount는 설정된 계정 ID와 일치할 때 해당 폴백 기본 계정 선택을 오버라이드해요.
  • 기존의 단일 계정 Baileys 인증 디렉토리는 openclaw doctor에 의해 whatsapp/default로 마이그레이션돼요.
  • 계정별 오버라이드: channels.whatsapp.accounts.<id>.sendReadReceipts, channels.whatsapp.accounts.<id>.dmPolicy, channels.whatsapp.accounts.<id>.allowFrom.
{
channels: {
telegram: {
enabled: true,
botToken: "your-bot-token",
dmPolicy: "pairing",
allowFrom: ["tg:123456789"],
groups: {
"*": { requireMention: true },
"-1001234567890": {
allowFrom: ["@admin"],
systemPrompt: "Keep answers brief.",
topics: {
"99": {
requireMention: false,
skills: ["search"],
systemPrompt: "Stay on topic.",
},
},
},
},
customCommands: [
{ command: "backup", description: "Git backup" },
{ command: "generate", description: "Create an image" },
],
historyLimit: 50,
replyToMode: "first", // off | first | all
linkPreview: true,
streaming: "partial", // off | partial | block | progress (default: off)
actions: { reactions: true, sendMessage: true },
reactionNotifications: "own", // off | own | all
mediaMaxMb: 100,
retry: {
attempts: 3,
minDelayMs: 400,
maxDelayMs: 30000,
jitter: 0.1,
},
network: {
autoSelectFamily: true,
dnsResultOrder: "ipv4first",
},
proxy: "socks5://localhost:9050",
webhookUrl: "https://example.com/telegram-webhook",
webhookSecret: "secret",
webhookPath: "/telegram-webhook",
},
},
}
  • Bot token: channels.telegram.botToken 또는 channels.telegram.tokenFile(일반 파일만 가능, 심볼릭 링크는 거부됨)을 사용하며, 기본 계정에 대해 TELEGRAM_BOT_TOKEN이 폴백으로 사용돼요.
  • 선택 사항인 channels.telegram.defaultAccount는 설정된 계정 ID와 일치할 때 기본 계정 선택을 오버라이드해요.
  • 다중 계정 설정(2개 이상의 계정 ID)에서는 폴백 라우팅을 피하기 위해 명시적인 기본값(channels.telegram.defaultAccount 또는 channels.telegram.accounts.default)을 설정하세요. 설정이 누락되거나 유효하지 않으면 openclaw doctor가 경고를 표시해요.
  • configWrites: false는 Telegram에서 시작된 설정 쓰기(슈퍼그룹 ID 마이그레이션, /config set|unset)를 차단해요.
  • 최상위 bindings[] 항목 중 type: "acp"인 설정은 포럼 토픽에 대한 영구 ACP 바인딩을 구성해요 (match.peer.id에 정규화된 chatId:topic:topicId 사용). 필드 의미는 ACP 에이전트에서 공유돼요.
  • Telegram 스트림 미리보기는 sendMessage + editMessageText를 사용해요 (다이렉트 및 그룹 채팅에서 작동).
  • 재시도 정책: 재시도 정책을 참조하세요.
{
channels: {
discord: {
enabled: true,
token: "your-bot-token",
mediaMaxMb: 8,
allowBots: false,
actions: {
reactions: true,
stickers: true,
polls: true,
permissions: true,
messages: true,
threads: true,
pins: true,
search: true,
memberInfo: true,
roleInfo: true,
roles: false,
channelInfo: true,
voiceStatus: true,
events: true,
moderation: false,
},
replyToMode: "off", // off | first | all
dmPolicy: "pairing",
allowFrom: ["1234567890", "123456789012345678"],
dm: { enabled: true, groupEnabled: false, groupChannels: ["openclaw-dm"] },
guilds: {
"123456789012345678": {
slug: "friends-of-openclaw",
requireMention: false,
ignoreOtherMentions: true,
reactionNotifications: "own",
users: ["987654321098765432"],
channels: {
general: { allow: true },
help: {
allow: true,
requireMention: true,
users: ["987654321098765432"],
skills: ["docs"],
systemPrompt: "Short answers only.",
},
},
},
},
historyLimit: 20,
textChunkLimit: 2000,
chunkMode: "length", // length | newline
streaming: "off", // off | partial | block | progress (progress maps to partial on Discord)
maxLinesPerMessage: 17,
ui: {
components: {
accentColor: "#5865F2",
},
},
threadBindings: {
enabled: true,
idleHours: 24,
maxAgeHours: 0,
spawnSubagentSessions: false, // opt-in for sessions_spawn({ thread: true })
},
voice: {
enabled: true,
autoJoin: [
{
guildId: "123456789012345678",
channelId: "234567890123456789",
},
],
daveEncryption: true,
decryptionFailureTolerance: 24,
tts: {
provider: "openai",
openai: { voice: "alloy" },
},
},
retry: {
attempts: 3,
minDelayMs: 500,
maxDelayMs: 30000,
jitter: 0.1,
},
},
},
}
  • Token: channels.discord.token을 사용하며, 기본 계정에 대해 DISCORD_BOT_TOKEN이 폴백으로 사용돼요.
  • 명시적인 Discord token을 제공하는 직접적인 아웃바운드 호출은 해당 토큰을 사용해요. 계정 재시도/정책 설정은 여전히 활성 런타임 스냅샷에서 선택된 계정으로부터 가져와요.
  • 선택 사항인 channels.discord.defaultAccount는 설정된 계정 ID와 일치할 때 기본 계정 선택을 오버라이드해요.
  • 전달 대상으로 user:<id> (DM) 또는 channel:<id> (길드 채널)를 사용하세요. 순수 숫자 ID는 거부돼요.
  • 길드 슬러그(slug)는 소문자이며 공백은 -로 대체돼요. 채널 키는 슬러그화된 이름을 사용해요 (# 없음). 길드 ID 사용을 권장해요.
  • 봇이 작성한 메시지는 기본적으로 무시돼요. allowBots: true로 설정하면 허용되며, allowBots: "mentions"를 사용하면 봇을 멘션하는 봇 메시지만 수락해요 (자신의 메시지는 여전히 필터링됨).
  • channels.discord.guilds.<id>.ignoreOtherMentions (및 채널 오버라이드)는 다른 사용자나 역할을 멘션하지만 봇은 멘션하지 않는 메시지를 삭제해요 (@everyone/@here 제외).
  • maxLinesPerMessage (기본값 17)는 2000자 미만이더라도 긴 메시지를 분할해요.
  • channels.discord.threadBindings는 Discord 스레드 바인딩 라우팅을 제어해요:
    • enabled: 스레드 바인딩 세션 기능(/focus, /unfocus, /agents, /session idle, /session max-age, 바인딩된 전달/라우팅)에 대한 Discord 오버라이드예요.
    • idleHours: 비활성 자동 포커스 해제 시간(시간 단위)에 대한 Discord 오버라이드예요 (0은 비활성화).
    • maxAgeHours: 하드 최대 수명(시간 단위)에 대한 Discord 오버라이드예요 (0은 비활성화).
    • spawnSubagentSessions: sessions_spawn({ thread: true }) 자동 스레드 생성/바인딩을 위한 옵트인 스위치예요.
  • 최상위 bindings[] 항목 중 type: "acp"인 설정은 채널 및 스레드에 대한 영구 ACP 바인딩을 구성해요 (match.peer.id에 채널/스레드 ID 사용). 필드 의미는 ACP 에이전트에서 공유돼요.
  • channels.discord.ui.components.accentColor는 Discord components v2 컨테이너의 강조 색상을 설정해요.
  • channels.discord.voice는 Discord 음성 채널 대화와 선택적인 자동 참여 + TTS 오버라이드를 활성화해요.
  • channels.discord.voice.daveEncryption 및 channels.discord.voice.decryptionFailureTolerance는 @discordjs/voice DAVE 옵션으로 전달돼요 (기본값은 각각 true 및 24).
  • OpenClaw는 복호화 실패가 반복될 때 음성 세션을 나갔다 다시 참여함으로써 음성 수신 복구를 추가로 시도해요.
  • channels.discord.streaming은 표준 스트림 모드 키예요. 기존의 streamMode 및 불리언 streaming 값은 자동으로 마이그레이션돼요.
  • channels.discord.autoPresence는 런타임 가용성을 봇 상태에 매핑하며(healthy => online, degraded => idle, exhausted => dnd), 선택적인 상태 텍스트 오버라이드를 허용해요.
  • channels.discord.dangerouslyAllowNameMatching은 변경 가능한 이름/태그 매칭을 다시 활성화해요 (긴급 호환성 모드).

반응 알림 모드: off (없음), own (봇의 메시지, 기본값), all (모든 메시지), allowlist (모든 메시지에 대해 guilds.<id>.users로부터의 반응).

{
channels: {
googlechat: {
enabled: true,
serviceAccountFile: "/path/to/service-account.json",
audienceType: "app-url", // app-url | project-number
audience: "https://gateway.example.com/googlechat",
webhookPath: "/googlechat",
botUser: "users/1234567890",
dm: {
enabled: true,
policy: "pairing",
allowFrom: ["users/1234567890"],
},
groupPolicy: "allowlist",
groups: {
"spaces/AAAA": { allow: true, requireMention: true },
},
actions: { reactions: true },
typingIndicator: "message",
mediaMaxMb: 20,
},
},
}
  • 서비스 계정 JSON: 인라인(serviceAccount) 또는 파일 기반(serviceAccountFile)으로 설정 가능해요.
  • 서비스 계정 SecretRef도 지원돼요 (serviceAccountRef).
  • 환경 변수 폴백: GOOGLE_CHAT_SERVICE_ACCOUNT 또는 GOOGLE_CHAT_SERVICE_ACCOUNT_FILE.
  • 전달 대상으로 spaces/<spaceId> 또는 users/<userId>를 사용하세요.
  • channels.googlechat.dangerouslyAllowNameMatching은 변경 가능한 이메일 주체 매칭을 다시 활성화해요 (긴급 호환성 모드).
{
channels: {
slack: {
enabled: true,
botToken: "xoxb-...",
appToken: "xapp-...",
dmPolicy: "pairing",
allowFrom: ["U123", "U456", "*"],
dm: { enabled: true, groupEnabled: false, groupChannels: ["G123"] },
channels: {
C123: { allow: true, requireMention: true, allowBots: false },
"#general": {
allow: true,
requireMention: true,
allowBots: false,
users: ["U123"],
skills: ["docs"],
systemPrompt: "Short answers only.",
},
},
historyLimit: 50,
allowBots: false,
reactionNotifications: "own",
reactionAllowlist: ["U123"],
replyToMode: "off", // off | first | all
thread: {
historyScope: "thread", // thread | channel
inheritParent: false,
},
actions: {
reactions: true,
messages: true,
pins: true,
memberInfo: true,
emojiList: true,
},
slashCommand: {
enabled: true,
name: "openclaw",
sessionPrefix: "slack:slash",
ephemeral: true,
},
typingReaction: "hourglass_flowing_sand",
textChunkLimit: 4000,
chunkMode: "length",
streaming: "partial", // off | partial | block | progress (preview mode)
nativeStreaming: true, // use Slack native streaming API when streaming=partial
mediaMaxMb: 20,
},
},
}
  • Socket mode는 botToken과 appToken이 모두 필요해요 (기본 계정 환경 변수 폴백은 SLACK_BOT_TOKEN + SLACK_APP_TOKEN).
  • HTTP mode는 botToken과 signingSecret(루트 또는 계정별)이 필요해요.
  • configWrites: false는 Slack에서 시작된 설정 쓰기를 차단해요.
  • 선택 사항인 channels.slack.defaultAccount는 설정된 계정 ID와 일치할 때 기본 계정 선택을 오버라이드해요.
  • channels.slack.streaming은 표준 스트림 모드 키예요. 기존의 streamMode 및 불리언 streaming 값은 자동으로 마이그레이션돼요.
  • 전달 대상으로 user:<id> (DM) 또는 channel:<id>를 사용하세요.

반응 알림 모드: off, own (기본값), all, allowlist (reactionAllowlist로부터의 반응).

스레드 세션 격리: thread.historyScope는 스레드별(기본값) 또는 채널 전체 공유로 설정할 수 있어요. thread.inheritParent는 부모 채널의 대화 기록을 새 스레드로 복사해요.

  • typingReaction은 답장이 진행되는 동안 인바운드 Slack 메시지에 임시 반응을 추가하고, 완료되면 제거해요. "hourglass_flowing_sand"와 같은 Slack 이모지 숏코드를 사용하세요.
액션 그룹기본값참고
reactions활성화반응 추가 + 반응 목록 조회
messages활성화읽기/전송/수정/삭제
pins활성화고정/고정 해제/목록 조회
memberInfo활성화멤버 정보
emojiList활성화커스텀 이모지 목록

Mattermost는 플러그인으로 제공돼요: openclaw plugins install @openclaw/mattermost.

{
channels: {
mattermost: {
enabled: true,
botToken: "mm-token",
baseUrl: "https://chat.example.com",
dmPolicy: "pairing",
chatmode: "oncall", // oncall | onmessage | onchar
oncharPrefixes: [">", "!"],
commands: {
native: true, // opt-in
nativeSkills: true,
callbackPath: "/api/channels/mattermost/command",
// Optional explicit URL for reverse-proxy/public deployments
callbackUrl: "https://gateway.example.com/api/channels/mattermost/command",
},
textChunkLimit: 4000,
chunkMode: "length",
},
},
}

채팅 모드: oncall (@-멘션 시 응답, 기본값), onmessage (모든 메시지), onchar (트리거 접두사로 시작하는 메시지).

Mattermost 네이티브 명령이 활성화된 경우:

  • commands.callbackPath는 전체 URL이 아닌 경로(예: /api/channels/mattermost/command)여야 해요.
  • commands.callbackUrl은 OpenClaw Gateway 엔드포인트로 연결되어야 하며 Mattermost 서버에서 접근 가능해야 해요.
  • 프라이빗/tailnet/내부 콜백 호스트의 경우, Mattermost의 ServiceSettings.AllowedUntrustedInternalConnections에 콜백 호스트/도메인을 포함해야 할 수도 있어요. 전체 URL이 아닌 호스트/도메인 값을 사용하세요.
  • channels.mattermost.configWrites: Mattermost에서 시작된 설정 쓰기를 허용하거나 거부해요.
  • channels.mattermost.requireMention: 채널에서 답장하기 전에 @mention을 요구해요.
  • 선택 사항인 channels.mattermost.defaultAccount는 설정된 계정 ID와 일치할 때 기본 계정 선택을 오버라이드해요.
{
channels: {
signal: {
enabled: true,
account: "+15555550123", // optional account binding
dmPolicy: "pairing",
allowFrom: ["+15551234567", "uuid:123e4567-e89b-12d3-a456-426614174000"],
configWrites: true,
reactionNotifications: "own", // off | own | all | allowlist
reactionAllowlist: ["+15551234567", "uuid:123e4567-e89b-12d3-a456-426614174000"],
historyLimit: 50,
},
},
}

반응 알림 모드: off, own (기본값), all, allowlist (reactionAllowlist로부터의 반응).

  • channels.signal.account: 채널 시작을 특정 Signal 계정 ID에 고정해요.
  • channels.signal.configWrites: Signal에서 시작된 설정 쓰기를 허용하거나 거부해요.
  • 선택 사항인 channels.signal.defaultAccount는 설정된 계정 ID와 일치할 때 기본 계정 선택을 오버라이드해요.

BlueBubbles는 권장되는 iMessage 경로예요 (플러그인 기반, channels.bluebubbles에서 설정).

{
channels: {
bluebubbles: {
enabled: true,
dmPolicy: "pairing",
// serverUrl, password, webhookPath, group controls, and advanced actions:
// see /channels/bluebubbles
},
},
}
  • 여기서 다루는 핵심 키 경로: channels.bluebubbles, channels.bluebubbles.dmPolicy.
  • 선택 사항인 channels.bluebubbles.defaultAccount는 설정된 계정 ID와 일치할 때 기본 계정 선택을 오버라이드해요.
  • 전체 BlueBubbles 채널 설정은 BlueBubbles에 문서화되어 있어요.

OpenClaw는 imsg rpc (stdio를 통한 JSON-RPC)를 실행해요. 데몬이나 포트가 필요하지 않아요.

{
channels: {
imessage: {
enabled: true,
cliPath: "imsg",
dbPath: "~/Library/Messages/chat.db",
remoteHost: "user@gateway-host",
dmPolicy: "pairing",
allowFrom: ["+15555550123", "user@example.com", "chat_id:123"],
historyLimit: 50,
includeAttachments: false,
attachmentRoots: ["/Users/*/Library/Messages/Attachments"],
remoteAttachmentRoots: ["/Users/*/Library/Messages/Attachments"],
mediaMaxMb: 16,
service: "auto",
region: "US",
},
},
}
  • 선택 사항인 channels.imessage.defaultAccount는 설정된 계정 ID와 일치할 때 기본 계정 선택을 오버라이드해요.
  • 메시지 DB에 대한 전체 디스크 접근 권한(Full Disk Access)이 필요해요.
  • chat_id:<id> 대상을 권장해요. imsg chats --limit 20을 사용하여 채팅 목록을 확인할 수 있어요.
  • cliPath는 SSH 래퍼를 가리킬 수 있어요. SCP 첨부 파일 가져오기를 위해 remoteHost (host 또는 user@host)를 설정하세요.
  • attachmentRoots 및 remoteAttachmentRoots는 인바운드 첨부 파일 경로를 제한해요 (기본값: /Users/*/Library/Messages/Attachments).
  • SCP는 엄격한 호스트 키 확인을 사용하므로 릴레이 호스트 키가 ~/.ssh/known_hosts에 이미 존재하는지 확인하세요.
  • channels.imessage.configWrites: iMessage에서 시작된 설정 쓰기를 허용하거나 거부해요.

iMessage SSH 래퍼 예시

#!/usr/bin/env bash
exec ssh -T gateway-host imsg "$@"

Microsoft Teams는 확장 기능 기반이며 channels.msteams에서 설정해요.

{
channels: {
msteams: {
enabled: true,
configWrites: true,
// appId, appPassword, tenantId, webhook, team/channel policies:
// see /channels/msteams
},
},
}
  • 여기서 다루는 핵심 키 경로: channels.msteams, channels.msteams.configWrites.
  • 전체 Teams 설정(자격 증명, 웹훅, DM/그룹 정책, 팀별/채널별 오버라이드)은 Microsoft Teams에 문서화되어 있어요.

IRC는 확장 기능 기반이며 channels.irc에서 설정해요.

{
channels: {
irc: {
enabled: true,
dmPolicy: "pairing",
configWrites: true,
nickserv: {
enabled: true,
service: "NickServ",
password: "${IRC_NICKSERV_PASSWORD}",
register: false,
registerEmail: "bot@example.com",
},
},
},
}
  • 여기서 다루는 핵심 키 경로: channels.irc, channels.irc.dmPolicy, channels.irc.configWrites, channels.irc.nickserv.*.
  • 선택 사항인 channels.irc.defaultAccount는 설정된 계정 ID와 일치할 때 기본 계정 선택을 오버라이드해요.
  • 전체 IRC 채널 설정(호스트/포트/TLS/채널/allowlist/멘션 게이팅)은 IRC에 문서화되어 있어요.

채널당 여러 계정을 실행할 수 있어요 (각각 고유한 accountId 보유):

{
channels: {
telegram: {
accounts: {
default: {
name: "Primary bot",
botToken: "123456:ABC...",
},
alerts: {
name: "Alerts bot",
botToken: "987654:XYZ...",
},
},
},
},
}
  • accountId가 생략된 경우(CLI + 라우팅) default가 사용돼요.
  • 환경 변수 토큰은 기본(default) 계정에만 적용돼요.
  • 기본 채널 설정은 계정별로 오버라이드되지 않는 한 모든 계정에 적용돼요.
  • 각 계정을 다른 에이전트로 라우팅하려면 bindings[].match.accountId를 사용하세요.
  • 단일 계정 최상위 채널 설정 상태에서 openclaw channels add(또는 채널 온보딩)를 통해 기본이 아닌 계정을 추가하면, OpenClaw는 기존 계정이 계속 작동하도록 계정 범위의 최상위 단일 계정 값을 channels.<channel>.accounts.default로 먼저 이동시켜요.
  • 기존의 채널 전용 바인딩(accountId 없음)은 기본 계정과 계속 매칭돼요. 계정 범위 바인딩은 선택 사항으로 남아요.
  • openclaw doctor --fix는 이름이 지정된 계정은 존재하지만 default가 누락된 경우, 계정 범위의 최상위 단일 계정 값을 accounts.default로 이동하여 혼합된 형태를 복구해요.

많은 확장 채널이 channels.<id>로 설정되며 전용 채널 페이지(예: Feishu, Matrix, LINE, Nostr, Zalo, Nextcloud Talk, Synology Chat, Twitch)에 문서화되어 있어요. 전체 채널 인덱스를 확인하세요: 채널.

그룹 메시지는 기본적으로 멘션 요구 (메타데이터 멘션 또는 정규식 패턴) 상태예요. WhatsApp, Telegram, Discord, Google Chat, iMessage 그룹 채팅에 적용돼요.

멘션 유형:

  • 메타데이터 멘션: 플랫폼 네이티브 @-멘션이에요. WhatsApp 셀프 채팅 모드에서는 무시돼요.
  • 텍스트 패턴: agents.list[].groupChat.mentionPatterns에 정의된 정규식 패턴이에요. 항상 확인돼요.
  • 멘션 게이팅은 감지가 가능할 때만(네이티브 멘션 또는 하나 이상의 패턴이 있을 때) 강제 적용돼요.
{
messages: {
groupChat: { historyLimit: 50 },
},
agents: {
list: [{ id: "main", groupChat: { mentionPatterns: ["@openclaw", "openclaw"] } }],
},
}

messages.groupChat.historyLimit은 글로벌 기본값을 설정해요. 채널별로 channels.<channel>.historyLimit(또는 계정별)을 통해 오버라이드할 수 있어요. 0으로 설정하면 비활성화돼요.

{
channels: {
telegram: {
dmHistoryLimit: 30,
dms: {
"123456789": { historyLimit: 50 },
},
},
},
}

해결 순서: DM별 오버라이드 → 프로바이더 기본값 → 제한 없음 (모두 유지).

지원 채널: telegram, whatsapp, discord, slack, signal, imessage, msteams.

자신의 번호를 allowFrom에 포함하여 셀프 채팅 모드를 활성화하세요 (네이티브 @-멘션은 무시하고 텍스트 패턴에만 응답함):

{
channels: {
whatsapp: {
allowFrom: ["+15555550123"],
groups: { "*": { requireMention: true } },
},
},
agents: {
list: [
{
id: "main",
groupChat: { mentionPatterns: ["reisponde", "@openclaw"] },
},
],
},
}
{
commands: {
native: "auto", // register native commands when supported
text: true, // parse /commands in chat messages
bash: false, // allow ! (alias: /bash)
bashForegroundMs: 2000,
config: false, // allow /config
debug: false, // allow /debug
restart: false, // allow /restart + gateway restart tool
allowFrom: {
"*": ["user1"],
discord: ["user:123"],
},
useAccessGroups: true,
},
}
명령 상세 정보
  • 텍스트 명령은 맨 앞에 /가 붙은 독립된 메시지여야 해요.
  • native: "auto"는 Discord/Telegram의 네이티브 명령을 켜고 Slack은 끈 상태로 둬요.
  • 채널별 오버라이드: channels.discord.commands.native (불리언 또는 "auto"). false는 이전에 등록된 명령을 삭제해요.
  • channels.telegram.customCommands는 Telegram 봇 메뉴 항목을 추가해요.
  • bash: true는 호스트 쉘을 위한 ! <cmd>를 활성화해요. tools.elevated.enabled가 필요하며 발신자가 tools.elevated.allowFrom.<channel>에 있어야 해요.
  • config: true는 /config(openclaw.json 읽기/쓰기)를 활성화해요. Gateway chat.send 클라이언트의 경우, 영구적인 /config set|unset 쓰기에는 operator.admin 권한도 필요해요. 읽기 전용인 /config show는 일반 쓰기 권한의 operator 클라이언트도 사용할 수 있어요.
  • channels.<provider>.configWrites는 채널별 설정 변경을 제어해요 (기본값: true).
  • 다중 계정 채널의 경우, channels.<provider>.accounts.<id>.configWrites는 해당 계정을 대상으로 하는 쓰기도 제어해요 (예: /allowlist --config --account <id> 또는 /config set channels.<provider>.accounts.<id>...).
  • allowFrom은 프로바이더별로 설정돼요. 설정되면 이것이 유일한 인증 소스가 돼요 (채널 allowlist/페어링 및 useAccessGroups는 무시됨).
  • useAccessGroups: false는 allowFrom이 설정되지 않았을 때 명령이 액세스 그룹 정책을 우회할 수 있게 해요.

기본값: ~/.openclaw/workspace.

{
agents: { defaults: { workspace: "~/.openclaw/workspace" } },
}

시스템 프롬프트의 Runtime 라인에 표시되는 선택적인 저장소 루트예요. 설정되지 않으면 OpenClaw가 워크스페이스에서 위로 올라가며 자동으로 감지해요.

{
agents: { defaults: { repoRoot: "~/Projects/openclaw" } },
}

워크스페이스 부트스트랩 파일(AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, HEARTBEAT.md, BOOTSTRAP.md)의 자동 생성을 비활성화해요.

{
agents: { defaults: { skipBootstrap: true } },
}

잘리기 전 워크스페이스 부트스트랩 파일당 최대 문자 수예요. 기본값: 20000.

{
agents: { defaults: { bootstrapMaxChars: 20000 } },
}

모든 워크스페이스 부트스트랩 파일에 걸쳐 주입되는 최대 총 문자 수예요. 기본값: 150000.

{
agents: { defaults: { bootstrapTotalMaxChars: 150000 } },
}

agents.defaults.bootstrapPromptTruncationWarning

섹션 제목: “agents.defaults.bootstrapPromptTruncationWarning”

부트스트랩 컨텍스트가 잘렸을 때 에이전트에게 보이는 경고 텍스트를 제어해요. 기본값: "once".

  • "off": 시스템 프롬프트에 경고 텍스트를 주입하지 않아요.
  • "once": 고유한 절단 시그니처당 한 번만 경고를 주입해요 (권장).
  • "always": 절단이 존재할 때마다 매 실행 시 경고를 주입해요.
{
agents: { defaults: { bootstrapPromptTruncationWarning: "once" } }, // off | once | always
}

프로바이더 호출 전 대화 기록/도구 이미지 블록에서 이미지의 가장 긴 변의 최대 픽셀 크기예요. 기본값: 1200.

낮은 값은 일반적으로 스크린샷이 많은 실행에서 vision-token 사용량과 요청 페이로드 크기를 줄여줘요. 높은 값은 더 많은 시각적 세부 사항을 보존해요.

{
agents: { defaults: { imageMaxDimensionPx: 1200 } },
}

시스템 프롬프트 컨텍스트를 위한 시간대예요 (메시지 타임스탬프가 아님). 호스트 시간대로 폴백돼요.

{
agents: { defaults: { userTimezone: "America/Chicago" } },
}

시스템 프롬프트의 시간 형식이에요. 기본값: auto (OS 설정 선호).

{
agents: { defaults: { timeFormat: "auto" } }, // auto | 12 | 24
}
{
agents: {
defaults: {
models: {
"anthropic/claude-opus-4-6": { alias: "opus" },
"minimax/MiniMax-M2.5": { alias: "minimax" },
},
model: {
primary: "anthropic/claude-opus-4-6",
fallbacks: ["minimax/MiniMax-M2.5"],
},
imageModel: {
primary: "openrouter/qwen/qwen-2.5-vl-72b-instruct:free",
fallbacks: ["openrouter/google/gemini-2.0-flash-vision:free"],
},
pdfModel: {
primary: "anthropic/claude-opus-4-6",
fallbacks: ["openai/gpt-5-mini"],
},
pdfMaxBytesMb: 10,
pdfMaxPages: 20,
thinkingDefault: "low",
verboseDefault: "off",
elevatedDefault: "on",
timeoutSeconds: 600,
mediaMaxMb: 5,
contextTokens: 200000,
maxConcurrent: 3,
},
},
}
  • model: 문자열("provider/model") 또는 객체({ primary, fallbacks })를 받아요.
    • 문자열 형식은 기본 모델만 설정해요.
    • 객체 형식은 기본 모델과 순서가 지정된 페일오버(failover) 모델들을 설정해요.
  • imageModel: 문자열("provider/model") 또는 객체({ primary, fallbacks })를 받아요.
    • image 도구 경로에서 vision-model 설정으로 사용돼요.
    • 선택된/기본 모델이 이미지 입력을 수락할 수 없을 때 폴백 라우팅으로도 사용돼요.
  • pdfModel: 문자열("provider/model") 또는 객체({ primary, fallbacks })를 받아요.
    • pdf 도구에서 모델 라우팅을 위해 사용돼요.
    • 생략하면 PDF 도구는 imageModel로 폴백하고, 그 다음 최선의 프로바이더 기본값으로 폴백해요.
  • pdfMaxBytesMb: 호출 시 maxBytesMb가 전달되지 않았을 때 pdf 도구의 기본 PDF 크기 제한이에요.
  • pdfMaxPages: pdf 도구의 추출 폴백 모드에서 고려되는 기본 최대 페이지 수예요.
  • model.primary: provider/model 형식이에요 (예: anthropic/claude-opus-4-6). 프로바이더를 생략하면 OpenClaw는 anthropic으로 간주해요 (권장되지 않음).
  • models: /model을 위한 설정된 모델 카탈로그 및 allowlist예요. 각 항목은 alias(단축키)와 params(프로바이더별 설정, 예: temperature, maxTokens, cacheRetention, context1m)를 포함할 수 있어요.
  • params 병합 우선순위(설정): agents.defaults.models["provider/model"].params가 기본이며, agents.list[].params(일치하는 에이전트 ID)가 키별로 오버라이드해요.
  • 이 필드들을 변경하는 설정 작성기(예: /models set, /models set-image, 폴백 추가/제거 명령)는 정규 객체 형식을 저장하고 가능한 경우 기존 폴백 목록을 보존해요.
  • maxConcurrent: 세션 전체에 걸친 최대 병렬 에이전트 실행 수예요 (각 세션은 여전히 직렬화됨). 기본값: 1.

내장 alias 단축키 (모델이 agents.defaults.models에 있을 때만 적용됨):

Alias모델
opusanthropic/claude-opus-4-6
sonnetanthropic/claude-sonnet-4-6
gptopenai/gpt-5.4
gpt-miniopenai/gpt-5-mini
geminigoogle/gemini-3.1-pro-preview
gemini-flashgoogle/gemini-3-flash-preview
gemini-flash-litegoogle/gemini-3.1-flash-lite-preview

사용자가 설정한 alias는 항상 기본값보다 우선해요.

Z.AI GLM-4.x 모델은 --thinking off를 설정하거나 agents.defaults.models["zai/<model>"].params.thinking을 직접 정의하지 않는 한 자동으로 thinking 모드를 활성화해요. Z.AI 모델은 도구 호출 스트리밍을 위해 기본적으로 tool_stream을 활성화해요. 비활성화하려면 agents.defaults.models["zai/<model>"].params.tool_stream을 false로 설정하세요. Anthropic Claude 4.6 모델은 명시적인 thinking 레벨이 설정되지 않은 경우 기본적으로 adaptive thinking을 사용해요.

텍스트 전용 폴백 실행(도구 호출 없음)을 위한 선택적인 CLI 백엔드예요. API 프로바이더가 실패할 때 백업으로 유용해요.

{
agents: {
defaults: {
cliBackends: {
"claude-cli": {
command: "/opt/homebrew/bin/claude",
},
"my-cli": {
command: "my-cli",
args: ["--json"],
output: "json",
modelArg: "--model",
sessionArg: "--session",
sessionMode: "existing",
systemPromptArg: "--system",
systemPromptWhen: "first",
imageArg: "--image",
imageMode: "repeat",
},
},
},
},
}
  • CLI 백엔드는 텍스트 우선이며, 도구는 항상 비활성화돼요.
  • sessionArg가 설정되면 세션이 지원돼요.
  • imageArg가 파일 경로를 수락하면 이미지 패스스루(pass-through)가 지원돼요.

주기적인 heartbeat 실행 설정이에요.

{
agents: {
defaults: {
heartbeat: {
every: "30m", // 0m disables
model: "openai/gpt-5.2-mini",
includeReasoning: false,
lightContext: false, // default: false; true keeps only HEARTBEAT.md from workspace bootstrap files
session: "main",
to: "+15555550123",
directPolicy: "allow", // allow (default) | block
target: "none", // default: none | options: last | whatsapp | telegram | discord | ...
prompt: "Read HEARTBEAT.md if it exists...",
ackMaxChars: 300,
suppressToolErrorWarnings: false,
},
},
},
}
  • every: 기간 문자열(ms/s/m/h). 기본값: 30m.
  • suppressToolErrorWarnings: true일 때 heartbeat 실행 중 도구 에러 경고 페이로드를 억제해요.
  • directPolicy: 다이렉트/DM 전달 정책이에요. allow(기본값)는 다이렉트 대상 전달을 허용해요. block은 다이렉트 대상 전달을 억제하고 reason=dm-blocked를 내보내요.
  • lightContext: true일 때 heartbeat 실행은 경량 부트스트랩 컨텍스트를 사용하며 워크스페이스 부트스트랩 파일 중 HEARTBEAT.md만 유지해요.
  • 에이전트별 설정: agents.list[].heartbeat를 설정하세요. 어떤 에이전트라도 heartbeat를 정의하면 해당 에이전트들만 heartbeat를 실행해요.
  • Heartbeat는 전체 에이전트 턴(turn)을 실행하므로, 간격이 짧을수록 더 많은 토큰을 소모해요.
{
agents: {
defaults: {
compaction: {
mode: "safeguard", // default | safeguard
reserveTokensFloor: 24000,
identifierPolicy: "strict", // strict | off | custom
identifierInstructions: "Preserve deployment IDs, ticket IDs, and host:port pairs exactly.", // used when identifierPolicy=custom
postCompactionSections: ["Session Startup", "Red Lines"], // [] disables reinjection
model: "openrouter/anthropic/claude-sonnet-4-5", // optional compaction-only model override
memoryFlush: {
enabled: true,
softThresholdTokens: 6000,
systemPrompt: "Session nearing compaction. Store durable memories now.",
prompt: "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store.",
},
},
},
},
}
  • mode: default 또는 safeguard(긴 히스토리를 위한 청크 단위 요약). Compaction을 참조하세요.
  • identifierPolicy: strict(기본값), off, 또는 custom. strict는 compaction 요약 중에 내장된 불투명 식별자 보존 가이드를 앞에 추가해요.
  • identifierInstructions: identifierPolicy=custom일 때 사용되는 선택적인 커스텀 식별자 보존 텍스트예요.
  • postCompactionSections: compaction 후 다시 주입할 선택적인 AGENTS.md H2/H3 섹션 이름들이에요. 기본값은 ["Session Startup", "Red Lines"]이며, []로 설정하면 재주입을 비활성화해요. 설정되지 않았거나 기본값 쌍으로 명시적으로 설정된 경우, 이전의 Every Session/Safety 헤딩도 레거시 폴백으로 수락돼요.
  • model: compaction 요약 전용의 선택적인 provider/model-id 오버라이드예요. 메인 세션은 한 모델을 유지하고 compaction 요약은 다른 모델에서 실행해야 할 때 사용하세요. 설정되지 않으면 세션의 기본 모델을 사용해요.
  • memoryFlush: 자동 compaction 전에 영구 메모리를 저장하기 위한 조용한 에이전트 턴이에요. 워크스페이스가 읽기 전용이면 건너뛰어요.

LLM에 보내기 전에 메모리 내 컨텍스트에서 오래된 도구 결과를 정리해요. 디스크의 세션 히스토리는 수정하지 않아요.

{
agents: {
defaults: {
contextPruning: {
mode: "cache-ttl", // off | cache-ttl
ttl: "1h", // duration (ms/s/m/h), default unit: minutes
keepLastAssistants: 3,
softTrimRatio: 0.3,
hardClearRatio: 0.5,
minPrunableToolChars: 50000,
softTrim: { maxChars: 4000, headChars: 1500, tailChars: 1500 },
hardClear: { enabled: true, placeholder: "[Old tool result content cleared]" },
tools: { deny: ["browser", "canvas"] },
},
},
},
}
cache-ttl 모드 동작
  • mode: "cache-ttl"은 정리 패스를 활성화해요.
  • ttl은 정리가 다시 실행될 수 있는 빈도를 제어해요 (마지막 캐시 터치 이후).
  • 정리는 먼저 너무 큰 도구 결과를 soft-trim하고, 필요한 경우 오래된 도구 결과를 hard-clear해요.

Soft-trim은 시작 부분과 끝 부분을 유지하고 중간에 ...을 삽입해요.

Hard-clear는 전체 도구 결과를 플레이스홀더로 교체해요.

참고:

  • 이미지 블록은 절대 트리밍되거나 삭제되지 않아요.
  • 비율은 정확한 토큰 수가 아닌 문자 수 기준(근사치)이에요.
  • keepLastAssistants보다 적은 수의 assistant 메시지가 존재하면 정리를 건너뛰어요.

동작 상세 정보는 세션 정리를 참조하세요.

{
agents: {
defaults: {
blockStreamingDefault: "off", // on | off
blockStreamingBreak: "text_end", // text_end | message_end
blockStreamingChunk: { minChars: 800, maxChars: 1200 },
blockStreamingCoalesce: { idleMs: 1000 },
humanDelay: { mode: "natural" }, // off | natural | custom (use minMs/maxMs)
},
},
}
  • Telegram이 아닌 채널에서 블록 답장을 활성화하려면 명시적인 *.blockStreaming: true가 필요해요.
  • 채널 오버라이드: channels.<channel>.blockStreamingCoalesce (및 계정별 변체). Signal/Slack/Discord/Google Chat의 기본값은 minChars: 1500이에요.
  • humanDelay: 블록 답장 사이의 무작위 일시 정지예요. natural = 800–2500ms. 에이전트별 오버라이드: agents.list[].humanDelay.

동작 및 청킹 상세 정보는 스트리밍을 참조하세요.

{
agents: {
defaults: {
typingMode: "instant", // never | instant | thinking | message
typingIntervalSeconds: 6,
},
},
}
  • 기본값: 다이렉트 채팅/멘션 시 instant, 멘션되지 않은 그룹 채팅 시 message.
  • 세션별 오버라이드: session.typingMode, session.typingIntervalSeconds.

타이핑 인디케이터를 참조하세요.

내장 에이전트를 위한 선택적인 Docker 샌드박싱 설정이에요. 전체 가이드는 샌드박싱을 참조하세요.

{
agents: {
defaults: {
sandbox: {
mode: "non-main", // off | non-main | all
scope: "agent", // session | agent | shared
workspaceAccess: "none", // none | ro | rw
workspaceRoot: "~/.openclaw/sandboxes",
docker: {
image: "openclaw-sandbox:bookworm-slim",
containerPrefix: "openclaw-sbx-",
workdir: "/workspace",
readOnlyRoot: true,
tmpfs: ["/tmp", "/var/tmp", "/run"],
network: "none",
user: "1000:1000",
capDrop: ["ALL"],
env: { LANG: "C.UTF-8" },
setupCommand: "apt-get update && apt-get install -y git curl jq",
pidsLimit: 256,
memory: "1g",
memorySwap: "2g",
cpus: 1,
ulimits: {
nofile: { soft: 1024, hard: 2048 },
nproc: 256,
},
seccompProfile: "/path/to/seccomp.json",
apparmorProfile: "openclaw-sandbox",
dns: ["1.1.1.1", "8.8.8.8"],
extraHosts: ["internal.service:10.0.0.5"],
binds: ["/home/user/source:/source:rw"],
},
browser: {
enabled: false,
image: "openclaw-sandbox-browser:bookworm-slim",
network: "openclaw-sandbox-browser",
cdpPort: 9222,
cdpSourceRange: "172.21.0.1/32",
vncPort: 5900,
noVncPort: 6080,
headless: false,
enableNoVnc: true,
allowHostControl: false,
autoStart: true,
autoStartTimeoutMs: 12000,
},
prune: {
idleHours: 24,
maxAgeDays: 7,
},
},
},
},
tools: {
sandbox: {
tools: {
allow: [
"exec",
"process",
"read",
"write",
"edit",
"apply_patch",
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"session_status",
],
deny: ["browser", "canvas", "nodes", "cron", "discord", "gateway"],
},
},
},
}
샌드박스 상세 정보

워크스페이스 액세스:

  • none: ~/.openclaw/sandboxes 아래의 스코프별 샌드박스 워크스페이스
  • ro: /workspace에 샌드박스 워크스페이스, /agent에 읽기 전용으로 마운트된 에이전트 워크스페이스
  • rw: /workspace에 읽기/쓰기 가능하게 마운트된 에이전트 워크스페이스

스코프(Scope):

  • session: 세션별 컨테이너 + 워크스페이스
  • agent: 에이전트당 하나의 컨테이너 + 워크스페이스 (기본값)
  • shared: 공유 컨테이너 및 워크스페이스 (세션 간 격리 없음)

**setupCommand**는 컨테이너 생성 후 한 번 실행돼요 (sh -lc를 통해). 네트워크 아웃바운드, 쓰기 가능한 루트, 루트 사용자가 필요해요.

**컨테이너 기본값은 network: "none"**이에요. 에이전트에게 아웃바운드 액세스가 필요한 경우 "bridge"(또는 커스텀 브릿지 네트워크)로 설정하세요. "host"는 차단돼요. "container:<id>"는 sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true를 명시적으로 설정하지 않는 한 기본적으로 차단돼요 (긴급용).

인바운드 첨부 파일은 활성 워크스페이스의 media/inbound/*에 스테이징돼요.

**docker.binds**는 추가적인 호스트 디렉토리를 마운트해요. 글로벌 및 에이전트별 바인딩이 병합돼요.

샌드박스 브라우저 (sandbox.browser.enabled): 컨테이너 내의 Chromium + CDP예요. noVNC URL이 시스템 프롬프트에 주입돼요. openclaw.json에 browser.enabled가 필요하지 않아요. noVNC 관찰자 액세스는 기본적으로 VNC 인증을 사용하며 OpenClaw는 (공유 URL에 비밀번호를 노출하는 대신) 수명이 짧은 토큰 URL을 내보내요.

  • allowHostControl: false (기본값)는 샌드박스 세션이 호스트 브라우저를 대상으로 하는 것을 차단해요.
  • network 기본값은 openclaw-sandbox-browser (전용 브릿지 네트워크)예요. 글로벌 브릿지 연결을 명시적으로 원하는 경우에만 bridge로 설정하세요.
  • cdpSourceRange는 선택적으로 컨테이너 에지에서의 CDP 인그레스를 CIDR 범위(예: 172.21.0.1/32)로 제한해요.
  • sandbox.browser.binds는 추가적인 호스트 디렉토리를 샌드박스 브라우저 컨테이너에만 마운트해요. 설정되면([] 포함) 브라우저 컨테이너에 대해 docker.binds를 대체해요.
  • 실행 기본값은 scripts/sandbox-browser-entrypoint.sh에 정의되어 있으며 컨테이너 호스트에 맞게 조정되어 있어요:
    • --remote-debugging-address=127.0.0.1
    • --remote-debugging-port=<OPENCLAW_BROWSER_CDP_PORT에서 파생됨>
    • --user-data-dir=${HOME}/.chrome
    • --no-first-run
    • --no-default-browser-check
    • --disable-3d-apis
    • --disable-gpu
    • --disable-software-rasterizer
    • --disable-dev-shm-usage
    • --disable-background-networking
    • --disable-features=TranslateUI
    • --disable-breakpad
    • --disable-crash-reporter
    • --renderer-process-limit=2
    • --no-zygote
    • --metrics-recording-only
    • --disable-extensions (기본 활성화)
    • --disable-3d-apis, --disable-software-rasterizer, --disable-gpu는 기본적으로 활성화되어 있으며, WebGL/3D 사용이 필요한 경우 OPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS=0으로 비활성화할 수 있어요.
    • 워크플로우가 확장에 의존하는 경우 OPENCLAW_BROWSER_DISABLE_EXTENSIONS=0으로 확장을 다시 활성화할 수 있어요.
    • --renderer-process-limit=2는 OPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT=<N>으로 변경할 수 있어요. Chromium의 기본 프로세스 제한을 사용하려면 0으로 설정하세요.
    • noSandbox가 활성화된 경우 --no-sandbox 및 --disable-setuid-sandbox가 추가돼요.
    • 기본값은 컨테이너 이미지 베이스라인이에요. 컨테이너 기본값을 변경하려면 커스텀 엔트리포인트가 있는 커스텀 브라우저 이미지를 사용하세요.

이미지 빌드:

Terminal window
scripts/sandbox-setup.sh # main sandbox image
scripts/sandbox-browser-setup.sh # optional browser image

agents.list (에이전트별 오버라이드)

섹션 제목: “agents.list (에이전트별 오버라이드)”
{
agents: {
list: [
{
id: "main",
default: true,
name: "Main Agent",
workspace: "~/.openclaw/workspace",
agentDir: "~/.openclaw/agents/main/agent",
model: "anthropic/claude-opus-4-6", // or { primary, fallbacks }
params: { cacheRetention: "none" }, // overrides matching defaults.models params by key
identity: {
name: "Samantha",
theme: "helpful sloth",
emoji: "🦥",
avatar: "avatars/samantha.png",
},
groupChat: { mentionPatterns: ["@openclaw"] },
sandbox: { mode: "off" },
runtime: {
type: "acp",
acp: {
agent: "codex",
backend: "acpx",
mode: "persistent",
cwd: "/workspace/openclaw",
},
},
subagents: { allowAgents: ["*"] },
tools: {
profile: "coding",
allow: ["browser"],
deny: ["canvas"],
elevated: { enabled: true },
},
},
],
},
}

채널이나 계정별로 응답 접두사를 다르게 설정할 수 있어요. channels.<channel>.responsePrefix 또는 channels.<channel>.accounts.<id>.responsePrefix를 사용하면 돼요.

우선순위는 계정 → 채널 → 글로벌 순으로 적용돼요. ""로 설정하면 기능을 끄고 상위 설정을 무시해요. "auto"로 설정하면 [{identity.name}] 형식을 자동으로 사용해요.

템플릿 변수:

변수설명예시
{model}짧은 모델 이름claude-opus-4-6
{modelFull}전체 모델 식별자anthropic/claude-opus-4-6
{provider}프로바이더 이름anthropic
{thinkingLevel}현재 사고(thinking) 수준high, low, off
{identity.name}에이전트 식별 이름("auto"와 동일)

변수는 대소문자를 구분하지 않아요. {think}는 {thinkingLevel}의 별칭으로 쓸 수 있어요.

  • 기본적으로 활성화된 에이전트의 identity.emoji를 사용하고, 없으면 "👀"를 사용해요. ""로 설정하면 끌 수 있어요.
  • 채널별 설정: channels.<channel>.ackReaction, channels.<channel>.accounts.<id>.ackReaction.
  • 우선순위: 계정 → 채널 → messages.ackReaction → ID 기본값 순이에요.
  • 범위(Scope): group-mentions (기본값), group-all, direct, all.
  • removeAckAfterReply: 답장 후 확인 반응을 삭제해요 (Slack/Discord/Telegram/Google Chat만 지원).

인바운드 디바운스 (Inbound debounce)

섹션 제목: “인바운드 디바운스 (Inbound debounce)”

동일한 발신자가 빠르게 보내는 여러 텍스트 메시지를 하나의 에이전트 턴으로 묶어줘요. 미디어나 첨부 파일은 즉시 처리되고, 제어 명령은 디바운싱을 거치지 않고 바로 실행돼요.

{
messages: {
tts: {
auto: "always", // off | always | inbound | tagged
mode: "final", // final | all
provider: "elevenlabs",
summaryModel: "openai/gpt-4.1-mini",
modelOverrides: { enabled: true },
maxTextLength: 4000,
timeoutMs: 30000,
prefsPath: "~/.openclaw/settings/tts.json",
elevenlabs: {
apiKey: "elevenlabs_api_key",
baseUrl: "https://api.elevenlabs.io",
voiceId: "voice_id",
modelId: "eleven_multilingual_v2",
seed: 42,
applyTextNormalization: "auto",
languageCode: "en",
voiceSettings: {
stability: 0.5,
similarityBoost: 0.75,
style: 0.0,
useSpeakerBoost: true,
speed: 1.0,
},
},
openai: {
apiKey: "openai_api_key",
baseUrl: "https://api.openai.com/v1",
model: "gpt-4o-mini-tts",
voice: "alloy",
},
},
},
}
  • auto는 자동 TTS를 제어해요. 세션별로 /tts off|always|inbound|tagged 명령어를 통해 설정을 바꿀 수 있어요.
  • summaryModel은 자동 요약을 위해 agents.defaults.model.primary 설정을 덮어써요.
  • modelOverrides는 기본적으로 활성화되어 있고, modelOverrides.allowProvider는 기본값이 false예요.
  • API 키는 ELEVENLABS_API_KEY/XI_API_KEY 및 OPENAI_API_KEY 환경 변수를 참조해요.
  • openai.baseUrl로 OpenAI TTS 엔드포인트를 변경할 수 있어요. 설정 파일, OPENAI_TTS_BASE_URL, https://api.openai.com/v1 순으로 확인해요.
  • openai.baseUrl이 OpenAI가 아닌 엔드포인트를 가리키면, OpenClaw는 이를 OpenAI 호환 TTS 서버로 간주하고 모델이나 음성 검증을 유연하게 처리해요.

macOS/iOS/Android에서 사용하는 Talk 모드의 기본 설정이에요.

{
talk: {
voiceId: "elevenlabs_voice_id",
voiceAliases: {
Clawd: "EXAVITQu4vr4xnSDxMaL",
Roger: "CwhRBWXzGAHq8TQ4Fs17",
},
modelId: "eleven_v3",
outputFormat: "mp3_44100_128",
apiKey: "elevenlabs_api_key",
silenceTimeoutMs: 1500,
interruptOnSpeech: true,
},
}
  • Voice ID는 ELEVENLABS_VOICE_ID 또는 SAG_VOICE_ID 환경 변수를 사용해요.
  • apiKey와 providers.*.apiKey에는 일반 문자열이나 SecretRef 객체를 넣을 수 있어요.
  • ELEVENLABS_API_KEY는 Talk API 키가 설정되지 않았을 때만 사용돼요.
  • voiceAliases를 설정하면 Talk 명령에서 친숙한 이름을 사용할 수 있어요.
  • silenceTimeoutMs는 사용자가 말을 멈춘 후 텍스트 변환 결과를 보낼 때까지 기다리는 시간이에요. 설정하지 않으면 플랫폼 기본값(macOS/Android 700ms, iOS 900ms)을 따라요.

tools.profile은 tools.allow/tools.deny를 적용하기 전의 기본 허용 목록을 설정해요.

로컬 온보딩 시 별도 설정이 없으면 새로운 로컬 설정은 tools.profile: "coding"으로 기본 지정돼요 (기존의 명시적인 프로필은 유지돼요).

프로필포함 내용
minimalsession_status만 포함
codinggroup:fs, group:runtime, group:sessions, group:memory, image
messaginggroup:messaging, sessions_list, sessions_history, sessions_send, session_status
full제한 없음 (설정하지 않은 것과 동일)
그룹도구
group:runtimeexec, process (bash는 exec의 별칭으로 허용돼요)
group:fsread, write, edit, apply_patch
group:sessionssessions_list, sessions_history, sessions_send, sessions_spawn, session_status
group:memorymemory_search, memory_get
group:webweb_search, web_fetch
group:uibrowser, canvas
group:automationcron, gateway
group:messagingmessage
group:nodesnodes
group:openclaw모든 내장 도구 (프로바이더 플러그인 제외)

글로벌 도구 허용/거부 정책이에요 (거부가 우선해요). 대소문자를 구분하지 않으며 * 와일드카드를 지원해요. Docker 샌드박스가 꺼져 있어도 적용돼요.

{
tools: { deny: ["browser", "canvas"] },
}

특정 프로바이더나 모델에 대해 도구를 더 제한할 수 있어요. 적용 순서는 기본 프로필 → 프로바이더 프로필 → 허용/거부 순이에요.

{
tools: {
profile: "coding",
byProvider: {
"google-antigravity": { profile: "minimal" },
"openai/gpt-5.2": { allow: ["group:fs", "sessions_list"] },
},
},
}

호스트에 대한 승인된(elevated) 실행 권한을 제어해요.

{
tools: {
elevated: {
enabled: true,
allowFrom: {
whatsapp: ["+15555550123"],
discord: ["1234567890123", "987654321098765432"],
},
},
},
}
  • 에이전트별 설정(agents.list[].tools.elevated)은 권한을 더 축소하는 방향으로만 작동해요.
  • /elevated on|off|ask|full 명령어로 세션별 상태를 저장할 수 있고, 인라인 명령은 단일 메시지에만 적용돼요.
  • 승인된 exec는 호스트에서 직접 실행되며 샌드박스를 우회해요.
{
tools: {
exec: {
backgroundMs: 10000,
timeoutSec: 1800,
cleanupMs: 1800000,
notifyOnExit: true,
notifyOnExitEmptySuccess: false,
applyPatch: {
enabled: false,
allowModels: ["gpt-5.2"],
},
},
},
}

도구 루프 감지 (tools.loopDetection)

섹션 제목: “도구 루프 감지 (tools.loopDetection)”

도구 루프 안전 점검은 기본적으로 비활성화되어 있어요. 감지 기능을 켜려면 enabled: true로 설정하세요. 글로벌 설정은 tools.loopDetection에서 하고, 에이전트별로 agents.list[].tools.loopDetection에서 덮어쓸 수 있어요.

{
tools: {
loopDetection: {
enabled: true,
historySize: 30,
warningThreshold: 10,
criticalThreshold: 20,
globalCircuitBreakerThreshold: 30,
detectors: {
genericRepeat: true,
knownPollNoProgress: true,
pingPong: true,
},
},
},
}
  • historySize: 루프 분석을 위해 보관할 최대 도구 호출 기록 수예요.
  • warningThreshold: 진전 없는 반복 패턴이 나타날 때 경고를 보내는 임계값이에요.
  • criticalThreshold: 심각한 루프를 차단하기 위한 더 높은 임계값이에요.
  • globalCircuitBreakerThreshold: 어떤 경우든 진전 없이 실행될 때 강제로 중단하는 임계값이에요.
  • detectors.genericRepeat: 동일한 도구와 인자로 반복 호출할 때 경고해요.
  • detectors.knownPollNoProgress: 알려진 폴링 도구(process.poll, command_status 등)에서 경고하거나 차단해요.
  • detectors.pingPong: 두 가지 도구가 진전 없이 번갈아 호출되는 패턴을 경고하거나 차단해요.
  • warningThreshold >= criticalThreshold 이거나 criticalThreshold >= globalCircuitBreakerThreshold 이면 유효성 검사에 실패해요.
{
tools: {
web: {
search: {
enabled: true,
apiKey: "brave_api_key", // or BRAVE_API_KEY env
maxResults: 5,
timeoutSeconds: 30,
cacheTtlMinutes: 15,
},
fetch: {
enabled: true,
maxChars: 50000,
maxCharsCap: 50000,
timeoutSeconds: 30,
cacheTtlMinutes: 15,
userAgent: "custom-ua",
},
},
},
}

인바운드 미디어(이미지/오디오/비디오) 이해 기능을 설정해요.

{
tools: {
media: {
concurrency: 2,
audio: {
enabled: true,
maxBytes: 20971520,
scope: {
default: "deny",
rules: [{ action: "allow", match: { chatType: "direct" } }],
},
models: [
{ provider: "openai", model: "gpt-4o-mini-transcribe" },
{ type: "cli", command: "whisper", args: ["--model", "base", "{{MediaPath}}"] },
],
},
video: {
enabled: true,
maxBytes: 52428800,
models: [{ provider: "google", model: "gemini-3-flash-preview" }],
},
},
},
}
미디어 모델 항목 필드

프로바이더 항목 (type: "provider" 또는 생략):

  • provider: API 프로바이더 ID (openai, anthropic, google/gemini, groq 등)
  • model: 모델 ID 덮어쓰기
  • profile / preferredProfile: auth-profiles.json 프로필 선택

CLI 항목 (type: "cli"):

  • command: 실행할 파일
  • args: 템플릿 인자 ({{MediaPath}}, {{Prompt}}, {{MaxChars}} 등 지원)

공통 필드:

  • capabilities: 선택적 목록 (image, audio, video). 기본값: openai/anthropic/minimax → image, google → image+audio+video, groq → audio.
  • prompt, maxChars, maxBytes, timeoutSeconds, language: 항목별 덮어쓰기.
  • 실패 시 다음 항목으로 넘어갑니다.

프로바이더 인증 순서: auth-profiles.json → 환경 변수 → models.providers.*.apiKey.

{
tools: {
agentToAgent: {
enabled: false,
allow: ["home", "work"],
},
},
}

세션 도구(sessions_list, sessions_history, sessions_send)가 접근할 수 있는 세션을 제어해요.

기본값은 tree (현재 세션 + 하위 에이전트 등 현재 세션에서 파생된 세션)예요.

{
tools: {
sessions: {
// "self" | "tree" | "agent" | "all"
visibility: "tree",
},
},
}

참고:

  • self: 현재 세션 키만 가능해요.
  • tree: 현재 세션과 거기서 파생된 세션(서브 에이전트)만 가능해요.
  • agent: 현재 에이전트 ID에 속한 모든 세션이 가능해요.
  • all: 모든 세션이 가능해요. 다른 에이전트를 대상으로 하려면 tools.agentToAgent 설정이 여전히 필요해요.
  • 샌드박스 제한: 현재 세션이 샌드박스 상태이고 agents.defaults.sandbox.sessionToolsVisibility="spawned"인 경우, tools.sessions.visibility="all"로 설정해도 tree로 강제 제한돼요.

sessions_spawn에 대한 인라인 첨부 파일 지원을 제어해요.

{
tools: {
sessions_spawn: {
attachments: {
enabled: false, // opt-in: set true to allow inline file attachments
maxTotalBytes: 5242880, // 5 MB total across all files
maxFiles: 50,
maxFileBytes: 1048576, // 1 MB per file
retainOnSessionKeep: false, // keep attachments when cleanup="keep"
},
},
},
}

참고:

  • 첨부 파일은 runtime: "subagent"에서만 지원돼요. ACP 런타임은 이를 거부해요.
  • 파일은 자식 워크스페이스의 .openclaw/attachments/<uuid>/ 경로에 생성되며 .manifest.json이 함께 생성돼요.
  • 첨부 파일 내용은 대화 기록 저장 시 자동으로 가려져요(redacted).
  • Base64 입력은 엄격한 검증을 거치며 디코딩 전 크기 제한이 적용돼요.
  • 파일 권한은 디렉토리 0700, 파일 0600으로 설정돼요.
  • 정리는 cleanup 정책을 따라요. delete는 항상 삭제하고, keep은 retainOnSessionKeep: true일 때만 유지해요.
{
agents: {
defaults: {
subagents: {
model: "minimax/MiniMax-M2.5",
maxConcurrent: 1,
runTimeoutSeconds: 900,
archiveAfterMinutes: 60,
},
},
},
}
  • model: 생성된 서브 에이전트의 기본 모델이에요. 생략하면 호출자의 모델을 상속받아요.
  • runTimeoutSeconds: 도구 호출 시 지정하지 않았을 때의 기본 타임아웃(초)이에요. 0은 타임아웃 없음을 의미해요.
  • 서브 에이전트별 도구 정책: tools.subagents.tools.allow / tools.subagents.tools.deny.

커스텀 프로바이더 및 베이스 URL (Custom providers and base URLs)

섹션 제목: “커스텀 프로바이더 및 베이스 URL (Custom providers and base URLs)”

OpenClaw는 pi-coding-agent 모델 카탈로그를 사용해요. 설정 파일의 models.providers나 ~/.openclaw/agents/<agentId>/agent/models.json을 통해 커스텀 프로바이더를 추가할 수 있어요.

{
models: {
mode: "merge", // merge (기본값) | replace
providers: {
"custom-proxy": {
baseUrl: "http://localhost:4000/v1",
apiKey: "LITELLM_KEY",
api: "openai-completions", // openai-completions | openai-responses | anthropic-messages | google-generative-ai
models: [
{
id: "llama-3.1-8b",
name: "Llama 3.1 8B",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128000,
maxTokens: 32000,
},
],
},
},
},
}
  • 커스텀 인증이 필요한 경우 authHeader: true와 headers를 사용하세요.
  • OPENCLAW_AGENT_DIR (또는 PI_CODING_AGENT_DIR) 환경 변수로 에이전트 설정 루트를 변경할 수 있어요.
  • 프로바이더 ID가 겹칠 때의 병합 우선순위:
    • 에이전트 models.json의 비어 있지 않은 baseUrl이 우선해요.
    • 해당 프로바이더가 SecretRef로 관리되지 않는 경우, 에이전트의 비어 있지 않은 apiKey가 우선해요.
    • SecretRef로 관리되는 프로바이더의 apiKey는 소스 마커(환경 변수는 ENV_VAR_NAME, 파일/실행 참조는 secretref-managed)에서 새로 고쳐져요.
    • SecretRef로 관리되는 프로바이더 헤더 값도 소스 마커에서 새로 고쳐져요.
    • 에이전트의 apiKey/baseUrl이 비어 있으면 설정 파일의 models.providers를 사용해요.
    • 모델의 contextWindow/maxTokens는 명시적 설정과 카탈로그 값 중 더 큰 값을 사용해요.
    • 설정을 통해 models.json을 완전히 새로 쓰려면 models.mode: "replace"를 사용하세요.
    • 마커 유지는 소스 권한을 가져요. 마커는 런타임의 비밀값이 아니라 활성 소스 설정 스냅샷(해석 전)에서 작성돼요.
  • models.mode: 프로바이더 카탈로그 동작 (merge 또는 replace).
  • models.providers: 프로바이더 ID를 키로 하는 커스텀 프로바이더 맵.
  • models.providers.*.api: 요청 어댑터 (openai-completions, openai-responses, anthropic-messages, google-generative-ai 등).
  • models.providers.*.apiKey: 프로바이더 인증 정보 (SecretRef/환경 변수 권장).
  • models.providers.*.auth: 인증 전략 (api-key, token, oauth, aws-sdk).
  • models.providers.*.injectNumCtxForOpenAICompat: Ollama + openai-completions 사용 시 요청에 options.num_ctx 주입 여부 (기본값: true).
  • models.providers.*.authHeader: 필요한 경우 Authorization 헤더에 인증 정보 강제 포함.
  • models.providers.*.baseUrl: 업스트림 API 베이스 URL.
  • models.providers.*.headers: 프록시/테넌트 라우팅을 위한 추가 정적 헤더.
  • models.providers.*.models: 명시적인 프로바이더 모델 카탈로그 항목.
  • models.providers.*.models.*.compat.supportsDeveloperRole: 선택적 호환성 힌트. api: "openai-completions"이면서 baseUrl이 OpenAI 공식 주소가 아니면 OpenClaw는 런타임에 이를 false로 강제해요.
  • models.bedrockDiscovery: Bedrock 자동 감지 설정.
  • models.bedrockDiscovery.enabled: 감지 폴링 활성화 여부.
  • models.bedrockDiscovery.region: 감지할 AWS 리전.
  • models.bedrockDiscovery.providerFilter: 특정 프로바이더 ID만 감지하도록 필터링.
  • models.bedrockDiscovery.refreshInterval: 감지 새로고침 간격.
  • models.bedrockDiscovery.defaultContextWindow: 감지된 모델의 기본 컨텍스트 창 크기.
  • models.bedrockDiscovery.defaultMaxTokens: 감지된 모델의 기본 최대 출력 토큰 수.

Cerebras (GLM 4.6 / 4.7)

{
env: { CEREBRAS_API_KEY: "sk-..." },
agents: {
defaults: {
model: {
primary: "cerebras/zai-glm-4.7",
fallbacks: ["cerebras/zai-glm-4.6"],
},
models: {
"cerebras/zai-glm-4.7": { alias: "GLM 4.7 (Cerebras)" },
"cerebras/zai-glm-4.6": { alias: "GLM 4.6 (Cerebras)" },
},
},
},
models: {
mode: "merge",
providers: {
cerebras: {
baseUrl: "https://api.cerebras.ai/v1",
apiKey: "${CEREBRAS_API_KEY}",
api: "openai-completions",
models: [
{ id: "zai-glm-4.7", name: "GLM 4.7 (Cerebras)" },
{ id: "zai-glm-4.6", name: "GLM 4.6 (Cerebras)" },
],
},
},
},
}

Cerebras를 사용하려면 cerebras/zai-glm-4.7을, Z.AI 직접 연결은 zai/glm-4.7을 사용하세요.

OpenCode

{
agents: {
defaults: {
model: { primary: "opencode/claude-opus-4-6" },
models: { "opencode/claude-opus-4-6": { alias: "Opus" } },
},
},
}

OPENCODE_API_KEY (또는 OPENCODE_ZEN_API_KEY)를 설정하세요. Zen 카탈로그는 opencode/...를, Go 카탈로그는 opencode-go/... 참조를 사용하세요. 단축 명령어: openclaw onboard --auth-choice opencode-zen 또는 openclaw onboard --auth-choice opencode-go.

Z.AI (GLM-4.7)

{
agents: {
defaults: {
model: { primary: "zai/glm-4.7" },
models: { "zai/glm-4.7": {} },
},
},
}

ZAI_API_KEY를 설정하세요. z.ai/*와 z-ai/* 모두 허용되는 별칭이에요. 단축 명령어: openclaw onboard --auth-choice zai-api-key.

  • 일반 엔드포인트: https://api.z.ai/api/paas/v4
  • 코딩 엔드포인트 (기본값): https://api.z.ai/api/coding/paas/v4
  • 일반 엔드포인트를 쓰려면 베이스 URL을 덮어쓴 커스텀 프로바이더를 정의하세요.

Moonshot AI (Kimi)

{
env: { MOONSHOT_API_KEY: "sk-..." },
agents: {
defaults: {
model: { primary: "moonshot/kimi-k2.5" },
models: { "moonshot/kimi-k2.5": { alias: "Kimi K2.5" } },
},
},
models: {
mode: "merge",
providers: {
moonshot: {
baseUrl: "https://api.moonshot.ai/v1",
apiKey: "${MOONSHOT_API_KEY}",
api: "openai-completions",
models: [
{
id: "kimi-k2.5",
name: "Kimi K2.5",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 256000,
maxTokens: 8192,
},
],
},
},
},
}

중국 엔드포인트의 경우: baseUrl: "https://api.moonshot.cn/v1" 또는 openclaw onboard --auth-choice moonshot-api-key-cn.

Kimi Coding

{
env: { KIMI_API_KEY: "sk-..." },
agents: {
defaults: {
model: { primary: "kimi-coding/k2p5" },
models: { "kimi-coding/k2p5": { alias: "Kimi K2.5" } },
},
},
}

Anthropic 호환 내장 프로바이더예요. 단축 명령어: openclaw onboard --auth-choice kimi-code-api-key.

Synthetic (Anthropic 호환)

{
env: { SYNTHETIC_API_KEY: "sk-..." },
agents: {
defaults: {
model: { primary: "synthetic/hf:MiniMaxAI/MiniMax-M2.5" },
models: { "synthetic/hf:MiniMaxAI/MiniMax-M2.5": { alias: "MiniMax M2.5" } },
},
},
models: {
mode: "merge",
providers: {
synthetic: {
baseUrl: "https://api.synthetic.new/anthropic",
apiKey: "${SYNTHETIC_API_KEY}",
api: "anthropic-messages",
models: [
{
id: "hf:MiniMaxAI/MiniMax-M2.5",
name: "MiniMax M2.5",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 192000,
maxTokens: 65536,
},
],
},
},
},
}

베이스 URL에서 /v1은 제외해야 해요 (Anthropic 클라이언트가 자동으로 붙여요). 단축 명령어: openclaw onboard --auth-choice synthetic-api-key.

MiniMax M2.5 (직접 연결)

{
agents: {
defaults: {
model: { primary: "minimax/MiniMax-M2.5" },
models: {
"minimax/MiniMax-M2.5": { alias: "Minimax" },
},
},
},
models: {
mode: "merge",
providers: {
minimax: {
baseUrl: "https://api.minimax.io/anthropic",
apiKey: "${MINIMAX_API_KEY}",
api: "anthropic-messages",
models: [
{
id: "MiniMax-M2.5",
name: "MiniMax M2.5",
reasoning: false,
input: ["text"],
cost: { input: 15, output: 60, cacheRead: 2, cacheWrite: 10 },
contextWindow: 200000,
maxTokens: 8192,
},
],
},
},
},
}

MINIMAX_API_KEY를 설정하세요. 단축 명령어: openclaw onboard --auth-choice minimax-api.

로컬 모델 (LM Studio)

로컬 모델 문서를 참고하세요. 요약하자면, 고성능 하드웨어에서 LM Studio Responses API를 통해 MiniMax M2.5를 실행하고, 실패 시를 대비해 호스팅 모델을 병합해 두는 것이 좋아요.


AI Setup Assistant

{
skills: {
allowBundled: ["gemini", "peekaboo"],
load: {
extraDirs: ["~/Projects/agent-scripts/skills"],
},
install: {
preferBrew: true,
nodeManager: "npm", // npm | pnpm | yarn
},
entries: {
"nano-banana-pro": {
apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" }, // or plaintext string
env: { GEMINI_API_KEY: "GEMINI_KEY_HERE" },
},
peekaboo: { enabled: true },
sag: { enabled: false },
},
},
}
  • allowBundled: 번들된 스킬에 대해서만 적용되는 선택적 허용 목록이에요 (관리형/워크스페이스 스킬은 영향을 받지 않아요).
  • entries.<skillKey>.enabled: false: 스킬이 번들되어 있거나 설치되어 있더라도 비활성화할 수 있어요.
  • entries.<skillKey>.apiKey: 주요 환경 변수를 선언하는 스킬을 위한 편의 필드예요 (일반 텍스트 문자열이나 SecretRef 객체를 사용할 수 있어요).

{
plugins: {
enabled: true,
allow: ["voice-call"],
deny: [],
load: {
paths: ["~/Projects/oss/voice-call-extension"],
},
entries: {
"voice-call": {
enabled: true,
hooks: {
allowPromptInjection: false,
},
config: { provider: "twilio" },
},
},
},
}
  • ~/.openclaw/extensions, <workspace>/.openclaw/extensions, 그리고 plugins.load.paths에서 플러그인을 로드해요.
  • 설정 변경 사항을 적용하려면 Gateway를 다시 시작해야 해요.
  • allow: 선택적 허용 목록이에요 (목록에 있는 플러그인만 로드돼요). deny 설정이 있는 경우 이 설정이 우선해요.
  • plugins.entries.<id>.apiKey: 플러그인 수준에서 사용할 수 있는 API Key 편의 필드예요 (플러그인이 이를 지원하는 경우).
  • plugins.entries.<id>.env: 플러그인 범위의 환경 변수 맵이에요.
  • plugins.entries.<id>.hooks.allowPromptInjection: 이 값이 false이면 코어에서 before_prompt_build를 차단하고, 레거시 before_agent_start에서 전달되는 프롬프트 변조 필드를 무시해요. 이때 레거시 modelOverride와 providerOverride는 그대로 유지돼요.
  • plugins.entries.<id>.config: 플러그인에서 정의한 설정 객체예요 (플러그인 스키마에 의해 검증돼요).
  • plugins.slots.memory: 활성화할 메모리 플러그인 ID를 선택하세요. 메모리 플러그인을 사용하지 않으려면 "none"으로 설정하면 돼요.
  • plugins.slots.contextEngine: 활성화할 컨텍스트 엔진 플러그인 ID를 선택하세요. 별도로 설치하고 선택하지 않으면 기본값은 "legacy"로 설정돼요.
  • plugins.installs: openclaw plugins update 명령어가 사용하는 CLI 관리 설치 메타데이터예요.
    • source, spec, sourcePath, installPath, version, resolvedName, resolvedVersion, resolvedSpec, integrity, shasum, resolvedAt, installedAt 정보를 포함하고 있어요.
    • plugins.installs.* 영역은 관리되는 상태이므로 직접 수정하기보다는 CLI 명령어를 사용하는 것을 추천해요.

Plugins 문서를 확인해 보세요.


{
browser: {
enabled: true,
evaluateEnabled: true,
defaultProfile: "chrome",
ssrfPolicy: {
dangerouslyAllowPrivateNetwork: true, // default trusted-network mode
// allowPrivateNetwork: true, // legacy alias
// hostnameAllowlist: ["*.example.com", "example.com"],
// allowedHostnames: ["localhost"],
},
profiles: {
openclaw: { cdpPort: 18800, color: "#FF4500" },
work: { cdpPort: 18801, color: "#0066CC" },
remote: { cdpUrl: "http://10.0.0.42:9222", color: "#00AA00" },
},
color: "#FF4500",
// headless: false,
// noSandbox: false,
// extraArgs: [],
// relayBindHost: "0.0.0.0", // only when the extension relay must be reachable across namespaces (for example WSL2)
// executablePath: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
// attachOnly: false,
},
}
  • evaluateEnabled: false로 설정하면 act:evaluate와 wait --fn 기능을 사용할 수 없어요.
  • ssrfPolicy.dangerouslyAllowPrivateNetwork는 설정하지 않았을 때 기본값이 true예요 (신뢰할 수 있는 네트워크 모델).
  • 엄격한 공용 네트워크 전용 브라우징이 필요하다면 ssrfPolicy.dangerouslyAllowPrivateNetwork: false로 설정하세요.
  • ssrfPolicy.allowPrivateNetwork는 레거시 별칭으로 계속 지원돼요.
  • 엄격 모드에서는 ssrfPolicy.hostnameAllowlist와 ssrfPolicy.allowedHostnames를 사용해 명시적으로 예외 대상을 지정할 수 있어요.
  • 원격 프로필은 attach-only 모드로 동작해요 (시작/중지/재설정 기능 비활성화).
  • 자동 감지 순서: Chromium 기반 기본 브라우저 → Chrome → Brave → Edge → Chromium → Chrome Canary 순서로 감지해요.
  • 제어 서비스: 루프백 전용이에요 (포트는 gateway.port에서 파생되며 기본값은 18791이에요).
  • extraArgs를 통해 로컬 Chromium 시작 시 추가적인 실행 플래그를 덧붙일 수 있어요 (예: --disable-gpu, 창 크기 지정, 디버그 플래그 등).
  • relayBindHost는 Chrome 확장 프로그램 릴레이가 대기하는 주소를 변경해요. 루프백 전용 접근을 원한다면 비워두세요. WSL2와 같이 네임스페이스 경계를 넘어야 하고 호스트 네트워크를 이미 신뢰할 수 있는 경우에만 0.0.0.0 같은 명시적인 비-루프백 바인드 주소를 설정하세요.

{
ui: {
seamColor: "#FF4500",
assistant: {
name: "OpenClaw",
avatar: "CB", // emoji, short text, image URL, or data URI
},
},
}
  • seamColor: 네이티브 앱 UI 크롬의 강조 색상이에요 (Talk Mode 버블 색상 등).
  • assistant: UI 정체성 오버라이드를 제어해요. 설정하지 않으면 활성화된 에이전트의 정체성을 기본으로 사용해요.
{
gateway: {
mode: "local", // local | remote
port: 18789,
bind: "loopback",
auth: {
mode: "token", // none | token | password | trusted-proxy
token: "your-token",
// password: "your-password", // or OPENCLAW_GATEWAY_PASSWORD
// trustedProxy: { userHeader: "x-forwarded-user" }, // for mode=trusted-proxy; see /gateway/trusted-proxy-auth
allowTailscale: true,
rateLimit: {
maxAttempts: 10,
windowMs: 60000,
lockoutMs: 300000,
exemptLoopback: true,
},
},
tailscale: {
mode: "off", // off | serve | funnel
resetOnExit: false,
},
controlUi: {
enabled: true,
basePath: "/openclaw",
// root: "dist/control-ui",
// allowedOrigins: ["https://control.example.com"], // required for non-loopback Control UI
// dangerouslyAllowHostHeaderOriginFallback: false, // dangerous Host-header origin fallback mode
// allowInsecureAuth: false,
// dangerouslyDisableDeviceAuth: false,
},
remote: {
url: "ws://gateway.tailnet:18789",
transport: "ssh", // ssh | direct
token: "your-token",
// password: "your-password",
},
trustedProxies: ["10.0.0.1"],
// Optional. Default false.
allowRealIpFallback: false,
tools: {
// Additional /tools/invoke HTTP denies
deny: ["browser"],
// Remove tools from the default HTTP deny list
allow: ["gateway"],
},
},
}
Gateway 필드 상세 정보
  • mode: local (Gateway 실행) 또는 remote (원격 Gateway 연결)를 설정해요. local이 아니면 Gateway가 시작되지 않아요.
  • port: WS와 HTTP를 위한 단일 멀티플렉싱 포트예요. 우선순위는 --port > OPENCLAW_GATEWAY_PORT > gateway.port > 18789 순서예요.
  • bind: auto, loopback (기본값), lan (0.0.0.0), tailnet (Tailscale IP 전용), 또는 custom을 사용할 수 있어요.
  • 레거시 bind 별칭: gateway.bind에는 호스트 별칭(0.0.0.0, 127.0.0.1, localhost, ::, ::1) 대신 bind 모드 값(auto, loopback, lan, tailnet, custom)을 사용해 주세요.
  • Docker 참고: 기본값인 loopback은 컨테이너 내부의 127.0.0.1에서 리스닝해요. Docker 브리지 네트워킹(-p 18789:18789)을 사용하면 트래픽이 eth0으로 들어오기 때문에 Gateway에 접속할 수 없어요. --network host를 사용하거나, 모든 인터페이스에서 리스닝하도록 bind: "lan" (또는 bind: "custom"과 customBindHost: "0.0.0.0")으로 설정하세요.
  • Auth: 기본적으로 인증이 필요해요. loopback이 아닌 bind의 경우 공유 token/password가 있어야 해요. 온보딩 마법사가 기본적으로 토큰을 생성해 줘요.
  • gateway.auth.token과 gateway.auth.password가 모두 설정된 경우(SecretRefs 포함), gateway.auth.mode를 token이나 password로 명확히 지정해야 해요. 둘 다 설정되어 있는데 모드가 지정되지 않으면 시작이나 서비스 설치/복구 프로세스가 실패해요.
  • gateway.auth.mode: "none": 인증을 사용하지 않는 모드예요. 신뢰할 수 있는 로컬 loopback 환경에서만 사용하세요. 온보딩 프롬프트에서는 이 옵션을 제공하지 않아요.
  • gateway.auth.mode: "trusted-proxy": 인증을 ID 인식 리버스 프록시에 위임하고, gateway.trustedProxies에서 오는 ID 헤더를 신뢰해요 (Trusted Proxy Auth 참고).
  • gateway.auth.allowTailscale: true로 설정하면 Tailscale Serve ID 헤더로 Control UI/WebSocket 인증을 통과할 수 있어요 (tailscale whois로 확인). 하지만 HTTP API 엔드포인트는 여전히 token/password 인증이 필요해요. 이 토큰 없는 흐름은 Gateway 호스트를 신뢰할 수 있다고 가정해요. tailscale.mode = "serve"일 때 기본값은 true예요.
  • gateway.auth.rateLimit: 선택 사항인 인증 실패 제한 기능이에요. 클라이언트 IP와 인증 범위(공유 비밀키와 디바이스 토큰은 독립적으로 추적됨)별로 적용돼요. 차단된 시도는 429 에러와 Retry-After를 반환해요.
    • gateway.auth.rateLimit.exemptLoopback은 기본값이 true예요. 테스트 환경이나 엄격한 프록시 배포를 위해 localhost 트래픽도 제한하고 싶다면 false로 설정하세요.
  • 브라우저 기반의 WS 인증 시도는 loopback 예외 없이 항상 제한돼요 (브라우저를 통한 localhost 무차별 대입 공격 방어).
  • tailscale.mode: serve (tailnet 전용, loopback bind) 또는 funnel (공개, 인증 필요) 중 선택해요.
  • controlUi.allowedOrigins: Gateway WebSocket 연결을 위한 브라우저 오리진 허용 목록이에요. 브라우저 클라이언트가 loopback이 아닌 오리진에서 접속할 때 필요해요.
  • controlUi.dangerouslyAllowHostHeaderOriginFallback: Host 헤더 오리진 정책에 의도적으로 의존하는 배포를 위한 위험한 모드예요. Host 헤더 오리진 폴백을 활성화해요.
  • remote.transport: ssh (기본값) 또는 direct (ws/wss)를 선택해요. direct의 경우 remote.url은 반드시 ws://나 wss://여야 해요.
  • OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1: 신뢰할 수 있는 사설 네트워크 IP에 대해 일반 텍스트 ws:// 연결을 허용하는 클라이언트 측 강제 오버라이드 설정이에요. 기본적으로 일반 텍스트는 loopback만 허용돼요.
  • gateway.remote.token / .password는 원격 클라이언트의 자격 증명 필드예요. 이것만으로는 Gateway 인증이 구성되지 않아요.
  • 로컬 Gateway 호출 경로는 gateway.auth.*가 설정되지 않았을 때만 gateway.remote.*를 폴백으로 사용할 수 있어요.
  • gateway.auth.token / gateway.auth.password가 SecretRef를 통해 명시적으로 설정되었지만 해결되지 않은 경우, 보안을 위해 원격 폴백 없이 실패 처리돼요.
  • trustedProxies: TLS를 종료하는 리버스 프록시 IP 목록이에요. 직접 제어하는 프록시만 등록하세요.
  • allowRealIpFallback: true인 경우, X-Forwarded-For가 없으면 Gateway가 X-Real-IP를 수락해요. 기본값은 안전을 위해 false예요.
  • gateway.tools.deny: HTTP POST /tools/invoke에서 차단할 추가 도구 이름 목록이에요 (기본 차단 목록에 추가됨).
  • gateway.tools.allow: 기본 HTTP 차단 목록에서 제거할 도구 이름 목록이에요.
  • Chat Completions: 기본적으로 비활성화되어 있어요. gateway.http.endpoints.chatCompletions.enabled: true로 활성화할 수 있어요.
  • Responses API: gateway.http.endpoints.responses.enabled로 설정해요.
  • Responses URL 입력 강화 설정:
    • gateway.http.endpoints.responses.maxUrlParts
    • gateway.http.endpoints.responses.files.urlAllowlist
    • gateway.http.endpoints.responses.images.urlAllowlist
  • 선택 사항인 응답 보안 헤더:
    • gateway.http.securityHeaders.strictTransportSecurity (직접 제어하는 HTTPS 오리진에만 설정하세요. Trusted Proxy Auth 참고)

고유한 포트와 상태 디렉토리를 사용하여 한 호스트에서 여러 Gateway를 실행할 수 있어요.

Terminal window
OPENCLAW_CONFIG_PATH=~/.openclaw/a.json \
OPENCLAW_STATE_DIR=~/.openclaw-a \
openclaw gateway --port 19001

편의를 위한 플래그: --dev (~/.openclaw-dev와 포트 19001 사용), --profile <name> (~/.openclaw-<name> 사용).

자세한 내용은 Multiple Gateways를 확인해 보세요.


{
hooks: {
enabled: true,
token: "shared-secret",
path: "/hooks",
maxBodyBytes: 262144,
defaultSessionKey: "hook:ingress",
allowRequestSessionKey: false,
allowedSessionKeyPrefixes: ["hook:"],
allowedAgentIds: ["hooks", "main"],
presets: ["gmail"],
transformsDir: "~/.openclaw/hooks/transforms",
mappings: [
{
match: { path: "gmail" },
action: "agent",
agentId: "hooks",
wakeMode: "now",
name: "Gmail",
sessionKey: "hook:gmail:{{messages[0].id}}",
messageTemplate: "From: {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}",
deliver: true,
channel: "last",
model: "openai/gpt-5.2-mini",
},
],
},
}

인증 방법: Authorization: Bearer <token> 또는 x-openclaw-token: <token>.

엔드포인트:

  • POST /hooks/wake → { text, mode?: "now"|"next-heartbeat" }
  • POST /hooks/agent → { message, name?, agentId?, sessionKey?, wakeMode?, deliver?, channel?, to?, model?, thinking?, timeoutSeconds? }
    • 요청 페이로드의 sessionKey는 hooks.allowRequestSessionKey=true일 때만 수락돼요 (기본값: false).
  • POST /hooks/<name> → hooks.mappings를 통해 해결돼요.
매핑 상세 정보
  • match.path: /hooks 이후의 하위 경로와 매칭돼요 (예: /hooks/gmail → gmail).
  • match.source: 일반 경로에 대해 페이로드 필드와 매칭돼요.
  • {{messages[0].subject}}와 같은 템플릿은 페이로드에서 데이터를 읽어와요.
  • transform: 훅 액션을 반환하는 JS/TS 모듈을 가리킬 수 있어요.
    • transform.module은 반드시 상대 경로여야 하며 hooks.transformsDir 내부에 있어야 해요 (절대 경로 및 상위 디렉토리 접근은 거부됨).
  • agentId: 특정 에이전트로 라우팅해요. 알 수 없는 ID는 기본값으로 폴백돼요.
  • allowedAgentIds: 명시적 라우팅을 제한해요 (* 또는 생략 시 모두 허용, [] 시 모두 거부).
  • defaultSessionKey: 명시적인 sessionKey 없이 실행되는 훅 에이전트를 위한 선택 사항인 고정 세션 키예요.
  • allowRequestSessionKey: /hooks/agent 호출자가 sessionKey를 설정할 수 있게 허용해요 (기본값: false).
  • allowedSessionKeyPrefixes: 명시적 sessionKey 값(요청 + 매핑)에 대한 선택 사항인 접두사 허용 목록이에요 (예: ["hook:"]).
  • deliver: true: 최종 응답을 채널로 전송해요. channel 기본값은 last예요.
  • model: 이 훅 실행에 대해 LLM을 오버라이드해요 (모델 카탈로그가 설정된 경우 허용된 모델이어야 함).
{
hooks: {
gmail: {
account: "openclaw@gmail.com",
topic: "projects/<project-id>/topics/gog-gmail-watch",
subscription: "gog-gmail-watch-push",
pushToken: "shared-push-token",
hookUrl: "http://127.0.0.1:18789/hooks/gmail",
includeBody: true,
maxBytes: 20000,
renewEveryMinutes: 720,
serve: { bind: "127.0.0.1", port: 8788, path: "/" },
tailscale: { mode: "funnel", path: "/gmail-pubsub" },
model: "openrouter/meta-llama/llama-3.3-70b-instruct:free",
thinking: "off",
},
},
}
  • 설정이 완료되면 Gateway 부팅 시 gog gmail watch serve가 자동으로 시작돼요. 비활성화하려면 OPENCLAW_SKIP_GMAIL_WATCHER=1을 설정하세요.
  • Gateway와 별도로 gog gmail watch serve를 실행하지 마세요.

{
canvasHost: {
root: "~/.openclaw/workspace/canvas",
liveReload: true,
// enabled: false, // or OPENCLAW_SKIP_CANVAS_HOST=1
},
}
  • 에이전트가 편집 가능한 HTML/CSS/JS 및 A2UI를 Gateway 포트의 HTTP를 통해 제공해요.
    • http://<gateway-host>:<gateway.port>/__openclaw__/canvas/
    • http://<gateway-host>:<gateway.port>/__openclaw__/a2ui/
  • 로컬 전용: gateway.bind: "loopback"(기본값)을 유지하세요.
  • loopback이 아닌 bind: 캔버스 경로는 다른 Gateway HTTP 서비스와 마찬가지로 Gateway 인증(token/password/trusted-proxy)이 필요해요.
  • Node WebViews는 보통 인증 헤더를 보내지 않아요. 노드가 페어링되고 연결된 후, Gateway는 캔버스/A2UI 접근을 위한 노드 범위의 기능(capability) URL을 광고해요.
  • 기능 URL은 활성 노드 WS 세션에 바인딩되며 빠르게 만료돼요. IP 기반 폴백은 사용되지 않아요.
  • 제공되는 HTML에 live-reload 클라이언트를 삽입해요.
  • 디렉토리가 비어 있으면 시작용 index.html을 자동으로 생성해요.
  • /__openclaw__/a2ui/에서 A2UI도 함께 제공해요.
  • 변경 사항을 적용하려면 Gateway를 재시작해야 해요.
  • 디렉토리가 너무 크거나 EMFILE 에러가 발생하면 live reload를 비활성화하세요.

{
discovery: {
mdns: {
mode: "minimal", // minimal | full | off
},
},
}
  • minimal (기본값): TXT 레코드에서 cliPath와 sshPort를 제외해요.
  • full: cliPath와 sshPort를 포함해요.
  • 호스트네임 기본값은 openclaw예요. OPENCLAW_MDNS_HOSTNAME으로 변경할 수 있어요.
{
discovery: {
wideArea: { enabled: true },
},
}

~/.openclaw/dns/ 아래에 유니캐스트 DNS-SD 존을 작성해요. 네트워크 간 디스커버리를 위해 DNS 서버(CoreDNS 권장) 및 Tailscale split DNS와 함께 사용하세요.

설정 방법: openclaw dns setup --apply.

{
env: {
OPENROUTER_API_KEY: "sk-or-...",
vars: {
GROQ_API_KEY: "gsk-...",
},
shellEnv: {
enabled: true,
timeoutMs: 15000,
},
},
}
  • 인라인 환경 변수는 프로세스 환경에 해당 키가 없을 때만 적용돼요.
  • .env 파일: 현재 작업 디렉토리(CWD)의 .env와 ~/.openclaw/.env를 불러오며, 두 파일 모두 기존 변수를 덮어쓰지 않아요.
  • shellEnv: 로그인 쉘 프로필에서 누락된 예상 키들을 가져와요.
  • 전체 우선순위는 Environment 문서에서 확인할 수 있어요.

환경 변수 치환 (Env var substitution)

섹션 제목: “환경 변수 치환 (Env var substitution)”

설정 문자열 어디서든 ${VAR_NAME} 형식을 사용해 환경 변수를 참조할 수 있어요.

{
gateway: {
auth: { token: "${OPENCLAW_GATEWAY_TOKEN}" },
},
}
  • [A-Z_][A-Z0-9_]* 패턴과 일치하는 대문자 이름만 매칭돼요.
  • 변수가 없거나 비어 있으면 설정 로드 시 에러가 발생해요.
  • 문자 그대로의 ${VAR}를 표현하고 싶다면 $${VAR}로 이스케이프 하세요.
  • $include와 함께 사용할 수 있어요.

시크릿 참조는 추가적인 방식이며, 일반 텍스트 값도 여전히 사용할 수 있어요.

다음과 같은 객체 형태를 사용해요.

{ source: "env" | "file" | "exec", provider: "default", id: "..." }

유효성 검사 규칙은 다음과 같아요.

  • provider 패턴: ^[a-z][a-z0-9_-]{0,63}$
  • source: "env" id 패턴: ^[A-Z][A-Z0-9_]{0,127}$
  • source: "file" id: 절대 경로 JSON 포인터 (예: "/providers/openai/apiKey")
  • source: "exec" id 패턴: ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$
  • source: "exec" id에는 . 또는 ..과 같이 슬래시로 구분된 경로 세그먼트가 포함될 수 없어요 (예: a/../b는 거부돼요).

지원되는 자격 증명 범위 (Supported credential surface)

섹션 제목: “지원되는 자격 증명 범위 (Supported credential surface)”
  • 표준 매트릭스: SecretRef Credential Surface
  • secrets apply는 지원되는 openclaw.json 자격 증명 경로를 대상으로 해요.
  • auth-profiles.json 참조는 런타임 확인 및 감사 범위에 포함돼요.

시크릿 프로바이더 설정 (Secret providers config)

섹션 제목: “시크릿 프로바이더 설정 (Secret providers config)”
{
secrets: {
providers: {
default: { source: "env" }, // 선택 사항인 명시적 env 프로바이더
filemain: {
source: "file",
path: "~/.openclaw/secrets.json",
mode: "json",
timeoutMs: 5000,
},
vault: {
source: "exec",
command: "/usr/local/bin/openclaw-vault-resolver",
passEnv: ["PATH", "VAULT_ADDR"],
},
},
defaults: {
env: "default",
file: "filemain",
exec: "vault",
},
},
}

참고 사항:

  • file 프로바이더는 mode: "json"과 mode: "singleValue"를 지원해요 (singleValue 모드에서 id는 반드시 "value"여야 해요).
  • exec 프로바이더는 절대 경로로 된 command가 필요하며, stdin/stdout을 통한 프로토콜 페이로드를 사용해요.
  • 기본적으로 심볼릭 링크로 된 커맨드 경로는 거부돼요. allowSymlinkCommand: true를 설정하면 심볼릭 링크를 허용하면서 최종 타겟 경로를 검증할 수 있어요.
  • trustedDirs가 설정된 경우, 신뢰할 수 있는 디렉토리 체크가 최종 타겟 경로에 적용돼요.
  • exec 자식 프로세스 환경은 기본적으로 최소화되어 있어요. 필요한 변수는 passEnv를 통해 명시적으로 전달해 주세요.
  • 시크릿 참조는 활성화 시점에 메모리 내 스냅샷으로 확인(resolve)되며, 이후 요청 경로는 이 스냅샷만 읽게 돼요.
  • 활성화 중에 활성 범위 필터링이 적용돼요. 활성화된 범위에서 확인되지 않은 참조가 있으면 시작 또는 재로드가 실패하며, 비활성 범위는 진단 정보와 함께 건너뛰게 돼요.
{
auth: {
profiles: {
"anthropic:me@example.com": { provider: "anthropic", mode: "oauth", email: "me@example.com" },
"anthropic:work": { provider: "anthropic", mode: "api_key" },
},
order: {
anthropic: ["anthropic:me@example.com", "anthropic:work"],
},
},
}
  • 에이전트별 프로필은 <agentDir>/auth-profiles.json에 저장돼요.
  • auth-profiles.json은 값 수준의 참조(value-level refs)를 지원해요 (api_key를 위한 keyRef, token을 위한 tokenRef).
  • 정적 런타임 자격 증명은 메모리 내에서 해결된 스냅샷에서 가져오며, 기존의 레거시 정적 auth.json 항목은 발견 시 삭제돼요.
  • 레거시 OAuth 임포트는 ~/.openclaw/credentials/oauth.json에서 이루어져요.
  • OAuth 문서를 참고해 주세요.
  • Secrets 런타임 동작과 audit/configure/apply 도구에 대해서는 Secrets Management에서 확인할 수 있어요.

{
logging: {
level: "info",
file: "/tmp/openclaw/openclaw.log",
consoleLevel: "info",
consoleStyle: "pretty", // pretty | compact | json
redactSensitive: "tools", // off | tools
redactPatterns: ["\\bTOKEN\\b\\s*[=:]\\s*([\"']?)([^\\s\"']+)\\1"],
},
}
  • 기본 로그 파일 경로는 /tmp/openclaw/openclaw-YYYY-MM-DD.log예요.
  • 고정된 경로를 사용하려면 logging.file을 설정하세요.
  • --verbose 플래그를 사용하면 consoleLevel이 debug로 올라가요.
{
cli: {
banner: {
taglineMode: "off", // random | default | off
},
},
}

cli.banner.taglineMode 설정을 통해 배너의 태그라인 스타일을 관리할 수 있어요.

  • "random" (기본값): 재미있거나 시즌에 어울리는 태그라인이 무작위로 돌아가며 나타나요.
  • "default": 고정된 중립적인 태그라인(All your chats, one OpenClaw.)이 표시돼요.
  • "off": 태그라인 텍스트가 나오지 않아요 (배너 제목과 버전은 여전히 표시돼요).

태그라인뿐만 아니라 배너 전체를 숨기고 싶다면, 환경 변수 OPENCLAW_HIDE_BANNER=1을 설정해 주세요.

onboard, configure, doctor와 같은 CLI Wizard가 작성하는 메타데이터예요.

{
wizard: {
lastRunAt: "2026-01-01T00:00:00.000Z",
lastRunVersion: "2026.1.4",
lastRunCommit: "abc1234",
lastRunCommand: "configure",
lastRunMode: "local",
},
}
{
agents: {
list: [
{
id: "main",
identity: {
name: "Samantha",
theme: "helpful sloth",
emoji: "🦥",
avatar: "avatars/samantha.png",
},
},
],
},
}

이 설정은 macOS onboarding assistant가 작성해요. 다음과 같은 기본값들을 자동으로 가져오죠:

  • identity.emoji를 기반으로 messages.ackReaction을 설정해요 (값이 없으면 👀를 사용해요).
  • identity.name이나 identity.emoji를 사용해 mentionPatterns를 생성해요.
  • avatar 항목에는 워크스페이스 상대 경로, http(s) URL, 또는 data: URI를 사용할 수 있어요.

최신 빌드에는 더 이상 TCP bridge가 포함되지 않아요. 이제 Node는 Gateway WebSocket을 통해 연결되거든요. bridge.* 키는 더 이상 설정 스키마의 일부가 아니에요. 이 키들을 제거하기 전까지는 유효성 검사에 실패하게 되는데, openclaw doctor --fix를 사용하면 알 수 없는 키들을 자동으로 제거할 수 있어요.

Legacy bridge config (historical reference)

{
"bridge": {
"enabled": true,
"port": 18790,
"bind": "tailnet",
"tls": {
"enabled": true,
"autoGenerate": true
}
}
}
{
cron: {
enabled: true,
maxConcurrentRuns: 2,
webhook: "https://example.invalid/legacy", // deprecated fallback for stored notify:true jobs
webhookToken: "replace-with-dedicated-token", // optional bearer token for outbound webhook auth
sessionRetention: "24h", // duration string or false
runLog: {
maxBytes: "2mb", // default 2_000_000 bytes
keepLines: 2000, // default 2000
},
},
}
  • sessionRetention: 완료된 개별 Cron 실행 세션을 sessions.json에서 삭제하기 전까지 보관하는 기간이에요. 보관 기간이 지난 삭제된 Cron 기록의 정리 작업도 함께 제어해요. 기본값은 24h이며, 기능을 끄려면 false로 설정하세요.
  • runLog.maxBytes: 실행 로그 파일(cron/runs/<jobId>.jsonl)이 정리되기 전까지의 최대 크기예요. 기본값은 2,000,000 바이트예요.
  • runLog.keepLines: 로그 정리가 시작될 때 유지할 최신 줄 수예요. 기본값은 2000줄이에요.
  • webhookToken: Cron Webhook POST 전송(delivery.mode = "webhook") 시 사용하는 Bearer 토큰이에요. 이 설정을 생략하면 인증 헤더를 보내지 않아요.
  • webhook: 더 이상 권장되지 않는(deprecated) 레거시 Webhook URL(http/https)이에요. 여전히 notify: true 설정이 남아 있는 저장된 작업에만 사용돼요.

Cron Jobs 문서도 함께 확인해 보세요.


tools.media.models[].args에서 사용할 수 있는 템플릿 변수들이에요.

변수설명
{{Body}}수신된 메시지 본문 전체
{{RawBody}}원본 본문 (히스토리나 발신자 정보 제외)
{{BodyStripped}}그룹 멘션이 제거된 본문
{{From}}발신자 식별자
{{To}}수신처 식별자
{{MessageSid}}채널 메시지 ID
{{SessionId}}현재 세션 UUID
{{IsNewSession}}새 세션이 생성되었을 때 "true"
{{MediaUrl}}수신 미디어 가상 URL
{{MediaPath}}로컬 미디어 경로
{{MediaType}}미디어 타입 (image/audio/document 등)
{{Transcript}}오디오 텍스트 변환 결과
{{Prompt}}CLI 항목에 대해 확인된 미디어 프롬프트
{{MaxChars}}CLI 항목에 대해 확인된 최대 출력 글자 수
{{ChatType}}"direct" 또는 "group"
{{GroupSubject}}그룹 주제 (최대한 확인된 정보)
{{GroupMembers}}그룹 멤버 미리보기 (최대한 확인된 정보)
{{SenderName}}발신자 표시 이름 (최대한 확인된 정보)
{{SenderE164}}발신자 전화번호 (최대한 확인된 정보)
{{Provider}}공급자 힌트 (whatsapp, telegram, discord 등)

설정 파일을 여러 개로 나누어 관리할 수 있어요.

~/.openclaw/openclaw.json
{
gateway: { port: 18789 },
agents: { $include: "./agents.json5" },
broadcast: {
$include: ["./clients/mueller.json5", "./clients/schmidt.json5"],
},
}

병합 동작 방식:

  • 단일 파일: 해당 객체를 통째로 대체해요.
  • 파일 배열: 순서대로 Deep-merge 되며, 나중에 나오는 파일이 이전 파일의 설정을 덮어써요.
  • 형제 키(Sibling keys): include가 처리된 후 병합되며, 포함된 값을 덮어써요.
  • 중첩 include: 최대 10단계 깊이까지 사용할 수 있어요.
  • 경로: include를 사용하는 파일을 기준으로 상대 경로를 계산해요. 단, 반드시 최상위 설정 디렉토리(openclaw.json이 있는 위치) 내에 있어야 해요. 절대 경로 나 ../ 형식은 이 경계 안에서 해석될 때만 허용돼요.
  • 에러: 파일 누락, 파싱 에러, 순환 참조가 발생하면 명확한 에러 메시지를 보여줘요.

관련 문서: Configuration · Configuration Examples · Doctor

{
agents: {
list: [
{ id: "home", default: true, workspace: "~/.openclaw/workspace-home" },
{ id: "work", workspace: "~/.openclaw/workspace-work" },
],
},
bindings: [
{ agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
{ agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },
],
}
{
agents: {
list: [
{
id: "personal",
workspace: "~/.openclaw/workspace-personal",
sandbox: { mode: "off" },
},
],
},
}
{
agents: {
list: [
{
id: "family",
workspace: "~/.openclaw/workspace-family",
sandbox: { mode: "all", scope: "agent", workspaceAccess: "ro" },
tools: {
allow: [
"read",
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"session_status",
],
deny: ["write", "edit", "apply_patch", "exec", "process", "browser"],
},
},
],
},
}
{
agents: {
list: [
{
id: "public",
workspace: "~/.openclaw/workspace-public",
sandbox: { mode: "all", scope: "agent", workspaceAccess: "none" },
tools: {
allow: [
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"session_status",
"whatsapp",
"telegram",
"slack",
"discord",
"gateway",
],
deny: [
"read",
"write",
"edit",
"apply_patch",
"exec",
"process",
"browser",
"canvas",
"nodes",
"cron",
"gateway",
"image",
],
},
},
],
},
}
{
session: {
scope: "per-sender",
dmScope: "main", // main | per-peer | per-channel-peer | per-account-channel-peer
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"],
},
reset: {
mode: "daily", // daily | idle
atHour: 4,
idleMinutes: 60,
},
resetByType: {
thread: { mode: "daily", atHour: 4 },
direct: { mode: "idle", idleMinutes: 240 },
group: { mode: "idle", idleMinutes: 120 },
},
resetTriggers: ["/new", "/reset"],
store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
parentForkMaxTokens: 100000, // skip parent-thread fork above this token count (0 disables)
maintenance: {
mode: "warn", // warn | enforce
pruneAfter: "30d",
maxEntries: 500,
rotateBytes: "10mb",
resetArchiveRetention: "30d", // duration or false
maxDiskBytes: "500mb", // optional hard budget
highWaterBytes: "400mb", // optional cleanup target
},
threadBindings: {
enabled: true,
idleHours: 24, // default inactivity auto-unfocus in hours (`0` disables)
maxAgeHours: 0, // default hard max age in hours (`0` disables)
},
mainKey: "main", // legacy (runtime always uses "main")
agentToAgent: { maxPingPongTurns: 5 },
sendPolicy: {
rules: [{ action: "deny", match: { channel: "discord", chatType: "group" } }],
default: "allow",
},
},
}
{
messages: {
responsePrefix: "🦞", // or "auto"
ackReaction: "👀",
ackReactionScope: "group-mentions", // group-mentions | group-all | direct | all
removeAckAfterReply: false,
queue: {
mode: "collect", // steer | followup | collect | steer-backlog | steer+backlog | queue | interrupt
debounceMs: 1000,
cap: 20,
drop: "summarize", // old | new | summarize
byChannel: {
whatsapp: "collect",
telegram: "collect",
},
},
inbound: {
debounceMs: 2000, // 0 disables
byChannel: {
whatsapp: 5000,
slack: 1500,
},
},
},
}
OpenClaw

OpenClaw Expert

아직 막혀 있나요?

이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.