12-Factor Agents: Patterns of reliable LLM applications

Jul 3, 2025, 视频: 12-Factor Agents: Patterns of reliable LLM applications — Dex Horthy, HumanLayer (YouTube)


  • 开场与动机

    • 询问现场有多少人做过代理(10 个、100 个)的举手互动,铺垫“大家都在做 agents”的共同经历。
    • 个人经历:最初决定做一个 agent,确定目标后为了快,用各种库堆起来,很快做到 70–80% 质量,足以让 CEO 兴奋、团队扩编。
    • 碰壁:想从 70–80% 冲到更高质量时,发现深陷库的调用栈里,难以追踪 prompt 如何构造、工具如何注入,只能推倒重来;有时还会发现“这根本不是适合 agent 的问题”。
  • 反思案例:DevOps Agent 失败教训

    • 尝试做 DevOps agent:让它读 makefile、执行构建命令。
    • 不断加细 prompt,甚至细到“准确的步骤顺序”,最终意识到:这类任务 90 秒写个 bash 脚本就能搞定——并非所有问题都需要 agent。
  • 田野调研与模式洞察

    • 访谈 100+ 位创始人/工程师,总结出行业里的共性做法。
    • 结论 1:大多数“生产级 agent”其实并不“agentic”,更像普通软件。
    • 结论 2:大家并非重写一切,而是在现有系统里引入一组没有名字、没有定义但行之有效的小型模块化概念。
    • 这些都是“软件工程基本功”,不需要 AI 背景就能运用。
  • “12-Factor Agents” 背景与定位

    • 基于一线实践整理出“AI agents 的 12 个因子”,并开源成文档与代码库,得到社区热烈反馈(快速涨星、多人贡献)。
    • 不是“反框架演讲”,更像是对框架的“需求清单”:让框架更好地服务追求高可靠与高迭代速度的工程师。
  • 核心目标与方法

    • 邀请大家“抛开成见”,从一线软件工程原则出发,重新思考如何打造“真正可靠”的 agents。
    • 本演讲不按编号逐一讲 12 因子,而是打包串讲若干关键主题;详细内容可会后自查。
  • 因子一(本质魔法):句子 → JSON

    • LLM 最神奇的能力与代码/循环/工具无关,而是把自然语言稳健地结构化成 JSON。
    • 后续因子解决“拿到 JSON 之后怎么用”的问题,但“稳定产出 JSON”本身即可立刻融入现有应用。
  • 因子四(观点):将“工具使用”去神秘化

    • 类比“goto 有害”的历史争论,提出“工具使用有害(的抽象)”——不是说不给 agent 外部能力,而是反对把工具想象成“灵体操控环境”的神秘过程。
    • 现实是:LLM 输出 JSON → 交给确定性代码执行 →(可回灌)。这不过是“JSON + 普通代码 + 循环/分支”,没什么神秘。
  • 因子八(打包主题):掌控你的控制流

    • 回顾软件中的 DAG 思维(if/else 也是图),Airflow/Prefect 等把流程拆成节点以换取可靠性。

    • “朴素 agent 循环”抽象:事件 → prompt → 产生“下一步动作” → 执行 → 把结果放回上下文 → 再喂给模型,直到“完成”。

    • 问题:对长流程不可靠,尤其是超长上下文;即便 API 支持超大上下文,受控、精简的上下文常常更可靠。

    • 将 agent 拆解为 4 个可控部件:

      • 选择下一步的 prompt(决策器)
      • 把模型 JSON 结果交给确定性代码的 switch/loop 执行
      • 构建传给模型的 上下文窗口
      • 驱动整体的 循环与退出条件
    • 当你“拥有控制流”后,可以灵活地 break/切换/汇总/引入评审(LM-as-judge) 等策略。

  • 执行态与业务态的区分与管理

    • 框架常见执行态字段:当前步骤、下一步、重试计数等。

    • 业务态则是“对用户展示的数据、消息历史、等待的审批”等。

    • 目标:像常规服务一样支持 启动/暂停/恢复

    • 实践建议:把 agent 暴露成 REST API 或 MCP 服务

      • 普通请求:加载对应上下文 → 喂给 LLM。
      • 长时工具:能 中断 流程,将 上下文序列化入库(因为上下文本就归你管)。
      • 回调到来:用 state_id 从数据库加载状态 → 把工具结果追加到“程序轨迹” → 再送回 LLM,agent 本身“无感”后台发生过什么。
    • 结论:agents 只是软件;要构建高质量,就必须“拿下内环”(inner loop)的主导权。

  • 因子二:拥有你的 Prompt(以及可试验性)

    • 现成模版能快速打出“还不错”的提示词,但要越过质量门槛,迟早要 手写每一个关键 token
    • 观点:LLM 是“纯函数”(tokens in → tokens out),质量几乎完全取决于你喂进去的 tokens。
    • 方法:多尝试、多旋钮、多评测,系统化探索。
  • 上下文构建的主导权(Context Engineering)

    • 不要被特定消息格式束缚:可把“到目前为止发生了什么”压成 一条 user 消息 或放进 system,自由地建模事件流/线程模型并序列化。
    • 关键在 密度与清晰度:每个 token 都要物尽其用。
    • 广义“上下文工程”= prompt + memory + RAG + 历史 等一切“喂给模型的东西”。
  • 失败恢复与错误上下文处理

    • 当模型调用了错误的工具或遇到下游 API 故障,不要“盲目把完整错误堆进上下文”让它重试。

    • 实践:

      • 当随后的工具调用成功,清理待处理的错误痕迹;
      • 错误要 摘要化,避免把长堆栈污染上下文;
      • 明确“告诉模型什么”才最有助于下一次成功。
  • 与人协作:把“人与工具的分叉”前置到自然语言层

    • 很多系统在最初输出就需要在“工具调用”与“回人类消息”之间选择。
    • 将这个选择推到 自然语言首 token(例如“我完成了/我需要澄清/我需要经理介入”),模型更擅长在自然语言上表达意图,也更利于后续分流。
    • 由此形成包含人类输入的轨迹与协议,也可扩展到 自动外环(auto outloop) 场景(此处不展开)。
  • 触发与接入的无处不在

    • 让用户 在他们所在之处 与 agent 交互:邮件、Slack、Discord、SMS 等,而不是逼用户开 N 个聊天页签。
  • 小而聚焦的“微型 agents”

    • 方案对比:巨大、长环路的 agent 往往不稳;经验有效的是 “确定性 DAG + 微小 agent 回合(3–10 步)”

    • 实际案例(HumanLayer 内部部署 bot):

      • 绝大部分 CI/CD 为确定性代码;
      • 当 PR 合入、开发环境测试过后,把“发布”阶段交给模型:它提议“先发前端”,人类可自然语言纠正“先发后端”,这会被结构化为下一步 JSON;
      • 后端部署获批并完成后,agent 再回到前端部署;
      • 成功后回到确定性流程执行端到端测试;如失败,交给“回滚 agent”。
    • 规模宣称:100 个工具、20 个步骤 也能驾驭——因为上下文可控、职责清晰。

  • 展望:从“撒点模型”到“全代理化”的渐进式演进

    • 现状:在主要是确定性的系统里“撒”小块 LLM 能力;
    • 随模型能力提升,LLM 可承接更大段落,直至某个 API/管线完全由 agent 驱动;
    • 即便如此,工程可靠性 仍靠“上下文与控制流的精细工程”取胜。
    • 经验法:寻找“模型刚好不太稳”的边界任务,通过工程化手段把它做稳,就能造出“超越同行的魔法”。
  • 状态观:agent 应“无状态”,状态归你管

    • 借由“reducer/transducer”梗强调:agent 自身应当 无状态,把状态外置,完全由你掌控。
  • 抽象仍在演化:框架 vs 库

    • 参考历史讨论:是追求抽象、还是允许一定重复?
    • 方向感:与其套一层不透明封装,不如提供类似 shadcn可脚手架、可完全自持 的“create 12-factor agent”风格起步方案。
  • 总结要点

    • Agents 是软件:会写 switch/while 的人都能上手。
    • LLM 是无状态纯函数:关键是把“对的东西”塞进上下文,换取“稳的输出”。
    • 掌控状态与控制流:为灵活性与可靠性买单。
    • 在人机协作中取胜:让 agent 与人高效协作。
    • 把难点留给自己:工具应替你挡住“非 AI 的繁琐”,让你专注于 prompt、流程与 token 质量这些“真正的 AI 难题”。
  • 尾声与在做的事

    • 演讲者经营一家小公司,多数工作与思考开源共享,但也在做一些“重要但无趣”的基础设施以减负。
    • 正在推进 A2 协议,希望促成“agent 如何联系人的”行业收敛。
    • 个人热爱自动化,已为找房、公司内部业务等做了大量 agents。
    • 号召与致谢:欢迎会后交流,继续一起把东西造出来。

