Langsung ke konten utama

Telegram (Bot API)

Status: siap produksi untuk DM bot + grup melalui grammY. Long polling adalah mode default; mode Webhook bersifat opsional.

Pairing

Kebijakan DM default untuk Telegram adalah pairing.

Pemecahan masalah kanal

Diagnostik lintas kanal dan playbook perbaikan.

Konfigurasi Gateway

Pola dan contoh konfigurasi kanal lengkap.

Penyiapan cepat

1

Buat token bot di BotFather

Buka Telegram dan mulai chat dengan @BotFather (pastikan handle-nya tepat @BotFather).Jalankan /newbot, ikuti petunjuk, dan simpan token-nya.
2

Konfigurasikan token dan kebijakan DM

{
  channels: {
    telegram: {
      enabled: true,
      botToken: "123:abc",
      dmPolicy: "pairing",
      groups: { "*": { requireMention: true } },
    },
  },
}
Fallback env: TELEGRAM_BOT_TOKEN=... (hanya akun default). Telegram tidak menggunakan openclaw channels login telegram; konfigurasikan token di config/env, lalu jalankan gateway.
3

Jalankan gateway dan setujui DM pertama

openclaw gateway
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
Kode pairing kedaluwarsa setelah 1 jam.
4

Tambahkan bot ke grup

Tambahkan bot ke grup Anda, lalu setel channels.telegram.groups dan groupPolicy agar sesuai dengan model akses Anda.
Urutan resolusi token memperhatikan akun. Dalam praktiknya, nilai config menang atas fallback env, dan TELEGRAM_BOT_TOKEN hanya berlaku untuk akun default.

Pengaturan di sisi Telegram

Bot Telegram secara default menggunakan Privacy Mode, yang membatasi pesan grup yang mereka terima.Jika bot harus dapat melihat semua pesan grup, lakukan salah satu hal berikut:
  • nonaktifkan privacy mode melalui /setprivacy, atau
  • jadikan bot sebagai admin grup.
Saat mengubah privacy mode, hapus lalu tambahkan kembali bot di setiap grup agar Telegram menerapkan perubahan tersebut.
Status admin dikendalikan di pengaturan grup Telegram.Bot admin menerima semua pesan grup, yang berguna untuk perilaku grup yang selalu aktif.
  • /setjoingroups untuk mengizinkan/menolak penambahan ke grup
  • /setprivacy untuk perilaku visibilitas grup

Kontrol akses dan aktivasi

channels.telegram.dmPolicy mengendalikan akses pesan langsung:
  • pairing (default)
  • allowlist (memerlukan setidaknya satu ID pengirim di allowFrom)
  • open (memerlukan allowFrom menyertakan "*")
  • disabled
channels.telegram.allowFrom menerima ID pengguna Telegram numerik. Prefix telegram: / tg: diterima dan dinormalisasi. dmPolicy: "allowlist" dengan allowFrom kosong memblokir semua DM dan ditolak oleh validasi config. Penyiapan hanya meminta ID pengguna numerik. Jika Anda melakukan upgrade dan config Anda berisi entri allowlist @username, jalankan openclaw doctor --fix untuk menyelesaikannya (best-effort; memerlukan token bot Telegram). Jika sebelumnya Anda bergantung pada file allowlist pairing-store, openclaw doctor --fix dapat memulihkan entri ke channels.telegram.allowFrom dalam alur allowlist (misalnya saat dmPolicy: "allowlist" belum memiliki ID eksplisit).Untuk bot dengan satu pemilik, gunakan dmPolicy: "allowlist" dengan ID allowFrom numerik yang eksplisit agar kebijakan akses tetap tahan lama di config (alih-alih bergantung pada persetujuan pairing sebelumnya).Kebingungan yang umum: persetujuan pairing DM tidak berarti “pengirim ini berwenang di mana-mana”. Pairing hanya memberikan akses DM. Otorisasi pengirim grup tetap berasal dari allowlist config yang eksplisit. Jika Anda ingin “saya diotorisasi sekali dan baik DM maupun perintah grup berfungsi”, masukkan ID pengguna Telegram numerik Anda ke channels.telegram.allowFrom.

Menemukan ID pengguna Telegram Anda

Lebih aman (tanpa bot pihak ketiga):
  1. Kirim DM ke bot Anda.
  2. Jalankan openclaw logs --follow.
  3. Baca from.id.
Metode resmi Bot API:
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
Metode pihak ketiga (kurang privat): @userinfobot atau @getidsbot.

Perilaku runtime

  • Telegram dimiliki oleh proses gateway.
  • Perutean bersifat deterministik: balasan masuk Telegram kembali ke Telegram (model tidak memilih kanal).
  • Pesan masuk dinormalisasi ke envelope kanal bersama dengan metadata balasan dan placeholder media.
  • Sesi grup diisolasi berdasarkan ID grup. Topik forum menambahkan :topic:<threadId> agar topik tetap terisolasi.
  • Pesan DM dapat membawa message_thread_id; OpenClaw merutekannya dengan kunci sesi yang sadar thread dan mempertahankan ID thread untuk balasan.
  • Long polling menggunakan grammY runner dengan sequencing per-chat/per-thread. Sink concurrency runner secara keseluruhan menggunakan agents.defaults.maxConcurrent.
  • Pemicu restart watchdog long polling terjadi setelah 120 detik tanpa liveness getUpdates yang selesai secara default. Tingkatkan channels.telegram.pollingStallThresholdMs hanya jika deployment Anda masih mengalami restart polling-stall palsu selama pekerjaan yang berjalan lama. Nilainya dalam milidetik dan diizinkan dari 30000 hingga 600000; override per-akun didukung.
  • Telegram Bot API tidak memiliki dukungan tanda telah dibaca (sendReadReceipts tidak berlaku).

