Mainstream messaging

Telegram

프로덕션에서 bot DM과 그룹에 사용할 준비가 되어 있으며 grammY를 사용합니다. 롱 폴링이 기본 모드이고, Webhook 모드는 선택 사항입니다.

빠른 설정

  • BotFather에서 bot 토큰 생성

    Telegram을 열고 @BotFather와 대화하세요(핸들이 정확히 @BotFather인지 확인).

    /newbot을 실행하고 안내를 따른 다음 토큰을 저장하세요.

  • 토큰 및 DM 정책 구성

    json5
    {channels: {telegram: {  enabled: true,  botToken: "123:abc",  dmPolicy: "pairing",  groups: { "*": { requireMention: true } },},},}

    환경 변수 대체값: TELEGRAM_BOT_TOKEN=...(기본 계정에만 해당). Telegram은 openclaw channels login telegram을 사용하지 않습니다. 구성/env에 토큰을 설정한 다음 gateway를 시작하세요.

  • Gateway 시작 및 첫 DM 승인

    bash
    openclaw gatewayopenclaw pairing list telegramopenclaw pairing approve telegram <CODE>

    페어링 코드는 1시간 후 만료됩니다.

  • bot을 그룹에 추가

    bot을 그룹에 추가한 다음, 그룹 접근에 필요한 두 ID를 모두 가져오세요.

    • allowFrom / groupAllowFrom에 사용되는 Telegram 사용자 ID
    • channels.telegram.groups 아래 키로 사용되는 Telegram 그룹 채팅 ID

    처음 설정할 때는 openclaw logs --follow, 전달된 ID를 알려주는 bot, 또는 Bot API getUpdates에서 그룹 채팅 ID를 가져오세요. 그룹이 허용된 후에는 /whoami@<bot_username>로 사용자 및 그룹 ID를 확인할 수 있습니다.

    -100으로 시작하는 음수 Telegram 슈퍼그룹 ID는 그룹 채팅 ID입니다. groupAllowFrom 아래가 아니라 channels.telegram.groups 아래에 넣으세요.

  • Telegram 측 설정

    개인정보 보호 모드와 그룹 표시 여부

    Telegram bot은 기본적으로 개인정보 보호 모드를 사용하며, 이 모드는 bot이 받는 그룹 메시지를 제한합니다.

    bot이 모든 그룹 메시지를 봐야 한다면 다음 중 하나를 수행하세요.

    • /setprivacy로 개인정보 보호 모드를 비활성화하거나
    • bot을 그룹 관리자로 지정합니다.

    개인정보 보호 모드를 전환할 때는 Telegram이 변경 사항을 적용하도록 각 그룹에서 bot을 제거한 뒤 다시 추가하세요.

    그룹 권한

    관리자 상태는 Telegram 그룹 설정에서 제어됩니다.

    관리자 bot은 모든 그룹 메시지를 받으므로, 항상 켜져 있는 그룹 동작에 유용합니다.

    유용한 BotFather 토글
    • 그룹 추가를 허용/거부하려면 /setjoingroups
    • 그룹 표시 동작을 설정하려면 /setprivacy

    접근 제어 및 활성화

    그룹 bot ID

    Telegram 그룹과 포럼 주제에서는 구성된 bot 핸들(예: @my_bot)을 명시적으로 멘션하면, agent 페르소나 이름이 Telegram 사용자 이름과 달라도 선택된 OpenClaw agent를 대상으로 한 것으로 처리됩니다. 관련 없는 그룹 트래픽에는 그룹 침묵 정책이 계속 적용되지만, bot 핸들 자체는 "다른 사람"으로 간주되지 않습니다.

    DM 정책

    channels.telegram.dmPolicy는 직접 메시지 접근을 제어합니다.

    • pairing(기본값)
    • allowlist(allowFrom에 최소 하나의 발신자 ID 필요)
    • open(allowFrom에 "*" 포함 필요)
    • disabled

    dmPolicy: "open"과 allowFrom: ["*"]를 함께 사용하면 bot 사용자 이름을 찾거나 추측한 모든 Telegram 계정이 bot에 명령할 수 있습니다. 도구가 엄격히 제한된 의도적 공개 bot에만 사용하세요. 단일 소유자 bot은 숫자 사용자 ID와 함께 allowlist를 사용해야 합니다.

    channels.telegram.allowFrom은 숫자 Telegram 사용자 ID를 받습니다. telegram: / tg: 접두사는 허용되며 정규화됩니다. 다중 계정 구성에서 제한적인 최상위 channels.telegram.allowFrom은 안전 경계로 처리됩니다. 계정 수준의 allowFrom: ["*"] 항목은 병합 후 유효 계정 허용 목록에 명시적 와일드카드가 남아 있지 않는 한 해당 계정을 공개로 만들지 않습니다. 빈 allowFrom과 함께 dmPolicy: "allowlist"를 사용하면 모든 DM이 차단되며 구성 검증에서 거부됩니다. 설정에서는 숫자 사용자 ID만 요청합니다. 업그레이드 후 구성에 @username 허용 목록 항목이 있다면 openclaw doctor --fix를 실행해 이를 확인하세요(최선 노력 방식이며 Telegram bot 토큰이 필요). 이전에 페어링 저장소 허용 목록 파일에 의존했다면, openclaw doctor --fix가 allowlist 흐름에서 항목을 channels.telegram.allowFrom으로 복구할 수 있습니다(예: dmPolicy: "allowlist"에 아직 명시적 ID가 없을 때).

    단일 소유자 bot의 경우, 이전 페어링 승인에 의존하는 대신 접근 정책이 구성에 지속되도록 명시적 숫자 allowFrom ID와 함께 dmPolicy: "allowlist"를 사용하는 것이 좋습니다.

    흔한 혼동: DM 페어링 승인은 "이 발신자가 모든 곳에서 권한을 가진다"는 뜻이 아닙니다. 페어링은 DM 접근을 부여합니다. 아직 명령 소유자가 없으면, 첫 번째 승인된 페어링은 소유자 전용 명령과 실행 승인이 명시적 운영자 계정을 갖도록 commands.ownerAllowFrom도 설정합니다. 그룹 발신자 권한 부여는 여전히 명시적 구성 허용 목록에서 나옵니다. "한 번 권한을 얻으면 DM과 그룹 명령이 모두 동작"하도록 하려면 숫자 Telegram 사용자 ID를 channels.telegram.allowFrom에 넣으세요. 소유자 전용 명령의 경우 commands.ownerAllowFrom에 telegram:<your user id>가 포함되어 있는지 확인하세요.

    Telegram 사용자 ID 찾기

    더 안전한 방법(서드파티 bot 없음):

    1. bot에 DM을 보냅니다.
    2. openclaw logs --follow를 실행합니다.
    3. from.id를 읽습니다.

    공식 Bot API 방법:

    bash
    curl "https://api.telegram.org/bot<bot_token>/getUpdates"

    서드파티 방법(개인정보 보호 수준 낮음): @userinfobot 또는 @getidsbot.

    그룹 정책 및 허용 목록

    두 제어가 함께 적용됩니다.

    1. 허용되는 그룹(channels.telegram.groups)

      • groups 구성이 없음:
        • groupPolicy: "open"인 경우: 모든 그룹이 그룹 ID 검사를 통과할 수 있음
        • groupPolicy: "allowlist"(기본값)인 경우: groups 항목(또는 "*")을 추가할 때까지 그룹이 차단됨
      • groups 구성됨: 허용 목록으로 동작(명시적 ID 또는 "*")
    2. 그룹에서 허용되는 발신자(channels.telegram.groupPolicy)

      • open
      • allowlist(기본값)
      • 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은 페어링 저장소가 아니라 구성 allowFrom으로 대체합니다. 단일 소유자 bot의 실용적인 패턴: 사용자 ID를 channels.telegram.allowFrom에 설정하고, groupAllowFrom은 설정하지 않은 채 대상 그룹을 channels.telegram.groups 아래에서 허용하세요. 런타임 참고: channels.telegram이 완전히 누락된 경우, channels.defaults.groupPolicy가 명시적으로 설정되지 않는 한 런타임은 실패 폐쇄형 groupPolicy="allowlist"를 기본값으로 사용합니다.

    소유자 전용 그룹 설정:

    json5
    {channels: {telegram: {  enabled: true,  dmPolicy: "pairing",  allowFrom: ["&lt;YOUR_TELEGRAM_USER_ID&gt;"],  groupPolicy: "allowlist",  groups: {    "&lt;GROUP_CHAT_ID&gt;": {      requireMention: true,    },  },},},}

    그룹에서 @<bot_username> ping으로 테스트하세요. requireMention: true인 동안 일반 그룹 메시지는 bot을 트리거하지 않습니다.

    예: 특정 그룹 하나에서 모든 멤버 허용:

    json5
    {channels: {telegram: {  groups: {    "-1001234567890": {      groupPolicy: "open",      requireMention: false,    },  },},},}

    예: 특정 그룹 하나 안에서 특정 사용자만 허용:

    json5
    {channels: {telegram: {  groups: {    "-1001234567890": {      requireMention: true,      allowFrom: ["8734062810", "745123456"],    },  },},},}

    멘션 동작

    그룹 답장은 기본적으로 멘션이 필요합니다.

    멘션은 다음에서 올 수 있습니다.

    • 기본 @botusername 멘션 또는
    • 다음의 멘션 패턴:
      • agents.list[].groupChat.mentionPatterns
      • messages.groupChat.mentionPatterns

    세션 수준 명령 토글:

    • /activation always
    • /activation mention

    이는 세션 상태만 업데이트합니다. 지속하려면 구성을 사용하세요.

    지속 구성 예제:

    json5
    {channels: {telegram: {  groups: {    "*": { requireMention: false },  },},},}

    그룹 히스토리 컨텍스트는 그룹에 대해 항상 켜져 있으며 historyLimit로 제한됩니다. Telegram 그룹 히스토리 창을 비활성화하려면 channels.telegram.historyLimit: 0을 설정하세요. 폐기된 includeGroupHistoryContext 키는 openclaw doctor --fix로 제거됩니다.

    그룹 채팅 ID 가져오기:

    • 그룹 메시지를 @userinfobot / @getidsbot으로 전달
    • 또는 openclaw logs --follow에서 chat.id 읽기
    • 또는 Bot API getUpdates 검사
    • 그룹이 허용된 후, 네이티브 명령이 활성화되어 있으면 /whoami@<bot_username> 실행

    런타임 동작

    • Telegram은 gateway 프로세스가 소유합니다.
    • 라우팅은 결정적입니다. Telegram 인바운드는 Telegram으로 다시 응답합니다(모델은 채널을 선택하지 않습니다).
    • 인바운드 메시지는 reply 메타데이터, 미디어 플레이스홀더, gateway가 관찰한 Telegram reply에 대한 영속 reply-chain 컨텍스트와 함께 공유 채널 envelope으로 정규화됩니다.
    • 그룹 세션은 그룹 ID로 격리됩니다. 포럼 topic은 topic을 격리하기 위해 :topic:<threadId>를 덧붙입니다.
    • DM 메시지는 message_thread_id를 포함할 수 있으며, OpenClaw는 reply를 위해 이를 보존합니다. DM topic 세션은 Telegram getMe가 봇에 대해 has_topics_enabled: true를 보고할 때만 분리됩니다. 그렇지 않으면 DM은 flat 세션에 유지됩니다.
    • Long polling은 chat/thread별 순서를 보장하는 grammY runner를 사용합니다. 전체 runner sink 동시성은 agents.defaults.maxConcurrent를 사용합니다.
    • 다중 계정 시작은 동시 Telegram getMe probe를 제한하여 대규모 봇 fleet이 모든 계정 probe를 한꺼번에 펼치지 않도록 합니다.
    • Long polling은 각 gateway 프로세스 안에서 보호되어 한 번에 하나의 활성 poller만 봇 토큰을 사용할 수 있습니다. 그래도 getUpdates 409 충돌이 보인다면 다른 OpenClaw gateway, 스크립트, 또는 외부 poller가 같은 토큰을 사용하고 있을 가능성이 큽니다.
    • Long-polling watchdog 재시작은 기본적으로 완료된 getUpdates liveness가 120초 동안 없을 때 트리거됩니다. 배포 환경에서 장시간 작업 중 잘못된 polling-stall 재시작이 계속 발생하는 경우에만 channels.telegram.pollingStallThresholdMs를 늘리세요. 값은 밀리초 단위이며 30000부터 600000까지 허용됩니다. 계정별 override도 지원됩니다.
    • Telegram Bot API는 read-receipt를 지원하지 않습니다(sendReadReceipts는 적용되지 않음).

    기능 참조

    Live stream preview (message edits)

    OpenClaw는 부분 reply를 실시간으로 스트리밍할 수 있습니다.

    • direct chat: preview 메시지 + editMessageText
    • group/topic: preview 메시지 + editMessageText

    요구 사항:

    • channels.telegram.streaming은 off | partial | block | progress입니다(기본값: partial)
    • 짧은 초기 answer preview는 debounce된 뒤, run이 아직 활성 상태이면 제한된 지연 후 materialize됩니다
    • progress는 tool 진행 상황을 위한 편집 가능한 status draft 하나를 유지하고, tool 진행 상황보다 answer activity가 먼저 도착하면 안정적인 status label을 표시하며, 완료 시 이를 지우고 최종 answer를 일반 메시지로 보냅니다
    • streaming.preview.toolProgress는 tool/progress 업데이트가 같은 편집된 preview 메시지를 재사용할지 제어합니다(기본값: preview streaming이 활성화되어 있으면 true)
    • streaming.preview.commandText는 해당 tool-progress 줄 안의 command/exec 세부 정보를 제어합니다. raw(기본값, 릴리스된 동작 보존) 또는 status(tool label만)
    • streaming.progress.commentary(기본값: false)는 임시 progress draft에 assistant commentary/preamble 텍스트를 포함하도록 opt in합니다
    • legacy channels.telegram.streamMode, boolean streaming 값, retired native draft preview 키는 감지됩니다. 현재 streaming config로 마이그레이션하려면 openclaw doctor --fix를 실행하세요

    Tool-progress preview 업데이트는 tool이 실행되는 동안 표시되는 짧은 status 줄입니다. 예를 들어 command 실행, 파일 읽기, 계획 업데이트, patch 요약, 또는 Codex app-server mode의 Codex preamble/commentary 텍스트가 있습니다. Telegram은 v2026.4.22 이후 릴리스된 OpenClaw 동작과 맞추기 위해 이를 기본적으로 활성화합니다.

    answer 텍스트에 대한 편집된 preview는 유지하되 tool-progress 줄을 숨기려면 다음을 설정하세요.

    json
    {  "channels": {    "telegram": {      "streaming": {        "mode": "partial",        "preview": {          "toolProgress": false        }      }    }  }}

    tool-progress는 보이게 유지하되 command/exec 텍스트를 숨기려면 다음을 설정하세요.

    json
    {  "channels": {    "telegram": {      "streaming": {        "mode": "partial",        "preview": {          "commandText": "status"        }      }    }  }}

    최종 answer를 같은 메시지에 편집해 넣지 않고 표시되는 tool progress를 원할 때는 progress mode를 사용하세요. command-text 정책은 streaming.progress 아래에 두세요.

    json
    {  "channels": {    "telegram": {      "streaming": {        "mode": "progress",        "progress": {          "toolProgress": true,          "commandText": "status"        }      }    }  }}

    최종본만 전달하고 싶을 때만 streaming.mode: "off"를 사용하세요. Telegram preview edit는 비활성화되고, 일반 tool/progress chatter는 독립 status 메시지로 전송되는 대신 억제됩니다. Approval prompt, media payload, error는 여전히 일반 final delivery를 통해 라우팅됩니다. tool-progress status 줄을 숨기면서 answer preview edit만 유지하려면 streaming.preview.toolProgress: false를 사용하세요.

    텍스트 전용 reply의 경우:

    • 짧은 DM/group/topic preview: OpenClaw는 같은 preview 메시지를 유지하고 최종 edit를 제자리에서 수행합니다
    • 여러 Telegram 메시지로 분할되는 긴 텍스트 final은 가능하면 기존 preview를 첫 번째 final chunk로 재사용한 뒤, 나머지 chunk만 보냅니다
    • progress-mode final은 status draft를 지우고 draft를 answer로 편집하는 대신 일반 final delivery를 사용합니다
    • 완료된 텍스트가 확인되기 전에 최종 edit가 실패하면 OpenClaw는 일반 final delivery를 사용하고 오래된 preview를 정리합니다

    복잡한 reply(예: media payload)의 경우 OpenClaw는 일반 final delivery로 fallback한 뒤 preview 메시지를 정리합니다.

    Preview streaming은 block streaming과 별개입니다. Telegram에 대해 block streaming이 명시적으로 활성화된 경우 OpenClaw는 중복 streaming을 피하기 위해 preview stream을 건너뜁니다.

    Reasoning stream 동작:

    • /reasoning stream은 지원되는 채널의 reasoning-preview 경로를 사용합니다. Telegram에서는 생성 중 reasoning을 live preview로 스트리밍합니다
    • reasoning preview는 final delivery 후 삭제됩니다. reasoning이 계속 표시되어야 하면 /reasoning on을 사용하세요
    • 최종 answer는 reasoning 텍스트 없이 전송됩니다
    Rich message formatting

    아웃바운드 텍스트는 기본적으로 표준 Telegram HTML 메시지를 사용하므로 현재 Telegram client 전반에서 reply를 읽기 쉽게 유지합니다. 이 compatibility mode는 일반 bold, italic, link, code, spoiler, quote를 지원하지만 native table, detail, rich media, formula 같은 Bot API 10.1 rich-only block은 지원하지 않습니다.

    Bot API 10.1 rich message를 사용하려면 channels.telegram.richMessages: true를 설정하세요.

    json5
    {channels: {telegram: {  richMessages: true,},},}

    활성화된 경우:

    • agent는 이 bot/account에서 Telegram rich message를 사용할 수 있다고 안내받습니다.
    • Markdown 텍스트는 OpenClaw의 Markdown IR을 통해 렌더링되고 Telegram rich HTML로 전송됩니다.
    • 명시적 rich HTML payload는 heading, table, detail, rich media, formula 같은 지원되는 Bot API 10.1 tag를 보존합니다.
    • rich message가 caption을 대체하지 않으므로 media caption은 계속 Telegram HTML caption을 사용합니다.

    이렇게 하면 모델 텍스트가 Telegram Rich Markdown sigil에서 멀어져 $400-600K 같은 통화가 수식으로 파싱되지 않습니다. 긴 rich text는 Telegram의 rich text와 rich block limit에 맞춰 자동으로 분할됩니다. Telegram의 column limit을 초과하는 table은 code block으로 전송됩니다.

    기본값: client 호환성을 위해 꺼짐. Rich message에는 호환되는 Telegram client가 필요합니다. 일부 현재 Desktop, Web, Android 및 third-party client는 허용된 rich message를 지원되지 않는 것으로 표시합니다. 봇과 함께 사용하는 모든 client가 이를 렌더링할 수 있는 경우가 아니면 이 옵션을 비활성화 상태로 유지하세요. /status는 현재 Telegram 세션에서 rich message가 켜져 있는지 꺼져 있는지 표시합니다.

    Link preview는 기본적으로 활성화되어 있습니다. channels.telegram.linkPreview: false는 rich text에 대한 자동 entity detection을 건너뜁니다.

    Native commands and custom commands

    Telegram command menu 등록은 시작 시 setMyCommands로 처리됩니다.

    Native command 기본값:

    • commands.native: "auto"는 Telegram에 대해 native command를 활성화합니다

    custom command menu entry를 추가하세요.

    json5
    {channels: {telegram: {  customCommands: [    { command: "backup", description: "Git backup" },    { command: "generate", description: "Create an image" },  ],},},}

    규칙:

    • name은 정규화됩니다(선행 / 제거, 소문자)
    • 유효한 pattern: a-z, 0-9, _, 길이 1..32
    • custom command는 native command를 override할 수 없습니다
    • conflict/duplicate는 건너뛰고 log됩니다

    참고:

    • custom command는 menu entry일 뿐이며, 동작을 자동으로 구현하지 않습니다
    • Plugin/Skills command는 Telegram menu에 표시되지 않아도 입력하면 계속 작동할 수 있습니다

    native command가 비활성화되어 있으면 built-in이 제거됩니다. 구성된 경우 custom/Plugin command는 여전히 등록될 수 있습니다.

    일반적인 설정 실패:

    • BOT_COMMANDS_TOO_MUCH와 함께 setMyCommands failed가 표시되면 trimming 후에도 Telegram menu가 여전히 overflow되었다는 뜻입니다. Plugin/Skills/custom command를 줄이거나 channels.telegram.commands.native를 비활성화하세요.
    • direct Bot API curl command는 작동하는데 deleteWebhook, deleteMyCommands, 또는 setMyCommands가 404: Not Found로 실패한다면 channels.telegram.apiRoot가 전체 /bot&lt;TOKEN&gt; endpoint로 설정되었을 수 있습니다. apiRoot는 Bot API root만이어야 하며, openclaw doctor --fix는 실수로 붙은 trailing /bot&lt;TOKEN&gt;을 제거합니다.
    • getMe returned 401은 Telegram이 구성된 봇 토큰을 거부했다는 뜻입니다. botToken, tokenFile, 또는 TELEGRAM_BOT_TOKEN을 현재 BotFather 토큰으로 업데이트하세요. OpenClaw는 polling 전에 중지하므로 이는 webhook cleanup 실패로 보고되지 않습니다.
    • network/fetch error와 함께 setMyCommands failed가 표시되면 보통 api.telegram.org로 나가는 DNS/HTTPS가 차단되었다는 뜻입니다.

    Device pairing command(device-pair Plugin)

    device-pair Plugin이 설치된 경우:

    1. /pair는 setup code를 생성합니다
    2. iOS app에 code를 붙여넣습니다
    3. /pair pending은 pending request를 나열합니다(role/scope 포함)
    4. request를 승인합니다.
      • 명시적 승인은 /pair approve <requestId>
      • pending request가 하나뿐이면 /pair approve
      • 가장 최근 항목은 /pair approve latest

    setup code는 수명이 짧은 bootstrap token을 포함합니다. Built-in setup-code bootstrap은 scopes: []가 있는 durable node token과 trusted mobile onboarding을 위한 제한된 operator handoff token을 반환합니다. 해당 operator token은 setup-time native configuration을 읽을 수 있지만 pairing mutation scope나 operator.admin을 부여하지 않습니다.

    device가 변경된 auth detail(예: role/scope/public key)로 다시 시도하면 이전 pending request는 supersede되고 새 request는 다른 requestId를 사용합니다. 승인하기 전에 /pair pending을 다시 실행하세요.

    자세한 내용: 페어링.

    Inline buttons

    인라인 키보드 범위 구성:

    json5
    {channels: {telegram: {  capabilities: {    inlineButtons: "allowlist",  },},},}

    계정별 재정의:

    json5
    {channels: {telegram: {  accounts: {    main: {      capabilities: {        inlineButtons: "allowlist",      },    },  },},},}

    범위:

    • off
    • dm
    • group
    • all
    • allowlist (기본값)

    레거시 capabilities: ["inlineButtons"]는 inlineButtons: "all"에 매핑됩니다.

    메시지 작업 예:

    json5
    {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" }],],}

    Mini App 버튼 예:

    json5
    {action: "send",channel: "telegram",to: "123456789",message: "Open app:",presentation: {blocks: [  {    type: "buttons",    buttons: [{ label: "Launch", web_app: { url: "https://example.com/app" } }],  },],},}

    Telegram web_app 버튼은 사용자와 봇 간의 비공개 채팅에서만 작동합니다.

    등록된 Plugin 대화형 핸들러가 처리하지 않은 콜백 클릭은 텍스트로 에이전트에 전달됩니다: callback_data: <value>

    Telegram message actions for agents and automation

    Telegram 도구 작업에는 다음이 포함됩니다:

    • sendMessage (to, content, 선택 사항 mediaUrl, replyToMessageId, messageThreadId)
    • react (chatId, messageId, emoji)
    • deleteMessage (chatId, messageId)
    • editMessage (chatId, messageId, content 또는 caption, 선택 사항 presentation 인라인 버튼; 버튼만 수정하는 경우 reply markup을 업데이트함)
    • createForumTopic (chatId, name, 선택 사항 iconColor, iconCustomEmojiId)

    채널 메시지 작업은 쓰기 편한 별칭(send, react, delete, edit, sticker, sticker-search, topic-create)을 노출합니다.

    게이팅 제어:

    • channels.telegram.actions.sendMessage
    • channels.telegram.actions.deleteMessage
    • channels.telegram.actions.reactions
    • channels.telegram.actions.sticker (기본값: 비활성화)

    참고: edit 및 topic-create는 현재 기본적으로 활성화되어 있으며 별도의 channels.telegram.actions.* 토글이 없습니다. 런타임 전송은 활성 config/secrets 스냅샷(시작/다시 로드)을 사용하므로, 작업 경로는 전송마다 임시 SecretRef 재해석을 수행하지 않습니다.

    반응 제거 의미 체계: /tools/reactions

    Reply threading tags

    Telegram은 생성된 출력에서 명시적 답장 스레딩 태그를 지원합니다:

    • [[reply_to_current]]는 트리거한 메시지에 답장합니다
    • [[reply_to:<id>]]는 특정 Telegram 메시지 ID에 답장합니다

    channels.telegram.replyToMode는 처리를 제어합니다:

    • off (기본값)
    • first
    • all

    답장 스레딩이 활성화되어 있고 원본 Telegram 텍스트 또는 캡션을 사용할 수 있으면, OpenClaw는 네이티브 Telegram 인용 발췌를 자동으로 포함합니다. Telegram은 네이티브 인용 텍스트를 1024개의 UTF-16 코드 단위로 제한하므로, 더 긴 메시지는 시작 부분부터 인용되며 Telegram이 인용을 거부하면 일반 답장으로 대체됩니다.

    참고: off는 암시적 답장 스레딩을 비활성화합니다. 명시적 [[reply_to_*]] 태그는 계속 적용됩니다.

    Forum topics and thread behavior

    포럼 슈퍼그룹:

    • 토픽 세션 키는 :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는 토픽 전용이며 그룹 기본값에서 상속되지 않습니다. topics."*"는 해당 그룹의 모든 토픽에 대한 기본값을 설정합니다. 정확한 토픽 ID는 여전히 "*"보다 우선합니다.

    토픽별 에이전트 라우팅: 각 토픽은 토픽 구성에서 agentId를 설정하여 다른 에이전트로 라우팅할 수 있습니다. 이렇게 하면 각 토픽에 자체 격리된 작업 공간, 메모리, 세션이 제공됩니다. 예:

    json5
    {  channels: {    telegram: {      groups: {        "-1001234567890": {          topics: {            "1": { agentId: "main" },      // General topic → main agent            "3": { agentId: "zu" },        // Dev topic → zu agent            "5": { agentId: "coder" }      // Code review → coder agent          }        }      }    }  }}

    그러면 각 토픽은 자체 세션 키를 갖습니다: agent:zu:telegram:group:-1001234567890:topic:3

    영구 ACP 토픽 바인딩: 포럼 토픽은 최상위 타입 지정 ACP 바인딩(type: "acp" 및 match.channel: "telegram", peer.kind: "group", 그리고 -1001234567890:topic:42 같은 토픽 한정 ID가 포함된 bindings[])을 통해 ACP 하네스 세션을 고정할 수 있습니다. 현재 그룹/슈퍼그룹의 포럼 토픽으로 범위가 제한됩니다. ACP 에이전트를 참조하세요.

    채팅에서 스레드 바인딩 ACP 생성: /acp spawn <agent> --thread here|auto는 현재 토픽을 새 ACP 세션에 바인딩합니다. 후속 메시지는 해당 세션으로 직접 라우팅됩니다. OpenClaw는 생성 확인을 토픽 안에 고정합니다. channels.telegram.threadBindings.spawnSessions가 계속 활성화되어 있어야 합니다(기본값: true).

    템플릿 컨텍스트는 MessageThreadId 및 IsForum을 노출합니다. message_thread_id가 있는 DM 채팅은 답장 메타데이터를 유지합니다. 봇에 대해 Telegram getMe가 has_topics_enabled: true를 보고하는 경우에만 스레드 인식 세션 키를 사용합니다. 이전 dm.threadReplies 및 direct.*.threadReplies 재정의는 의도적으로 폐기되었습니다. BotFather 스레드 모드를 단일 정보 소스로 사용하고 openclaw doctor --fix를 실행하여 오래된 구성 키를 제거하세요.

    Audio, video, and stickers

    오디오 메시지

    Telegram은 음성 메모와 오디오 파일을 구분합니다.

    • 기본값: 오디오 파일 동작
    • 에이전트 답장에 [[audio_as_voice]] 태그를 넣으면 음성 메모 전송을 강제합니다
    • 인바운드 음성 메모 전사는 에이전트 컨텍스트에서 기계 생성, 신뢰할 수 없는 텍스트로 프레이밍됩니다. 멘션 감지는 여전히 원시 전사를 사용하므로 멘션 게이트가 적용된 음성 메시지가 계속 작동합니다.

    메시지 작업 예:

    json5
    {action: "send",channel: "telegram",to: "123456789",media: "https://example.com/voice.ogg",asVoice: true,}

    비디오 메시지

    Telegram은 비디오 파일과 비디오 노트를 구분합니다.

    메시지 작업 예시:

    json5
    {action: "send",channel: "telegram",to: "123456789",media: "https://example.com/video.mp4",asVideoNote: true,}

    비디오 노트는 캡션을 지원하지 않으며, 제공된 메시지 텍스트는 별도로 전송됩니다.

    스티커

    수신 스티커 처리:

    • 정적 WEBP: 다운로드되어 처리됨(플레이스홀더 <media:sticker>)
    • 애니메이션 TGS: 건너뜀
    • 비디오 WEBM: 건너뜀

    스티커 컨텍스트 필드:

    • Sticker.emoji
    • Sticker.setName
    • Sticker.fileId
    • Sticker.fileUniqueId
    • Sticker.cachedDescription

    스티커 설명은 반복적인 비전 호출을 줄이기 위해 OpenClaw SQLite Plugin 상태에 캐시됩니다.

    스티커 작업 활성화:

    json5
    {channels: {telegram: {  actions: {    sticker: true,  },},},}

    스티커 작업 전송:

    json5
    {action: "sticker",channel: "telegram",to: "123456789",fileId: "CAACAgIAAxkBAAI...",}

    캐시된 스티커 검색:

    json5
    {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가 수신 메시지를 처리하는 동안 확인 이모지를 보냅니다. ackReactionScope는 해당 이모지가 실제로 언제 전송되는지를 결정합니다.

    이모지(ackReaction) 해석 순서:

    • channels.telegram.accounts.<accountId>.ackReaction
    • channels.telegram.ackReaction
    • messages.ackReaction
    • 에이전트 ID 이모지 폴백(agents.list[].identity.emoji, 없으면 "👀")

    참고:

    • Telegram은 유니코드 이모지를 예상합니다(예: "👀").
    • 채널 또는 계정의 반응을 비활성화하려면 ""를 사용하세요.

    범위(messages.ackReactionScope):

    Telegram provider는 messages.ackReactionScope에서 범위를 읽습니다(기본값 "group-mentions"). 현재 Telegram 계정 또는 Telegram 채널 수준 재정의는 없습니다.

    값: "all"(DM + 그룹), "direct"(DM만), "group-all"(모든 그룹 메시지, DM 제외), "group-mentions"(봇이 언급된 그룹, DM 제외 — 기본값), "off" / "none"(비활성화됨).

    Telegram 이벤트 및 명령의 설정 쓰기

    채널 설정 쓰기는 기본적으로 활성화되어 있습니다(configWrites !== false).

    Telegram에서 트리거되는 쓰기에는 다음이 포함됩니다.

    • channels.telegram.groups를 업데이트하기 위한 그룹 마이그레이션 이벤트(migrate_to_chat_id)
    • /config set 및 /config unset(명령 활성화 필요)

    비활성화:

    json5
    {channels: {telegram: {  configWrites: false,},},}
    롱 폴링과 Webhook

    기본값은 롱 폴링입니다. Webhook 모드의 경우 channels.telegram.webhookUrl 및 channels.telegram.webhookSecret을 설정하세요. 선택적으로 webhookPath, webhookHost, webhookPort를 설정할 수 있습니다(기본값 /telegram-webhook, 127.0.0.1, 8787).

    롱 폴링 모드에서 OpenClaw는 업데이트가 성공적으로 디스패치된 후에만 재시작 워터마크를 유지합니다. 핸들러가 실패하면 해당 업데이트는 같은 프로세스에서 재시도 가능한 상태로 남으며, 재시작 중복 제거를 위해 완료된 것으로 기록되지 않습니다.

    로컬 리스너는 127.0.0.1:8787에 바인딩됩니다. 공개 인그레스의 경우 로컬 포트 앞에 리버스 프록시를 두거나 의도적으로 webhookHost: "0.0.0.0"을 설정하세요.

    Webhook 모드는 Telegram에 200을 반환하기 전에 요청 가드, Telegram 비밀 토큰, JSON 본문을 검증합니다. 그런 다음 OpenClaw는 롱 폴링에서 사용하는 것과 동일한 채팅별/토픽별 봇 레인을 통해 업데이트를 비동기적으로 처리하므로, 느린 에이전트 턴이 Telegram의 전달 ACK를 붙잡지 않습니다.

    제한, 재시도 및 CLI 대상
    • channels.telegram.textChunkLimit의 기본값은 4000입니다.
    • channels.telegram.chunkMode="newline"은 길이로 분할하기 전에 문단 경계(빈 줄)를 우선합니다.
    • channels.telegram.mediaMaxMb(기본값 100)는 수신 및 발신 Telegram 미디어 크기를 제한합니다.
    • channels.telegram.mediaGroupFlushMs(기본값 500)는 Telegram 앨범/미디어 그룹을 OpenClaw가 하나의 수신 메시지로 전달하기 전에 얼마나 오래 버퍼링할지 제어합니다. 앨범 일부가 늦게 도착하면 늘리고, 앨범 응답 지연을 줄이려면 줄이세요.
    • channels.telegram.timeoutSeconds는 Telegram API 클라이언트 타임아웃을 재정의합니다(설정하지 않으면 grammY 기본값이 적용됨). Bot 클라이언트는 설정값을 60초 발신 텍스트/입력 중 요청 가드보다 낮게 제한하여, OpenClaw의 전송 가드와 fallback이 실행되기 전에 grammY가 표시되는 응답 전달을 중단하지 않도록 합니다. Long polling은 여전히 45초 getUpdates 요청 가드를 사용하므로 유휴 poll이 무기한 방치되지 않습니다.
    • channels.telegram.pollingStallThresholdMs의 기본값은 120000입니다. polling 중단 재시작이 오탐일 때만 30000에서 600000 사이로 조정하세요.
    • 그룹 컨텍스트 기록은 channels.telegram.historyLimit 또는 messages.groupChat.historyLimit(기본값 50)을 사용합니다. 0이면 비활성화됩니다.
    • 응답/인용/전달 보조 컨텍스트는 Gateway가 상위 메시지를 관찰한 경우 선택된 하나의 대화 컨텍스트 창으로 정규화됩니다. 관찰된 메시지 캐시는 OpenClaw SQLite Plugin 상태에 저장되며, openclaw doctor --fix는 레거시 sidecar를 가져옵니다. Telegram은 업데이트에 얕은 reply_to_message 하나만 포함하므로, 캐시보다 오래된 체인은 Telegram의 현재 업데이트 payload로 제한됩니다.
    • Telegram allowlist는 주로 누가 agent를 트리거할 수 있는지를 제어하며, 완전한 보조 컨텍스트 비식별화 경계가 아닙니다.
    • DM 기록 제어:
      • channels.telegram.dmHistoryLimit
      • channels.telegram.dms["<user_id>"].historyLimit
    • channels.telegram.retry 설정은 복구 가능한 발신 API 오류에 대해 Telegram 전송 helper(CLI/tools/actions)에 적용됩니다. 수신 최종 응답 전달도 Telegram 사전 연결 실패에 대해 제한된 safe-send 재시도를 사용하지만, 표시되는 메시지를 중복할 수 있는 모호한 전송 후 네트워크 envelope은 재시도하지 않습니다.

    CLI 및 message-tool 전송 대상은 숫자 chat ID, 사용자 이름 또는 forum topic 대상일 수 있습니다.

    bash
    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 poll은 openclaw message poll을 사용하며 forum topic을 지원합니다.

    bash
    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 플래그:

    • --poll-duration-seconds (5-600)
    • --poll-anonymous
    • --poll-public
    • forum topic용 --thread-id(또는 :topic: 대상 사용)

    Telegram 전송은 다음도 지원합니다.

    • channels.telegram.capabilities.inlineButtons가 허용하는 경우 inline keyboard용 buttons 블록과 함께 --presentation
    • bot이 해당 chat에서 pin할 수 있을 때 pin된 전달을 요청하는 --pin 또는 --delivery '{"pin":true}'
    • 발신 이미지, GIF, 동영상을 압축된 사진, animated-media 또는 동영상 업로드 대신 문서로 보내는 --force-document

    작업 제한:

    • channels.telegram.actions.sendMessage=false는 poll을 포함한 발신 Telegram 메시지를 비활성화합니다.
    • channels.telegram.actions.poll=false는 일반 전송은 활성화한 채 Telegram poll 생성을 비활성화합니다.
    Telegram의 exec 승인

    Telegram은 승인자 DM에서 exec 승인을 지원하며, 원본 chat 또는 topic에 프롬프트를 게시하도록 선택적으로 설정할 수 있습니다. 승인자는 숫자 Telegram user ID여야 합니다.

    설정 경로:

    • channels.telegram.execApprovals.enabled(해결 가능한 승인자가 하나 이상 있으면 자동 활성화)
    • channels.telegram.execApprovals.approvers(commands.ownerAllowFrom의 숫자 owner ID로 fallback)
    • channels.telegram.execApprovals.target: dm(기본값) | channel | both
    • agentFilter, sessionFilter

    channels.telegram.allowFrom, groupAllowFrom, defaultTo는 누가 bot과 대화할 수 있는지와 일반 응답을 어디로 보낼지 제어합니다. 이것이 누군가를 exec 승인자로 만들지는 않습니다. 아직 command owner가 없을 때 최초로 승인된 DM pairing이 commands.ownerAllowFrom을 부트스트랩하므로, 단일 owner 설정은 execApprovals.approvers 아래에 ID를 중복하지 않아도 계속 작동합니다.

    Channel 전달은 chat에 command text를 표시합니다. 신뢰할 수 있는 그룹/topic에서만 channel 또는 both를 활성화하세요. 프롬프트가 forum topic에 도착하면 OpenClaw는 승인 프롬프트와 후속 메시지에 topic을 유지합니다. Exec 승인은 기본적으로 30분 후 만료됩니다.

    Inline 승인 버튼도 대상 표면(dm, group 또는 all)을 허용하도록 channels.telegram.capabilities.inlineButtons가 필요합니다. plugin: 접두사가 붙은 승인 ID는 Plugin 승인을 통해 해석되고, 그 외에는 먼저 exec 승인을 통해 해석됩니다.

    Exec 승인을 참고하세요.

    오류 응답 제어

    agent가 전달 또는 provider 오류를 만나면, 오류 정책은 오류 메시지를 Telegram chat으로 보낼지 여부를 제어합니다.

    키 값 기본값 설명
    channels.telegram.errorPolicy always, once, silent always always — 모든 오류 메시지를 chat으로 보냅니다. once — cooldown 창마다 각 고유 오류 메시지를 한 번 보냅니다(반복되는 동일 오류 억제). silent — 오류 메시지를 chat으로 보내지 않습니다.
    channels.telegram.errorCooldownMs number (ms) 14400000 (4h) once 정책의 cooldown 창입니다. 오류가 전송된 후에는 이 간격이 지날 때까지 동일한 오류 메시지가 억제됩니다. 장애 중 오류 spam을 방지합니다.

    계정별, 그룹별, topic별 재정의가 지원됩니다(다른 Telegram 설정 키와 동일한 상속).

    json5
    {  channels: {    telegram: {      errorPolicy: "always",      errorCooldownMs: 120000,      groups: {        "-1001234567890": {          errorPolicy: "silent", // suppress errors in this group        },      },    },  },}

    문제 해결

    bot이 mention 없는 그룹 메시지에 응답하지 않음
    • requireMention=false이면 Telegram privacy mode가 전체 가시성을 허용해야 합니다.
      • BotFather: /setprivacy -> Disable
      • 그런 다음 bot을 그룹에서 제거하고 다시 추가
    • 설정이 mention 없는 그룹 메시지를 기대하면 openclaw channels status가 경고합니다.
    • openclaw channels status --probe는 명시적인 숫자 group ID를 확인할 수 있습니다. wildcard "*"는 멤버십 probe를 할 수 없습니다.
    • 빠른 세션 테스트: /activation always.
    bot이 그룹 메시지를 전혀 보지 못함
    • channels.telegram.groups가 있으면 그룹이 목록에 있어야 합니다(또는 "*" 포함).
    • 그룹 내 bot 멤버십 확인
    • skip 이유는 로그 확인: openclaw logs --follow
    command가 부분적으로 작동하거나 전혀 작동하지 않음
    • 발신자 identity를 승인하세요(pairing 및/또는 숫자 allowFrom).
    • 그룹 정책이 open이어도 command 승인은 계속 적용됩니다.
    • BOT_COMMANDS_TOO_MUCH와 함께 setMyCommands failed가 표시되면 native menu 항목이 너무 많다는 뜻입니다. Plugin/skill/custom command를 줄이거나 native menu를 비활성화하세요.
    • deleteMyCommands / setMyCommands 시작 호출과 sendChatAction 입력 호출은 제한되어 있으며 요청 timeout 시 Telegram의 transport fallback을 통해 한 번 재시도합니다. 지속적인 network/fetch 오류는 일반적으로 api.telegram.org에 대한 DNS/HTTPS 도달성 문제를 나타냅니다.
    시작 시 승인되지 않은 token을 보고함
    • getMe returned 401은 설정된 bot token에 대한 Telegram 인증 실패입니다.
    • BotFather에서 bot token을 다시 복사하거나 재생성한 다음, 기본 계정의 channels.telegram.botToken, channels.telegram.tokenFile, channels.telegram.accounts.<id>.botToken 또는 TELEGRAM_BOT_TOKEN을 업데이트하세요.
    • 시작 중 deleteWebhook 401 Unauthorized도 auth 실패입니다. 이를 "webhook이 없음"으로 처리하면 동일한 잘못된 token 실패를 이후 API 호출로 미룰 뿐입니다.
    Polling 또는 네트워크 불안정
    • Node 22+와 custom fetch/proxy는 AbortSignal type이 일치하지 않으면 즉시 abort 동작을 유발할 수 있습니다.
    • 일부 host는 api.telegram.org를 IPv6로 먼저 해석합니다. 손상된 IPv6 egress는 간헐적인 Telegram API 실패를 일으킬 수 있습니다.
    • 로그에 TypeError: fetch failed 또는 Network request for 'getUpdates' failed!가 포함되면 OpenClaw는 이제 이를 복구 가능한 네트워크 오류로 재시도합니다.
    • polling 시작 중 OpenClaw는 grammY를 위해 성공한 시작 getMe probe를 재사용하므로 runner가 첫 getUpdates 전에 두 번째 getMe를 수행할 필요가 없습니다.
    • polling 시작 중 deleteWebhook이 일시적인 네트워크 오류로 실패하면 OpenClaw는 또 다른 pre-poll control-plane 호출을 하지 않고 long polling으로 계속 진행합니다. 아직 활성화된 webhook은 getUpdates conflict로 드러납니다. 그러면 OpenClaw는 Telegram transport를 다시 만들고 webhook cleanup을 재시도합니다.
    • Telegram socket이 짧고 고정된 주기로 재활용되면 낮은 channels.telegram.timeoutSeconds를 확인하세요. bot 클라이언트는 설정값을 발신 및 getUpdates 요청 가드보다 낮게 제한하지만, 이전 release에서는 이 값이 해당 가드보다 낮게 설정되면 모든 poll 또는 응답이 abort될 수 있었습니다.
    • 로그에 Polling stall detected가 포함되면 OpenClaw는 기본적으로 완료된 long-poll liveness 없이 120초가 지난 뒤 polling을 다시 시작하고 Telegram transport를 다시 만듭니다.
    • openclaw channels status --probe 및 openclaw doctor는 실행 중인 polling 계정이 시작 grace 이후 getUpdates를 완료하지 않았거나, 실행 중인 webhook 계정이 시작 grace 이후 setWebhook을 완료하지 않았거나, 마지막으로 성공한 polling transport activity가 오래되었을 때 경고합니다.
    • 장시간 실행되는 getUpdates 호출은 정상인데 host가 계속 polling-stall 재시작을 오탐으로 보고할 때만 channels.telegram.pollingStallThresholdMs를 늘리세요. 지속적인 중단은 일반적으로 host와 api.telegram.org 사이의 proxy, DNS, IPv6 또는 TLS egress 문제를 가리킵니다.
    • Telegram은 Bot API transport에 대해 HTTP_PROXY, HTTPS_PROXY, ALL_PROXY 및 해당 소문자 variant를 포함한 process proxy env도 따릅니다. NO_PROXY / no_proxy는 여전히 api.telegram.org를 우회할 수 있습니다.
    • 서비스 환경에서 OpenClaw managed proxy가 OPENCLAW_PROXY_URL을 통해 설정되고 표준 proxy env가 없으면, Telegram도 해당 URL을 Bot API transport에 사용합니다.
    • 직접 egress/TLS가 불안정한 VPS host에서는 channels.telegram.proxy를 통해 Telegram API 호출을 라우팅하세요.
    yaml
    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 전용 동작이 명시적으로 더 잘 작동한다면 패밀리 선택을 강제하세요.
    yaml
    channels:telegram:network:  autoSelectFamily: false
    • RFC 2544 벤치마크 범위 응답(198.18.0.0/15)은 기본적으로 이미 Telegram 미디어 다운로드에 허용됩니다. 신뢰할 수 있는 fake-IP 또는 투명 프록시가 미디어 다운로드 중 api.telegram.org를 다른 사설/내부/특수 용도 주소로 다시 쓴다면 Telegram 전용 우회를 옵트인할 수 있습니다.
    yaml
    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=1
      • OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1
      • OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first
    • DNS 응답을 검증하세요.
    bash
    dig +short api.telegram.org Adig +short api.telegram.org AAAA

    추가 도움말: 채널 문제 해결.

    구성 참조

    기본 참조: 구성 참조 - Telegram.

    신호 가치가 높은 Telegram 필드
    • 시작/인증: enabled, botToken, tokenFile, accounts.* (tokenFile은 일반 파일을 가리켜야 하며, 심볼릭 링크는 거부됩니다)
    • 접근 제어: dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groups, groups.*.topics.*, 최상위 bindings[] (type: "acp")
    • 토픽 기본값: groups.<chatId>.topics."*"는 일치하지 않는 포럼 토픽에 적용되며, 정확한 토픽 ID가 이를 재정의합니다
    • 실행 승인: execApprovals, accounts.*.execApprovals
    • 명령/메뉴: commands.native, commands.nativeSkills, customCommands
    • 스레딩/답장: replyToMode
    • 스트리밍: streaming(미리 보기), streaming.preview.toolProgress, blockStreaming
    • 형식/전송: textChunkLimit, chunkMode, richMessages, linkPreview, responsePrefix
    • 미디어/네트워크: mediaMaxMb, mediaGroupFlushMs, timeoutSeconds, pollingStallThresholdMs, retry, network.autoSelectFamily, network.dangerouslyAllowPrivateNetwork, proxy
    • 사용자 지정 API 루트: apiRoot(Bot API 루트만 해당, /bot&lt;TOKEN&gt;을 포함하지 마세요)
    • Webhook: webhookUrl, webhookSecret, webhookPath, webhookHost
    • 작업/기능: capabilities.inlineButtons, actions.sendMessage|editMessage|deleteMessage|reactions|sticker
    • 반응: reactionNotifications, reactionLevel
    • 오류: errorPolicy, errorCooldownMs
    • 쓰기/기록: configWrites, historyLimit, dmHistoryLimit, dms.*.historyLimit

    관련 항목

    Was this useful?
    On this page

    On this page