Lab Meeting Report · Full Fidelity HTML

12-Factor Agents 组会报告:
从 Agent Demo 到
生产级 LLM 软件

一句话结论:12-Factor Agents 关心的不是“再造一个 Agent 框架”,而是把 LLM 应用里最容易失控的部分变成可设计、可测试、可暂停、可恢复的软件工程对象。

讲述主线

从通用 tool loop 的失控风险出发,依次讲清 prompt、context、structured output、control flow、thread、human-in-the-loop、error compacting、small agents 和 eval-first。正文完整承接新版 Markdown,不做摘要替换。

内容体量

5个模块
32个二级章节
36个代码/图块
73行表格

12-Factor Agents 组会报告:从 Agent Demo 到生产级 LLM 软件

一句话结论:12-Factor Agents 关心的不是“再造一个 Agent 框架”,而是把 LLM 应用里最容易失控的部分变成可设计、可测试、可暂停、可恢复的软件工程对象。

这份报告的目标,是把 12-Factor Agents 讲成一条完整的工程主线:为什么 2025 年大家开始意识到通用 Agent tool loop 不够用;12 个 factor 分别在控制 prompt、context、state、tool、human、error、agent scope 时解决了什么问题;一年后再看,它还缺什么;最后,作为用 AI 做 vibe coding 的开发者,我们到底能从中学到什么。

如果只背 12 条原则,听众很容易把它当成 checklist。这个 checklist 当然有用,但组会里更适合把它读成四组质量杠杆:

质量杠杆关心的问题对应内容
输入输出LLM 每轮到底看什么、按什么规则判断、输出什么Prompt、context、structured output、tool call
控制流谁决定执行、暂停、拒绝、升级给人类deterministic code、human-in-the-loop、control flow
状态生命周期任务如何记录、恢复、审计、复现thread、execution state、业务状态、resume
可靠性规模Agent 如何避免越做越大、越跑越乱compact errors、small focused agents、eval-first

整个报告会反复用一个具体场景来解释这些原则:发票归档 / 报销审批 Agent。这个场景足够普通,也足够暴露问题:用户自然语言很模糊,发票字段可能缺失,归档类别要符合规则,重复发票要审查,高风险操作需要人工确认,外部系统还可能失败。也就是说,它刚好覆盖 12-Factor Agents 想处理的核心难题。

报告结构和时间分配

按照原先设定的比例,本稿分为五个模块:

模块建议篇幅这一部分要讲清楚什么
模块一:什么是 12-Factor Agents40%逐条理解 12 个 factor,并按运行流程重新分组
模块二:为什么提出它20%从 Agent 发展痛点解释 12-factor 出现的必要性
模块三:它在框架中的体现10%看这些原则如何出现在当代 Agent 框架和工具里
模块四:一年后它的边界20%从今天视角讨论它没有充分解决的问题
模块五:开发者能学什么10%落到 vibe coding 和实际 Agent 开发习惯

这五个模块不是平行罗列。它们合起来回答一个问题:

当 Agent 从演示走向真实业务时,开发者到底应该把哪些控制权从“模型和框架黑箱”里拿回来?

模块一先给出完整语言和概念工具;模块二解释为什么这些工程纪律会在 2025 年变得迫切;模块三说明行业其实已经在不同框架中实践类似思想;模块四补上冷静视角,避免把 12-Factor Agents 神化;模块五把讨论收回到开发者自己的工作方式。

听众需要先抓住的四个词

Tool loop:最常见的 Agent demo 结构。模型读上下文,决定调用工具,工具结果再塞回上下文,模型继续决定下一步。它适合演示,但在真实系统里容易变成难调试、难恢复、难审计的黑箱循环。

Thread:一次 Agent 任务从开始到当前的事件记录。它不只是聊天历史,也记录工具结果、人工审批、错误摘要、恢复点和业务状态。后面讲状态统一、暂停恢复、审计复现时,thread 是核心。

Structured output:LLM 不直接“执行工具”,而是输出结构化意图,例如 JSON。真正的执行由确定性代码接管。这个设计把模型的语义判断能力和软件系统的控制能力分开。

Human-in-the-loop:人类介入不是系统失败后的临时聊天,而是被设计进控制流的正式状态。系统应该知道什么时候暂停、问谁、问什么、收到回复后如何恢复。

带着这四个词进入模块一,后面的 12 个 factor 就不会只是概念列表,而会变成一套围绕生产级 Agent 生命周期展开的工程方法。


模块一:什么是 12-Factor Agents

12-Factor Agents 是一套面向生产级 LLM 应用的工程原则。

很多 Agent demo 会把任务目标、工具列表和聊天历史交给 LLM,让模型在一个通用 tool loop 中反复决定下一步。这种方式在演示中很灵活,但进入真实业务后会暴露出几个问题:上下文越来越长,状态难以追踪,错误难以恢复,高风险操作缺少清晰审批,框架内部 prompt 和控制流也不容易调试。12-Factor Agents 要解决的就是这个问题:

典型 Agent demo 的运行方式大致是这样:

flowchart LR A["用户目标"] --> B["把任务目标 / 工具列表 / 聊天历史塞给 LLM"] B --> C["LLM 自己决定下一步"] C --> D{"调用工具?"} D -- "是" --> E["执行工具"] E --> F["工具结果追加进聊天历史"] F --> C D -- "否" --> G["输出最终回答"] C -. "问题" .-> H["上下文越来越长<br/>状态散在聊天记录里<br/>失败和审批难以恢复"]
典型 demo loop 把任务、工具和历史交给 LLM 循环处理,演示灵活,但状态、审批和恢复边界容易变模糊。

这张图的重点是:demo loop 看起来灵活,但很多关键责任都默认交给 LLM 和框架内部循环。任务走远以后,系统很难回答“业务上到哪一步了”“执行状态在哪里”“高风险动作谁批准”“失败后从哪里恢复”。

如何保留 LLM 的语义理解和灵活决策能力,同时把 prompt、context、state、control flow、tool execution、human approval 等关键环节变成可显式设计、可测试、可恢复的软件工程对象。

在 12-Factor Agents 原则下,Agent 更像是一个被软件系统包裹的“下一步决策器”,而不是一个自顾自执行到底的黑箱。它的工作方式可以拆成三层:

开发者负责设计 Agent 的工程边界:维护 prompt 模板,定义工具 schema,决定 thread 记录哪些事件,设计 context 的组织方式,规定哪些动作可以自动执行、哪些动作必须暂停或审批。