Referensi fitur

OpenClaw dapat melakukan streaming balasan parsial secara real time:
  • obrolan langsung: pesan pratinjau + editMessageText
  • grup/topik: pesan pratinjau + editMessageText
Persyaratan:
  • channels.telegram.streaming adalah off | partial | block | progress (default: partial)
  • progress dipetakan ke partial di Telegram (kompatibilitas dengan penamaan lintas kanal)
  • streaming.preview.toolProgress mengendalikan apakah pembaruan alat/progres menggunakan kembali pesan pratinjau yang sama yang diedit (default: true). Setel false untuk mempertahankan pesan alat/progres yang terpisah.
  • nilai boolean channels.telegram.streamMode dan streaming lama dipetakan otomatis
Untuk balasan teks saja:
  • DM: OpenClaw mempertahankan pesan pratinjau yang sama dan melakukan edit final di tempat (tanpa pesan kedua)
  • grup/topik: OpenClaw mempertahankan pesan pratinjau yang sama dan melakukan edit final di tempat (tanpa pesan kedua)
Untuk balasan kompleks (misalnya payload media), OpenClaw menggunakan fallback ke pengiriman final normal lalu membersihkan pesan pratinjau.Streaming pratinjau terpisah dari block streaming. Ketika block streaming secara eksplisit diaktifkan untuk Telegram, OpenClaw melewati stream pratinjau untuk menghindari streaming ganda.Jika transport draf native tidak tersedia/ditolak, OpenClaw secara otomatis menggunakan fallback ke sendMessage + editMessageText.Stream reasoning khusus Telegram:
  • /reasoning stream mengirim reasoning ke pratinjau langsung saat menghasilkan
  • jawaban akhir dikirim tanpa teks reasoning
Teks keluar menggunakan Telegram parse_mode: "HTML".
  • Teks bergaya Markdown dirender menjadi HTML yang aman untuk Telegram.
  • HTML mentah dari model di-escape untuk mengurangi kegagalan parsing Telegram.
  • Jika Telegram menolak HTML yang sudah diparse, OpenClaw mencoba ulang sebagai teks biasa.
Pratinjau tautan diaktifkan secara default dan dapat dinonaktifkan dengan channels.telegram.linkPreview: false.
Pendaftaran menu perintah Telegram ditangani saat startup dengan setMyCommands.Default perintah native:
  • commands.native: "auto" mengaktifkan perintah native untuk Telegram
Tambahkan entri menu perintah kustom:
{
  channels: {
    telegram: {
      customCommands: [
        { command: "backup", description: "Cadangan Git" },
        { command: "generate", description: "Buat gambar" },
      ],
    },
  },
}
Aturan:
  • nama dinormalisasi (hapus / di depan, huruf kecil)
  • pola valid: a-z, 0-9, _, panjang 1..32
  • perintah kustom tidak dapat menimpa perintah native
  • konflik/duplikat dilewati dan dicatat ke log
Catatan:
  • perintah kustom hanyalah entri menu; mereka tidak otomatis mengimplementasikan perilaku
  • perintah plugin/Skills tetap dapat berfungsi saat diketik meskipun tidak ditampilkan di menu Telegram
Jika perintah native dinonaktifkan, perintah bawaan dihapus. Perintah kustom/plugin mungkin tetap terdaftar jika dikonfigurasi.Kegagalan penyiapan yang umum:
  • setMyCommands failed dengan BOT_COMMANDS_TOO_MUCH berarti menu Telegram masih meluap setelah dipangkas; kurangi perintah plugin/Skills/kustom atau nonaktifkan channels.telegram.commands.native.
  • setMyCommands failed dengan kesalahan network/fetch biasanya berarti DNS/HTTPS keluar ke api.telegram.org diblokir.

Perintah pairing perangkat (device-pair Plugin)

Saat Plugin device-pair terpasang:
  1. /pair menghasilkan kode penyiapan
  2. tempel kode di aplikasi iOS
  3. /pair pending menampilkan daftar permintaan yang tertunda (termasuk peran/scope)
  4. setujui permintaan:
    • /pair approve <requestId> untuk persetujuan eksplisit
    • /pair approve jika hanya ada satu permintaan tertunda
    • /pair approve latest untuk yang paling baru
