第 33 章 · Background Agents

一个不该占着人的活

还是那个卖家。他手下有个跨境运营,每天上班第一件事,是打开五个竞品的亚马逊页面,抄下价格、Buy Box、库存状态,填进一张表,看看昨晚有没有异动。半小时,日复一日,纯体力活。

他找过来问:“这事能不能让 Agent 干?但我不想每天早上还得亲自去点一下让它跑。”

这就点到了要害。前面二十九章,我们的 Agent 大多是交互式(interactive)的——你发一句,它答一句,你盯着看。可这位运营的需求不一样:没人盯着、按时自己跑、跑完把结果送到我面前。半夜扫一遍竞品价、监控数据源有变就分析、CI 里每个 PR 自动审一遍——这些活都该这么干。

这类不依附于交互式会话、在后台自主运行的 Agent,就是 Background Agents(后台智能体)

后台 Agent 要多解决的五件事

后台 Agent 和交互式 Agent 底层是同一套 ReAct 循环,区别全在“没人盯着”逼出来的几个新问题:

  1. 自主运行(autonomous):没有人实时下指令,它得靠预设目标和触发条件自己往下跑(连到第 13 章规划)。
  2. 状态持久(state persistence):跑很久、甚至跨进程重启,状态必须存在外部、随时可恢复(回顾第 12 章会话持久化)。这是后台化最硬的门槛——存不住状态,一崩就前功尽弃。
  3. 触发机制(trigger):怎么启动?定时(cron)、事件(webhook、文件变化)、或队列消息。
  4. 异步通知(async notification):跑完了、或需要人介入时,怎么找到你?Slack、邮件、webhook。
  5. 护栏尤其重要:没人盯着,一旦失控(死循环、烧钱)后果被放大——预算和轮次上限(第 26 章)从“建议”变成“必需”。

把这五件事想清楚,后台 Agent 就不神秘了:它不是一种新的 Agent 逻辑,而是给已有的循环套上“自己会启动、状态存得住、跑完会喊你”的外壳

触发机制:谁按下开始键

交互式 Agent 的“开始键”是人敲回车。后台 Agent 没有人,就得换个东西来按。常见三类:

  • 定时触发(cron):最简单可靠。“每天凌晨 2 点扫一遍竞品价”就是它——固定节奏,适合巡检、日报、周期性对账。
  • 事件触发(event / webhook):外部系统一有动静就拉起 Agent。“竞品页面内容变了”“GitHub 来了个新 PR”“库存低于阈值”——适合需要实时响应的场景。
  • 队列消息(queue):任务扔进队列,后台 Agent 逐个消费。适合耗时任务削峰、失败重试。

选哪种,取决于你的活是“按点做”还是“有事才做”。那位运营的抄价需求,显然是 cron。

用 pi 实现:RPC 远程驱动 + 事件触发

回顾第 24 章:pi 的 RPC + 可寻址会话(addressable session) 让 Agent 能在别处运行、被远程驱动。这正是后台 Agent 的地基——一个后台 Agent,本质就是“一个跑在服务端、由事件而非人来驱动的会话”

把触发器、RPC、通知组合起来,那位运营的抄价机器人大致是这样:

// 概念示意:定时触发 → RPC 远程驱动一个后台会话 → 跑完异步通知
// 1. 触发器:每天凌晨 2 点(cron)
scheduler.cron("0 2 * * *", async () => {
  // 2. 通过 RPC 在服务端拉起/驱动一个会话(第 24 章)
  const session = await pi.rpc.createSession({ cwd: repoPath });

  // 状态持久在服务端:即便中途崩了,会话可按 id 恢复续跑(第 12 章)
  await session.send(
    "打开这 5 个竞品页,抄下价格/Buy Box/库存,和昨天对比,只报有异动的"
  );

  // 3. 跑完异步通知(人不在场,凌晨 2 点没人看屏幕)
  const report = await session.waitForCompletion();
  if (report.hasChanges) {
    await notify.slack("#pricing", report.summary);   // 有异动才打扰人
  }
});

几处呼应前面章节:会话在服务端状态持久,崩了能按 id 恢复(第 12 章);驱动方式是 RPC(第 24 章),运行时本身没变;“有异动才通知”是对异步通知的克制——别让后台 Agent 变成刷屏噪音。

pi 的扩展机制(第 8 章)也能承接后台触发:官方列举的扩展用途里就包括“文件监听、webhook、CI 触发”。而“CI 里自动审查 PR”这类场景,pi 生态还有专门的 pi-chat(Slack / chat 自动化与工作流)可以参考。

