Agent 自主规划 —— 怎么让 Agent 自己拆解任务、动态调整策略

先放结论:自主规划不是"让模型随便发挥",而是给 Agent 一套"目标→拆解→执行→反馈→重规划"的闭环机制。 没有这个闭环,Agent 就是个只会按固定流程跑的机器人;有了这个闭环,它才像个有经验的项目负责人------你只给目标,它自己搞定过程。

为什么硬编码流程不够用

回顾前几篇,我们写的 Agent 基本都是这个结构:

arduino 复制代码
const workflow = new StateGraph<AgentState>()
    .addNode('step1', step1)
    .addNode('step2', step2)
    .addNode('step3', step3)
    .addEdge('__start__', 'step1')
    .addEdge('step1', 'step2')
    .addEdge('step2', 'step3')
    .addEdge('step3', END);

流程是固定的:step1 → step2 → step3。如果 step1 失败了怎么办?如果 step2 发现需要额外步骤怎么办?如果用户的目标变了怎么办?硬编码流程回答不了这些问题。

硬编码流程的四个瓶颈:

  1. 无法应对变化:执行过程中环境变了(比如场地订不到、API 挂了),流程不会自动调整
  2. 无法处理未知:遇到预设流程之外的情况,Agent 直接卡死
  3. 无法优化路径:明明可以并行执行的任务,硬编码只能串行
  4. 无法从错误中学习:同样的错误会重复犯,因为没有"反思"机制

自主规划的本质 :把"流程"从代码里抽出来,变成 Agent 运行时动态生成的"计划"。计划不是一次性写死的清单,而是一个可维护、可修正、可重规划的动态结构。

自主规划的闭环:感知→规划→执行→反馈→重规划

一个能自主规划的 Agent,核心是这五个环节的闭环:

css 复制代码
┌─────────────────────────────────────────────┐
│              目标输入                        │
│  "帮我安排一次本周末从北京出发的两天一夜      │
│   家庭旅行,预算 2000 元,适合带 5 岁小孩"    │
└──────────────────┬──────────────────────────┘
                   ↓
┌─────────────────────────────────────────────┐
│  ① 感知:理解目标 + 感知环境                │
│  - 解析约束:预算 2000、两天一夜、带小孩     │
│  - 感知资源:可用工具(天气、酒店、机票API)  │
│  - 感知限制:周末、北京出发                  │
└──────────────────┬──────────────────────────┘
                   ↓
┌─────────────────────────────────────────────┐
│  ② 规划:拆解任务 + 生成执行路径            │
│  - 子任务1:查询北京周边适合亲子游的目的地    │
│  - 子任务2:查询目的地周末天气               │
│  - 子任务3:筛选预算内的酒店                 │
│  - 子任务4:查询往返交通方案                 │
│  - 子任务5:生成行程单                      │
└──────────────────┬──────────────────────────┘
                   ↓
┌─────────────────────────────────────────────┐
│  ③ 执行:调用工具 + 执行子任务              │
│  - 调用天气 API → 发现目的地 A 周末下雨       │
│  - 调用酒店 API → 发现目的地 B 酒店满房       │
└──────────────────┬──────────────────────────┘
                   ↓
┌─────────────────────────────────────────────┐
│  ④ 反馈:检查结果 + 识别问题                │
│  - 问题1:目的地 A 天气不好,不适合出行       │
│  - 问题2:目的地 B 酒店满房,需要换目的地     │
└──────────────────┬──────────────────────────┘
                   ↓
┌─────────────────────────────────────────────┐
│  ⑤ 重规划:调整计划 + 继续执行              │
│  - 重新筛选目的地(排除 A,换其他备选)       │
│  - 重新查询酒店和交通                       │
│  - 生成新的行程单                           │
└─────────────────────────────────────────────┘

关键区别:硬编码流程里,"目的地 A 下雨"这个情况不在预设分支里,Agent 直接报错;自主规划里,Agent 感知到反馈后,自己调整计划,换目的地继续执行。

五种主流规划范式

自主规划不是单一技术,而是一组方法的集合。以下是五种主流范式,各有适用场景:

1. ReAct(Reasoning + Acting)

核心思想:推理和行动交替进行,每执行一步就观察结果,再决定下一步。

json 复制代码
思考:用户想查天气,我需要调用天气工具
行动:调用 weather_api(city="北京")
观察:{"temperature": 25, "condition": "晴"}
思考:天气信息已获取,可以回答用户了
行动:返回结果

优点 :简单直接,适合短流程、交互式任务。 缺点:缺乏全局视角,容易"走一步看一步",长任务容易跑偏。

LangChain 实现:

php 复制代码
import { createReactAgent } from '@langchain/langgraph/prebuilt';
import { ChatOpenAI } from '@langchain/openai';
import { TavilySearchResults } from '@langchain/community/tools/tavily_search';

