釘釘接 AI 有三條路,選錯不是「多寫點程式」,而是上線後收不到訊息、被限流,或者資料邊界說不清
| 維度 | 方案 A:企業內部機器人 + Stream | 方案 B:自訂群機器人 Webhook | 方案 C:第三方 SaaS 託管 |
|---|---|---|---|
| 收訊息 | ✅ 單聊/群聊都可收可發 | ❌ 只能往群裡發 | ✅ 平台代收代發 |
| 要不要公網位址 | 不用:服務主動連釘釘長連線 | 不用(只出不進) | 不用 |
| 資料邊界 | 訊息與回覆都在自己伺服器 | 推送內容經釘釘伺服器 | 對話內容經第三方平台 |
| 上線耗時 | 1–3 天(主要是長連線與卡片除錯) | 約 10 分鐘 | 半天到 1 天(設定為主) |
| 適合場景 | 正式 AI 助手、客服答疑、流程查詢 | 警報播報、日報推送、CI/CD 通知 | 快速驗證價值、無開發人力 |
一句話:做對話助手選 A,做通知播報選 B,先驗證價值選 C。最常見的錯誤是拿方案 B 做對話(收不到群裡的訊息,做不了),或者沒評估資料邊界就直接上方案 C。
這是釘釘官方推薦的接入方式:你的服務用 Stream 模式主動和釘釘建立 WebSocket 長連線,員工在機器人會話裡發訊息 → 釘釘透過這條連線把訊息推給你的服務 → 服務調 AI → 再透過連線把回覆發回去。因為沒有入站 HTTP 回調,不需要公網 IP、不需要備案網域、不需要在防火牆上開埠,內網機器也能跑,這是它和「HTTP 回調」路線最大的區別。
釘釘開發者後台 →「應用開發」→「企業內部應用」→ 建立應用,然後在應用裡「加入機器人」,訊息接收模式選 Stream 模式。記下三個值:
Client ID(原 AppKey):應用憑證頁Client Secret(原 AppSecret):應用憑證頁(只顯示一次,立即存入金鑰管理,不要進程式庫)robotCode:機器人詳情頁,發訊息時要帶上發布前先把可見範圍設成一個小部門做灰度,驗證通過再放開。
Stream 模式的核心是:服務啟動時用憑證換一個臨時連線位址,然後連上去、訂閱機器人訊息主題。連線斷了要重連——這是後面坑 1 的根源。
# dingtalk_stream_bot.py —— 建立長連線並訂閱機器人訊息
from dingtalk_stream import DingTalkStreamClient, Credential
from dingtalk_stream.chatbot import ChatbotHandler, ChatbotMessage
class AIHandler(ChatbotHandler):
async def process(self, callback):
msg = ChatbotMessage.from_dict(callback.data)
# 先回執,再異步處理,別在回調裡等 AI(見坑 3)
self.reply_text("收到,正在處理…", msg)
question = msg.text.content.strip()
answer = ask_ai(question) # 你自己的 AI 服務 / 知識庫
self.reply_text(answer, msg)
return 200, "OK"
credential = Credential(CLIENT_ID, CLIENT_SECRET) # 從環境變數讀,別寫死
client = DingTalkStreamClient(credential)
client.register_callback_handler("/v1.0/im/bot/messages/get", AIHandler())
client.start_forever() # 內含自動重連,但要有行程級守護
除錯期最容易踩的坑:主題(topic)寫錯——機器人訊息的主題是固定的,寫錯會表現為「連上了但永遠收不到訊息」,日誌裡卻沒有任何報錯。
回覆會話用機器人訊息介面;如果要做「審批進度」「工單狀態」這類可點擊的互動,用互動卡片。兩個介面都走同一個 access_token,必須集中快取(有效期 7200 秒,有取得頻率限制)。
# dingtalk_client.py —— token 集中快取 + 發送機器人訊息
import time, requests
_token, _ts = "", 0
def get_token():
global _token, _ts
if _token and time.time() - _ts < 7000: # 留 200 秒餘量
return _token
r = requests.post("https://api.dingtalk.com/v1.0/oauth2/accessToken",
json={"appKey": CLIENT_ID, "appSecret": CLIENT_SECRET},
timeout=5).json()
_token, _ts = r["accessToken"], time.time()
return _token
def reply_text(user_id, text):
requests.post(
"https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend",
headers={"x-acs-dingtalk-access-token": get_token()},
json={"robotCode": ROBOT_CODE, "userIds": [user_id],
"msgKey": "sampleText", "msgParam": '{"content": "%s"}' % text[:1800]},
timeout=5)
注意最後一行:釘釘的文字訊息內容是包在 msgParam 的 JSON 字串裡的,超長要先截斷或分段,否則介面直接報錯(見坑 5)。
把 ask_ai() 換成你的 RAG 知識庫或大模型服務即可。三個工程要點:
conversationId 存最近幾輪,別把整段歷史無限拼進 prompt群設定 →「智慧群助手」→「加入機器人」→「自訂」,拿到一個 Webhook 位址,之後往這個位址 POST JSON 就能往群裡發訊息(可選加簽校驗):
curl 'https://oapi.dingtalk.com/robot/send?access_token=你的TOKEN' \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"部署完成:訂單服務 v2.3 已上線"}}'
它的定位是單向通知:監控告警、CI/CD 結果、每日播報。三個硬限制:收不到群裡的訊息(做不了對話)、每個機器人每分鐘發送條數有限(高頻告警必須做聚合)、@ 人要填手機號或 userId(不是暱稱)。支援 text、markdown、link、actionCard 等類型,適合「把系統裡的事件告訴人」,不適合「人問系統答」。
市面上有不少託管平台:授權釘釘後網頁設定知識庫和話術,不用自己寫長連線程式,半天就能上線。適合兩種情況:沒有開發人力、想先小成本驗證 AI 助手有沒有價值。
但要在簽約前問清四件事,不然日後很難受:
| 維度 | 釘釘 | 飛書 | 企業微信 |
|---|---|---|---|
| 主流接入方式 | 企業內部機器人 + Stream 長連線 | 事件訂閱(長連線或 HTTP 回調) | 自建應用 + HTTP 回調 |
| 要不要公網位址 | 不用(長連線主動外連) | 二選一,長連線可免 | 要:必須 HTTPS 回調 |
| 回調時效要求 | 長連線無 5 秒硬限 | HTTP 回調同樣要求快速返回 | 5 秒內必須響應,否則重試 |
| 訊息去重 | 按訊息 ID 去重 | 按事件 ID 去重 | 按 MsgId 去重 |
| 內網部署友好度 | 高:不需要入站埠 | 中 | 低:要暴露回調位址 |
結論:如果公司內網出網受限、又不想為回調單獨申請公網網域,釘釘的 Stream 模式是三家裡面最好落地的;企業微信的 5 秒回調硬限最需要工程兜底;飛書介於兩者之間。多平台一起接的時候,把「收訊息 → 調 AI → 回覆」抽成一層統一閘道,各平台的差異只留在適配層,後面加平台才不會推倒重來。
現象:早上員工問機器人沒反應,重啟服務就好了。
根因:長連線被中間網路設備掐斷,客戶端沒有重連成功,或者行程因為未捕獲異常退出了。
現象:日誌顯示已連線,員工發訊息卻毫無反應,也沒有報錯。
根因:訂閱的主題寫錯;或者機器人沒有發布、可見範圍沒包含提問人;或者註冊的回調路徑與訊息類型不匹配。
現象:問題複雜時,同一句話被回答兩三次,或者只回了個「收到」。
根因:在回調裡同步等 AI,逾時後平台重推;或者先回了「收到」卻沒有後續訊息。
現象:故障期間警報刷屏,最關鍵的幾條反而沒到群裡。
根因:自訂群機器人有每分鐘發送條數上限,超了直接丟棄或報錯。
現象:AI 回答長一點,員工端收不到或只有前半截,介面報參數錯誤。
根因:文字內容包在 msgParam 的 JSON 字串裡,超長或引號未轉義都會失敗。
json.dumps 產生 msgParam 而不是手拼字串;超長內容按段落切分成多條,或只回摘要 + 連結到知識庫頁面。三種方案沒有絕對優劣,選擇取決於三件事:資料邊界要求多高、有多少開發人力、要解決什麼場景。通知播報別上方案 A 浪費人力;正式對話助手別用方案 B(收不到訊息);上方案 C 之前把資料邊界四問問清楚。多數團隊的真實路徑是:先用 C 或 B 快速驗證,驗證成功後遷到方案 A 做長期自營。
如果只需要一個結論:做對話選 A,做通知選 B,做驗證選 C——別混用。