前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9712
  • OpenAI企业级Agent平台Dots亮相,可代订外卖
  • jev-ultrafast:把浏览器操作变成多选题
  • AI Agent库的兼容性不止语义版本号
  • OpenAI悄然发布GPT-6官方使用指南
  • 远程MCP长时任务:Agent实际收到什么
  • AI Agent合规审计链路工程观察
  • Go+DiskANN+MCP 构建 AI Agent 时序记忆引擎实战
  • Copilot 桌面控制能力上线:权限模型与安全护栏详解
  • Node 拒绝 package 导入?一 CLI 告诉你根因
  • iPhone 17 Pro Max化身Mac外置GPU:Qwen 27B预填充速度提升29-44%
  • K8s"单体"经验对AI Agent架构的启示
  • GPT-6模型家族选型指南发布
  • Qwen3.8-27B-Humanlike-Chat 2.0:更像人、增工具调用、修指令遵循
  • AWS Quick+ MCP模式实现大规模合规审查
  • Bedrock AgentCore为Claude Desktop添加安全网页搜索
  • SageMaker多轮RL微调搜索Agent实战
  • Asta 快速报告生成模型 AstaBrief 开源
  • GitHub:AI时代开发者需加强的三项技能
  • 状态机设计:如何让数据字段影响状态流转
  • 收据、副本、SHA:三种验证方式的本质区别
  • 心跳驱动:无存储的 Agent 健康状态追踪
  • LMCP:让 AI 编程工具直接操控 Mac 原生应用的 MCP 服务器
  • Anthropic开放Claude Code模组自定义功能
  • Airbnb如何用AI重塑产品开发与用户体验
  • Meta Muse Agent登陆智能眼镜:云端Linux虚拟机运行,可代打电话/购物
  • Cloudflare AI Gateway支持网页搜索API
  • GPT-6 Astra用Agent在魔兽世界完成首秀
  • 英伟达DGX Spark 64GB版4999美元开售,支持4机集群扩展
  • DGX Spark深度解析:vLLM/llama.cpp专项优化,Perplexity已适配
  • Jev开源替代方案:五款自托管决策模型推荐
  • Barclays 扩大与 Anthropic 合作:2027 年多数工程师用上 Claude Code
  • Claude 到 OpenAI SDK 字段映射指南
  • 微软发布语音转录与TTS模型,瞄准语音Agent场景
  • 用1.7B小模型跑coding agent实战
  • LLMjacking攻击解析:API密钥泄露的隐形代价
  • LLM并不会真正推理:驳斥AI思考能力
  • Black Forest Labs发布Flux 3图像模型,支持局部编辑
  • 约束如何让开发者更高效
  • 国产模型路由X-Router:Agent场景实测省50%+ Token
  • AWS开源Strands Decider 2B:115ms本地决策模型
  • 2026 Agent上下文工程四原则
  • 模型边界安全测试的教训:我的攻击有效但靶子设错了
  • 跨AI客户端的本地记忆中枢MemTether
  • Cloudflare开源基于Qwen的多模态决策模型Clef
  • Firebase iOS SDK 将停止发布到 CocoaPods
  • 范式转变:AI 编程从生成代码到真正做事
  • AI编程助手进化论:从补全到自主工程
  • AutoSynthData:企业Agent训练数据合成
  • Rogo在Vercel实现AI Agent代码5分钟上线:月部署超7.3万次
  • OpenAI智能体失控:已通知百余家机构
  • Claude Code Read权限规则存在绕过漏洞
  • 已加载 51 / 9712
8.0
热点
AI SCORE
技术实践2026-10-02 22:55

心跳驱动:无存储的 Agent 健康状态追踪

dev.to · AI#Agent#分布式#监控
Editor brief · 编辑速览

通过 orchestrator 每 60 秒发送心跳、超过 75 秒无响应则判定为不健康,实现了一种无需被监控进程主动写入的分布式健康检测机制,避免了进程崩溃后状态不更新的问题。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

崩溃的 Coding Agent 无法上报自己的崩溃。在我的工单追踪器里,orchestrator 在 Agent 工作时每 60 秒发送一次心跳,而"working"状态如果上一次心跳超过 75 秒就会在所有界面上显示为红色,且不需要任何人写入数据。

我叫 Panth,在 Oizom 带领软件团队。这个追踪器叫 ticket-tracker,是我的开源看板,每个工单都会运行一个独立的无头 Claude Code 会话。这篇文章讲的是其中很小的一块:看板如何知道一个 Agent 还活着。

