团队把一项真实研发任务直接交给模型:
text
分析新的结算规则会影响哪些前端项目,并给出直接影响、间接影响、项目负责人和验证建议。
模型可以理解"影响面分析"是什么意思,却不知道公司有哪些项目、代码存在哪里、当前依赖关系是什么。继续补充 Prompt 可以约束输出格式,却不能凭空取得这些实时事实,更不能直接查询企业系统。
团队于是为 Agent 接入读取需求、搜索代码、查询依赖和查询负责人的 Tool。模型终于能访问真实环境,但新的问题很快出现:第一次运行只搜索需求关键词,找到两个项目;第二次运行先定位业务入口,再沿共享组件和包依赖扩大范围,找到五个项目。
两次运行都没有 Tool 报错。差异发生在搜索顺序、扩大范围、影响分级和结果校验。继续增加 Tool,只会增加可执行动作,不一定让 Agent 更会完成影响面分析。
上一篇拆解了 Agent Runtime 如何执行 Tool Call。本篇沿着一条更直接的线索继续:Prompt 不够时增加什么,Tool 接好后为什么还需要 MCP、Skill 与 Workflow?
一、为什么 Prompt 已经不够?
Prompt 可以规定角色、目标、约束、示例和输出格式。对于总结、改写、分类或生成独立代码片段,这些信息可能已经足够。
影响面分析不同。模型必须取得企业内部的当前事实:
- 需求文档的完整内容;
- 项目与仓库清单;
- 组件、接口和包依赖;
- 项目负责人;
- 当前分支与版本状态。
这些信息不在模型参数中,也不应该全部复制进一段长期维护的 Prompt。更重要的是,任务还要求执行搜索和查询动作。
因此,Prompt 的边界不是"只能写一句话",而是它主要组织一次模型调用所需的指令与上下文。当任务必须动态读取事实或操作外部系统时,系统需要给 Agent 增加可调用能力。
这就引出第一项扩展:Tool。
二、Tool 让 Agent 能执行动作,但不会自动形成任务方法
Agent Tool 是供智能体调用、承载具体查询或业务操作的功能单元,例如接口查询、文件读写、数据计算和系统操作。
在当前案例中,团队先接入四个 Tool:
read_prd:读取需求文档;search_code:搜索代码;get_project_dependencies:查询项目依赖;list_project_owners:查询项目负责人。
1. Function Tool 是 Tool 的一种
Tool 为模型提供可请求调用的能力接口。以 Function Tool 为例,应用用名称、描述和参数 Schema 告诉模型"可以做什么";模型生成结构化 Tool Call;应用执行对应代码,再把结果交回模型。[1](#1)
第二篇已经完整拆过这段执行循环:模型提出动作,Runtime 与 Tool Executor 把动作变成真实结果。
Function Tool 也不是 Tool 的全部。模型平台还可能提供 Web Search、Code Execution 等 Built-in Tool;MCP Server 也可以向 Host 暴露 MCP Tool。++它们的执行位置和接入方式不同,但都会以某种可描述、可调用的能力接口进入 Agent Runtime。++
2. 一个 Tool 应该提供清晰动作
影响面分析需要搜索代码。与其提供一个含义模糊的 search,更合适的是把动作范围、输入和输出边界写清楚:
typescript
const searchCodeTool = {
type: "function",
name: "search_code",
description:
"在指定代码仓库中搜索文本或符号,返回匹配文件、行号和代码片段。" +
"只负责检索,不判断项目是否受需求影响。",
parameters: {
type: "object",
properties: {
query: {
type: "string",
description: "要搜索的文本、接口名、组件名或符号"
},
repositories: {
type: "array",
items: { type: "string" },
description: "限定搜索的仓库;为空时由运行时使用授权范围"
},
filePattern: {
type: "string",
description: "可选文件模式,例如 **/*.tsx"
},
limit: {
type: "integer",
minimum: 1,
maximum: 100
}
},
required: ["query"]
}
};
这段定义有两个重要边界。
一是 Tool Description 不只说明"能搜索代码",还告诉模型它不负责判断影响结论。二是 Tool Executor 只需忠实执行检索、返回匹配位置,不必承担完整报告的生成与验收。
如果把"解析需求、搜索项目、追踪依赖、查询负责人、生成报告"全部塞进一个 analyze_impact Tool,当然也能运行,但模型将看不到中间选择,Runtime 也更难在某一步插入权限、审批或重试。Tool 的粒度没有唯一答案,关键是动作边界要与需要控制和观察的步骤匹配。
3. 动作积木不等于任务方法
现在回到已有的四个 Tool。它们分别解决读取、搜索、查询依赖和查询负责人的动作问题,却没有规定:
- 如何从 PRD 提取业务域、接口和关键术语;
- 先定位入口项目,还是扫描所有仓库;
- 何时沿共享包、路由和接口调用继续扩散;
- 直接影响与间接影响如何分级;
- 报告生成后用什么规则校验。
这些不是第五个 Tool 能自然补齐的内容,而是完成一类任务所需的过程知识。
缺少必要动作时,应增加 Tool;动作已经存在、结果却随着搜索顺序和判断方式波动时,问题已经从"能不能做"转向"应该怎么做"。
三、当多个 Agent 都要接入同一能力,MCP 解决什么?
Tool 可以直接注册在某个 Agent Runtime 中。如果研发 IDE、桌面助手和企业 Agent 平台都要访问 GitLab、文档系统与依赖服务,逐个写适配代码会产生另一类问题:能力如何被不同 Host 发现和复用?
1. MCP 的核心是 Host、Client 与 Server
MCP 是连接 LLM Application 与外部数据、工具的开放协议。本文采用 2025-11-25 稳定规范:协议以 JSON-RPC 2.0 为基础,由 Host、Client 和 Server 组成,并在初始化时协商双方支持的 Capabilities。[2](#2)
- MCP Host 是用户实际使用的 AI Application,例如 IDE 或桌面助手;
- MCP Client 是 Host 内的协议组件,一个 Client 与一个 Server 建立连接;
- MCP Server 是提供专门 Context 与 Capabilities 的程序,可以运行在本地,也可以部署为远程服务。[3](#3)
放到影响面分析场景中,关系可以是:
#mermaid-svg-8qSP6g4hcqS4S9c0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8qSP6g4hcqS4S9c0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8qSP6g4hcqS4S9c0 .error-icon{fill:#552222;}#mermaid-svg-8qSP6g4hcqS4S9c0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8qSP6g4hcqS4S9c0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8qSP6g4hcqS4S9c0 .marker.cross{stroke:#333333;}#mermaid-svg-8qSP6g4hcqS4S9c0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8qSP6g4hcqS4S9c0 p{margin:0;}#mermaid-svg-8qSP6g4hcqS4S9c0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8qSP6g4hcqS4S9c0 .cluster-label text{fill:#333;}#mermaid-svg-8qSP6g4hcqS4S9c0 .cluster-label span{color:#333;}#mermaid-svg-8qSP6g4hcqS4S9c0 .cluster-label span p{background-color:transparent;}#mermaid-svg-8qSP6g4hcqS4S9c0 .label text,#mermaid-svg-8qSP6g4hcqS4S9c0 span{fill:#333;color:#333;}#mermaid-svg-8qSP6g4hcqS4S9c0 .node rect,#mermaid-svg-8qSP6g4hcqS4S9c0 .node circle,#mermaid-svg-8qSP6g4hcqS4S9c0 .node ellipse,#mermaid-svg-8qSP6g4hcqS4S9c0 .node polygon,#mermaid-svg-8qSP6g4hcqS4S9c0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8qSP6g4hcqS4S9c0 .rough-node .label text,#mermaid-svg-8qSP6g4hcqS4S9c0 .node .label text,#mermaid-svg-8qSP6g4hcqS4S9c0 .image-shape .label,#mermaid-svg-8qSP6g4hcqS4S9c0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-8qSP6g4hcqS4S9c0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8qSP6g4hcqS4S9c0 .rough-node .label,#mermaid-svg-8qSP6g4hcqS4S9c0 .node .label,#mermaid-svg-8qSP6g4hcqS4S9c0 .image-shape .label,#mermaid-svg-8qSP6g4hcqS4S9c0 .icon-shape .label{text-align:center;}#mermaid-svg-8qSP6g4hcqS4S9c0 .node.clickable{cursor:pointer;}#mermaid-svg-8qSP6g4hcqS4S9c0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8qSP6g4hcqS4S9c0 .arrowheadPath{fill:#333333;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8qSP6g4hcqS4S9c0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8qSP6g4hcqS4S9c0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8qSP6g4hcqS4S9c0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8qSP6g4hcqS4S9c0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8qSP6g4hcqS4S9c0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8qSP6g4hcqS4S9c0 .cluster text{fill:#333;}#mermaid-svg-8qSP6g4hcqS4S9c0 .cluster span{color:#333;}#mermaid-svg-8qSP6g4hcqS4S9c0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8qSP6g4hcqS4S9c0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8qSP6g4hcqS4S9c0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-8qSP6g4hcqS4S9c0 .icon-shape,#mermaid-svg-8qSP6g4hcqS4S9c0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8qSP6g4hcqS4S9c0 .icon-shape p,#mermaid-svg-8qSP6g4hcqS4S9c0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8qSP6g4hcqS4S9c0 .icon-shape .label rect,#mermaid-svg-8qSP6g4hcqS4S9c0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8qSP6g4hcqS4S9c0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8qSP6g4hcqS4S9c0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8qSP6g4hcqS4S9c0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-8qSP6g4hcqS4S9c0 .host>*{fill:#409EFF!important;color:#fff!important;}#mermaid-svg-8qSP6g4hcqS4S9c0 .host span{fill:#409EFF!important;color:#fff!important;}#mermaid-svg-8qSP6g4hcqS4S9c0 .host tspan{fill:#fff!important;}#mermaid-svg-8qSP6g4hcqS4S9c0 .server>*{fill:#42b983!important;color:#fff!important;}#mermaid-svg-8qSP6g4hcqS4S9c0 .server span{fill:#42b983!important;color:#fff!important;}#mermaid-svg-8qSP6g4hcqS4S9c0 .server tspan{fill:#fff!important;} 用户
研发 IDE / MCP Host
MCP Client
MCP Client
GitLab MCP Server
文档 MCP Server
GitLab API
依赖分析服务
文档 API
MCP 标准化的是 Host 与能力提供方之间的协议边界。它不是充当 Agent 与后端系统之间的通用数据管道,也没有要求所有能力必须经过 MCP。
2. MCP 不只有 Tool
稳定版 MCP Server 可以暴露三类核心 Primitive:Tool、Resource 和 Prompt。[2](#2)[4](#4)
| Primitive | 主要作用 | 影响面案例 | 典型使用方式 |
|---|---|---|---|
| Tool | 执行动作或查询 | 搜索代码、查询依赖 | 模型可请求调用 |
| Resource | 提供上下文数据 | 架构说明、仓库索引 | Host 决定如何加入 Context |
| Prompt | 提供可复用交互模板 | 启动影响面分析模板 | 通常由用户显式选择 |
MCP Tool 通过 tools/list 被 Client 发现,通过 tools/call 调用;Server 还可以在 Tool 列表变化时发送通知。[5](#5) Resource 则用于共享文件、数据库 Schema 或应用数据等上下文,具体如何选择和放入 Model Context,由 Host Application 决定。[4](#4)
这里也能看到 MCP Prompt 与 Agent Skill 的差别。MCP Prompt 是 Server 提供的一类交互模板;Agent Skill 是以 SKILL.md 为核心、可以携带脚本和参考资料、按需激活的目录资产。二者都可能包含指令,但封装方式与加载生命周期不同。
3. MCP Server 常常建立在既有 API 之上
接入 MCP 后,GitLab API 并没有消失。项目、代码搜索、成员权限等业务语义仍由 GitLab 定义,MCP Server 只是挑选适合 Agent 使用的能力,以标准协议暴露给不同 Host。
更准确的关系是:
API 定义业务系统本身的接口;MCP 定义 AI Host 与能力提供方之间的一种标准接入协议。MCP Server 常常建立在既有 API 之上。
这也是为什么"API 给开发者用,MCP 给 Agent 用"并不准确。开发者同样要实现 MCP 客户端与服务端,Agent Runtime 也可以直接使用 Function Tool 调用业务 API。是否采用 MCP,取决于跨 Host 复用、能力发现和协议治理是否值得增加这一层。
4. MCP 统一接入,不包办权限和工具选择
MCP 为 HTTP Transport 定义了 Authorization 机制,但接入协议并不会自动补齐企业的业务对象权限、敏感操作审批、凭据隔离和本地进程 Sandbox。[6](#6)[7](#7)
tools/list 让 Client 可以发现 Server 提供的 Tool,也不意味着这些 Tool 都应该进入当前 Model Context。Host 仍要决定当前用户能看到什么、哪些 Tool 与任务相关,以及哪些调用必须确认。Tool 很多时,还可以通过独立的 Tool Search 机制按需加载。[8](#8)
接入 MCP 之后,模型并不直接感知 MCP Server 的存在。MCP Client 通过 tools/list 获取 Server Tool 列表后,Runtime 会将其适配封装成本地 Function Tool 的形态,再注入模型调用接口。对模型而言,调用一个 MCP Tool 与调用一个本地注册的 Function Tool 在交互体验上完全一致。MCP 影响的只是工具定义的来源和生命周期,不改变模型的 Tool Call 协议。
所以,MCP 解决的是标准接入,不是权限平台,也不是模型侧 Tool Selection。它让不同 Host 更容易复用外部能力,却仍然没有告诉 Agent 应该怎样完成影响面分析。
四、Tool 都会用了,为什么还需要 Skill?
影响面分析的搜索顺序、分级规则、参考资料和输出约定,需要一个可维护、可发现、可复用的载体。Agent Skill 正是承载这类任务方法的最佳载体。
1. Agent Skills 已经有开放基础格式
Agent Skills 是一种开放格式。一个 Skill 至少是包含 SKILL.md 的目录;文件使用 YAML Frontmatter 描述 name 和 description,正文则保存任务指令。目录还可以包含 scripts/、references/ 和 assets/。[9](#9)
Cursor、Claude 与 OpenAI 都已支持或兼容这套基础格式。[10](#10)这意味着不能再把 skill.yaml、validators/ 或某一家产品的字段写成 Skill 的通用标准。
共同格式之外,平台仍有自己的扩展。例如 Cursor 支持 paths、disable-model-invocation 等 Frontmatter;OpenAI Hosted Skills 具有上传和版本机制;不同运行环境对 Script、网络和文件系统的权限也不相同。开放格式解决可移植的基础封装,不保证所有平台的执行行为完全一致。
2. Skill 与 Prompt 的差异不在文本长短
"Prompt 是一句话,Skill 是一套文件"听起来直观,却不够准确。Prompt 可以包含很长的 System Instructions、示例和上下文;Skill 被激活后,它的 Instructions 最终也会进入当前 Model Context。
真正的工程差异是:
- Prompt 是某次 Model Call 的输入组成;
- Skill 是可以独立发现、选择激活、版本控制和复用的文件资产;
- Skill 还可以携带脚本、参考资料和模板,而不是每次在 Prompt 中重复粘贴。
换句话说,Skill 没有创造一种脱离 Prompt 的模型能力。它解决的是任务知识如何包装、发现和按需进入 Context。
3. Progressive Disclosure 让任务知识按需加载
Agent Skills 采用 Progressive Disclosure:[11](#11)
- Discovery :启动时只暴露
name和description; - Activation :任务匹配后读取完整
SKILL.md; - Execution:需要时再读取 Reference、加载 Asset 或执行 Script。
因此,影响面分析的架构地图和分级说明不必常驻每一次对话。Agent 先看到 impact-analysis 的名称与描述;只有用户真的要求分析需求影响面时,才加载完整步骤;需要确认间接影响定义时,再读取对应 Reference。
这比把所有团队方法写入常驻 System Prompt 更容易维护,也减少无关信息长期占据 Context。但它并非没有成本:每个 Skill 的 Metadata 仍需要被发现,Description 是否准确会影响触发,Skill 版本变化也需要评测。
4. 用 impact-analysis 封装任务方法
一个符合开放规范基础结构的 Skill 可以是:
text
impact-analysis/
├── SKILL.md
├── references/
│ ├── architecture-map.md
│ └── impact-levels.md
└── scripts/
└── validate-report.ts
SKILL.md 不需要重新实现 GitLab Tool,它只需要告诉 Agent 如何使用可用能力完成任务:
markdown
---
name: impact-analysis
description: >
分析产品需求或技术变更影响的前端项目、共享依赖与负责人。
当用户要求影响面分析、改造范围评估或项目清单时使用。
---
# 需求影响面分析
## 执行步骤
1. 读取需求,提取业务域、页面入口、接口和关键术语。
2. 搜索直接引用这些术语、接口或组件的项目。
3. 读取 `references/architecture-map.md`,检查共享包和平台入口。
4. 查询项目依赖,继续追踪间接影响,但记录扩展依据。
5. 查询受影响项目的负责人。
6. 按 `references/impact-levels.md` 区分直接和间接影响。
7. 输出项目、影响依据、负责人、风险与验证建议。
8. 运行 `scripts/validate-report.ts` 校验报告结构。
## 边界
- 不根据仓库名称猜测影响,结论必须附代码或依赖证据。
- 不修改代码、不创建工单;这些动作由独立 Tool 或 Workflow 处理。
这里封装的是过程知识:先做什么、何时扩大搜索、使用哪些参考资料、输出需要满足什么约定。search_code 等 Tool 仍负责真实动作,MCP 仍可负责这些 Tool 如何被 Host 接入。
Skill 也可以引用一个 MCP Tool,却不因此位于 MCP 的"上层"。从协议角度看,Skill 和 MCP 没有强制依赖;从具体任务看,它们只是可以互补:Skill 教 Agent 如何完成任务,MCP 为任务提供外部能力。[12](#12)
五、Skill 已经写了步骤,为什么还需要 Workflow?
Skill 已经要求 Agent 在输出前运行校验脚本。但如果报告发布前必须通过 Schema Validation、Owner Review 和人工审批,仅把这些要求写进 Skill 是否足够?
1. 先区分两个语境中的 workflow
Agent Skills 的官方材料会用 workflow 描述 Skill 内部的多步骤任务方法。例如刚才的 impact-analysis,它确实包含一段分析流程。
本文所说的应用级 Workflow 采用另一种更严格的架构含义:LLM 和 Tool 沿预定义代码路径执行。相对地,Agent 会根据输入与环境反馈动态决定过程和工具使用。[13](#13)
二者虽都可视为"流程",但控制力截然不同:
- Skill 中的指引仅为 Agent 提供常规做法参考;
- 应用级 Workflow 则通过代码、Graph 或状态机强制执行既定路径。
前者保存过程知识,后者控制运行路径。把这两个语境混在一起,就容易得出"Workflow 是多个 Skill 的组合"这种过度简化的结论。
2. Skill 提供方法,Workflow 强制门禁
影响面分析中,搜索关键词、扩大依赖范围和组织报告可以根据实际需求动态调整,适合由 Agent 按 Skill 推进。但以下步骤不能只依赖模型记得执行:
- 输入必须满足任务 Schema;
- 报告必须包含项目、证据、负责人和验证建议;
- 发布前必须经过 Owner Review;
- 高风险结论必须人工审批;
- 审批后才能写入 Jira 或正式发布。
其核心意图并非定义具体语法,而是分离'动态分析'与'固定门禁'"。可以用一段框架无关的伪配置表达:
yaml
workflow: publish-impact-report
steps:
- validate_input
- run_agent:
skill: impact-analysis
- validate_report_schema
- owner_review:
type: human
- approval:
required_when: high_risk
- publish_report
这不是某个框架的真实配置,只用于展示控制边界:run_agent 节点内部允许动态搜索,前后的 Validation、Review 和 Approval 则由 Workflow 固定。
一个实用判断是:
可以根据任务协商的方法写入 Skill,不能跳过的业务门禁进入 Workflow。
这是本文的工程建议,不是 Agent Skills 或某个 Workflow 框架的官方定义。
3. Workflow 与 Agent 不是替代关系
任务路径固定、要求一致性和审计时,应用级 Workflow 更合适;路径无法提前确定、需要根据搜索结果持续调整时,Agent 更有价值。二者可以嵌套,而不是只能二选一。
在当前案例中,Workflow 不需要知道 Agent 会搜索几轮、先查哪个共享包;它只要求分析节点最终产出符合 Schema 的报告。Agent 也不需要决定是否跳过 Owner Review,因为这条边根本不在它的控制范围内。
反过来,一个 Agent 也可以调用边界清楚的 Workflow,例如"创建工单并通知负责人"。只要输入、输出和副作用约束明确,这个 Workflow 可以作为 Agent 的一个受控能力。
4. Workflow 不依赖 Skill 才能成立
应用级 Workflow 的节点可以是普通代码、Model Call、Tool、Agent 或人工审批。Skill-enabled Agent 只是其中一种节点形态。
例如一个确定性的发布流程可以完全不使用 Skill:
text
运行测试 → 构建产物 → 人工审批 → 发布 → 通知
同样,一个 Skill 也可以在没有应用级 Workflow 的情况下被 Agent 直接激活。Skill 是可复用任务资产,Workflow 是运行控制结构;两者可以组合,但不存在固定上下级关系。当 Workflow 与 Agent 嵌套时,还需明确控制权传递与可观测性归属。Workflow 调用 Agent 时,Agent 是否继承外部 Workflow 的终止信号(Cancel / Timeout)、预算限制和审计追踪?Agent 调用 Workflow 时,Workflow 的执行日志和 Trace 是否归入 Agent 的父级 Span?这些没有统一答案,但必须在接入时显式约定。嵌套不是简单地"一个调用另一个",而是两个控制域的交汇点。
六、Tool、MCP、Skill、Workflow 到底是什么关系?
分别理解四个概念后,最容易犯的错误是把它们重新排成一条链:
text
Agent → Workflow → Skill → Tool → MCP → Enterprise System
这张图看起来整齐,却容易产生误导:仿佛 Tool 必须经过 MCP,Skill 必须由 Workflow 调用,Workflow 又必然位于 Agent 之下。官方规范和实际组合都不支持这种固定关系。
1. 先看一种可行组合
在需求影响面分析中,可以采用下面的结构:
#mermaid-svg-dnCXNtYdywGTeplW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dnCXNtYdywGTeplW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dnCXNtYdywGTeplW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dnCXNtYdywGTeplW .error-icon{fill:#552222;}#mermaid-svg-dnCXNtYdywGTeplW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dnCXNtYdywGTeplW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dnCXNtYdywGTeplW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dnCXNtYdywGTeplW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dnCXNtYdywGTeplW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dnCXNtYdywGTeplW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dnCXNtYdywGTeplW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dnCXNtYdywGTeplW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dnCXNtYdywGTeplW .marker.cross{stroke:#333333;}#mermaid-svg-dnCXNtYdywGTeplW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dnCXNtYdywGTeplW p{margin:0;}#mermaid-svg-dnCXNtYdywGTeplW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-dnCXNtYdywGTeplW .cluster-label text{fill:#333;}#mermaid-svg-dnCXNtYdywGTeplW .cluster-label span{color:#333;}#mermaid-svg-dnCXNtYdywGTeplW .cluster-label span p{background-color:transparent;}#mermaid-svg-dnCXNtYdywGTeplW .label text,#mermaid-svg-dnCXNtYdywGTeplW span{fill:#333;color:#333;}#mermaid-svg-dnCXNtYdywGTeplW .node rect,#mermaid-svg-dnCXNtYdywGTeplW .node circle,#mermaid-svg-dnCXNtYdywGTeplW .node ellipse,#mermaid-svg-dnCXNtYdywGTeplW .node polygon,#mermaid-svg-dnCXNtYdywGTeplW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dnCXNtYdywGTeplW .rough-node .label text,#mermaid-svg-dnCXNtYdywGTeplW .node .label text,#mermaid-svg-dnCXNtYdywGTeplW .image-shape .label,#mermaid-svg-dnCXNtYdywGTeplW .icon-shape .label{text-anchor:middle;}#mermaid-svg-dnCXNtYdywGTeplW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dnCXNtYdywGTeplW .rough-node .label,#mermaid-svg-dnCXNtYdywGTeplW .node .label,#mermaid-svg-dnCXNtYdywGTeplW .image-shape .label,#mermaid-svg-dnCXNtYdywGTeplW .icon-shape .label{text-align:center;}#mermaid-svg-dnCXNtYdywGTeplW .node.clickable{cursor:pointer;}#mermaid-svg-dnCXNtYdywGTeplW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dnCXNtYdywGTeplW .arrowheadPath{fill:#333333;}#mermaid-svg-dnCXNtYdywGTeplW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dnCXNtYdywGTeplW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dnCXNtYdywGTeplW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dnCXNtYdywGTeplW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dnCXNtYdywGTeplW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dnCXNtYdywGTeplW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dnCXNtYdywGTeplW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dnCXNtYdywGTeplW .cluster text{fill:#333;}#mermaid-svg-dnCXNtYdywGTeplW .cluster span{color:#333;}#mermaid-svg-dnCXNtYdywGTeplW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dnCXNtYdywGTeplW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dnCXNtYdywGTeplW rect.text{fill:none;stroke-width:0;}#mermaid-svg-dnCXNtYdywGTeplW .icon-shape,#mermaid-svg-dnCXNtYdywGTeplW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dnCXNtYdywGTeplW .icon-shape p,#mermaid-svg-dnCXNtYdywGTeplW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dnCXNtYdywGTeplW .icon-shape .label rect,#mermaid-svg-dnCXNtYdywGTeplW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dnCXNtYdywGTeplW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dnCXNtYdywGTeplW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dnCXNtYdywGTeplW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-dnCXNtYdywGTeplW .fixed>*{fill:#409EFF!important;color:#fff!important;}#mermaid-svg-dnCXNtYdywGTeplW .fixed span{fill:#409EFF!important;color:#fff!important;}#mermaid-svg-dnCXNtYdywGTeplW .fixed tspan{fill:#fff!important;}#mermaid-svg-dnCXNtYdywGTeplW .dynamic>*{fill:#42b983!important;color:#fff!important;}#mermaid-svg-dnCXNtYdywGTeplW .dynamic span{fill:#42b983!important;color:#fff!important;}#mermaid-svg-dnCXNtYdywGTeplW .dynamic tspan{fill:#fff!important;} 用户任务
应用级 Workflow
固定校验、评审与发布门禁
Agent Runtime
动态分析影响面
激活 impact-analysis Skill
本地 Function Tool
MCP Client
MCP Server
MCP Tool / Resource
GitLab / 文档 API
Owner Review / Approval
这只是一个可行组合,不是目标架构:
- Workflow 可以只包含普通代码和人工节点,不使用 Agent;
- Agent 可以直接响应一次性任务,不进入 Workflow;
- Skill 可以指导 Agent 调用本地 Function Tool,也可以调用 MCP Tool;
- MCP Server 可以只提供 Resource,不提供 Tool;
- Tool 可以直接注册在 Runtime 中,不必通过 MCP。
Skill 与 MCP 的互补关系也应在这个意义上理解:Skill 可以保存"如何使用工具完成任务"的方法,MCP 可以让外部能力以标准方式被多个 Host 接入。两者各自独立,又能在具体任务中配合。[12](#12)
2. 用四个问题判断当前缺口
本文把四者整理成一张职责矩阵:
| 概念 | 解决问题 | 典型交付物 | 对执行路径的控制 |
|---|---|---|---|
| Tool | Agent 可以执行什么动作 | Name、Description、Schema、Executor | 不规定完整路径 |
| MCP | 怎么连接外部系统 | Host / Client / Server、Protocol、Capabilities | 不规定业务路径 |
| Agent Skill | Agent 如何完成某类专业任务 | SKILL.md、Scripts、References、Assets |
提供过程指令,通常不强制 |
| Workflow | 多个能力组合成业务流程(按预定义路径执行) | Code Path、Graph、State Machine、Approval Gate | 强制控制 |
这张表是本文为了选型做的观察框架,不是官方"四层架构"。真正落到设计时,可以依次问:
- 缺必要动作吗? Agent 是否无法取得必要事实或执行必要操作?
- 缺连接复用吗? 多个 Host 是否在重复接入同一外部系统?
- 缺任务方法吗? 同一类任务是否每次从零开始,步骤与输出难以复用?
- 缺强制门禁吗? 是否存在模型不能跳过的校验、审批和交付路径?
对应关系如下:
| 当前问题 | 优先考虑 | 影响面案例 |
|---|---|---|
| Agent 无法执行必要查询或动作 | Tool | 增加 get_project_dependencies |
| 多个 Host 重复接入同一外部系统 | MCP | 用 GitLab MCP Server 标准化暴露能力 |
| 一类任务的方法、资料和输出规则无法复用 | Agent Skill | 沉淀 impact-analysis |
| 某些步骤、审批或交付门禁不能跳过 | Workflow | 校验 → Owner Review → 审批 → 发布 |
3. 不是每个任务都要集齐四件套
如果只做一次探索性分析,Prompt 加已有 Tool 可能已经足够。为了"架构完整"再加 MCP、Skill 和 Workflow,只会增加部署、版本、权限和评测成本。
当影响面分析开始重复出现,并且团队需要统一搜索方法、影响分级和报告格式时,才值得沉淀 impact-analysis Skill。若研发 IDE、内部助手和云端 Agent 都要访问相同 GitLab 能力,再评估 MCP 带来的跨 Host 复用价值。
只有当报告进入正式交付,存在不可跳过的 Schema Validation、Owner Review 或审批时,才需要应用级 Workflow 固化这些边界。动态分析仍然留在 Agent 节点中,不必把每一次代码搜索都预先写死。
这也给出两个排除问题:
- 任务边界清楚、一次调用就能可靠完成吗?如果可以,不必增加 Agentic Complexity。
- 步骤是否必须根据环境反馈变化?如果不需要,确定性 Workflow 往往比让 Agent 自由选择更容易控制。[13](#13)
4. 能力扩展的顺序应由缺口决定
回到开头,两次影响面分析结果不同,首先应该检查的不是"还缺哪个热门组件",而是差异发生在哪个环节:
- 缺少查询依赖的动作,就补 Tool;
- Tool 在多个 Host 重复接入,就评估 MCP;
- 搜索顺序和判断规则不稳定,就沉淀 Skill;
- 校验和评审不能跳过,就用 Workflow 固化。
四者分别对应执行能力、接入复用、任务方法与控制路径。它们既非能力成熟度等级,也非企业 Agent 必须依次通关的技术栈。
总结:能力扩展不是继续堆 Tool
Agent 有了 read_prd、search_code、get_project_dependencies 和 list_project_owners,只说明它具备了完成任务所需的部分动作。稳定的影响面分析还需要可复用的任务方法、合适的外部接入方式,以及不能跳过的交付门禁。
这篇文章可以先带走三个判断:
- Tool 让 Agent 能请求动作,但不自动形成专业任务能力。
- MCP、Agent Skill 与 Workflow 分别处理连接复用、任务方法复用和预定义控制路径。
- 先判断缺口,再选择抽象;不要从一张固定层级图反推系统。
简单任务可以只用 Prompt + Tool;采用 MCP 不必然需要 Skill;沉淀 Skill 也不必然需要 Workflow。高风险或强合规步骤,则不应只依赖 Skill Instructions。
下一篇会继续讨论:当这些能力已经能够被发现、调用和组合,Agent 要进入企业生产环境,还需要怎样的 Runtime、Memory、Knowledge、Evaluation 与 Observability。
-
OpenAI, "Function calling", https://platform.openai.com/api/docs/guides/function-calling (official-doc) ↩︎
-
Model Context Protocol, "Specification 2025-11-25", https://modelcontextprotocol.io/specification/2025-11-25 (official-doc) ↩︎ ↩︎
-
Model Context Protocol, "Architecture", https://modelcontextprotocol.io/specification/2025-11-25/architecture (official-doc) ↩︎
-
Model Context Protocol, "Architecture overview" 与 "Resources", https://modelcontextprotocol.io/docs/learn/architecture 、https://modelcontextprotocol.io/specification/2025-11-25/server/resources (official-doc) ↩︎ ↩︎
-
Model Context Protocol, "Tools", https://modelcontextprotocol.io/specification/2025-11-25/server/tools (official-doc) ↩︎
-
Model Context Protocol, "Authorization", https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization (official-doc) ↩︎
-
Model Context Protocol, "Understanding MCP clients", https://modelcontextprotocol.io/docs/learn/client-concepts (official-doc) ↩︎
-
OpenAI, "Tool search";Claude Platform, "Tool search tool", https://platform.openai.com/api/docs/guides/tools-tool-search 、https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool (official-doc) ↩︎
-
Agent Skills, "Specification", https://agentskills.io/specification.md (official-doc) ↩︎
-
Cursor, "Agent Skills", https://cursor.com/docs/skills (official-doc) ↩︎
-
Agent Skills, "How to add skills support to your agent", https://agentskills.io/client-implementation/adding-skills-support (official-doc) ↩︎
-
OpenAI, "Customization";Anthropic, "Equipping agents for the real world with Agent Skills", https://platform.openai.com/codex/concepts/customization 、https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills (official-doc / official-blog) ↩︎ ↩︎
-
Anthropic, "Building effective agents", https://www.anthropic.com/engineering/building-effective-agents (official-blog) ↩︎ ↩︎