菜鸟AI - 让提示词生成更简单! 全站导航 全站导航
AI工具安装 新手教程 进阶教程 辅助资源 AI提示词 热点资讯 技术资讯 产业资讯 内容生成 模型技术 AI信息库

已有账号?

首页 > 资讯 > AI Agent Plan Mode实战:复杂任务安全执行全攻略
其他资讯 Mode实战

AI Agent Plan Mode实战:复杂任务安全执行全攻略

2026-06-02
阅读 0
热度 0
作者 菜鸟AI编辑部
摘要

摘要

上一篇文章我们为Agent配置了记忆系统,算是解决了一个关键痛点。不过细心的读者可能已

上一篇文章我们为Agent配置了记忆系统,算是解决了一个关键痛点。不过细心的读者可能已经注意到:当Agent接到一个复杂任务时,它时常直接动手执行——这好比让一个初级开发人员未经架构评审就直接重构核心模块,还没弄清代码依赖关系就已经改了一堆文件。等你察觉异常,代码库可能已千疮百孔。

这正好引出了今天要讨论的核心机制:Plan Mode(计划模式)。核心思路很简单:让Agent在执行之前先花时间“侦察”——深度探索代码库、生成详细实施计划,等你确认后再动手。表面上看多了一个环节,但在实际工程中,这一环节恰恰是控制风险的关键杠杆。

从零打造 AI Agent (三)—— Plan Mode:复杂任务的安全执行

为什么需要 Plan Mode?

先看一个典型场景。用户说“重构登录模块”,普通模式下的Agent会怎么操作?

用户: 重构登录模块
Agent: 直接开始修改...
       - 修改了 auth.py
       - 修改了 user.py
       - 修改了 database.py
       - 修改了 ...

发现问题了吗?问题在于,往往是Agent已经改了大量文件之后,你才意识到哪里不对——但这时候已经来不及纠正。这种“事后反馈”模式,对于简单任务还能勉强接受,可一旦涉及多文件、跨模块的修改,风险就会急速攀升。

那Plan Mode是怎么解决的呢?

用户: 重构登录模块
Agent: [进入计划模式]
       1. 探索代码库,了解登录模块结构
       2. 生成重构计划
       3. 展示计划,等待批准
       
用户: 批准
Agent: [开始执行计划]
       - 修改 auth.py
       - 修改 user.py
       仅此而已,风险可控

两者的区别一目了然。普通模式是“先斩后奏”,Plan Mode则是“先奏后斩”。

特性Normal ModePlan Mode
执行方式直接执行探索 → 计划 → 批准 → 执行
适用场景简单任务复杂/多文件修改
用户控制事后反馈事前批准
风险控制

状态机设计:让流程可追踪

要实现Plan Mode,核心在于设计一个清晰的状态机。为什么必须用状态机?因为只有明确定义每个阶段的责任和转换条件,Agent的行为才是可预测、可管控的。

                    ┌─────────────┐
                    │    IDLE     │ (普通模式)
                    └──────┬──────┘
                           │ run(plan_mode=True)
                           ▼
                    ┌─────────────┐
              ┌───▶│  EXPLORING  │ ◀──────┐
              │    └──────┬──────┘        │
              │           │ 探索完成       │ RESTART
              │           ▼               │
              │    ┌─────────────┐        │
              │    │  PLANNING   │────────┘
              │    └──────┬──────┘
              │           │ 计划生成
              │           ▼
              │    ┌─────────────┐
              │    │  PENDING    │──APPROVE──┐
              │    │ _APPROVAL   │           │
              │    └─────────────┘           │
              │           │                  │
              │    REJECT │                  │
              │           ▼                  │
              │    ┌─────────────┐           │
              └────│  ABANDONED  │           │
                   └─────────────┘           │
                                             ▼
                                    ┌─────────────┐
                                    │  EXECUTING  │──完成──COMPLETED
                                    └─────────────┘

对应的状态枚举如下:

class PlanState(Enum):
    IDLE = "idle"              # 空闲(普通模式)
    EXPLORING = "exploring"    # 探索阶段
    PLANNING = "planning"     # 规划阶段
    PENDING_APPROVAL = "pending"  # 等待批准
    EXECUTING = "executing"   # 执行阶段
    COMPLETED = "completed"    # 完成
    ABANDONED = "abandoned"    # 放弃

