基于经典 12-factor app 原则,提出构建可靠 LLM Agent 应用的架构最佳实践,对生产级 AI 系统开发有直接指导意义。
按照 12 Factor Apps 的精神编写。本项目源代码公开在 https://github.com/humanlayer/12-factor-agents,欢迎提供反馈和贡献。让我们一起搞清楚这个问题!
错过了 AI Engineer World's Fair?点这里看演讲
在找 Context Engineering?直接跳到 factor 3
想贡献到 npx/uvx create-12-factor-agent?看看讨论帖
嗨,我是 Dex。我做 AI agents 工作已有一段时间了。
我试过市面上的每个 agent 框架,从即插即用的 crew/langchain 系列,到"极简"的 smolagents,再到"生产级"的 langraph、griptape 等等。
我和很多真正强大的创始人聊过天,他们有的在 YC,有的不在,都在用 AI 构建令人印象深刻的东西。大多数都是自己搭建整套技术栈。我在生产环境中看到框架被使用的情况并不多。
我惊讶地发现,市面上大多数自称是"AI Agents"的产品其实并不像代理。很多其实是代码为主,LLM 步骤只在恰当的地方穿插进来,以提供真正神奇的体验。
好的 Agent 不遵循"给你提示词,给你一堆工具,循环直到达成目标"的模式。相反,它们主要由软件组成。
所以我想回答这个问题:
我们用什么原则来构建 LLM 驱动的软件,使其足够好到能交给生产环保户使用?
欢迎来到 12-factor agents。就像自 Daley 以来的每位芝加哥市长都在城市主要机场贴遍的宣传语那样,我们很高兴你在这里。
特别感谢 @iantbutler01、@tnm、@hellovai、@stantonk、@balanceiskey、@AdjectiveAllison、@pfbyjy、@a-churchill,以及 SF MLOps 社区对本指南的早期反馈。
即使 LLM 继续以指数级变得更强大,也会有核心工程技术使 LLM 驱动的软件更加可靠、更易扩展、更容易维护。
Factor 1:自然语言到工具调用
Factor 2:自有你的提示词
Factor 3:自有你的上下文窗口
Factor 4:工具只是结构化输出
Factor 5:统一执行状态和业务状态
Factor 6:用简单 API 启动/暂停/恢复
Factor 7:用工具调用联系人类
Factor 8:自有你的控制流
Factor 9:将错误压缩进上下文窗口
Factor 10:小而专焦的 Agent
Factor 11:从任何地方触发,在用户所在之处相遇
Factor 12:让你的 Agent 成为无状态 reducer
更深入了解我的 agent 历程和我们走到这里的过程,请查看 A Brief History of Software - 快速摘要在这里:
我们会聊很多有向图(DGs)及其无环朋友 DAGs。我先指出……好吧……软件就是有向图。我们曾经用流程图来表示程序,是有原因的。
大约 20 年前,我们开始看到 DAG 编排器变得流行。我说的是像 Airflow、Prefect 这样的经典框架,还有一些前驱者,以及像 dagster、inggest、windmill 这样的新框架。这些遵循同样的图模式,加上了可观测性、模块化、重试、管理等优点。
我不是第一个说这句话的人,但当我开始学习 agent 时,我最大的收获是——你可以扔掉 DAG。与其让软件工程师编码每一步和边界情况,不如给 agent 一个目标和一组转移:
让 LLM 实时做决策来计算路径。
这里的承诺是你写更少的软件,只需给 LLM 图的"边",让它计算出节点。你可以从错误中恢复,你可以少写代码,而且你可能会发现 LLM 找到问题的新颖解决方案。
如我们稍后将看到的那样,这似乎并不完全行得通。
让我们更深入地了解一下——使用 agent,你有一个由 3 步组成的循环:
initial_event = {"message": "..."}
context = [initial_event]
while True:
next_step = await llm.determine_next_step(context)
context.append(next_step)
if (next_step.intent === "done"):
return next_step.final_answer
result = await execute_step(next_step)
context.append(result)
我们的初始上下文就是起始事件(可能是用户消息、cron 触发、webhook 等),我们要求 llm 选择下一步(工具)或确定我们完成了。
这是一个多步骤的例子:
最终,这种方法的效果不如我们想要的那样好。
在构建 HumanLayer 时,我和至少 100 名 SaaS 构建者(大多数是技术创始人)交过流,他们都想让现有产品更加 agentic。旅程通常是这样的:
免责声明:我不确定在哪里说这句话最合适,但这里似乎不错:这绝对不是对众多框架或从事这些框架工作的聪明人的批评。他们带来了不可思议的东西,加速了 AI 生态。
我希望这篇文章的一个结果是 agent 框架构建者可以从我和他人的经历中学习,使框架更加完善。
特别是对想快速进展但需要深度控制的构建者。
免责声明 2:我不打算讨论 MCP。我相信你能看出它的位置。
免责声明 3:我主要使用 typescript,有原因,但所有这些东西在 python 或你喜欢的任何其他语言中都能工作。
不管怎样,回到主题……
挖掘了数百个 AI 库并与数十位创始人合作后,我的直觉是这样的:
有一些核心的东西使 agent 变得伟大。
全力押注一个框架并构建本质上的全新编写可能会适得其反。
有一些核心原则使 agent 变得伟大,如果你拉进一个框架,你会获得大多数/全部这些原则。
但是,我看到的构建者向客户提供高质量 AI 软件的最快方式是采用来自 agent 构建的小的、模块化的概念,并将它们整合到现有产品中。
这些来自 agent 的模块化概念可以由大多数熟练的软件工程师定义和应用,即使他们没有 AI 背景。
Factor 13:预取你可能需要的所有上下文
参与贡献本指南
我在 2025 年 3 月的 Tool Use 播客一集中讨论了很多这方面的内容
我在 The Outer Loop 上写过一些相关的东西
我和 @hellovai 一起做关于"通过 LLM 最大化性能"的网络研讨会
我们在 got-agents/agents 下用这种方法构建开源 agent
我们无视了自己的所有建议,构建了一个在 kubernetes 中运行分布式 agent 的框架
本指南的其他链接:12 Factor Apps Building Effective Agents(Anthropic)Prompts are Functions Library patterns: Why frameworks are evil The Wrong Abstraction Mailcrew Agent Mailcrew Demo Video Chainlit Demo TypeScript for LLMs Schema Aligned Parsing Function Calling vs Structured Outputs vs JSON Mode BAML on GitHub OpenAI JSON vs Function Calling Outer Loop Agents Airflow Prefect Dagster Inngest Windmill The AI Agent Index(MIT)NotebookLM on Finding Model Capability Boundaries
Building Effective Agents(Anthropic)
Prompts are Functions
Library patterns: Why frameworks are evil
The Wrong Abstraction
Schema Aligned Parsing
Function Calling vs Structured Outputs vs JSON Mode
OpenAI JSON vs Function Calling
The AI Agent Index(MIT)
NotebookLM on Finding Model Capability Boundaries
感谢所有为 12-factor agents 做出贡献的人!
所有内容和图像都在 CC BY-SA 4.0 许可证下授权
代码在 Apache 2.0 许可证下授权