交互式 vs 后台:一体两面

值得特别强调的一点:同一个 Agent 运行时,既能交互式用,也能后台跑——区别只在“谁来驱动”。

交互式 Agent后台 Agent
驱动者人,实时对话事件/定时,自主
状态会话在前台状态持久在服务端
反馈同步,你盯着异步,跑完通知
护栏重要更重要(没人盯)

pi 的分层架构(第 23 章)+ RPC(第 24 章)让这“一体两面”成为可能:白天你在终端里和它对话调竞品分析的口径,调好了,晚上就把同一套逻辑挂到 cron 上让它自己跑。运行时不变,换个驱动方式而已。

动手看看

翻 pi 的 RPC 相关代码(packages/coding-agent/src/modes/rpc/),看它是怎么“在别处拉起一个会话、按 id 驱动、拿回结果”的——这就是后台 Agent 的核心动作。

再想一个设计题:如果让你把上面那个抄价机器人做成生产可用的,你会在哪几处加护栏?(提示:给会话设最大轮次和预算上限防它凌晨空转烧钱、给“打开外部页面”这步做隔离、把每次运行的会话都留档以便事后查——分别对应第 25、27、24 章。)

实战中的几个坑

坑一:状态没存外部,一崩就从头来。

  • 现象:后台任务跑到一半进程重启,之前的进度全丢,下次从零开始。
  • 原因:把状态留在内存/前台会话里,没做持久化。
  • 对策:会话状态持久到服务端(第 12 章),支持按 id 恢复续跑。

坑二:没人盯着,失控烧一整晚。

  • 现象:后台 Agent 陷入死循环反复调工具,早上一看账单吓一跳。
  • 原因:没设硬预算和轮次上限——交互式时人能随手喊停,后台没这道保险。
  • 对策:预算 + 轮次上限设成硬刹车(第 26 章),触发即中断并通知。

坑三:通知要么没有,要么刷屏。

  • 现象:跑完没人知道,或者每次都发一大堆,重要信号被淹没。
  • 原因:没设计通知策略,无脑发或干脆不发。
  • 对策:只在“有结果 / 需人介入 / 出错”时通知,日常静默;异动才打扰人。

坑四:高风险决策擅自做主。

  • 现象:后台 Agent 自作主张改了线上配置、发了对外邮件。
  • 原因:没有“暂停等待人确认”的机制,把不可逆操作也交给它自主完成。
  • 对策:高风险步骤设为暂停点,通知人来拍板后再继续;写操作、部署操作务必隔离(第 28 章)。

对比:其他框架

后台 Agent 需要五件事:自主运行、状态持久、触发机制、异步通知、更强护栏。各家框架里,状态持久最能拉开差距——能不能把一次运行的状态存下来、之后由事件继续驱动。

框架Background Agents 怎么做特点
LangGraphcheckpointer 让状态图持久化、中断后恢复甚至分支,Platform 提供部署与定时/异步后台形态最成熟的一档
CrewAI围绕一次团队任务执行,不聚焦长期驻留;后台跑需框架外套调度器+状态存储非后台导向
PydanticAI定位写单次 Agent 逻辑,不内建持久化与触发;后台化靠自己的队列/DB/调度需完全自建后台管道
AgnoAgentOS 运行时 + Memory 承载更长生命周期会话,事件触发/异步通知仍需自搭有运行时,管道半成品
piRPC + 可寻址会话远程驱动,扩展承接文件监听/webhook/CI 触发;交互/后台一体两面同一运行时两种驱动

共性:后台化的关键是状态持久 + 触发,而非新的 Agent 逻辑;差别在于框架把持久化和运行时替你做到了几分。

小结

  1. Background Agents 是“由事件而非人驱动的会话”:不依附交互式对话,在后台自主运行。
  2. 它比交互式 Agent 多解决五件事:自主运行、状态持久、触发机制(cron/webhook/队列)、异步通知、更强护栏——其中状态持久是最硬的门槛。
  3. pi 用 RPC + 可寻址会话远程驱动,扩展机制承接文件监听/webhook/CI 触发;同一运行时交互/后台一体两面,区别只在谁来驱动。
  4. 因无人监督,信任门槛更高:硬预算、隔离执行、完整追踪、高风险决策要能暂停等人。
  5. 通知要克制:只在有结果、需介入、出错时打扰人,别让后台 Agent 变成噪音源。

后台 Agent 让 Agent 无处不在。而无论前台后台,成本都绕不开——下一章讲一个贯穿全书的省钱利器:分层模型策略