# 23. Agent Active Heartbeat System — 主动心跳与监控架构 > **版本**: v2.0 (已实现) > **日期**: 2026-03-26 > **状态**: ✅ 已完成 (Agent 级 + 公司级心跳均已上线) > **前置**: Phase 3 记忆架构已完成,OKR 目标大盘已上线 --- ## 一、需求背景与痛点 当前的 LemonBoss 架构中,所有的 Agent(包含管理者、执行者、QA 仲裁者等)都处于**“被动响应”**状态。 即:只有当人类或者其他 Agent 发送一条消息(如 `TaskDispatch` 或直接 Chat),它们才会被唤醒并进行一轮推理和动作执行。 **痛点:** 随着 OKR 系统(Goal Nodes)复杂度的增加,如果一个任务的负责人(Owner)迟迟不推进进度,或者产出质量不达标。在没有外部输入时,系统的主节点(如 `qa-judge` 质量裁判,或者 `master` 主节点)只能一直假死等待,这严重违背了“**自主智能体(Autonomous Agent)**”能在后台 24/7 监控并主动下发指令的设计初衷。 **目标:** 使特定的高级 Agent(如 `qa-judge`)具备内建的相对时间感知能力。通过实现一套主推的“心跳机制(Active Heartbeat)”,使其能每隔 N 分钟自动“苏醒”,根据当前注入体内的 OKR 目标大盘数据,主动进行一次进度巡检、质量总结,并主动向下游 Agent 节点派发反馈任务或催办通知。 --- ## 二、架构设计原理 由于 LLM(如 Claude)本身是无状态、无法自主定时的算法黑盒,我们必须通过 Node.js 后端作为起搏器(Pacemaker)来主动触碰 Agent 的执行核心。 ### 1. 核心流程图 ```mermaid sequenceDiagram participant Cron as Node.js Heartbeat Service participant Goal as OKR / Goals Data participant Agent as qa-judge (Agent) participant Worker as poet (Downstream Agent) loop 每 N 分钟 Cron->>Goal: 获取当前活跃的 OKR 大盘状态 Cron->>Agent: [SYSTEM HEARTBEAT] 唤醒 (无前端UI展示) Note over Agent: 挂载 memory、heartbeat.md 及最新 Goal Context Agent->>Agent: 推理分析 (是否有节点超时/待验收?) alt 需要干预 Agent->>Worker: API调用: TaskDispatch (催促或驳回重做) Agent->>Agent: "已向负责人发送警告" else 一切正常 Agent->>Agent: "保持观察,无需操作" end Agent-->>Cron: 结束本次心跳推理 (保存 session 记录入短期记忆) end ``` ### 2. 参与模块设计 #### (1) 后端起搏器 (`server/services/heartbeat-service.js`) - 系统级别的 `setInterval` 或使用 `node-cron` 定时任务管理器。 - 模块初始化时,读取注册了 `cron.json` 或在 `config.json` 中配置了 `active_heartbeat: true` 的全网 Agent。 - 按设定时间周期(如每 5 分钟、或 15 分钟),发起内部进程级或 HTTP `POST /api/agent/:id/chat` 请求。 - **消息构造**:必须带有特殊的标记,如 `[SYSTEM HEARTBEAT] 这是系统周期心跳。时间:{当前时间}。如果无需采取行动,请只回复[心跳正常];如果发现 OKR 或任务阻塞,请使用你的 dispatch 工具发送跟进动作。` #### (2) Agent 身份与职责声明 (`data/agents/qa-judge/heartbeat.md`) 这部分将作为心跳特供的系统注入层。因为 Agent 被系统唤醒后可能“不知所措”,所以需要在注入时提供明确的**心跳策略**。 - `qa-judge` 的 `heartbeat.md` 应当规定: - 检查当前全局进度是低于预期、正常还是卡点。 - 对于已经标记为 `ready_for_review` 的节点,主动执行抽样检查工具,如果抽样不通过,则主动调度退回给原作者。 - 规定其只有遇到问题才说话,没事的时候必须节约 Token,直接结案。 #### (3) 会话隐藏与静默运行 (隐式聊天机制) 为了不污染用户的主聊天界面: - 心跳触发的 Conversation 应当拥有独特的 ID(如 `heartbeat-177xxxxx`)。 - 在前端 UI(AgentChat.vue)中,如果不特别切换到 heartbeat 专区,应该不展示这类后台巡逻日志,以保持人类界面的干净。 - 但心跳的整个完整推演过程(产生的 session)**必须依然进入现有的 Memory 三层架构**。也就是说,如果 `qa-judge` 在心跳中发出了很多派发任务,这个行为依然会记录进 `short-term/session.md` 里并最终写进日常报表(Daily Report)。 --- ## 三、实现状态 - [x] **1. Heartbeat 后端引擎** - `server/services/heartbeat-service.js` — Agent 级心跳服务(按 config.json 中的 heartbeatInterval 独立配置) - `server/services/company-heartbeat-service.js` — 公司级心跳服务(扫描所有公司,按 company.json 心跳配置唤醒 CEO) - 已适配 multi-tenant 架构,支持 `system/agents/` + `data/{companyId}/agents/` 双路径 - [x] **2. 隐式对话 API** - `agent-chat.js` 支持 `silent: true` 模式,心跳会话不污染前端主界面 - 会话依然经历 Memory 三层架构,记录进 short-term + reflections - [x] **3. Agent 心跳策略** - 每个 Agent 的 `heartbeat.md` 定义专项心跳行为(如 CEO 早间巡检、晚间复盘) - 模板库中 CEO/COO 等模板已包含 heartbeat.md - [x] **4. 前端心跳控制** - `CompanyDashboard.vue` per-agent 心跳开关(启动/停止/配置间隔) - API: `PUT /api/company/:companyId/agents/:agentId/heartbeat` - API: `POST /api/company/:companyId/agents/:agentId/heartbeat/start` - API: `POST /api/company/:companyId/agents/:agentId/heartbeat/stop` - [x] **5. Anti-Loop 制衡** - 借助 Memory 架构,Agent 在心跳前读取最近 session,避免重复催促 --- ## 四、技术优势 1. **"起搏"+"记忆"打造真实自主引擎**:依赖已实现的海马体与短期记忆,Agent 不再是简单的代码循环,而是拥有自己时间轴与经验累积的鲜活生命体。 2. **极低侵入性**:依然可以复用现有的 Claude CLI 通道和 `runClaudeCliSession` 函数,仅仅是多了一个虚拟的"系统定时发信人"。 3. **闭环 OODA loop**:观察(OKR数据注入)- 导向(heartbeat.md规则)- 决策(推理判定)- 行动(ToolDispatch),在此实现完整的智能自主控制闭环。