LLM 负责运行时的语义判断:读取当前 prompt 和 context,理解用户自然语言、业务事件、工具结果和历史状态,然后输出结构化的下一步动作,例如 classify_invoicerequest_reviewarchive_invoicedone_for_now

确定性代码负责执行和控制流程:预取上下文、调用 LLM、解析结构化输出、执行工具、保存 thread、校验权限、处理错误、暂停/恢复任务,并在必要时把流程升级给业务人员。

业务人员并不是每一步都手动参与,而是在信息缺失、异常情况、高风险操作或授权节点介入。也就是说,12-Factor Agents 不是反自动化,而是把自动化拆成清楚的责任边界:LLM 做判断,代码管流程,人类设计规则并处理关键例外。

12-Factor Agents 规则下,更推荐把同一件事拆成清楚的工程边界:

12-Factor Agents 规则下 Agent 流程图
12-Factor Agents 把 LLM 放在“下一步判断”位置,执行、暂停、升级和恢复都由确定性代码与 Thread 接住。

这里的 thread 可以理解为:一次 Agent 任务从开始到当前为止的事件记录本,它既是流程状态,也是下一轮 LLM 判断的上下文来源。

为什么分成四组讲

12 个 Factor 如果逐条讲,很容易变成清单记忆。这里按照 Agent 的实际运行流程来分组,而不是按编号顺序平铺。

一个 12-Factor Agent 的主流程大致是:

Prompt / Context
  ↓
LLM 输出结构化下一步
  ↓
确定性代码接管控制流
  ↓
执行工具 / 暂停等待 / 升级给人类
  ↓
结果写回 Thread
  ↓
根据 Thread 恢复或继续

因此四组可以这样理解:

分组划分依据包含 Factor
输入输出层LLM 每一轮推理时看什么、按什么规则判断、输出什么F1F2F3F4
控制流与人机协作层代码如何接住 LLM 的结构化输出,决定执行、暂停、拒绝或升级F7F8F11
状态与生命周期层结果如何写回 Thread,任务如何保存、暂停、恢复、复现F5F6F12
可靠性与规模层如何让整个 Agent 系统更稳定、更小、更不容易失控F9F10F13
12-Factor Agents 四层架构图
这张图说明:四组 factor 不是清单分类,而是一次 Agent 运行中从输入输出、控制流、状态生命周期到可靠性规模的工程分层。

这个顺序的好处是:前三组和流程图一一对应,第四组作为横切规范贯穿全局。听众不用记 12 个零散条目,只要顺着一次 Agent 运行过程理解:LLM 怎么被调用,代码怎么接管输出,状态怎么保存恢复,系统怎么变可靠。

第一组:输入输出层

包含 F1F2F3F4

这一组回答:LLM 看什么、按什么规则判断、输出什么。

以发票归档为例,用户最初可能只是说:

帮我把这张发票归档一下,这是接专家用的打车费。

开发者提前维护一个 Prompt 模板,规定 Agent 的职责、规则、可用动作和输出格式:

你是一个发票归档助手。
你的任务是根据用户说明、发票 OCR 结果、校验结果和归档规则,判断下一步动作。

你只能输出以下 intent:
- classify_invoice
- archive_invoice
- request_review
- done_for_now

规则:
- 如果发票信息完整、金额未超限、未重复,可以建议归档。
- 如果类别不确定、金额异常或发现重复发票,必须请求人工复核。
- 不要编造发票字段。
- 输出必须是 JSON。

以下是当前上下文:

{{context}}

请判断下一步。

运行时,系统把当前任务相关信息整理成 context:

<user_request>
帮我把这张发票归档一下,这是接专家用的打车费。
</user_request>

<invoice_ocr>
title: 某某科技有限公司
amount: 238
date: 2026-05-21
item: 出租车服务
</invoice_ocr>

<validation_result>
title_valid: true
duplicate_found: false
amount_within_limit: true
</validation_result>

<policy>
交通类发票可归入差旅费或专家交流交通费,需要根据用途判断。
</policy>

<current_question>
下一步应该做什么?
</current_question>

在 Prompt 和 Context 的共同约束下,LLM 输出结构化结果:

{
  "intent": "classify_invoice",
  "invoice_id": "INV-2026-0521",
  "suggested_category": "专家交流交通费",
  "confidence": 0.91
}

自然语言被理解成业务意图,而工具调用只是结构化 JSON,真正是否归档仍由代码决定。

第二组:控制流与人机协作层

包含 F7F8F11

这一组回答:代码如何接住 LLM 的输出,决定执行、暂停、拒绝或升级。

在发票归档场景中,如果系统发现发票疑似重复,LLM 不应该随便生成一句“请人工看看”,而是输出结构化的人类复核请求:

{
  "intent": "request_review",
  "reviewer_role": "finance_admin",
  "invoice_id": "INV-2026-0521",
  "reason": "该发票疑似重复提交,需要人工确认",
  "options": ["confirm_duplicate", "not_duplicate", "need_more_info"]
}

这体现 F7:人类介入也是一个明确的工具调用。人类不是被随意拉进聊天,而是作为流程中的结构化节点进入系统。

接下来,真正控制流程的是代码:

switch (nextStep.intent) {
  case "request_review":
    const threadId = await store.save(thread)
    await notifyReviewer(nextStep)
    return { status: "paused", threadId }

  case "archive_invoice":
    if (!policyAllows(nextStep.category)) {
      thread.events.push({
        type: "policy_blocked",
        data: "类别不符合政策,不能归档"
      })
      continue
    }

    return archiveInvoice(nextStep)
}

这体现 F8:LLM 只提出下一步,代码决定是否执行、暂停、拒绝或继续循环。LLM 不能绕过政策直接归档,也不能自己宣称“已经联系过人”。

最后,这个流程不要求所有人都回到同一个聊天窗口。Agent 可以从不同入口启动或恢复:

用户上传发票 → 启动 Agent
定时任务扫描文件夹 → 启动 Agent
复核系统提交结果 → 恢复 Agent
财务系统 webhook 返回失败 → 恢复 Agent

例如复核完成后,外部系统可以通过 webhook 恢复任务:

app.post("/webhook/review-completed", async (req, res) => {
  await resumeAgent(req.body.threadId, {
    type: "review_result",
    data: req.body.result
  })

  res.json({ ok: true })
})

这体现 F11:Agent 可以从任何地方触发和恢复,而不是只能待在聊天框里。

