最近把 AI 编码代理用进了日常开发流程后,发现不少同行对编码代理的认知还停留在“聊天窗口 + 自动补代码”的阶段。实际上,真正能稳定产出生产级代码的代理,内部靠的是几套互相咬合的概念体系:Skills、MCP、Prompt、SubAgent。刚接触 iManus 这类编码代理的同学,八成会被这几个词绕晕,甚至很多人以为它们是同一种东西的不同叫法。
这篇文章就把这四个概念挨个拆开,讲清楚它们各自的定位、它们之间的边界和协作关系,再结合我在 iManus 上搭过的实际流程,告诉你如何不踩坑地把它们组合成一套可复用的编码工作流水线。不管你是团队里的技术负责人、独立开发者,还是刚入门的 AI 编程爱好者,这都已经不是“要不要了解”的范畴,而是“晚了解一天就多踩一天坑”的必修内容。
1. 整体设计与概念定位
1.1 为什么突然冒出这么多名词
过去我们用 AI 写代码,通常是一条消息发过去,模型给一段代码,最多再做多轮对话。这套路你把它当成“高级补全工具”没问题,但当任务变成“把项目里的某个微服务重构一遍,并保证 CI 全绿”,单轮对话就撑不住了。
编码代理和传统辅助工具的本质区别在于,它拥有目标拆解、工具调用、结果验证的闭环能力。为了实现闭环,工程上自然要把“意图、能力、上下文、分工”这几个维度拆出来:
- 意图由 Prompt 承载
- 能力由 Skills 和 MCP 承载
- 上下文由会话和状态记忆承载
- 分工由 SubAgent 承载
这几层互相耦合,但职责必须分清。很多配置完 iManus 后跑不明白的人,问题都出在把四者的边界搞混了。比如,有人把 MCP 当作 Prompt 的替代品,有人把 SubAgent 当成 Skills 的升级版,这种理解偏差,会导致后续所有流程设计都拧巴。
1.2 四条核心概念的底层关系
我用一句话给它们定位:
Prompt 是“做什么”,Skills 是“怎么做的流程”,MCP 是“能摸到什么数据”,SubAgent 是“由谁去干”。
在 iManus 里,这四处是可独立配置又相互调用的模块,最终由代理运行时统一编排。
用一个生活化的类比:你要开一家中餐厅(编码代理),餐厅菜单是 Prompt,决定你对外承诺做什么菜;厨师的标准操作流程是 Skills,决定每道菜怎么做才稳定;食材供应商是 MCP,决定你能买到什么级别的食材;最后,炒菜、切菜、传菜分别交给不同岗位的 SubAgent 去执行。如果没有菜单,顾客不知道点啥;没有 SOP,大厨发挥不稳定;没有供应商,巧妇难为无米之炊;没有岗位分工,大厨一个人再厉害也忙不过来。
理解了这个底层结构后,你会发现网上很多配置教程都讲偏了。它们往往只教你在某个 JSON 里加一段 MCP 配置,却没说清楚为什么要开放这几个接口、哪些能力该沉淀成 Skills、哪些任务该丢给独立 SubAgent。这篇文章后面的每一节,都在补全这层缺失的逻辑。
2. 核心概念逐一拆解:Prompt 与 Skills
2.1 Prompt 不只是“你说了什么”
在编码代理的语境下,Prompt 远比“你发给 AI 的那句话”要大得多。它包含系统提示词、用户任务描述、约束条件、输出格式要求,甚至包括代理给自己制定的分步计划。
绝大多数人在编码代理上遇到的问题,追根溯源都出在 Prompt 设计含糊。比如:如果只告诉代理“把这个模块拆了重写”,它可能拆掉可用代码再重构出更差的结构。正确的 Prompt 至少要包含以下信息:
- 任务目标:要用一句可验证的话描述“做完是什么状态”
- 范围边界:明确哪些文件不能碰、哪些依赖不能升
- 验收标准:测试通过?类型检查通过?还是性能指标达标?
- 风格约束:项目现有代码风格、命名习惯、注释语言
我自己常用的做法是,把项目级约束写进系统提示词,把单次任务指令写进用户提示词,不要让代理把两者混在一起去推断。比如,某项目要求对外接口错误码统一走枚举,那我就把这条放在系统层,这样代理在生成新接口时才会自动遵循,而不是每次任务里反复口头提醒。
提示:对代理说“写得好一点”是最无效的指令。可验证、可测量的描述,才是有效指令。
2.2 Skills:把重复工作沉淀成“可复用能力”
Skills 是 iManus 中用来把一段稳定、可复用、多步骤的操作流程固化成模块的机制。我第一次用 Skills 时,觉得它像个高级宏,但它比宏复杂:宏只能按固定顺序执行,而 Skills 可以有前置条件、决策分支、自定义参数和外部工具联动。
一个典型的 Skills 由以下部分组成:
- 触发条件:什么场景下应该调用它
- 参数接口:调用时需要传入哪些变量
- 执行步骤:定义好了的、代理可执行的序列化步骤
- 退出条件:步骤结束后如何验证成果
- 依赖项:它依赖哪些 MCP 服务、脚本或外部工具
我在一个 Web 服务项目里,把“新增一个带有标准中间件链的 API 接口”做成 Skills。以前代理每次新增接口时,可能要现读现有代码、照葫芦画瓢,偶尔还会漏掉超时控制和限流配置。做成 Skills 后,代理只要拿到路由参数、请求类型和数据模型定义,就能生成一个符合既有约束的接口骨架,中间件链条一个不少。
这里有一个很关键的认知:Skills 不是用来“把所有代码生成规则塞进去”的,它更适合沉淀“有明确步骤、结果可验证、执行频率高”的操作。如果你试图把整个项目的编码规范全塞进 Skills,那这个 Skills 最终会因为过度的耦合而难以维护,远不如让它保持单一职责。
2.3 Prompt 与 Skills 怎么配合
Prompt 和 Skills 在 iManus 中是两层配合的关系:Prompt 负责“意图解析”,Skills 负责“意图落地”。
比如我给代理下达“给用户模块新增注销接口”的任务(Prompt 层),它在任务解析阶段会在语义空间里找到对应的 Skills——“新增基础 CRUD 接口”,然后将注销接口转成该 Skills 的一个具体参数组合来执行。
实践中,两者的边界问题经常被人为搞乱。有人恨不得把 Skills 的名称和调用逻辑全写进 Prompt,结果 Prompt 变得又臭又长;有人则希望 Skills 能覆盖所有 Prompt 语义,最终 Skills 列表长到无法管理。
我的建议很简单:Prompt 里只写任务、约束、目标、验收标准,不做具体步骤指定;步骤的复用部分由代理自行路由到合适的 Skills。你可能会担心代理路由不准,与其把所有步骤写死在 Prompt 里,不如完善 Skills 的描述和触发条件,让路由精度更高。
3. 核心概念逐一拆解:MCP 是什么,为什么是关键
3.1 MCP 解决了“信息孤岛”问题
MCP(Model Context Protocol,模型上下文协议)是当前编码代理体系中打通外部数据与工具的关键一环。没有它,代理的工作范围只能限定在“你自己输入给它的文字”里,它无法直接读取数据库结构、调用 API、操作文件系统。
MCP 的架构不复杂,它分为客户端和服务端:代理本身是 MCP 客户端,通过标准协议向服务端发起请求;服务端可以是一个文件系统工具、数据库采集器、HTTP 请求封装器,或者其他任何能提供数据和能力的中间层。
在 iManus 中使用 MCP,最常见的场景是我让代理直接读取本地设计文档和接口定义文件,再从运维平台拉取当前运行日志,进而判断线上问题。没有 MCP 时,这个操作链条需要我先把文档内容粘贴进对话,再把日志片段手动贴进去运行,每一步都容易截断和失真。
MCP 的协议本身是标准化的,这意味着同一个服务端可以接入多个符合协议的代理客户端,不用针对不同代理重复实现。这也让第三方生态有机会共享“同一份连接能力”,不用为每个产品单独适配。
3.2 最常见的四类 MCP 服务
我目前会用到的 MCP 服务。当然服务是手作开发或者社区引入的,按照用途大致可分为以下几类:
| MCP 服务类型 | 典型能力 | 典型用途 |
|---|---|---|
| 文件系统访问 | 读写本地/远程文件、目录遍历 | 代理动态读取文档、生成代码文件、批量修改配置 |
| 数据库连接 | 执行 SQL、读取表结构、获取执行计划 | 代理根据真实表结构生成数据访问层代码 |
| HTTP 请求封装 | 调用第三方 API、拉取接口返回 | 代理直接访问内部接口文档或线上状态接口 |
| 代码执行沙箱 | 运行测试、执行脚本,返回结果 | 代理自己验证测试用例是否通过,不用人工反复来回切换 |
每种服务都有自己的适用场景。文件系统访问是最基础的能力,几乎所有编码代理必须配备;数据库连接则适合业务系统开发场景,尤其是数据密集型的后端项目;HTTP 请求封装通常用于横向拉取多个服务的信息,跨团队协作时尤其有用;代码执行沙箱则是提升“代理自主迭代能力”的关键,它能缩短验证回路。
3.3 动手配置一个 MCP 服务端
在 iManus 中配置 MCP 服务端,并不需要从零写协议实现。以我做过的模拟项目 X 为例,当时想给代理开放“读取测试环境最近一小时错误日志”的能力,做法是:
- 定一个名为错误日志查询服务 的 MCP 服务。
- 服务端实现两个工具:获取近一小时错误日志、获取错误详情。
- 在 iManus 的 MCP 配置区注册这个服务,并填写服务地址与鉴权信息。
- 重启代理会话,触发一次操作验证,看代理能否正确调用这个工具并解析返回内容。
整个过程的核心不在配置这一步,而在服务端的接口能力设计。接口的输入输出不能太宽泛,比如错误日志查询 若要带时间范围参数,需要服务端支持 parameter 化查询,代理才能在调用时动态传参。
MCP 设计中的一个高频误区是:把服务端接口做得太“大”,一个工具试图完成所有功能。比如我见过有人把“查询仓库代码元数据”、“拉取提交记录”、“执行 git 命令”塞进一个工具,表面上省事,实际上代理在调用时无法精确控制参数、解析结果也变得困难。正确的做法是粒度和职能细分:一个工具对应一个明确的单一能力。
注意:如果你在配置 MCP 后代理没有按预期使用它,优先排查服务端返回的数据结构,是不是破坏了代理最容易解析的平面字段结构。
4. SubAgent:编码代理里的“多角色分工”
4.1 SubAgent 其实是独立执行的子代理
SubAgent 这个概念并不玄乎:它就是一个可以被主代理(Main Agent)调度、有独立上下文的子任务执行单元。你可以把它理解为“团队里专门负责某类工作的人”。
在 iManus 的实现里,SubAgent 不是给主代理发消息的那个“聊天对象”,而是主代理在任务拆解后,将某个子任务交给其独立执行的进程实体。它有自己的提示词、上下文窗口和可调用工具集,执行完后将结果回传给主代理。
我最早接触 SubAgent 是在一次跨平台系统开发任务里(模拟项目),主代理发现任务同时涉及前端界面重构和后端接口设计,两者需要的上下文几乎不重叠。如果把它们硬放在同一个会话里执行,会有大量的重度上下文切换,不仅拖慢速度,也容易让模型忘记前面的约束。拆成两个 SubAgent 并行跑,一个负责前端,一个处理后端,各自上下文精炼,任务完成度明显更高。
4.2 SubAgent 和 Skills 的“分工差异”
有时候初学者会把 SubAgent 和 Skills 混为一谈。它们确实有相似之处:都是把一个复杂的、完整的工作拆成可管理的小单元。但两者的本质区别在于:
- Skills 的粒度是“步骤”,它是一段流程的固化,它没有独立的目标制定能力;
- SubAgent 的粒度是“职责”,它是一个独立的执行单元,它自己可以调用 Skills 和 MCP 完成任务,也能对任务进行处理。
用一个直白的类比:Skills 是一本“烹饪手册”,告诉你怎么做一道菜;SubAgent 是一位“厨师”,你告诉他“今天给客人做一桌商务宴”,他会自己翻手册、备菜、掌勺,最后上菜。两者不是谁替代谁的关系,而是协作关系。
4.3 如何设计 SubAgent 的任务边界
设计 SubAgent 时最容易犯的错误是边界不清晰,让子代理负责“这也能做、那也能做”的模糊目标。比如,定义一个“质量保障 Agent”,它要同时做代码审查、安全扫描、性能测试、环境部署。看起来是一个人顶四个人,实际上这个 SubAgent 会因为没有清晰的优先级而四顾不暇。
我个人的经验是:
- 一个 SubAgent 只承担一项核心职责。
- 给它设计明确的工作协议:输入什么、输出什么、交付格式是什么。
- 设定它的工具边界:在 iManus 中,给不同 SubAgent 挂载不同的 MCP 工具集,而不是全部通用。
以我的某次操作为例,我在 iManus 里同时配了两个 SubAgent:接口定义审查 Agent 和数据库建模 Agent。前者负责检查 API 定义的完整性与风格一致性,后者负责数据关系的边界判定和索引设计评估。它们可以被一次任务同步勾选,但彼此不共享上下文,结果汇总到主代理后统一输出交付。任务一开始时不至于互相干扰,最终效果很理想。
5. 四个概念协同工作的完整链路
5.1 一次典型任务的完整流转
要真正理解前面四个概念,最好的办法是看它们在一次真实任务里如何接力。我拿一个最常见的场景:给某模块新增一个“查询用户列表”接口,来说明整套流转过程。
- 用户在主代理的输入框里给出一段任务描述,其中明确目标、约束、验收标准,这是 Prompt 层在做意图定义。
- 主代理解析意图后,识别到这个任务涉及后端代码生成、已有中间件链路由、数据库表结构查询。
- 它通过 MCP 读取数据库的表结构信息,通过文件系统 MCP 读取现有接口的代码模板,确认要生成的代码格式。
- 它发现项目里已有“新增 GET 接口”的 Skills,于是将接口路由、参数模型、返回模型作为参数传给该 Skills,让 Skills 按既定步骤搭建接口骨架。
- 数据库字段适配部分,代理判断需要专项处理,于是将这部分任务派发给数据库建模 SubAgent,等子代理返回字段映射结果后,主代理结合该结果补齐数据访问层代码。
- 最后,代理在代码执行沙箱里运行冒烟测试,验证接口是否能正常访问数据库并返回数据结构,测试通过后向用户输出交付说明。
看这个流程就知道,Skills、MCP、Prompt、SubAgent 每一个都不可缺席。没有 MCP,代理读不到真实的表结构;没有 Skills,它只能靠临场发挥;没有 SubAgent,它必须用一个大上下文承载所有专业细节;没有 Prompt,它不知道目标边界。
5.2 在 iManus 中的实际配置清单
根据我的配置经验,一套能打仗的 iManus 工作区至少需要这些模块:
- 一套系统提示词:包含项目背景、技术栈约束、编码规范、验收标准。
- 文件系统 MCP:给代理访问项目源码与文档的能力。
- 代码执行沙箱 MCP:让代理能自己跑测试和脚本。
- 数据库访问 MCP:给后端开发任务提供数据结构的实时读取能力。
- 基础编码类 Skills:如“生成接口骨架”“生成数据模型”“编写单元测试模板”。
- 一个代码审查 SubAgent:在主代理完成任务后,承担专职复查工作。
每加一套模块,都要回到成本收益来校验:这个模块是否反复解决问题?它是否降低了任务的整体复杂度?如果答案是否定的,宁可去掉也不要让配置堆叠成“什么都能做、什么都做不好”的大杂烩。
6. 常见问题与排查技巧实录
6.1 代理出错时,是 Prompt 的问题还是 Skills 的问题
这个排查思路必须放在最前面。我这几次跑偏(指代开发流程出错)的教训告诉我:当你拿到一个不符合预期的输出时,第一件事不是重新写一遍 Prompt,而是先判断哪一层出了问题。
按以下顺序排查:
- 任务有没有被正确解析?如果方向都错了,说明 Prompt 层意图不清晰,先改 Prompt。
- 执行过程有没有按正确的标准流程走?如果步骤对、流程错,说明 Skills 的触发条件或步骤定义有问题。
- 中间数据有没有成功获取?如果报出“拿不到文件”“查不到表”,说明 MCP 服务端配置或鉴权有问题。
- 任务结果有没有经过专职复查?如果没有,说明 SubAgent 的职责链条断了。
不要一上来就盲目调 Prompt,先把执行日志打印出来,看代理实际走了哪几步再定位。
6.2 Skills 跑不起来,通常是“描述性”问题
我在 iManus 上配置 Skills 时踩过最深的坑,是给 Skills 起的名字和描述含糊不清。代理判断是否调用 Skills,依赖的是名字和描述与用户意图的语义匹配度。如果描述写得像“这是一个高级编码流程”,代理根本不知道什么时候该用它。
后来我改成非常直白的描述,例如:
“当用户需要新增一个标准 CRUD API 接口时,使用此 Skills。”
这种描述让路由精度大幅提升。所以,如果你的 Skills 总是没被调用,先去查看它的 name 和 description,而不是怀疑代理的能力。
6.3 MCP 配置正确但调用失败,如何定位
MCP 服务端配置正确并不代表调用链路一定通畅。我常用的是三个排查动作:
- 第一,检查服务鉴权信息是否已注入当前会话环境。有时候服务端配置没问题,但新起的子会话没有携带鉴权令牌,导致空手而归。
- 第二,检查返回内容里的字段命名是否前后一致。如果服务端返回了一个额外的嵌套结构,代理在解析时可能会抓不住重点。
- 第三,检查超时时间设置。编码代理经常要并发调用多个 MCP 服务,如果同步阻塞式地等待某个响应超过限制时间,整个链路就停了。
6.4 SubAgent 的结果质量不稳定
如果你发现 SubAgent 输出的东西时好时坏,一多半是因为它的工作协议没定义清楚。我建议给每个 SubAgent 补充“交付格式要求”和“自检清单”,这会带来不小的改善。比如,接口定义审查 Agent 的协议里明确要求“输出按严重级别排序的清单”“每条建议必须说明关联代码文件与字段”,它就不会给出一堆泛泛而谈的评论。
另外要留一个心眼:多条 SubAgent 并行时,主代理的内存占用和调用时长都会明显上升。如果你的任务有大量上下文依赖,不要盲目并行,先让主代理评估两个子任务之间的耦合度。
6.5 不要过度配置
最后聊一个我到后期才想明白的事:这套体系不是模块配得越多越好。配置过度的典型症状是,主代理每次启动任务前要先花大量时间确定该用哪个 Skills、该派给哪个 SubAgent,最终不仅慢,还可能因为模块见的优先级冲突给出奇怪的结果。
我最开始给某项目一口气配了十几个 Skills、五个 SubAgent、七八个 MCP 服务,结果代理在一个简单的新增接口任务里绕了一圈弯路,最后生成的代码还不如不配。后来精简到三个必需 Skills 加一个专用 SubAgent,效果反而稳定了。
我的个人建议是:先从“最小可用”起步,先配置文件系统 MCP 和代码执行沙箱,再把高频重复工作沉淀成两到三个 Skills,等确认流程熟练后再引入 SubAgent 做专项分工。一点一点加,最后这个配置体系就是你自己的真实工作流的镜像,而不是一个为了满足配置欲望而堆出来的展示架。
这篇文章里提到的几个配置清单和操作流程,是我在多个虚构项目上反复实验后筛出来的经验值。每个人的项目类型不一样,最终形态也未必相同,但核心思路是一致的:分清 Prompt、Skills、MCP、SubAgent 各自的位置,然后让它们在一个完整链路里各司其职。我自己的习惯是,每接一个新项目,先花半小时梳理这四个层面的“最简需要”,而不是照搬旧项目的全套配置。这种“少即是多”的做法,在陌生项目里往往比堆配置更能跑出你想要的效果。