构建可靠 LLM 应用的模式:12-Factor Agents 原则
humanlayer/12-factor-agents
要构建足够可靠,能够交付给生产环境用户的 LLM 驱动软件,我们可以遵循哪些原则?
License
View license 368 stars 18 forks
12 Factor Agents - 构建可靠 LLM 应用的原则
秉承 12 Factor Apps 的精神。 本项目源码公开在 https://github.com/humanlayer/12-factor-agents,欢迎您提出反馈和贡献。让我们一起解决这个问题!
大家好,我是 Dex。我一直在 hacking AI agents 并且已经有一段时间了a while。
我尝试过市面上所有的 agent 框架,从即插即用的 crew/langchains,到 "极简主义" 的 smolagents,再到 "生产级" 的 langraph, griptape 等。
我和很多非常优秀的创始人交流过,包括 YC 内外的,他们都在用 AI 构建非常令人印象深刻的东西。他们中的大多数都在自己构建技术栈。我在面向客户的生产 agent 中没有看到很多框架。
我惊讶地发现,市面上大多数标榜为 "AI Agents" 的产品,其实并没有那么 "agentic"。它们中的很多主要是确定性代码,在恰当的位置添加 LLM 步骤,从而使体验真正神奇。
Agent,至少好的 agent,并不遵循 "给你一个 prompt,给你一堆工具,循环直到达到目标" 模式。相反,它们主要由软件组成。
所以,我开始尝试回答这个问题:
我们可以使用哪些原则来构建 LLM 驱动的软件,使其真正足够好,可以交付给生产环境用户?
欢迎来到 12-factor agents。正如自 Daley 以来,每一位芝加哥市长都持续地在城市的主要机场上宣传的那样,我们很高兴你在这里。
特别感谢 @iantbutler01, @tnm, @hellovai, @stantonk, @balanceiskey, @AdjectiveAllison, @pfbyjy, @a-churchill 和 SF MLOps 社区,感谢他们对本指南的早期反馈。
简短版本:12 个要素
即使 LLM 持续呈指数级增长,仍然有一些核心工程技术可以使 LLM 驱动的软件更可靠、更具可扩展性,并且更易于维护。
- 我们是如何走到这里的:软件简史
- 要素 1:自然语言到工具调用 (Natural Language to Tool Calls)
- 要素 2:拥有你的 prompts (Own your prompts)
- 要素 3:拥有你的上下文窗口 (Own your context window)
- 要素 4:工具只是结构化输出 (Tools are just structured outputs)
- 要素 5:统一执行状态和业务状态 (Unify execution state and business state)
- 要素 6:使用简单的 API 启动/暂停/恢复 (Launch/Pause/Resume with simple APIs)
- 要素 7:使用工具调用与人类联系 (Contact humans with tool calls)
- 要素 8:拥有你的控制流 (Own your control flow)
- 要素 9:将错误压缩到上下文窗口 (Compact Errors into Context Window)
- 要素 10:小型、专注的 Agents (Small, Focused Agents)
- 要素 11:从任何地方触发,在用户所在的地方与他们见面 (Trigger from anywhere, meet users where they are)
- 要素 12:使你的 agent 成为无状态 reducer (Make your agent a stateless reducer)
可视化导航
我们是如何走到这里的
要深入了解我的 agent 之旅以及引导我们走到这里的原因,请查看 软件简史 - 这里是一个快速摘要:
Agents 的前景
我们将讨论很多关于有向图 (DGs) 及其非循环朋友 DAGs。我将首先指出... 嗯... 软件就是一个有向图。我们过去将程序表示为流程图是有原因的。
从代码到 DAGs
大约 20 年前,我们开始看到 DAG 编排器变得流行。我们讨论的是像 Airflow, Prefect 这样的经典产品、一些前身,以及一些较新的产品(如 dagster, inggest, windmill)。这些产品都遵循相同的图模式,并具有可观察性、模块化、重试、管理等额外优势。
agents 的前景
我不是第一个 说这话的人,但当我开始学习 agents 时,我最大的收获是你可以丢弃 DAG。工程师无需编写每个步骤和边缘案例的代码,你可以给 agent 一个目标和一组转换:
并让 LLM 实时做出决策以找出路径
这里的前景是你编写更少的软件,你只需为 LLM 提供图的 "边",并让它找出节点。你可以从错误中恢复,你可以编写更少的代码,并且你可能会发现 LLM 找到了解决问题的新颖方法。
agents 作为循环
正如我们稍后将看到的,事实证明这并不完全有效。
让我们更深入一步 - 使用 agents,你将获得一个包含 3 个步骤的循环:
- LLM 确定工作流程中的下一步,输出结构化的 JSON ("tool calling")
- 确定性代码执行 tool call
- 结果附加到上下文窗口
- 重复,直到确定下一步为 "完成"
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 选择下一步(工具)或确定我们已完成。
这是一个多步骤的例子:
027-agent-loop-animation.mp4 GIF Version
为什么是 12-factor agents?
归根结底,这种方法的效果不如我们期望的那么好。
在构建 HumanLayer 时,我至少与 100 位希望使其现有产品更具 agentic 的 SaaS 构建者(主要是技术创始人)进行了交谈。这个过程通常是这样的:
- 决定要构建一个 agent
- 产品设计,UX 映射,要解决什么问题
- 想要快速行动,所以抓住 $FRAMEWORK 并 开始构建
- 达到 70-80% 的质量标准 5a. 意识到 80% 对于大多数面向客户的功能来说还不够好 5b. 意识到超过 80% 需要对框架、prompts、流程等进行逆向工程
- 从头开始
随机声明
声明:我不确定在哪里说这个最合适,但这里似乎和其他地方一样好:这绝不是对现有框架或从事这些框架工作的聪明人的抨击。 它们实现了令人难以置信的事情,并加速了 AI 生态系统。
我希望这篇文章的一个结果是,agent 框架构建者可以从我和其他人的旅程中学习,并使框架变得更好。
特别是对于那些想要快速行动但需要深入控制的构建者。
声明 2:我不会谈论 MCP。我相信你可以看到它在哪里适用。
声明 3:我主要使用 TypeScript,因为原因,但所有这些东西都可以在 Python 或你喜欢的任何其他语言中使用。
总之,回到正题...
优秀 LLM 应用的设计模式
在研究了数百个 AI 库并与数十位创始人合作后,我的直觉是:
- 有一些核心的东西使 agent 变得伟大
- 全力投入框架并构建本质上是绿地重写的程序可能适得其反
- 有一些核心原则使 agent 变得伟大,如果你引入一个框架,你将获得大部分/全部这些原则
- 但是,我见过的构建者将高质量 AI 软件交付给客户的最快方法是从 agent 构建中提取小型、模块化的概念,并将它们整合到他们现有的产品中
- 这些来自 agent 的模块化概念可以由大多数熟练的软件工程师定义和应用,即使他们没有 AI 背景
我见过的构建者将优秀的 AI 软件交付给客户的最快方法是从 agent 构建中提取小型、模块化的概念,并将它们整合到他们现有的产品中
12 个要素(再次)
- 我们是如何走到这里的:软件简史
- 要素 1:自然语言到工具调用 (Natural Language to Tool Calls)
- 要素 2:拥有你的 prompts (Own your prompts)
- 要素 3:拥有你的上下文窗口 (Own your context window)
- 要素 4:工具只是结构化输出 (Tools are just structured outputs)
- 要素 5:统一执行状态和业务状态 (Unify execution state and business state)
- 要素 6:使用简单的 API 启动/暂停/恢复 (Launch/Pause/Resume with simple APIs)
- 要素 7:使用工具调用与人类联系 (Contact humans with tool calls)
- 要素 8:拥有你的控制流 (Own your control flow)
- 要素 9:将错误压缩到上下文窗口 (Compact Errors into Context Window)
- 要素 10:小型、专注的 Agents (Small, Focused Agents)
- 要素 11:从任何地方触发,在用户所在的地方与他们见面 (Trigger from anywhere, meet users where they are)
- 要素 12:使你的 agent 成为无状态 reducer (Make your agent a stateless reducer)
特别提及 / 其他建议
相关资源
- 在此处 贡献本指南
- 我在 2025 年 3 月的 Tool Use 播客的一集中谈到了很多这些内容
- 我在 The Outer Loop 上写了一些关于这些内容的内容
- 我与 @hellovai 一起 举办关于最大化 LLM 性能的在线研讨会
- 我们在 got-agents/agents 下使用这种方法构建 OSS agents
- 我们忽略了我们所有的建议,并构建了一个 用于在 Kubernetes 中运行分布式 agent 的框架
- 本指南中的其他链接:
- 构建有效的 Agents (Anthropic)
- Prompts are Functions
- 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
关于
我们如何使用哪些原则来构建 LLM 驱动的软件,使其真正足够好,可以交付给生产环境用户?
Topics
framework ai memory orchestration agents 12-factor rag prompt-engineering llms context-window 12-factor-agents