Factor在例子中的体现
F7LLM 输出结构化 request_review,把人类复核变成 tool call
F8代码通过 switch 决定执行、暂停、拒绝还是继续
F11上传文件、定时任务、复核 webhook、财务系统 webhook 都能触发或恢复 Agent

第三组:状态与生命周期层

包含 F5F6F12

这一组回答:结果如何写回 Thread,任务如何保存、暂停、恢复、复现。

发票归档流程可以被记录成 thread:

<invoice_uploaded>INV-2026-0521.pdf</invoice_uploaded>
<ocr_result>金额 238,项目 出租车服务</ocr_result>
<validation_result>疑似重复发票</validation_result>
<request_review>请求人工复核</request_review>

这体现 F5:thread 同时记录业务事件和执行进度。看这份记录,既知道业务上发生了什么,也知道流程当前暂停在“等待复核”。

当 Agent 输出 request_review 时,确定性代码保存 thread 并暂停:

if (nextStep.intent === "request_review") {
  const threadId = await store.save(thread)

  await notifyReviewer({
    threadId,
    invoiceId: nextStep.invoice_id,
    reason: nextStep.reason
  })

  return { status: "paused", threadId }
}

复核完成后,外部系统用 threadId 恢复任务:

async function resumeAgent(threadId, reviewResult) {
  const thread = await store.load(threadId)

  thread.events.push({
    type: "review_result",
    data: reviewResult
  })

  return runAgent(thread)
}

这体现 F6:Agent 任务不是一次性聊天,而是一个可以 start、pause、resume 的可恢复程序。

恢复后的 thread 变成:

<invoice_uploaded>INV-2026-0521.pdf</invoice_uploaded>
<ocr_result>金额 238,项目 出租车服务</ocr_result>
<validation_result>疑似重复发票</validation_result>
<request_review>请求人工复核</request_review>
<review_result>确认不是重复发票,可以继续归档</review_result>

然后 Agent 再根据完整 thread 判断下一步:

async function runAgent(thread) {
  const nextStep = await determineNextStep(
    promptTemplate,
    thread.serializeForLLM()
  )

  thread.events.push({
    type: "tool_call",
    data: nextStep
  })

  return handleNextStep(thread, nextStep)
}

这体现 F12:Agent 不依赖隐藏状态,只根据 promptTemplate + thread 计算下一步。换句话说,状态在 thread 里,Agent 是根据状态输出下一步的函数。

Factor在例子中的体现
F5thread 同时记录业务事件和执行进度
F6request_review 时保存并暂停,复核后通过 resumeAgent(threadId, reviewResult) 恢复
F12Agent 不依赖隐藏状态,只根据 promptTemplate + thread 计算下一步

第四组:可靠性与规模层

包含 F9F10,以及附录 F13

这一组回答:如何让整个 Agent 系统更稳定、更小、更不容易失控。

在发票归档场景中,如果归档失败,不应该把完整系统日志丢给 LLM,而应该压缩成:

<archive_error>
reason: category_not_allowed
detail: 当前项目不允许归档为专家交流交通费
suggested_next_steps:
  - 改为差旅费
  - 请求人工复核
</archive_error>

这体现 F9:错误进入上下文,但要压缩成 LLM 可理解、可行动的信息。

同时,发票归档 Agent 不负责整个财务系统。它只负责“读取发票、判断类别、归档或升级复核”。预算审批、付款、审计报表可以由其他模块或其他小 Agent 处理。这体现 F10:小而专。

F13 则体现在上下文构造阶段。LLM 判断发票类别时大概率需要 OCR、查重结果、归档政策、项目类别等信息。与其让 LLM 一轮轮请求这些信息,不如由确定性代码提前取好:

async function buildContext(invoiceId, userRequest) {
  const [ocr, duplicateCheck, policy, projectCategories] = await Promise.all([
    readInvoiceOCR(invoiceId),
    checkDuplicate(invoiceId),
    loadArchivePolicy(),
    loadProjectCategories()
  ])

  return {
    userRequest,
    invoiceOcr: ocr,
    duplicateCheck,
    policy,
    projectCategories
  }
}

再把完整 context 交给 LLM:

const context = await buildContext(invoiceId, userRequest)
const nextStep = await determineNextStep(promptTemplate, context)

这体现 F13:确定性的信息收集由代码提前完成,LLM 专注于判断“这些信息意味着下一步该做什么”。

Factor在例子中的体现
F9把归档失败压缩成 <archive_error>,而不是塞整段日志
F10发票归档 Agent 只负责归档相关小流程,不负责整个财务系统
F13buildContext() 提前读取 OCR、查重、政策、项目类别,再交给 LLM 判断

模块小结

通过这四组原则可以看到,12-Factor Agents 并不是要否定 Agent 的灵活性,而是要把这种灵活性放进明确的软件工程边界中。

它保留 LLM 最有价值的能力:理解自然语言、综合上下文、判断下一步意图;同时把生产系统必须可靠掌控的部分显式化:prompt 由开发者维护,context 由系统组织,工具调用以结构化输出表达,控制流由代码接管,状态沉淀到 thread,错误被压缩进上下文,人类只在必要节点介入。

因此,12-Factor Agents 的真正价值不在于提出某个新框架,而在于给 Agent 工程提供了一套可复用的组织方式:

让 LLM 做语义判断,让代码掌控工程流程,让人类设计边界并处理关键例外。

这样,Agent 才能从演示中的黑箱循环,变成一个可显式设计、可测试、可恢复、可审计的生产级 LLM 软件组件。


模块二:为什么提出 12-Factor Agents

模块一已经回答了“12-Factor Agents 是什么”:它是一套把 Agent 做成生产级 LLM 软件组件的工程原则。模块二要回答另一个问题:为什么 2025 年前后会需要这样一套原则?

答案不是“开发者不会写 Agent”,恰恰相反,是因为开发者已经可以很快写出 Agent demo。真正的问题是:demo 里的 Agent 看起来很聪明,但一旦进入真实业务,就会撞上软件工程里的老问题:流程要可控,状态要可追踪,错误要可恢复,高风险动作要可审批,质量要能稳定复现。

12-Factor Agents 的提出,本质上是一次工程纪律的回归:

当 LLM agent 从演示走向生产,关键不再只是“模型能不能决定下一步”,而是“系统能不能可靠地管理每一个下一步”。

从软件史看 Agent 的承诺