Kode penyiapan membawa token bootstrap berumur pendek. Serah-terima bootstrap bawaan menjaga token Node utama tetap pada scopes: []; token operator yang diserahkan tetap dibatasi ke operator.approvals, operator.read, operator.talk.secrets, dan operator.write. Pemeriksaan scope bootstrap menggunakan prefix peran, sehingga allowlist operator itu hanya memenuhi permintaan operator; peran non-operator tetap memerlukan scope di bawah prefix perannya sendiri.Jika sebuah perangkat mencoba ulang dengan detail auth yang berubah (misalnya peran/scope/public key), permintaan tertunda sebelumnya akan digantikan dan permintaan baru menggunakan requestId yang berbeda. Jalankan kembali /pair pending sebelum menyetujui.Detail lebih lanjut: Pairing.
Konfigurasikan cakupan keyboard inline:
{
  channels: {
    telegram: {
      capabilities: {
        inlineButtons: "allowlist",
      },
    },
  },
}
Override per akun:
{
  channels: {
    telegram: {
      accounts: {
        main: {
          capabilities: {
            inlineButtons: "allowlist",
          },
        },
      },
    },
  },
}
Cakupan:
  • off
  • dm
  • group
  • all
  • allowlist (default)
capabilities: ["inlineButtons"] lama dipetakan ke inlineButtons: "all".Contoh aksi pesan:
{
  action: "send",
  channel: "telegram",
  to: "123456789",
  message: "Pilih sebuah opsi:",
  buttons: [
    [
      { text: "Ya", callback_data: "yes" },
      { text: "Tidak", callback_data: "no" },
    ],
    [{ text: "Batal", callback_data: "cancel" }],
  ],
}
Klik callback diteruskan ke agen sebagai teks: callback_data: <value>
Aksi alat Telegram mencakup:
  • sendMessage (to, content, opsional mediaUrl, replyToMessageId, messageThreadId)
  • react (chatId, messageId, emoji)
  • deleteMessage (chatId, messageId)
  • editMessage (chatId, messageId, content)
  • createForumTopic (chatId, name, opsional iconColor, iconCustomEmojiId)
Aksi pesan kanal mengekspos alias yang lebih ergonomis (send, react, delete, edit, sticker, sticker-search, topic-create).Kontrol pemfilteran:
  • channels.telegram.actions.sendMessage
  • channels.telegram.actions.deleteMessage
  • channels.telegram.actions.reactions
  • channels.telegram.actions.sticker (default: disabled)
Catatan: edit dan topic-create saat ini diaktifkan secara default dan tidak memiliki toggle channels.telegram.actions.* terpisah. Pengiriman runtime menggunakan snapshot config/secrets aktif (startup/reload), sehingga jalur aksi tidak melakukan re-resolve SecretRef ad hoc untuk setiap pengiriman.Semantik penghapusan reaksi: /tools/reactions
Telegram mendukung tag threading balasan eksplisit dalam output yang dihasilkan:
  • [[reply_to_current]] membalas pesan pemicu
  • [[reply_to:<id>]] membalas ID pesan Telegram tertentu
channels.telegram.replyToMode mengendalikan penanganannya:
  • off (default)
  • first
  • all
Catatan: off menonaktifkan threading balasan implisit. Tag [[reply_to_*]] eksplisit tetap dihormati.
Supergroup forum:
  • kunci sesi topik menambahkan :topic:<threadId>
  • balasan dan indikator mengetik menargetkan thread topik
  • path config topik: channels.telegram.groups.<chatId>.topics.<threadId>
Topik umum (threadId=1) kasus khusus:
  • pengiriman pesan menghilangkan message_thread_id (Telegram menolak sendMessage(...thread_id=1))
  • aksi mengetik tetap menyertakan message_thread_id
Pewarisan topik: entri topik mewarisi pengaturan grup kecuali dioverride (requireMention, allowFrom, skills, systemPrompt, enabled, groupPolicy). agentId hanya untuk topik dan tidak mewarisi default grup.Perutean agen per topik: Setiap topik dapat dirutekan ke agen yang berbeda dengan menyetel agentId di config topik. Ini memberi setiap topik workspace, memori, dan sesi terisolasi sendiri. Contoh:
{
  channels: {
    telegram: {
      groups: {
        "-1001234567890": {
          topics: {
            "1": { agentId: "main" },      // Topik umum → agen main
            "3": { agentId: "zu" },        // Topik dev → agen zu
            "5": { agentId: "coder" }      // Tinjauan kode → agen coder
          }
        }
      }
    }
  }
}
Setiap topik kemudian memiliki kunci sesi sendiri: agent:zu:telegram:group:-1001234567890:topic:3Binding topik ACP persisten: Topik forum dapat menyematkan sesi harness ACP melalui binding ACP bertipe tingkat atas:
  • bindings[] dengan type: "acp" dan match.channel: "telegram"
Contoh:
{
  agents: {
    list: [
      {
        id: "codex",
        runtime: {
          type: "acp",
          acp: {
            agent: "codex",
            backend: "acpx",
            mode: "persistent",
            cwd: "/workspace/openclaw",
          },
        },
      },
    ],
  },
  bindings: [
    {
      type: "acp",
      agentId: "codex",
      match: {
        channel: "telegram",
        accountId: "default",
        peer: { kind: "group", id: "-1001234567890:topic:42" },
      },
    },
  ],
  channels: {
    telegram: {
      groups: {
        "-1001234567890": {
          topics: {
            "42": {
              requireMention: false,
            },
          },
        },
      },
    },
  },
}
Ini saat ini dibatasi pada topik forum di grup dan supergroup.Spawn ACP yang terikat ke thread dari chat:
  • /acp spawn <agent> --thread here|auto dapat mengikat topik Telegram saat ini ke sesi ACP baru.
  • Pesan topik lanjutan dirutekan langsung ke sesi ACP yang terikat (tidak perlu /acp steer).
  • OpenClaw menyematkan pesan konfirmasi spawn di dalam topik setelah binding berhasil.
  • Memerlukan channels.telegram.threadBindings.spawnAcpSessions=true.
