news 2026/9/15 12:19:41

Kimi Code CLI 计划模式(Plan Mode)全解析:从 EnterPlanMode 到 ExitPlanMode 的规划与审批工作流

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kimi Code CLI 计划模式(Plan Mode)全解析:从 EnterPlanMode 到 ExitPlanMode 的规划与审批工作流

Kimi Code CLI 计划模式(Plan Mode)全解析:从 EnterPlanMode 到 ExitPlanMode 的规划与审批工作流

【免费下载链接】kimi-cliKimi Code CLI is your next CLI agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kimi-cli

导读

Kimi Code CLI 内置了一套"先规划、后执行"的计划模式(Plan Mode),让 Agent 在动手改代码前先产出可评审的实现方案,并通过ExitPlanMode工具将方案提交给用户审批。本文以 ExitPlanMode 工具描述文档 为核心,结合 EnterPlanMode 实现、ExitPlanMode 实现(注:实际为__init__.py,见下文)与 plan_mode 动态注入 等源码,完整讲解计划模式的工作机制、options多方案参数、Yolo/Afk 模式下的自动审批行为,以及 AskUserQuestion 与计划审批的边界。读完本文,你将掌握如何在 Kimi Code CLI 的 Agent 会话中正确驱动一次"探索 → 设计 → 写方案 → 审批 → 执行"的完整规划闭环。

ExitPlanMode:计划审批的入口工具

ExitPlanMode是计划模式的核心收尾工具,其官方描述位于 src/kimi_cli/tools/plan/description.md,定义如下:

Use this tool when you are in plan mode and have finished writing your plan to the plan file and are ready for user approval.

也就是说:只有当你处于计划模式、且已经把完整方案写入 plan 文件、准备请求用户批准时,才调用该工具。它的行为在 src/kimi_cli/tools/plan/init.py 中实现,工具名常量NAME = "ExitPlanMode",描述直接由load_desc(Path(__file__).parent / "description.md")从该 Markdown 文件加载(第 28-31 行 为 EnterPlanMode 的对应加载方式,ExitPlanMode 同理)。

工作原理:方案从文件读取,而非参数传入

文档明确强调了一条关键设计:

  • 该工具不接收计划内容作为参数——它从你写入的 plan 文件中读取方案;
  • 用户在评审时,看到的就是你 plan 文件中的完整内容。