从IDLE到最终完成,整个流程是线性的,但值得注意的是,如果用户拒绝了计划,Agent会进入ABANDONED状态。当然,也可以从RESTART分支重新开始探索——这给了用户调整任务描述的余地。

核心数据结构:计划长什么样?

有了状态机,还得有承载信息的“容器”。这里定义了Plan和PlanStep两个数据结构。

Plan 数据结构

@dataclass
class Plan:
    task: str                  # 原始任务
    steps: list[PlanStep]     # 具体步骤
    prerequisites: list[str]  # 前置条件
    risks: list[str]          # 潜在风险
    exploration_findings: str # 探索发现
    reasoning: str            # 规划推理

注意这里多了exploration_findingsreasoning两个字段,它们记录的是Agent在探索阶段的发现和规划阶段的推理过程。这些信息对于用户判断计划是否合理至关重要。

PlanStep 数据结构

@dataclass
class PlanStep:
    id: int
    description: str           # 步骤描述
    file_path: str | None     # 涉及的文件
    action: str | None        # 具体操作

每个步骤都明确指向了具体的文件和操作,这才是可执行的计划,而不是笼统的“做某事”。

核心实现:PlanMode 类

有了数据和状态,接下来就是管理这一切的PlanMode类。

class PlanMode:
    """计划模式管理器"""    def __init__(self, agent):
        self.agent = agent
        self.state = PlanState.IDLE
        self.current_plan: Plan | None = None
        self.exploration_findings = ""    def enter_plan_mode(self, task: str):
        """进入计划模式"""
        self.state = PlanState.EXPLORING
        self.current_task = task    def set_exploring(self):
        self.state = PlanState.EXPLORING    def set_planning(self):
        self.state = PlanState.PLANNING    def set_pending_approval(self, plan: Plan):
        self.state = PlanState.PENDING_APPROVAL
        self.current_plan = plan    def approve(self):
        self.state = PlanState.EXECUTING    def reject(self):
        self.state = PlanState.ABANDONED    def complete(self):
        self.state = PlanState.COMPLETED

其实核心逻辑非常简洁:每个方法本质上就是在切换状态,同时记录当前正在处理的计划。真正的“重头戏”在于如何驱动这个流程。

工作流程

def run_plan_mode(self, user_input: str) -> str:
    """运行计划模式"""    # 1. 进入计划模式
    self.plan_mode.enter_plan_mode(user_input)    # 2. 探索阶段 - 了解代码库结构
    self.plan_mode.set_exploring()
    exploration_findings = self._explore_codebase(user_input)    # 3. 规划阶段 - 生成实施计划
    self.plan_mode.set_planning()
    plan = self._generate_plan(user_input, exploration_findings)    # 4. 展示计划,等待批准
    self.plan_mode.set_pending_approval(plan)
    self._show_plan(plan)
    approved = Confirm.ask("是否批准执行此计划?")    if not approved:
        self.plan_mode.reject()
        return "计划已取消"    # 5. 执行计划
    self.plan_mode.approve()
    return self._execute_plan(plan)

这个流程实际上就是一个“探索→规划→批准→执行”的闭环。每一步都有明确的目标和产出。

探索阶段:让 Agent 先“踩点”

为了让Agent在执行前充分了解代码库,我们新增了三个探索工具。为什么是这三个?因为它们是代码探索的“铁三角”:搜内容、找文件、批量读。

工具功能
grep正则搜索文件内容
find_files按名称查找文件
read_multiple_files批量读取文件

工具实现

# grep 搜索
@staticmethod
def grep(params: dict) -> ToolResult:
    """在指定目录下搜索匹配的文件内容"""
    path = params.get("path", ".")
    pattern = params.get("pattern", "")
    file_pattern = params.get("file_pattern", "*")    # 使用正则搜索文件
    regex = re.compile(pattern)
    matches = []    for f in Path(path).rglob(file_pattern):
        if f.is_file():
            try:
                content = f.read_text(encoding='utf-8')
                for i, line in enumerate(content.split('n'), 1):
                    if regex.search(line):
                        matches.append(f"{f}:{i}: {line.rstrip()}")
            except:
                pass    return ToolResult(
        success=True,
        content=f"找到 {len(matches)} 处匹配:n" + "n".join(matches[:50])
    )# find_files 查找