Konteks template mencakup:
  • MessageThreadId
  • IsForum
Perilaku thread DM:
  • chat privat dengan message_thread_id tetap mempertahankan perutean DM tetapi menggunakan kunci sesi/target balasan yang sadar thread.

Pesan audio

Telegram membedakan catatan suara dan file audio.
  • default: perilaku file audio
  • tag [[audio_as_voice]] dalam balasan agen untuk memaksa pengiriman sebagai catatan suara
Contoh aksi pesan:
{
  action: "send",
  channel: "telegram",
  to: "123456789",
  media: "https://example.com/voice.ogg",
  asVoice: true,
}

Pesan video

Telegram membedakan file video dan catatan video.Contoh aksi pesan:
{
  action: "send",
  channel: "telegram",
  to: "123456789",
  media: "https://example.com/video.mp4",
  asVideoNote: true,
}
Catatan video tidak mendukung caption; teks pesan yang diberikan dikirim secara terpisah.

Stiker

Penanganan stiker masuk:
  • WEBP statis: diunduh dan diproses (placeholder <media:sticker>)
  • TGS animasi: dilewati
  • WEBM video: dilewati
Bidang konteks stiker:
  • Sticker.emoji
  • Sticker.setName
  • Sticker.fileId
  • Sticker.fileUniqueId
  • Sticker.cachedDescription
File cache stiker:
  • ~/.openclaw/telegram/sticker-cache.json
Stiker dideskripsikan satu kali (jika memungkinkan) dan di-cache untuk mengurangi panggilan vision berulang.Aktifkan aksi stiker:
{
  channels: {
    telegram: {
      actions: {
        sticker: true,
      },
    },
  },
}
Aksi kirim stiker:
{
  action: "sticker",
  channel: "telegram",
  to: "123456789",
  fileId: "CAACAgIAAxkBAAI...",
}
Cari stiker yang di-cache:
{
  action: "sticker-search",
  channel: "telegram",
  query: "cat waving",
  limit: 5,
}
Reaksi Telegram datang sebagai pembaruan message_reaction (terpisah dari payload pesan).Saat diaktifkan, OpenClaw mengantrekan peristiwa sistem seperti:
  • Telegram reaction added: 👍 by Alice (@alice) on msg 42
Konfigurasi:
  • channels.telegram.reactionNotifications: off | own | all (default: own)
  • channels.telegram.reactionLevel: off | ack | minimal | extensive (default: minimal)
Catatan:
  • own berarti hanya reaksi pengguna pada pesan yang dikirim bot (best-effort melalui cache pesan terkirim).
  • Peristiwa reaksi tetap mematuhi kontrol akses Telegram (dmPolicy, allowFrom, groupPolicy, groupAllowFrom); pengirim yang tidak berwenang dibuang.
  • Telegram tidak menyediakan ID thread dalam pembaruan reaksi.
    • grup non-forum dirutekan ke sesi chat grup
    • grup forum dirutekan ke sesi topik umum grup (:topic:1), bukan topik asal yang tepat
allowed_updates untuk polling/Webhook otomatis menyertakan message_reaction.
ackReaction mengirim emoji pengakuan saat OpenClaw sedang memproses pesan masuk.Urutan resolusi:
  • channels.telegram.accounts.<accountId>.ackReaction
  • channels.telegram.ackReaction
  • messages.ackReaction
  • fallback emoji identitas agen (agents.list[].identity.emoji, atau ”👀”)
Catatan:
  • Telegram mengharapkan emoji unicode (misalnya ”👀”).
  • Gunakan "" untuk menonaktifkan reaksi pada kanal atau akun.
Penulisan config kanal diaktifkan secara default (configWrites !== false).Penulisan yang dipicu Telegram mencakup:
  • peristiwa migrasi grup (migrate_to_chat_id) untuk memperbarui channels.telegram.groups
  • /config set dan /config unset (memerlukan pengaktifan perintah)
Nonaktifkan:
{
  channels: {
    telegram: {
      configWrites: false,
    },
  },
}
Default: long polling.Mode Webhook:
  • setel channels.telegram.webhookUrl
  • setel channels.telegram.webhookSecret (wajib saat URL Webhook disetel)
  • opsional channels.telegram.webhookPath (default /telegram-webhook)
  • opsional channels.telegram.webhookHost (default 127.0.0.1)
  • opsional channels.telegram.webhookPort (default 8787)