const model = new ChatOpenAI({ model: 'gpt-4o' });
const tools = [new TavilySearchResults({ maxResults: 3 })];

// ReAct Agent 自动处理 思考→行动→观察 循环
const agent = createReactAgent({
    llm: model,
    tools,
});

const result = await agent.invoke({
    messages: [{ role: 'user', content: '帮我查一下北京今天的天气,并推荐一个适合户外活动的公园' }],
});

2. Plan-and-Execute(规划-执行)

核心思想:先一次性生成完整计划(DAG 或步骤清单),再逐步执行。

arduino 复制代码
第一步:生成计划
LLM 输出:["查询天气", "搜索公园", "评估公园 suitability", "生成推荐"]

第二步:按顺序执行
执行 step 1 → 执行 step 2 → 执行 step 3 → 执行 step 4

优点 :有全局视野,适合流程相对固定的场景。 缺点:初始规划如果错了,后续全错;需要配合动态修正机制。

LangGraph 实现:

typescript 复制代码
import { StateGraph, END } from '@langgraph/graph';
import { ChatOpenAI } from '@langchain/openai';

interface PlanState {
    goal: string;
    plan: string[];
    currentStep: number;
    results: Record<string, any>;
    finalAnswer: string;
}

const model = new ChatOpenAI({ model: 'gpt-4o' });

// 规划节点:生成完整计划
async function planner(state: PlanState): Promise<Partial<PlanState>> {
    const prompt = `用户目标:${state.goal}
请将这个目标拆解为可执行的步骤列表,每步一个动作。
输出 JSON 数组格式:["步骤1", "步骤2", ...]`;
    const result = await model.invoke(prompt);
    const plan = JSON.parse(result.content);
    return { plan, currentStep: 0 };
}

// 执行节点:执行当前步骤
async function executor(state: PlanState): Promise<Partial<PlanState>> {
    const currentTask = state.plan[state.currentStep];
    // 根据任务调用相应工具...
    const toolResult = await executeTask(currentTask);
    return {
        results: { ...state.results, [state.currentStep]: toolResult },
        currentStep: state.currentStep + 1,
    };
}

// 判断是否完成
function shouldContinue(state: PlanState): string {
    return state.currentStep < state.plan.length ? 'executor' : 'finalizer';
}

// 汇总节点:生成最终答案
async function finalizer(state: PlanState): Promise<Partial<PlanState>> {
    const prompt = `基于以下执行结果,生成最终回答:\n${JSON.stringify(state.results)}`;
    const result = await model.invoke(prompt);
    return { finalAnswer: result.content };
}

const workflow = new StateGraph<PlanState>()
    .addNode('planner', planner)
    .addNode('executor', executor)
    .addNode('finalizer', finalizer)
    .addEdge('__start__', 'planner')
    .addEdge('planner', 'executor')
    .addConditionalEdges('executor', shouldContinue)
    .addEdge('finalizer', END);

const app = workflow.compile();

3. Tree of Thoughts(思维树)

核心思想:同时探索多条可行路径,评估每条路径的价值,择优或回溯。

css 复制代码
目标:解决一个复杂数学问题

路径A:用代数方法 → 评估:可行,但计算量大
路径B:用几何方法 → 评估:简洁,但需要画图
路径C:用数值方法 → 评估:快速,但精度有限

选择路径B → 继续深入探索

优点 :适合高难度决策、复杂推理场景。 缺点:Token 消耗大,成本高。

4. 分层规划(Hierarchical Planning)

核心思想:高层 Agent 负责宏观目标拆分,底层 Agent 负责原子子任务执行。

css 复制代码
Level 1(战略层):目标"完成市场调研报告"
  ↓ 拆分为
Level 2(战术层):["竞品分析", "用户调研", "趋势分析"]
  ↓ 每个子任务再拆分为
Level 3(执行层):["搜索竞品A信息", "搜索竞品B信息", ...]

优点 :适合大型复杂项目,是工业级落地首选方案。 缺点:架构复杂,调试困难。

5. 反思与重规划(Reflection & Replanning)

核心思想:执行过程中持续评估计划是否还成立,不成立就重新规划。

css 复制代码
初始计划:["订场地A", "发邀请", "准备物料"]
执行中:场地A 被订走了
反思:原计划不可行,需要重规划
新计划:["订场地B", "更新邀请中的地址", "准备物料"]

关键机制:

  • 计划校验层:检测循环依赖、逻辑冲突
  • 任务状态机:记录待执行/执行中/成功/失败状态
  • 增量式调整:只修改受影响的步骤,不是全盘推翻

工程实践:用 LangGraph 实现自主规划 Agent

下面是一个完整的自主规划 Agent 案例,结合了 Plan-and-Execute + 反思重规划:

typescript 复制代码
import { StateGraph, END } from '@langgraph/graph';
import { ChatOpenAI } from '@langchain/openai';
import { TavilySearchResults } from '@langchain/community/tools/tavily_search';

// 定义状态
interface AutoPlanState {
    goal: string;           // 用户目标
    plan: string[];         // 当前计划
    stepResults: Record<number, any>;  // 每步执行结果
    currentStep: number;    // 当前执行到哪一步
    reflection: string;     // 反思结果
    maxSteps: number;       // 最大步数(防死循环)
    finalAnswer: string;
}

const model = new ChatOpenAI({ model: 'gpt-4o' });
const searchTool = new TavilySearchResults({ maxResults: 3 });

// ① 规划节点:根据目标生成计划
async function planner(state: AutoPlanState): Promise<Partial<AutoPlanState>> {
    const prompt = `你是一个任务规划专家。用户目标:${state.goal}

请将目标拆解为可执行的步骤列表。每个步骤应该:
1. 具体、可操作
2. 有明确的完成标准
3. 步骤之间逻辑连贯

输出 JSON 数组格式,例如:["步骤1", "步骤2", "步骤3"]`;

    const result = await model.invoke(prompt);
    const plan = JSON.parse(result.content);
    console.log(' 生成计划:', plan);
    return { plan, currentStep: 0, maxSteps: plan.length + 3 };
}

// ② 执行节点:执行当前步骤
async function executor(state: AutoPlanState): Promise<Partial<AutoPlanState>> {
    const currentTask = state.plan[state.currentStep];
    console.log(` 执行步骤 ${state.currentStep + 1}/${state.plan.length}: ${currentTask}`);

    // 调用搜索工具(实际项目中根据任务类型选择不同工具)
    const toolResult = await searchTool.invoke({ query: currentTask });

    return {
        stepResults: { ...state.stepResults, [state.currentStep]: toolResult },
        currentStep: state.currentStep + 1,
    };
}

// ③ 反思节点:评估执行结果,决定是否需要重规划
async function reflector(state: AutoPlanState): Promise<Partial<AutoPlanState>> {
    const currentResult = state.stepResults[state.currentStep - 1];
    const prompt = `你是任务执行的质检员。

当前目标:${state.goal}
当前步骤:${state.plan[state.currentStep - 1]}
执行结果:${JSON.stringify(currentResult)}
已完成步骤:${state.currentStep}/${state.plan.length}

请评估:
1. 当前步骤是否成功完成?
2. 原计划是否仍然可行?
3. 是否需要调整后续步骤?

输出 JSON 格式:{"success": true/false, "needReplan": true/false, "reason": "原因"}`;

    const result = await model.invoke(prompt);
    const reflection = JSON.parse(result.content);
    console.log(' 反思结果:', reflection);

    return { reflection: JSON.stringify(reflection) };
}

// ④ 重规划节点:根据反思结果调整计划
async function replanner(state: AutoPlanState): Promise<Partial<AutoPlanState>> {
    const prompt = `你是任务规划专家。原计划执行中遇到问题,需要调整。

用户目标:${state.goal}
原计划:${JSON.stringify(state.plan)}
已执行到第 ${state.currentStep} 步
执行结果:${JSON.stringify(state.stepResults)}
反思结果:${state.reflection}

请基于当前情况,生成新的计划(可以修改后续步骤,也可以增加新步骤)。
输出 JSON 数组格式。`;

    const result = await model.invoke(prompt);
    const newPlan = JSON.parse(result.content);
    console.log(' 重规划:', newPlan);

    return { plan: newPlan };
}

// ⑤ 汇总节点:生成最终答案
async function finalizer(state: AutoPlanState): Promise<Partial<AutoPlanState>> {
    const prompt = `你是任务执行主管。基于以下执行结果,生成最终回答。

用户目标:${state.goal}
执行结果:${JSON.stringify(state.stepResults)}`;

    const result = await model.invoke(prompt);
    return { finalAnswer: result.content };
}

// 条件路由:决定下一步去哪
function routeAfterExecute(state: AutoPlanState): string {
    // 超过最大步数,强制结束
    if (state.currentStep >= state.maxSteps) {
        return 'finalizer';
    }
    // 所有步骤执行完毕,进入汇总
    if (state.currentStep >= state.plan.length) {
        return 'finalizer';
    }
    // 否则进入反思
    return 'reflector';
}

function routeAfterReflect(state: AutoPlanState): string {
    const reflection = JSON.parse(state.reflection);
    if (reflection.needReplan) {
        return 'replanner';
    }
    return 'executor';
}

function routeAfterReplan(state: AutoPlanState): string {
    return 'executor';
}

