https://github.com/humanlayer/12-factor-agents 项目解析

下面这 repo 不是一个“框架”,而是一份工程实践蓝图:用 12 个“因子”把 LLM/Agent 做到可上线、可维护、可观测。作者强调:多数所谓“Agent”其实是确定性软件,只在关键节点撒一点 LLM 魔法;与其一把梭的黑盒框架,不如把这些原则模块化地嵌入你现有系统。这是它的核心立场与价值主张。

项目定位与核心主张

  • 定位:受 Heroku《12-Factor App》启发,为“可靠的 LLM 应用/Agent”给出工程原则,而非运行时或 SDK。
  • 主张:真正能上生产的“Agent”大多不是“给个 Prompt + 一袋工具 + 循环直到成功”的自动化魔法,而是以确定性控制流为骨架、LLM 只做少量不可枚举的判断与结构化转换。
  • 状态:当前版本 v1.0,v1.1 在草案分支推进;仓库还附带 workshops 与 packages 样例。
  • 周边:社区正在做 create-12-factor-agent 脚手架,帮助按“12 因子”起 repo,但仍然不是框架

12 个因子(精炼解读)

官方“短版目录”列出 12 个因子,下面按工程落地要点解读。
  1. 自然语言 → 工具调用(Structured Tool Calls)把 LLM 的核心能力视为将 NL 转成结构化 JSON/函数调用。你的业务逻辑仍由确定性代码执行,LLM 只产出“下一步要做什么”的结构化指令。落地:用 JSON Schema / Zod / BAML 约束输出,失败就重试/降级。
  2. 掌控你的 Prompt(Own your prompts)Prompt 属于产品代码的一部分:版本化、评测、回滚、A/B,而不是被某个框架隐藏。配合回放集做离线评估。
  3. 掌控你的上下文窗(Own your context window)不要把“上下文”交给模型自由堆叠。把该写数据库的就写数据库,只把必要的紧凑摘要与“任务状态”送进上下文(见因子 9)。这也是作者提出“上下文工程(Context Engineering)”的语境。
  4. 工具 ≈ 结构化输出(Tools are just structured outputs)“工具调用”本质就是结构化消息纯函数执行:把神秘感去除,统一到你的类型系统与错误处理里。
  5. 统一执行态与业务态(Unify execution & business state)会话/步骤日志(execution state)与业务状态(business state)共识化:落到同一套持久化/事件溯源里,支持重放、恢复、审计、幂等
  6. 启动/暂停/恢复的简单 API(Launch/Pause/Resume)Agent 是长期运行的业务流程,必须能外部可控:HTTP API / Webhook / 队列事件能随时介入暂停、恢复、回滚。
  7. 把“找人”做成工具调用(Contact humans with tool calls)人工复核/审批变成第一等公民的工具调用,能发任务到工单/IM,并把人类反馈纳入同一事件流。
  8. 掌控你的控制流(Own your control flow)控制流归你:用编排器/有向图/状态机明确步骤与回退,不把流程决策完全交给 LLM 循环。作者也举了与 Airflow/Prefect/Dagster 等 DAG 编排类比的上下文。
  9. 把错误压缩进上下文(Compact Errors into Context Window)错误要结构化提炼后放回上下文,避免把长日志直接塞给模型,既省 tokens 又提升可恢复性。
  10. 小而专注的 Agent(Small, Focused Agents)能力/场景切分:若干小 Agent 协作优于一个无所不能的大 Agent。
  11. 随处触发,直达用户所在(Trigger from anywhere)把 Agent 当作可被任何事件触发的组件:HTTP、Cron、队列、产品内按钮,输出到用户当下渠道。
  12. 把 Agent 做成“无状态 reducer”(Stateless reducer)把 Agent 设计成从(事件日志 + 输入)→ 新状态的纯函数。真正的“状态”在你的存储层,Agent 本身易于水平扩展与回放。

上面 1→3→8→12 串起来,就是作者给的“理想循环”:LLM 选下一步(JSON)→ 确定性代码执行 → 结果入上下文/状态 → 循环直到 done。文档在 v1.1 草案里把这个循环的伪代码也写明了。

与《12-Factor App》的呼应

  • “配置外置/版本化”在这套方法里对应 Prompt 与工具定义也要版本化
  • “日志即事件流”对应 把执行态与业务态统一进事件/存储
  • “无状态进程”对应 Agent 作为 reducer,状态留在外部

这仓库里有什么

  • 主文档(README + content/)**:阐述每个因子的动机与做法,并链接相关参考。
  • workshops/packages/:用于实战演练/样例的目录。
  • 版本信息:v1.0 已发布、v1.1 草案分支、跟踪 issue。

适配你的场景(前端/工作流/多媒体编辑)

结合你在 Next.js/React Flow/Node 流程编排与视频编辑里的实践,建议这样落地:

  1. 把“工具”先类型化(因子 1/4)为关键动作(转码、抽帧、TTS、LoRA 选择、任务编排)定义统一的 ToolCall JSON Schema(Zod/TypeScript 类型),LLM 只产出 intent + args,其余交给确定性代码。
  2. Prompt 归档与评测(因子 2)把 Prompt 放进 repo(分环境变量注入变体),对关键节点建立离线评测集(回放真实任务与边界 case),以 PR 门禁做 A/B 与回滚。
  3. 上下文工程(因子 3/9)把完整素材/日志放对象存储+DB,仅把紧凑摘要(失败原因、关键元数据、上一步产出)注入上下文。错误经“提炼器”压缩成结构化摘要再投喂模型。
  4. 状态统一与可回放(因子 5/12)把“聊天/工具调用/结果”作为同一事件流写入(如 Postgres+事件表或 Kafka),Agent 实现成从事件流 → 新事件的纯函数,可 100% 重放。
  5. 控制流外置(因子 8)把主流程建成显式状态机/有向图(你已有 React Flow),让 LLM 只在“不可枚举”的判定点起作用;失败/补偿走确定性分支。
  6. 人类在环(因子 7)把“需要审批/判读”的节点做成 request_human_review 工具,派发到你用的 IM/工单系统,回执进入同一事件流。
  7. 生命周期 API(因子 6/11)以 /agents/:id/{launch|pause|resume} + webhook/cron 触发器把 Agent 暴露出去:可在产品按钮、CI、消息流里触发与管控。

适用与局限

  • 适用:你要强控制、可观测、可审计、能回放的生产级 Agent;不想被某框架限制。
  • 局限不是开箱即用的框架,胶水代码会多;因此社区才做了脚手架 create-12-factor-agent 来“搭骨架”,仍保留完全控制权。

12-factor-agents