Listener lokal default untuk mode Webhook bind ke 127.0.0.1:8787.Jika endpoint publik Anda berbeda, letakkan reverse proxy di depan dan arahkan webhookUrl ke URL publik tersebut. Setel webhookHost (misalnya 0.0.0.0) saat Anda memang membutuhkan ingress eksternal.
  • default channels.telegram.textChunkLimit adalah 4000.
  • channels.telegram.chunkMode="newline" mengutamakan batas paragraf (baris kosong) sebelum pemisahan berdasarkan panjang.
  • channels.telegram.mediaMaxMb (default 100) membatasi ukuran media Telegram masuk dan keluar.
  • channels.telegram.timeoutSeconds menimpa timeout klien API Telegram (jika tidak disetel, default grammY berlaku).
  • channels.telegram.pollingStallThresholdMs default ke 120000; setel antara 30000 dan 600000 hanya untuk restart polling-stall false-positive.
  • riwayat konteks grup menggunakan channels.telegram.historyLimit atau messages.groupChat.historyLimit (default 50); 0 menonaktifkan.
  • konteks tambahan balasan/kutipan/terusan saat ini diteruskan sebagaimana diterima.
  • allowlist Telegram terutama memfilter siapa yang dapat memicu agen, bukan batas penyuntingan penuh untuk konteks tambahan.
  • kontrol riwayat DM:
    • channels.telegram.dmHistoryLimit
    • channels.telegram.dms["<user_id>"].historyLimit
  • config channels.telegram.retry berlaku untuk helper pengiriman Telegram (CLI/tools/actions) untuk kesalahan API keluar yang dapat dipulihkan.
Target kirim CLI dapat berupa ID chat numerik atau username:
openclaw message send --channel telegram --target 123456789 --message "hi"
openclaw message send --channel telegram --target @name --message "hi"
Poll Telegram menggunakan openclaw message poll dan mendukung topik forum:
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
Flag poll khusus Telegram:
  • --poll-duration-seconds (5-600)
  • --poll-anonymous
  • --poll-public
  • --thread-id untuk topik forum (atau gunakan target :topic:)
Pengiriman Telegram juga mendukung:
  • --presentation dengan blok buttons untuk keyboard inline saat channels.telegram.capabilities.inlineButtons mengizinkannya
  • --pin atau --delivery '{"pin":true}' untuk meminta pengiriman yang disematkan saat bot dapat menyematkan di chat tersebut
  • --force-document untuk mengirim gambar dan GIF keluar sebagai dokumen alih-alih unggahan foto terkompresi atau media animasi
Pemfilteran aksi:
  • channels.telegram.actions.sendMessage=false menonaktifkan pesan Telegram keluar, termasuk poll
  • channels.telegram.actions.poll=false menonaktifkan pembuatan poll Telegram sambil tetap mengaktifkan pengiriman biasa
Telegram mendukung persetujuan exec di DM penyetuju dan secara opsional dapat memposting prompt persetujuan di chat atau topik asal.Path config:
  • channels.telegram.execApprovals.enabled
  • channels.telegram.execApprovals.approvers (opsional; fallback ke ID pemilik numerik yang disimpulkan dari allowFrom dan defaultTo langsung bila memungkinkan)
  • channels.telegram.execApprovals.target (dm | channel | both, default: dm)
  • agentFilter, sessionFilter
Penyetuju harus berupa ID pengguna Telegram numerik. Telegram otomatis mengaktifkan persetujuan exec native saat enabled tidak disetel atau "auto" dan setidaknya satu penyetuju dapat di-resolve, baik dari execApprovals.approvers maupun dari config pemilik numerik akun (allowFrom dan defaultTo pesan langsung). Setel enabled: false untuk menonaktifkan Telegram sebagai klien persetujuan native secara eksplisit. Jika tidak, permintaan persetujuan menggunakan fallback ke rute persetujuan lain yang dikonfigurasi atau ke kebijakan fallback persetujuan exec.Telegram juga merender tombol persetujuan bersama yang digunakan oleh kanal chat lain. Adaptor Telegram native terutama menambahkan perutean DM penyetuju, fanout channel/topik, dan petunjuk mengetik sebelum pengiriman. Saat tombol-tombol itu ada, tombol tersebut menjadi UX persetujuan utama; OpenClaw hanya boleh menyertakan perintah /approve manual ketika hasil alat menyatakan persetujuan chat tidak tersedia atau persetujuan manual adalah satu-satunya jalur.Aturan pengiriman:
  • target: "dm" mengirim prompt persetujuan hanya ke DM penyetuju yang berhasil di-resolve
  • target: "channel" mengirim prompt kembali ke chat/topik Telegram asal
  • target: "both" mengirim ke DM penyetuju dan chat/topik asal
Hanya penyetuju yang berhasil di-resolve yang dapat menyetujui atau menolak. Non-penyetuju tidak dapat menggunakan /approve dan tidak dapat menggunakan tombol persetujuan Telegram.Perilaku resolusi persetujuan:
  • ID yang diawali plugin: selalu di-resolve melalui persetujuan plugin.
  • ID persetujuan lainnya mencoba exec.approval.resolve terlebih dahulu.
  • Jika Telegram juga diotorisasi untuk persetujuan plugin dan gateway menyatakan persetujuan exec tidak dikenal/kedaluwarsa, Telegram mencoba ulang sekali melalui plugin.approval.resolve.
  • Penolakan/kesalahan persetujuan exec yang nyata tidak diam-diam dialihkan ke resolusi persetujuan plugin.
