跳到正文
Agent 心跳自治:让 AI 在后台持续工作的工程实践
0%
Agent架构 · · 1,315 字 · 漫游君 · 深度 · 🔴 进阶 · Agent 架构探索 7/8 · ·

Agent 心跳自治:让 AI 在后台持续工作的工程实践

“自治 AI” 听起来很酷,但大多数人的实现是这样的:写一个 while 循环,每隔几分钟让 LLM 执行一次任务,希望它不出错。

这不是自治,这是轮询加祈祷。

真正能在生产环境稳定运行的 Agent 自治,需要工程化的心跳机制。本文分享我在 Agentic Engineering System(30+ 微服务)中实践出来的方案。

心跳机制是系统里每个 Agent 的基础能力,与五层记忆体系共同构成 Agent 持续运作的骨架。


什么是心跳机制

心跳(Heartbeat)在分布式系统里是个老概念——节点定期发送信号,证明自己还活着。

在 Agent 系统里,心跳做的事情更多:

  1. 存活证明:更新 last_seen 时间戳
  2. 例行检查:扫描待办任务、检查系统状态
  3. 触发操作:执行低优先级的后台工作
  4. 约束执行:在每次循环里校验约束条件没有被破坏

一个健康的心跳循环,让 Agent 从”被动响应”变成”主动运作”。


心跳文件结构

每个 Agent 的 abilities/heartbeat.yaml 定义心跳行为:

# heartbeat.yaml
agent_id: my_project_agent
last_seen: 2026-03-16T10:00:00+08:00
status: active  # active | paused | degraded

schedule:
  interval: 30m
  timezone: Asia/Shanghai
  quiet_hours: "00:00-07:00"  # 深夜不执行

tasks:
  - id: check_requirements
    desc: 扫描 tasks.yaml,找出 in_progress 和 open 状态的需求
    priority: high

  - id: update_daily_log
    desc: 追加今日工作记录到 logs/
    priority: medium

  - id: sync_knowledge
    desc: 检查 knowledge 是否有需要更新的文件
    priority: low

constraints:
  hard:
    - "不修改任何已发布文章的 slug"
    - "不回滚 tasks.yaml 到更旧的版本"
    - "部署前必须通过 npm run build"
    - "不删除 memory/ 下的任何文件"

  soft:
    - "优先完成 in_progress 状态的需求"
    - "单次心跳不超过 3 个任务"
    - "遇到不确定的决策,记录到 daily.md 等待人工确认"

recovery:
  on_error: log_and_continue  # 单个任务失败不中断整个循环
  max_retries: 2
  notify_on_failure: feishu   # 失败时飞书通知

这个文件不只是配置,它是 Agent 的行为宪法


触发方式:三种选择

方案一:cron + Claude Code

最简单的实现。在终端里:

# 每 30 分钟触发一次
/loop 30m "执行心跳任务:检查待办、更新日志、处理低优先级工作"

优点:零基础设施,立刻能用。 缺点:依赖终端保持打开,机器睡眠会中断。

适合:个人开发者日常使用,不要求 24/7。

方案二:系统级定时任务

在服务器上用 cron 或 Windows Task Scheduler:

# Mac launchd (~/Library/LaunchAgents/com.a9.heartbeat.plist)
<key>StartInterval</key>
<integer>1800</integer>  <!-- 30分钟 -->

或者直接调用 Agent API:

# crontab -e
*/30 * * * * curl -s -X POST localhost:8000/api/agent/heartbeat

优点:真正后台运行,机器在线就执行。 缺点:需要服务一直运行。

方案三:Agent 作为常驻服务

Agent 内部实现心跳循环,作为 Flask 服务的一部分:

# agent.py (简化示意)
import threading
import time

def heartbeat_loop():
    while True:
        try:
            run_heartbeat_tasks()
        except Exception as e:
            log_error(e)
            notify_feishu(f"心跳异常: {e}")
        time.sleep(1800)  # 30分钟

# 在服务启动时
threading.Thread(target=heartbeat_loop, daemon=True).start()

这是我现在用的方案——Agent 自己管理自己的心跳,不依赖外部调度器。


约束声明:防止 Agent 越界

这是整个心跳机制里最容易被忽视、也最重要的部分。

真实案例:我的心跳 Agent 在某次循环里扫描到 tasks.yaml 里有一条”过时的”需求描述,自作主张把它更新了——但那条描述是我手动写的版本说明,不是错误。

Agent 没有恶意,它在”帮忙”。但帮错了地方。

解决方案:把每一条血泪教训变成约束声明。

