Snowflake无人值守Agent:六种失败模式与护栏
有效阅读仅保存在当前浏览器,用于「为你」推荐;暂停或清除记录。
DataHot 速览
Snowflake官方博客介绍如何用CoCo automations在Snowflake内调度无人值守的编码Agent,让它自动跟进PR、CI失败和评审评论。作者采用按仓库/PR维护状态表、拆分监控与评审任务、独立watchdog,以及把权限校验放在Agent之外等架构。文章总结六种误导性失败模式,并解释每道护栏的作用。CoCo automations目前处于public preview,功能可能变化。
为什么值得关注:对在数据平台内构建和生产化Agent的团队有参考价值:它讲清了调度、状态、权限隔离、独立看门狗和失败模式,而非只展示功能发布。
译文
AI 逐段翻译在 Snowflake 中调度一个无人值守的编码 agent 现在只需几个 CLI 标志。让它保持诚实才是真正的工作。下面是我们最终采用的整体架构,以及六种失败模式——正是它们让我们明白了每道护栏为何存在。
注意:CoCo 自动化处于公开预览阶段。 以下内容均描述预览功能,可能会发生变化。
你将了解到:
- 无需单独的运行器即可运行定时 agent
- 拆分工作并添加独立的看门狗
- 把权限检查放在 agent 之外
- 识别六种误导性失败以及该检查什么
让拉取请求无人值守地持续推进
我们希望 agent 能察觉到某个分支落后于 main、CI 失败、或有评审意见无人回应——而无需有人先打开聊天。
这意味着要调度运行、记住之前的工作,并限制 agent 能改动什么。我们使用 CoCo 自动化,以免维护单独的运行器或容器。搭建过程很直接。搞清楚定时工作是否真的完成了,则要费更多功夫。

整体结构
四个术语,因为后文措辞很重要:
- 自动化:一次循环的、无人值守的 agent 运行。存储为 AGENT TASK,定时调度,在 Snowflake 管理的沙箱中执行。agent 循环本身不需要仓库。
- 运行手册:提示词。一个 markdown 文件,描述 agent 每次运行应做什么,在创建自动化时随其一同保存。
- MCP 服务器:agent 如何触达外部世界,包括源代码控制和聊天。显式挂接到自动化上。
- 状态表:一张普通的 Snowflake 表,以仓库和拉取请求为键,保存 agent 在两次运行之间绝不能忘记的一切。
Snowflake 负责运行时,因此我们不需要维护单独的服务器或运行器。自动化以其创建者的身份运行,凭证存储在 Snowflake 密钥对象中,而不是 CI 中。
我们把工作拆分到多个独立的自动化中,而不是一个大自动化,事实证明这比预期更重要:
- 一个监控器每小时运行一次。它保持打开的拉取请求可合并,在分支落后时将基础分支合并进来,并就任何非例行的维护事务通知作者。
- 一个评审引擎每小时运行一次,消费一个工作队列,发布标准评审,并回应来自人类和机器人的未解决评论。
- 一个看门狗按自己的计划运行,并且可以关闭评审引擎。
- 一个摘要每个工作日早晨运行一次,报告发生了什么。
拆分它们意味着看门狗不是由它所监督的对象实现的,而且嘈杂组件中的故障不会拖垮那个向你报告故障的组件。写下来这听起来显而易见。在构建时却并不明显。
此命令创建监控器。自动化处于公开预览阶段,因此复制之前请对照当前文档检查标志。
cortex automation create \
--name PR_MONITOR \
--connection my_connection \
--schedule "hourly" \
--timezone America/New_York \
--workspace MY_DB.MY_SCHEMA.AGENT_WS \
--mcp MY_DB.MY_SCHEMA.MCP_STATE_WRITES \
--mcp MY_DB.MY_SCHEMA.MCP_GITHUB \
--mcp MY_DB.MY_SCHEMA.MCP_JIRA \
--mcp MY_DB.MY_SCHEMA.MCP_NOTIFY \
--prompt-file ./monitor_runbook.md自动化以创建用户的默认角色和默认次要角色运行,而不是您创建它们时处于活动状态的角色。如果您想要只读上限,请使用受限会话范围设置一个。我们通过一个以 MCP 工具形式暴露的存储过程写入状态,因此 agent 只能以我们定义的方式更改状态。
agent 的记忆不是向量存储,也不是仓库中的文件。它是一张表,每个拉取请求一行,当有异常时你可以查询它。
CREATE OR REPLACE TABLE PR_STATE (
REPO VARCHAR NOT NULL,
PR_NUMBER NUMBER NOT NULL,
HEAD_SHA VARCHAR,
CI_SHA VARCHAR,
CI_STATE VARCHAR,
REVIEW_DIFF_HASH VARCHAR,
LAST_CHECKED_AT TIMESTAMP_NTZ,
PRIMARY KEY (REPO, PR_NUMBER)
);我们跟踪 CI 检查了哪个提交、我们已经评审了哪些更改,以及监控器上次检查该 PR 的时间。