软件系统从来不是一团自由流动的文本,而是由状态、分支、输入、输出和副作用组成的流程。早期程序可以画成流程图,后来的后端服务、数据管道、自动化脚本,本质上也都是一张有向图:满足某个条件,就进入某个节点;某个节点执行完,再进入下一步。

DAG 编排器的价值在于,它没有假装复杂流程不存在,而是把复杂流程显式化。Airflow、Prefect、Dagster、Inngest、Windmill 这类工具都在解决类似问题:任务怎么拆,怎么排队,失败怎么重试,日志怎么看,中断后怎么恢复。

LLM agent 带来的承诺更激进。它似乎在说:能不能少写一点 DAG?能不能只给模型一个目标、一组工具和当前上下文,让模型实时判断下一步?

这个承诺非常诱人。因为很多真实任务并不是固定流程:用户表达会变化,业务条件会变化,工具结果会变化,人类反馈也会变化。让 LLM 参与“下一步判断”,确实可以让软件系统变得更柔软。

问题在于,这种柔软如果没有工程边界,就会变成黑箱。

Tool loop 为什么一开始看起来很美

典型 Agent demo 往往是一个通用 tool loop:

context = [initial_event]

while True:
    next_step = llm.determine_next_step(context)
    context.append(next_step)

    if next_step.intent == "done":
        return next_step.final_answer

    result = execute_tool(next_step)
    context.append(result)

这个循环的魅力在于简单。开发者不需要把所有分支都写死,只要准备好 prompt、工具列表和执行器,LLM 就能在运行时决定:该调用哪个工具、工具参数怎么填、失败后要不要换一条路、什么时候追问用户、什么时候宣称任务完成。

这就是很多 Agent demo 让人眼前一亮的原因。比如模块一的发票归档场景里,用户只说“这是接专家用的打车费”,LLM 能理解这句话和“专家交流交通费”之间的语义关系;如果 OCR 缺字段,它能想到请求补充;如果发现疑似重复,它能提出人工复核。

从产品体验上看,这比传统表单更自然。从工程实现上看,它也比手写所有规则更快。

但这个 demo 模式天然容易让开发者产生一个错觉:既然 LLM 能决定下一步,那是不是可以把流程控制也交给它?

12-Factor Agents 的回答是:不行。LLM 可以参与判断,但不能吞掉工程边界。

真正的问题:不是 Agent 不会走,而是走远后不可控

12-Factor Agents 针对的不是“一步工具调用”问题,而是多步骤 Agent 在生产环境中的失控问题。尤其当任务从 3 步变成 10 步、20 步,当工具结果、错误信息、人类反馈和业务状态不断进入 context,通用 tool loop 会暴露出几个典型问题。

第一,上下文会变长,注意力会变稀。

每一轮工具调用都会把新结果追加进 context。短任务时这没问题,但长任务中,context 会混入用户原始请求、工具调用参数、工具返回结果、错误日志、修正尝试、人类反馈和历史分支。模型不是数据库,它每一轮都要从这些文本里重新判断重点。上下文越长,越容易重复旧错误、忽略关键约束,或者把已经解决的问题当成仍未解决。

这也是模块一强调 F3F9 的原因:context 不是聊天记录垃圾桶,而是 LLM 的主要输入界面。要让 Agent 可靠,必须主动设计 context 的结构,并把错误压缩成可行动的信息。

第二,状态会散落在多个地方。

如果 Agent 的执行状态在内存里,业务状态在数据库里,聊天历史在模型消息里,审批状态又在另一个系统里,那么一旦任务暂停、进程重启或外部 webhook 回来,系统就很难回答三个问题:

这就是模块一里 thread 概念的重要性。12-Factor Agents 并不是为了发明一个新名词,而是要求把“执行进度”和“业务事实”尽量统一进可持久化、可恢复、可复现的事件记录里。

第三,控制流会被框架或模型藏起来。

很多 Agent 框架能快速启动项目,但它们往往也会代管循环、工具选择、消息拼接、重试和中断逻辑。早期这很省事,到了生产阶段却会变成阻碍。因为高风险动作通常不能“模型一选工具,代码立刻执行”。

例如发票归档里,archive_invoice 可能只是低风险动作;但如果换成生产部署、付款审批、客户数据删除,系统必须能在“LLM 选择工具”和“工具实际执行”之间插入权限检查、人工审批、审计记录或暂停点。没有这个粒度,Agent 要么只能做低风险任务,要么就会变成不敢放权的自动化玩具。

第四,质量会卡在 70-80%。

HumanLayer 作者总结过一个常见路径:团队决定做 Agent,选择一个框架快速开始,很快做到 70-80% 的效果;但当它要面对真实客户、真实权限、真实异常和真实 SLA 时,80% 就不够了。继续往上做时,团队发现必须理解甚至逆向工程框架里的 prompt、context、state、flow,最后常常被迫重写。

这里的 70-80% 不是一个严格实验指标,而是生产体验里的质量天花板:demo 可以容忍偶尔答错、卡住或重试;客户功能不能。一个 Web 应用如果 10% 的页面加载失败,没人会说它“基本可用”;同理,一个 Agent 如果 10% 的多步骤任务会走丢、误操作或无法恢复,也不能算生产级。

为什么偏偏是 2025 年

2025 年前后,Agent 工程进入了一个微妙阶段:模型能力、工具调用和框架生态都已经足够成熟,让大家相信 Agent 能进入真实产品;但工程实践还没有完全跟上,导致“会 demo”和“能交付”之间出现落差。

2025 年 Agent 工程压力汇聚图
这张图说明:2025 年的关键变化不是某个框架突然出现,而是模型能力、工具生态和真实业务压力同时汇聚,迫使 Agent 工程从 demo 走向可控交付。

OpenAI 在 2025 年 3 月发布 Responses API、内置工具和 Agents SDK,把工具调用、web search、file search、computer use、多 Agent 编排、tracing 等能力推到更标准的位置。Anthropic 在 2024 年底的《Building effective agents》中,也明确区分了 workflows 和 agents,并强调简单、可组合的模式通常比复杂框架更可靠。

这说明 Agent 不再只是社区 demo,而是模型平台和应用开发者共同推进的主线能力。

同时,开发者已经亲身遇到长上下文和长任务问题。很多人不一定手写过 Agent 框架,但大多用过 agentic coding tools。大家会有类似体验:一开始它很聪明,能快速修改代码、解释错误、运行测试;但对话拖长后,它会遗忘早先约束、重复尝试失败方案,或者需要重新开一个窗口才能恢复效率。

