第 33 章 · Background Agents
一个不该占着人的活
还是那个卖家。他手下有个跨境运营,每天上班第一件事,是打开五个竞品的亚马逊页面,抄下价格、Buy Box、库存状态,填进一张表,看看昨晚有没有异动。半小时,日复一日,纯体力活。
他找过来问:“这事能不能让 Agent 干?但我不想每天早上还得亲自去点一下让它跑。”
这就点到了要害。前面二十九章,我们的 Agent 大多是交互式(interactive)的——你发一句,它答一句,你盯着看。可这位运营的需求不一样:没人盯着、按时自己跑、跑完把结果送到我面前。半夜扫一遍竞品价、监控数据源有变就分析、CI 里每个 PR 自动审一遍——这些活都该这么干。
这类不依附于交互式会话、在后台自主运行的 Agent,就是 Background Agents(后台智能体)。
后台 Agent 要多解决的五件事
后台 Agent 和交互式 Agent 底层是同一套 ReAct 循环,区别全在“没人盯着”逼出来的几个新问题:
- 自主运行(autonomous):没有人实时下指令,它得靠预设目标和触发条件自己往下跑(连到第 13 章规划)。
- 状态持久(state persistence):跑很久、甚至跨进程重启,状态必须存在外部、随时可恢复(回顾第 12 章会话持久化)。这是后台化最硬的门槛——存不住状态,一崩就前功尽弃。
- 触发机制(trigger):怎么启动?定时(cron)、事件(webhook、文件变化)、或队列消息。
- 异步通知(async notification):跑完了、或需要人介入时,怎么找到你?Slack、邮件、webhook。
- 护栏尤其重要:没人盯着,一旦失控(死循环、烧钱)后果被放大——预算和轮次上限(第 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 怎么做 | 特点 |
|---|---|---|
| LangGraph | checkpointer 让状态图持久化、中断后恢复甚至分支,Platform 提供部署与定时/异步 | 后台形态最成熟的一档 |
| CrewAI | 围绕一次团队任务执行,不聚焦长期驻留;后台跑需框架外套调度器+状态存储 | 非后台导向 |
| PydanticAI | 定位写单次 Agent 逻辑,不内建持久化与触发;后台化靠自己的队列/DB/调度 | 需完全自建后台管道 |
| Agno | AgentOS 运行时 + Memory 承载更长生命周期会话,事件触发/异步通知仍需自搭 | 有运行时,管道半成品 |
| pi | RPC + 可寻址会话远程驱动,扩展承接文件监听/webhook/CI 触发;交互/后台一体两面 | 同一运行时两种驱动 |
共性:后台化的关键是状态持久 + 触发,而非新的 Agent 逻辑;差别在于框架把持久化和运行时替你做到了几分。
小结
- Background Agents 是“由事件而非人驱动的会话”:不依附交互式对话,在后台自主运行。
- 它比交互式 Agent 多解决五件事:自主运行、状态持久、触发机制(cron/webhook/队列)、异步通知、更强护栏——其中状态持久是最硬的门槛。
- pi 用 RPC + 可寻址会话远程驱动,扩展机制承接文件监听/webhook/CI 触发;同一运行时交互/后台一体两面,区别只在谁来驱动。
- 因无人监督,信任门槛更高:硬预算、隔离执行、完整追踪、高风险决策要能暂停等人。
- 通知要克制:只在有结果、需介入、出错时打扰人,别让后台 Agent 变成噪音源。
后台 Agent 让 Agent 无处不在。而无论前台后台,成本都绕不开——下一章讲一个贯穿全书的省钱利器:分层模型策略。