Skip to content

Telegram

Telegram 은 양쪽 모드 모두 동작합니다.

Mode동작
알림알림 파이프라인의 단방향 sendMessage.
IM 브릿지getUpdates long-poll 을 통한 에이전트 양방향 채팅.

같은 봇 토큰 (8…:AA…, @BotFather 에서) 이 둘을 구동합니다 — Telegram 은 path 의 토큰으로 인증합니다. 별도의 서명 스킴은 없습니다.

Feishu / DingTalk 권역 밖 사용자를 위해 설계됨

Telegram 은 Ongrid 가 비중국 팀과 운영자가 마침 Telegram 에 사는 하이브리드 배포에 권장하는 IM 채널입니다. provider 는 ADR-031 에서 추가되었습니다.

알림 모드

notify.Sender{chat_id, text}https://api.telegram.org/bot<TOKEN>/sendMessage 로 POST. 자격 증명은 (path 의) 봇 토큰; chat_id (숫자) 는 목적지 채팅입니다.

go
// internal/pkg/notify/webhook.go
NewTelegramSender(name, endpoint, chatID, client)

endpoint 는 리터럴 …/bot<TOKEN>/sendMessage URL 이고 chatID 는 대상 채팅 (DM 은 사용자의 숫자 ID, 그룹은 Telegram 이 제공하는 음수) 입니다.

설정:

  1. @BotFather 에 DM → /newbot → 사용자 이름 고르기 → 토큰 복사.
  2. 대상 채팅 (그룹 / 채널) 에 봇 추가 또는 한 번 DM 해서 봇이 당신을 알게 합니다.
  3. chat ID 가져오기. 가장 빠른 방법: 채팅에 메시지 보내고 curl https://api.telegram.org/bot<TOKEN>/getUpdatesresult[0].message.chat.id 읽기.
  4. Ongrid 에서: Settings → Channels → New → Provider = telegram → Endpoint = https://api.telegram.org/bot<TOKEN>/sendMessage, chat_id = 3 단계의 숫자.

IM 브릿지 모드 (양방향)

인바운드는 매니저의 아웃바운드 HTTPS 연결에서 long-poll 됩니다. 호출이 아웃바운드 이기 때문에 Telegram 은 NAT, 방화벽, HTTPS 프록시 뒤에서 동작합니다. setWebhook (대안) 은 Telegram 이 매니저에 도달해야 하므로 대부분의 사설 클라우드 배포와 호환되지 않고 중국 본토에서 신뢰성이 없습니다.

stream 이 유일한 모드

validator 는 그 외 모든 것을 거부:

telegram only supports stream mode

webhook 모드는 Telegram 에 대해 UI 에 노출되지 않습니다.

자격 증명 매핑

im_apps 행은 기존 컬럼을 재사용합니다 — 스키마 변경 없음:

im_apps columnTelegram 의미
provider"telegram"
mode"stream" (validator 가 고정)
app_id봇 사용자 이름 (예: ongridbot). 표시 + dedupe.
app_secretBotFather 토큰 (8…:AA…). 저장 시 암호화.
allow_from필수 콤마 구분 숫자 사용자 ID.
verify_token사용 안 함.
encrypt_key사용 안 함.

allow_from

봇과 대화 가능한 비어 있지 않은 숫자 Telegram 사용자 ID 리스트. validator 는 비숫자 토큰 (오타 alice 는 조용한 빈 화이트리스트 대신 깔끔한 required-error 로 안착) 을 버리고 음수 토큰 (그룹 / 슈퍼그룹 chat ID 이며 발신자 화이트리스트에 속하지 않음) 을 거부합니다.

telegram requires allow_from — at least one numeric Telegram user ID (the bot is publicly reachable; an empty allowlist would let anyone command the agent)

숫자 사용자 ID 찾는 방법:

  • @userinfobot 에 DM 하면 숫자 ID 로 답합니다.
  • 또는 등록 후 채팅에 메시지를 보내고 curl https://api.telegram.org/bot<TOKEN>/getUpdates 를 실행해 result[0].message.from.id 읽기.

telegram: / tg: 접두사는 조용히 제거 (OpenClaw 호환) 되므로 telegram:123456789123456789 은 같은 엔트리입니다.

Miss 시 조용한 drop