@staticmethod
def find_files(params: dict) -> ToolResult:
    """按名称查找文件"""
    path = params.get("path", ".")
    name = params.get("name", "*")
    file_type = params.get("type", "f")    results = []
    for f in Path(path).rglob(name):
        if file_type == "f" and f.is_file():
            results.append(str(f))
        elif file_type == "d" and f.is_dir():
            results.append(str(f) + "/")    return ToolResult(
        success=True,
        content=f"找到 {len(results)} 个文件:n" + "n".join(results[:50])
    )# read_multiple_files 批量读取
@staticmethod
def read_multiple_files(params: dict) -> ToolResult:
    """批量读取多个文件"""
    paths = params.get("paths", [])    results = []
    for p in paths:
        path = Path(p)
        if path.exists():
            results.append(f"=== {p} ===n{path.read_text(encoding='utf-8')}")
        else:
            results.append(f"=== {p} ===n[文件不存在]")    return ToolResult(success=True, content="nn".join(results))

探索流程

探索阶段的具体实现其实是一个组合策略:先列出项目结构,再根据任务关键词搜索相关文件,最后批量读取关键代码。

def _explore_codebase(self, task: str) -> str:
    """探索代码库,收集相关信息"""    findings = []    # 1. 列出项目结构
    structure = self.tools.execute("list_dir", {"path": "."})
    findings.append(f"项目结构:n{structure}n")    # 2. 搜索相关文件
    keywords = self._extract_keywords(task)
    for kw in keywords:
        files = self.tools.execute("find_files", {"path": ".", "name": f"*{kw}*"})
        findings.append(f"相关文件 ({kw}):n{files}n")    # 3. 读取关键代码
    # ... 根据搜索结果决定要读取的文件    return "n".join(findings)

规划阶段:从信息到行动

探索结束后,Agent手里已经握有了大量的上下文信息。接下来就是把这些信息转化为可执行的计划。

生成计划

def _generate_plan(self, task: str, exploration_findings: str) -> Plan:
    """基于探索发现生成实施计划"""    prompt = f"""用户请求: {task}探索发现:
{exploration_findings}请生成一个详细的实施计划,包括:
1. 具体步骤(每个步骤涉及哪个文件,做什么修改)
2. 前置条件
3. 潜在风险以结构化格式返回。"""    response = self.llm.create_message(
        messages=[{"role": "user", "content": prompt}],
        tools=[],
        system="你是一个规划助手,负责生成详细的实施计划。"
    )    return self._parse_plan_response(response)

这里的关键在于prompt的设计。它明确要求LLM输出“具体步骤+前置条件+潜在风险”,并且要结构化。这一点非常重要——如果LLM输出的是散文式的描述,后续的程序解析就会非常痛苦。

计划展示

生成计划后,Agent会用Markdown格式将它展示给用户。为什么要用Markdown?因为它的可读性最好,无论是终端还是Web界面都能清晰呈现。

def _show_plan(self, plan: Plan):
    """以 Markdown 格式展示计划"""    print("n" + "=" * 60)
    print(" 实施计划")
    print("=" * 60)    print(f"n 任务: {plan.task}n")    print("### 步骤n")
    for i, step in enumerate(plan.steps, 1):
        print(f"{i}. {step.description}")
        if step.file_path:
            print(f"    文件: {step.file_path}")
        if step.action:
            print(f"    操作: {step.action}")
        print()    if plan.prerequisites:
        print("### 前置条件n")
        for p in plan.prerequisites:
            print(f"- {p}")
        print()    if plan.risks:
        print("### 潜在风险n")
        for r in plan.risks:
            print(f"- ️ {r}")
        print()    print("=" * 60 + "n")

工具集成:让探索成为 Agent 的“本能”

探索工具不是孤立的,它们需要被正式注册到Agent的工具系统中。

# 注册探索工具
registry.register(Tool(
    name="grep",
    description="在目录中搜索匹配正则表达式的内容",
    parameters={
        "path": {"type": "string", "description": "搜索路径", "default": "."},
        "pattern": {"type": "string", "description": "正则表达式"},
        "file_pattern": {"type": "string", "description": "文件模式", "default": "*"},
    },
    handler=ToolHandlers.grep
))registry.register(Tool(
    name="find_files",
    description="按名称查找文件",
    parameters={
        "path": {"type": "string", "description": "搜索路径", "default": "."},
        "name": {"type": "string", "description": "文件名模式"},
        "type": {"type": "string", "description": "类型: f(文件) 或 d(目录)", "default": "f"},
    },
    handler=ToolHandlers.find_files
))registry.register(Tool(
    name="read_multiple_files",
    description="批量读取多个文件",
    parameters={
        "paths": {"type": "array", "description": "文件路径列表"},
    },
    handler=ToolHandlers.read_multiple_files
))

