1. 内网环境为什么优先选 Stream 模式OpenClaw 钉钉机器人接入的起点内网部署钉钉机器人最容易被卡住的地方不是代码而是网络方向。传统 Webhook 回调要求钉钉开放平台能主动访问你的服务地址这意味着你需要一个公网可解析的域名、可被外网访问的端口还要处理证书和备案。对于放在公司内网、实验室隔离网段、甚至只有一台内网测试机的 OpenClaw 网关来说这条路基本走不通。Stream 模式换了个思路不是让钉钉来找你而是你的程序主动通过 WebSocket 长连接连到钉钉开放平台。连接建立后消息沿着这条已经存在的长连接推下来你的内网机器不需要暴露任何入站端口也不需要公网域名。这就是 OpenClaw 钉钉机器人能在内网跑起来的关键。先把几个概念对齐后面配置才不会迷路。OpenClaw 是你本地或内网运行的网关/工具服务负责接收钉钉消息、调用模型能力、把结果回传。钉钉企业内部应用是你在钉钉开发者后台创建的应用载体机器人能力挂在它下面。Client ID 和 Client Secret 是这对应用的身份证前者类似账号名后者是密钥。Stream 模式则是消息接收方式决定了钉钉怎么把用户消息送到你的程序。适合谁看这篇手上已经有一台能跑 OpenClaw 的内网机器想把它接到钉钉群里做任务协同或者你正在评估内网机器人方案想确认 Stream 模式到底能不能绕开公网域名。整篇按“钉钉后台配置 → 拿凭证 → 写配置文件 → 启动验证 → 排错”的顺序走每一步都给可复制的片段。需要提前说明一点钉钉后台的配置改动必须发布新版本才会真正生效。很多人在开发态测试半天没反应就是因为只保存没发布。这个坑后面会单独讲。2. TaoToken 前置准备模型侧凭证与 OpenClaw 网关的对接思路OpenClaw 网关本身负责消息通道但机器人要真正“会说话”背后得有一个模型服务。这里我用 TaoToken 来做模型侧接入它的接口是 OpenAI 兼容格式配置起来比较直接。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。在动手配钉钉之前建议先把模型侧跑通这样出问题时能快速判断是钉钉通道的问题还是模型调用的问题。先去控制台创建一个 API Key入口在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建后复制保存注意别把 Key 贴到公开仓库里。模型侧需要记三个东西Base URL、API Key、Model ID。Base URL 填 https://taotoken.net/api API Key 用刚创建的那串Model ID 按你实际要用的模型填。这三个值在 OpenClaw 的模型配置段里会用到。如果你不确定该选哪个模型可以先去模型对话页面试一下效果地址是 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 在网页里发几条消息确认模型可用再回到本地配置。为什么强调先跑通模型侧因为 OpenClaw 接钉钉后消息链路是“钉钉 → OpenClaw 网关 → 模型服务 → 回传钉钉”。如果模型侧 Key 错了你在钉钉里发消息会一直没回复但日志里可能只看到网关在转圈排查方向容易被带偏。先把模型侧用 curl 验证一遍链路就清晰了。如果你后续要做长期编码或 Agent 类任务可以了解下 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。不过本篇聚焦钉钉通道模型侧只要保证 Base URL、Key、Model ID 三件套正确即可。另外接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到接口格式问题可以对照查。API Keys 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 方便你随时轮换密钥。3. 可复制配置钉钉后台参数与 OpenClaw 配置文件片段这一节是整篇的核心分两部分先在钉钉开发者后台把应用和机器人建好、拿到 Client ID 和 Client Secret再把这些值写进 OpenClaw 的配置文件。3.1 钉钉后台创建企业内部应用并开通机器人打开钉钉开发者后台 https://open-dev.dingtalk.com 用有开发者或管理员权限的企业账号登录。进入应用开发选择创建企业内部应用按提示填应用名称和描述。创建完成后进入应用面板在应用能力区域找到“机器人”点添加。这一步是前提没开通机器人能力后面 Stream 配置项不会出现。机器人配置页里名称、简介、描述按需填。图标要求 JPG/PNG、240×240px 以上、1:1、2MB 以内、无圆角消息预览图 png/jpeg/jpg、不超过 2M。素材不合规会直接上传失败建议提前用工具裁好。消息接收模式这里选 Stream 模式选完不需要填公网回调地址。配置完进入版本管理与发布填版本号和描述可用范围测试阶段建议选“仅我可见”避免影响同事。点保存并发布。记住不发布配置不生效。3.2 获取 Client ID 与 Client Secret版本发布后进入“凭证与基础信息”页面记录两个值参数说明示例格式Client ID原 AppKey应用标识dingxxxxxxxxxxClient Secret原 AppSecret应用密钥一长串随机字符复制时注意别带首尾空格这是后面 401 报错的常见原因。3.3 OpenClaw 配置文件片段OpenClaw 的配置一般放在网关目录下的配置文件里具体文件名以你部署版本为准常见是config.toml或settings.json。下面给一份 TOML 片段把钉钉通道和模型侧一起写进去[dingtalk] enabled true client_id dingxxxxxxxxxx client_secret 你的ClientSecret robot_code dingxxxxxxxxxx stream_mode true [model] base_url https://taotoken.net/api api_key 你的TaoTokenKey model_id 你的ModelID如果你用的是 JSON 配置等价写法如下{ dingtalk: { enabled: true, client_id: dingxxxxxxxxxx, client_secret: 你的ClientSecret, robot_code: dingxxxxxxxxxx, stream_mode: true }, model: { base_url: https://taotoken.net/api, api_key: 你的TaoTokenKey, model_id: 你的ModelID } }robot_code 通常和 Client ID 一致部分版本要求单独填按你部署包的字段说明来。stream_mode 必须为 true否则会走回调模式内网环境下会连不上。注意Client Secret 和 API Key 都属于敏感信息配置文件不要提交到公开仓库建议用环境变量注入或加本地权限控制。4. 启动与验证确认 Stream 长连接建立、消息能回配置写好后重启 OpenClaw 网关。启动日志里应该能看到类似“dingtalk stream connected”或“websocket established”的字样这说明长连接已经建立。如果日志里出现连接重试先别急着改配置往下看排错节。验证分两步。第一步在钉钉里找到你刚发布的机器人给它发一条消息比如“你好”。如果模型侧配置正确几秒内应该收到回复。第二步看 OpenClaw 网关日志确认消息进来时打印了接收记录模型调用返回了内容回传也成功。如果钉钉端没反应先用 curl 单独验证模型侧是否通curl https://taotoken.net/api/chat/completions \ -H Authorization: Bearer 你的TaoTokenKey \ -H Content-Type: application/json \ -d { model: 你的ModelID, messages: [{role: user, content: ping}] }返回里有 choices 字段和内容说明模型侧没问题问题在钉钉通道。如果这里就报 401说明 Key 不对或没带 Bearer 前缀。再验证钉钉侧凭证。可以在网关目录下用一段最小脚本测试 Stream 连接或者直接看网关日志里 Client ID 是否被正确读取。很多“连不上”其实是 Client ID 复制时多了空格或者 Client Secret 被截断。成功的结果长这样钉钉里发消息机器人回复内容与模型输出一致网关日志显示 stream 连接稳定没有反复重连模型侧 curl 返回正常。三者都对上内网部署就算跑通了。5. 常见报错排查401、local proxy failed、reading choices、OAuth这一节按真实报错来对。以下报错名都是实际会出现在日志里的关键词对照着查。401 Unauthorized出现在模型侧 curl 或网关日志里。原因通常是 API Key 错误、没带Bearer前缀、Key 被撤销。检查 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 里的 Key 状态重新复制一次。如果 Key 正确还报 401看 Base URL 是不是写成了https://taotoken.net/api/多带斜杠导致路径拼接异常统一用https://taotoken.net/api。local proxy failed这个报错一般出现在网关尝试走本地代理但代理不可用时。内网环境如果配了 HTTP_PROXY 之类的环境变量但代理服务没起就会报这个。检查环境变量把不需要的代理配置清掉或者确认代理服务在运行。注意不要配置任何违规的网络工具内网直连即可。reading choices 相关报错通常是模型返回体里没有 choices 字段或者返回了错误结构。原因可能是 Model ID 填错、请求体格式不对、或者模型侧返回了错误信息被当成正常响应解析。先用 curl 看原始返回确认有choices[0].message.content再回来看网关配置。OAuth 相关报错钉钉侧凭证问题。Client ID 或 Client Secret 不对、应用没发布、机器人能力没开通都可能触发。回到钉钉后台确认版本已发布凭证页复制的是最新值。如果用了 CC Switch、Cline MCP 或 Codex 的 auth.json 这类配置务必把 Base URL、Key、Model ID 三件套写全缺一个都会在鉴权阶段失败。再补几个非报错但常见的现象。机器人不回复但日志无异常多半是版本没发布回后台点发布。回复内容为空模型侧返回了空 content检查 Model ID 是否支持对话。连接反复断开检查内网是否有防火墙拦截出站 WebSocketStream 模式需要能出站访问钉钉开放平台。提示排查时按“模型侧 curl → 钉钉凭证 → 网关日志”的顺序能最快定位问题在哪一段避免同时改多个配置。6. 内网长期运行的配置建议与接入入口跑通之后如果打算长期在内网使用有几个点值得注意。配置文件里的密钥建议用环境变量注入比如DINGTALK_CLIENT_SECRET和TAOTOKEN_API_KEY这样配置文件可以安全地放进版本管理。网关进程建议用系统服务方式托管断线能自动重启Stream 长连接偶尔抖动时不用人工干预。日志要保留尤其是连接建立和消息收发的记录。内网环境出问题时日志是唯一能回溯的依据。如果机器人要开放给多个群使用钉钉后台的可用范围按实际权限调整测试阶段保持“仅我可见”最稳妥。模型侧如果后续要换模型或做更复杂的 Agent 任务Base URL 和 Key 不变只改 Model ID 即可。需要管理密钥就去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 要查接口细节就去 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。想先试模型效果模型对话页在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。长期编码或 Agent 场景可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。最后回到配置本身Client ID、Client Secret、Stream 模式、版本发布这四个点任何一个出问题都会导致机器人不工作。我自己的习惯是每次改完钉钉后台先在后台确认版本状态是“已发布”再重启网关看日志两步都过了再去钉钉发消息。这样排查路径最短也不会把配置问题和网络问题混在一起。