本文基于AI Mind项目真实实现整理。GitHubhttps://github.com/HWYD/ai-mind对应代码版本v0.1.1AI Mind 是一个正在持续升级的 Next.js AI Chat 项目。它从最基础的本地聊天开始逐步加入流式协议、工具调用、MCP、Skill 和 Agent 能力。如果这篇文章或者 AI Mind 项目对你有所帮助也欢迎到 GitHub 给项目点个 Star这会是对我继续更新很大的鼓励。很多 Agent 文章会默认走向一个方向让模型自己规划、自己选工具、自己决定下一步最好还能循环执行。但在这个版本里我选择了一个更保守的方案不给 Tasklist Agent 无限自由只在原有固定流程里增加一次受控的规划决策。在 v0.1.0 中AI Mind 已经有了第一个受控 Tasklist Agent用户通过/tasklist docs://versions/*.md显式引用版本方案后系统会读取方案、生成任务清单草稿、执行结构校验并在必要时最多自动修正一次。这个设计的好处是边界清楚入口明确、资源明确、工具明确、自动修正次数也明确普通聊天链路不会被 Agent 逻辑污染。但它的问题也很明显流程太固定。如果版本方案信息不足、上下文缺失或者用户输入已经超出 Tasklist Agent 的处理边界v0.1.0 只能继续往下生成或者直接失败。它缺少一个中间判断当前信息到底适不适合继续生成任务清单所以 v0.1.1 的主题可以概括为一次受控规划决策。它只在原有受控链路里增加一次规划决策Planning Decision让模型在运行时白名单允许的 5 类动作中选择下一步。如果只看真实执行链路v0.1.1 的 Tasklist Agent 可以先简化成这张图否是缺少关键版本目标选择澄清动作输入超出 Agent 能力边界选择边界停止动作需要补一点项目背景选择读取可选上下文动作方案可继续选择继续或带复核继续动作需要立即修正fixNow 0通过 / 仅人工复核/tasklist 版本方案引用入口命中fail closed提示先引用 docs://versions/*.md读取版本方案并判断方案就绪度执行规划决策让模型在 5 类安全动作action里选一个受控动作action进入停止状态本轮不生成草稿补读 1 个白名单上下文失败则带复核点继续生成任务清单拆分策略控制粒度、分组和优先级生成任务清单草稿 v1结构校验validate_tasklist_structure警告分流WarningDisposition自动修正一次生成 v2并再次校验评估修正效果RevisionEffectResult最终输出Trace 展示过程Artifact 展示 tasklist先看结论这版的核心判断可以压成一句话只放开 action 选择 不放开资源权限、工具权限、写入权限和循环权限。模型可以选择下一步但只能从运行时给出的安全动作里选。它不能自己决定读取源码不能扫描目录不能写入文件也不能无限修正。这比纯固定流程更灵活也没有把整个系统推向开放式 Planner。v0.1.0固定流程为什么还不够v0.1.0 的主链路很直接读取版本方案 - 生成任务清单草稿 v1 - 执行结构校验 - 必要时自动修正 v2 - 再次校验 - 输出最终回答这条链路已经能完成一个受控 Agent 的基本闭环。但真实版本方案并不总是完美的。有些方案信息完整可以直接生成。有些方案主体可用但缺少测试计划、非目标或风险说明应该继续生成但最终提醒人工复核。有些方案缺少核心目标继续生成会变成模型脑补。还有些输入根本不该进入 Tasklist Agent比如从裸目标生成任务清单、自动读取源码、写入 docs、扫描历史任务清单。固定流程很难细分这些情况。v0.1.1 想解决的不是“让 Agent 彻底自由”而是让它在关键位置多一次判断。第一层控制先判断方案够不够用在让模型做选择之前v0.1.1 先加了一层方案就绪度判断Plan Readiness。它回答一个问题这份版本方案够不够用来生成任务清单这一步不调用模型而是由运行时用规则判断。结果只有三类exportinterfacePlanReadinessResult{// 缺失字段比如 targetVersion、Goals、tasklistBasis。missingFields:string[]// 给 Trace 和最终摘要使用的中文原因。reason:string// ready可继续needs_review可继续但需要复核blocked不可继续。status:blocked|needs_review|ready// 弱项字段比如 Non-goals、Interface Changes、Test Plan。weakFields:string[]}比如目标版本无法识别、正文过短、缺少可拆分目标就会进入不可继续blocked。如果只是缺少测试计划或非目标则可以继续但需要在最终结果里提示人工复核。这一步很重要。模型不是从一片空白开始规划而是拿到运行时已经整理好的输入判断。换句话说方案就绪度不是为了让 Agent 更聪明而是先给 Agent 画出第一道边界。第二层控制模型只能选择 5 种动作规划决策Planning Decision是 v0.1.1 的核心变化。但这里的“规划”不是自由规划。模型只能从 5 种动作中选一个真实代码里的合同是这样的exporttypePlanningDecisionAction|{// 方案足够完整继续进入任务清单拆分策略。reason:stringtype:proceed_to_tasklist_strategy}|{// 只允许读取一个运行时白名单里的补充上下文。reason:stringresourceUri:VersionPlanTasklistOptionalContextResourceUri type:read_optional_context}|{// 缺一个关键答案时本轮输出澄清问题并停止。question:stringreason:stringtype:ask_clarification}|{// 可以继续生成但把弱项沉淀成最终人工复核点。reason:stringreviewItems:VersionPlanTasklistManualReviewItem[]type:proceed_with_manual_review_items}|{// 输入越过 Tasklist Agent 边界本轮输出边界提示并停止。message:stringreason:stringtype:stop_with_boundary_message}这 5 个动作覆盖了固定流程最需要分岔的场景。方案完整就继续生成。方案基本可用但需要补一点背景就读取一个可选上下文。缺少关键答案就提出澄清问题。存在弱项但不阻塞就带人工复核点继续。输入越界就停止。重点是模型只能选择方向不能扩大边界。第三层控制状态机决定动作能不能执行只限制模型输出还不够。如果模型选择“读取可选上下文read_optional_context”运行时还要继续判断当前状态真的允许读取吗读取的是不是白名单资源之前有没有已经读过一次这就是状态机的作用。状态机可以简单理解成一套“当前处在哪个阶段、下一步允许做什么”的规则。它常见于流程边界很明确的系统里比如订单状态流转、审批流程、任务执行器、文件上传流程或者像这里这样的 Agent 执行链路。它解决的不是“怎么生成内容”而是“系统现在走到哪一步接下来哪些动作是合法的”。在 v0.1.1 里状态机就是 Agent 的执行路线图。它不负责生成文本也不负责理解语义它只回答一个很硬的问题当前状态下这个动作能不能执行v0.1.1 的状态不是随便记几个字符串而是把 Agent 的关键阶段显式拆开exporttypeVersionPlanTasklistAgentStatus|idle|plan_read|readiness_checked|planning_decided|optional_context_read|strategy_decided|drafted_v1|validated_v1|revised_v2|validated_v2|revision_effect_evaluated|stopped|final这些状态不是为了把实现写得复杂而是为了把边界说清楚idle刚开始只能读取用户显式引用的版本方案。plan_read已经读到版本方案可以检查方案就绪度。readiness_checked已经完成规则判断可以做一次规划决策。planning_decided模型已经选择了下一步运行时才允许继续推进。optional_context_read已经读取最多一个可选上下文。strategy_decided已经确定任务清单拆分策略可以生成草稿。stopped已经澄清或边界停止不能继续生成。这带来一个很重要的效果模型说了不等于系统就做。比如读取资源这个动作真实代码里会先看当前状态if(state.statusidle){// 第一轮只能读取用户显式引用的 version plan。returnaction.resourceUristate.versionPlanReference.uri?{success:true}:{success:false}}if(state.status!planning_decided){// 补充上下文只能发生在规划决策之后。return{success:false}}constplanningDecisionstate.artifacts.planning.decisionif(planningDecision?.type!read_optional_context){// 只有 read_optional_context 决策授权后才能补读上下文。return{success:false}}这段逻辑解决的是一个常见 Agent 风险模型一旦觉得“多读一点可能更好”系统就不断打开新的资源入口。在 v0.1.1 里不会这样。只有当规划决策明确选择读取可选上下文并且当前状态已经进入planning_decided运行时才会允许读取。而且状态机还会继续检查资源 URI、读取次数和最大步数。if(action.resourceUri!planningDecision.resourceUri){// 只能读取规划决策指定的那个资源不能临时换一个。return{success:false}}if(state.counters.optionalContextReadsstate.limits.maxOptionalContextReads){// 可选上下文最多读取一次。return{success:false}}if(state.counters.stepsstate.limits.maxSteps){// Agent 总步数也有上限。return{success:false}}这里的状态机不是“流程图装饰”而是运行时硬边界。它控制了四类事情顺序必须先读方案再判断就绪度再做规划决策。 权限只有特定决策能触发特定资源读取。 次数可选上下文最多一次自动修正最多一次。 停止澄清、边界停止或达到上限后不允许继续往后跑。受控 Agent 的控制力不来自一句 prompt而来自运行时对每一步的硬约束。模型可以提出选择但状态机决定这个选择能不能执行。读取可选上下文只补读一个白名单资源规划决策里有一个动作叫读取可选上下文read_optional_context。它的设计目标很克制如果版本方案基本可用但补一份项目背景或架构边界能让拆分更稳运行时允许 Agent 读取一个白名单资源。白名单不是模型自己决定的而是代码里固定的exportconstVERSION_PLAN_TASKLIST_OPTIONAL_CONTEXT_RESOURCE_URIS[docs://README.md,docs://architecture/agent-runtime.md,docs://architecture/capability-skill-surface.md,docs://architecture/runtime-boundary.md,docs://architecture/stream-core.md,project://latest-context,]asconst这意味着模型即使选择了读取可选上下文也只能在这几个资源里选一个。它不能读源码目录不能读历史任务清单不能扫描版本方案目录也不能把这一步扩展成开放式资源选择。读取失败也不会让整个 Agent 崩掉。运行时会降级继续仍然基于原始版本方案生成任务清单同时把“补充上下文读取失败”加入人工复核点。这一步的目标不是让 Agent 无限制知道更多而是只在需要时补读一个受控上下文。拆分策略结构化地影响下一次生成这里要说清楚一点任务清单拆分策略最终仍然是通过提示词prompt影响下一次模型生成。它不是一个单独的执行器也不会直接修改草稿内容。但它和普通“多写几句提示词”不一样。v0.1.1 先让模型输出结构化的任务清单拆分策略TasklistStrategy运行时会校验它、保存它然后在生成任务清单草稿时把它明确注入 draft prompt。所以这里的关键不是“脱离 prompt”而是让 prompt 增强变得受控策略字段是固定的。输出必须通过 schema。策略会写入本轮 AgentState。后续 draft prompt 必须消费它。它只能影响粒度、步骤范围、分组和优先级不能扩大版本方案范围。真实代码里的策略结构是这样的exportinterfaceTasklistStrategy{// 预计生成多少个 Step。expectedStepRange:[number,number]// 拆分粒度粗粒度、细粒度或中等粒度。granularity:coarse|detailed|medium// Step 标题和章节优先围绕这些分组组织。grouping:string[]// checklist 和执行顺序优先遵循这些优先级。priority:string[]// 说明为什么这样拆。reason:string}在生成任务清单草稿时它会被写进草稿生成提示词变成明确的生成约束任务清单拆分策略 - Step 数量尽量落在 expectedStepRange 之间。 - Step 标题和顺序优先围绕 grouping 组织。 - 每个 Step 内 checklist 的先后顺序优先遵循 priority。 - 拆分粒度遵循 granularity。 - 不得新增版本方案中没有的能力范围。所以TasklistStrategy 不是在替代 prompt而是在把 prompt 增强从“自由文本建议”变成“结构化、可校验、由运行时注入的生成条件”。规则和模型怎么分工v0.1.1 的分工可以概括成模型负责选择和生成 运行时负责边界和判断。模型负责语义弹性更强的部分选择下一步、生成澄清问题、生成边界提示、生成拆分策略、生成草稿、修正一次草稿。规则负责确定性更强的部分方案是否够用、动作能不能执行、上下文是否在白名单、警告该自动修还是人工复核、修正是否有效、最多走多少步。如果所有判断都交给模型系统会更“聪明”但也更难测试、更难复现。如果所有东西都写成固定规则系统会很稳但不够灵活。v0.1.1 选择的是中间路线让模型参与一次方向判断但把边界控制留给运行时。不是所有 warning 都应该自动修任务清单草稿生成后会执行结构校验。v0.1.0 的规则比较粗发现问题后最多自动修一次。v0.1.1 则增加了警告分流WarningDisposition把问题分成两类exportinterfaceWarningDisposition{// 需要立即自动修正的问题编号。fixNow:string[]// 不自动修但要展示给用户确认的问题。manualReviewItems:VersionPlanTasklistManualReviewItem[]// 本次分流的说明。reason:string}结构硬伤比如缺少实施步骤、缺少清单项、缺少工程验证进入立即修正fixNow。质量弱项比如风险说明偏弱、暂停点需要人工确认则进入人工复核点manualReviewItems。这一步很小但很有工程意义。不是所有“不完美”都应该交给模型继续修。有些不确定性明确告诉人看一眼反而更可靠。修了以后还要知道有没有变好如果触发自动修正v0.1.1 还会做修正效果评估Revision Effect。它会比较 v1 和 v2 的结构校验结果exportinterfaceRevisionEffectResult{// 最终结论可采用、需人工复核或阻塞。finalDecision:blocked|final|final_with_manual_review_items// 已经修掉的问题编号。fixedIssues:string[]// 分数是否提升。improved:boolean// 仍然存在的问题编号。remainingIssues:string[]// 修正后分数。scoreAfter:number// 修正前分数。scoreBefore:number}这里同样不让模型自由总结而是基于稳定的问题编号比较。如果 v2 仍然失败最终结论会变成阻塞blocked并提示当前草稿不建议直接采用。但这一版不会继续生成 v3。原则很明确可以自动补一轮结构问题 但不能把自动修正变成无边界循环。Trace 展示过程Artifact 展示产物后端有状态机、有规则、有质量门如果前端只展示最后一段文本用户其实感知不到这些过程。所以 v0.1.1 继续强化了 Agent 执行过程面板AgentTracePanel。它展示的是轻量摘要而不是完整调试日志方案是否就绪 规划决策选择了什么动作 是否读取了可选上下文 拆分策略的粒度和步骤范围 警告分流结果 修正效果 最终决策同时最终任务清单正文不再混在普通聊天回答里而是通过 Agent 文本产物面板AgentTextArtifactPanel独立展示。最终回答分成三层执行过程AgentTracePanel 最终产物AgentTextArtifactPanel 摘要说明普通 assistant text这个分工对 AI 应用前端很重要。Agent 类应用不能只设计“最后答案”。过程应该可追踪产物应该可复制、可独立阅读摘要应该帮助用户判断当前产物是否能用。这一版刻意收住了什么更准确地说v0.1.1 只验证一件事在固定流程里开放一次受控选择权 但不顺手放开资源、工具、写入、循环和持久化。所以这一版把下面这些能力先放在边界外不把 Tasklist Agent 扩成通用 Agent Runtime 或多 Agent。不用 LangGraph 替换当前 Runtime也不做开放式规划执行。不开放自由工具调用仍然只允许结构校验这个受控工具。不自动扫描版本目录不读取历史任务清单也不从裸目标直接生成任务清单。不写入 docs 文件最终只输出可复制的任务清单草稿。不做暂停 / 恢复 / 检查点也不持久化 AgentState。不生成 v3 自动修正不把 Artifact 做成产物工作台。这样写边界不是为了证明“还没做什么”而是为了保护本版主题当模型只有一次选择权时运行时能不能仍然把这次选择控制住。这版证明了什么v0.1.1 最重要的结论不是“模型会规划了”。更准确地说它证明的是一个固定流程 Agent可以先演进成有限决策 Agent。这中间不一定要一步跳到自由规划。在这版里模型只做一次选择。选择范围只有 5 种。资源只能读白名单。工具只有结构校验。自动修正最多一次。最终不写入文件。什么时候停止由状态机决定。但即便限制这么多Agent 的行为已经比固定流程更灵活。它可以在方案太弱时提出澄清问题。它可以在输入越界时停止。它可以在方案可用但有风险时带人工复核点继续。它可以在需要时补读一个受控上下文。它可以用拆分策略影响最终草稿。这就是“一次受控规划决策”的价值在受控系统里增加一点可解释的弹性。后续方向v0.1.1 之后我更想继续沿着“受控增强”的路线推进。后续更值得评估的是Agent Trace 持久化 任务清单草稿保存与人工确认流 更完整的 Agent 动作执行器 和 LangGraph 做边界清晰的对照实验这些都不应该回填到 v0.1.1。这一版已经完成了它该完成的事情让第一个 Tasklist Agent 从固定流程迈到一次有限决策。结尾AI Mind v0.1.1 做的是一件很小、但对我很关键的事在一条已经受控的任务清单生成链路里让模型获得一次有限选择权再用运行时状态机、白名单、规则判断、质量门和前端展示把这次选择落住。这版真正让我确认的是Agent 工程化不一定从“自由规划”开始 也可以从“固定流程里的第一次受控分岔”开始。这也是我目前更认可的 Agent 演进路线先让它可控 再让它有限选择 最后再讨论更开放的规划执行。项目地址 GitHubhttps://github.com/HWYD/ai-mind 线上体验https://ai.hwyblog.cloud/instant-mind如果这篇文章或者 AI Mind 项目对你有所帮助也欢迎给项目点个 Star⭐。你的支持会是我持续更新这个系列、继续整理项目实现过程和设计复盘的很大动力。