Agent 工程体系 · 第 2/98 篇。内容以 2026 年 9 月可验证的公开规范和稳定接口为基线;框架版本敏感能力会明确标注,不把实验行为写成通用保证。
Agent、工作流与普通程序:自治边界、确定性和正确选型
在 AI 系统中,“普通程序”“工作流”和“Agent”经常被放在同一张架构图里,但它们并不是同一层次的概念。
普通程序解决的是:给定输入后,按照预先编写的规则执行什么步骤。
工作流解决的是:把多个步骤、模型调用、工具调用和校验节点组织成一条预先设计的执行路径。
Agent 解决的是:在目标、约束和可用工具给定后,由模型在运行时决定下一步做什么,并通过观察结果继续推进任务。
三者都可以调用大模型,也都可以包含循环、分支、状态和人工审批。真正的区别不在于“是否使用了 LLM”,而在于:
下一步行动是由程序代码预先决定,还是由模型根据运行时信息动态决定。
Anthropic 将工作流描述为由预定义代码路径编排 LLM 和工具的系统,将 Agent 描述为由 LLM 动态控制过程和工具使用的系统。OpenAI 的 Agents SDK 文档则把 Agent 概括为能够规划、调用工具、协作并维护足够状态以完成多步任务的应用。(anthropic.com)
这一区别决定了系统的自治边界、可预测性、测试方式、故障处理方式和最终成本。
一、先建立三个基本模型
1. 普通程序:控制流由代码决定
普通程序可以抽象为一个状态转换函数:
其中:
- 是第 步的程序状态;
- 是当前输入或外部事件;
- 是由代码实现的确定性或显式随机函数;
- 是下一状态。
例如,一个订单支付程序可能固定执行:
读取订单
→ 校验库存
→ 创建支付单
→ 调用支付网关
→ 更新订单状态
→ 发送通知
代码已经决定了:
- 哪些步骤存在;
- 步骤之间的顺序;
- 哪些条件会进入哪个分支;
- 哪些错误可以重试;
- 什么时候结束。
即使其中某一步调用了大模型,例如让模型生成一封通知邮件,程序的主控制流仍然是确定的。模型只负责某个节点内部的输出,不负责决定整个任务的执行路径。
可以将普通程序的决策表示为:
这里的策略 是程序员写下来的分支、循环和调用关系。
2. 工作流:控制流由代码编排,模型负责局部判断
工作流是普通程序的扩展。它通常增加了:
- 一个或多个 LLM 调用;
- 工具调用;
- 结构化输出;
- 节点间的数据传递;
- 重试、超时和人工审批;
- 并行执行和结果聚合。
但它仍然具有一个关键特征:
整体执行图在系统设计时已经确定,运行时只是在这张图上选择允许的路径。
例如,客服工单分类工作流可以设计成:
用户问题
↓
分类
├── 退款 → 退款流程
├── 技术问题 → 技术排障流程
└── 其他 → 通用问答流程
分类节点可以由 LLM 完成,但“分类之后只能进入这三个分支”是程序定义的。
形式化地说,工作流拥有一个预定义有向图:
其中:
- 是节点集合,例如
classify、refund、support; - 是允许的边集合,例如
classify → refund; - 每次状态转移都必须满足:
模型可能参与决定某个节点的输出,甚至参与选择一条边,但它不能任意创建新的节点、工具或转移关系。
因此,工作流的动态性是受限动态性:
模型可以在允许集合 中做判断,但不能把任意动作加入这个集合。
3. Agent:控制流本身成为模型决策对象
Agent 的核心不是“会聊天”,也不是“有记忆”,而是模型参与决定后续行动。
一个典型 Agent 运行循环可以写成:
其中:
- 是目标;
- 是约束和策略;
- 是模型看到的观察结果;
- 是模型选择的动作;
- 是工具或环境返回的结果;
- 是更新后的状态。
Agent 不一定要拥有无限权限,也不一定要长时间运行。只要模型能够在运行时决定:
- 是否调用工具;
- 调用哪个工具;
- 先做哪一步;
- 是否继续调查;
- 是否改变计划;
- 是否请求人工帮助;
- 是否结束任务;
它就已经具有 Agent 性质。
OpenAI 对 Agent 运行时的描述包括工具循环、Agent 间切换、状态维护以及在完成或等待审批时停止运行。(developers.openai.com)
二、自治边界到底是什么
“自治”不是一个二元属性。系统不是只有“完全自动”和“完全手动”两种状态,而是存在多个可以独立控制的自治维度。
1. 任务分解自治
系统是否自行决定把任务拆成哪些子任务?
固定的:
先提取合同条款,再计算金额,最后生成摘要。
这是工作流。
动态的:
先检查合同是否包含违约条款;
如果存在,再查询历史案例;
如果金额超过阈值,再请求法务复核。
如果这些后续步骤由模型根据观察结果临时决定,则属于 Agent 的任务分解自治。
2. 工具选择自治
系统是否由模型选择工具?
固定调用:
customer = get_customer(user_id)
orders = get_orders(user_id)
这是普通程序或工作流。
动态选择:
模型根据问题决定调用:
- 查询订单工具
- 查询物流工具
- 查询退款政策工具
- 创建退款申请工具
这是工具选择自治。
但要注意:允许模型选择工具,不等于允许模型任意操作。
工具集合仍然可以由程序限制:
ALLOWED_TOOLS = {
"get_order",
"get_shipping_status",
"get_refund_policy",
}
如果 Agent 不能调用写操作工具,它的自治边界就停留在“只读调查”。
3. 执行顺序自治
固定顺序:
查库存 → 查价格 → 计算折扣 → 生成报价
模型只能填充每个节点的参数,这仍然是工作流。
动态顺序:
先查库存还是先查供应商?
是否需要比较两个仓库?
是否需要先确认用户预算?
模型根据当前状态选择顺序,才构成更强的 Agent 自治。
4. 终止自治
终止条件是一个经常被忽略的自治边界。
固定终止:
for step in STEPS:
run(step)
return result
运行次数、结束节点和失败条件都由代码决定。
动态终止:
模型认为证据已经足够,于是结束;
或者认为信息不足,继续搜索;
或者发现风险,需要请求人工确认。
这时,Agent 的“什么时候停止”也是模型决策的一部分。
生产系统不能只依赖模型的自然语言判断。通常需要同时设置:
- 最大循环次数;
- 最大工具调用次数;
- 最大运行时长;
- 最大预算;
- 明确的成功条件;
- 明确的不可恢复失败条件;
- 人工审批节点。
因此,可靠 Agent 不是“让模型自由运行”,而是:
让模型在一个由系统强制限制的行动空间内自治。
三、确定性不等于没有大模型
确定性经常被误解为“系统中不能出现 LLM”。实际上,确定性至少有三种不同含义。
1. 控制流确定性
给定相同状态,下一步执行哪个节点是确定的。
if payment_status == "paid":
send_receipt()
else:
retry_payment()
即使 payment_status 来自模型提取,只要后续分支由代码定义,控制流仍然是显式的。
2. 输出确定性
给定相同输入,输出内容完全相同。
LLM 通常难以提供强输出确定性,即使设置较低随机性,也可能因为模型版本、服务端实现、上下文变化或工具结果变化而产生不同结果。
因此:
- “输出 JSON”不等于输出值确定;
- “使用结构化输出”不等于业务结论正确;
- “temperature 为 0”不等于整个系统可复现。
结构化输出解决的是格式约束,不是语义正确性。
3. 业务结果确定性
给定相同业务事实,系统是否保证最终结果符合规则。
例如,计算税额时:
tax = round(amount * tax_rate, 2)
这是业务结果确定的。
如果让模型回答:
这笔订单应该收多少税?
即使模型多数时候答对,也不能把它当作业务规则执行器,除非后面还有权威规则校验。
四、一个完整算例:退款处理应该选什么
假设需求是:
用户要求退款。系统需要判断订单状态、退款期限和退款金额;金额不超过 100 元时自动退款,超过 100 元时提交人工审批。
方案一:普通程序
如果所有输入字段结构化,规则明确,可以直接写成:
from dataclasses import dataclass
from datetime import date
@dataclass
class RefundRequest:
order_status: str
days_since_purchase: int
amount: float
reason: str
def decide_refund(req: RefundRequest) -> str:
if req.order_status != "paid":
return "reject:not_paid"
if req.days_since_purchase > 7:
return "reject:expired"
if req.amount <= 100:
return "approve:auto"
return "review:human"
cases = [
RefundRequest("paid", 2, 80, "重复购买"),
RefundRequest("paid", 3, 180, "商品损坏"),
RefundRequest("paid", 12, 50, "不想要了"),
]
for case in cases:
print(decide_refund(case))
预期输出:
approve:auto
review:human
reject:expired
每一个结果都可以通过单元测试覆盖。这里没有必要使用 Agent,因为:
- 输入字段明确;
- 判断规则明确;
- 工具调用顺序明确;
- 错误路径明确;
- 不需要探索未知信息。
使用 Agent 反而会引入额外不确定性。
方案二:工作流
现实中的用户可能只说:
这个订单我不想要了,帮我退一下。
系统需要先从自然语言中提取订单号、退款原因和用户意图。可以使用 LLM,但把它限制在工作流节点中:
用户消息
↓
LLM:提取订单号和退款意图
↓
代码:查询订单
↓
代码:查询退款政策
↓
代码:计算是否符合条件
↓
代码:自动退款或进入人工审批
伪代码如下:
def refund_workflow(message: str, user_id: str):
extracted = llm_extract(
message,
schema={
"order_id": "string|null",
"intent": "refund|other",
"reason": "string|null",
},
)
if extracted["intent"] != "refund":
return {"status": "unsupported_intent"}
if not extracted["order_id"]:
return {"status": "need_order_id"}
order = get_order(user_id, extracted["order_id"])
if order.status != "paid":
return {"status": "rejected", "reason": "not_paid"}
policy = get_refund_policy(order.product_id)
if order.days_since_purchase > policy.max_days:
return {"status": "rejected", "reason": "expired"}
if order.amount <= policy.auto_approve_limit:
result = issue_refund(order.id, order.amount)
return {"status": "refunded", "refund_id": result.id}
approval_id = create_human_approval(order.id, order.amount)
return {"status": "waiting_approval", "approval_id": approval_id}
这里 LLM 只负责理解非结构化输入;它没有决定:
- 是否绕过支付状态检查;
- 是否修改退款期限;
- 是否直接发起高金额退款;
- 是否跳过人工审批。
因此它是一个包含 LLM 的确定性工作流。
方案三:Agent
如果需求变成:
处理复杂售后问题。你可以查询订单、物流、商品说明、历史沟通记录和退款政策;必要时联系仓库或转交人工。请自行判断还需要哪些信息。
这时输入通常不完整,所需步骤无法预先枚举。Agent 可能执行:
观察:用户只提供订单号
→ 查询订单
→ 发现订单已签收
→ 查询物流异常记录
→ 发现物流无异常
→ 查询商品售后政策
→ 发现需要判断“质量问题”还是“主观原因”
→ 询问用户补充照片
→ 接收照片
→ 调用图片分析工具
→ 建议退款
→ 发现金额超过阈值
→ 发起人工审批
这里的关键不是步骤多,而是:
- 下一步依赖上一步的发现;
- 可能需要动态增加或减少调查步骤;
- 工具调用顺序不能完全预先写死;
- 系统需要根据中间结果重新规划。
这才是 Agent 的适用边界。
五、工作流和 Agent 的边界不是“有没有循环”
很多工作流也有循环。例如:
for attempt in range(3):
result = call_model()
if valid(result):
break
这不是 Agent。循环本身不能证明存在自治。
判断标准应当是:
循环的下一次动作是否由预先编写的程序决定,还是由模型根据当前观察结果决定。
工作流循环
for page in range(1, 4):
results.extend(search(page))
循环次数和动作都由代码决定。
Agent 循环
while not finished:
observation = collect_observation(state)
action = model_choose_action(observation, tools, constraints)
result = execute(action)
state = update(state, result)
模型可能选择:
{"tool": "search", "arguments": {"query": "..."}}
也可能选择:
{"tool": "ask_user", "arguments": {"question": "..."}}
或者直接返回最终答案。
因此,区分两者不能看“有没有循环”,而要看循环中的策略函数是谁实现的。
六、Agent 的自治必须被状态机约束
一个生产 Agent 至少要有显式状态。推荐把状态分成四类。
1. 任务状态
描述任务本身:
{
"goal": "判断退款资格",
"user_id": "u_123",
"order_id": "o_456",
"status": "investigating"
}
2. 观察状态
描述已经获得的事实:
{
"order_status": "paid",
"delivery_status": "delivered",
"purchase_days": 3,
"refund_policy": {
"max_days": 7,
"auto_approve_limit": 100
}
}
3. 执行状态
描述正在进行或已经完成的动作:
{
"completed_actions": [
"get_order",
"get_delivery_status",
"get_refund_policy"
],
"pending_action": null
}
4. 治理状态
描述权限、审批和预算:
{
"tool_budget_remaining": 7,
"requires_approval": true,
"approval_status": "not_requested"
}
一个简化状态机如下:
stateDiagram-v2
[*] --> Ready
Ready --> Planning
Planning --> Acting: 选择工具
Planning --> WaitingUser: 信息不足
Planning --> WaitingApproval: 高风险动作
Planning --> Completed: 满足成功条件
Acting --> Observing: 工具成功
Acting --> Recovering: 工具失败
Observing --> Planning
Recovering --> Planning: 可重试或改用备用工具
Recovering --> Failed: 超过重试上限
WaitingUser --> Planning: 收到用户输入
WaitingApproval --> Acting: 审批通过
WaitingApproval --> Failed: 审批拒绝
Completed --> [*]
Failed --> [*]
关键路径是:
Planning → Acting → Observing → Planning
这条边允许 Agent 根据工具结果重新规划。
而以下路径必须由系统控制:
Planning → WaitingApproval
Planning → Failed
Recovering → Failed
模型可以提出动作,但不能自行取消审批、无限重试或把失败伪装成成功。
OpenAI 文档将 guardrails、human review、resumable state 和 tracing 作为 Agent 运行时的重要能力,说明实际 Agent 设计不只是“让模型调用工具”,还必须处理暂停、恢复和审计。(developers.openai.com)
七、状态、记忆和自治不是同一个概念
三个概念经常被混淆。
状态
状态是为了让一次运行能够继续:
当前处于哪个节点?
已经调用过哪些工具?
上一个工具返回了什么?
是否等待审批?
记忆
记忆是跨运行保存的信息:
用户偏好中文;
用户所在组织;
过去的订单和沟通记录。
自治
自治是模型是否能够决定后续过程:
下一步调用什么工具?
是否继续?
是否改用另一种方法?
是否向用户提问?
一个系统可以:
- 有状态,但没有自治:固定工作流;
- 有记忆,但没有自治:带用户画像的普通程序;
- 有自治,但没有长期记忆:一次性 Agent;
- 同时具备三者:长期运行的 Agent 系统。
因此,“有上下文窗口”“支持会话”“保存历史消息”都不能单独证明系统是 Agent。
八、确定性如何逐层恢复
Agent 的优势是灵活,但它天然会降低可预测性。工程上通常不是在“Agent”和“确定性”之间二选一,而是把确定性放在高风险边界上。
1. 用程序限制动作集合
不要把整个后端 API 暴露给模型,而是提供窄接口:
def issue_refund(order_id: str, amount: float):
...
工具本身还应进行:
- 用户身份校验;
- 订单归属校验;
- 金额上限校验;
- 幂等键校验;
- 权限校验;
- 审批状态校验。
模型只能提出调用请求,真正的业务权限仍由工具实现。
2. 用结构化结果替代自然语言协议
不可靠:
请告诉我是否可以退款。
更适合系统处理:
{
"decision": "approve|reject|review",
"reason_code": "expired|not_paid|over_limit|eligible",
"evidence": ["order.status", "policy.max_days"],
"next_action": "issue_refund|ask_user|request_approval"
}
结构化输出减少解析歧义,但不自动保证字段值正确。业务代码仍需校验枚举值、证据是否存在以及动作是否符合权限。
3. 用守卫条件限制状态转移
可以把状态转移写成:
其中 是自动审批金额上限。
模型可以建议 issue_refund,但只有当 eligible ∧ approved 成立时,守卫条件才允许状态转移到 Refunded。
4. 用幂等性处理重复行动
Agent 可能因为工具超时而重复调用:
第一次退款请求已成功,但响应丢失
→ Agent 认为失败
→ 再次发起退款
因此,写操作必须使用幂等键:
refund_key = f"refund:{order_id}:{request_id}"
issue_refund(order_id, amount, idempotency_key=refund_key)
工具端需要保证相同幂等键不会产生两次业务副作用。
这不是 Agent 特有问题,但 Agent 的动态重试和较长运行时间会显著放大这个问题。
九、一个反例:把固定流程包装成 Agent
以下系统经常被称为 Agent:
让模型生成摘要
→ 让模型生成标题
→ 让模型翻译
→ 让模型检查语法
→ 返回结果
如果顺序、节点和重试次数都固定,那么它本质上是工作流。即使每个节点都由大模型完成,也没有发生控制流自治。
另一个反例是:
模型输出一个 JSON:
{
"next_step": "search"
}
如果程序只允许:
if next_step == "search":
search()
elif next_step == "finish":
finish()
那么这是一个带模型分类器的工作流。
只有当模型可以在受限工具集合内动态决定多个后续动作,并且工具结果会影响后续计划时,Agent 的定义才成立。
十、另一个反例:把 Agent 强行写成工作流
反过来,如果任务本身需要探索,却硬编码成固定流程,也会产生失败。
假设要分析一个未知代码仓库中的安全问题。不同仓库可能:
- 使用不同语言;
- 拥有不同目录结构;
- 风险集中在不同模块;
- 需要不同测试命令;
- 需要根据第一轮扫描结果继续检查。
固定工作流可能写成:
读取 README
→ 扫描 src/
→ 扫描 tests/
→ 运行固定测试
→ 生成报告
但如果代码实际位于 packages/,或者风险出现在 CI 配置和部署脚本中,流程就会遗漏目标。
此时更合理的是使用受控 Agent:
先观察仓库结构
→ 选择相关目录
→ 判断需要哪类扫描
→ 执行检查
→ 根据发现决定是否深入
→ 运行与修改范围相关的验证
→ 输出带证据的报告
不过,“使用 Agent”不等于“让模型拥有任意 shell 权限”。更合理的做法是:
- 使用沙箱;
- 限制文件范围;
- 限制命令集合;
- 记录每次工具调用;
- 对写文件和联网操作单独审批;
- 通过测试和静态检查验证结果。
十一、如何正确选型
可以按以下顺序判断,而不是先决定“要不要上 Agent”。
第一步:任务目标是否明确
如果目标可以写成明确的输入、规则和输出契约,优先考虑普通程序或工作流。
例如:
读取 CSV → 校验字段 → 聚合统计 → 写入数据库
不需要 Agent。
如果目标是:
调查这个问题,找到足够证据并提出解决方案
且过程依赖未知信息,则可能需要 Agent。
第二步:步骤是否可以在设计时枚举
如果可以枚举:
A → B → C
使用普通程序或工作流。
如果只能描述为:
先获取信息,观察结果,然后决定下一步
才需要考虑 Agent。
第三步:错误是否可以预先分类
如果错误可以枚举:
超时 → 重试
参数错误 → 修正参数
权限不足 → 失败
工作流通常更适合。
如果错误表现为:
当前证据不足,需要换一种搜索方式;
工具返回的信息互相矛盾,需要进一步核验;
原计划不再适用,需要重新拆解任务。
Agent 的动态规划能力更有价值。
第四步:错误代价是否允许探索
Agent 可能:
- 多调用工具;
- 重复尝试;
- 选择次优路径;
- 产生额外成本;
- 在边界输入上做出不稳定判断。
如果错误代价很高,例如转账、删库、发版、修改权限,应该把 Agent 放在建议或调查环节,而不是直接放在最终提交环节。
一个常见架构是:
Agent:调查、分析、生成计划
↓
程序:校验计划
↓
人工或策略引擎:审批
↓
程序:执行副作用
第五步:是否真的需要模型驱动的控制流
很多问题只需要一次 LLM 调用加检索:
检索相关文档
→ 让模型根据文档回答
Anthropic 明确建议先选择最简单的方案;在许多应用中,单次 LLM 调用结合检索和上下文示例已经足够。Agent 通常以更高的延迟和成本换取更强的任务完成能力。(anthropic.com)
如果问题可以通过:
- 更好的提示词;
- 结构化输出;
- 检索;
- 少量示例;
- 规则校验;
- 固定流程;
得到稳定结果,就不应为了“看起来智能”引入 Agent。
十二、三种模型的工程对照
| 维度 | 普通程序 | 工作流 | Agent |
|---|---|---|---|
| 控制流 | 代码固定 | 代码预定义图 | 模型动态决定 |
| 分支 | 代码条件 | 受限分支 | 运行时规划 |
| 工具选择 | 代码调用 | 节点配置或有限路由 | 模型选择 |
| 终止条件 | 代码定义 | 流程节点定义 | 模型建议,系统强制兜底 |
| 可复现性 | 高 | 中到高 | 较低 |
| 适合任务 | 规则明确、输入结构化 | 多步骤、路径可枚举 | 目标明确但过程未知 |
| 测试方式 | 单元测试、性质测试 | 节点测试、路径测试 | 轨迹评估、工具调用评估、结果评估 |
| 故障处理 | 显式异常分支 | 重试和补偿节点 | 重新规划、换工具、请求人工 |
| 主要风险 | 规则遗漏 | 流程覆盖不足 | 越权、循环、错误规划 |
| 推荐副作用边界 | 可直接执行 | 可直接执行但需校验 | 通常经审批或程序校验后执行 |
这个表格中的“Agent 可复现性较低”不是说 Agent 一定不可测试,而是说测试对象发生了变化:不再只是判断最终输出,还要判断模型是否选择了合理工具、是否遵守约束、是否在失败后正确恢复。
十三、生产诊断:看到失败表现后先判断是哪一层失控
1. 最终答案错误,但工具调用正确
可能是:
- 证据聚合错误;
- 提示词没有明确证据优先级;
- 输出校验不足;
- 模型对工具结果理解错误。
这通常是模型输出层或评估层问题,不一定需要更强自治。
2. 工具调用顺序错误
可能是:
- 工具描述不清;
- 状态没有记录已完成动作;
- Agent 没有明确的前置条件;
- 工具集合过大;
- 系统把本应固定的流程交给了模型。
如果顺序本来就固定,应把它改回工作流,而不是继续修改提示词。
3. Agent 无限循环
常见原因包括:
- 没有最大步数;
- 工具返回结果没有改变状态;
- 成功条件不可判定;
- 模型反复搜索同一问题;
- 重试动作没有幂等性。
应记录每一步的:
状态摘要
模型决策
工具名称和参数
工具结果
状态变化
循环计数
剩余预算
如果连续两次状态没有实质变化,可以触发停机或人工接管。
4. Agent 直接执行高风险操作
这通常不是模型“太聪明”,而是权限边界设计错误。
应检查:
- 高风险工具是否直接暴露;
- 工具端是否再次校验权限;
- 是否存在审批状态;
- 审批是否可恢复;
- 重试是否可能重复副作用;
- 是否能通过审计日志还原决策链。
OpenAI 的 Agents SDK 文档也将 guardrails、人工审批、可恢复运行状态和跨模型调用链的 tracing 作为独立能力,而不是假设提示词可以替代这些机制。(developers.openai.com)
十四、框架的作用与边界
Agent 框架通常提供:
- Agent 定义;
- 工具注册;
- 运行循环;
- 多 Agent 协作;
- 状态和会话;
- 审批暂停与恢复;
- 追踪和评估接口。
它们减少了样板代码,但不会消除模型的不确定性,也不会替开发者定义正确的业务边界。
Anthropic 建议开发者先直接使用 LLM API 理解底层调用,再决定是否引入框架;原因是框架的抽象层可能遮蔽真实的提示词、模型响应和工具调用,使调试更困难。(anthropic.com)
OpenAI 当前文档区分了由应用自行控制循环的 Responses API,以及由 SDK 管理 Agent 循环、工具调用、分支、交接和可恢复审批的 Agents SDK。这个区分本质上仍然对应本文的核心问题:谁拥有控制流——应用代码,还是 Agent 运行时。(developers.openai.com)
因此,选择框架前应先回答:
我需要的是:
1. 一次模型调用?
2. 一个固定的多节点工作流?
3. 一个需要动态规划和工具循环的 Agent?
4. 一个包含审批、恢复和多 Agent 交接的运行时?
如果答案只是第 1 或第 2 项,直接使用更低层的 API 往往更容易验证。
十五、最终判断标准
可以用一个简化判定式总结:
其中第三项不能省略。
仅仅因为任务复杂,并不意味着需要 Agent。一个复杂但规则明确的任务,往往更适合工作流。
反过来,一个步骤很少但需要动态选择工具的任务,也可能是 Agent。例如:
根据用户描述,决定查询哪个系统,并判断是否需要继续追问。
正确选型不是比较“普通程序、工作流和 Agent 谁更先进”,而是确定:
- 哪些控制流必须由代码掌握;
- 哪些判断可以交给模型;
- 哪些工具可以被调用;
- 哪些状态转移必须有守卫;
- 哪些副作用必须审批;
- 哪些失败可以重试;
- 什么时候系统必须停止。
最可靠的架构通常不是纯粹的三选一,而是分层组合:
普通程序负责规则、权限、计算、幂等和副作用;
工作流负责稳定的节点编排、校验和恢复;
Agent 负责不确定过程中的观察、规划、工具选择和动态调整。
自治的价值不在于让模型接管一切,而在于只把无法经济地预先编码、同时又能够被安全约束的那部分控制流交给模型。
系列导航与关联阅读
- 系列入口:Agent 工程完整路线:从运行循环、记忆与协议到安全、评测和生产交付
- 下一篇:Agent 运行循环:观察、决策、行动、反馈、状态与终止
- 延伸:Agent 状态机设计:节点、事件、守卫、转移和可恢复执行
官方资料
本文依据 Agent、模型、协议与框架官方资料重新梳理;正文、示例与生产清单由 WR BLOG 编写。

评论
0 条讨论