构建agent的12个准则:12-factor-agents
2025-11-18
深度学习
00

目录

12-Factor Agents 准则详解
准则1:自然语言转工具调用
准则2:拥有你的提示词
准则3:拥有你的上下文窗口
准则4:工具就是结构化输出
准则5:统一执行状态和业务状态
准则6:启动/暂停/恢复的简单API
准则7:通过工具调用联系人类
准则8:拥有你的控制流
准则9:将错误压缩到上下文窗口
准则10:小而专注的代理
准则11:从任何地方触发,在用户所在的地方见面
准则12:让代理成为无状态的归约器
总结

https://github.com/humanlayer/12-factor-agents/tree/main

12-Factor Agents 准则详解

准则1:自然语言转工具调用

核心:将用户的自然语言请求转换为结构化的工具调用。

例子:用户说“给Terri创建一个750美元的付款链接,用于2月AI聚会赞助”,转换为:

json
展开代码
{ "function": "create_payment_link", "parameters": { "amount": 750, "customer": "cust_xxx", "memo": "..." } }

然后由确定性代码执行。这是代理的基础能力。


准则2:拥有你的提示词

核心:不要依赖框架的黑盒提示词,要自己编写和控制。

原因:

  • 框架的提示词可能不适合你的场景
  • 难以调试和优化
  • 无法精确控制输入给模型的内容

做法:把提示词当作代码来管理,可以测试、迭代、版本控制。就像写函数一样写提示词。


准则3:拥有你的上下文窗口

核心:自定义如何组织和传递上下文给LLM,不一定要用标准的消息格式。

要点:

  • 上下文包括:提示词、历史对话、工具调用结果、RAG文档、错误信息等
  • 可以用XML、YAML等自定义格式,提高信息密度和token效率
  • 控制哪些信息进入上下文,过滤敏感数据

例子:可以用XML标签组织上下文,而不是标准的role/content格式,让模型更容易理解。


准则4:工具就是结构化输出

核心:工具调用本质就是LLM输出的结构化JSON,不需要复杂抽象。

理解:

  • LLM输出JSON → 解析为工具对象 → 执行对应操作
  • 工具调用和普通结构化输出没有本质区别
  • 可以用switch语句处理不同的工具调用

好处:简单直接,易于理解和调试。


准则5:统一执行状态和业务状态

核心:不要过度分离“执行状态”(当前步骤、重试次数等)和“业务状态”(历史记录、工具调用等),尽量统一。

做法:

  • 将执行状态也放入上下文窗口
  • 从上下文窗口可以推断出所有执行状态
  • 一个Thread对象包含所有信息

好处:

  • 单一数据源,易于序列化
  • 调试方便,所有历史可见
  • 可以从任意点恢复执行

准则6:启动/暂停/恢复的简单API

核心:让代理像普通程序一样,可以通过简单API启动、暂停、恢复。

能力:

  • 用户/应用可以通过API启动代理
  • 代理可以在长时间操作时暂停
  • 外部触发器(如webhook)可以让代理恢复执行

重要性:支持异步操作和人工审核,让代理更可靠。


准则7:通过工具调用联系人类

核心:将人类交互也作为工具调用,统一处理。

做法:

  • 定义request_human_input这样的工具
  • LLM可以决定何时需要人类帮助
  • 统一处理人类响应和工具调用结果

好处:

  • 支持“外循环”代理(由事件触发,而非用户发起)
  • 可以协调多个人类的输入
  • 易于扩展到代理间通信

准则8:拥有你的控制流

核心:自定义控制流程,支持中断、恢复、错误处理等。

能力:

  • 某些工具调用后可以中断循环等待响应
  • 某些工具调用后继续循环
  • 可以自定义错误处理、日志记录、速率限制等

例子:

  • request_clarification → 中断,等待人类响应
  • fetch_git_tags → 继续循环
  • deploy_backend → 中断,等待人工批准

准则9:将错误压缩到上下文窗口

核心:当工具调用失败时,将错误信息放入上下文,让LLM尝试自我修复。

做法:

python
展开代码
try: result = await handle_next_step(thread, next_step) except Exception as e: thread.events.append({ "type": "error", "data": format_error(e) }) # 继续循环,让LLM看到错误并重试

注意:需要限制重试次数,避免无限循环。连续失败后应升级给人类处理。


准则10:小而专注的代理

核心:不要构建大而全的代理,要构建小而专注的代理。

原因:

  • 上下文窗口越大,LLM越容易迷失
  • 3-10步(最多20步)的任务更容易成功
  • 小而专注的代理更容易测试和调试

策略:

  • 每个代理只做一件事
  • 复杂任务拆分成多个小代理
  • 随着LLM能力提升,可以逐步扩大代理范围

准则11:从任何地方触发,在用户所在的地方见面

核心:支持多渠道触发和响应(Slack、邮件、SMS等)。

能力:

  • 用户可以从任何渠道触发代理
  • 代理可以在同一渠道响应
  • 支持“外循环”代理(由事件、定时任务等触发)

好处:

  • 让AI应用更像数字同事
  • 支持高风险的代理操作(因为可以快速联系人类)
  • 提高可用性和用户体验

准则12:让代理成为无状态的归约器

核心:用函数式编程思想,将代理设计为无状态的归约器(reducer)。

理解:

  • 代理 = (state, event) => newState
  • 给定当前状态和事件,返回新状态
  • 无状态,易于测试和推理

好处:

  • 函数式设计,易于理解和维护
  • 状态转换清晰
  • 支持时间旅行调试

总结

这12个准则的核心思想:

  1. 保持简单:不要过度抽象,工具就是JSON输出
  2. 保持控制:拥有提示词、上下文、控制流
  3. 保持灵活:支持暂停、恢复、多渠道
  4. 保持专注:小而精的代理,而非大而全
  5. 保持可靠:错误处理、人类介入、状态管理
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!