每个人都痴迷于提示词。他们微调问候语,调整语气,担心模型的语气是否足够亲切。这是一种分心。当一个 AI Agent 开始向真实用户发送真实的邮件时,危险并不在于它写的是“Best regards”而不是“Cheers”。危险在于,你无法确定在 Agent 的决策与邮件进入收件箱之间究竟发生了什么。我首先关注边界。那是生产系统悄然崩溃的地方。
契约是薄弱环节
AI 演示(Demo)是很宽容的。浏览器窗口中流畅的对话掩盖了一堆假设。在生产环境中,真正的脆弱点在于三者之间的契约:Agent 的决策、执行动作的工具,以及验证结果的步骤。如果这个边界模糊不清,系统在出问题之前表现得非常完美。然后,它会发生静默失败,向整个客户群体发送重复邮件,或者在没有明确记录原因的情况下,在错误的时间发出消息。提示词可能读起来像诗一样优美,但其底层的架构可能还只是靠一根绳子维系着。
停止让 Agent 自由写作
最常见的错误是给 Agent 一张白纸。团队让它用原始文本描述一封邮件,然后寄希望于下游工具能从散文中解析出意图。这是脆弱的。LLM 可能会建议一个合理的意图,但你的基础设施不需要创造力。它需要的是契约。它需要特定的字段,以便机器可以毫无歧义地进行验证。
当 Agent 发出邮件请求时,输出应该携带执行流程所需的所有内容:
- Template version (模板版本): 使用的是哪个版本的邮件正文,以便你知道用户看到了什么。
- Recipient scope (收件人范围): 由用户 ID 或细分规则定义,而不是使用像“刚刚注册的用户”这样的自然语言。
- Trace ID (追踪 ID): 一个唯一的标识符,该请求会从 Agent 经过执行器、邮件提供商,一直追踪到你的日志中。
- Time window (时间窗口): 该发送动作的有效期,这样过时的 Agent 决策就不会在几小时后触发午夜邮件。
- Idempotency (幂等性): 一个键值,用于防止在 Agent 重试或网络波动时,同一个逻辑发送动作被触发两次。
原始文本是一个糟糕的 API。它在紧急程度、受众和动作方面留下了歧义的空间。特定的字段是机器可读、可审计且可测试的。它们将模糊的指令转化为可验证的命令。
是动作,而非散文
与其交给 Agent 一个开放式的写作任务,不如将其限制在一个允许的操作菜单中。把它想象成一个具有固定 enum 的内部 API。Agent 不需要起草主题行,也不需要纠结问候语。它只需选择一个动作,例如 send_review_request 或 send_retry_notice。这就是它创造力的极限。
然后,一个确定性的执行器(deterministic executor)会获取该动作键,从版本控制中提取正确的模板,使用清洗后的数据进行填充,从经过验证的来源填充收件人列表,并构建最终的命令。Agent 决定需要发生什么。而枯燥、可预测的代码决定如何发生。
这种分离使得系统易于测试。你可以验证给定的输入状态是否能可靠地触发 send_retry_notice,而完全无需运行 LLM 推理。你的单元测试会变得快速且具有确定性,因为它们检查的是映射逻辑,而不是模型的 temperature。你的集成测试关注的是执行器是否将动作正确映射到邮件服务,而不是模型那天心情好不好。
分五层构建
一个稳健的系统不是通过单个提示词产生的。它是分层构建的,每一层都承担单一、明确的职责。
1. 后端将事件简化为安全的数据。
无论是触发器是 Webhook、数据库变更还是定时任务,这一层都会对输入进行清洗,剔除意外字段,并只向 Agent 提供它需要的内容。如果 Webhook 负载包含 20 个字段,但 Agent 只需要 2 个,那就只传递那 2 个。任何未经检查的原始用户文本都不应到达决策层。
2. Agent 从固定 schema 中选择一个动作。
它查看上下文,做出判断,并输出预定义的动作键之一以及所需的元数据。它不撰写散文,也不猜测收件人。它返回一个结构化负载,下一层可以根据 JSON schema 进行验证。
3. 工具验证权限和必填字段。
该 agent 上下文是否有权为该用户触发 send_review_request?接收者范围是否非空且在允许的限制范围内?幂等键(idempotency key)是否存在且在日志中是唯一的?trace ID 格式是否正确?在此处果断报错,确保在触及任何邮件服务之前就发现问题。
4. 邮件服务通过 trace ID 记录发送情况。
每一条离开系统的消息都应携带该 trace 标识符,通过提供商的 API 进入您的可观测性栈(observability stack)。如果用户投诉收到了两份副本,您应该能够通过查询一个 ID 来准确查看重复发生的原因:是 agent 调用重试、executor 不稳定,还是回调(callback)异常。
5. 端到端测试检查实际收件箱的内容和效果。
在真实的邮箱中打开渲染后的消息。主题行是否正确填充?退订链接是否有效?点击主要的行动号召(call-to-action)按钮后,是否跳转到了具有正确用户状态的正确页面?单元测试通过仅意味着代码运行了。只有收件箱测试才能告诉你邮件对人类用户确实有效。
证据胜于猜测
当此流水线中的测试失败时,您需要四项具体的证据。除此之外,不接受任何其他形式。
- 来自 agent 的原始决策。 它选择了什么操作,完整的输入上下文是什么?
- 来自工具的规范化命令。 在应用模板、数据填充逻辑(hydration logic)和验证规则后,确定性执行器(deterministic executor)构建了什么?
- 隔离收件箱中的消息。 不是您认为发送的内容的日志,而是捕获在专用测试邮箱中的真实 MIME 消息(包含所有报头)。
- 点击链接后的最终效果。 证明邮件已达到其目的的结果页面状态、数据库变更或外部事件。
如果缺少其中任何一项,您的团队就会用假设来填补空白。他们会进行猜测。在自动化流程中进行猜测是昂贵的。它会浪费大量时间,侵蚀信任,并将每一次事故变成一场取证式的谜团,而不是一个