这和 12-Factor Agents 讨论的生产 Agent 是同一类问题:模型能力提升不等于上下文管理自动消失。上下文窗口变长,只是让你能塞更多东西;它不保证模型总能在长历史中抓住最关键的信息。

无 12-Factor 与有 12-Factor 的对比

无 12-Factor 与有 12-Factor 的控制权对比图
这张图说明:12-Factor Agents 的核心价值,是把 prompt、context、tool call、human review、error、lifecycle 和 scope 这些控制权从黑箱循环里拿回工程系统。

继续沿用模块一的发票归档场景。

没有 12-Factor 思维时,团队可能会这样做:把用户请求、OCR 结果和一组财务工具塞给一个通用 Agent,让它在循环里自己决定分类、查重、归档、复核和结束。早期 demo 会很顺,因为大部分样例都是正常发票。到了真实业务里,问题开始出现:

采用 12-Factor 思维后,设计会变成另一种形态:

工程环节无 12-Factor 的做法有 12-Factor 的做法
Prompt使用框架默认 prompt 或散落在代码里把 prompt 当成一等公民维护、评审和测试
Context追加全部聊天和工具结果主动组织成 thread,选择性提供关键信息
Tool callLLM 选择后立即执行LLM 只输出结构化意图,由代码校验和执行
Human review自然语言里临时喊人request_review 是结构化动作,可暂停、可恢复
Error handling把日志原样塞回上下文压缩成 <archive_error> 这类可行动事件
Lifecycle一次长对话跑到底支持 launch、pause、resume 和 webhook 恢复
Scope一个 Agent 管完整财务流程发票归档 Agent 只处理归档相关小流程

这样设计后,LLM 仍然负责最有价值的部分:理解用户自然语言和业务上下文,判断下一步意图。但系统不再把执行权、状态权和审计权交给黑箱循环。代码负责接管结构化输出,人类在关键节点介入,thread 记录完整过程。

这就是从 Agent demo 到生产级 LLM 软件的分界线。

模块小结

12-Factor Agents 之所以出现,是因为 Agent 工程在 2025 年前后走到了一个拐点:做出 demo 变容易了,把 demo 变成可靠产品反而成为主要难题。

传统软件和 DAG 编排器留下的经验是:生产系统必须显式管理流程、状态、错误和恢复。LLM agent 带来的新能力是:可以让模型在局部环节理解语义、吸收反馈、判断下一步。12-Factor Agents 要做的,就是把这两者重新接起来。

因此,它不是要把 Agent 重新关回传统流程图里,而是要给 Agent 加上工程护栏:

LLM 负责让软件更会理解人,软件工程负责让 LLM 的理解能被可靠地使用。


模块三:12-Factor Agents 在当代 Agent 框架中的体现

12-Factor Agents 不是一个新框架,而是一套观察和设计 Agent 系统的工程原则。因此,讨论它和当代 Agent 框架的关系时,重点不是判断“哪个框架实现了 12-Factor Agents”,而是看这些框架分别把哪些工程问题显式化了。

更准确地说,Agent 框架的发展正在从“让 LLM 在通用 tool loop 里自由循环”,转向“让开发者重新拥有 prompt、context、state、control flow、tool execution 和 human approval”。

事件时间线:12-Factor Agents 前后的 Agent 工程演进

这里以本地 git 验证的 2025-03-30 initial commit 作为 12-Factor Agents 的出现分界点。

12-Factor Agents 前后的 Agent 框架演进时间线
这张图说明:12-Factor Agents 不是孤立出现的概念,它前后都嵌在 Agent 框架从对话协作走向状态化、可恢复、可治理的演进脉络里。

提出之前:它不是凭空出现的

时间案例说明能证明什么
2023-09-25Microsoft AutoGenMicrosoft Research 发布 AutoGen,强调 multi-agent conversation,让多个 LLM、工具和人类通过对话协作完成任务早在 2023 年,业界已经开始探索“多个小 Agent 协作”,对应 F10
2024-01-17LangGraphLangChain 发布 LangGraph,用 state、node、edge、conditional edge 表达可循环的 agent runtime通用 tool loop 不够可控,Agent 需要显式控制流,对应 F5F8F12
2025-03-11OpenAI Responses API / Agents SDKOpenAI 发布 Responses API、内置工具、Agents SDK、tracing 等 agent building blocks主流模型平台开始把工具调用、追踪、多 Agent 编排标准化,对应 F1F4F8F10

这一组案例说明:12-Factor Agents 并不是凭空发明的一套概念。它出现之前,AutoGen 已经在处理多 Agent 协作,LangGraph 已经在处理显式控制流和状态,OpenAI 已经在把工具、追踪和 Agent 编排平台化。12-Factor Agents 的贡献,是把这些分散的工程趋势提炼成一套更清晰的原则语言。

提出之后:行业继续朝生产级 Agent 工程演进

时间案例说明和 12-Factor Agents 的呼应
2025-04-09Google Agent Development Kit(ADK)Google 推出开源 ADK,面向 agents 和 multi-agent systems,覆盖 build、interact、evaluate、deploy 生命周期Agent 框架开始从“写一个 Agent”走向“构建、评估、部署多 Agent 系统”,呼应 F10 和生产生命周期
2025-10-22LangGraph 1.0 GALangGraph 1.0 正式发布,强调 durable state、built-in persistence、human-in-the-loop、graph-based execution显式状态、持久化、人类审批成为生产级 Agent 框架的一等能力,呼应 F5F6F7F8
2026-04-15OpenAI Agents SDK 新一代能力OpenAI 更新 Agents SDK,引入 model-native harness、native sandbox execution,让 Agent 能在受控环境中处理文件、命令和长任务Agent 工程继续走向沙箱隔离、长任务恢复、安全执行和生产基础设施,呼应 F6F8F9F12

这一组案例说明:12-Factor Agents 提出之后,行业并没有回到“给 LLM 一个目标然后循环到底”的路线,而是继续加强工程护栏。Google ADK 强调多 Agent 生命周期,LangGraph 1.0 强调持久状态和人类审批,OpenAI Agents SDK 2026 更新则进一步把沙箱、文件系统、长任务和安全执行纳入 Agent 运行时。

前三个例子证明 12-Factor Agents 是对既有工程趋势的总结;后三个例子证明它总结的问题在 2025 年之后继续成为 Agent 框架演进的主线。

几个代表性框架和工具