// 构建工作流
const workflow = new StateGraph<AutoPlanState>()
    .addNode('planner', planner)
    .addNode('executor', executor)
    .addNode('reflector', reflector)
    .addNode('replanner', replanner)
    .addNode('finalizer', finalizer)
    .addEdge('__start__', 'planner')
    .addEdge('planner', 'executor')
    .addConditionalEdges('executor', routeAfterExecute)
    .addConditionalEdges('reflector', routeAfterReflect)
    .addConditionalEdges('replanner', routeAfterReplan)
    .addEdge('finalizer', END);

const app = workflow.compile();

// 使用
const result = await app.invoke({
    goal: '帮我调研一下 2026 年 AI Agent 领域的最新趋势,并总结三个关键方向',
});
console.log(' 最终答案:', result.finalAnswer);

关键点:

  • 规划→执行→反思→重规划 形成闭环,Agent 能根据执行结果动态调整
  • maxSteps 防死循环:设置最大步数,防止 Agent 陷入无限重规划
  • 条件路由:根据反思结果决定是继续执行、重规划还是结束
  • 结构化输出:强制 LLM 输出 JSON,便于程序解析和状态管理

自主规划的三个工程坑

1. 计划漂移

Agent 在执行过程中逐渐偏离原始目标,最后做的事和用户需求没关系了。

对策:

  • 每执行 N 步后,让 Agent 回顾原始目标,确认当前方向是否正确
  • 在 State 中保留原始 goal,每次规划时都带上
  • 设置"目标一致性检查"节点

2. 无限重规划

Agent 不断重规划但始终无法推进,陷入死循环。

对策:

  • 设置最大重规划次数(如 3 次),超过后强制结束或人工介入
  • 记录重规划历史,检测是否在同一问题上反复打转
  • 重规划时必须说明"为什么原计划不行",防止无意义调整

3. Token 爆炸

自主规划需要多次 LLM 调用(规划、执行、反思、重规划),Token 消耗远高于硬编码流程。

对策:

  • 用轻量模型做规划和反思(如 gpt-4o-mini),重模型只做最终汇总
  • 压缩上下文:只保留关键信息,丢弃中间冗余
  • 缓存历史计划:相似目标直接复用历史计划,跳过规划阶段

硬编码流程 vs 自主规划:怎么选

维度 硬编码流程 自主规划
适用场景 步骤稳定、规则明确、可穷举 路径不可预知、环境动态变化
开发成本 低,流程写死即可 高,需要设计规划/反思/重规划机制
可预测性 高,行为确定 低,每次执行路径可能不同
灵活性 低,变化需改代码 高,自动适应变化
Token 成本 低 高(多次 LLM 调用)
调试难度 低,流程固定 高,需要全链路追踪
容错性 低,异常需预设分支 高,自动重试/重规划

决策原则:

  • 能用硬编码就用硬编码:如果任务流程稳定、可穷举,硬编码更可靠、成本更低
  • 不确定性高才上自主规划:如果任务路径无法提前确定、环境动态变化,自主规划才有价值
  • 混合架构最实用:核心流程硬编码(保证稳定性),异常处理和边界情况交给自主规划(保证灵活性)

小结

  • 自主规划的本质:给 Agent 一套"目标→拆解→执行→反馈→重规划"的闭环机制,而不是硬编码流程
  • 五种规划范式:ReAct(交替推理行动)、Plan-and-Execute(先规划后执行)、Tree of Thoughts(多路径探索)、分层规划(宏观→微观)、反思重规划(动态调整)
  • 三个工程坑:计划漂移、无限重规划、Token 爆炸
  • 选型原则:能用硬编码就用硬编码,不确定性高才上自主规划,混合架构最实用
  • 核心代码模式:规划节点 → 执行节点 → 反思节点 → 条件路由 → 重规划/汇总
相关推荐
李溪白2 小时前
LangGraph 高级用法:状态管理、条件路由、人工介入的完整案例
agent
柒和远方2 小时前
DocResearch 项目面试:把每个模块讲明白,而不是背术语
python·llm·agent
拍手笑沙鸥3 小时前
系列4之「超体」工具调用与 Function Calling:给智能体装上"双手"
aigc·agent
Luhui_Dev3 小时前
数学问题在 Agent 实践中的难点
人工智能·数学·agent
柒和远方3 小时前
DocResearch 项目理解:从一条命令到一份有出处的报告
python·llm·agent
Maiko Star3 小时前
* LangChain Agent智能体详解(上):创建调用、工具绑定与系统提示词
python·langchain·agent
七夜zippoe3 小时前
Agent 自主决策机制:什么时候该检索、什么时候该直接回答
人工智能·ai·agent·检索·自主决策
沉默王二3 小时前
再见了 WebUI,DeepSeek 桌面版真不错。
openai·agent·deepseek
效率工作实验室3 小时前
用 AI Agent 做游戏数据分析,哪些场景效果最好?
ai·agent·智能体·游戏数据·游戏数据分析