注:以下要点严格按视频叙述顺序梳理,时间段为近似区间,信息主要来源于视频原文;在涉及通用概念或案例时,附上外链以便核验与延伸。

  • [00:02–00:34] 开场与“造 Agent 的共同经历”

    • 与会者互动:有多少人在做 agents?做过 10+ / 100+ 个的也有。
    • 引出主题:很多团队把 agent 做到 70–80% 质量时就“卡住”了——CEO 被 demo 激动、团队扩编,但要继续提升就很痛苦。
  • [00:34–01:08] 框架/库导致的“黑箱”复杂度

    • 遇到问题:为了追过 80% 质量线,你会在多层调用栈里“反向工程”prompt 与工具调用的来源与拼装方式,难以把控。
    • 常见结局:推倒重来,或承认“这不是适合用 agent 的问题”。
  • [01:08–01:28] DevOps Agent 反例

    • 尝试做“看懂 Makefile、能编译项目”的 DevOps agent,结果步骤全错。不断加 prompt 细节,最后基本变成“精确下发每一步”。
    • 复盘结论:这类任务 90 秒写个 bash 脚本更靠谱——不是所有问题都需要 agent
  • [01:28–02:07] 100+ 个一线 Builder 的访谈观察

    • 生产中的“agent”大多并不很 agentic,本质更像普通软件,但存在一组有效且可复用的工程模式,显著提升 LLM 应用的可靠性。
  • [02:07–02:39] 渐进式引入而非重写

    • 这些模式通常是小而清晰的模块化做法,能直接嵌入既有代码,不需要“从零起步的大重构”。
    • 这不是“AI 专业背景”才能做的事,更多是软件工程基本功
  • [02:22–03:26] 12-Factor Agents 由来与定位

    • 参考 Heroku 的“12-Factor App”精神,整理出12 条构建可靠 LLM 应用的原则,开源合辑得到社区广泛响应(HN 置顶、stars 快速增长)。(12factor.net, humanlayer.dev, Hacker News)
    • 不是“反框架宣言”,更像是框架功能愿望清单:让框架更好地服务对可靠性与迭代速度都有高要求的开发者。
  • [03:26–03:43] 方法论姿态

    • 邀请大家“忘掉成见”,回到一原则:把软件工程中行之有效的做法用于打造“真正可靠”的 agents。
  • [03:43–04:23] 因子示例:Structured Output 是魔法起点

  • [04:23–05:01] 因子4:Tool Use is “Harmful”(语义层面)

    • 不是否定“让模型访问外部世界”的价值;而是指出“工具调用被神秘化”会遮蔽其本质:LLM 输出 JSON → 确定性代码执行 →(可选)结果回填
    • 因而可用普通的循环/分支来组织工具调用,不必神化“工具”。(“Considered harmful”用法源自 Dijkstra “GOTO 语句有害”文章标题的范式。)(Wikipedia, CWI Homepages)
  • [05:01–05:40] 拥有你的控制流:从 DAG 思维到 Agent Loop

    • 代码本来就是图;DAG 编排(Airflow/Prefect 等)通过拆成节点获得可观测性与可靠性。(Apache Airflow, docs.prefect.io, prefect.io)
    • 朴素 agent 循环:LLM 选下一步→执行→把结果并入上下文→继续,直到“完成”。
  • [05:40–06:18] 朴素循环的局限:长上下文 & 稳定性

    • “把所有东西都塞进上下文”在长流程上常不奏效;控制上下文大小与密度通常更可靠。
  • [06:18–07:13] 把 Agent 分解为 4 个部件

    • Prompt(选步骤)Switch(把模型 JSON 交给确定性代码)上下文构建循环与退出条件
    • 当你拥有控制流时,就能插入 “break/summarize/LLM as judge”等策略。
  • [07:13–08:06] 执行态 vs 业务态,Pause/Resume 与可序列化

    • 除了“当前步骤、重试计数”等执行态,还要管理业务态(过往消息、用户可见数据、待审批项)。
    • 最佳实践:把 agent 作为标准 API(REST)或 MCP 服务器来封装;遇到长时工具调用时序列化上下文到数据库,回调携带 state id 继续执行,无缝恢复。(Model Context Protocol, Anthropic, The Verge)
  • [08:06–08:37] 核心宗旨

    • Agents 本质是软件:为了灵活性与可靠性,务必自己掌控内循环
  • [08:37–09:33] 因子2:拥有你的 Prompt(可测可调)

    • 高质量门槛之后,最终会回到“逐 Token 手写/可组合/可评测”的 Prompt 工程
    • LLM 是“纯函数”:输入 Token → 输出 Token;可靠性的关键是“把对的 Token 放进去”。
  • [09:33–10:12] 拥有你的上下文构建

    • 不局限于 OpenAI “messages”格式;可把事件/线程模型自由序列化成一段输入,精准告诉模型“到目前为止发生了什么”。
  • [10:12–10:55] 错误处理 ≠ 盲目堆栈

    • 工具报错时,把“错误+调用”送回模型重试是常见做法,但易“旋涡失控”。
    • 要掌控上下文:成功一次就清理历史错误、只保留浓缩后的关键信号,避免堆栈/日志污染上下文。
  • [10:55–11:34] 用“联系人的工具”把人纳入回路(HITL)

    • 在**“工具调用 vs 与人交流”第一拍**就做清晰区分;把“需要澄清/需要经理批准”等意图落在自然语言 token 上,提升决策的稳定性与可解释性。
    • 对应工程化:在 Slack/Email/SMS 等触达渠道上引入审批/沟通。(humanlayer.dev, Y Combinator)
  • [11:34–12:25] 从任意地方触发,与用户“就地相逢”

    • 让用户在现有工作流里(邮件、Slack、短信等)直接与 agent 交互,而不是开多个“Chat”标签。(humanlayer.dev)
  • [12:25–13:32] 小而专注的 Micro-agents(关键做法)

    • 有效模式:主要流程保持确定性 DAG,把 3–10 步的小 agent loop 嵌入关键分支。
    • 真实用例:HumanLayer 内部部署机器人——CI/CD 多数是确定性;合并通过后,交给模型“决定下一步部署前后端顺序”,人可插话修正,自然语义→下一步 JSON,随后再回到确定性流程(E2E 测试/回滚小 agent 等)。
  • [13:32–14:19] 随模型演进逐步“撒胡椒面”

    • 随着模型可做的“可靠边界”扩大,可逐渐把更多步骤从确定性迁往 agent
    • 经验法:找“模型刚刚够得到但不稳定”的任务,通过工程化(上下文/控制流/评测)把它压到稳定边界内,形成差异化能力。
    • 提到 NotebookLM 的做法,作为“在边界上做好工程化”的示意参考。(Google NotebookLM, blog.google, The Verge)
  • [14:19–15:01] 状态应由你来管:Agent 近似“无状态变换器”

    • Agent 自身保持无状态,把状态外置并可观测/可持久化,你获得最大灵活度。
    • 行业仍在找抽象;“框架 vs 库”的老话题仍适用。
  • [15:01–15:18] 脚手架理念:像 shadcn/ui 一样可接管

    • 与其包一层黑盒,不如生成 scaffold 让开发者全盘接管(提到“create-12-factor-agent”的方向性想法)。
  • [15:18–16:11] 总结五点

    • Agents 是软件;LLM 是无状态纯函数——把“对的上下文”放进去就有更可靠输出
    • 拥有状态与控制流,为灵活性与可靠性服务。
    • 在“模型能力边界”处,通过工程化把不稳定变稳定。
    • 人-机协作常使 agent 更强。
    • 框架应帮忙解决“非 AI 的难点”,让开发者把精力聚焦在 prompt/流控/token 质量上。
  • [16:11–16:48] HumanLayer & A2(Agent-to-Human)方向与收尾

    • 其公司专注“人与 agent 协作”的难题(审批、异步沟通、触达渠道)。提到在做 A2 协议来统一“agent 如何联系到人”的语义。相关理念与落地可参考其产品与文档。(humanlayer.dev, GitHub)

术语与案例延伸(外链)

Tags: AI-Agent