AutoGen 可以理解为“让多个 Agent 开会协作”的框架。它证明了复杂任务往往不适合交给一个超级 Agent,而更适合拆给多个小 Agent。但它也提醒我们,多 Agent 如果没有清晰分工和终止条件,就会变成更大的黑箱。

LangGraph 可以理解为“给 Agent 画流程图”的框架。它用图来表达状态、步骤和分支,让开发者重新掌握控制流。它最适合说明:生产级 Agent 不能只靠一个无限 tool loop,而要有可追踪、可恢复的流程结构。

OpenAI Agents SDK 可以理解为“官方 Agent 工具箱”。它把工具调用、结构化输出、handoff、人类审批、guardrails、tracing 等能力做成标准组件。它说明 Agent 正在从简单模型调用,变成需要完整运行时支持的软件系统。

Google ADK 可以理解为“面向多 Agent 应用的开发套件”。它关注的不只是写 Agent,还包括交互、评估和部署。它说明 2025 年之后,Agent 框架开始进入完整生命周期管理阶段。

HumanLayer 可以理解为“让 Agent 正式找人审批”的工具。它把人工批准、补充信息和外部渠道交互变成结构化事件,而不是让 Agent 在自然语言里随便喊一句“请人工看看”。

BAML 可以理解为“把 prompt 和输出格式写成代码”的工具。它让开发者显式维护 prompt、输入输出类型和测试,说明 prompt 不应该藏在框架黑箱里,而应该像普通代码一样被管理。

模块小结

当代 Agent 框架的发展方向,正在从“让 LLM 自由循环”转向“让开发者重新拥有工程边界”。

AutoGen 说明多 Agent 协作需求很早就出现了;LangGraph 说明 Agent 需要显式控制流和状态;OpenAI 2025 年的工具发布说明主流平台开始把 Agent building blocks 标准化。12-Factor Agents 正是在这个背景下,把分散实践总结成工程原则。

而 2025 年之后,Google ADK、LangGraph 1.0、OpenAI Agents SDK 新一代能力继续强化多 Agent 生命周期、持久状态、人类审批、沙箱执行和长任务恢复。这说明 12-Factor Agents 关注的问题不是一时热点,而是 Agent 工程长期要解决的核心问题。

框架可以提供能力,但不能替开发者拥有 prompt、context、state 和 control flow。12-Factor Agents 的意义,不是让你拒绝框架,而是让你带着工程边界去使用框架。

本模块引用的框架资料统一放到文末“附录:参考资料”,避免打断正文节奏。


模块四:一年后回看:12-Factor Agents 的边界

一年后回看,12-Factor Agents 的价值仍然很清楚:它不是一个新框架,而是一套把 Agent 拉回软件工程的原则。它提醒开发者,不要把 Agent 做成“LLM + tools + 无限循环”的黑箱,而要重新拥有 prompt、context、state、control flow 和 human approval。

但也正因为它是一套工程原则,而不是一本完整的 Agent 系统教材,所以我们不能把它理解成“所有 Agent 问题的答案”。更准确地说,12-Factor Agents 最擅长解决的是:

如何让一个使用工具、处理流程、需要暂停恢复的 Agent 变得可控、可测、可恢复。

它的边界主要体现在三个方面。

12-Factor Agents 边界地图
这张图说明:12-Factor Agents 最擅长把流程型 Agent 管住;长期自治、系统评估、多 Agent 协作协议和长期记忆治理,则需要在它之上继续补足。

第一,它更适合流程型 Agent,不适合被理解成万能自治 Agent

12-Factor Agents 最适合的场景,是目标相对明确、工具相对明确、风险边界相对明确的任务。

比如前面反复提到的发票归档场景:

用户上传发票
  ↓
系统读取 OCR、查重、归档政策
  ↓
LLM 判断下一步
  ↓
代码决定归档、暂停、复核或结束
  ↓
结果写回 thread

这个场景非常适合 12-Factor Agents。因为它的动作可以被整理成结构化 intent,比如 classify_invoicearchive_invoicerequest_reviewdone_for_now。LLM 负责判断下一步,代码负责控制流程,人类在必要时介入。

但是,如果任务变成开放式探索,情况就复杂很多。比如:

这类任务不是简单地从几个工具里选择下一步。它们需要计划、探索、阶段性总结、反思、终止条件和质量判断。12-Factor Agents 里的很多原则仍然有用,比如管理 context、保存 thread、压缩错误,但它没有完整回答“开放式长期自治 Agent 应该怎样规划和收敛”。

所以第一点边界可以概括为:

12-Factor Agents 很适合把流程型 Agent 做可靠,但不能直接等同于开放式自治 Agent 的完整方法论。

第二,它告诉我们怎样把 Agent 管住,但没有展开怎样证明 Agent 真的变好了

12-Factor Agents 很强调工程结构:prompt 要自己维护,context 要自己组织,状态要写进 thread,控制流要由代码接管。这些都很重要,因为它们能让 Agent 从黑箱变成可调试的软件系统。

但“结构更清楚”不等于“质量已经达标”。

例如发票归档 Agent 看起来已经很工程化了:有 prompt、有 context、有 thread、有人工复核、有错误压缩。但我们仍然要问:

这些问题不能靠感觉回答,而要靠 eval。

可以这样理解:

12-Factor Agents 解决的Eval 要解决的
Agent 的流程是否可控Agent 的结果是否可靠
状态是否能恢复恢复后的判断是否正确
错误是否能压缩进上下文错误恢复成功率是多少
prompt 是否由开发者拥有prompt 改动是否引入回归
tool call 是否结构化tool call 选择是否准确

12-Factor Agents 原文提到很多团队会卡在 70-80% 质量天花板,但它没有系统展开如何用评测集、trace、回归测试和线上指标把质量继续往上推。

所以第二点边界可以概括为:

12-Factor Agents 让 Agent 更容易被调试,但要证明 Agent 真的可靠,还需要 eval-first 的工程习惯。

第三,它强调“小而专”,但没有详细展开小 Agent 之间怎样协作

Factor 10 提出 Small, Focused Agents,这是非常务实的建议。不要做一个什么都管的超级 Agent,而是让每个 Agent 只处理一个清晰的小任务。

比如发票归档 Agent 只负责:

读取发票
判断类别
归档
必要时请求复核

它不负责预算审批,不负责付款,不负责审计报表。这会让上下文更短,职责更清楚,也更容易测试。

