# Agent-Ops-WeCom-Bridge **Repository Path**: LY115LY/Agent-Ops-WeCom-Bridge ## Basic Information - **Project Name**: Agent-Ops-WeCom-Bridge - **Description**: 基于多平台(企微等)打造的重算力 Agent 控制面(Control Plane)。将 IM 化作“一人公司”驾驶舱,远程调度 Claude Code 等本地 Agent,并可通过 MQTT 联动物理端侧设备。Apache-2.0 开源的人机协同范式。 - **Primary Language**: Python - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: https://github.com/Ly-FirmwareLab/Agent-Ops-WeCom-Bridge - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-30 - **Last Updated**: 2026-11-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Agent-Ops-WeCom-Bridge **为多平台打造的重算力 Agent 控制台与运维网关** 同一份内核已在**飞书**与 **Slack** 上真机打通 —— **平台是入口,不是身份。** > 🔗 **三件套** · [🧠 控制面(本仓)](https://github.com/Ly-Systems-Lab/Agent-Ops-WeCom-Bridge) · [🔌 数据面 · Edge-Hub](https://github.com/Ly-Systems-Lab/Agent-Ops-Edge-Hub) · [🔭 总蓝图 · Architecture](https://github.com/Ly-Systems-Lab/Agent-Ops-Architecture) > > 企业微信(推荐)可作为你的调度台:Claude Code 等重算力 Agent 在这里被指挥、被看见、被拦下 > (流式进度、打断、权限拦截),原生打通 MQTT 还能直接触达物理世界。 > > 它是 **Agent Ops 三件套里的「控制面」**: > > | 仓 | 角色 | 状态 | > |---|---|---| > | **本仓** · [`Agent-Ops-WeCom-Bridge`](https://github.com/Ly-Systems-Lab/Agent-Ops-WeCom-Bridge) | 控制面 · 人 ⇄ Agent | 已公开 | > | [`Agent-Ops-Edge-Hub`](https://github.com/Ly-Systems-Lab/Agent-Ops-Edge-Hub) | 数据面 · Agent ⇄ 物理世界(MQTT / 端侧设备) | 已公开 | > | [`Agent-Ops-Architecture`](https://github.com/Ly-Systems-Lab/Agent-Ops-Architecture) | 总蓝图 · 《协同宣言》与全景架构(只有文档,不含代码) | 已公开 | > > 🔌 **它同时是「联邦式中枢」的插座**:入口可以是企微 / 飞书 / Slack, > 执行面可以是本机 / 设备 / 钉钉 / 飞书 —— 官方能力当插件,本项目只做那层闸门。 > 见下方「**插座与插件**」一节。 ## 🎬 演示 | 看什么 | 视频 | |---|---| | **总览** · 一个群里的多个 Agent(Claude Code / Codex / OpenCode / DSH …),外加一个纯模型答疑位(DeepSeek),跨企微与飞书 | [▶ 观看](https://www.bilibili.com/video/BV1LBW167Epz) | | **交互基准** · 手机上发指令,结果落在 Windows 本地;任务卡片(允许 / 拒绝 / 实时进度 / 上下文余量)与 `/stop` 即刻停止 | [▶ 观看](https://www.bilibili.com/video/BV1nY4w6kEiy) | | **幽灵漫游** · 三平台互相热切换(企微 / 飞书 / Slack)+ 联邦式中枢 | [▶ 观看](https://www.bilibili.com/video/BV1U7WB6mEVD) | | **识图与主动推送** · DSH 与 CC 的对话记录(含它自己整理的企微官方能力表) | [▶ 观看](https://www.bilibili.com/video/BV1MgWo6KEzF) | 🖼️ **[实拍图集 →](https://github.com/Ly-Systems-Lab/Agent-Ops-Architecture/blob/main/docs/showcase/README.md)** · 手机端下指令、Windows 本地干活、Agent 自动修 Bug、读者自己搭的一份 💬 **[真实用户反馈 →](docs/feedback/README.md)** · 真实不定用户提交的“作业” —— 评论区原话 + 他自己的运行截图(含一位自述 **macOS** 上成功的) ## 🧩 一份内核,不同的聊天平台 这里要解决的问题从来不是「企业微信」这四个字,而是: > **人不在电脑前的时候,怎么找到并驱动那台机器上的 Agent。** 企业微信只是跑得最远的那个入口。**同一份内核已经接上了形态很不一样的飞书和 Slack** —— 长连接换成官方 SDK / Socket Mode,消息模型、卡片回调、字节上限、推送频率全都不一样, 而「交互基准」那五条,一条都没改。 | 平台 | 作为入口 | 状态 | |---|---|---| | 企业微信 | ✅ | **参考实现** · 真机验收 + 两次外部 Agent 独立复现 | | 飞书 | ✅ | **真机验收** · 五项交互 + 连续在线 24 小时 + 断网自愈 | | Slack | ✅ | **真机验收** · 24 小时连续运行(进程零重启) | | 钉钉 | — | 官方 `dws` 已覆盖通道层,本项目**只把它当执行面**,不重复造入口 | 👉 想换入口,从 [`platforms/`](platforms/README.md) 开始;想把官方 CLI 当"手"接进来,看 [`interop/`](interop/README.md)。 ## 👻 控制面无状态热漂移:「幽灵漫游」 > **一句话**:换个平台不用换 Agent、不用改配置、不用重装 —— 在聊天里说一句, > 它就从另一扇门进来,**原来那个窗口的进度还在**。 「平台是入口,不是身份」的操作版就是这一条:`/platform wecom` · `/platform feishu` · `/platform slack`。 换的是"从哪扇门进来",不是内核、不是工作区、不是记忆。 🎬 **[三平台互相热切换的完整演示](https://www.bilibili.com/video/BV1U7WB6mEVD)** **实测(2026-11-13,三个平台互切)**:切走再切回,问一句「我刚刚说了什么?」—— 它答的正是切换前那个窗口里的对话。因为会话本来就**不属于平台**,只属于「哪个窗口 + 谁」。 **为什么值得单独说**:入口只是"人能找到 Agent 的那扇门"。门可以换、可以被关上, Agent 不会跟着消失 —— 它也**没有把"自己是谁"押在某一家平台上**。某个入口不可用了 (关停、限流、政策),换一扇门就行,代价是一分钟的重启,不是重做一遍。
展开:它和总蓝图是什么关系(为什么叫"幽灵")
- **数据面**:Agent 可以附着在接入的**端侧设备**上(P4 面板、C3 小电视、具身小车)—— 设备只管执行,不持有智能。 - **控制面**:Agent 可以附着在接入的**任何平台**上 —— 平台只管"找到人",也不持有智能。 - 同一个模式:**附着点决定"从哪儿被找到",但 Agent 不属于任何一个附着点。** - 「任何」是目标(**生态中的生态 · 一切皆插件**);企微 / 飞书 / Slack 是这条路的 **最小闭环验证** —— 三个形态完全不同的入口(自建长连接 / 官方 SDK / Socket Mode)都接上了, **一切皆插件**,这套约定不是围着某一家写的,也不是给某一家开的特例。
> ⚠️ **两条诚实的限制,切换前先看一眼** > > 1. **切换会终止正在跑的任务**(进程要换)。先让它答完,或者先 `/stop`。 > 2. **各平台的窗口是各自独立的会话** —— 这既是"进度不丢"的原因,也是它的边界: > 别指望在企微说的上下文,切到 Slack 还接着用。Agent 的记忆(工作区里的文件、笔记) > 在哪儿都在;**当前这轮对话**只在它自己的窗口里。 > 如果你自己把它们配成了「同一个窗口」,那两次切换之间就是在同一份上下文上来回挪, > **进度漂移的风险依然存在** ⇒ **切换前先记录好自己的进度**。 ## 🌌 The Manifesto | 我们的协同宣言 **在这个模型狂飙的时代,我们拒绝“许愿式”的 AI 幻想。**
展开完整宣言
我们坚信,**AI 时代不是工具的替代,而是智慧的共存。** **我们鼓励勇敢闯入“未至之境”**,别因底层知识的壁垒而不敢迈出第一步;但我们也必须保持工程师的严谨——**绝不不懂装懂,永远敬畏物理世界的客观规律。** 面对浩瀚的复杂术语与专业名词,大模型(军师)可作为我们最好的破壁机; 面对真实的业务逻辑与物理设备,Agent(将领)可作为我们最得力的执行官。 **让人类负责意图、决策与底线,让 AI 负责算力、检索与执行。** 敢用、会用、用好,这就是我们定义下一代人机协同的“基本标准”。 —— 献给所有敢于在 AI 时代重构自身工作流的探索者
## 🎣 这个仓真正想给的:授人以渔,而非死板代码 **代码只是参考实现(reference implementation)。** 换台机器、换个 Agent,下面这套东西照样成立 —— 这才是我们想留给读者的部分。 **五条约定** 1. 💬 **入口是聊天** —— 你在哪,工作台就在哪。不需要公网 IP、不需要服务器。 2. 🎯 **`@` 是路由,人是唯一的调度者** —— Agent 之间不直接通信(防打架、防串通)。 3. 🧠 **一个 Agent = 一个工作区 + 一份记忆 + 一个大脑**,换个窗口进来还是同一个 Agent。 4. 🧩 **能力分层,别重复造轮子** —— 官方已经有的一律用官方的,官方没覆盖的才自己补。 5. 🧾 **每个动作留痕** —— 谁点的、跑了什么、上下文还剩多少,都看得见。 **一个任务从「收到」到「干完」该长什么样**,这就是我们说的**交互基准**: | 环节 | 应有的样子 | |---|---| | 收到 | 先回执,且和正文**共用同一个气泡**(不新开一条"处理中") | | 执行 | 气泡里给**真进度**:第几步、正在读哪个文件 —— 不是定时器编的"已跑 N 秒" | | 打断 | 任何时候都能 `/stop`,而且杀的是**进程树** | | 有副作用 | 危险动作先问「允许 / 拒绝」,**否决权在 hook 自己手里**(不在 harness) | | 收尾 | 结果、拒绝、错误**一律如实回报**;超长才切片,每片等回执 | > ⚠️ **能"直接抄"的只有这一段**:`Windows + Claude Code` 的最小闭环,就是本仓这份代码。 > 换成 macOS、换成 Codex、DeepSeek Harness 或任何能跑命令的 Agent, > **约定照用,接入步骤要照官方教程重走一遍** —— 我们只写了官方没覆盖的入站与交互这一段。 > > 🐧 **Linux 这条也要说清楚**:同一套最小闭环在**树莓派**上同样跑通了(连开机自启), > 只是那边用的是另一套 Agent 实现与系统服务自启,不是本仓的 Windows 脚本。 > 平台相关的那几处(自启、单实例、进程树)按你的系统替换即可 —— > **而且可以直接让 Agent 陪你搭**:把这份约定交给它,它会照着你的系统补。 > > 🍎 **macOS 也有回执了**:一位用户在评论区自述「**mac 大成功**」,并附了自己的运行截图。 > 原话直出 —— 这是**使用者反馈**,不是我们的实测:[真实用户反馈](docs/feedback/README.md)。 > > **换 harness 到底要重写哪几处?** 教程 [§8 的「6 个适配点」表](docs/claude-code-wecom-guide.md) > 把通用契约和运行器适配点分开列了:通用部分照抄,这 6 处按你的 Agent 自己回答。 > > 📄 **已经有人照着接过了**:[外部接入记录](docs/field-reports/README.md) —— > OpenCode、Codex、DeepSeek Harness 三个 Agent 各按同一份文档从零接入, > 附它们自己的评价与踩坑(含原图);其中 DSH 接入之后**又把新版收回去了一次**, > 自己那半边一处没丢(见该页「回灌」一节)。 > > 🧬 **为什么这个仓可以被「取长补短」**:[锚点与增量](docs/anchor-and-delta.md) 讲分发模型 > (为什么要留那条缝、它已经有哪些证据、我们对下游的义务); > 具体怎么吸收一次新版:[升级与取长补短](docs/UPGRADING.md)。 > > 🖼️ **图片总览**:[docs/field-reports/assets/](docs/field-reports/assets/) —— > 各份接入记录的原始截图都在这个目录里,点进去就能看全。 > > 目标很简单:**让更多人照着这套约定,更好、更便捷地人机协同学习、工作等**, > 而不是又多一个“更先进的工具”。
📊 换一个 harness 到底要改多少?(DSH 自己统计的表) ![DSH 统计的改动量](docs/field-reports/assets/dsh-02-changes.jpg) > 「新增代码约 1000 行,改动既有代码 5 处。这个比例就是它帮助多大的直接证据 —— > **换掉一个『大脑』,身体一行没动。**」
## 👥 一个群,几种成员 我们自己的群里现在就是这么用的。下面写的是**角色**,不是某个具体的人: | 成员 | 谁在跑 | 干什么 | |---|---|---| | **你** | 人 | 唯一的路由器,也是唯一的共享上下文 —— `@` 谁谁干活 | | **CC(本项目)** | 你的电脑 | **动手**:读代码、改文件、跑命令,结果回到同一个气泡 | | **官方云端大模型机器人** | 企微官方(**普通模式,免费**) | **答疑**:名词解释、代码讲解、思路讨论 —— 不动手,也不碰你的机器 | | 其它 Agent 终端 | 树莓派 / 另一台电脑 / Codex… | 各自的工作区,各自闭环 | | **端侧设备机器人** | P4 面板 / C3 小电视 | **物理世界**:显示、播放、采集 —— 而且它们也在群里、也能被 `@` | > 关键点:这些机器人**互相看不见对方**(平台只把 `@` 自己的消息推给谁)。 > 所以"一个群里好几个 AI"不会变成"AI 互相打架",也不会背着你串通 —— > 这是**协议层隔离**,不是配置出来的。 ``` 【组织层】企微群 = 入口 / 会议室 / 审计记录 ← 你是唯一的路由器 你 ──@──▶ CC(本机 Claude Code) ← 动手 ──@──▶ 官方云端大模型机器人 ← 答疑(免费) ──@──▶ 其它 Agent 终端(树莓派 / Codex / …) ──@──▶ 设备机器人(P4 面板 / C3 小电视) 【设备层】MQTT / HTTP = 设备总线 Agent ──▶ 端侧设备(它们同时也在群里,可以被 @) ``` **为什么不是一个"全能大管家"**:一个 Agent = 一个「工作区 + 记忆 + 大脑」,跑在某台设备上; 企微群、私聊、直接开终端,默认是**同一个 Agent 的不同窗口**,换个窗口进来接着做,上下文不丢 (把私聊用 `CC_CWD_DM` 指到另一个工作区时,它就变成另一个 Agent 的窗口——这是可选项,见教程 §6.11)。 各 Agent 之间**不能直接通信是故意的**:能互通就会冒出"谁听谁的"和"私下串通"两件事 —— 前者还能用权限压住,后者压不住。不通信,这两件事就都不存在。 ⇒ 于是**人既是唯一的路由器,也是唯一的共享上下文**,层级活在「人的判断 + 群聊 `@`」里。 ## 🚀 快速开始 **接入指南(人 + AI Agent 双读者)见 [`docs/claude-code-wecom-guide.md`](docs/claude-code-wecom-guide.md)** —— 开头那节「开始之前」就是安装,跳过它通常会卡在第一步。 ```bash python -m venv .venv .venv\Scripts\activate # macOS/Linux: source .venv/bin/activate pip install -r requirements.txt # requests + websocket-client + pycryptodome cp .env.example .env # 填 Bot ID/Secret、你自己的 userid、ANTHROPIC_* .venv\Scripts\python.exe -X utf8 app\bridge.py ``` - 依赖只有三个第三方包(`pycryptodome` 只用来解**加密的图片**;不装它文本照常,图片会明确报错)。 其余全是标准库。**Windows 实测**;Linux 树莓派上同一套控制面闭环 也已跑通(自启用的是系统服务,不是本仓脚本);macOS 协议层同样通用,自启需自己换一套 —— 已有用户自述在 macOS 上接入成功([反馈原文](docs/feedback/README.md))。 - **默认是只读档**(`dontAsk`):能问答、能读代码,**不会动你的机器**。 要让 Agent 真干活,显式改 `CC_PERMISSION_MODE` —— 见「[权限](#权限三种形态一个开关)」。 - 可选:让它常驻(登录自启、单实例、看门狗自愈、日志保留 14 天、运行期间不睡眠) ```bash .venv\Scripts\python.exe -X utf8 app\bridge.py --install-autostart # 装(不需要管理员) .venv\Scripts\python.exe -X utf8 app\bridge.py --autostart-status # 看 .venv\Scripts\python.exe -X utf8 app\bridge.py --uninstall-autostart # 卸 ``` **一台机器跑多套桥**(换一个 Agent 就行):各自在 `.env` 里设 `BRIDGE_INSTANCE`(如 `dsh`)。 它**只**改两个系统级名字的后缀 —— 单实例互斥量和计划任务名;留空就等于上游行为。 不设的后果是静默的:第二套**起不来**,而装自启会把第一套的任务**覆盖**掉。 ## 🧰 它现在能做什么 **群聊 + 私聊都通**;流式气泡、模板卡片、审批卡片都已**真机验收**; [`tools/test_phase1.py`](tools/test_phase1.py) 里 339 项检查(含会真调一次模型的那几项)全过 —— 你可以自己复跑。 | 能力 | 说明 | |---|---| | 长连接 | 主动外连 `wss://openws.work.weixin.qq.com`;30s 心跳;断线指数退避(3s→30s,连上即重置) | | 鉴权 | `from.userid` **白名单**是唯一真正的鉴权;群里的 `@` 只是消息路由。**留空即拒绝启动**(fail-closed) | | 群聊 / 私聊 | 群里 `@` 它、私聊直接发;两条路径**各自独立上下文**,默认共用一个 `cwd`,也可用 `CC_CWD_DM` 分开(见教程 §6.11) | | 会话 | 每个 `(会话, 用户)` 一份 session,跨消息续接;`/new` 清上下文 | | 控制指令 | `/status` `/new` `/stop` `/model` `/platform` —— **忙碌时也即时可用**(`/status` 是按钮卡) | | **模型热切换** | 聊天里 `/model` 看列表、`/model <编号\|名字>` 切换、`/model reset` 回默认。**下一条消息生效,不用重启**;切换前先真调一次验证,通过才写进 `data/model.json`;**全局**(群聊 + 私聊一起变)。⚠️ **切到/切离「有自己的工作目录」的模型(例如本地模型)会自动新开会话**(主动设计,见下方第 4 条) | | **平台切换**
「幽灵漫游」 | 聊天里 `/platform` 看当前值、`/platform <平台>` 切换。⚠️ 平台是"进程的形状",所以这是**重启**(约 1~2 分钟不可用)而不是热切换:预检 → 写 `data/platform.json` → 拉起新进程 → 看守(软窗口 25s / 硬上限 120s)→ 才停旧;**起不来自动回滚,并先把没就绪的新进程收掉**。也能用控制目录(`data/control/`,任何 Agent 会写文件就能用)或 `tools/bridgectl.py` 驱动。见本页「幽灵漫游」一节、[联邦式中枢](docs/federation.md) 与教程 §6.12 | | 忙碌语义 | 处理中再发 → 回「忙碌中…本条已忽略」,**丢弃不排队**(防输入轰炸) | | 长回答 | 先整条发;只有被平台 `40058` 拒了才切片(每片等回执,失败会明说哪段没送到) | | **图片** | 发图片给它 → 解出直链、落盘 → 提示模型用**你自己的读图工具**打开(Claude Code 里是 `Read`)。**能不能"看见"取决于所接模型是否支持图像输入**:图存在系统临时目录,下一轮说"刚才那张图"还在。⚠️ 企微的图是**加密**的(AES-256-CBC、**填充块 32 字节**),解密需要 `pycryptodome` | | 上下文余量 | 每条回复尾部 `📊 上下文 x% (m/n)`:分母取 `modelUsage.contextWindow`,分子取**本轮最后一次 assistant 调用的 usage**(不是累计值) | | **真进度** | 气泡显示「正在跑(12s · 第 3 步)+ 当前工具」;**变化才推**,附 60s 兜底心跳 | | **模板卡片** | `/status` = 刷新 / 清空 / 停止。⚠️ 按钮文字**只有 2 个字的余量**:4 个字会被截成「清...」 | | **审批卡片** | `Bash`/`Write`/`Edit` 先发「允许 / 拒绝」,点了才执行;只读直放。**仅全自动档位下有效**;开启后群聊 + 私聊都挂卡,**免不免卡按发消息的人**(`CC_APPROVAL_AUTO_USERS`) | | 常驻 | 登录自启、单实例、看门狗自愈、日志保留 14 天、运行期间不睡眠 | | 企业能力 | 邮件 / 文档 / 表格 / 日程 / 会议 / 待办 / 微盘 / 通讯录 / 读 7 天群历史 —— **由官方 `wecom-cli` 提供**,本仓零代码接入 | | 设备总线 | MQTT / HTTP 控端侧设备 —— **在数据面那个仓**([`Agent-Ops-Edge-Hub`](https://github.com/Ly-Systems-Lab/Agent-Ops-Edge-Hub)),不在本仓库 | | 多 Agent 同群 | 多个机器人同处一群、`@` 谁谁干活、互不串台 —— **形态成立**(已在同一群里用过) | **关于「物理世界」这一半**:端侧设备(C3 小电视、P4 触控面板、具身小车)已经接在同一条设备总线上, 它们**本身就是群成员、可以被 `@`**。接法与实测数据在数据面那个仓的 [企微接入教程](https://github.com/Ly-Systems-Lab/Agent-Ops-Edge-Hub/blob/main/ai-agent-wecom/README.md) 里 —— 那是**架构思路**,不是另一份接入流程。**MQTT 数据层底座已经公开**([`Agent-Ops-Edge-Hub`](https://github.com/Ly-Systems-Lab/Agent-Ops-Edge-Hub)); 两个仓合起来,才是完整的「**人 ⇄ Agent ⇄ 物理世界**」这条路。 > 🎬 **[看实拍:一句话驱动三台端侧设备(36 秒)](https://www.bilibili.com/video/BV18Zx86KEDT/)** —— > C3 小电视 → P4 触控面板 → 具身智能小车,由 Agent 依次执行。 ## 🏛️ 和官方是什么关系:站在官方肩膀上 **先去看官方。** 这一页就是入口:**[企业微信 · AI 开放能力](https://work.weixin.qq.com/nl/index/aicli)** (以下按该页 2026-10-29 的内容整理,**以官方当时的版本为准**;本文不复制、不改写它的教程)。 它当前列出 **6 个 Agent 工具**(WorkBuddy、DeepSeek Harness、MiniMax Code、Kimi Work、Codex、 企业自研智能体)、**11 项核心开放能力**、**CLI 与 MCP 两种调用方式**,FAQ 里还有 **「如何通过长连接模式访问机器人?」**—— 也就是本项目的入口。 ⚠️ 这份名单里**没有 Claude Code**(另有 OpenClaw 这类工具由官方单独提供文档)。 不是官方漏了什么,各家路径本来就不同 —— 我们只是把 **Windows + Claude Code** 这一条的坑写下来。 | | 官方 aicli(`wecom-cli`) | 本项目 | |---|---|---| | 定位 | **Agent 的「手」**:发邮件、建文档、排日程、查通讯录 | **Agent 的「耳朵和嘴」**:收实时消息、把结果回到同一个气泡 | | 入站 | ✅ 有,但是**轮询**:以**授权真人**身份拉最近 **7 天**的会话历史 | ✅ **事件驱动**:长连接回调,机器人只看得见 **@ 自己**的 | | 出站 | 11 项核心能力(`wecom-cli schema list` 实测列出 **15 个服务**) | 回复同一个气泡(流式)+ 模板卡片(按钮可点) | | 身份 | 你本人(能看到你这个人能看到的) | 机器人(只看得到 @ 它的) | | 需要什么 | 装 CLI + `auth init` 授权 | 一个 Bot ID / Secret | | 能否同时用 | ✅ 可以,而且**建议一起用** | ✅ 可以 | **两者是叠加关系,不是替代关系。** 官方补的是"Agent 会使用企微的业务能力";本项目补的是 "**人不在电脑前的时候,怎么找到并驱动那个 Agent**"—— 官方入口是命令行 / API 调用, **没有常驻监听**;要"手机发一句话、电脑里的 Agent 立刻收到并回话",得有人把长连接一直维持着。 > 我们不说"官方不行"。官方把地基、协议、教程都做好了, > **这个项目只是在它没走到的地方,多修了一小段路。** ⚠️ **装了官方 CLI 也不等于能用**:默认档位 `dontAsk` 下模型跑不了 `Bash(wecom-cli:*)` (实测 `--allowedTools` 也放不进来,2026-10-29)。要用企业能力,得开全自动或「逐次询问」。 ## 🔌 插座与插件:一个 Agent,多个入口,多个执行面 **入口**负责"人跟 Agent 说话",**执行面**负责"事情真正落地"。两者不必是同一家公司。 ```text 在企微说一句话 → Agent 判断该用哪只手 → 到钉钉查待办 / 到飞书改文档 / 在本机改代码 ↓ 结果回到企微同一个气泡 ``` **官方能力是插件,我们是插座。** `dws`(钉钉)、`lark-cli`(飞书)、`wecom-cli`(企微) 已经把"给 Agent 用的结构化命令 + Skills"做完了 —— 我们**直接引用,不包装、不复刻**; 本项目只补它们没有的那一层:**审批闸门、身份边界、会话与模型的路由**。 | 我们要保证的 | 落在哪 | |---|---| | 接得进来 | Skills 装到 `~/.claude/skills/`,一次安装,所有入口通用 | | 看得见 | 审批卡写清「平台 / 目标 / 动作 / 以谁的身份」 | | 拦得住 | 策略表外按写处理;跨平台写操作**默认全部弹卡** | | 换得掉 | 内核不认识任何平台 —— 换执行面不改代码 | 接入方法、四个平台的差异、每一步的验收判据:[**`interop/`**](interop/README.md); 为什么这么设计:[**联邦式中枢**](docs/federation.md)。
展开:为什么不是「再写一条钉钉通道」,也不是「包成 MCP Server」
- **再写一条通道**:官方 `dws dev connect` 已经覆盖"群 @ → 本机 AI"(多轮、`/new`、白名单、限流)。 再写一遍,收益只剩"工具级审批 + 聊天里切模型"两项,维护成本却要自己扛。 - **包成 MCP Server**:多一层进程、多一套协议。官方 CLI 本身就是结构化命令 + `SKILL.md`, Agent 会 Bash 就能用 —— 包装只会让我们替官方背升级。 - **直接用官方 CLI**:零适配层,升级跟着官方走,坏了拆掉即可。 ⚠️ **身份要说清楚**:`dws` / `lark-cli` 用的是**你本人的 OAuth**。 Agent 在钉钉里发的一条消息,**同事看到的是你发的,不是机器人**。 这是"借力"的代价,也是它的价值 —— 所以写操作上,闸门必须做实。
## 🔐 权限:三种形态,一个开关 **怎么切换:改 `.env`,然后重启桥。** 聊天里**没有**切换指令 —— `/status` 卡片上的「档位」一行只负责**显示**,三个按钮(刷新 / 清空 / 停止)里没有切换。 这是有意的:档位是"这台机器交给谁"的边界,不该能被聊天里的任何一句话改掉。 | 形态 | 配置 | 实际效果 | |---|---|---| | **只读**(默认) | `CC_PERMISSION_MODE=dontAsk` | 能问答、能读代码;**执行命令 / 写文件一律被拒**,拒绝原因如实回到聊天里 | | **全自动** | `CC_PERMISSION_MODE=bypassPermissions` | 模型直接在你机器上执行命令、改文件,不弹任何确认 | | **逐次询问** | `bypassPermissions` + `CC_APPROVAL=1` | 有副作用的调用(`Bash`/`Write`/`Edit`/`WebFetch`)先发「允许 / 拒绝」卡;只读工具(`Read`/`Grep`/`Glob`/`TodoWrite`)直放 | **谁要弹卡,按发消息的人分**:审批一旦开启(`CC_APPROVAL=1`),群聊和私聊都会走闸门; 列进 `CC_APPROVAL_AUTO_USERS` 的 userid 全自动,其余人一律弹卡。 留空 = 谁都要卡。旧开关 `CC_APPROVAL_DM`(私聊全自动)已废弃。 工作区也可以分开(`CC_CWD` / `CC_CWD_DM`)—— 完整教程见 [§6.11](docs/claude-code-wecom-guide.md)。 三条必须知道的事实(都是实测,细节见教程 [§3.5](docs/claude-code-wecom-guide.md) / [§6.10](docs/claude-code-wecom-guide.md)): 1. **「逐次询问」不是第四个档位**,它是全自动档位**之上**加的一道闸。`--permission-mode` 只有 `acceptEdits / auto / bypassPermissions / manual / dontAsk / plan` 六个合法值(**没有 `default`**)。 2. 🚨 **审批卡片不替代 `dontAsk`**:PreToolUse hook **不能越过权限档位** —— `dontAsk` 下 就算你点了「允许」,命令照样不执行。它是"已经决定全自动之后"的第二道闸,不是"让全自动变安全"的东西。 3. **改配置要重启 —— 但模型例外**:`.env` 只在进程启动时读一次,运行期不会重读 ⇒ 改了不重启 = 没改(常驻实例按 PID 停掉再拉起,或等任务计划程序的下一次兜底; 桥是登录自启的,直接重启电脑同样生效)。 **换 API key / 服务商 / 工作区属于这一类** —— 改完 `ANTHROPIC_*` 必须重启桥。 **模型不用重启**:它是运行时状态,聊天里 `/model` 改完下一条消息就生效(见下)。 > 想确认**当前真的在跑哪一档**:聊天里发 `/status`,卡片「档位」一行就是实际生效的那个值。 **模型(本地 / 云端)怎么切**(不用碰 `.env`,也不用重启)—— 展开看用法与设计选择:
展开:/model 用法与四条设计选择
``` /model 列出候选 + 当前值 /model 2 按编号切 /model glm-5.2 按名字切(任意名字都行,会先验证) /model reset 回到 .env 里 CC_MODEL 的默认值 ``` 四条设计选择,都是有意的: - **切换前先真调一次**。端点不提供模型枚举(实测 `GET /v1/models` 回 `404`), 名字对不对只有调一次才知道 ⇒ 探测通过才写进 `data/model.json`, 错的模型**永远进不了真源**。失败的原文会压成一句人能读的话。 - **模型是全局的**,群聊和私聊一起变;**正在跑的任务不受影响**(它启动时就定了)。 - **真源坏了不会哑**:`data/model.json` 读不出来 ⇒ 报警并用 `last_good`; 整份文件坏 ⇒ 退到 `.env` 的 `CC_MODEL`(两个文件不会一起坏);都不行才不传 `--model`。 - ⚠️ **切到「有自己的工作目录」的模型会自动新开会话 —— 这是主动设计,不是会话丢了。** 不同模型的上下文窗口能差一个数量级(本地 9B 只有 32K,云端是 1M), 把旧会话硬续上去会直接撑爆;而且撑爆是**静默**的:模型突然不会用工具了,不报错。 所以换工作目录 = 新开会话,**下一条消息就稳稳落在新模型上**。 **本地与云端模型切换:新开会话,上下文不互通。** 切换前请确认没有正在进行的工作。 **云端模型之间互切(同一个工作目录)不新开会话**,上下文照常延续,方便接着干活。
## 🛡️ 安全边界 - `from.userid` **白名单**是唯一真正的鉴权;群里 `@` 只是消息路由。 **留空 ⇒ 拒绝启动**;要开放全部必须显式 `WECOM_ALLOW_ANYONE=1`。 - 想要全自动就把 `CC_PERMISSION_MODE` 改成 `bypassPermissions` —— 那是**一次有意识的选择**。 ⚠️ 别以为 `acceptEdits` 更安全:实测在 headless 下它**照样执行 Bash**,与全自动无区别。 - **审批整体默认关(`CC_APPROVAL=0`)**;一旦开启(`CC_APPROVAL=1`),群聊 + 私聊都走闸门、**谁能免卡按发消息的人**(`CC_APPROVAL_AUTO_USERS`),而且**不替代 `dontAsk`**。它的否决权握在 [`tools/approval_hook.py`](tools/approval_hook.py) 自己手里:harness 超时/崩溃一律**放行**, 所以 hook 自己 120 秒到点主动拒绝,harness 的 300 秒只是兜底。 开了它但**自检不过就拒绝启动**(不再静默降级成全自动)—— 自检查两件事:Claude 真的会加载 这个 hook(`settings.json` 注册 + `--setting-sources` 含 `project`),以及 hook 脚本真的跑得起来。 群聊 / 私聊用不同工作区时,**每个会挂卡的工作区各查一遍**,任一不过就拒绝启动。 - **凭证不进代码、不进文档、不进日志**:`bot_secret`、`ANTHROPIC_AUTH_TOKEN` 只从 `.env` 读, 日志里最多出现键名和长度,不出现值。 - **但运行日志**会**记 `userid` / `chatid`,以及消息正文的前 80 个字符** —— 排查"谁发的、 为什么被拒"离不开它。这些日志只写本机 `logs/bridge-YYYYMMDD.log`(已 gitignore、保留 14 天、 不外发);要把日志贴给别人,请先自己脱敏。 - `permission_denials` 与 `is_error` **一律回报**,不许假装成功。 - 杀进程要杀**进程树**(`taskkill /PID /T /F`),并且**看结果** —— 没确认退出就不能说"已清理"。 - 本项目涉及本地算力调度与物理硬件控制,**请务必在人类监督下使用**。因 AI 幻觉或网络延迟导致的设备损坏或数据泄露,**概不负责**。 ## 📚 继续往下读 | 想知道什么 | 去哪 | |---|---| | **从零安装、建机器人、填 `.env`、首次自检** | [`docs/`](docs/claude-code-wecom-guide.md) 开头「开始之前」+ §2 | | Claude Code 侧的**实测事实**(`is_error`、`stream-json`、权限档位矩阵…) | [`docs/`](docs/claude-code-wecom-guide.md) §3 | | 企微长连接的**真实协议形状**(字段、三条回复通道、20480 上限) | [`docs/`](docs/claude-code-wecom-guide.md) §4 | | **必须自己实现的 10 个机制**(每条附"不这么做会怎样") | [`docs/`](docs/claude-code-wecom-guide.md) §6 | | 让**另一个 AI Agent** 照着实现 | [`docs/`](docs/claude-code-wecom-guide.md) §8(自包含契约,可整段丢给它) | | **换一个聊天平台**(飞书 / 钉钉 / Slack) | [`platforms/`](platforms/README.md):同一套约定,四个平台各答一遍 | | **把官方 CLI 接进来当执行面**(钉钉 `dws` / 飞书 `lark-cli`) | [`interop/`](interop/README.md):四个平台的差异 + 接入六步 + 验收判据 | | **在它上面改出自己的版本,之后怎么跟进上游** | [`docs/UPGRADING.md`](docs/UPGRADING.md):哈希树对比 → 只看删除行 → 整份替换 vs 定点合并 → 验证 → 回归 | | **这套「锚点 + 增量」的分发模型本身**(为什么、证据、我们对下游的义务) | [`docs/anchor-and-delta.md`](docs/anchor-and-delta.md) | | **验收清单** / 发布前红线 | [`docs/`](docs/claude-code-wecom-guide.md) §9 / §10 | | 代码在哪 | 见下表「目录」 | ## 📁 目录 | 路径 | 内容 | |---|---| | [`app/bridge.py`](app/bridge.py) | 桥本体(单文件) | | [`tools/approval_hook.py`](tools/approval_hook.py) | 审批卡片的 `PreToolUse` hook(独立进程,**否决权在这里**) | | [`tools/verify_headless.py`](tools/verify_headless.py) | 首次自检①:依赖 + 认证 + headless 行为矩阵(会真调一次模型) | | [`tools/env_from_settings.py`](tools/env_from_settings.py) | 把 `~/.claude/settings.json` 里 `ANTHROPIC*` 搬到 `.env`(只打键名和长度,不回显 token) | | [`tools/test_phase1.py`](tools/test_phase1.py) | 单元测试(`--skip-llm` 只跑离线部分) | | [`.claude/settings.json`](.claude/settings.json) | 注册 `approval_hook.py`;`CC_APPROVAL=0` 时它是空壳 | | [`docs/`](docs/claude-code-wecom-guide.md) | 接入教程(人 + AI Agent 双读者);[锚点与增量](docs/anchor-and-delta.md) / [升级](docs/UPGRADING.md) / [联邦式中枢](docs/federation.md) | | [`platforms/`](platforms/README.md) | 平台适配:契约 + 企业微信 / 飞书 / 钉钉 / Slack 各自的答案 | | [`interop/`](interop/README.md) | 生态互联:官方 CLI 怎么当执行面接进来,四个平台差在哪 | | [`LICENSE`](LICENSE) [`NOTICE`](NOTICE) | Apache-2.0 全文与版权声明(都在仓库根目录) | | `logs/` `data/` `.env` | 运行产物与凭证,**不入库** | > 开发侧的探针脚本(`probe_permission_modes.py` / `probe_hooks.py` 等)与台账(`notes/`) > **不随公开仓发布** —— 它们是给我们自己复现结论用的,带着本机路径和实验痕迹。 ## 🤝 贡献与支持 欢迎提交 Issue 或 PR。如果你觉得这个架构对你有启发,请点个 Star ⭐! ## 📜 许可 **Apache License 2.0** —— 全文见 [`LICENSE`](LICENSE),版权声明见 [`NOTICE`](NOTICE)。 我们坚信开源与共享的力量。在遵守许可证条款的前提下,你可以自由地使用、修改、分发本项目(包括商业用途),甚至将其闭源集成到你的商业产品中。我们唯一的期望是:**保留原作者的版权声明(NOTICE 文件)。** **开源不仅是给人看,更是给 AI 学习。我们希望这套架构理念能成为未来人机协同的基石。**