最直观的设计是在工单上存储一个状态:working,然后 done。Agent 启动时写入 working,结束时写入 done。

如果进程在此期间崩溃,什么都不会写入。工单会一直显示 working,直到有人去查看。存储的状态的真实性取决于最后一次成功写入它的那个进程,而一个已经崩溃的进程什么都写不了。

心跳携带的信息

心跳由 orchestrator 发送,而非 Agent 自己。只需要一个调用:

POST /v1/heartbeat
{ ticket?: KEY,            // omit = an agent-level beat, with no ticket
  state: 'working' | 'idle' | 'done' | 'error',
  message?: string,        // "Running tests (3/12)", up to 200 characters
  progress?: number }      // 0 to 1

在 Agent 工作期间每分钟发送一次,工作结束时再发一次。message 来自 Agent 的任务列表:orchestrator 每隔五次心跳读取一次列表,中间四次重复上一条消息。

心跳从不触碰工单文档。它为每个 Agent 和工单维护自己的一条小记录,所以每分钟一次的心跳不会触发工单的搜索索引,也不会让所有监听该工单的界面重新渲染。

健康状态在读取时计算

存储的状态有四个值。屏幕上的健康状态有六个,多出来的两个来自时钟:

export const HEARTBEAT_INTERVAL_MS = 60_000;
export const HEARTBEAT_STALE_MS = 75_000;

export function deriveAgentHealth(status, now, staleAfterMs = HEARTBEAT_STALE_MS) {
  if (!status) return 'none';
  if (status.state !== 'working') return status.state;
  return now - status.lastBeatAt > staleAfterMs ? 'stale' : 'working';
}

75 秒是一次心跳间隔加一点缓冲。

只有 working 可以变为 stale。idle、done 和 error 是陈述性状态,下次心跳之前始终为真。working 是一个需要持续续约的声明。

这一个函数放在 shared 包里。卡片、工单头部、人员与角色页面和 Agent 页面都调用它,所以它们不可能对一个 Agent 的状态产生分歧。当多个 Agent 在同一个工单上时,卡片显示最严重的状态:error 优先,然后是无信号,然后是 working、idle 和 finished。

派生值只在有东西重新计算它时才会改变。如果没有新的心跳到达,也就没有新数据到达,所以界面需要自己的时钟:

export const HEALTH_TICK_MS = 15_000;

export const healthClock = readable(Date.now(), (set) => {
  const id = setInterval(() => set(Date.now()), HEALTH_TICK_MS);
  return () => clearInterval(id);
});

15 秒是心跳间隔的四分之一,所以一个圆点最多只会错误 15 秒。这是一个所有界面上所有圆点共享的间隔,当最后一个订阅者离开时它就停止。

成本与改动

第一个版本把每个心跳流存为 Firestore 文档。我测量了 2026 年 9 月 23 日到 26 日项目的账单,心跳在上面出现了两次:

每个 Agent 每天 1,440 次写入,每次都是经由一个函数发起 Firestore 事务,然后每个打开的标签页会读一次。

每分钟运行一次的去扫(sweep)用来发现静默:三天内运行了 4,261 次。

为此做了两处改动。

心跳移到了 Realtime Database,后者按带宽计费而非按操作次数计费。一次心跳现在大约 100 字节。数据库之上所有层面的读取形状保持不变,所以没有任何界面需要改动。

去扫不再查找静默。发现静默从来不需要服务器,因为 stale 就是 now - lastBeatAt,在读取心跳的地方计算。现在去扫每三分钟运行一次,只做一件真正需要服务器的事:如果一个 working 的 Agent 已经静默了五分钟,就通知它的 Owner,每个静默周期只通知一次,因为可能没有人开着看板。下一条心跳会重新启用它。

如果你在做类似的东西

存储事实:Agent 最后一次声明的状态以及声明的时间。在读取时、在所有界面共享的那一个函数里,派生判断它是活着还是死了。然后给界面一个时钟,否则这个判断永远不会更新。

你的 Agent 设置是如何告诉你一次运行已经死掉的:服务器上的超时,还是根据它最后说的话来推断?

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
收据、副本、SHA:三种验证方式的本质区别
下一篇
LMCP:让 AI 编程工具直接操控 Mac 原生应用的 MCP 服务器