但问题是:当系统真的拆成很多小 Agent 以后,新的复杂性会出现。

例如一个完整财务流程里,可能会有:

发票归档 Agent
预算审批 Agent
付款 Agent
审计 Agent
通知 Agent

这时就会出现很多协作问题:

也就是说,“小而专”解决了单个 Agent 失控的问题,但会带来多个 Agent 协作的问题。12-Factor Agents 提出了拆小的方向,但没有详细规定小 Agent 之间的交接协议、共享状态、冲突解决和全局控制。

所以第三点边界可以概括为:

小而专的 Agent 更可靠,但小 Agent 变多以后,还需要清晰的协作协议,否则只是把一个大黑箱拆成多个小黑箱。

模块小结

一年后回看,12-Factor Agents 最重要的意义仍然成立:它把 Agent 从“神秘的自主循环”重新拉回软件工程。它告诉我们,LLM 不应该直接掌控整个业务流程,而应该作为“下一步判断器”嵌入一个可控的软件系统中。

但它也有清楚的适用边界:

边界简单理解
更适合流程型 Agent它擅长让 tool-use / workflow Agent 可靠,不等于开放式长期自治的完整方案
缺少系统 eval 方法它让 Agent 可调试,但还需要评测体系证明 Agent 真的变好
小 Agent 协作未展开它建议小而专,但多个小 Agent 之间还需要交接和协调规则

因此,对 12-Factor Agents 最公平的评价不是“它不完整所以不够好”,而是:

它不是 Agent 工程的终点,而是 Agent 工程化的起点。

它先帮我们把单个 Agent 管住;接下来,还要用 eval、协作协议和更清晰的系统设计,把多个 Agent 管好。

最终可以收束到一句话:

12-Factor Agents 的价值,是让我们不再迷信 Agent 的“自主性”;它的边界,是它主要回答“如何控制 Agent”,而不是回答“如何评价、组织和长期运营整个 Agent 系统”。


模块五:对智能体开发者的启示

前四个模块已经说明:12-Factor Agents 不是一个新框架,而是一套把 Agent 从 demo 拉回生产级软件工程的原则。它的核心价值不在于告诉开发者“用哪个框架”,而在于提醒智能体开发者:不要把 Agent 做成一个由 LLM 自由循环到底的黑箱,而要把 prompt、context、state、control flow、tool execution、human approval 显式设计出来。

对智能体开发者来说,12-Factor Agents 的启示可以概括为一句话:

生产级 Agent 的关键,不是让 LLM 拥有更多自由,而是让 LLM 的自由被可靠的软件系统承接。

智能体开发者的 3 组心智模型
这张图说明:对开发者来说,九条启示可以先压成三组心智模型:怎么开始、怎么控制、怎么交付。

LLM 最擅长的是理解自然语言、综合上下文、判断下一步意图;但真正的生产系统还需要权限、状态、审计、恢复、测试、评估和人工审批。这些不能靠模型“自己记住”,而必须由开发者设计。

第一,不要从“我要做一个 Agent”开始,而要从“哪一段流程需要 LLM 判断”开始

很多 Agent 项目一开始就会问:我要用 LangGraph、AutoGen,还是 OpenAI Agents SDK?但 12-Factor Agents 的提醒是,框架不是第一问题,任务边界才是第一问题。

更好的起点不是:

我要做一个财务 Agent。

而是:

我要做一个发票归档 Agent。
它只负责读取发票、判断类别、决定归档或请求复核。
预算审批、付款、审计报表不在它的职责内。

这就是 Factor 10 的现实意义:小而专的 Agent 更可靠。智能体开发者要先判断:

如果这些问题没有回答清楚,就直接搭 Agent 框架,往往只能得到一个看起来很灵活、实际很难控的 tool loop。

第二,把 LLM 定位成“下一步判断器”,而不是整个系统的主人

模块一反复强调:12-Factor Agents 下的 Agent 更像一个被软件系统包裹的“下一步决策器”。这对智能体开发者非常重要。

LLM 可以判断:

{
  "intent": "request_review",
  "reason": "该发票疑似重复提交,需要人工确认"
}

但它不应该直接拥有完整执行权。真正的系统流程应该是:

LLM 输出结构化意图
  ↓
代码解析 intent
  ↓
代码检查权限、政策、状态和风险
  ↓
低风险动作自动执行
  ↓
高风险动作暂停并请求人工审批
  ↓
结果写回 thread

这意味着智能体开发者要改变一个常见想法:Agent 不是“LLM + 一堆工具 + 自动循环”。更准确地说,Agent 是:

Prompt + Context + LLM 判断 + Structured Output + Deterministic Control Flow + Persistent State

LLM 负责语义判断,代码负责工程控制。两者缺一不可。

第三,Prompt 和 Context 必须由开发者拥有

生产级 Agent 最容易失控的地方,往往不是模型不会回答,而是模型看到的输入不稳定。

如果 prompt 藏在框架默认配置里,开发者就很难知道模型到底被怎样约束;如果 context 只是不断追加聊天历史和工具结果,模型就会在长任务里逐渐失焦。

所以智能体开发者必须把 prompt 和 context 当成一等工程对象。

Prompt 要明确规定:

Context 要主动组织,而不是简单堆叠。例如发票归档 Agent 的 context 不应是完整聊天记录,而应是结构化事实:

<user_request>
帮我把这张发票归档一下,这是接专家用的打车费。
</user_request>

<invoice_ocr>
amount: 238
item: 出租车服务
date: 2026-05-21
</invoice_ocr>

<duplicate_check>
duplicate_found: false
</duplicate_check>

<policy>
交通类发票可归入差旅费或专家交流交通费,需要根据用途判断。
</policy>

这样 LLM 才是在读取“业务状态”,而不是在一堆噪音里猜重点。

第四,工具调用不是魔法,而是结构化输出

智能体开发者要理解 Factor 4 的关键含义:工具调用本质上不是“模型真的执行了工具”,而是模型输出了一段结构化数据,代码再决定怎么处理。

例如:

{
  "intent": "archive_invoice",
  "invoice_id": "INV-2026-0521",
  "category": "专家交流交通费",
  "confidence": 0.91
}

这只是一个意图,不是已经完成归档。

代码仍然要检查:

这能避免一个危险误解:不是 LLM “调用了工具”,系统就必须立刻执行。工具执行权始终应该在确定性代码手里。

第五,Agent 必须能暂停、恢复和审计

