作者:Dex Horthy (HumanLayer)
仓库:https://github.com/humanlayer/12-factor-agents
灵感来源:12 Factor Apps
本地路径:/Users/zhaoweiguo/6ai/opensources/12-factor-agents
核心观点
大多数生产级 Agent 并非”给 LLM 一堆工具让它循环”,而是以软件为主体,LLM 在关键节点介入。框架能帮你快速到 70-80% 质量,但突破 80% 往往需要反向工程框架本身——不如从一开始就掌控核心原则。
最快把高质量 AI 软件交到用户手中的方式,是把 Agent 构建的小型模块化概念融入现有产品,而不是全量重写。
12 条原则
1. 自然语言 → 工具调用(Natural Language to Tool Calls)
将用户意图原子化地转换为结构化工具调用 JSON。这是 Agent 最基础的能力单元。
2. 掌控你的 Prompt(Own Your Prompts)
不要把 Prompt 工程外包给框架。框架的黑盒 Agent(role=..., goal=...) 让你失去对模型输入的控制。直接写 Prompt,版本化管理。
3. 掌控你的上下文窗口(Own Your Context Window)
在 Agent 的任意时刻,你给 LLM 的输入就是”到目前为止发生了什么,下一步是什么”
上下文工程 = Prompt + 检索文档 + 历史工具调用结果 + Memory + 输出格式指令。自己控制什么进入上下文,而不是让框架决定。
4. 工具只是结构化输出(Tools Are Just Structured Outputs)
工具调用本质上是 LLM 输出的 JSON,触发确定性代码执行。不需要复杂抽象,一个 intent 字段 + 参数就够了。
5. 统一执行状态与业务状态(Unify Execution State and Business State)
- 执行状态:当前步骤、等待状态、重试次数
- 业务状态:工具调用历史、消息列表
尽量从上下文窗口推断执行状态,避免维护两套独立状态系统。
6. 简单 API 实现启动/暂停/恢复(Launch/Pause/Resume with Simple APIs)
Agent 应支持通过简单 API 启动、暂停(等待长时操作)、通过 webhook 恢复。依赖 Factor 5(统一状态)和 Factor 8(掌控控制流)。
7. 用工具调用联系人类(Contact Humans with Tool Calls)
Human-in-the-loop 不应是特殊路径,而是普通工具调用。request_approval、ask_clarification 和其他工具调用一样处理,统一进入控制流。
8. 掌控你的控制流(Own Your Control Flow)
自己写循环,不要让框架决定何时继续、何时暂停。可以在控制流中插入:
- 工具结果的摘要/缓存
- LLM-as-judge 验证
- 上下文压缩
- 日志/追踪/指标
- 客户端限流
- 持久化睡眠/等待事件
9. 将错误压缩进上下文窗口(Compact Errors into Context Window)
工具调用失败时,把错误信息追加到上下文,让 LLM 自我修复。这是”自愈”能力的最小实现,不需要其他 11 条原则就能单独使用。
10. 小而专注的 Agent(Small, Focused Agents)
每个 Agent 只做一件事,3-20 步为宜。上下文越长,LLM 越容易迷失。小 Agent 带来:
- 可管理的上下文窗口
- 清晰的职责边界
- 更高的可靠性
- 更容易测试和调试
11. 从任何地方触发,在用户所在之处响应(Trigger from Anywhere)
支持从 Slack、Email、SMS、Webhook、Cron 等任意渠道触发 Agent,并通过相同渠道响应。让 Agent 成为真正的”数字同事”。
12. 让 Agent 成为无状态 Reducer(Stateless Reducer)
Agent = foldl(左折叠)。给定初始事件和历史,Agent 是一个纯函数:(state, event) → next_state。无状态设计使 Agent 可水平扩展、易于测试。
附录 13. 预取所有可能需要的上下文(Pre-fetch Context)
在 Agent 开始执行前,一次性拉取所有可能用到的上下文,而不是在循环中按需获取。减少延迟,避免上下文碎片化。
核心循环模式
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
try:
result = await execute_step(next_step)
context.append(result)
except Exception as e:
context.append({"type": "error", "data": str(e)})与框架的关系
作者明确:不是反对框架,框架加速了 AI 生态。但对于需要深度控制的生产级产品,理解这 12 条原则比依赖框架更重要。框架可以给你 12 条原则的实现,但你需要知道它们在哪里。
相关链接
- agent-harness-anatomy — Agent Harness 六大组件(与 Factor 3/8 高度相关)
- agent-continual-learning — Agent 持续学习三层框架(与 Factor 3/5 呼应)
- openclaw-sessions-tools — OpenClaw 的 sessions_spawn 实现了 Factor 6/11
- hermes-agent — 自我进化 Agent,体现 Factor 10/12
附录:灵感来源 — 云原生 12-Factor App
原文:https://12factor.net/ | 作者:Adam Wiggins(Heroku)| 2017
12-Factor Agents 的命名和结构直接借鉴自云原生领域的经典方法论。对照阅读有助于理解 Agent 版本的设计意图。
| # | 云原生 12-Factor | 一句话 |
|---|---|---|
| I | Codebase | 一份代码库,多份部署 |
| II | Dependencies | 显式声明并隔离依赖 |
| III | Config | 配置存储在环境变量中 |
| IV | Backing Services | 把后端服务当作附加资源 |
| V | Build, Release, Run | 严格分离构建和运行阶段 |
| VI | Processes | 以无状态进程执行 app |
| VII | Port Binding | 通过端口绑定暴露服务 |
| VIII | Concurrency | 通过进程模型扩展 |
| IX | Disposability | 快速启动和优雅关闭 |
| X | Dev/Prod Parity | 保持开发、预发、生产环境一致 |
| XI | Logs | 把日志当作事件流 |
| XII | Admin Processes | 用一次性进程运行管理任务 |
与 Agent 版本的对应关系:
- Factor VI(无状态进程)→ Agent Factor 12(无状态 Reducer)
- Factor III(Config in env)→ Agent Factor 2/3(掌控 Prompt 和上下文)
- Factor IX(Disposability)→ Agent Factor 6(启动/暂停/恢复)
- Factor XI(Logs as streams)→ Agent Factor 8(掌控控制流,插入日志/追踪)