화이트리스트에 없는 발신자는 WARN 로그와 함께 버려짐:

text
telegram inbound from non-allowlisted sender — ignored
  user_id=42  user_name=alice  chat_id=42

답신 없음. placeholder 없음. 봇은 자신의 존재조차 확인하지 않습니다. 이는 OpenClaw allowFrom 을 미러링 — 답신은 에이전트 백엔드 봇이 이 사용자명에 산다는 사실을 노출하고 사람들이 탐색하도록 유혹할 수 있습니다.

설정

  1. @BotFather 에 DM → /newbot → 이름과 bot 으로 끝나는 고유 사용자 이름 선택. 토큰 복사.
  2. (선택) 봇이 그룹에서 메시지를 보길 원한다면 @BotFather → /setprivacy → Disable (기본은 mention-only).
  3. @userinfobot 으로 숫자 사용자 ID 찾기.
  4. Ongrid 에서: Settings → IM bridge → New → Provider = telegram → Mode = stream → App ID = 봇 사용자 이름 → App secret = BotFather 토큰 → allow_from = 자신 (및 팀원) 의 숫자 ID. 저장하고 Enable.
  5. 허용된 계정에서 봇에 DM. 봇이 placeholder 로 답하고 에이전트가 추론할 때마다 그 자리에서 편집합니다.

프록시 이야기

Telegram API 호스트 (api.telegram.org) 는 대부분의 네트워크에서 도달 가능하지만 중국 본토에서는 차단됩니다. provider 는 zero-value http.Client 를 사용하므로 매니저 환경의 HTTPS_PROXY / HTTP_PROXY / NO_PROXY 를 존중합니다 — getUpdates 를 운반하는 것과 같은 프록시가 sendMessage 를 운반합니다.

docker-compose 배포에서는 docker-compose.override.yml 에 프록시를 영속화하세요.

yaml
services:
  manager:
    environment:
      HTTPS_PROXY: http://your-proxy:8080
      NO_PROXY: localhost,127.0.0.1,manager,mysql,prometheus,loki,tempo,grafana,qdrant

메인 docker-compose.yml 에 프록시를 넣지 말 것

메인 docker-compose.yml 은 모든 릴리스에 실립니다. override 파일은 환경별이며 make package / install 스크립트 재실행에서 살아남습니다.

알아둘 만한 특이점

message is not modified 는 무해

editMessageText payload 가 현재 메시지 텍스트와 정확히 일치하면 Telegram 은 HTTP 400 (message is not modified) 을 반환합니다. 점진적 스트리밍은 쓰로틀 틱이나 최종 플러시에서 같은 청크를 반복할 수 있습니다. 클라이언트는 정확히 이 에러 문자열만 삼키고 nil 을 반환합니다 — 그 외의 것 (400, 403, 5xx) 은 여전히 전파됩니다. EditMessageText 참고.

봇당 poller 는 하나만

Telegram 은 동시 getUpdates 호출을 거부합니다. StreamSupervisorim_app 행당 하나의 클라이언트를 강제합니다. Telegram 앱 행을 복제하면 하나만 성공적으로 poll 하고 나머지는 409 Conflict 를 보고 백오프합니다.

Rate-limit 재시도

429 Too Many Requests 는 최대 3 회 재시도됩니다. 대기 시간은 Telegram 의 parameters.retry_after 를 60 초 상한으로 따릅니다. 5xx 에러는 1 초 / 2 초 / 4 초 백오프로 재시도. 하드 4xx (400/401/403) 는 재시도 하지 않음 — supervisor 로 버블하며 토큰 / chat-id 이슈를 시사합니다. maxCallRetries 참고.

Long-poll 타임아웃

서버 사이드 long poll 은 25 초 대기 (pollTimeoutSec), 클라이언트 사이드에 10 초 버퍼. 느린 네트워크는 그저 더 긴 poll 사이클을 볼 뿐이며 supervisor 가 busy-wait 재연결을 하지는 않습니다.

텍스트 전용

스티커, 사진, 음성 메모, 파일은 조용히 버려집니다. message.text 이벤트만 에이전트 턴을 구동합니다. 브릿지는 의도적으로 S1 (텍스트 입력 / 텍스트 출력); 리치 미디어는 향후 확장입니다.