生产级 Agent 与 demo Agent 的一个重要分界线是:demo 可以靠一次长对话跑到底,生产系统不行。

真实业务里经常会出现:

因此,智能体开发者必须设计 thread 或 event log,把业务事实和执行进度统一记录下来。

例如:

<invoice_uploaded>INV-2026-0521.pdf</invoice_uploaded>
<ocr_result>金额 238,项目 出租车服务</ocr_result>
<duplicate_check>未发现重复</duplicate_check>
<classify_invoice>建议归为专家交流交通费</classify_invoice>
<request_review>请求财务管理员复核</request_review>

这份 thread 同时回答两个问题:

业务上发生了什么?
Agent 执行到哪里了?

有了 thread,Agent 才能 pause / resume,才能在失败后恢复,才能被审计,才能复现过去的判断过程。

第六,人类介入要成为正式流程,而不是临时聊天

很多 Agent 系统会在遇到不确定情况时输出一句自然语言:“建议人工确认。”这在 demo 中可以,但在生产系统中不够。

12-Factor Agents 的启示是:人类介入也应该是结构化 tool call。

例如:

{
  "intent": "request_review",
  "reviewer_role": "finance_admin",
  "invoice_id": "INV-2026-0521",
  "reason": "该发票疑似重复提交",
  "options": ["confirm_duplicate", "not_duplicate", "need_more_info"]
}

这带来几个好处:

智能体开发者要把 human-in-the-loop 当成系统设计的一部分,而不是失败后的补丁。

第七,错误要压缩进上下文,而不是把日志倒给模型

Agent 的“自我修复”能力建立在一个前提上:模型看到的是可理解、可行动的错误信息。

如果归档接口失败,不应该把完整堆栈和系统日志全部塞回 context,而应该整理成:

<archive_error>
reason: category_not_allowed
detail: 当前项目不允许归档为专家交流交通费
suggested_next_steps:
  - 改为差旅费
  - 请求人工复核
</archive_error>

这体现了 Factor 9:错误要进入上下文,但必须经过压缩。

智能体开发者要为每类错误设计摘要格式,例如:

否则,Agent 很容易在长日志中反复尝试同一个错误方案,进入失控循环。

第八,小 Agent 需要协作协议

模块四已经指出,Small, Focused Agents 很重要,但拆小以后会带来新问题。智能体开发者不能只说“我们把大 Agent 拆成多个小 Agent”,还要设计它们之间如何协作。

例如完整财务流程可能包含:

发票归档 Agent
预算审批 Agent
付款 Agent
审计 Agent
通知 Agent

这时需要回答:

所以,“小而专”只是第一步。真正的生产级多 Agent 系统,还需要交接协议、共享状态策略、冲突解决机制和全局控制流。

第九,eval-first 是从“可调试”走向“可交付”的关键

12-Factor Agents 能让 Agent 更可控、更可调试,但这不等于 Agent 已经可靠。模块四已经指出:要证明 Agent 真的变好,还需要 eval。

智能体开发者应该为 Agent 建立评估体系:

要评估的问题示例
intent 是否选对该请求人工复核时,有没有误归档
参数是否正确发票 ID、类别、金额是否填对
边界条件是否稳定OCR 缺字段、重复发票、金额异常时是否正确处理
错误恢复是否有效工具失败后是否能选择合理下一步
prompt 改动是否回归新 prompt 是否破坏旧案例
人工审批是否正确接入审批结果是否写回 thread 并恢复流程

没有 eval,Agent 很容易停在“看起来 70-80% 可用”的阶段。有 eval,开发者才知道每次 prompt、context、schema 或控制流改动,到底让系统变好了还是变坏了。

模块小结

对智能体开发者来说,12-Factor Agents 最大的启示不是某个具体技术点,而是一种工程姿态:

不要迷信 Agent 的自主性,要设计 Agent 的可控性。

生产级 Agent 不是让 LLM 自由地在工具之间无限循环,而是把 LLM 放进一个清晰的软件系统中:

开发者定义边界
  ↓
系统组织 context
  ↓
LLM 判断下一步
  ↓
结构化输出 intent
  ↓
确定性代码接管执行
  ↓
thread 记录状态
  ↓
必要时暂停并联系人类
  ↓
eval 持续验证质量

因此,一个成熟的智能体开发者,不只是会调用模型 API 或使用 Agent 框架的人,而是能设计完整 Agent 生命周期的人:能控制上下文、管理状态、定义工具边界、处理错误、接入人类审批、拆分小 Agent,并用 eval 证明系统真的可靠。

最终可以收束为一句话:

Agent 工程的关键,不是让 AI 看起来更像自主智能,而是让 AI 的判断能够被软件工程可靠地使用。


总结:12-Factor Agents 真正改变的是控制权意识

回到开头的问题:12-Factor Agents 到底想解决什么?

它想解决的不是“怎样让 Agent 看起来更聪明”,而是“怎样让 LLM 的判断可以被可靠地放进真实软件系统”。这两件事差别很大。前者追求演示效果,后者关心失败后的恢复、上线后的审计、权限边界、状态一致性、评估回归和长期维护。

所以,这份报告可以用三句话收束:

  1. LLM 适合做语义判断,不适合独自拥有整个控制流。 它可以判断用户想归档哪张发票、下一步该不该请求复核、错误后应该换一个方案;但真正的执行、权限、暂停、恢复和审计,应该交给确定性代码。
  2. Agent 的可靠性来自显式工程对象。 Prompt 要能维护,context 要能组织,tool call 要能校验,thread 要能复现,错误要能压缩,人类审批要能恢复,eval 要能证明改动没有破坏旧能力。
  3. 12-Factor Agents 不是终点,而是生产级 Agent 的最低工程底座。 它把单个 Agent 怎么写清楚了,但多 Agent 协作、持续评估、治理策略、长期记忆和生态标准化,还需要在它之上继续补。

对组会报告来说,最重要的结论不是记住每个 factor 的编号,而是记住它背后的工程姿态:

不要把 Agent 当成一个会自己完成任务的黑箱,而要把它当成一个由软件系统精心约束、记录、恢复和评估的语义决策组件。

这也是它对 vibe coding 开发者的提醒。用 AI 写代码、搭应用、做 Agent,速度确实更快了;但越快越需要把控制权设计清楚。真正能交付的 Agent,不是 prompt 写得最玄的那个,而是失败后还能解释、暂停后还能恢复、上线后还能评估、多人协作时还能维护的那个。

附录:参考资料