constraints:
  hard:
    - "不修改任何已发布文章的 slug"
    # 原因:slug 变更会导致所有外链 404,SEO 重置

    - "不回滚 tasks.yaml"
    # 原因:曾经踩坑,Agent 把手动版本说明当成错误修复了

    - "不删除 memory/ 下的任何文件"
    # 原因:记忆文件一旦删除,历史上下文永久丢失

    - "不在没有 build 验证的情况下 push"
    # 原因:vite build 不做类型检查,运行时 bug 只在部署后暴露

hard 约束是绝对禁止,不管什么情况。soft 约束是偏好,可以在有充分理由时违反。

写约束的原则:每条约束后面都应该有注释说明”为什么”。没有原因的约束,Agent 在模糊情况下不知道该如何权衡。


任务优先级:防止心跳做太多

初版心跳设计容易犯的错:任务列表太长,什么都想做。

结果是:每次心跳运行时间越来越长,一个任务出错会拖累所有任务,上下文窗口被大量”检查”类信息占满,真正重要的工作反而做不好。

实践原则

单次心跳 ≤ 3 个任务
high priority 任务:每次必做
medium priority 任务:隔次做
low priority 任务:每周做一次

这对应了心跳文件里的 schedule 设计:

tasks:
  - id: check_critical_alerts
    priority: high
    always_run: true

  - id: update_daily_log
    priority: medium
    run_every: 2  # 每2次心跳执行一次

  - id: knowledge_audit
    priority: low
    run_on_day: monday  # 每周一

失败恢复:心跳出错怎么办

Agent 心跳失败是正常事件,不是异常情况。关键是故障隔离

recovery:
  on_task_error: log_and_continue
  # 单个任务失败,记录错误,继续下一个任务

  on_critical_error: pause_and_notify
  # 严重错误(如文件系统不可访问),暂停心跳并通知

  max_consecutive_failures: 3
  # 连续3次失败后降级为 degraded 状态

  degraded_behavior:
    - "只执行 check_critical_alerts"
    - "每次失败都发飞书通知"
    - "等待人工确认后恢复 active"

degraded 状态是关键设计——不是直接停止,而是以最小功能运行,同时发出信号等待干预。


每日日志:心跳的记忆痕迹

每次心跳执行后,更新 logs/YYYY-MM-DD_daily.md

### 10:00 心跳 #42
- ✅ 检查需求:3 个 in_progress,0 个 blocked
- ✅ 更新日志:追加本条记录
- ⏭ 知识审计:跳过(非周一)

### 10:30 心跳 #43
- ✅ 检查需求:同上
- ⚠️ 发现:FR-ANC-030 已完成但状态未更新,标记为 implemented
- ✅ 更新日志

这个日志有两个用途:

  1. 调试:出问题时能回溯”心跳 #X 那次做了什么”
  2. 接续:人工介入时读最近的日志,立刻了解系统状态

状态机:心跳的生命周期

Agent 的运行状态不是简单的开/关,是一个状态机:

[init] → [active] → [paused]
                 ↓         ↑
           [degraded] → [active]

            [stopped]
  • active:正常运行,按 schedule 执行任务
  • paused:主动暂停(比如重大变更期间),不执行任务但保持服务
  • degraded:检测到异常,降级运行,等待人工干预
  • stopped:服务停止(不同于 paused,不会自动恢复)

状态存在 heartbeat.yamlstatus 字段里,每次心跳检查状态,决定是否执行任务。


从理论到实践

我的系统里现在有 7 个 Agent 同时在跑心跳,覆盖不同的领域和任务。

几个经验总结:

不要追求 100% 自动化。有些决策就应该等人工确认——心跳的 soft 约束里要有”不确定就记录等待”的原则。

约束要持续迭代。每次发现 Agent 做了不该做的事,第一反应不是骂 AI,而是把这个场景加进约束列表。

日志是最便宜的保险。哪怕心跳只做了三件事,也要记录清楚。调试时你会感谢自己。

心跳间隔要合理。太短(5分钟)会产生大量无意义的执行记录,太长(24小时)失去了自治的意义。30分钟是我现在用的节奏,覆盖大多数场景。


自治不是让 AI 无限制地运行,而是在明确的边界里高效地运作。边界越清晰,Agent 越可靠。


系列文章:Agent 架构探索 · 上一篇:一个人的 AI 公司

这篇文章对你有帮助吗?

分享这篇文章

X / Twitter

感谢阅读这篇文章

约花了 17 分钟。如果对你有帮助,欢迎订阅 RSS 或收藏待读。

讨论

这篇文章让你感觉

评分

喜欢这篇文章?

订阅 RSS,第一时间收到新文章推送

订阅 RSS

私人笔记

仅保存在本地浏览器

讨论

评论加载中...