- 文档
- 教程
- 人工智能
- 大模型
- AI Agent
【免费下载链接】12-factor-agents
What are the principles we can use to build LLM-powered software that is actually good enough to put in the hands of production customers?
面对“什么都想做”的巨型单体 Agent,第 10 条原则给出的答案恰恰相反:把 Agent 拆成小而专注的单元,每个只做好一件事,并把它们作为更大、更确定性系统中的构件来使用。这篇指南将解释为什么任务越复杂、上下文越长,LLM 越容易"迷路";给出 3–10 步(最多 20 步)的可操作规模边界;并用本仓库 workshop 源码中的计算器 Agent 与 deploybot 微型 Agent 实例,展示"小即可靠"的工程落地方式。
12-Factor Agents 第 10 条:Small, Focused Agents——用多个小 Agent 替代一个巨型单体 Agent
核心主张:Agent 只是更大确定性系统中的一个构件
第 10 条的开篇主张非常明确:与其构建一个试图包揽一切的单体 Agent(monolithic agent),不如构建小而专注的 Agent——每个 Agent 只把一件事做好。Agent 并不是系统的全部,它只是更大的、以确定性代码为主的系统中的一个构建块。
Rather than building monolithic agents that try to do everything, build small, focused agents that do one thing well. Agents are just one building block in a larger, mostly deterministic system.
这一点与本仓库的整体理念一脉相承。在 README.md 中,作者反复强调:市面上大多数自称"AI Agent"的产品其实"并没有那么 agentic",它们大多是确定性代码,只是在恰到好处的位置点缀 LLM 步骤。而 brief-history-of-software.md 中专门提出了"micro agents(微型 Agent)"这一实践形态——把 Agent 模式"洒进一个更广泛的确定性 DAG 中",而不是把整个流程都交给一个长循环 Agent。
仓库为此提供了明确的事实依据:在 content/brief-history-of-software.md 的 "A real life micro agent" 一节中,作者记录了 HumanLayer 自用 deploybot 的真实运行序列——Human 合并 PR → 确定性代码部署到 staging → 确定性代码跑 e2e 测试 → 交给 Agent 执行生产部署 → 确定性代码请求人工审批。在这个流程里,Agent 只负责一个 5–10 步的小工作流,其余全部由确定性代码完成:
- 合并 PR 到 GitHub main 分支(Human)
- 部署到 staging 环境(确定性代码)
- 对 staging 跑端到端测试(确定性代码)
- 以 "deploy SHA 4af9ec0 to production" 为初始上下文,把生产部署交给 Agent
- Agent 调用
deploy_frontend_to_prod(4af9ec0) - 确定性代码请求人工审批,被 Human 以 "can you deploy the backend first?" 拒绝
- Agent 据此改调
deploy_backend_to_prod(4af9ec0),获批执行后再部署前端 - Agent 判定任务完成,确定性代码最后对生产环境跑 e2e 测试,必要时交给回滚 Agent
这个例子的关键启发是:LLM 的核心价值只在于解析用户纯文本反馈、并据此提出修正后的行动方案,而不是掌握全部部署逻辑。作者明确写道:"我们没有给这个 Agent 一堆庞大的工具或任务……我们尽可能隔离任务和上下文,让 LLM 专注于一个 5–10 步的小工作流。"
为什么任务越大越容易失败:上下文增长导致的"迷路"问题
小而专注并不是一种风格偏好,而是对 LLM 真实局限的回应。第 10 条的核心洞察是:
As context grows, LLMs are more likely to get lost or lose focus. 随着上下文增长,LLM 更可能迷路或失去焦点。
其推理链条是:任务越大越复杂 → 需要的步骤越多 → 上下文窗口越长 → LLM 越容易迷路或失去焦点。因此,把 Agent 聚焦在特定领域、把步骤控制在 3–10 步(最多 20 步),就能让上下文窗口保持在可控范围,从而维持较高的 LLM 表现。
这一结论在本仓库的历史梳理中得到了呼应。在 content/brief-history-of-software.md 的 "The problem with this 'loop until you solve it' pattern" 一节中,作者把"loop until you solve it"模式的最大问题总结为:
Agents get lost when the context window gets too long - they spin out trying the same broken approach over and over again.
即:上下文过长时,Agent 会陷入"用同一个坏方法反复重试"的失控循环。作者进一步给出一个更激进的判断,也是做 Agent 工程时值得反复咀嚼的直觉:
Even as models support longer and longer context windows, you'll ALWAYS get better results with a small, focused prompt and context即使模型支持越来越长的上下文窗口,使用小而聚焦的 prompt 和上下文,你总是能获得更好的结果。
为什么这足以"压垮"长循环方案?因为现实质量门槛非常苛刻——作者在与大量 builder 交流后发现,"任何超过 10–20 轮的流程都会变成 LLM 无法恢复的一团糟",即使 Agent 有 90% 的正确率,也"离可以交付给客户还差十万八千里"(可以想象一个 10% 页面加载崩溃的 Web 应用)。这也是第 9 条 content/factor-09-compact-errors.md 中那句结论的由来:防止错误失控循环的头号方法,就是拥抱第 10 条——小而专注的 Agent。
小而专注的五条收益
第 10 条原文档列出了五个直接收益,每一项都可以在生产实践中得到验证:
- 可管理的上下文(Manageable Context):更小的上下文窗口意味着更好的 LLM 表现。这与第 3 条"拥有你的上下文窗口"(content/factor-03-own-your-context-window.md)直接相关——小 Agent 从源头上让上下文构建变得容易。
- 职责清晰(Clear Responsibilities):每个 Agent 都有明确界定的范围和目的,prompt、工具集、成功标准都围绕单一职责设计,团队协作时边界不会互相污染。
- 更好的可靠性(Better Reliability):在复杂工作流中迷路的概率更低。单个 Agent 只处理它擅长的窄域,出错的随机性被限制在可控范围内。
- 更容易测试(Easier Testing):验证特定功能更简单。下文会看到,本仓库 workshop 中正是用 BAML 测试对单个 Agent 的意图判断做断言。
- 更易调试(Improved Debugging):问题发生时更容易定位和修复。故障域小,出错时能快速判断是哪个 Agent、哪一步、哪个工具调用出了问题。
仓库实证一:workshop 计算器 Agent——小型 Agent 的完整源码拆解
要理解"小而专注"在代码层面长什么样,最直接的方式是看本仓库 workshop 的最终版实现:workshops/2025-05/final/src/agent.ts。这个 Agent 的职责范围被刻意压缩到极致:只有四个计算器工具(加、减、乘、除),外加"请求澄清"与"结束"两类人类交互意图。核心是agentLoop这个典型的 Agent 循环:
export async function agentLoop(thread: Thread): Promise<Thread> { while (true) { const nextStep = await b.DetermineNextStep(thread.serializeForLLM()); console.log("nextStep", nextStep); thread.events.push({ "type": "tool_call", "data": nextStep }); switch (nextStep.intent) { case "done_for_now": case "request_more_information": // response to human, return the thread return thread; case "divide": // divide is scary, return it for human approval return thread; case "add": case "subtract": case "multiply": thread = await handleNextStep(nextStep, thread); } } }这个循环完美体现了"小"的两层含义:一是步骤规模小(每次只决定一步,且明确设定了done_for_now这样的终止意图);二是职责范围小(divide这种"危险操作"直接跳出循环交给人审,而不是让 LLM 自行处置)。这正是第 8 条"拥有你的控制流"(content/factor-08-own-your-control-flow.md)里讲的"在工具选择与工具调用之间打断并恢复"的落地形态——Agent 只负责"选",人负责"批"。
Agent 的"大脑"定义在 workshops/2025-05/final/baml_src/agent.baml 中。DetermineNextStep函数的 prompt 极其精简:系统提示词只有一句"You are a helpful assistant that can help with tasks",随后把序列化后的 thread 交给模型,让它输出结构化的下一步意图:
function DetermineNextStep( thread: string ) -> HumanTools | CalculatorTools { client "openai/gpt-4o" prompt #" {{ _.role("system") }} You are a helpful assistant that can help with tasks. {{ _.role("user") }} You are working on the following thread: {{ thread }} What should the next step be? {{ ctx.output_format }} "# }由于 Agent 小,测试也可以做得非常聚焦。同一个文件里的LongMath测试构造了一个三段式计算(multiply 3×4 → divide by 2 → add 12),完整模拟了一个 3 步小工作流的上下文,最终断言 Agent 应输出done_for_now且答案包含 "18":
test LongMath { functions [DetermineNextStep] args { thread #" <user_input> can you multiply 3 and 4, then divide the result by 2 and then add 12 to that result? </user_input> ...(multiply / tool_response / divide / tool_response / add / tool_response 逐步追加) "# } @@assert(intent, {{this.intent == "done_for_now"}}) @@assert(answer, {{"18" in this.message}}) }MathOperationWithClarification与MathOperationPostClarification两个测试则验证了"遇到含糊输入先向人澄清、拿到澄清后再回到计算"的完整闭环——这正是在 content/brief-history-of-software.md 中强调的:让语言模型管理界定良好的任务集合,可以轻松融入实时人工反馈,并把反馈翻译成工作流步骤,而不会陷入上下文错误循环。
在模型选择上,仓库也没有一味追求"大模型"。在 workshops/2025-05/final/baml_src/clients.baml 中可以看到,它同时配置了 gpt-4o、gpt-4o-mini、claude-3-5-sonnet、claude-3-haiku 等多个 client,并通过round-robin(轮询)与fallback(回退)策略在小型快速模型之间调度——小任务用轻量模型即可,这从资源层面进一步印证了"小"的经济性。CLI 入口 workshops/2025-05/final/src/cli.ts 则演示了如何以一条命令行消息启动 Agent、在"等待人回复"与"继续循环"之间切换,直到意图变为done_for_now才输出最终结果。同一模式也被固化进了脚手架 packages/create-12-factor-agent/template/src/agent.ts,说明它已经是一个可复用的参考实现。
步骤规模的实践经验:3–10 步,最多 20 步
第 10 条给了一个可操作的规模经验值:把 Agent 聚焦在特定领域,步骤控制在 3–10 步,最多不要超过 20 步。这是作者在真实产品实践中总结出的边界,也与 content/brief-history-of-software.md 中"超过 10–20 轮就会变成 LLM 无法恢复的混乱"相互印证。
值得注意的是,"小"同时意味着"上下文构建更简单"。小 Agent 的 thread 序列化成本低,可以直接把事件序列以紧凑的 XML 或 JSON 形式呈现给模型(见 packages/create-12-factor-agent/template/src/agent.ts 中serializeForLLM的实现),而不必引入复杂的压缩、摘要或检索策略。反过来,一旦 Agent 职责膨胀、上下文变长,就不得不依赖第 3 条的"上下文压缩"、第 9 条的"错误压缩进上下文"等补救手段——与其事后补救,不如事前把 Agent 拆小。
如果 LLM 变聪明了,还需要这样做吗?
第 10 条专门回答了一个必然会被问到的质疑:"如果未来 LLM 足够聪明,能处理 100+ 步的工作流,我们还需要这套方法论吗?"
原文档给出的答案简洁而坚定:需要(tl;dr yes)。理由分两层:
- 着眼当下:随着 Agent 与 LLM 能力的提升,它们可能会自然扩展到处理更长的上下文窗口,这意味着能承担更大的 DAG 中更多的部分。但这是"可能",不是现在。
- 渐进扩展:小而专注的做法确保你今天就能拿到结果(get results TODAY),同时为将来随着 LLM 上下文窗口变得更可靠而逐步扩大 Agent 的职责范围做好准备。
随着模型能力增强,小 Agent 的职责范围可以渐进式扩张(agent scope grow),但仍要保持可维护的质量边界
原文档点出了一个让老工程师会心一笑的类比:如果你重构过大型确定性代码库,你会对这句话深有共鸣。Agent 的规模/范围扩张,本质上和单体代码库的逐步模块化重构是同一种工程纪律——对 Agent 的规模/范围保持刻意(intentional),只以能维持质量的方式增长,是这里的关键。盲目跟随"模型变强就放宽一切"的直觉,只会把当年的单体代码库问题原样搬进 Agent 架构。
这一判断也贯穿在其他因子中。第 11 条 content/factor-11-trigger-from-anywhere.md 明确把"更大更好"的能力建立在小的基础上:Agent 可能连续工作 5、20、90 分钟,但当到达关键节点时,它需要停下来联系人类求助、反馈或审批;只有在小而专注、职责清晰的体系内,才能放心地给 Agent 开放"发送外部邮件、更新生产数据"这类高风险工具,并靠清晰的审批标准获得可审计性与信心。
能力边界与"魔法时刻":来自 NotebookLM 团队的洞见
第 10 条在结尾引用了一个非常值得玩味的观点,来自 NotebookLM 的构建团队(转引自 swyx 对 NotebookLM 的剖析):
I feel like consistently, the most magical moments out of AI building come about for me when I'm really, really, really just close to the edge of the model capability. 我始终觉得,AI 构建中最神奇的瞬间,几乎都发生在我无比贴近模型能力边界的时候。
这条引用的用意在于:无论模型的"能力边界"现在在哪里、将来在哪里,如果你能找到这个边界并稳定地踩在边界上(get it right consistently),你就能构建出神奇的体验。而"稳定地踩在边界上"恰恰是工程问题:
- 边界会随模型升级而移动,所以 Agent 的规模需要渐进式调整,而不是一次性梭哈;
- 踩边界意味着随时可能越界出错,所以每个 Agent 都要小而可测、可调试、可回滚;
- 这里可以构建很多护城河(moats),但和往常一样,它们需要工程上的严谨(engineering rigor)。
换句话说,小而专注不是"保守"或"不酷",它恰恰是让你能够持续、刻意地贴近模型能力上限而不翻车的工程手段。
在 12 因子体系中的位置:与相邻因子的协同
第 10 条不是孤立的一条原则,它与前后因子构成闭环:
- 第 9 条 Compact Errors:把错误压缩进上下文窗口可以解决"单次工具调用失败后自愈",但错误失控循环的根治方案是第 10 条——content/factor-09-compact-errors.md 明确写道:"防止错误失控循环的头号方法,就是拥抱 factor 10——小而专注的 Agent"。
- 第 8 条 Own Your Control Flow:小 Agent 依赖确定性代码在"工具选择"与"工具调用"之间打断、审批、恢复(content/factor-08-own-your-control-flow.md),workshop 计算器 Agent 中
divide跳出循环等人审批即是两者协同的样板。 - 第 3 条 Own Your Context Window:小 Agent 天然拥有可管理的上下文,是第 3 条"拥有上下文构建"最省力的实现方式。
- 第 11 条 Trigger From Anywhere:小 Agent 可以通过 Slack、邮件、短信等任意渠道被触发、并用同一渠道回复;正是因为 Agent 小、边界清楚,才敢于让它们接触高风险工具并接受人工审批。
落地建议:今天就能开始的三件事
- 先盘点再拆解:审视你现有的 Agent,把超过 20 步的流程按业务域拆成多个 3–10 步的小 Agent,每个 Agent 只暴露最小工具集,并让确定性代码负责编排与串联(参考 content/brief-history-of-software.md 的 deploybot 时序)。
- 为每个小 Agent 写测试:仿照 workshops/2025-05/final/baml_src/agent.baml 中的
HelloWorld、LongMath、MathOperationWithClarification,用结构化断言覆盖"正常路径、多步路径、需澄清路径、澄清后恢复路径",把 LLM 行为约束在可验证的范围内。 - 把"危险操作"交给人与确定性代码:参照 workshops/2025-05/final/src/agent.ts 中
divide的处理方式,为高风险工具设计跳出循环、请求人工审批的控制流,而不是把审批逻辑塞进 prompt。
最后回到第 10 条的本质:Agent 只是更大、更确定性系统中的一个构件。刻意控制每个 Agent 的规模与范围,只在能维持质量的前提下渐进扩张,并持续贴近模型能力边界——这套纪律,正是把 LLM 软件从"演示级"推向"能交付到生产客户手中"的关键一步。
- 文档
- 教程
- 人工智能
- 大模型
- AI Agent
【免费下载链接】12-factor-agents
What are the principles we can use to build LLM-powered software that is actually good enough to put in the hands of production customers?
相关推荐
12-Factor Agents:构建生产级LLM决策系统的新范式
12 Factor Agents:构建生产级LLM决策系统的新范式 你还在为LLM应用的可靠性和维护头疼吗?传统开发模式下,智能决策系统往往面临控制流混乱、状态
文档教程人工智能大模型AI Agent5分钟上手!repvit_m2_3.dist_300e_in1k图像分类完整代码示例 🚀
5分钟上手!repvit_m2_3.dist_300e_in1k图像分类完整代码示例 🚀 想要快速上手 图像分类 吗?今天我将为你详细介绍如何在5分钟内使用
12-Factor Agents微服务架构:小型专注代理的设计哲学
12 Factor Agents微服务架构:小型专注代理的设计哲学 引言:为什么我们需要小型专注的AI代理? 在构建生产级LLM应用时,你是否遇到过这样的困境:
文档教程人工智能大模型AI Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考