12 Factor 方法论合并知识图谱 / 分组目录 / 12 Factor Agent 体系 / 工具即结构化输出

工具即结构化输出

Agent 体系基础方法原则GB · 12 Factor Agent 体系

What · 是什么

工具只是模型的结构化输出,可无限组合
工具不需要复杂,其核心就是『LLM 输出的结构化数据,用于触发确定性代码』——工具本质上只是结构化输出。
让 LLM『用其中一个工具』,本质上只是让它输出一段我们可以解析成代表这些工具的对象的 JSON,别无玄机。
示例:CreateIssue 类携带 intent='create_issue' 与嵌套的 Issue 对象;SearchIssues 携带 intent='search_issues' 与 query、what_youre_looking_for 查询字段。
模式三步:①LLM 输出结构化 JSON;②确定性代码执行对应动作(如调用外部 API);③结果被捕获并喂回上下文。
这在 LLM 的『决策』与应用的『行动』之间建立了干净分离:LLM 决定做什么,但你的代码控制怎么做。
『LLM 调用了工具』不意味着你必须每次都去执行同一个固定函数——同一意图可以根据业务逻辑走不同实现。
把工具调用想成『模型输出一段描述确定性代码该做什么的 JSON』,会解锁大量灵活性,可与 factor 8 配合。
原文引用 switch 语句:nextStep.intent=='create_payment_link' → stripe.paymentlinks.create;'wait_for_a_while' → 某种 monadic 处理;else → 兜底。
『下一步』不一定原子到『执行纯函数并返回结果』,模型输出的 JSON 可以驱动更复杂、更长的控制流。
原文链接了 plain prompting vs tool calling vs JSON mode vs constrained generation 等路线权衡的资源,但声明不展开讨论。

Why · 为什么

原理 · Principle

决策与执行解耦:LLM 只输出『意图+参数』的 JSON,具体怎么执行由确定代码决定,行为可预测、可审计。

同样的 JSON 意图可以映射到不同实现,随业务变化灵活调整,不锁死工具与函数的严格一一对应,实现可独立演进。

为掌控控制流铺路:既然工具是 JSON,你就可以在 JSON 与执行之间插入审批、暂停、重试等逻辑(factor 8)。

结构化输出天然可测试:schema 明确、解析稳定,比解析自由文本可靠得多,回归有保障,错误能准确定位到字段。

符合『Agent 循环』第一步的标准化产出,后续每一步(执行、回写、再决策)都能被确定性处理,全链路可控。

How · 怎么做

用数据类(Python class 或 BAML class)定义每个工具:intent 字段加业务参数,如 CreateIssue 内含 intent 与嵌套的 Issue 对象。
让 LLM 基于 schema 输出 JSON,用 BAML 的 type 联合(如 HumanTools | CalculatorTools)约束可选项,从类型上杜绝未知意图。
在确定性代码里按 intent 做 switch/if 分发:命中执行外部 API,未命中走 else 兜底,保证流程不中断。
把每次工具调用的结果捕获并追加回上下文(thread.events),供模型决定下一步,形成闭环,执行信息不丢失。
模板实现:agent.ts 的 handleNextStep 对 add/subtract/multiply/divide 分别计算并把 tool_response 事件 push 进 thread。
用 @description 注解给 BAML 类补充行为约束,例如 ProcessRefund 注明『退款前必须先向经理请求批准』。
用 @description 给字段补充说明,例如 DoneForNow.message 注明『写给用户的工作完成说明』。
把工具输出与意图组合成联合类型返回(DetermineNextStep -> HumanTools | CalculatorTools | CustomerSupportTools),让类型系统承接工具集。

案例 · Cases

代表性案例
CreateIssue / SearchIssues 两个工具类的定义示例,intent 字段加业务参数结构。
Issue 嵌套对象:title/description/team_id/assignee_id 四个字段的完整定义。
switch 语句示例:nextStep.intent == 'create_payment_link' → stripe.paymentlinks.create 的执行分支。
模板 BAML 工具:AddTool/SubtractTool/MultiplyTool/DivideTool 四个计算器类(intent add/subtract/multiply/divide,a/b 为 int|float)。
ProcessRefund 类:intent 'process_refund',含 order_id/amount/reason,注解要求退款前请求经理批准。
type CalculatorTools = AddTool | SubtractTool | MultiplyTool | DivideTool 的联合类型定义。
模板 agent.ts 的 handleNextStep:按 intent 分发并返回更新后的 thread,供外层循环继续。
原文链接资源:boundaryml schema-aligned parsing、Vellum 的 function calling vs structured outputs vs JSON mode、LlamaIndex 对比。

反模式 · Anti-patterns

相关边

实践资源 · 源码引用

路径说明
08-source/agent-content/factor-04-tools-are-structured-outputs.md原文完整内容:工具即结构化输出的三步模式
08-source/agent-packages/create-12-factor-agent/template/baml_src/tool_calculator.baml模板计算器工具类:Add/Subtract/Multiply/Divide
08-source/agent-packages/create-12-factor-agent/template/baml_src/agent.baml模板工具联合类型与函数签名(HumanTools/CalculatorTools/CustomerSupportTools)
08-source/agent-packages/create-12-factor-agent/template/src/agent.ts模板 handleNextStep 按 intent 分发执行的确定性代码