使用方式:两种模式,两种体验

在CLI层面,用户可以通过简单的命令切换模式:

# 普通模式(直接执行)
用户: 添加用户登录功能# 计划模式(先探索再执行)
用户: /plan 添加用户登录功能

在代码层面,只需要传入一个参数即可:

# 进入 Plan Mode
agent = Agent()
response = agent.run("重构登录模块", plan_mode=True)

执行效果预览

实际运行时的效果非常直观:

╭───────────────────────────────────────╮
│      Plan Mode - 复杂任务安全执行      │
╰───────────────────────────────────────╯ User: /plan 重构登录模块 正在探索代码库...
   - 列出项目结构
   - 搜索相关文件
   - 读取关键代码 正在生成计划...============================================================
 实施计划
============================================================ 任务: 重构登录模块### 步骤1. 提取认证逻辑到独立模块
    文件: auth.py
    操作: 重构2. 更新用户模型引用
    文件: models/user.py
    操作: 修改3. 更新相关测试
    文件: tests/test_auth.py
    操作: 修改### 前置条件- 备份现有代码
- 确保测试用例覆盖登录功能### 潜在风险- ️ 可能影响依赖旧接口的其他模块
- ️ 需要同步更新 API 文档============================================================是否批准执行此计划? [y/N]: y Agent: 开始执行计划...
    步骤 1/3: 提取认证逻辑
    步骤 2/3: 更新用户模型
    步骤 3/3: 更新测试

与 Claude Code 的对应关系

如果你用过Claude Code,会发现Plan Mode的设计思路与其非常相似。两者都遵循“先探索、再规划、后执行”的模式。

本项目Claude Code
plan.pyPlan Mode 组件
EXPLORINGResearch 阶段
PLANNINGPlanning 阶段
PENDING_APPROVALPlan 展示给用户
EXECUTING执行用户批准的计划

架构总结

整体来看,Plan Mode是Agent体系中的一个独立模块,以状态机的形式与核心循环协同工作。

┌─────────────────────────────────────────────────────────────┐
│                        Agent                                │
│                      (ReAct 核心循环)                        │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │LLMClient    │  │ToolRegistry │  │ContextManager       │  │
│  │(LLM 交互)    │  │(工具系统)    │  │(上下文管理)           │  │
│  └──────┬──────┘  └──────┬──────┘  └──────────┬──────────┘  │
│         │                │                     │            │
│         └────────────────┼─────────────────────┘            │
│                          │                                  │
│                          ▼                                  │
│                   ┌─────────────┐                           │
│                   │  PlanMode   │                           │
│                   │ (状态机)     │                           │
│                   └──────┬──────┘                           │
│                          │                                  │
│         ┌────────────────┼────────────────┐                 │
│         ▼                ▼                ▼                 │
│   ┌──────────┐     ┌──────────┐     ┌──────────┐            │
│   │EXPLORING │     │ PLANNING │     │ PENDING  │            │
│   │(探索)     │     │ (规划)   │     │ (等待)    │            │
│   └──────────┘     └──────────┘     └──────────┘            │
└─────────────────────────────────────────────────────────────┘

待优化方向

当然,目前的Plan Mode只是一个起点。以下几个方向是值得持续打磨的:

  • 支持计划修改(用户指定修改某些步骤)
  • 计划持久化(保存/加载计划)
  • 增量执行(逐步骤确认)
  • 回滚机制(执行失败时回退)
  • 探索策略优化(更智能的文件搜索)

下一步

目前我们已经完成了三个核心模块:最小可运行Agent记忆系统和今天的Plan Mode。下一个里程碑,我们将探索流式输出——让Agent的响应更加实时。这不仅仅是用户体验的提升,更是Agent从“批处理”走向“实时交互”的关键一步。

来源:互联网

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

同类文章推荐

相关文章推荐

更多