源码印证了这一设计:ExitPlanMode.__call__首先通过plan_path = self._plan_file_path_getter()拿到当前会话的 plan 文件路径,然后读取其文本内容(src/kimi_cli/tools/plan/init.py#L121-L132):

plan_path = self._plan_file_path_getter() plan_content: str | None = None if plan_path and await asyncio.to_thread(plan_path.exists): plan_content = await asyncio.to_thread(plan_path.read_text, encoding="utf-8") if not plan_content: return ToolError( message=f"No plan file found. Write your plan to {plan_path} first, " "then call ExitPlanMode.", brief="No plan file", )

如果 plan 文件不存在或为空,工具会直接返回错误:"没有找到 plan 文件,请先把方案写入{plan_path},再调用 ExitPlanMode"。这意味着在调用 ExitPlanMode 之前,Agent 必须已经用 WriteFile 或 StrReplaceFile 创建并写好了 plan 文件

使用时机:只用于实现类任务

文档对"何时使用"给出了明确限定:

  • 应当使用:需要规划实现步骤的任务(如新功能开发、多文件改动、架构决策);
  • 绝不使用:纯研究类任务(搜索文件、阅读代码、理解代码库),这类任务不应调用 ExitPlanMode。

这与 src/kimi_cli/agents/default/plan.yaml 中 plan 子代理(subagent)的定位完全一致:plan 子代理被描述为"Read-only implementation planning and architecture design",用于在改动代码前产出分步实现计划、关键文件识别与架构权衡分析。

options 参数:向用户呈现多个候选方案

当你的计划中包含多种可选的实现路径时,文档要求通过options参数把它们传给 ExitPlanMode,让用户在审批时直接选择执行哪一条:

  • 每个 option 需要有一个简洁的标签(label)和简短的权衡说明(description);
  • 如果你推荐其中某个方案,在其标签后追加"(Recommended)"
  • 用户会同时看到所有 option,以及系统自动追加的 "Reject" 和 "Revise" 选项;
  • 最多提供 2-3 个方案(系统会自动追加一个 "Reject" 选项,所以用户最终看到 3-4 个选项);
  • 严禁使用 "Reject"、"Revise"、"Approve" 作为 option 的标签——这些是系统保留标签。

参数模型与校验规则

源码中Params模型定义了options字段(src/kimi_cli/tools/plan/init.py#L58-L78):

class PlanOption(BaseModel): label: str = Field( description=( "Short name for this option (1-8 words). " "Append '(Recommended)' if you recommend this option." ), ) description: str = Field( default="", description="Brief summary of this approach and its trade-offs.", ) class Params(BaseModel): options: list[PlanOption] | None = Field( default=None, max_length=3, description=( "When the plan contains multiple alternative approaches, list them here " "so the user can choose which one to execute. 2-3 options. " "Do not use 'Reject', 'Revise', 'Approve', or 'Reject and Exit' as labels." ), )

同时有两道内置校验:

  1. 保留标签校验PlanOption.label_not_reserved会把标签小写化后与_RESERVED_LABELS = {"reject", "revise", "approve", "reject and exit"}比对,命中即报错(第 30 行);
  2. 唯一性校验options_labels_unique要求所有 option 标签互不相同,重复会触发ValueError

有无 options 时审批界面的差异

源码展示了两种截然不同的审批呈现方式(src/kimi_cli/tools/plan/init.py#L167-L214):

  • 有 options(≥2 个)has_options = params.options is not None and len(params.options) >= 2,界面列出每个 option 作为可选按钮,并追加 "Reject"(留在计划模式)与 "Reject and Exit"(退出计划模式)两个选项;
  • 无 options:界面显示 "Approve"(退出计划模式并开始执行)、"Reject"、"Reject and Exit" 三个按钮;
  • 无论哪种情况,都通过other_label="Revise"提供一个自由文本修订入口,用户可输入反馈要求 Agent 留在计划模式中继续修改方案。

用户选择后的六种结果分支

ExitPlanMode对用户响应做了完整的分类处理(src/kimi_cli/tools/plan/init.py#L234-L339):

用户选择行为返回类型
Approve(单选方案)退出计划模式,返回完整已批准方案,所有工具恢复可用ToolReturnValue
选中某个 option退出计划模式,只执行被选中的方案,忽略计划中的其他方案ToolReturnValue
Reject and Exit退出计划模式,等待用户下一条消息ToolRejectedError
Reject留在计划模式,等待用户反馈后修订ToolRejectedError
Revise(带/不带反馈)留在计划模式,根据反馈修订方案ToolReturnValue
直接关闭(dismissed)计划模式保持激活,可继续完善方案或再次调用ToolReturnValue

特别值得注意的是:当用户批准的是某个具体 option 时,工具返回的输出中会明确写入IMPORTANT: Execute ONLY the selected approach "{chosen_option}". Ignore other approaches in the plan.——这是为了让执行阶段严格收敛到用户选择的路径上,避免 Agent 混用多个方案。

使用前须知:Yolo、Afk 与 AskUserQuestion 的边界

文档在 "Before Using" 一节定义了计划审批与其他机制的关键边界,这些规则全部在源码中有对应实现:

Yolo 模式不豁免计划审批

  • Yolo 模式只绕过权限审批,不会让会话变成非交互
  • 在 Yolo 模式下,EnterPlanMode 会被自动批准,但ExitPlanMode 仍会把方案呈现在用户面前等待批准

源码中 EnterPlanMode 将is_yolo作为自动进入的判定(src/kimi_cli/tools/plan/enter.py#L49-L55):

self._is_auto_approve = is_auto_approve or is_yolo

而 ExitPlanMode 的自动批准只绑定should_auto_approve_exit回调(src/kimi_cli/tools/plan/init.py#L91-L104),并不会因为 Yolo 而跳过用户审批。

Afk 模式下的自动批准

  • Afk 模式同时绕过权限审批且非交互
  • 在 Afk 模式下不要使用 AskUserQuestion,而是基于现有上下文做最佳决策;
  • EnterPlanMode 与 ExitPlanMode 在 Afk 模式下都会被自动批准,因为此时没有用户在场。

源码中 ExitPlanMode 的自动批准分支会直接调用_toggle_callback()退出计划模式,并返回"Plan approved (auto-approved)"及完整方案内容(src/kimi_cli/tools/plan/init.py#L134-L150)。

AskUserQuestion 的职责边界

文档给出了非常明确的提示词纪律:

  • 如果尚未进入 Afk 且还有未解决的问题,先用 AskUserQuestion 澄清
  • 如果有多个方案且尚未收敛,考虑先用 AskUserQuestion 让用户选方向,然后只为被选中的方向写方案;
  • 绝不能用 AskUserQuestion 问"这个方案可以吗?"或"我该继续吗?"——那正是 ExitPlanMode 的职责;
  • 方案被拒绝后,根据反馈修订,然后再次调用 ExitPlanMode

这套纪律在 plan_mode 动态注入提醒 中被反复强化:"Never ask about plan approval via text or AskUserQuestion"、"Do NOT use AskUserQuestion to ask about plan approval or reference 'the plan'——the user cannot see the plan until you call ExitPlanMode"。

EnterPlanMode:进入计划模式的前置工具

完整的规划闭环从 EnterPlanMode 开始,其使用说明在 enter_description.md 中。文档建议:当你即将开始一项非平凡的实现任务时,主动使用它,在写代码前先获得用户对方案的认可,避免返工。

适用条件(满足任意一条即建议使用)

  1. 新功能实现——例如"给 API 增加缓存层";
  2. 存在多个有效方案——例如"优化数据库查询"(索引 vs 重写 vs 缓存);
  3. 代码改造——例如"重构 auth 模块以支持 OAuth";
  4. 架构决策——例如"添加 WebSocket 支持";
  5. 多文件改动——涉及超过 2-3 个文件;
  6. 需求不明确——需要探索来确定范围;
  7. 用户偏好会影响实现——用户的输入会实质性地改变实现路径。

何时不要使用

  • 单行或几行的修复(拼写错误、明显 bug、小调整);
  • 用户已给出非常具体、详细的指示;
  • 纯研究/探索类任务。

进入计划模式后的标准工作流

enter_description.md定义了进入计划模式后 Agent 应当遵循的五步流程:

  1. 识别 2-3 个对方案至关重要的代码库关键问题;如果对代码库结构或相关路径没有把握,优先用Agent(subagent_type="explore")去调查(对非平凡任务强烈推荐);
  2. 用 Glob、Grep、ReadFile 等只读工具快速查证剩余问题;
  3. 基于调查结果设计实现方案
  4. 将方案写入 plan 文件
  5. 通过ExitPlanMode 向用户呈交方案并等待批准。

这一流程与 plan 子代理(plan.yaml)的建议一脉相承:在产出实现计划前,先明确"已知道什么"与"还需要 explore 调查什么"。

交互实现:确认对话框与自动进入

EnterPlanMode的实现细节(src/kimi_cli/tools/plan/enter.py#L57-L197):

  • 重复进入防护:若已在计划模式,返回错误"Already in plan mode. Use ExitPlanMode when your plan is ready.";
  • 自动进入:在 Yolo/Afk 等自动审批场景下直接激活计划模式,并返回工作流指引;
  • 交互确认:通过 Wire 协议发送QuestionRequest,向用户弹出一个"Enter plan mode?"问题,提供 Yes/No 两个选项;
  • 用户拒绝:返回"User declined to enter plan mode",Agent 需与用户确认是否直接开始实现;
  • 用户关闭对话框:按"直接开始实现"处理;
  • 客户端不支持:返回错误并明确指示"不要再调用此工具"("Do NOT call this tool again")。

进入成功后,返回给 Agent 的提示会强调:"Plan mode activated. You MUST NOT edit code files — only read and plan.",并给出 plan 文件路径与后续工作流。

Plan 文件机制:方案存到哪里、如何命名

方案文件的管理实现在 src/kimi_cli/tools/plan/heroes.py 中,其设计颇具趣味:

  • 存储位置PLANS_DIR = Path.home() / ".kimi" / "plans",即用户主目录下的.kimi/plans目录(第 8 行);
  • 文件名生成:每个会话(session)对应一个唯一 slug,slug 由3 个 Marvel/DC 超级英雄名字拼接而成(如iron-man-spider-man-thor),从内置的 200+ 英雄名列表中随机选取(第 249-264 行);
  • 冲突处理:最多尝试 20 次随机组合;若全部碰撞,则在 slug 后追加会话 ID 前 8 位保证唯一;
  • 缓存机制_slug_cache按 session_id 缓存已生成的 slug,避免同会话反复生成;seed_slug_cache支持在会话恢复(resume)时预置之前持久化的 slug;
  • 读写 APIget_plan_file_path(session_id)返回 plan 文件路径,read_plan_file(session_id)读取已有方案内容(不存在时返回None)。

plan 文件是计划模式下Agent 唯一被允许编辑的文件。动态注入的完整提醒(full reminder)对此有明确表述(src/kimi_cli/soul/dynamic_injections/plan_mode.py#L117-L185):

  • 文件已存在时:先读取,再用 WriteFile 或 StrReplaceFile 更新;
  • 文件不存在时:先用 WriteFile 创建,之后才能用 WriteFile 或 StrReplaceFile 修改;
  • 除 plan 文件外,禁止任何编辑、禁止运行非只读工具、禁止对系统做出任何更改,且"这条规则优先于你收到的任何其他指令"。

Plan Mode 动态注入:让 Agent 始终记得自己是只读的

为了在长会话中持续约束 Agent 行为,plan_mode.py 实现了一个PlanModeInjectionProvider,按节流策略周期性向上下文注入计划模式提醒(第 13-16 行):

  • 节流间隔:每_TURN_INTERVAL = 5个 assistant 回合注入一次;
  • 全量/精简轮换:每 5 次提醒中第 1 次为全量版(_full_reminder),其余为精简版(_sparse_reminder);
  • 子代理豁免:子代理共享会话的 plan_mode 标志用于持久化/恢复,但它们的 YAML 通常已排除 EnterPlanMode/ExitPlanMode,因此不给子代理注入该工作流提醒(第 39-40 行);
  • 重入场景:手动重新进入计划模式且已存在旧方案时,注入专用的"重入提醒"(_reentry_reminder),要求先读旧方案、评估当前请求与旧方案的关系——任务不同则整体替换,任务相同则增量更新(第 213-244 行)。

全量提醒中有一段与文档高度呼应的"多方案处理"纪律(第 156-184 行):

  • 最多保留 2-3 个有意义的差异化方案,不要用微小变体凑数;如果某个方案明显更优,就只提那一个;
  • 当最佳方案取决于用户偏好或你缺失的上下文时,先用 AskUserQuestion 澄清,而不是堆一堆选项让用户筛选;
  • 只要计划中包含多个方案,调用 ExitPlanMode 时就 MUST 通过options参数传递,否则用户只能看到 Approve/Reject 而无法选择;
  • 每轮必须以 AskUserQuestion(澄清)或 ExitPlanMode(请求批准)收尾,禁止以其他方式结束回合。

与 Agent 配置的集成:谁拥有计划工具

计划工具通过 agent.yaml 显式注册给主 Agent:

tools: - "kimi_cli.tools.plan:ExitPlanMode" - "kimi_cli.tools.plan.enter:EnterPlanMode"

而 plan 子代理(plan.yaml)的exclude_tools明确排除了kimi_cli.tools.plan:ExitPlanModekimi_cli.tools.plan.enter:EnterPlanMode,同时排除了 AskUserQuestion、Shell、WriteFile、StrReplaceFile 等工具,其allowed_tools仅保留 ReadFile、ReadMediaFile、Glob、Grep、SearchWeb、FetchURL 等只读工具——这与"plan 子代理只读规划、审批权归主 Agent"的架构完全吻合,也与动态注入中"不给子代理注入 plan 提醒"的设计互为印证。

源码与测试验证:行为有据可依

计划模式的各项行为都有测试用例背书(tests/core/test_plan_mode.py):

  • 英雄名 slug 生成TestHeroSlug系列用例验证随机 slug 生成、会话级缓存(同一会话复用同一 slug)、不同会话 slug 不同、以及 20 次碰撞后的回退逻辑;
  • 守卫条件TestExitPlanModeGuards验证"不在计划模式时调用报错"、"工具未正确初始化报错"、"plan 文件不存在时报错"等防御分支;
  • 审批快乐路径TestExitPlanModeHappyPaths覆盖 Approve(退出并返回方案)、Reject(返回ToolRejectedError且留在计划模式)、Revise 带/不带反馈、用户直接关闭、客户端不支持 Question 协议、Question 请求异常等全部分支;
  • 动态注入:验证手动切换进入计划模式时激活注入延迟到下一个 LLM 步骤、子代理在根 Agent 处于计划模式时不接收注入等行为。

这些测试与 description.md 中的每一条规则一一对应,读者可以通过阅读测试了解工具在各种边界条件下的精确行为。

实战要点速查

  1. 进入:非平凡实现任务开始前调用EnterPlanMode,通过用户确认或自动审批进入只读规划状态;
  2. 调研:用 explore 子代理 + Glob/Grep/ReadFile 摸清代码库,必要时用 AskUserQuestion 澄清需求或收敛方向;
  3. 写方案:将方案写入~/.kimi/plans/<英雄名组合>.md(唯一可编辑文件);
  4. 多方案:计划含 2-3 个候选路径时,必须通过options参数传递并标注(Recommended),且不得使用系统保留标签;
  5. 提交:调用ExitPlanMode等待用户 Approve / 选择方案 / Reject / Revise;
  6. 执行:批准后计划模式退出、所有工具恢复;若用户选了具体方案,只执行该方案
  7. 被拒后:根据反馈修订 plan 文件,再次调用 ExitPlanMode;
  8. 边界:Yolo 不豁免 ExitPlanMode 审批;Afk 下两者均自动批准;AskUserQuestion 只用于澄清,绝不用来问"方案行不行"。

通过以上流程,Kimi Code CLI 的 Agent 能够在改代码前与用户对齐实现方案,将返工成本降到最低——这正是 plan 工具族 与 plan_mode 动态注入 协同工作的核心价值。

【免费下载链接】kimi-cliKimi Code CLI is your next CLI agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kimi-cli

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 12:18:46

Linux内核VXLAN收发包流程详解:从FDB查表到MTU调优

做Linux网络内核调试的人&#xff0c;几乎都绕不开VXLAN。K8s里Flannel的VXLAN后端、OpenStack里的overlay网络、各种容器网络方案&#xff0c;喊的都是同一个东西&#xff1a;用UDP隧道把二层帧送到远端。很多人对“VXLAN原理”聊得头头是道&#xff0c;但一落到内核里就会懵—…

作者头像 李华
网站建设 2026/9/15 12:18:26

透明变电站数字孪生建设指南:六类公司技术路线与选型避坑全解读

这两年&#xff0c;只要和电力运维沾边的项目&#xff0c;讨论到最后基本都能落到一个词上&#xff1a;透明变电站。我自己的直观感受是&#xff0c;这个词已经从概念PPT里走了出来&#xff0c;变成越来越多电网单位、工业用户、EPC总包方真正立项掏钱的方向。可我接触过不少业…

作者头像 李华
网站建设 2026/9/15 12:18:00

Java+Python混合架构:企业级模型评估平台后端设计实践

简介&#xff1a;面向AI模型评估场景的后端设计源码&#xff0c;主体采用Java构建服务端核心框架&#xff0c;并加入Python脚本处理与模型评估相关的数据处理逻辑&#xff0c;适合后端开发工程师、AI平台研发人员以及高校实验平台建设者阅读与二次开发。压缩包共76个文件&#…

作者头像 李华
网站建设 2026/9/15 12:17:27

ROS-I simple_message协议深度解析:工业机器人实时通信核心

1. 项目概述&#xff1a;从一条“简单消息”看工业机器人通信的底层逻辑你有没有在调试ABB或KUKA机器人时&#xff0c;突然发现ROS节点发出去的指令像石沉大海&#xff1f;明明topic名称对得上&#xff0c;rostopic echo也显示数据在流动&#xff0c;但机械臂就是纹丝不动——最…

作者头像 李华
网站建设 2026/9/15 12:16:53

OpenHarmony高性能图像列表渲染优化实践

1. 项目背景与核心挑战在OpenHarmony生态中实现高性能图像列表渲染一直是个棘手问题。传统方案在加载网络图片时往往需要完整下载后才能获取尺寸信息&#xff0c;导致列表布局频繁重排&#xff0c;严重影响滚动流畅度。image_size_getter_http_input组件正是为解决这一痛点而生…

作者头像 李华
网站建设 2026/9/15 12:16:49

ARIA属性实战指南:从语义契约到键盘导航与状态同步

1. 这不是“加个标签”就完事的适配——无障碍到底在适配什么&#xff1f;无障碍适配这个词&#xff0c;最近在开发圈、设计圈甚至产品会上被提得越来越频繁。但说实话&#xff0c;我见过太多团队把“做了无障碍”当成一个交付 checklist 上的勾选项&#xff1a;加几个aria-lab…

作者头像 李华