Mainstream messaging
Telegram
프로덕션 준비가 완료되어 grammY를 통해 봇 DM과 그룹에서 사용할 수 있습니다. Long polling이 기본 모드이며, Webhook 모드는 선택 사항입니다.
빠른 설정
BotFather에서 봇 토큰 만들기
Telegram을 열고 @BotFather와 채팅하세요(핸들이 정확히 @BotFather인지 확인하세요).
/newbot을 실행하고 안내를 따른 뒤 토큰을 저장하세요.
토큰과 DM 정책 구성하기
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
groups: { "*": { requireMention: true } },
},
},
}
Env 대체값: TELEGRAM_BOT_TOKEN=...(기본 계정에만 해당).
Telegram은 openclaw channels login telegram을 사용하지 않습니다. config/env에 토큰을 구성한 다음 Gateway를 시작하세요.
Gateway를 시작하고 첫 DM 승인하기
openclaw gateway
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
페어링 코드는 1시간 후 만료됩니다.
봇을 그룹에 추가하기
봇을 그룹에 추가한 다음, 액세스 모델에 맞게 channels.telegram.groups와 groupPolicy를 설정하세요.
Telegram 측 설정
개인정보 보호 모드와 그룹 가시성
Telegram 봇은 기본적으로 개인정보 보호 모드를 사용하며, 이 모드는 봇이 수신하는 그룹 메시지를 제한합니다.
봇이 모든 그룹 메시지를 봐야 한다면 다음 중 하나를 수행하세요.
/setprivacy를 통해 개인정보 보호 모드를 비활성화하거나- 봇을 그룹 관리자로 만드세요.
개인정보 보호 모드를 전환할 때는 Telegram이 변경 사항을 적용하도록 각 그룹에서 봇을 제거한 뒤 다시 추가하세요.
그룹 권한
관리자 상태는 Telegram 그룹 설정에서 제어됩니다.
관리자 봇은 모든 그룹 메시지를 수신하므로, 항상 켜져 있는 그룹 동작에 유용합니다.
유용한 BotFather 전환 옵션
- 그룹 추가를 허용/거부하려면
/setjoingroups - 그룹 가시성 동작을 설정하려면
/setprivacy
액세스 제어와 활성화
DM 정책
channels.telegram.dmPolicy는 다이렉트 메시지 액세스를 제어합니다.
pairing(기본값)allowlist(allowFrom에 하나 이상의 발신자 ID 필요)open(allowFrom에"*"포함 필요)disabled
allowFrom: ["*"]와 함께 dmPolicy: "open"을 사용하면 봇 사용자 이름을 찾거나 추측한 모든 Telegram 계정이 봇에 명령을 내릴 수 있습니다. 도구가 엄격하게 제한된 의도적으로 공개된 봇에만 사용하세요. 단일 소유자 봇은 숫자 사용자 ID와 함께 allowlist를 사용해야 합니다.
channels.telegram.allowFrom은 숫자 Telegram 사용자 ID를 허용합니다. telegram: / tg: 접두사는 허용되며 정규화됩니다.
다중 계정 config에서 제한적인 최상위 channels.telegram.allowFrom은 안전 경계로 취급됩니다. 계정 수준의 allowFrom: ["*"] 항목은 병합 후 유효한 계정 allowlist에 명시적 와일드카드가 여전히 포함되어 있지 않으면 해당 계정을 공개 상태로 만들지 않습니다.
빈 allowFrom과 함께 dmPolicy: "allowlist"를 사용하면 모든 DM이 차단되며 config 검증에서 거부됩니다.
설정은 숫자 사용자 ID만 요청합니다.
업그레이드 후 config에 @username allowlist 항목이 포함되어 있다면, 이를 확인하려면 openclaw doctor --fix를 실행하세요(최선의 시도 방식이며 Telegram 봇 토큰이 필요합니다).
이전에 페어링 저장소 allowlist 파일에 의존했다면, openclaw doctor --fix가 allowlist 흐름에서 항목을 channels.telegram.allowFrom으로 복구할 수 있습니다(예: dmPolicy: "allowlist"에 아직 명시적 ID가 없는 경우).
단일 소유자 봇의 경우, 이전 페어링 승인에 의존하는 대신 액세스 정책이 config에서 지속되도록 명시적인 숫자 allowFrom ID와 함께 dmPolicy: "allowlist"를 선호하세요.
흔한 혼동: DM 페어링 승인이 "이 발신자는 모든 곳에서 승인됨"을 의미하지는 않습니다.
페어링은 DM 액세스를 부여합니다. 명령 소유자가 아직 없다면, 처음 승인된 페어링은 소유자 전용 명령과 exec 승인에 명시적인 운영자 계정이 있도록 commands.ownerAllowFrom도 설정합니다.
그룹 발신자 승인은 여전히 명시적인 config allowlist에서 옵니다.
"한 번 승인되면 DM과 그룹 명령이 모두 작동"하기를 원한다면 숫자 Telegram 사용자 ID를 channels.telegram.allowFrom에 넣으세요. 소유자 전용 명령의 경우 commands.ownerAllowFrom에 telegram:<your user id>가 포함되어 있는지 확인하세요.
Telegram 사용자 ID 찾기
더 안전한 방법(타사 봇 없음):
- 봇에 DM을 보냅니다.
openclaw logs --follow를 실행합니다.from.id를 읽습니다.
공식 Bot API 메서드:
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
타사 방법(개인정보 보호 수준 낮음): @userinfobot 또는 @getidsbot.
그룹 정책과 allowlist
두 제어가 함께 적용됩니다.
-
허용되는 그룹(
channels.telegram.groups)groupsconfig 없음:groupPolicy: "open"사용 시: 모든 그룹이 그룹 ID 검사를 통과할 수 있음groupPolicy: "allowlist"(기본값) 사용 시:groups항목(또는"*")을 추가할 때까지 그룹이 차단됨
groups가 구성됨: allowlist로 동작함(명시적 ID 또는"*")
-
그룹에서 허용되는 발신자(
channels.telegram.groupPolicy)openallowlist(기본값)disabled
groupAllowFrom은 그룹 발신자 필터링에 사용됩니다. 설정되지 않은 경우 Telegram은 allowFrom으로 대체합니다.
groupAllowFrom 항목은 숫자 Telegram 사용자 ID여야 합니다(telegram: / tg: 접두사는 정규화됨).
Telegram 그룹 또는 슈퍼그룹 채팅 ID를 groupAllowFrom에 넣지 마세요. 음수 채팅 ID는 channels.telegram.groups 아래에 둡니다.
숫자가 아닌 항목은 발신자 승인에서 무시됩니다.
보안 경계(2026.2.25+): 그룹 발신자 인증은 DM 페어링 저장소 승인을 상속하지 않습니다.
페어링은 DM 전용으로 유지됩니다. 그룹의 경우 groupAllowFrom 또는 그룹별/토픽별 allowFrom을 설정하세요.
groupAllowFrom이 설정되지 않은 경우 Telegram은 페어링 저장소가 아니라 config allowFrom으로 대체합니다.
단일 소유자 봇의 실용적인 패턴: 사용자 ID를 channels.telegram.allowFrom에 설정하고, groupAllowFrom은 설정하지 않은 채 대상 그룹을 channels.telegram.groups 아래에서 허용하세요.
런타임 참고: channels.telegram이 완전히 누락된 경우, channels.defaults.groupPolicy가 명시적으로 설정되지 않는 한 런타임은 실패 닫힘 기본값 groupPolicy="allowlist"를 사용합니다.
예시: 특정 그룹 하나에서 모든 멤버 허용:
{
channels: {
telegram: {
groups: {
"-1001234567890": {
groupPolicy: "open",
requireMention: false,
},
},
},
},
}
예시: 특정 그룹 하나 안에서 특정 사용자만 허용:
{
channels: {
telegram: {
groups: {
"-1001234567890": {
requireMention: true,
allowFrom: ["8734062810", "745123456"],
},
},
},
},
}
멘션 동작
그룹 답장은 기본적으로 멘션이 필요합니다.
멘션은 다음에서 올 수 있습니다.
- 기본
@botusername멘션 또는 - 다음의 멘션 패턴:
agents.list[].groupChat.mentionPatternsmessages.groupChat.mentionPatterns
세션 수준 명령 전환:
/activation always/activation mention
이는 세션 상태만 업데이트합니다. 지속성에는 config를 사용하세요.
지속적 config 예시:
{
channels: {
telegram: {
groups: {
"*": { requireMention: false },
},
},
},
}
그룹 채팅 ID 가져오기:
- 그룹 메시지를
@userinfobot/@getidsbot으로 전달 - 또는
openclaw logs --follow에서chat.id읽기 - 또는 Bot API
getUpdates검사
런타임 동작
- Telegram은 Gateway 프로세스가 소유합니다.
- 라우팅은 결정적입니다. Telegram 인바운드는 Telegram으로 답장합니다(모델이 채널을 선택하지 않음).
- 인바운드 메시지는 답장 메타데이터와 미디어 자리표시자를 포함한 공유 채널 봉투로 정규화됩니다.
- 그룹 세션은 그룹 ID별로 격리됩니다. 포럼 토픽은 토픽을 격리하기 위해
:topic:<threadId>를 추가합니다. - DM 메시지는
message_thread_id를 포함할 수 있습니다. OpenClaw는 답장을 위해 thread ID를 보존하지만 기본적으로 DM은 평면 세션에 유지합니다. 의도적으로 DM 토픽 세션 격리를 원할 때는channels.telegram.dm.threadReplies: "inbound",channels.telegram.direct.<chatId>.threadReplies: "inbound",requireTopic: true또는 일치하는 토픽 config를 구성하세요. - Long polling은 채팅별/스레드별 순서를 지정하는 grammY runner를 사용합니다. 전체 runner sink 동시성은
agents.defaults.maxConcurrent를 사용합니다. - Long polling은 각 Gateway 프로세스 내부에서 보호되므로 한 번에 하나의 활성 poller만 봇 토큰을 사용할 수 있습니다. 그래도
getUpdates409 충돌이 보인다면 다른 OpenClaw Gateway, 스크립트 또는 외부 poller가 같은 토큰을 사용하고 있을 가능성이 큽니다. - Long-polling watchdog 재시작은 기본적으로 완료된
getUpdates활성 상태가 120초 동안 없으면 트리거됩니다. 배포 환경에서 장시간 실행 작업 중에도 잘못된 polling-stall 재시작이 계속 발생하는 경우에만channels.telegram.pollingStallThresholdMs를 늘리세요. 값은 밀리초 단위이며30000부터600000까지 허용됩니다. 계정별 재정의가 지원됩니다. - Telegram Bot API는 읽음 확인을 지원하지 않습니다(
sendReadReceipts는 적용되지 않음).
기능 참조
라이브 스트림 미리보기(메시지 편집)
OpenClaw는 부분 답장을 실시간으로 스트리밍할 수 있습니다.
- 다이렉트 채팅: 미리보기 메시지 +
editMessageText - 그룹/토픽: 미리보기 메시지 +
editMessageText
요구 사항:
channels.telegram.streaming은off | partial | block | progress입니다(기본값:partial)progress는 도구 진행 상황을 위해 편집 가능한 상태 초안 하나를 유지하고, 완료 시 이를 지운 뒤 최종 답변을 일반 메시지로 보냅니다streaming.preview.toolProgress는 도구/진행 상황 업데이트가 동일한 편집된 미리보기 메시지를 재사용할지 제어합니다(기본값: 미리보기 스트리밍이 활성화된 경우true)streaming.preview.commandText는 해당 도구 진행 상황 줄 안의 command/exec 세부 정보를 제어합니다:raw(기본값, 릴리스된 동작 보존) 또는status(도구 레이블만)- 레거시
channels.telegram.streamMode및 booleanstreaming값이 감지됩니다. 이를channels.telegram.streaming.mode로 마이그레이션하려면openclaw doctor --fix를 실행하세요
도구 진행 상황 미리보기 업데이트는 도구가 실행되는 동안 표시되는 짧은 상태 줄입니다. 예를 들어 명령 실행, 파일 읽기, 계획 업데이트 또는 패치 요약이 있습니다. Telegram은 v2026.4.22 이상에서 릴리스된 OpenClaw 동작과 일치하도록 기본적으로 이를 활성화된 상태로 유지합니다. 답변 텍스트용 편집 미리보기는 유지하되 도구 진행 상황 줄을 숨기려면 다음을 설정하세요.
{
"channels": {
"telegram": {
"streaming": {
"mode": "partial",
"preview": {
"toolProgress": false
}
}
}
}
}
도구 진행 상황은 표시하되 command/exec 텍스트를 숨기려면 다음을 설정하세요:
{
"channels": {
"telegram": {
"streaming": {
"mode": "partial",
"preview": {
"commandText": "status"
}
}
}
}
}
최종 답변을 같은 메시지에 편집해 넣지 않고 보이는 도구 진행 상황을 원할 때는 progress 모드를 사용하세요. 명령 텍스트 정책은 streaming.progress 아래에 둡니다.
{
"channels": {
"telegram": {
"streaming": {
"mode": "progress",
"progress": {
"toolProgress": true,
"commandText": "status"
}
}
}
}
}
최종 결과만 전달하려는 경우에만 streaming.mode: "off"를 사용하세요. Telegram 미리보기 편집이 비활성화되고, 일반 도구/진행 상황 잡담은 독립 상태 메시지로 전송되지 않고 억제됩니다. 승인 프롬프트, 미디어 페이로드, 오류는 여전히 일반 최종 전달 경로를 통해 라우팅됩니다. 답변 미리보기 편집은 유지하면서 도구 진행 상태 줄만 숨기려면 streaming.preview.toolProgress: false를 사용하세요.
텍스트 전용 답장의 경우:
- 짧은 DM/그룹/토픽 미리보기: OpenClaw는 같은 미리보기 메시지를 유지하고 최종 편집을 제자리에서 수행합니다.
- 여러 Telegram 메시지로 나뉘는 긴 텍스트 최종 답변은 가능하면 기존 미리보기를 첫 번째 최종 청크로 재사용한 다음, 나머지 청크만 보냅니다.
- 진행 모드 최종 답변은 상태 초안을 지우고, 초안을 답변으로 편집하는 대신 일반 최종 전달을 사용합니다.
- 완료된 텍스트가 확인되기 전에 최종 편집이 실패하면 OpenClaw는 일반 최종 전달을 사용하고 오래된 미리보기를 정리합니다.
복잡한 답장(예: 미디어 페이로드)의 경우 OpenClaw는 일반 최종 전달로 폴백한 다음 미리보기 메시지를 정리합니다.
미리보기 스트리밍은 블록 스트리밍과 별개입니다. Telegram에 블록 스트리밍이 명시적으로 활성화되어 있으면, OpenClaw는 이중 스트리밍을 피하기 위해 미리보기 스트림을 건너뜁니다.
Telegram 전용 추론 스트림:
/reasoning stream은 생성 중 추론을 라이브 미리보기로 보냅니다.- 추론 미리보기는 최종 전달 후 삭제됩니다. 추론을 계속 표시해야 하면
/reasoning on을 사용하세요. - 최종 답변은 추론 텍스트 없이 전송됩니다.
서식 지정 및 HTML 폴백
발신 텍스트는 Telegram parse_mode: "HTML"을 사용합니다.
- Markdown과 유사한 텍스트는 Telegram에 안전한 HTML로 렌더링됩니다.
- 원시 모델 HTML은 Telegram 파싱 실패를 줄이기 위해 이스케이프됩니다.
- Telegram이 파싱된 HTML을 거부하면 OpenClaw는 일반 텍스트로 다시 시도합니다.
링크 미리보기는 기본적으로 활성화되며 channels.telegram.linkPreview: false로 비활성화할 수 있습니다.
네이티브 명령 및 사용자 지정 명령
Telegram 명령 메뉴 등록은 시작 시 setMyCommands로 처리됩니다.
네이티브 명령 기본값:
commands.native: "auto"는 Telegram용 네이티브 명령을 활성화합니다.
사용자 지정 명령 메뉴 항목 추가:
{
channels: {
telegram: {
customCommands: [
{ command: "backup", description: "Git backup" },
{ command: "generate", description: "Create an image" },
],
},
},
}
규칙:
- 이름은 정규화됩니다(선행
/제거, 소문자 변환). - 유효한 패턴:
a-z,0-9,_, 길이1..32 - 사용자 지정 명령은 네이티브 명령을 재정의할 수 없습니다.
- 충돌/중복은 건너뛰고 로그에 기록됩니다.
참고:
- 사용자 지정 명령은 메뉴 항목일 뿐이며, 동작을 자동으로 구현하지 않습니다.
- Plugin/skill 명령은 Telegram 메뉴에 표시되지 않아도 입력하면 계속 작동할 수 있습니다.
네이티브 명령이 비활성화되어 있으면 내장 항목은 제거됩니다. 사용자 지정/Plugin 명령은 구성된 경우 계속 등록될 수 있습니다.
일반적인 설정 실패:
BOT_COMMANDS_TOO_MUCH와 함께setMyCommands failed가 발생하면 Telegram 메뉴가 잘라낸 후에도 여전히 초과되었다는 뜻입니다. Plugin/skill/사용자 지정 명령을 줄이거나channels.telegram.commands.native를 비활성화하세요.- 직접 Bot API curl 명령은 작동하는데
deleteWebhook,deleteMyCommands또는setMyCommands가404: Not Found로 실패하면,channels.telegram.apiRoot가 전체/bot<TOKEN>엔드포인트로 설정되었음을 의미할 수 있습니다.apiRoot는 Bot API 루트만이어야 하며,openclaw doctor --fix는 실수로 붙은 후행/bot<TOKEN>을 제거합니다. getMe returned 401은 Telegram이 구성된 봇 토큰을 거부했다는 뜻입니다.botToken,tokenFile또는TELEGRAM_BOT_TOKEN을 현재 BotFather 토큰으로 업데이트하세요. OpenClaw는 폴링 전에 중지하므로 이것은 Webhook 정리 실패로 보고되지 않습니다.- 네트워크/가져오기 오류와 함께
setMyCommands failed가 발생하면 일반적으로api.telegram.org로 나가는 DNS/HTTPS가 차단되었다는 뜻입니다.
기기 페어링 명령(device-pair Plugin)
device-pair Plugin이 설치되어 있으면:
/pair가 설정 코드를 생성합니다.- iOS 앱에 코드를 붙여넣습니다.
/pair pending은 대기 중인 요청(역할/범위 포함)을 나열합니다.- 요청을 승인합니다.
- 명시적 승인은
/pair approve <requestId> - 대기 중인 요청이 하나뿐이면
/pair approve - 가장 최근 요청은
/pair approve latest
- 명시적 승인은
설정 코드는 수명이 짧은 부트스트랩 토큰을 전달합니다. 내장 부트스트랩 핸드오프는 기본 노드 토큰을 scopes: []로 유지합니다. 핸드오프된 모든 운영자 토큰은 operator.approvals, operator.read, operator.talk.secrets, operator.write로 제한됩니다. 부트스트랩 범위 검사는 역할 접두사가 붙으므로, 해당 운영자 허용 목록은 운영자 요청만 충족합니다. 비운영자 역할에는 여전히 자체 역할 접두사 아래의 범위가 필요합니다.
기기가 변경된 인증 세부 정보(예: 역할/범위/공개 키)로 다시 시도하면, 이전 대기 요청은 대체되고 새 요청은 다른 requestId를 사용합니다. 승인하기 전에 /pair pending을 다시 실행하세요.
자세한 내용: 페어링.
인라인 버튼
인라인 키보드 범위 구성:
{
channels: {
telegram: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
}
계정별 재정의:
{
channels: {
telegram: {
accounts: {
main: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
},
},
}
범위:
offdmgroupallallowlist(기본값)
레거시 capabilities: ["inlineButtons"]는 inlineButtons: "all"로 매핑됩니다.
메시지 작업 예시:
{
action: "send",
channel: "telegram",
to: "123456789",
message: "Choose an option:",
buttons: [
[
{ text: "Yes", callback_data: "yes" },
{ text: "No", callback_data: "no" },
],
[{ text: "Cancel", callback_data: "cancel" }],
],
}
콜백 클릭은 텍스트로 agent에 전달됩니다.
callback_data: <value>
agent 및 자동화를 위한 Telegram 메시지 작업
Telegram 도구 작업에는 다음이 포함됩니다.
sendMessage(to,content, 선택 사항mediaUrl,replyToMessageId,messageThreadId)react(chatId,messageId,emoji)deleteMessage(chatId,messageId)editMessage(chatId,messageId,content)createForumTopic(chatId,name, 선택 사항iconColor,iconCustomEmojiId)
채널 메시지 작업은 사용하기 쉬운 별칭(send, react, delete, edit, sticker, sticker-search, topic-create)을 노출합니다.
게이팅 제어:
channels.telegram.actions.sendMessagechannels.telegram.actions.deleteMessagechannels.telegram.actions.reactionschannels.telegram.actions.sticker(기본값: 비활성화)
참고: edit 및 topic-create는 현재 기본적으로 활성화되어 있으며 별도의 channels.telegram.actions.* 토글이 없습니다.
런타임 전송은 활성 config/secrets 스냅샷(시작/다시 로드)을 사용하므로, 작업 경로는 전송마다 임의의 SecretRef 재해석을 수행하지 않습니다.
반응 제거 의미 체계: /tools/reactions
답장 스레딩 태그
Telegram은 생성된 출력에서 명시적 답장 스레딩 태그를 지원합니다.
[[reply_to_current]]는 트리거한 메시지에 답장합니다.[[reply_to:<id>]]는 특정 Telegram 메시지 ID에 답장합니다.
channels.telegram.replyToMode는 처리를 제어합니다.
off(기본값)firstall
답장 스레딩이 활성화되어 있고 원본 Telegram 텍스트 또는 캡션을 사용할 수 있으면, OpenClaw는 네이티브 Telegram 인용 발췌를 자동으로 포함합니다. Telegram은 네이티브 인용 텍스트를 1024 UTF-16 코드 단위로 제한하므로, 더 긴 메시지는 시작 부분부터 인용되고 Telegram이 인용을 거부하면 일반 답장으로 폴백합니다.
참고: off는 암시적 답장 스레딩을 비활성화합니다. 명시적 [[reply_to_*]] 태그는 여전히 적용됩니다.
포럼 토픽 및 스레드 동작
포럼 슈퍼그룹:
- 토픽 세션 키는
:topic:<threadId>를 덧붙입니다. - 답장과 입력 중 표시는 토픽 스레드를 대상으로 합니다.
- 토픽 구성 경로:
channels.telegram.groups.<chatId>.topics.<threadId>
일반 토픽(threadId=1) 특수 처리:
- 메시지 전송은
message_thread_id를 생략합니다(Telegram은sendMessage(...thread_id=1)을 거부합니다). - 입력 중 작업은 여전히
message_thread_id를 포함합니다.
토픽 상속: 토픽 항목은 재정의되지 않는 한 그룹 설정(requireMention, allowFrom, skills, systemPrompt, enabled, groupPolicy)을 상속합니다.
agentId는 토픽 전용이며 그룹 기본값에서 상속되지 않습니다.
토픽별 agent 라우팅: 각 토픽은 토픽 구성에서 agentId를 설정해 다른 agent로 라우팅할 수 있습니다. 이를 통해 각 토픽은 자체적으로 격리된 워크스페이스, 메모리, 세션을 가집니다. 예시:
{
channels: {
telegram: {
groups: {
"-1001234567890": {
topics: {
"1": { agentId: "main" }, // 일반 토픽 → main agent
"3": { agentId: "zu" }, // 개발 토픽 → zu agent
"5": { agentId: "coder" } // 코드 리뷰 → coder agent
}
}
}
}
}
}
그러면 각 토픽에는 자체 세션 키가 있습니다. agent:zu:telegram:group:-1001234567890:topic:3
영구 ACP 토픽 바인딩: 포럼 토픽은 최상위 typed ACP 바인딩(type: "acp" 및 match.channel: "telegram", peer.kind: "group", -1001234567890:topic:42 같은 토픽 한정 ID가 포함된 bindings[])을 통해 ACP 하네스 세션을 고정할 수 있습니다. 현재는 그룹/슈퍼그룹의 포럼 토픽으로 범위가 제한됩니다. ACP Agents를 참조하세요.
채팅에서 스레드 바인딩 ACP 생성: /acp spawn <agent> --thread here|auto는 현재 토픽을 새 ACP 세션에 바인딩합니다. 후속 메시지는 그곳으로 직접 라우팅됩니다. OpenClaw는 생성 확인을 토픽 내에 고정합니다. channels.telegram.threadBindings.spawnSessions가 활성화된 상태로 유지되어야 합니다(기본값: true).
템플릿 컨텍스트는 MessageThreadId와 IsForum을 노출합니다. message_thread_id가 있는 DM 채팅은 기본적으로 플랫 세션에서 DM 라우팅과 답장 메타데이터를 유지합니다. threadReplies: "inbound", threadReplies: "always", requireTopic: true 또는 일치하는 토픽 구성으로 설정된 경우에만 스레드 인식 세션 키를 사용합니다. 계정 기본값에는 최상위 channels.telegram.dm.threadReplies를 사용하고, 특정 DM 하나에는 direct.<chatId>.threadReplies를 사용하세요.
오디오, 비디오 및 스티커
오디오 메시지
Telegram은 음성 메모와 오디오 파일을 구분합니다.
- 기본값: 오디오 파일 동작
- 에이전트 답장에 태그
[[audio_as_voice]]를 넣어 음성 메모 전송 강제 - 수신 음성 메모 전사는 에이전트 컨텍스트에서 기계 생성, 신뢰할 수 없는 텍스트로 프레이밍됩니다. 멘션 감지는 여전히 원시 전사를 사용하므로 멘션으로 제한된 음성 메시지는 계속 동작합니다.
메시지 작업 예:
{
action: "send",
channel: "telegram",
to: "123456789",
media: "https://example.com/voice.ogg",
asVoice: true,
}
비디오 메시지
Telegram은 비디오 파일과 비디오 메모를 구분합니다.
메시지 작업 예:
{
action: "send",
channel: "telegram",
to: "123456789",
media: "https://example.com/video.mp4",
asVideoNote: true,
}
비디오 메모는 캡션을 지원하지 않습니다. 제공된 메시지 텍스트는 별도로 전송됩니다.
스티커
수신 스티커 처리:
- 정적 WEBP: 다운로드 후 처리됨(플레이스홀더
<media:sticker>) - 애니메이션 TGS: 건너뜀
- 비디오 WEBM: 건너뜀
스티커 컨텍스트 필드:
Sticker.emojiSticker.setNameSticker.fileIdSticker.fileUniqueIdSticker.cachedDescription
스티커 캐시 파일:
~/.openclaw/telegram/sticker-cache.json
스티커는 가능한 경우 한 번 설명되고 반복적인 비전 호출을 줄이기 위해 캐시됩니다.
스티커 작업 활성화:
{
channels: {
telegram: {
actions: {
sticker: true,
},
},
},
}
스티커 전송 작업:
{
action: "sticker",
channel: "telegram",
to: "123456789",
fileId: "CAACAgIAAxkBAAI...",
}
캐시된 스티커 검색:
{
action: "sticker-search",
channel: "telegram",
query: "cat waving",
limit: 5,
}
반응 알림
Telegram 반응은 message_reaction 업데이트로 도착합니다(메시지 페이로드와 별개).
활성화하면 OpenClaw는 다음과 같은 시스템 이벤트를 큐에 넣습니다.
Telegram reaction added: 👍 by Alice (@alice) on msg 42
구성:
channels.telegram.reactionNotifications:off | own | all(기본값:own)channels.telegram.reactionLevel:off | ack | minimal | extensive(기본값:minimal)
참고:
own은 봇이 보낸 메시지에 대한 사용자 반응만 의미합니다(전송 메시지 캐시를 통한 최선 노력).- 반응 이벤트도 Telegram 액세스 제어(
dmPolicy,allowFrom,groupPolicy,groupAllowFrom)를 준수합니다. 권한이 없는 발신자는 삭제됩니다. - Telegram은 반응 업데이트에서 스레드 ID를 제공하지 않습니다.
- 비포럼 그룹은 그룹 채팅 세션으로 라우팅됩니다.
- 포럼 그룹은 정확한 원래 토픽이 아니라 그룹 일반 토픽 세션(
:topic:1)으로 라우팅됩니다.
폴링/Webhook용 allowed_updates에는 message_reaction이 자동으로 포함됩니다.
Ack 반응
ackReaction은 OpenClaw가 수신 메시지를 처리하는 동안 확인 이모지를 보냅니다.
확인 순서:
channels.telegram.accounts.<accountId>.ackReactionchannels.telegram.ackReactionmessages.ackReaction- 에이전트 ID 이모지 폴백(
agents.list[].identity.emoji, 없으면 "👀")
참고:
- Telegram은 유니코드 이모지를 예상합니다(예: "👀").
- 채널 또는 계정의 반응을 비활성화하려면
""를 사용하세요.
Telegram 이벤트 및 명령에서 구성 쓰기
채널 구성 쓰기는 기본적으로 활성화됩니다(configWrites !== false).
Telegram에서 트리거되는 쓰기에는 다음이 포함됩니다.
channels.telegram.groups를 업데이트하는 그룹 마이그레이션 이벤트(migrate_to_chat_id)/config set및/config unset(명령 활성화 필요)
비활성화:
{
channels: {
telegram: {
configWrites: false,
},
},
}
Long polling 대 Webhook
기본값은 long polling입니다. Webhook 모드에는 channels.telegram.webhookUrl과 channels.telegram.webhookSecret을 설정하세요. 선택 사항인 webhookPath, webhookHost, webhookPort의 기본값은 /telegram-webhook, 127.0.0.1, 8787입니다.
long-polling 모드에서 OpenClaw는 업데이트가 성공적으로 디스패치된 후에만 재시작 워터마크를 유지합니다. 핸들러가 실패하면 해당 업데이트는 같은 프로세스에서 재시도 가능 상태로 남으며, 재시작 중복 제거를 위해 완료로 기록되지 않습니다.
로컬 리스너는 127.0.0.1:8787에 바인딩됩니다. 공개 인그레스의 경우 로컬 포트 앞에 리버스 프록시를 두거나 의도적으로 webhookHost: "0.0.0.0"을 설정하세요.
Webhook 모드는 Telegram에 200을 반환하기 전에 요청 가드, Telegram 비밀 토큰, JSON 본문을 검증합니다.
그런 다음 OpenClaw는 long polling에서 사용하는 것과 동일한 채팅별/토픽별 봇 레인을 통해 업데이트를 비동기적으로 처리하므로, 느린 에이전트 턴이 Telegram의 전달 ACK를 붙잡지 않습니다.
제한, 재시도 및 CLI 대상
channels.telegram.textChunkLimit기본값은 4000입니다.channels.telegram.chunkMode="newline"은 길이 분할 전에 단락 경계(빈 줄)를 우선합니다.channels.telegram.mediaMaxMb(기본값 100)는 수신 및 발신 Telegram 미디어 크기를 제한합니다.channels.telegram.mediaGroupFlushMs(기본값 500)는 OpenClaw가 Telegram 앨범/미디어 그룹을 하나의 수신 메시지로 디스패치하기 전에 버퍼링하는 시간을 제어합니다. 앨범 일부가 늦게 도착하면 늘리고, 앨범 답장 지연 시간을 줄이려면 줄이세요.channels.telegram.timeoutSeconds는 Telegram API 클라이언트 제한 시간을 재정의합니다(설정하지 않으면 grammY 기본값이 적용됨). 봇 클라이언트는 구성된 값이 60초 발신 텍스트/입력 중 요청 가드보다 낮으면 클램프하여, OpenClaw의 전송 가드와 폴백이 실행되기 전에 grammY가 표시되는 답장 전달을 중단하지 않도록 합니다. long polling은 여전히 45초getUpdates요청 가드를 사용하므로 유휴 폴이 무기한 방치되지 않습니다.channels.telegram.pollingStallThresholdMs기본값은120000입니다. 거짓 양성 polling-stall 재시작에만30000과600000사이에서 조정하세요.- 그룹 컨텍스트 기록은
channels.telegram.historyLimit또는messages.groupChat.historyLimit(기본값 50)을 사용합니다.0은 비활성화합니다. - 답장/인용/전달 보조 컨텍스트는 현재 수신된 그대로 전달됩니다.
- Telegram 허용 목록은 주로 전체 보조 컨텍스트 수정 경계가 아니라 에이전트를 트리거할 수 있는 사람을 제한합니다.
- DM 기록 제어:
channels.telegram.dmHistoryLimitchannels.telegram.dms["<user_id>"].historyLimit
channels.telegram.retry구성은 복구 가능한 발신 API 오류에 대해 Telegram 전송 헬퍼(CLI/도구/작업)에 적용됩니다. 수신 최종 답장 전달도 Telegram 사전 연결 실패에 대해 제한된 안전 전송 재시도를 사용하지만, 표시되는 메시지를 중복할 수 있는 모호한 전송 후 네트워크 엔벌로프는 재시도하지 않습니다.
CLI 및 메시지 도구 전송 대상은 숫자 채팅 ID, 사용자 이름 또는 포럼 토픽 대상일 수 있습니다.
openclaw message send --channel telegram --target 123456789 --message "hi"
openclaw message send --channel telegram --target @name --message "hi"
openclaw message send --channel telegram --target -1001234567890:topic:42 --message "hi topic"
Telegram 폴은 openclaw message poll을 사용하며 포럼 토픽을 지원합니다.
openclaw message poll --channel telegram --target 123456789 \
--poll-question "Ship it?" --poll-option "Yes" --poll-option "No"
openclaw message poll --channel telegram --target -1001234567890:topic:42 \
--poll-question "Pick a time" --poll-option "10am" --poll-option "2pm" \
--poll-duration-seconds 300 --poll-public
Telegram 전용 폴 플래그:
--poll-duration-seconds(5-600)--poll-anonymous--poll-public- 포럼 토픽용
--thread-id(또는:topic:대상 사용)
Telegram 전송은 다음도 지원합니다.
channels.telegram.capabilities.inlineButtons가 허용할 때 인라인 키보드용buttons블록과 함께--presentation- 봇이 해당 채팅에서 고정할 수 있을 때 고정 전달을 요청하는
--pin또는--delivery '{"pin":true}' - 발신 이미지와 GIF를 압축된 사진 또는 애니메이션 미디어 업로드 대신 문서로 보내는
--force-document
작업 게이팅:
channels.telegram.actions.sendMessage=false는 폴을 포함한 발신 Telegram 메시지를 비활성화합니다.channels.telegram.actions.poll=false는 일반 전송을 활성 상태로 둔 채 Telegram 폴 생성을 비활성화합니다.
Telegram의 exec 승인
Telegram은 승인자 DM에서 exec 승인을 지원하며, 선택적으로 원래 채팅 또는 토픽에 프롬프트를 게시할 수 있습니다. 승인자는 숫자 Telegram 사용자 ID여야 합니다.
구성 경로:
channels.telegram.execApprovals.enabled(확인 가능한 승인자가 하나 이상 있으면 자동 활성화)channels.telegram.execApprovals.approvers(commands.ownerAllowFrom의 숫자 소유자 ID로 폴백)channels.telegram.execApprovals.target:dm(기본값) |channel|bothagentFilter,sessionFilter
channels.telegram.allowFrom, groupAllowFrom, defaultTo는 누가 봇과 대화할 수 있는지와 봇이 일반 답장을 어디로 보내는지를 제어합니다. 이것들이 누군가를 exec 승인자로 만들지는 않습니다. 명령 소유자가 아직 없을 때 첫 승인된 DM 페어링이 commands.ownerAllowFrom을 부트스트랩하므로, 단일 소유자 설정은 execApprovals.approvers 아래에 ID를 중복하지 않아도 계속 동작합니다.
채널 전달은 채팅에 명령 텍스트를 표시합니다. 신뢰할 수 있는 그룹/토픽에서만 channel 또는 both를 활성화하세요. 프롬프트가 포럼 토픽에 도착하면 OpenClaw는 승인 프롬프트와 후속 메시지에 해당 토픽을 유지합니다. exec 승인은 기본적으로 30분 후 만료됩니다.
인라인 승인 버튼도 대상 표면(dm, group 또는 all)을 허용하려면 channels.telegram.capabilities.inlineButtons가 필요합니다. plugin: 접두사가 붙은 승인 ID는 Plugin 승인을 통해 해석되고, 그 외 ID는 먼저 exec 승인을 통해 해석됩니다.
exec 승인을 참고하세요.
오류 답장 제어
에이전트가 전달 또는 제공자 오류를 만나면, Telegram은 오류 텍스트로 답장하거나 이를 억제할 수 있습니다. 두 구성 키가 이 동작을 제어합니다.
| 키 | 값 | 기본값 | 설명 |
|---|---|---|---|
channels.telegram.errorPolicy |
reply, silent |
reply |
reply는 친절한 오류 메시지를 채팅에 보냅니다. silent는 오류 답장을 완전히 억제합니다. |
channels.telegram.errorCooldownMs |
숫자(ms) | 60000 |
같은 채팅에 대한 오류 답장 사이의 최소 시간입니다. 장애 중 오류 스팸을 방지합니다. |
계정별, 그룹별, 토픽별 재정의가 지원됩니다(다른 Telegram 구성 키와 동일한 상속).
{
channels: {
telegram: {
errorPolicy: "reply",
errorCooldownMs: 120000,
groups: {
"-1001234567890": {
errorPolicy: "silent", // suppress errors in this group
},
},
},
},
}
문제 해결
봇이 멘션이 없는 그룹 메시지에 응답하지 않음
requireMention=false인 경우 Telegram 개인정보 보호 모드는 전체 가시성을 허용해야 합니다.- BotFather:
/setprivacy-> Disable - 그런 다음 그룹에서 봇을 제거하고 다시 추가합니다.
- BotFather:
- 구성에서 멘션되지 않은 그룹 메시지를 기대할 때
openclaw channels status가 경고합니다. openclaw channels status --probe는 명시적인 숫자 그룹 ID를 확인할 수 있습니다. 와일드카드"*"는 멤버십 프로브를 수행할 수 없습니다.- 빠른 세션 테스트:
/activation always.
봇이 그룹 메시지를 전혀 보지 못함
channels.telegram.groups가 있으면 그룹이 목록에 있어야 합니다(또는"*"포함).- 그룹 내 봇 멤버십을 확인합니다.
- 건너뛰기 이유는 로그에서 확인합니다:
openclaw logs --follow
명령이 일부만 작동하거나 전혀 작동하지 않음
- 발신자 ID를 승인합니다(페어링 및/또는 숫자
allowFrom). - 그룹 정책이
open이어도 명령 승인은 계속 적용됩니다. BOT_COMMANDS_TOO_MUCH와 함께setMyCommands failed가 표시되면 네이티브 메뉴 항목이 너무 많다는 뜻입니다. Plugin/Skills/사용자 지정 명령을 줄이거나 네이티브 메뉴를 비활성화하세요.deleteMyCommands/setMyCommands시작 호출과sendChatAction타이핑 호출은 제한 시간이 정해져 있으며 요청 제한 시간 초과 시 Telegram 전송 대체 경로를 통해 한 번 재시도합니다. 지속적인 네트워크/가져오기 오류는 보통api.telegram.org에 대한 DNS/HTTPS 도달성 문제를 나타냅니다.
시작 시 승인되지 않은 토큰이 보고됨
getMe returned 401은 구성된 봇 토큰에 대한 Telegram 인증 실패입니다.- BotFather에서 봇 토큰을 다시 복사하거나 재생성한 다음 기본 계정의
channels.telegram.botToken,channels.telegram.tokenFile,channels.telegram.accounts.<id>.botToken또는TELEGRAM_BOT_TOKEN을 업데이트합니다. - 시작 중
deleteWebhook 401 Unauthorized도 인증 실패입니다. 이를 "Webhook이 없음"으로 처리하면 동일한 잘못된 토큰 실패가 이후 API 호출로 미뤄질 뿐입니다.
폴링 또는 네트워크 불안정
- Node 22+와 사용자 지정 fetch/프록시는 AbortSignal 타입이 일치하지 않으면 즉시 중단 동작을 유발할 수 있습니다.
- 일부 호스트는
api.telegram.org를 IPv6로 먼저 확인합니다. IPv6 송신이 고장 나면 간헐적인 Telegram API 실패가 발생할 수 있습니다. - 로그에
TypeError: fetch failed또는Network request for 'getUpdates' failed!가 포함된 경우 OpenClaw는 이제 이를 복구 가능한 네트워크 오류로 재시도합니다. - 폴링 시작 중 OpenClaw는 성공한 시작
getMe프로브를 grammY에 재사용하므로 러너가 첫 번째getUpdates전에 두 번째getMe를 수행할 필요가 없습니다. - 폴링 시작 중 일시적인 네트워크 오류로
deleteWebhook이 실패하면 OpenClaw는 다른 사전 폴링 제어 평면 호출을 하지 않고 긴 폴링으로 계속 진행합니다. 아직 활성 Webhook이 있으면getUpdates충돌로 드러납니다. 그러면 OpenClaw는 Telegram 전송을 다시 빌드하고 Webhook 정리를 재시도합니다. - Telegram 소켓이 짧은 고정 주기로 재활용되는 경우 낮은
channels.telegram.timeoutSeconds가 설정되어 있는지 확인합니다. 봇 클라이언트는 구성 값이 송신 및getUpdates요청 가드보다 낮으면 해당 값에 맞춰 제한하지만, 이전 릴리스에서는 이 값이 가드보다 낮게 설정되면 모든 폴링 또는 응답이 중단될 수 있었습니다. - 로그에
Polling stall detected가 포함된 경우 OpenClaw는 기본적으로 완료된 긴 폴링 활성 상태가 120초 동안 없으면 폴링을 다시 시작하고 Telegram 전송을 다시 빌드합니다. openclaw channels status --probe및openclaw doctor는 실행 중인 폴링 계정이 시작 유예 기간 이후getUpdates를 완료하지 않았거나, 실행 중인 Webhook 계정이 시작 유예 기간 이후setWebhook을 완료하지 않았거나, 마지막으로 성공한 폴링 전송 활동이 오래된 경우 경고합니다.- 장시간 실행되는
getUpdates호출이 정상인데도 호스트가 잘못된 폴링 정지 재시작을 보고하는 경우에만channels.telegram.pollingStallThresholdMs를 늘립니다. 지속적인 정지는 보통 호스트와api.telegram.org사이의 프록시, DNS, IPv6 또는 TLS 송신 문제를 가리킵니다. - Telegram은
HTTP_PROXY,HTTPS_PROXY,ALL_PROXY및 소문자 변형을 포함해 Bot API 전송에 대한 프로세스 프록시 환경 변수도 따릅니다.NO_PROXY/no_proxy는 여전히api.telegram.org를 우회할 수 있습니다. - 서비스 환경에서 OpenClaw 관리형 프록시가
OPENCLAW_PROXY_URL을 통해 구성되어 있고 표준 프록시 환경 변수가 없으면 Telegram도 해당 URL을 Bot API 전송에 사용합니다. - 직접 송신/TLS가 불안정한 VPS 호스트에서는
channels.telegram.proxy를 통해 Telegram API 호출을 라우팅합니다.
channels:
telegram:
proxy: socks5://<user>:<password>@proxy-host:1080
- Node 22+는 기본적으로
autoSelectFamily=true입니다(WSL2 제외). Telegram DNS 결과 순서는OPENCLAW_TELEGRAM_DNS_RESULT_ORDER, 그다음channels.telegram.network.dnsResultOrder, 그다음NODE_OPTIONS=--dns-result-order=ipv4first같은 프로세스 기본값을 따릅니다. 적용되는 항목이 없으면 Node 22+는ipv4first로 대체됩니다. - 호스트가 WSL2이거나 명시적으로 IPv4 전용 동작이 더 잘 작동하는 경우 패밀리 선택을 강제합니다.
channels:
telegram:
network:
autoSelectFamily: false
- RFC 2544 벤치마크 범위 응답(
198.18.0.0/15)은 기본적으로 Telegram 미디어 다운로드에 이미 허용됩니다. 신뢰할 수 있는 fake-IP 또는 투명 프록시가 미디어 다운로드 중api.telegram.org를 다른 비공개/내부/특수 용도 주소로 다시 쓰는 경우 Telegram 전용 우회에 옵트인할 수 있습니다.
channels:
telegram:
network:
dangerouslyAllowPrivateNetwork: true
- 동일한 옵트인은 계정별로
channels.telegram.accounts.<accountId>.network.dangerouslyAllowPrivateNetwork에서도 사용할 수 있습니다. - 프록시가 Telegram 미디어 호스트를
198.18.x.x로 확인하는 경우 먼저 위험 플래그를 꺼 둡니다. Telegram 미디어는 기본적으로 RFC 2544 벤치마크 범위를 이미 허용합니다.
- 환경 재정의(임시):
OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first
- DNS 응답을 검증합니다.
dig +short api.telegram.org A
dig +short api.telegram.org AAAA
추가 도움말: 채널 문제 해결.
구성 참조
기본 참조: 구성 참조 - Telegram.
핵심 Telegram 필드
- 시작/인증:
enabled,botToken,tokenFile,accounts.*(tokenFile은 일반 파일을 가리켜야 하며, 심볼릭 링크는 거부됩니다) - 액세스 제어:
dmPolicy,allowFrom,groupPolicy,groupAllowFrom,groups,groups.*.topics.*, 최상위bindings[](type: "acp") - 실행 승인:
execApprovals,accounts.*.execApprovals - 명령/메뉴:
commands.native,commands.nativeSkills,customCommands - 스레딩/응답:
replyToMode,dm.threadReplies,direct.*.threadReplies - 스트리밍:
streaming(미리 보기),streaming.preview.toolProgress,blockStreaming - 형식 지정/전달:
textChunkLimit,chunkMode,linkPreview,responsePrefix - 미디어/네트워크:
mediaMaxMb,mediaGroupFlushMs,timeoutSeconds,pollingStallThresholdMs,retry,network.autoSelectFamily,network.dangerouslyAllowPrivateNetwork,proxy - 사용자 지정 API 루트:
apiRoot(Bot API 루트만 해당,/bot<TOKEN>은 포함하지 마세요) - Webhook:
webhookUrl,webhookSecret,webhookPath,webhookHost - 작업/기능:
capabilities.inlineButtons,actions.sendMessage|editMessage|deleteMessage|reactions|sticker - 반응:
reactionNotifications,reactionLevel - 오류:
errorPolicy,errorCooldownMs - 쓰기/기록:
configWrites,historyLimit,dmHistoryLimit,dms.*.historyLimit