Pengiriman kanal menampilkan teks perintah di chat, jadi aktifkan channel atau both hanya di grup/topik tepercaya. Saat prompt masuk ke topik forum, OpenClaw mempertahankan topik tersebut baik untuk prompt persetujuan maupun tindak lanjut pasca-persetujuan. Persetujuan exec default kedaluwarsa setelah 30 menit.Tombol persetujuan inline juga bergantung pada channels.telegram.capabilities.inlineButtons yang mengizinkan permukaan target (dm, group, atau all).Dokumen terkait: Persetujuan exec

Kontrol balasan kesalahan

Saat agen mengalami kesalahan pengiriman atau penyedia, Telegram dapat membalas dengan teks kesalahan atau menekannya. Dua kunci config mengendalikan perilaku ini:
KunciNilaiDefaultDeskripsi
channels.telegram.errorPolicyreply, silentreplyreply mengirim pesan kesalahan yang ramah ke chat. silent menekan seluruh balasan kesalahan.
channels.telegram.errorCooldownMsnumber (ms)60000Waktu minimum antar balasan kesalahan ke chat yang sama. Mencegah spam kesalahan saat outage.
Override per-akun, per-grup, dan per-topik didukung (pewarisan yang sama seperti kunci config Telegram lainnya).
{
  channels: {
    telegram: {
      errorPolicy: "reply",
      errorCooldownMs: 120000,
      groups: {
        "-1001234567890": {
          errorPolicy: "silent", // suppress errors in this group
        },
      },
    },
  },
}

Pemecahan masalah

  • Jika requireMention=false, mode privasi Telegram harus mengizinkan visibilitas penuh.
    • BotFather: /setprivacy -> Disable
    • lalu hapus + tambahkan kembali bot ke grup
  • openclaw channels status memberi peringatan saat config mengharapkan pesan grup tanpa penyebutan.
  • openclaw channels status --probe dapat memeriksa ID grup numerik eksplisit; wildcard "*" tidak dapat diperiksa keanggotaannya.
  • tes sesi cepat: /activation always.
  • saat channels.telegram.groups ada, grup harus terdaftar (atau menyertakan "*")
  • verifikasi keanggotaan bot di grup
  • tinjau log: openclaw logs --follow untuk alasan pengabaian
  • otorisasi identitas pengirim Anda (pairing dan/atau allowFrom numerik)
  • otorisasi perintah tetap berlaku walaupun kebijakan grup adalah open
  • setMyCommands failed dengan BOT_COMMANDS_TOO_MUCH berarti menu native memiliki terlalu banyak entri; kurangi perintah plugin/Skills/kustom atau nonaktifkan menu native
  • setMyCommands failed dengan kesalahan network/fetch biasanya menunjukkan masalah keterjangkauan DNS/HTTPS ke api.telegram.org
  • Node 22+ + fetch/proxy kustom dapat memicu perilaku abort langsung jika tipe AbortSignal tidak cocok.
  • Beberapa host me-resolve api.telegram.org ke IPv6 terlebih dahulu; egress IPv6 yang rusak dapat menyebabkan kegagalan API Telegram yang intermiten.
  • Jika log menyertakan TypeError: fetch failed atau Network request for 'getUpdates' failed!, OpenClaw kini mencoba ulang ini sebagai kesalahan jaringan yang dapat dipulihkan.
  • Jika log menyertakan Polling stall detected, OpenClaw memulai ulang polling dan membangun ulang transport Telegram setelah 120 detik tanpa liveness long-poll yang selesai secara default.
  • Tingkatkan channels.telegram.pollingStallThresholdMs hanya ketika panggilan getUpdates yang berjalan lama sehat tetapi host Anda tetap melaporkan restart polling-stall palsu. Stall yang persisten biasanya menunjukkan masalah proxy, DNS, IPv6, atau TLS egress antara host dan api.telegram.org.
  • Pada host VPS dengan egress/TLS langsung yang tidak stabil, rute panggilan API Telegram melalui channels.telegram.proxy:
channels:
  telegram:
    proxy: socks5://<user>:<password>@proxy-host:1080
  • Node 22+ default ke autoSelectFamily=true (kecuali WSL2) dan dnsResultOrder=ipv4first.
  • Jika host Anda adalah WSL2 atau secara eksplisit bekerja lebih baik dengan perilaku khusus IPv4, paksa pemilihan family:
channels:
  telegram:
    network:
      autoSelectFamily: false
  • Jawaban benchmark-range RFC 2544 (198.18.0.0/15) sudah diizinkan untuk unduhan media Telegram secara default. Jika fake-IP atau proxy transparan tepercaya menulis ulang api.telegram.org ke alamat privat/internal/special-use lain selama unduhan media, Anda dapat ikut serta pada bypass khusus Telegram ini:
channels:
  telegram:
    network:
      dangerouslyAllowPrivateNetwork: true
  • Opt-in yang sama juga tersedia per akun di channels.telegram.accounts.<accountId>.network.dangerouslyAllowPrivateNetwork.
  • Jika proxy Anda me-resolve host media Telegram ke 198.18.x.x, biarkan flag berbahaya tetap nonaktif terlebih dahulu. Media Telegram sudah mengizinkan benchmark range RFC 2544 secara default.
