AI Agent 工程实践(37):需求分析——一个 Agent 项目到底应该怎么拆

AI Agent 工程实践(37):需求分析——一个 Agent 项目到底应该怎么拆 发布时间2026-08-30标签AI Agent工程实践需求分析Agent 架构上一篇AI Agent 工程实践36不要再写 Agent 教程——先定义一个真实问题下一篇AI Agent 工程实践38从需求到 Agent 架构——为什么需要这些节点上一篇我定了方向仓库诊断这个任务值得用 Agent 做。但值得做离能开工之间还隔着一道很深的沟。朋友问我那你到底要做什么我说做一个能诊断代码仓库的 Agent。他追问它接收什么产出什么中间能碰哪些系统哪些东西它得记住哪些事它绝对不能做我张了张嘴发现一个都答不利索。那一刻我明白了我有一个想法和我理解了需求是两件完全不同的事。而把需求想清楚这件事在 Agent 项目里比传统软件项目难得多——因为你要面对的不是一个输入→输出的函数而是一个会自己决定下一步干什么的大模型。问题背景这是第五阶段的第二篇。上一篇解决了选对问题这一篇解决选对之后怎么把一句模糊的需求翻译成 Agent 能执行的确定性。先说清楚一件事这里的拆需求不是画产品原型也不是写接口文档而是把需求拆成 Agent 能理解的八个槽位。这是 Agent 项目和传统软件项目在需求阶段最大的不同。传统软件的需求分析产出的是功能清单和页面流程而 Agent 的需求分析产出的是八个能力槽——因为你最终要面对的是一个大模型它不像代码那样有确定的输入输出你必须先想清楚喂给它什么、允许它碰什么、要求它记住什么、禁止它做什么。为什么传统需求分析在这套不了因为传统软件的需求是写给代码看的——代码不自由发挥你写清楚输入 A 输出 B它就不会输出 C。但 Agent 的需求是写给模型看的——模型会自由发挥你的需求里少定义一个绝对不能做的事它就真的可能去做。所以 Agent 需求分析的核心不是定义功能而是定义边界哪些能做、哪些不能做、边界在哪。错误尝试第一次尝试一句话需求直接开写我最初的做法很天真直接开写。我的第一版需求文档只有一句话——做一个能帮我分析仓库的 Agent用 LangGraph 实现。然后就跑去搭环境、装依赖、写第一个工具。结果写到一半就卡住了用户问这个 bug 在哪我到底该让它读几个文件读到什么程度算找到它能不能执行git checkout它给出的结论要不要附带证据每一个问题都让我停下来重新想而每重新想一次前面写好的代码就得推倒一块。需求没拆清楚就开始写代码就像没画图纸就盖楼——每一堵墙都在返工。更糟的是因为需求是模糊的我对做完没有也完全没有标准只能靠感觉。这种感觉驱动的开发在 Agent 项目里尤其危险因为 Agent 的输出本身就是不确定的你连一个对的输出长什么样都说不清。第二次尝试以为想清楚了就够了没写下来第一次失败后我吸取了要拆需求的教训但犯了第二个错只在脑子里拆没落到纸上。我想嗯输入是用户问题输出是诊断结论工具就是那几个边界是只读不改。——自认为已经想清楚了于是又开始写代码。结果写到一半发现我想的那几个工具只有三个但写的时候发现还需要读 git 历史我以为只读不改就够了但用户实际会问帮我修这个 bug那改代码到底算不算这些模糊点因为没写下来每次都是写到那个位置才被迫面对又变成了返工。以为想清楚了和真的写清楚了差距巨大。脑子里的需求会自动补全那些你没定义的槽——你以为你想过其实你只是默认了。关键观察八个问题转折点来自一个很土的办法我把需求拆成了八个问题逼自己逐个回答。回答不出来的就说明我还没想清楚。这八个问题后来成了我拆所有 Agent 项目的固定框架Input进来的是什么Task它要干哪几类事State干的过程中它要记住哪些中间状态Tools它能调用哪些外部能力Knowledge它需要哪些静态知识Memory跨会话它要长期记住什么Policy哪些事它绝对不能做Output出来的是什么为什么是这八个因为它们恰好覆盖了 Agent 项目里必须提前想清楚的八个边界输入边界Input、任务边界Task、状态边界State、能力边界Tools、知识边界Knowledge、记忆边界Memory、行为边界Policy、输出边界Output。任何一个没定义清楚Agent 就会在运行期用自由发挥替你补一个错误答案。核心洞察是拆需求的过程就是把你脑子里的模糊翻译成 Agent 能执行的确定性。八个槽填满的那一刻做完才有了定义。最终方案把 Repo Doctor 拆进八个槽拿我们的贯穿项目 Repo Doctor 来实操逐个槽填满。每个槽我都会给是什么 一个反例不定义清楚的后果1. Input输入用户的自然语言问句这个项目里支付逻辑在哪一个本地仓库的路径Agent 的操作范围锚点反例如果只定义用户问句不定义仓库路径锚点Agent 就会在多个仓库间乱窜甚至去读用户的整个磁盘。2. Task任务三种bug 定位从现象反查代码找到根因代码解释讲清某段逻辑是干嘛的PR review评估一次改动的风险反例如果只定义诊断一个大类不拆成三种子任务Agent 就会把解释代码和审查 PR混为一谈——该解释时去挑毛病该审查时去背文档。3. State中间状态已读过的文件列表已确认的线索支付入口在 order.py当前假设怀疑是回调没注册待验证的疑点队列反例如果不定义 StateAgent 就会重复读同一个文件、忘记自己查过什么——这正是第 40 篇State Error的高发区。4. Tools工具grep搜代码、read_file读文件、git_log看历史、run_test跑测试反例如果不限定工具集Agent 可能去调用写文件删文件这类危险工具——所以 Tools 槽的另一个作用是能力白名单。5. Knowledge静态知识目标框架的 API 用法如 FastAPI 的路由、依赖注入常见报错模式库这个报错通常是 xx 原因反例如果没有 KnowledgeAgent 面对不熟悉的框架时会瞎猜 API 用法产生幻觉。6. Memory跨会话记忆这个仓库的目录结构、核心模块分布之前诊断过的历史结论上次这个 bug 是 xx 修的反例如果没有 Memory同一个仓库每次诊断都要从零摸结构浪费时间上周修过的 bug这周又当新问题查。7. Policy红线只读不写绝不修改任何文件不碰.git内部不读取、不输出.env、密钥等敏感内容反例这是最不能省的槽。没有 Policy用户说一句帮我看看 .env 里有什么Agent 可能真的读出来给你——这是真实发生过的事。8. Output输出诊断结论 证据链每个结论都要指向具体的文件行修复建议可选但不直接改代码反例如果不强制证据链Agent 就会给出没有根据的结论——可能是数据库问题这种话你无法验证它是对是错。八个槽填完你会发现一个神奇的变化做完没有第一次有了客观标准——它答对了没有就看它的结论有没有证据、证据对不对得上文件。架构图 / 流程图八个槽的关系不是平铺的它们之间有一条数据流向。画出来是这样关键在中间那个闭环State → 调用 Tools → 回到 State这是 Agent 区别于普通函数的核心——它在执行中不断更新自己的认知直到认为证据够了才走向 Output。这个状态驱动的调查闭环就是第 39 篇要动手实现的第一个东西。第二张图八槽的生命周期视角发布提示可用 draw.io 重画成正式图与 Mermaid 图形成双图组合┌───────────────────────────────────────┐ │ 一次任务的生命周期 │ └───────────────────────────────────────┘ 进来: Input(问句仓库) ─→ Task(识别类型) ─→ Policy(红线过滤) │ 执行: ┌──────────── 循环 ────────────┐ │ │ State(当前认知) │ │ │ │ 调用 │ │ │ ▼ │ │ │ Tools / Knowledge ─→ 新证据 │◄──────────┘ │ │ 更新 │ │ └──→ 回到 State │ └───────────────────────────────┘ │ 出来: State 证据够 → Memory 沉淀 → Output(结论证据)这张图强调的是Policy 是整个循环的外圈护栏——它不参与循环但约束循环里的每一步。八槽里最容易漏的就是这个外圈护栏Policy因为它不产生输出、只防止错误输出。代码或配置示例八个槽不是纸面概念我会把它落成一份真实的配置骨架作为整个项目的需求底座# repo_doctor/requirements.yaml —— 需求拆解的唯一事实源 agent: name: Repo Doctor input: - query: string # 用户问句 - repo_path: string # 仓库根路径 tasks: - bug_locate # 定位 bug - code_explain # 解释代码 - pr_review # PR 审查 state: - files_read: [] # 已读文件 - clues: [] # 已确认线索 - hypothesis: null # 当前假设 - pending: [] # 待验证疑点 tools: - grep - read_file - git_log - run_test knowledge: - framework_api: fastapi - error_patterns: true memory: - repo_structure # 记住仓库结构 - past_diagnostics # 记住历史诊断 policy: - read_only: true # 只读 - no_dot_git: true # 不碰 .git - no_secrets: true # 不泄露敏感信息 output: - conclusion: string - evidence: [] # 证据链必填 - suggestion: optional这份 YAML 的价值在于它把我大概知道要做什么钉成了每个槽是什么、边界在哪。后面所有代码都是对这份需求的翻译。为了让八槽不流于形式我还会给每槽加一条验收标准——填槽时问自己这条写清楚了没有# 八槽验收清单填槽时自问 acceptance: input: 能举出 3 种典型输入并知道边界什么不该收 task: 能列全任务类型并说清每类的判定特征 state: 能列出运行中必须记住的所有中间信息 tools: 能列出能力白名单并标注哪些是危险项 knowledge: 能列出 Agent 必须提前知道、不能靠猜的东西 memory: 能区分会话内与跨会话各记什么 policy: 能列出 3 条以上绝对红线 output: 能定义结论必须带证据这类硬约束设计权衡候选方案优点缺点为什么不选只写一句需求就开干快写到一半反复返工做完没标准需求模糊是 Agent 返工的根因写 50 页 PRD详尽太重Agent 需求大多 8 个槽就够过度设计拖慢启动八槽拆解法边界清晰、够用槽与槽之间有耦合需再梳理正好卡在够用和清晰之间一个诚实的边界八个槽不是银弹。对于特别复杂的 Agent比如要对接几十个系统你可能需要更细的拆解但对于从零做一个项目这个阶段八个槽是性价比最高的框架——它逼你想清楚又不至于把你拖进文档泥潭。另一个提醒槽与槽之间有耦合。比如 Policy 会限制 Tools只读意味着删掉所有写工具、Output 依赖 State证据链来自中间状态。填槽时不要孤立地填要顺着数据流走一遍确认八个槽能串成一条自洽的链路。常见误区FAQQ1八槽和写接口文档有什么区别接口文档定义输入输出类型八槽额外定义行为边界Policy中间状态State跨会话记忆Memory——这些都是传统接口文档没有、但对 Agent 至关重要的槽。Q2一定要把八个槽全写成文档吗写下来至少一次。哪怕只写在自己的笔记里。关键是写这个动作——它逼你面对脑子里默认但没定义的槽。我第二次失败就是栽在这以为想清楚了其实只是默认了。Q3需求拆完后面需求变了怎么办改 requirements.yaml然后顺着改动重新检查关联槽比如加了新 TaskState/Tools/Policy 都可能要跟着动。八槽是唯一事实源改动都从它发起就不会散落各处。Q4Policy 槽到底该多严参考最少权限原则只给完成任务所需的最小能力。Repo Doctor 只需要读就绝不配写工具宁可在需求阶段多删一条能力也不要在运行期多一个风险面。总结✅ 需求拆解的目标把模糊翻译成 Agent 能执行的确定性。✅ 固定框架Input / Task / State / Tools / Knowledge / Memory / Policy / Output 八个槽。✅ 八个槽本质是八条边界输入/任务/状态/能力/知识/记忆/行为/输出。✅ 核心闭环State → Tools → State这是 Agent 区别于函数的地方。✅ 产出物是一份 YAML 需求底座作为后续所有代码的唯一事实源。✅ 做完没有第一次有了客观标准结论有没有证据、证据对不对得上。参考资料OpenAI《A Practical Guide to Building Agents》→ 为什么引用它把 Agent 的关键要素tools、state、guardrails体系化是八槽框架的参照。LangGraph 的 State 设计文档 → 为什么引用State 是八槽里最关键的一环这里提前确认了它的工程形态。系列导航上一篇AI Agent 工程实践36不要再写 Agent 教程——先定义一个真实问题下一篇AI Agent 工程实践38从需求到 Agent 架构——为什么需要这些节点本文是 [AI Agent 工程实践] 系列的第 37 篇。