护栏
护栏一:在 agent 之外授权更改agent 提出修复方案;一个确定性的辅助程序检查它是否可以推送这些修复。这些检查位于 agent 循环之外的代码中。每个贡献者被设置为一种模式,从仅评审到自动修复,该模式决定修复是否需要人工批准。
在批准模式下,人类必须回复一个由辅助程序生成的、一次性的令牌,修复才会被推送。辅助程序检查该令牌。agent 的说明不算作批准。
护栏二:给看门狗自己的职责 agent 可能会陷入修复自己修复的循环。我们运行一个独立的看门狗,检查仓库提交历史中的失控循环,并可以禁用评审引擎。
看门狗按自己的计划运行,不依赖引擎对发生情况的描述。如果引擎在循环,我们希望由该引擎之外的某个对象来判断一切是否正常。
护栏三:知道你的测试衡量的是什么我们从影子模式开始:引擎提出修复方案但不推送任何内容。在转向批准令牌之前,我们对这些方案进行了评分。
影子模式测试了修复质量,但无法表明某个修复是否会无休止地触发另一个修复。没有推送,就没有第二轮。批准令牌让我们能够在有人参与的情况下观察真实的推送和随后的 CI 周期。
失败模式
我当时在度假,用手机检查一切,并用 CoCo 试着在雨林徒步 🌲 和游客购物狂欢 🛍️ 之间修复错误。真希望我在亲身体验这些之前就知道它们。
一个并不是超时的超时 工作没有完成,但每次运行都报告成功。我以为可能是运行时间太长并触发了超时。问题出在超时设置本身。该工具最多接受 600 秒,而我配置的值超过了这个数。每次调用都立即失败,甚至在存储过程开始之前就失败了。把设置降到 600 就解决了。然后我在第二个工具中犯了同样的错误,尽管我已经记下了第一个工具的教训。我怎么又这样了?!我计划添加一个测试,在工具发布前拒绝无效的超时。我还没有构建它。与此同时,我愿意相信我不会第三次犯同样的错误。
agent 误诊了失败agent 把失败的调用描述为“查询超时”,这让我去寻找容量问题。该调用实际上在执行之前就被拒绝了。我们需要检查底层错误,而不是依赖 agent 的解释。
毫无意义的成功一次运行可以在什么工作都没做的情况下报告成功。任务完成了;代理的工具全部失败;没有任何报错。我们的报告会在绿灯下连续数周失去踪影。如果你唯一的健康信号是“计划运行是否完成”,那你就没有健康信号。要对输出做出断言:是否有一行数据落地,是否有一条消息发布,产物是否比本次运行更新。
工具的配置会覆盖你的运行手册每个工具都带有自己的计算配置。运行手册中的 USE WAREHOUSE 语句无法保护一个被固定到另一个已饱和仓库的工具。我们的情况正是如此,所有告警都在队列中滞留了四天,而运行手册看起来却完全正确。检查每个工具自身的仓库设置,而不只是运行手册。
命名一个工具并不等同于绑定到它一个引用了服务器的运行手册只能证明作者意图建立绑定。在我们的运行中,describe 命令没有列出已附加的服务器,因此有一个月时间,我们的摘要被绑定到了一个不包含运行手册所调用工具的服务器上。读取实际对象定义。将其与你原本的意图进行差异比对。
而代价最大的一个:长期的误报掩盖了真实的故障我们有一个质量门,其阈值来自其自身历史输出的中位数。它连续十二天每天触发。团队学会了忽略它。在其之下,一个真正的上游中断在期间开始,并在余下的时间里未被察觉,因为本应告知我们的渠道早已充满了我们训练自己去跳过的噪音。

在发布告警阈值之前,用历史数据回放它,并检查它本会触发的频率。
回顾
- 一个自动化组合了计划提示、附加的 MCP 工具和一个状态表。代理循环本身不需要仓库。
- 拆分工作。看门狗不能是它自己所监视的东西。
- 代理提出建议;确定性代码负责授权。
- 了解你的验证在衡量什么。影子模式测试的是修复质量,而不是循环深度。
- 一次绿色的运行证明不了任何东西。要对输出做出断言。
- 嘈杂的告警比没有告警更糟。
作者:Kat Prince-Sayward,GTM 分析负责人。
你的代理整夜运行了。以下是它做错的地方。最初发表于Snowflake Builders Blog:数据工程师、应用开发者、AI 与数据科学于 Medium,人们通过高亮并回应这个故事在那里继续对话。
这篇内容对你有用吗?
反馈只用于改善内容筛选,不等同于收藏