青蛙小白

Agent Automation

Agent Automation 指无人值守、按调度定时运行的后台 Agent 自动化:没有人发消息触发它,而是由 cron 之类的调度周期性唤醒,从一组固定来源(Slack 频道、GitHub 仓库等)读取自上次运行以来的变化,把"你需要知道的事"投递到一个目的地(如一个 Slack 频道)。这个词目前主要来自 Anthropic 的工程语境(其文章《Building Effective Agent Automations》与 Claude Managed Agents 的 daily-brief 参考实现),尚不算完全标准化的行业术语,但对应的实践形态——定时摘要、巡检通知、后台值守——已经在各家托管 Agent 平台普遍出现(参见 Agents API)。

与交互式 Agent 相比,它的根本差异是没人盯着:MCP 工具要权限审批时没人批,来源挂了没人发现,post 失败没人重试,成本失控没人喊停。所以它的工程重点不在模型能力,而在把"读增量、报失败、确认送达、管住花钱"做成确定性规则写进 run steps。

六个组件

Anthropic 的参考实现把一个定时自动化拆成六个组件:

组件内容关键设计
Sources命名的读取来源列表只读;经 MCP 代理或 HTTPS 访问,凭证放 vault 不进沙箱
Destination唯一可写的投递目的地一个 Slack 频道;投递成功前不改任何状态
Agent模型 + 系统 prompt + 工具的版本化配置agent.md 里写 run steps 和判断规则
Schedulecron 调度deployment.md 声明调度、时区与每轮首条消息
Memorypreferences(用户只读)+ state(Agent 读写)书签、账本、运行记录都在 state
Guardrails能做什么、能花多少只读权限、网络 allowlist、每轮预算上限
flowchart LR
    S["Schedule(cron)"] --> A["Agent(沙箱内运行)"]
    A -->|"读增量(书签→本轮窗口)"| SRC["Sources
Slack / GitHub 等"] A -->|"确认送达后投递"| D["Destination
Slack 频道"] MEM["Memory
preferences(只读)+ state(读写)"] <--> A G["Guardrails
只读权限 · allowlist · 预算"] -.->|约束| A

在 Claude Managed Agents 上,Agent 只是配置文件(agent.md、deployment.md、environment.yaml、记忆 store 与 vault 的 YAML),ant apply 命令把资源创建到平台侧,之后调度运行完全在 Anthropic 基础设施上,本地不需要任何常驻进程。每轮调度触发都会开一个全新 session、全新沙箱。

增量读取:书签,不是固定时间窗口

最常见的错误是让 Agent 读"最近 24 小时":跑晚了留缺口,跑早了重复报。正确做法是给每个来源维护一个书签(bookmark)——每轮结束时把该来源读到的最新条目时间戳写进 bookmarks.json,下一轮从书签开始读。窗口随两次运行的实际间隔伸缩,天然覆盖"跑晚了的缺口",也不重复。

失败的读取 ≠ 安静的一天

如果某来源的 MCP server 挂了或 token 过期,run 仍会启动,只是缺那一路工具——Agent 什么都看不到,于是报"今天没新东西"。读者会误以为真的无事发生。规则是:来源读取失败时,书签保持不动(下次接着读)、用其余来源照常出报、并在结尾明确写一行"本次无法读取 XXX"。宁可承认读不到,不能把故障伪装成无事。

投递确认:先确认,后记账

自动化有真实副作用(往频道发消息),持久执行原则在这里体现为记账必须晚于确认:如果记了账但消息没发出去,书签已经前移,那些条目永远不会再报;如果不确定是否发出就再发一次,读者收到重复报。daily-brief 的做法分三步:

  1. 发帖前先在频道近期消息里查今天的标题,已存在则不重发(幂等去重);
  2. 只有 Slack 返回 "ok": true 且带 message ts 才算发送成功;
  3. 确认之后才更新账本和书签;结果不明就把本轮标记为 “maybe posted”,其余一律不动。

Agent 记忆里维护一份账本(ledger):每条报过的条目记录报告日期、来源、不变 ID(Slack 消息时间戳 / PR 号)和最后已知状态。已报且仍开放的条目只折叠成一行"仍在等,第 3 天",不重复展开;已关闭的静默移除。

发布前复核:世界在你读取时继续动

从读取来源到发帖之间有时间差,条目可能已经解决或状态反转。规则是在发帖前对每条要报的条目重查实时状态:已解决则删掉,仍开放但变化则改写,无法确认则删掉并记入本轮 cuts。文中给出的判断值得记住:一条过时的"还在等你处理"比十条漏报更伤信任,所以状态要么断言、要么删掉,绝不模糊措辞。所有链接都从来源自身的 link 字段复制(如 PR 的 html_url),不手工拼。

记忆双仓:偏好只读,状态读写

无人值守场景下记忆要分两仓:

  • preferences(用户的,Agent 只读):读哪些频道和仓库、排除什么、长度上限、投递目的地、何时停止。每轮开始重新读文件,绝不把偏好复制进 prompt——prompt 里烤进去的副本会在你改完偏好后继续生效旧规则。读不到偏好文件时应停下来报告,而不是按默认值跑。
  • state(Agent 的,读写):书签、账本、每轮运行记录、对偏好的修改建议、各来源的行为笔记(如"只返回最新 50 条")。

陈旧记忆同样危险:会把已解决的报成"仍在等",或因"已报过"而漏掉仍开放的事。

护栏:没人盯着的自动化要限权限钱

定时自动化的护栏有两类:

限制能做什么。 Agent 读的消息和 issue 是别人写的文本,可能被解读成指令(提示注入,见 OWASP Agentic AI Top 10)。原则是:只读的地方就给只读权限——GitHub token 设 read-only、preferences store 对 Agent 只读、环境只放行 allowlist 内的主机。同一 token 读写共用时(如 Slack bot),只把 bot 拉进它确实需要读写的频道。

限制能花多少。 每轮运行设预算上限(Managed Agents 的 budget),从真实运行成本出发:初始设为正常一轮的 3–5 倍,看到真实数字后再收紧。触顶的 run 是暂停而非失败(stop reason 为 budget_reached)——所以预算设太低的表现不是报错,而是简报悄悄消失。架构图里还有一点正文未展开但值得记下:护栏还包括轮数/时间上限,以及一个有人盯着的 heartbeat——后台自动化需要外部的心跳监控,沉默本身就应该触发告警。

相关概念

参考来源
  1. 1. https://claude.dev/blog/building-effective-agent-automations/
  2. 2. https://github.com/anthropics/claude-quickstarts/tree/main/managed-agents/daily-brief
  3. 3. https://www.anthropic.com/engineering/managed-agents
评论