面包屑图标 当前位置: 首页
AI资讯
热点详情

AI Agent实战(三):Plan Mode安全执行复杂任务

AI热点日报
AI热点日报时间:2026-06-03
热点解读

AIAgent在执行复杂任务时引入PlanMode,先探索代码库生成详细计划,经用户批准后方可执行。通过状态机管理探索、规划、等待批准、执行等阶段,并定义Plan及PlanStep数据结构与探索工具,有效降低多文件修改风险,实现事前控制。

上篇文章我们为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 = # 等待批准
    EXECUTING = ""

executing"   # oriinal execution阶段
    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": , : prompt}],
        tools=[],
        system=
    )    return self._parse_plan_response(response)

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

计划展示

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

def _show_plan(self, plan: Plan):
    """以 Markdown 格式展示计划"""    print( +  * 60)
    print()
    print( * 60)    print({plan.task}n\")    print()
    for i, step in enumerate(plan.steps, 1):
        print({i}. {step.description}\")
        if step.file_path:
            print({step.file_path}\")
        if step.action:
            print({step.action}\")
        print()    if plan.prerequisites:
        print()
        for p in plan.prerequisites:
            print({p}\")
        print()    if plan.risks:
        print()
        for r in plan.risks:
            print({r}\")
        print()    print( * 60 + )

工具集成:让探索成为 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从“批处理”走向“实时交互”的关键一步。

热点追踪提示词
你是一名 AI 行业编辑,请围绕下面这条热点输出一份资讯解读:
热点:AI Agent实战(三):Plan Mode安全执行复杂任务要求:
1. 先用一句话解释这条热点在讲什么
2. 再总结它为什么重要
3. 说明会影响哪些 AI 产品或内容方向
4. 最后给出 3 个适合资讯站使用的标题
来源:https://juejin.cn/post/7646480731195359283
ai

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关热点
AI热点2026-07-16 23:00
佑驾创新与乐动机器人达成战略合作共谋发展

佑驾创新与乐动机器人达成战略合作,围绕技术、产品、场景、数据四维度展开深度协同,旨在加速物理AI规模化落地,拓展无人车与机器人场景边界,推动具身智能商业化进程。

AI热点2026-07-16 23:00
Meta出售算力非清库存,市场需求驱动付费意愿

Meta开放AI算力租赁业务,市场反应从算力过剩转向算力商业运营。GPU从自用转向对外出租,算力从成本中心转为利润中心。AI云竞争核心从拥有GPU数量转向稳定跑满GPU的能力,依赖同步与参考时钟等底层基础设施的长期稳定运行。

AI热点2026-07-16 23:00
大仓AI工程化实战 从Vibe Coding到Harness

针对大型多仓库工程(30+微服务、10+前端微应用),搭建包含规则、技能、子代理、13阶段工作流与门禁脚本的Harness系统,解决PRD不可信、方案与代码脱节、改完无人验证、交付环节琐碎等痛点,使AI在真实业务中稳定跑完需求。

AI热点2026-07-16 22:59
MCP Toolbox部署前别急着动手

部署MCP Toolbox前,先看清它的适用场景与安全边界,避免在权限管理不完善时接入敏感数据。 核心内容: 1 MCP Toolbox的核心功能与两种使用路线 2 项目适合与不适合的团队场景分析 3 实际验证的安全检查与关键限制 先说结论 MCP Toolbox 很适合小团队研究“让 AI

延伸阅读