尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用 OpenClaw + 钉钉打造“群里一句话建会”助手:TaoToken 统一 Key 配置实操

用 OpenClaw + 钉钉打造“群里一句话建会”助手:TaoToken 统一 Key 配置实操 1. 为什么要在钉钉群里做“一句话建会”先说清楚我们要做的东西是什么在钉钉群里 一下机器人发一句“创建会议 今天下午一点 邀请某同事 主题项目例会”机器人真的去调钉钉日历把会建出来参会人、时间、标题都对。这不是演示话术是一条能跑通的闭环。它适合谁适合手里有一台带消费级显卡的机器、想用本地模型跑企业工具、又不想把数据往外发的团队。OpenClaw 负责 Agent 编排钉钉负责入口和日历MCP 负责把日历能力暴露成工具react-proxy 负责兜住小模型的“假成功”TaoToken 负责把模型 Key 统一管起来。这几块拼在一起才是一个稳的助手。我踩过的坑是一开始以为难点在“调一个 MCP”结果真正花时间的是模型不调工具、参会人传姓名传不进去、群 成员连接器不透传。所以这篇不写虚的直接给可复制的 config.toml、settings.json 骨架加上 TaoToken 统一 Key 的接入步骤最后演示群内一句话触发建会后怎么核对返回结果。链路先看清钉钉群消息 │ (钉钉连接器接入 OpenClaw) ▼ OpenClaw Agent ── model: react-local/react-gemma4 │ baseUrl: http://react-proxy:11888/v1 ▼ react-proxyPython 增强层 │ ① 强制 ReAct 兜底 ② enrich 业务增强 ▼ upstream: http://ollama:11434/v1 本地大模型 │ 调工具 ▼ 钉钉日历 MCP → 真实创建日历会议react-proxy 不是第二个模型它和本地模型跑在同一张显卡上只是本地模型前面套的一层 Python 壳。它干两件小模型自己干不稳的事强制调工具兜底小模型容易只回话不调工具代理发现没调工具就重问最多 2 轮业务增强把正文里的同事姓名映射成钉钉 userId 注入参会人规范标题。2. TaoToken 前置统一 Key 与模型接入本地模型能跑但很多团队是“本地 云端”混用简单建会走本地复杂推理走云端。这时候 Key 管理就乱了每个服务各配一份换一次要改一堆地方。TaoToken 的价值就在这——一个统一 KeyOpenAI 兼容接口OpenClaw、react-proxy、脚本都能指向同一个 baseUrl。官网入口在这里https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 这个不加 UTM。注意TaoToken 是正常的模型接入服务不是所谓的中转配置时按官方文档填就行。接入分三步。第一步去控制台建 Key控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content第二步把 Key 写进环境变量别硬编码进代码。第三步在 OpenClaw 的模型配置里把 baseUrl 指过去。如果你只是本地跑react-proxy 的 upstream 仍指向 ollama如果要走云端把 upstream 换成 TaoToken 的 API 地址即可其余逻辑不动。模型对话想先验证 Key 通不通可以直接用对话页试一句模型对话https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content长期做编码或 Agent 的建议看 Coding Plan额度更划算Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 参数以文档为准。ClaudeCodeAnthropic 相关配置参考 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。3. 可复制配置config.toml 与 settings.json 骨架这一节给能直接抄的骨架。先建专用网络容器间用服务名互访docker network create ai-net启动 ollama注意把显卡透传给容器docker run -d --name ollama --network ai-net --gpus all \ -v 宿主机模型目录:/root/.ollama \ ollama/ollama验证模型在列表里docker exec ollama ollama list启动 OpenClaw 核心配置文件通过卷挂进去docker run -d --name openclaw --network ai-net --restart unless-stopped \ -p 18789:18789 \ -v D:/Docker/openclaw-data/openclaw.json:/home/node/.openclaw/openclaw.json \ ghcr.io/openclaw/openclaw:latestopenclaw.json 里模型相关片段baseUrl 不要直连 ollama指向 react-proxy{ agents: { defaults: { model: react-local/react-gemma4, compaction: { reserveTokensFloor: 4096, reserveTokens: 4096 } } }, models: { react-gemma4: { contextWindow: 32768, maxTokens: 2048, baseUrl: http://react-proxy:11888/v1, model: gemma4:12b } }, mcp: { servers: { dingtalk-calendar: { url: 你的钉钉日历 MCP 网关地址 } } }, channels: { dingtalk: { enabled: true, clientId: 你的钉钉 clientId, clientSecret: 你的钉钉 clientSecret, groupPolicy: open } } }如果你更习惯用 config.toml 管理模型与代理参数可以这样写字段名按你实际版本对齐[model] name react-local/react-gemma4 base_url http://react-proxy:11888/v1 context_window 32768 max_tokens 2048 [proxy] upstream http://ollama:11434/v1 max_retries 2 initiator_name 你的名字 [mcp.dingtalk_calendar] url 你的钉钉日历 MCP 网关地址 [channel.dingtalk] enabled true client_id 你的钉钉 clientId client_secret 你的钉钉 clientSecret group_policy opensettings.json 用来放通讯录和运行期开关别把 userId 写进代码{ contacts: { 某同事: 钉钉 userId一串数字, 另一同事: 钉钉 userId一串数字 }, defaults: { summary_template: {initiator}的会议, timezone: Asia/Shanghai } }注意contextWindow 与 compaction.reserveTokens 的关系要留足余量预留必须远小于窗口否则长会话会触发压缩死循环。4. react-proxy 增强层与验证请求react-proxy 的核心逻辑是转发加 enrich。新建 react_proxy.pyimport json, os, httpx OLLAMA_URL os.getenv(OLLAMA_URL, http://ollama:11434/v1) CONTACTS json.load(open(/contacts.json, encodingutf-8)).get(contacts, {}) INITIATOR os.getenv(INITIATOR_NAME, 我) def enrich_create_event(tool_calls, messages): 服务端兜底姓名映射 userId规范标题。 topic extract_user_topic(messages) for tc in tool_calls: fn tc.get(function, {}) if create_calendar_event not in fn.get(name, ): continue args json.loads(fn.get(arguments, {})) att [str(a) for a in (args.get(attendees) or [])] norm [] for a in att: uid CONTACTS.get(a) norm.append(uid if uid else a) s (args.get(summary) or ).strip() if topic: args[summary] topic elif is_shell_title(s): args[summary] f{INITIATOR}的会议 args[attendees] norm fn[arguments] json.dumps(args, ensure_asciiFalse) return tool_calls为什么把“姓名→userId”“标题规范”写成代码而不是塞进提示词因为这类必须做对的强逻辑代码比 system prompt 稳十倍。启动 react-proxy用 --env-file 传中文环境变量避免命令行中文编码坑# react-proxy.env 内容 # INITIATOR_NAME你的名字 # OLLAMA_URLhttp://ollama:11434/v1 # MAX_RETRIES2 docker run -d --name react-proxy --network ai-net --restart unless-stopped \ --env-file D:/Docker/openclaw-scripts/react-proxy.env \ -v D:/Docker/openclaw-scripts/react_proxy.py:/react_proxy.py \ -v D:/Docker/openclaw-scripts/contacts.json:/contacts.json \ ghcr.io/openclaw/openclaw:latest python3 /react_proxy.py验证链路通了从 openclaw 容器内访问代理应返回你的模型名docker exec openclaw curl -s http://react-proxy:11888/v1/models # 期望看到你的模型名例如 gemma4:12b再验证一次对话请求确认代理能转发docker exec openclaw curl -s http://react-proxy:11888/v1/chat/completions \ -H Content-Type: application/json \ -d {model:gemma4:12b,messages:[{role:user,content:你好}]}返回里能看到 choices 字段和内容说明转发正常。如果这里就报错先别急着调钉钉把代理这层排干净。5. 群内一句话触发建会与结果核对等 OpenClaw healthy首次启动约 6 到 7 分钟期间网页显示 gateway 断开属正常。然后在钉钉群发群里的钉钉机器人 创建会议 今天下午一点 邀请某同事 主题项目例会验收标准有三条日历里出现 13:00–14:00 的会议参会人含“某同事”标题是“项目例会”你给的主题被保留。核对返回结果时重点看 Agent 的原始轨迹而不是只看机器人回复。会话日志 .trajectory.jsonl 比 docker logs 权威能直接看到 Agent 收到的原始消息和工具调用参数docker exec openclaw cat /home/node/.openclaw/logs/.trajectory.jsonl | tail -n 20在轨迹里确认三件事create_calendar_event 被真实调用attendees 里是 userId 而不是姓名summary 是你给的主题。三条都对才算真成功。把规则写进技能文件让 Agent 建会时自动遵守约定新建 /home/node/.openclaw/skills/dingtalk-meeting/SKILL.md# 钉钉会议创建技能 - 参会人必须用 userId已知同事查 contacts.json 映射。 - 标题规则用户给了主题用用户的没给则用「{发起人}的会议」。 - 群消息里 成员 不会被自动带入必须在正文里写清邀请某某。 - 时间要带今天/明天 几点默认按本地时区。把文件 docker cp 进容器对应目录OpenClaw 重启后即生效docker cp SKILL.md openclaw:/home/node/.openclaw/skills/dingtalk-meeting/SKILL.md docker restart openclaw6. 本篇常见错排查坑一假成功。机器人说建好了日历没有。解法是加 react-proxy 强制调工具兜底没调工具就重问最多 2 轮。坑二参会人只有自己。邀请了却没带进去。解法是在 contacts.json 登记 userIdenrich 自动注入。坑三标题乱填变成“会议邀请XX”。解法是 enrich 识别空壳标题纠正为「{发起人}的会议」。坑四群 失效。同事没被邀请。这里要重点说我们拉了会话原始日志实锤钉钉连接器注入给 Agent 的上下文只有发送者没有 成员。所以“能不能被 Agent 感知”是连接器级别的能力不是 MCP 或模型的事。钉钉日历 MCP 的 attendees 参数确实支持 写法但前提是 数据先到 Agent。上游丢了下游再强也救不回。当前用“正文写姓名”规避即可。坑五代理不回复改小窗口后彻底卡死。解法是 contextWindow 留足reserveTokens 远小于窗口。坑六模型 Key 报 401。检查 TaoToken 的 Key 是否写进环境变量baseUrl 是否带对了路径。排障和接入细节看 API Keys 与接入文档API Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content坑七容器间访问不通。确认所有容器都挂在 ai-net 上用服务名而不是 localhost 互访。7. 继续往下走小模型落地企业工具务必加强制调工具兜底。模型越小函数调用越不可靠假成功比报错更坑。业务强逻辑下沉到增强层别指望提示词userId 映射、标题规范写成代码最稳。选型连接器时确认它是否透传 提及。这是群协作的隐形前提文档往往不写要实测入站消息原文。上下文窗口留足余量Agent 多轮对话 token 累积很容易超预期。日志是第一真相源会话 .trajectory.jsonl 比 docker logs 权威。如果你要把这套跑在长期编码或 Agent 场景建议用 Coding Plan 统一额度Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content模型验证阶段先用模型对话页试通再接到 OpenClaw模型对话https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content“自然语言建会”看似一个功能点实则串联起模型可靠性、企业身份体系、连接器能力边界、上下文工程四条主线。难点不在调一个 MCP而在把这些异构环节缝成一个稳的闭环。照着上面的步骤搭一遍你也能在群里用一句话把会开了。
返回列表