channels.telegram.network.dangerouslyAllowPrivateNetwork melemahkan proteksi SSRF media Telegram. Gunakan hanya untuk lingkungan proxy tepercaya yang dikendalikan operator seperti routing fake-IP Clash, Mihomo, atau Surge ketika mereka mensintesis jawaban privat atau special-use di luar benchmark range RFC 2544. Biarkan nonaktif untuk akses Telegram internet publik normal.
  • Override env (sementara):
    • OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1
    • OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1
    • OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first
  • Validasi jawaban DNS:
dig +short api.telegram.org A
dig +short api.telegram.org AAAA
Bantuan lebih lanjut: Pemecahan masalah kanal.

Penunjuk referensi config Telegram

Referensi utama:
  • channels.telegram.enabled: aktifkan/nonaktifkan startup kanal.
  • channels.telegram.botToken: token bot (BotFather).
  • channels.telegram.tokenFile: baca token dari path file biasa. Symlink ditolak.
  • channels.telegram.dmPolicy: pairing | allowlist | open | disabled (default: pairing).
  • channels.telegram.allowFrom: allowlist DM (ID pengguna Telegram numerik). allowlist memerlukan setidaknya satu ID pengirim. open memerlukan "*". openclaw doctor --fix dapat me-resolve entri @username lama menjadi ID dan dapat memulihkan entri allowlist dari file pairing-store dalam alur migrasi allowlist.
  • channels.telegram.actions.poll: aktifkan atau nonaktifkan pembuatan poll Telegram (default: aktif; tetap memerlukan sendMessage).
  • channels.telegram.defaultTo: target Telegram default yang digunakan oleh CLI --deliver saat tidak ada --reply-to eksplisit.
  • channels.telegram.groupPolicy: open | allowlist | disabled (default: allowlist).
  • channels.telegram.groupAllowFrom: allowlist pengirim grup (ID pengguna Telegram numerik). openclaw doctor --fix dapat me-resolve entri @username lama menjadi ID. Entri non-numerik diabaikan saat auth. Auth grup tidak menggunakan fallback pairing-store DM (2026.2.25+).
  • Prioritas multi-akun:
    • Saat dua atau lebih ID akun dikonfigurasi, setel channels.telegram.defaultAccount (atau sertakan channels.telegram.accounts.default) untuk membuat perutean default menjadi eksplisit.
    • Jika keduanya tidak disetel, OpenClaw menggunakan fallback ke ID akun ternormalisasi pertama dan openclaw doctor akan memberi peringatan.
    • channels.telegram.accounts.default.allowFrom dan channels.telegram.accounts.default.groupAllowFrom hanya berlaku untuk akun default.
    • Akun bernama mewarisi channels.telegram.allowFrom dan channels.telegram.groupAllowFrom saat nilai tingkat akun tidak disetel.
    • Akun bernama tidak mewarisi channels.telegram.accounts.default.allowFrom / groupAllowFrom.
  • channels.telegram.groups: default per-grup + allowlist (gunakan "*" untuk default global).
    • channels.telegram.groups.<id>.groupPolicy: override per-grup untuk groupPolicy (open | allowlist | disabled).
    • channels.telegram.groups.<id>.requireMention: default pemfilteran penyebutan.
    • channels.telegram.groups.<id>.skills: filter Skills (kosongkan = semua Skills, kosong [] = tidak ada).
    • channels.telegram.groups.<id>.allowFrom: override allowlist pengirim per-grup.
    • channels.telegram.groups.<id>.systemPrompt: system prompt tambahan untuk grup.
    • channels.telegram.groups.<id>.enabled: nonaktifkan grup saat false.
    • channels.telegram.groups.<id>.topics.<threadId>.*: override per-topik (field grup + agentId khusus topik).
    • channels.telegram.groups.<id>.topics.<threadId>.agentId: rutekan topik ini ke agen tertentu (menimpa perutean tingkat grup dan binding).
  • channels.telegram.groups.<id>.topics.<threadId>.groupPolicy: override per-topik untuk groupPolicy (open | allowlist | disabled).
  • channels.telegram.groups.<id>.topics.<threadId>.requireMention: override pemfilteran penyebutan per-topik.
  • bindings[] tingkat atas dengan type: "acp" dan ID topik kanonis chatId:topic:topicId di match.peer.id: field binding topik ACP persisten (lihat ACP Agents).
  • channels.telegram.direct.<id>.topics.<threadId>.agentId: rutekan topik DM ke agen tertentu (perilaku sama seperti topik forum).
  • channels.telegram.execApprovals.enabled: aktifkan Telegram sebagai klien persetujuan exec berbasis chat untuk akun ini.
  • channels.telegram.execApprovals.approvers: ID pengguna Telegram yang diizinkan untuk menyetujui atau menolak permintaan exec. Opsional ketika channels.telegram.allowFrom atau channels.telegram.defaultTo langsung sudah mengidentifikasi pemilik.
  • channels.telegram.execApprovals.target: dm | channel | both (default: dm). channel dan both mempertahankan topik Telegram asal bila ada.
  • channels.telegram.execApprovals.agentFilter: filter ID agen opsional untuk prompt persetujuan yang diteruskan.
  • channels.telegram.execApprovals.sessionFilter: filter kunci sesi opsional (substring atau regex) untuk prompt persetujuan yang diteruskan.
  • channels.telegram.accounts.<account>.execApprovals: override per-akun untuk perutean persetujuan exec Telegram dan otorisasi penyetuju.
  • channels.telegram.capabilities.inlineButtons: off | dm | group | all | allowlist (default: allowlist).
  • channels.telegram.accounts.<account>.capabilities.inlineButtons: override per-akun.
  • channels.telegram.commands.nativeSkills: aktifkan/nonaktifkan perintah Skills native Telegram.
  • channels.telegram.replyToMode: off | first | all (default: off).
  • channels.telegram.textChunkLimit: ukuran chunk keluar (karakter).
  • channels.telegram.chunkMode: length (default) atau newline untuk memisah pada baris kosong (batas paragraf) sebelum chunking berdasarkan panjang.
  • channels.telegram.linkPreview: toggle pratinjau tautan untuk pesan keluar (default: true).
  • channels.telegram.streaming: off | partial | block | progress (pratinjau stream langsung; default: partial; progress dipetakan ke partial; block adalah kompatibilitas mode pratinjau lama). Streaming pratinjau Telegram menggunakan satu pesan pratinjau yang diedit di tempat.
  • channels.telegram.streaming.preview.toolProgress: gunakan kembali pesan pratinjau langsung untuk pembaruan alat/progres saat streaming pratinjau aktif (default: true). Setel false untuk mempertahankan pesan alat/progres yang terpisah.
  • channels.telegram.mediaMaxMb: batas media Telegram masuk/keluar (MB, default: 100).
  • channels.telegram.retry: kebijakan retry untuk helper pengiriman Telegram (CLI/tools/actions) pada kesalahan API keluar yang dapat dipulihkan (attempts, minDelayMs, maxDelayMs, jitter).
  • channels.telegram.network.autoSelectFamily: override Node autoSelectFamily (true=aktifkan, false=nonaktifkan). Default aktif pada Node 22+, dengan WSL2 default nonaktif.
  • channels.telegram.network.dnsResultOrder: override urutan hasil DNS (ipv4first atau verbatim). Default ipv4first pada Node 22+.
  • channels.telegram.network.dangerouslyAllowPrivateNetwork: opt-in berbahaya untuk lingkungan fake-IP atau proxy transparan tepercaya ketika unduhan media Telegram me-resolve api.telegram.org ke alamat privat/internal/special-use di luar allowance benchmark-range RFC 2544 default.
  • channels.telegram.proxy: URL proxy untuk panggilan Bot API (SOCKS/HTTP).
  • channels.telegram.webhookUrl: aktifkan mode Webhook (memerlukan channels.telegram.webhookSecret).
  • channels.telegram.webhookSecret: secret Webhook (wajib saat webhookUrl disetel).
  • channels.telegram.webhookPath: path Webhook lokal (default /telegram-webhook).
  • channels.telegram.webhookHost: host bind Webhook lokal (default 127.0.0.1).
  • channels.telegram.webhookPort: port bind Webhook lokal (default 8787).
  • channels.telegram.actions.reactions: filter reaksi alat Telegram.
  • channels.telegram.actions.sendMessage: filter pengiriman pesan alat Telegram.
  • channels.telegram.actions.deleteMessage: filter penghapusan pesan alat Telegram.
  • channels.telegram.actions.sticker: filter aksi stiker Telegram — kirim dan cari (default: false).
  • channels.telegram.reactionNotifications: off | own | all — kendalikan reaksi mana yang memicu peristiwa sistem (default: own bila tidak disetel).
  • channels.telegram.reactionLevel: off | ack | minimal | extensive — kendalikan kapabilitas reaksi agen (default: minimal bila tidak disetel).
  • channels.telegram.errorPolicy: reply | silent — kendalikan perilaku balasan kesalahan (default: reply). Override per-akun/grup/topik didukung.
  • channels.telegram.errorCooldownMs: ms minimum antar balasan kesalahan ke chat yang sama (default: 60000). Mencegah spam kesalahan saat outage.
  • Referensi konfigurasi - Telegram
