邮件轮询 Agent 如何避免无限等待与串单
文章建议为邮件等待工具定义明确契约,规定目标消息、等待时长、查询次数及返回证据。空结果不能直接说明投递失败,还需区分延迟、筛选错误和不同执行批次,避免重复调用或误用旧邮件。
AI 深度解读
让 LLM Agent 等一封注册确认邮件,难点不在于反复查询收件箱,而在于它凭什么认定邮件正确,又该在什么时候停止。原文给出的答案是:先约定等待契约,把时间、查询次数和验收条件交给工具与编排层执行。
这套思路适合涉及注册、找回账号的自动化测试。它没有提供性能对照实验,却把一个常见问题拆得很清楚:空收件箱、重复邮件、历史邮件和真正的产品故障,不能靠模型不断重试来区分。
收件箱为空,为什么不能直接再试一次
一次邮件流程跨过好几个环节:浏览器提交操作,后端发布事件,邮件服务商投递,工具读取收件箱。Agent 看到的只是其中一部分。
工具返回 [],只能证明这次查询没有结果。邮件可能没有发出,也可能还在路上,还可能是筛选条件写错了。继续查询并不会自动解释原因,反而可能读到上一次执行留下的邮件,让失败流程被误判为成功。
作者因此把等待拆成三个独立约束:总共允许等多久,最多查询多少次,以及什么邮件才算命中。最后一个约束尤其容易被忽略。收到邮件不等于拿到了本次操作的证据。
停止条件应该在执行前确定,不能让模型在重试过程中临时发挥。
Agent 可以决定失败后如何处理,但等待边界需要先由工具契约或编排策略固定下来。
一份等待契约,需要约定哪些内容
原文用下面这个对象描述查询请求,将执行标识、邮箱、筛选条件和预算放在一起:
{
"run_id": "signup-1842",
"mailbox_id": "mbx-7f2",
"subject_contains": "Confirma tu cuenta",
"after": "2026-10-30T17:20:00Z",
"deadline_seconds": 45,
"max_polls": 9,
"poll_interval_seconds": 5
}
重点看 run_id、after 和 max_polls:它们分别承担关联本次操作、排除旧邮件、限制调用次数的职责。deadline_seconds: 45 给出等待时长,poll_interval_seconds: 5 则让查询节奏可以复现和比较。
不过,run_id 写进请求并不等于关联已经成立。邮件里的什么字段能与它对应,原文没有说清,实际接入时必须补上。原文还建议使用绝对截止时间,而示例提供的是相对秒数;工具需要明确从哪个时刻计算这 45 秒。
查询间隔可以调整,但作者主张让工具或有版本记录的策略控制它。Agent 如果未经说明就把间隔从 5 秒改成 30 秒,不同执行之间便难以比较。LLM 可以在设计阶段建议参数,生产执行应遵守确定的配置。
响应也不能只有 true 或 false,而要区分四种状态:
found表示邮件符合约定,可以继续。timeout表示等待时间耗尽,需要结合原因判断。ambiguous表示存在多个候选,不能直接选一个。invalid_request表示请求缺少必要信息,应在查询前拒绝。
两个有效候选同时出现时,作者建议返回 ambiguous,并保留两者标识。直接接受第一封,可能掩盖后端重复发送的问题。
工具停下了,Agent 也必须停得下来
单次工具调用有超时,并不能阻止 Agent 再调用一次。作者还要求给 Agent 设置独立的步骤预算。
整个流程可以按三个检查点理解。触发邮件前,保存 run_id 和触发时间;进入工具时,拒绝没有截止时间的请求;工具返回 timeout 后,Agent 应报告失败或选择不同动作,不能无限重复原来的查询。
作者用两个假设说明如何定位问题:如果只进行了 5 次查询,工具就报告超时,可以检查投递、队列等环节;如果契约明明限制 9 次,Agent 却查了 30 次,就应检查编排层。这些数字是排障示例,不是实测统计。
工具还需要返回足够解释结果的证据,包括最终状态与原因、run_id、脱敏的 mailbox_id、候选数量、接受邮件的标识与主题及接收时间,以及实际查询次数和总耗时。有安全存储的产物时,可以附上引用。
证据不必包含整封邮件。作者建议不要把完整 token 放进模型上下文,集成测试有时只需要局部哈希,或者一个「链接包含 token」的标志。不过,这类标志只能支持相应断言,不能据此声称完整验证流程已经通过。
执行顺序也很关键:创建与 run_id 关联的隔离邮箱,在触发操作前记录时间,按固定策略查询,排除旧邮件、重复邮件和无法关联的候选,保存结果后再释放邮箱。第二次业务操作应生成新的 run_id;如果复用,必须说明原因。
原文提到的 tepm mail com 只是查找旧文档时可能出现的搜索写法,不能作为契约字段值或验收规则。
我的判断
我认同作者把确定规则放进工具和编排层。对邮件验证这样的流程,是否过期、是否超过调用次数,都可以由程序直接判断;让模型反复推断这些边界,只会增加排障难度。
但这是一套工程设计建议。作者没有给出调用量、token 消耗或误判率的对照数据,因此「减少无效调用」有明确的机制支撑,具体能改善多少仍属于未验证的部分。
它与普通定时轮询并不冲突。固定间隔查询同样可以做好隔离、关联、去重和证据记录。这里最有用的补充,是防止 Agent 在工具超时之后自行开启新一轮等待。
还有两个边界需要实现者自行定义:如果第一封合格邮件到达就返回,后续重复邮件如何被发现;遇到短暂查询异常时,是否计入 max_polls。原文没有给出完整规则。45 秒、9 次、5 秒也只是示例配置,不能直接当成团队默认值。
timeout 是一次等待的结果,不能单独作为产品故障的结论。
能拿来做什么
- 为注册和找回账号测试建立统一的邮件等待工具,把
run_id、触发时间、截止时间和查询次数上限设为明确输入,缺失必要信息就返回invalid_request。 - 在 Node 编排层记录一次等待已经执行过多少步骤,并为
timeout设置明确分支,避免 AI 编程助手生成「失败就继续调用」的无界循环。 - 在测试报告里展示状态、候选数量、查询次数和耗时,保留必要的邮件标识,同时避免把完整 token 和邮件正文塞进模型上下文。
- 先补齐邮件与本次操作的关联规则,再根据实际投递情况调整预算;对重复候选返回
ambiguous,不要用「先收到就通过」掩盖重复发送。