课程地址: learn.deeplearning.ai/courses/agentic-ai
github地址: datawhalechina/agentic-ai
( Planning workflows )
就像复杂软件系统需要工厂模式、单例模式、依赖倒置等等设计模式和原则一样,Agent系统想要实现复杂度与效率并重,也需要一些设计模式。
本节我们将介绍规划 (Planning) 设计模式,规划模式的Agent系统高度自主,能够自行决定执行复杂任务所需的工具调用序列,而无需事先硬编码。
真实案例:客服助理Agnet

目标: 构建能够回答广泛、复杂查询的智能体,在运行时灵活地决定采取哪些行动。在本系统中,是一个能够回答客户像“你们有没有库存中售价低于100美元的圆形太阳眼镜?”这类复杂问题的Agent。
方法:提供工具集: 给 LLM 提供一套功能工具。在本例中,是如下工具:
| 工具名 | 功能说明 | 示例用途 |
|---|---|---|
| get_item_descriptions | 获取商品的文字描述或元数据(如名称、款式、材质、颜色、形状等) | 当用户说“round sunglasses”时,用它来查出所有带“round”特征的太阳眼镜 |
| get_item_price | 查询指定商品的价格 | 在找到商品后,用它来判断哪些低于 $100 |
| check_inventory | 检查商品是否有库存(以及库存数量) | 找到圆形眼镜后,查询这些商品是否在库 |
| check_past_transactions | 查看用户的历史交易记录(如购买过哪些商品、是否退换货过) | 用于客户支持场景,如“我上周买的眼镜有问题” |
| process_item_sale | 处理购买行为,即创建销售订单或执行购买交易 | 当用户确认要买时,调用这个工具执行交易 |
| process_item_return | 处理退货操作 | 当用户想退货时,用它发起退货请求 |
LLM 编写计划: 要求LLM根据用户请求返回一个逐步的执行计划,说明应按什么顺序调用哪些工具。在本例中,是如下流程:
LLM 计划调用
get_item_descriptions 来找“round sunglasses”
根据 Step 1 的输出(找到的产品)
再调用
check_inventory 查看库存
对库存中有货的结果
调用
get_item_price 检查哪些低于 $100
输出最终结果
逐步执行: 按照计划,将每一步的指令和上一步的输出/上下文依次喂给 LLM,让它调用相应的工具并执行。
最终输出: 将所有步骤的结果反馈给 LLM,生成最终的用户答案。
可以看出,规划模式的Agent有许多好处,比如Agent拥有非常丰富的能力,进而扩展了能执行的任务范围。开发者也无需事先编排工具调用的确切序列,提高了系统的灵活性和自主性。
规划模式的Agent系统在流程控制与实际场景上也有些风险点。在运行时,开发者无法预知 LLM 会生成什么样的计划,带来了结果不稳定/出错/越权的风险。目前,规划模式在AI Coding应用中非常成功,但在其他领域仍然处在尝试阶段。
不过,可以看到的是,随着基础模型的智能程度不断提高,现在使用这种完全由Agent控制流程的AI系统的场景也越发多了,笔者自己开发应用时也经常用到。这种规划模式灵活度高,代码量小,难点在于工具设计与流程设计。
对于同一个场景,经验丰富的开发者可能会抽象出三个封装好了复杂逻辑的核心工具即可解决问题,而经验不足的开发者往往容易过度抽象出十几种工具,或是索性直接提供最基本的一两个工具(在本例中,有可能是商品系统后台的数据库session——这是极其不安全的!),让AI自己编写代码来写业务。
这里推荐一个笔者个人十分喜欢的Agent框架:来自Huggingface社区的smolagents框架。它代码简洁,抽象程度少,工具开发难度低(只需要一个@tool装饰器),自由程度高,也具有流程跟踪功能,开发者很容易入门,也很方便理解重写其中的一些逻辑,来实现自己定制化的系统。
Creating and executing LLM plans
在规划模式中,如何利用结构化输出来保证 LLM 生成的计划能够被下游代码可靠地执行,是非常重要的。
在上一讲中,我们让LLM直接讲出自己的任务规划,但自然语言不够清晰和明确,难以被下游代码稳定地解析和执行。所以在本节中,我们要求 LLM 以结构化格式(如 JSON 或 XML)输出计划。
结构化格式能够清楚地界定计划的步骤、所需工具及其参数,从而允许下游代码更可靠地解析 (parse) 计划的每个步骤,从而系统性地、一步一步地执行。
为了实现结构化输出,开发者应该这样写 LLM 指示词:“你可以访问以下工具,并需要以 JSON 格式创建一个分步计划”,同时详细描述所需的 JSON 结构。

LLM 会返回一个 JSON 列表,列表中的每个对象代表一个步骤,包含清晰的键值:
description (步骤描述)
tool (要调用的工具名称)
arguments (传递给工具的参数)
这样一来,我们只要接收LLM的字符串输出,转化为JSON格式,并提取参数,执行对应函数即可。这样的解析器编写起来非常方便。