LangChain Plan-and-Execute Agent:复杂任务规划与执行的工程实践

发布时间:2026/8/14 3:18:19
LangChain Plan-and-Execute Agent:复杂任务规划与执行的工程实践 1. 从“直接干”到“先想后做”为什么复杂任务需要Plan-and-Execute Agent如果你用过LangChain的Agent或者尝试过直接让大模型LLM去完成一个多步骤的任务大概率会遇到这种情况你给了一个看似明确的指令比如“帮我分析一下这个季度的销售数据找出问题并生成一份报告”结果模型要么卡在某个步骤要么输出的内容七零八落完全不成体系。更常见的是它可能直接开始“写报告”却忘了先去“获取数据”和“分析数据”这两个前置步骤。这就是典型的“一步到位”思维在复杂任务面前的局限性。传统的Agent比如LangChain里经典的ZeroShotAgent其工作模式可以概括为“思考一步执行一步”。它拿到任务后会利用LLM的推理能力结合可用的工具Tools决定下一步该做什么然后执行再根据结果思考下一步。这种模式对于简单、线性的任务很有效比如“查一下北京的天气”或者“计算一下15的平方根”。但当任务变得复杂、步骤之间存在依赖关系、或者需要宏观规划时这种“走一步看一步”的方式就容易陷入局部最优甚至迷失方向。Plan-and-Execute Agent的核心思想就是把“规划”和“执行”这两个认知阶段分离开来。它引入了一个“规划者”Planner角色专门负责“想”。这个规划者会通盘考虑整个任务将其分解成一个有序的、逻辑清晰的步骤列表也就是一个“计划”。然后另一个“执行者”Executor角色负责严格地、按部就班地“干”它只关心如何完成当前步骤并把结果传递给下一步。这种架构非常像我们人类处理复杂项目时的做法先开个会定个方案Plan再分头去执行Execute。那么这种模式具体解决了哪些痛点呢第一提升任务完成的可靠性和一致性。一个深思熟虑的计划可以避免执行过程中的逻辑混乱和步骤遗漏。比如在数据处理的场景中计划会明确“先清洗数据再计算指标最后可视化”确保流程正确。第二更好地处理长上下文和复杂依赖。规划者可以一次性看到所有步骤及其关系从而做出更优的排序。例如它知道“安装依赖包”必须在“运行脚本”之前。第三便于调试和优化。因为计划和执行是分离的当任务失败时你可以清晰地看到是计划本身不合理比如步骤顺序错了还是某个具体步骤的执行出了问题比如工具调用失败这大大降低了排查成本。第四为更高级的协作模式铺平道路。理论上规划者和执行者可以由不同能力的模型担任。比如用一个擅长战略规划但速度慢的模型如GPT-4做规划者再用一个速度快、成本低的模型如Claude Haiku做执行者实现成本与效果的平衡。接下来我们就深入LangChain的内部看看这个“先写计划再干活”的智能体究竟是如何构建和运作的。2. Plan-and-Execute Agent的架构拆解Planner与Executor如何协同工作要理解Plan-and-Execute Agent我们必须先抛开对单个“智能体”的模糊印象把它看作一个由两个核心组件构成的微型系统。这个系统的设计哲学是“各司其职专业分工”。2.1 核心组件一规划者Planner规划者的唯一职责就是将用户输入的、通常比较模糊的自然语言指令转化成一个具体的、可操作的任务计划。这个计划不是一个简单的待办清单而是一个结构化的指令序列。在LangChain的实现中规划者本身通常也是一个LLMChain它接收用户输入和可用的工具描述然后输出一个计划。这个计划的具体格式在LangChain的早期版本中可能是一个用特定分隔符如\n分隔的字符串列表。但在更成熟或定制的实现里它很可能是一个结构化的对象比如一个包含多个步骤的列表每个步骤可能有id、action、input等字段。规划者输出的关键质量在于完整性是否覆盖了完成任务所必需的所有步骤。顺序性步骤之间的依赖关系是否被正确识别和排序。可执行性每个步骤是否都能被后续的执行者利用现有工具来落实。规划者模型的提示词Prompt设计至关重要。它需要清晰地被告知“你是一个规划者你有这些工具Tool A, Tool B, Tool C请为这个任务制定一个分步计划。” 提示词中通常会包含一些示例Few-shot教模型如何产出格式正确的计划。2.2 核心组件二执行者Executor执行者是计划的忠实履行者。它从规划者那里拿到计划然后从头开始一步一步地执行。对于计划中的每一个步骤执行者需要做的是理解当前步骤解析步骤描述明确这一步要做什么。选择并调用工具根据步骤要求从可用的工具集中选出最合适的那个并生成正确的调用参数。执行并观察结果运行工具获取执行结果可能是成功的数据也可能是错误信息。传递上下文将当前步骤的结果作为上下文传递给下一个步骤。有些复杂的计划后续步骤可能需要前面步骤的输出作为输入。执行者通常也是一个Agent比如一个ZeroShotAgent。但它和传统Agent有一个关键区别它的目标非常聚焦不是思考整个任务而是思考“如何完成当前这一步”。这降低了它的认知负荷也使得它的行为更加稳定和可预测。2.3 协同工作流与状态管理这两个组件是如何串联起来的呢一个典型的工作流如下初始化用户提交任务系统初始化规划者和执行者并加载所有可用工具。规划阶段将用户任务和工具描述传递给规划者。规划者LLM运行生成一个分步计划Plan。执行循环 a. 执行者读取计划中的第一个或下一个未完成步骤。 b. 执行者将当前步骤描述、之前步骤的结果如果有作为上下文决定调用哪个工具及参数。 c. 系统调用工具获得结果。 d. 执行者将结果记录到该步骤的状态中如标记为完成并存储输出。 e. 检查计划是否全部完成。如果未完成回到步骤a处理下一个步骤如果完成进入下一步。汇总与返回所有步骤执行完毕后系统将所有步骤的结果进行整理有时可能还需要一个“总结者”模型来生成最终的用户友好答复然后返回给用户。在这个过程中计划的状态管理是一个容易被忽略但极其重要的细节。我们需要一个数据结构来跟踪计划总共有多少步当前执行到哪一步每一步的输入、输出、执行状态成功/失败是什么在LangChain的生态中PlanAndExecute执行器通常会与BaseChatMessageHistory等组件结合来维护这个执行上下文。对于更复杂、可能涉及循环或条件分支的计划则需要引入像LangGraph这样的框架来管理状态图。理解了架构我们就可以动手搭建一个属于自己的Plan-and-Execute Agent了。下面我将用一个贴近实际开发的例子带你走完全程。3. 实战构建手把手实现一个数据分析报告生成Agent我们假设一个场景你是一家电商公司的数据分析师经常需要重复性地完成“获取、清洗、分析、报告”的数据工作流。今天我们构建一个Agent让它根据你的指令自动完成“获取最近7天的订单数据计算每日销售额和订单量找出销售额最高和最低的那天并用一段话总结发现”。为了完成这个任务我们需要为Agent配备几个工具Toolsget_recent_orders(days: int): 模拟从数据库获取最近N天的订单数据返回一个包含order_id,date,amount的列表。clean_data(order_data: list): 模拟数据清洗处理缺失值、异常值等返回清洗后的数据。calculate_daily_metrics(cleaned_data: list): 计算每日的销售额总和和订单量返回一个按日期汇总的字典。find_extreme_days(metrics: dict): 从每日指标中找出销售额最高和最低的日期。generate_summary(metrics: dict, extremes: tuple): 根据指标和极值日生成一段文字总结。3.1 第一步环境准备与工具定义首先确保你的环境已安装LangChain和OpenAI或其他你选择的LLM提供商的包。pip install langchain langchain-openai然后我们定义上述工具。在真实场景中这些工具的后端可能是数据库查询、Pandas操作或API调用。这里我们用函数模拟。from langchain.tools import tool from typing import List, Dict, Any import random from datetime import datetime, timedelta # 工具1获取近期订单模拟 tool def get_recent_orders(days: int) - List[Dict]: Fetches order data for the recent specified number of days. # 模拟生成数据 data [] base_date datetime.now() for i in range(days): current_date base_date - timedelta(daysi) date_str current_date.strftime(%Y-%m-%d) # 模拟每天1-5个订单 for j in range(random.randint(1, 5)): order_id fORD-{date_str}-{j:03d} # 模拟订单金额在50-500之间 amount round(random.uniform(50.0, 500.0), 2) data.append({order_id: order_id, date: date_str, amount: amount}) return data # 工具2清洗数据模拟 tool def clean_data(order_data: List[Dict]) - List[Dict]: Cleans the order data, e.g., handling missing values or outliers. # 这里简单模拟移除金额为0或负数的异常订单实际中可能更复杂 cleaned [order for order in order_data if order[amount] 0] # 模拟处理缺失日期这里假设数据源可靠跳过 print(fData cleaning: Removed {len(order_data) - len(cleaned)} invalid orders.) return cleaned # 工具3计算每日指标 tool def calculate_daily_metrics(cleaned_data: List[Dict]) - Dict[str, Dict]: Calculates total sales amount and order count per day. metrics {} for order in cleaned_data: date order[date] if date not in metrics: metrics[date] {total_sales: 0.0, order_count: 0} metrics[date][total_sales] order[amount] metrics[date][order_count] 1 return metrics # 工具4找出极值日 tool def find_extreme_days(metrics: Dict[str, Dict]) - Dict[str, Any]: Finds the day with the highest and lowest sales. if not metrics: return {highest: None, lowest: None} sorted_days sorted(metrics.items(), keylambda x: x[1][total_sales]) lowest_day, lowest_data sorted_days[0] highest_day, highest_data sorted_days[-1] return { highest: {date: highest_day, sales: highest_data[total_sales]}, lowest: {date: lowest_day, sales: lowest_data[total_sales]} } # 工具5生成总结 tool def generate_summary(metrics: Dict[str, Dict], extremes: Dict[str, Any]) - str: Generates a textual summary based on metrics and extreme days. total_days len(metrics) total_orders sum(day[order_count] for day in metrics.values()) total_sales sum(day[total_sales] for day in metrics.values()) avg_sales total_sales / total_days if total_days 0 else 0 summary f在过去{total_days}天中共有{total_orders}笔订单总销售额为${total_sales:.2f}日均销售额为${avg_sales:.2f}。 if extremes[highest]: summary f 销售额最高的一天是{extremes[highest][date]}达到${extremes[highest][sales]:.2f}。 if extremes[lowest]: summary f 销售额最低的一天是{extremes[lowest][date]}为${extremes[lowest][sales]:.2f}。 return summary # 将所有工具放入列表 tools [get_recent_orders, clean_data, calculate_daily_metrics, find_extreme_days, generate_summary]3.2 第二步构建规划者Planner规划者需要一个大语言模型LLM和一个精心设计的提示词。我们将使用ChatOpenAI和LLMChain。from langchain_openai import ChatOpenAI from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.schema import SystemMessage, HumanMessage, AIMessage # 初始化LLM这里使用gpt-3.5-turbo成本较低且足够完成规划任务 planner_llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 构建规划者提示词 planner_prompt ChatPromptTemplate.from_messages([ SystemMessage(content你是一个任务规划专家。你的目标是将用户的复杂请求分解成一个清晰的、线性的、可执行的分步计划。 每个步骤都应该对应一个可用的工具。请只使用以下工具 {tools} 请严格按照以下格式输出计划 1. 第一步使用[工具名称]做[简短描述]输入参数是[参数说明] 2. 第二步使用[工具名称]做[简短描述]输入参数是[参数说明] ... 例如 用户帮我分析上周的销售数据。 计划 1. 第一步使用get_recent_orders获取最近7天的订单数据输入参数是days7 2. 第二步使用clean_data清洗第一步获取的订单数据输入参数是order_data第一步的输出 3. 第三步使用calculate_daily_metrics计算清洗后数据的每日指标输入参数是cleaned_data第二步的输出 4. 第四步使用find_extreme_days从每日指标中找出销售额最高和最低的日期输入参数是metrics第三步的输出 5. 第五步使用generate_summary生成分析报告输入参数是metrics第三步的输出, extremes第四步的输出 现在请为下面的用户请求制定计划。), MessagesPlaceholder(variable_namechat_history), HumanMessage(content{input}) ]) # 创建规划链 planner_chain planner_prompt | planner_llm3.3 第三步构建执行者Executor执行者我们使用LangChain标准的create_react_agent来构建它基于ReAct范式适合逐步执行计划。from langchain.agents import create_react_agent, AgentExecutor from langchain.memory import ConversationBufferMemory # 为执行者准备一个独立的LLM可以用同一个也可以区分。 executor_llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 执行者需要记忆来存储中间结果我们使用一个简单的内存 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 创建执行者Agent executor_agent create_react_agent(executor_llm, tools, verboseTrue) # 创建Agent执行器 agent_executor AgentExecutor.from_agent_and_tools( agentexecutor_agent, toolstools, memorymemory, verboseTrue, handle_parsing_errorsTrue # 处理解析错误 )3.4 第四步组装Plan-and-Execute工作流现在我们需要编写一个协调器将规划者和执行者串联起来。这个协调器负责调用规划者生成计划然后解析计划一步步驱动执行者去完成。import re class PlanAndExecuteAgent: def __init__(self, planner_chain, agent_executor): self.planner planner_chain self.executor agent_executor def run(self, user_input: str): print( 规划阶段 ) # 1. 生成计划 plan_response self.planner.invoke({ input: user_input, tools: \n.join([f- {tool.name}: {tool.description} for tool in tools]) }) plan_text plan_response.content print(f生成的计划\n{plan_text}) # 2. 解析计划步骤 steps self._parse_plan(plan_text) if not steps: return 无法解析出有效的计划步骤。 print(f\n 执行阶段 ) # 3. 按顺序执行计划 intermediate_results {} # 用于存储每一步的输出 for i, step in enumerate(steps, 1): print(f\n--- 执行步骤 {i}: {step[description]} ---) # 构建给执行者的指令。这里的关键是告诉执行者当前要做什么并把之前步骤的结果作为上下文。 # 我们简单地将步骤描述和之前的结果格式化后作为输入。 context self._build_context(intermediate_results, step) executor_input f当前任务{step[description]}。请使用工具完成。上下文信息{context} try: result self.executor.invoke({input: executor_input}) output result[output] print(f步骤 {i} 结果{output}) # 存储结果键名可以是步骤序号或工具名 intermediate_results[fstep_{i}] output # 特别地如果这一步调用了工具我们也可以按工具输出存储方便后续步骤引用 # 这里简化处理只按步骤存储 except Exception as e: print(f步骤 {i} 执行出错{e}) intermediate_results[fstep_{i}] fError: {e} # 在实际应用中可能需要更复杂的错误处理逻辑比如重试或修改计划 # 4. 返回最终结果通常是最后一步的输出 final_output intermediate_results.get(fstep_{len(steps)}, 执行未完成) print(f\n 任务完成 ) return final_output def _parse_plan(self, plan_text: str) - List[Dict]: 解析规划者输出的文本计划提取步骤列表。 steps [] # 简单的正则匹配匹配 1. 第一步使用[工具]做[事]输入是xxx 这种格式 pattern r\d\.\s*[^:]使用(\w)\s*[^]输入参数是([^\n]) matches re.findall(pattern, plan_text) for match in matches: tool_name, input_desc match # 根据工具名找到对应的工具对象获取其描述用于构建步骤指令 tool_obj next((t for t in tools if t.name tool_name), None) if tool_obj: steps.append({ tool: tool_name, input_description: input_desc.strip(), description: f使用工具 {tool_name}{tool_obj.description} }) return steps def _build_context(self, results: Dict, current_step: Dict) - str: 构建当前步骤的上下文字符串。 context_parts [] for step_key, result in results.items(): # 避免上下文过长可以截断 context_parts.append(f{step_key}的结果是{result[:200]}...) return .join(context_parts) if context_parts else 暂无之前的执行结果。 # 实例化我们的Plan-and-Execute Agent plan_execute_agent PlanAndExecuteAgent(planner_chain, agent_executor)3.5 第五步运行与测试现在让我们用一开始设定的任务来测试这个Agent。user_query 获取最近7天的订单数据计算每日销售额和订单量找出销售额最高和最低的那天并用一段话总结发现。 final_result plan_execute_agent.run(user_query) print(f\n最终报告\n{final_result})当你运行这段代码时会在控制台看到清晰的“规划阶段”和“执行阶段”日志。规划者会输出一个类似示例的五步计划。然后执行者会一步步调用工具获取数据、清洗、计算指标、找极值日、生成总结。最终你将得到一段包含关键数据的文本报告。这个例子虽然简化但完整展示了Plan-and-Execute Agent从设计到实现的核心流程。在实际项目中你可能需要更健壮的计划解析器、更完善的错误处理、以及更强大的状态管理例如使用LangGraph。但万变不离其宗其“先规划后执行”的思想内核是一致的。4. 深入原理Plan-and-Execute与ReAct、LangGraph的对比与选型在LangChain的Agent生态里除了Plan-and-Execute你肯定还听说过ReAct和LangGraph。它们之间是什么关系又该如何选择呢理解这一点能帮助你在实际项目中做出更合适的技术决策。4.1 ReAct思考与行动的即时循环ReActReasoning Acting是驱动大多数基础Agent如ZeroShotAgent的核心范式。它的工作流在一个循环内完成思考ThinkLLM根据当前任务描述、可用工具和上一步的观察结果思考下一步应该做什么。行动ActLLM决定调用哪个工具并生成调用参数。观察Observe执行工具获得结果或错误。将观察结果作为新的上下文回到步骤1直到LLM认为任务完成输出Final Answer。优点灵活、通用对于动态变化的环境或需要即时调整策略的任务表现良好。缺点对于需要长远规划的多步骤任务容易“短视”可能做出局部最优但全局低效的决策。同时所有“思考”都发生在同一个LLM调用中上下文可能变得冗长混乱。Plan-and-Execute可以看作是对ReAct范式的一种结构化增强。它将“宏观规划”Planning这个高层次的“思考”剥离出来放在最前面一次性完成。剩下的“执行”阶段虽然内部可能还是一个ReAct循环用于完成每个子步骤但每个子步骤的目标非常明确且有限从而降低了复杂度。4.2 LangGraph用图来定义复杂的工作流LangGraph是LangChain中用于构建有状态、多参与者的工作流或称“图”的库。在LangGraph中你可以定义多个节点Node可以是LLM、工具、函数等和边Edge决定流程走向的条件从而构建出带循环、分支、并行等复杂逻辑的智能体系统。Plan-and-Execute Agent非常适合用LangGraph来实现。你可以将“规划者”和“执行者”定义为两个节点。工作流可以是开始-规划节点生成计划-执行节点按计划执行步骤本身可能是一个子图或循环-结束。使用LangGraph的好处是显式状态管理整个工作流的状态包括当前计划、已完成的步骤、中间结果被封装在一个状态对象中在各个节点间传递非常清晰。支持复杂逻辑如果某个步骤执行失败你可以很容易地通过条件边Conditional Edge跳转到错误处理节点或重试逻辑。可视化与可调试性LangGraph的图结构可以可视化便于理解和调试复杂的工作流。4.3 如何选择一个简单的决策框架面对一个任务你该用基础的ReAct AgentPlan-and-Execute还是上LangGraph可以参考以下思路任务简单且步骤少3步直接使用ReAct Agent如create_react_agent。它简单快捷足够应付大多数一次性问答和简单操作。任务步骤清晰、顺序固定、但较多3步使用Plan-and-Execute模式。它能显著提升任务完成的可靠性和可解释性。你可以用我们上面演示的方式自己组装也可以寻找社区中更成熟的实现。任务流程复杂包含条件判断、循环或并行使用LangGraph。例如“监控系统日志如果出现错误A则执行预案B如果出现错误C则执行预案D并循环监控”。LangGraph是描述这种复杂、有状态流程的终极工具。注意这三种模式不是互斥的而是可以组合的。例如在LangGraph构建的Plan-and-Execute工作流中“执行者”节点本身可能就是一个ReAct Agent。选择的核心在于用合适的工具匹配任务的复杂度避免“杀鸡用牛刀”或“小马拉大车”。5. 避坑指南与性能优化让Plan-and-Execute Agent真正可靠构建一个能跑通的Demo是一回事让它在生产环境中稳定、高效地运行是另一回事。在实际使用Plan-and-Execute Agent时你会遇到一些典型的“坑”。下面是我从实践中总结出的关键问题和优化建议。5.1 规划阶段的常见问题与对策问题1规划者生成不可执行的计划。表现计划中的步骤调用了不存在的工具或者输入参数描述模糊导致执行者无法理解。根因规划者LLM对可用工具的理解不足或者提示词Prompt不够精确。解决方案优化工具描述确保每个tool装饰器下的函数文档字符串docstring清晰、准确包含参数类型和示例。LLM严重依赖这些描述。提供高质量示例Few-shot在规划者的提示词中提供2-3个针对你常用任务类型的、完美的计划示例。这是引导LLM输出正确格式的最有效方法。输出格式约束要求规划者以严格的格式如JSON、YAML或带编号的列表输出。这可以通过在Prompt中指定或者使用LangChain的OutputParser如PydanticOutputParser来实现强制结构化输出。问题2计划步骤顺序不合理或遗漏关键步骤。表现计划让执行者“计算指标”在“获取数据”之前或者忘了“保存结果”这一步。根因任务复杂度超出规划者模型的上下文理解能力或者领域知识不足。解决方案分而治之对于极其复杂的任务可以考虑两级规划。第一级规划者进行粗粒度分解如“阶段一数据准备阶段二模型训练阶段三结果评估”第二级规划者再对每个阶段进行细粒度规划。使用更强的规划模型如果任务至关重要可以考虑使用能力更强的模型如GPT-4作为规划者。虽然成本高但规划质量直接影响整个任务的成败这笔投资往往是值得的。人工审核或修正计划在关键业务流中可以引入“人工在环”Human-in-the-loop机制让规划者生成的计划先经过人工确认或微调后再执行。5.2 执行阶段的常见问题与对策问题3执行者无法正确解析上一步的输出作为当前步骤的输入。表现计划中写“输入参数是第一步的输出”但执行者LLM在调用工具时传递的是一个无意义的字符串而不是第一步的实际结果对象。根因我们自制的协调器在_build_context函数中只是简单地将之前步骤的输出结果以文本形式拼接。如果输出是复杂对象如字典、列表直接转换成字符串可能丢失结构信息导致后续LLM无法正确提取所需字段。解决方案结构化中间状态不要只存储文本结果。为每个步骤定义一个明确的输出模式Schema。例如get_recent_orders步骤的输出可以定义为List[Order]类型。协调器维护一个结构化的状态字典。智能参数绑定在执行每个步骤时协调器应能根据步骤描述如input_desc和当前结构化状态自动将正确的值绑定到工具参数上。这可能需要一个简单的模板引擎或参数解析器。例如解析到input_desc为metrics第三步的输出就去状态字典里找到step_3的结果并将其作为metrics参数的值。使用LangChain Expression Language (LCEL)或LangGraph这些高级框架内置了更完善的状态管理和数据流机制能更好地处理步骤间的数据传递。问题4某个步骤执行失败导致整个任务中断。表现工具调用超时、返回错误、或LLM解析工具输出失败。根因网络问题、工具异常、或LLM的“幻觉”导致生成了不合法的工具调用。解决方案重试机制为工具调用和LLM调用增加指数退避的重试逻辑。许多HTTP客户端和LLM SDK都支持重试。超时设置为每个步骤设置合理的超时时间防止因某个工具卡死而阻塞整个流程。备选计划Plan B在规划时可以让规划者思考“如果某工具失败备用方案是什么”。或者在执行时由协调器捕获异常并尝试使用备用工具或跳过该步骤如果允许。检查点Checkpoint定期保存执行状态。这样即使整个进程崩溃重启后可以从最近一个成功的步骤继续而不是从头开始。5.3 性能与成本优化策略1模型分工降低成本。正如之前提到的让GPT-4做规划者调用一次让GPT-3.5-Turbo做执行者可能调用多次。规划需要深谋远虑值得用更好的模型执行是机械化的子任务用性价比高的模型即可。策略2缓存规划结果。对于高频、重复的任务如“每日销售报告”其计划几乎是固定的。可以将规划结果缓存起来例如以任务指令的哈希值为Key下次直接使用省去一次LLM调用。策略3异步执行。如果计划中的某些步骤之间没有依赖关系可以考虑让它们并行执行。这需要更高级的工作流引擎如LangGraph来支持。例如“获取用户信息”和“获取产品列表”这两个步骤如果可以同时进行就能缩短总执行时间。策略4精简上下文。在执行阶段传递给执行者LLM的上下文应只包含当前步骤必需的信息避免将整个计划历史都塞进去导致令牌数激增、成本上升且可能影响模型性能。构建一个健壮的Plan-and-Execute Agent是一个迭代过程。从最简单的原型开始逐步增加错误处理、状态管理、性能优化等特性。理解其核心思想——分离关注点——能帮助你在面对各种复杂需求时设计出清晰、可维护的智能体系统。