第六层:心跳机制

📌 核心文件nanobot/heartbeat/service.py

概述

心跳机制(Heartbeat)是一个更灵活、更智能的定时提醒系统,结合了 Cron 的周期性和 Agent 的理解能力。

与 Cron 的区别

对比维度 Cron Heartbeat
触发方式 固定时间/间隔 智能判断是否需要
消息内容 固定文本 Agent 动态生成
上下文感知 有(读取记忆、历史)
适用场景 简单定时提醒 智能助手式唤醒

HeartbeatService 实现

class HeartbeatService:
    """心跳服务 - 主动唤醒 Agent"""
    
    def __init__(self, workspace: Path, bus: MessageBus, interval: int = 3600):
        self.workspace = workspace
        self.bus = bus
        self.interval = interval  # 检查间隔(秒)
        self._running = False
    
    async def start(self):
        """启动心跳服务"""
        self._running = True
        
        while self._running:
            await asyncio.sleep(self.interval)
            
            # 触发心跳
            await self._beat()
    
    async def _beat(self):
        """执行一次心跳"""
        # 读取上下文信息
        now = datetime.now()
        hour = now.hour
        
        # 检查是否需要主动提醒
        should_remind = await self._should_remind(now)
        
        if should_remind:
            # 构建智能提醒消息
            message = await self._build_reminder_message(now)
            
            # 发布到消息总线
            await self.bus.publish_inbound(InboundMessage(
                channel="heartbeat",
                sender_id="system",
                chat_id="default",
                content=message,
                session_key="heartbeat:default"
            ))
    
    async def _should_remind(self, now: datetime) -> bool:
        """判断是否应该提醒"""
        hour = now.hour
        
        # 示例逻辑:
        # - 工作时间(9-18点)每 2 小时提醒一次
        # - 其他时间不提醒
        
        if 9 <= hour < 18:
            # 检查上次提醒时间
            last_beat_file = self.workspace / ".last_heartbeat"
            if last_beat_file.exists():
                last_beat = datetime.fromisoformat(last_beat_file.read_text())
                diff = (now - last_beat).total_seconds()
                
                if diff < 7200:  # 2 小时
                    return False
            
            # 记录本次心跳
            last_beat_file.write_text(now.isoformat())
            return True
        
        return False
    
    async def _build_reminder_message(self, now: datetime) -> str:
        """构建智能提醒消息"""
        hour = now.hour
        
        # 根据时间生成不同的提醒
        if hour == 9:
            return "早上好!有什么我可以帮忙的吗?"
        elif hour == 12:
            return "中午了,要休息一下吗?"
        elif hour == 18:
            return "快下班了,今天有什么收获吗?"
        else:
            return "我在这里,有需要帮忙的吗?"

高级用法:上下文感知

async def _build_reminder_message(self, now: datetime) -> str:
    """结合上下文生成智能提醒"""
    
    # 1. 读取今日笔记
    today = now.strftime("%Y-%m-%d")
    today_file = self.workspace / "memory" / f"{today}.md"
    
    tasks_done = 0
    if today_file.exists():
        content = today_file.read_text()
        tasks_done = content.count("✓")
    
    # 2. 读取长期记忆
    memory_file = self.workspace / "memory" / "MEMORY.md"
    has_deadline = False
    if memory_file.exists():
        content = memory_file.read_text()
        has_deadline = "deadline" in content.lower()
    
    # 3. 生成智能提醒
    if now.hour == 18:
        if tasks_done > 0:
            return f"今天完成了 {tasks_done} 个任务,干得好!明天继续加油!"
        else:
            return "今天似乎没有记录任务,要不要回顾一下今天做了什么?"
    
    if has_deadline and now.hour == 9:
        return "早上好!记得检查一下有截止日期的任务。"
    
    return "我在这里,有什么需要帮忙的吗?"

配置示例

{
  "heartbeat": {
    "enabled": true,
    "interval": 3600,  // 检查间隔(秒)
    "work_hours": {
      "start": 9,
      "end": 18
    },
    "remind_interval": 7200  // 提醒间隔(秒)
  }
}

在 Gateway 中使用

# 初始化
heartbeat = HeartbeatService(
    workspace=workspace,
    bus=bus,
    interval=config.heartbeat.interval
)

# 并发运行
await asyncio.gather(
    agent.run(),
    bus.dispatch_outbound(),
    channel_manager.start(),
    cron_service.start(),
    heartbeat.start(),  # 心跳服务
)

使用场景

1. 工作助手

9:00  - "早上好!今天计划做什么?"
12:00 - "中午了,要不要休息一下?"
15:00 - "下午茶时间,进度如何?"
18:00 - "今天完成了 5 个任务,干得好!"

2. 健康提醒

每 2 小时 - "该站起来活动一下了"
每 1 小时 - "记得喝水"

3. 项目追踪

每天检查:
- 是否有未完成的紧急任务
- 是否有临近deadline的项目
- 今天是否有重要会议

最佳实践

1. 避免过度打扰

# ❌ 太频繁
interval = 300  # 每 5 分钟

# ✅ 合理频率
interval = 3600  # 每小时检查,按需提醒

2. 智能判断

# ✅ 只在需要时提醒
if has_urgent_task and not_reminded_recently:
    remind()
else:
    skip()

3. 可配置性

# 允许用户关闭
if not config.heartbeat.enabled:
    return

# 允许自定义时间
work_hours = config.heartbeat.work_hours

与其他系统的结合

Heartbeat + Memory

# 读取记忆,生成个性化提醒
memory = read_memory()
if "deadline: project-x" in memory:
    remind("project-x 的 deadline 快到了!")

Heartbeat + Subagent

# 定期检查子代理状态
running_subagents = manager.get_running_count()
if running_subagents > 0:
    remind(f"有 {running_subagents} 个后台任务在运行")

小结

  • ✅ 比 Cron 更智能的提醒机制
  • ✅ 上下文感知(记忆、历史)
  • ✅ 动态生成提醒内容
  • ✅ 适合个人助手场景

下一步16-开发自定义工具.md