Field sinyal tinggi khusus Telegram:
  • startup/auth: enabled, botToken, tokenFile, accounts.* (tokenFile harus menunjuk ke file biasa; symlink ditolak)
  • kontrol akses: dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groups, groups.*.topics.*, bindings[] tingkat atas (type: "acp")
  • persetujuan exec: execApprovals, accounts.*.execApprovals
  • perintah/menu: commands.native, commands.nativeSkills, customCommands
  • threading/balasan: replyToMode
  • streaming: streaming (pratinjau), streaming.preview.toolProgress, blockStreaming
  • pemformatan/pengiriman: textChunkLimit, chunkMode, linkPreview, responsePrefix
  • media/jaringan: mediaMaxMb, timeoutSeconds, pollingStallThresholdMs, retry, network.autoSelectFamily, network.dangerouslyAllowPrivateNetwork, proxy
  • Webhook: webhookUrl, webhookSecret, webhookPath, webhookHost
  • actions/capabilities: capabilities.inlineButtons, actions.sendMessage|editMessage|deleteMessage|reactions|sticker
  • reaksi: reactionNotifications, reactionLevel
  • kesalahan: errorPolicy, errorCooldownMs
  • penulisan/riwayat: configWrites, historyLimit, dmHistoryLimit, dms.*.historyLimit

Terkait