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.ownerAllowFromtelegram:<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.streamingoff | 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, 또는 setMyCommands404: 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 (기본값: 비활성화)

    참고: edittopic-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).

    템플릿 컨텍스트는 MessageThreadIdIsForum을 노출합니다. message_thread_id가 있는 DM 채팅은 답장 메타데이터를 유지합니다. 봇에 대해 Telegram getMehas_topics_enabled: true를 보고하는 경우에만 스레드 인식 세션 키를 사용합니다. 이전 dm.threadRepliesdirect.*.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.webhookUrlchannels.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 --probeopenclaw 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