Agent 和 Skill 到底差在哪?
潘忠显 / 2026-07-02
在上一篇里,我聊了 Agent Runtime 是什么、它和 Agent 有什么区别。这一篇换个角度,聊一个更贴近日常使用的困惑。
如果你用过 Cursor、Claude Code、Codex 这类工具,去翻它们的配置目录,会发现一个有意思的现象:
Agent 是一堆 Markdown,Skill 也是一堆 Markdown。 所以很多人第一反应是:都是 markdown,Skill 不就是个小号 Agent 吗?
这个"形式上都是 markdown"的判断没错。但和上一篇讲 Agent 与 Runtime 一样,形式相似,不代表定位相同。
- Agent:在很多工具里,通常表现为一个(或一组)Markdown 配置 + Prompt + 工具权限声明。
- Skill:在很多工具里,也常常表现为一个 Markdown 文件,配合特定目录结构和元数据,外加一些脚本、模板、资源。
实际上,Agent 定义"我是谁",Skill 定义"这件事怎么做"。 本文会围绕此展开讨论。
一、Agent:定义「我是怎样一个 AI」
Agent 更像是一个角色配置。比如一个 Go 工程师 Agent,它的 Markdown 大概长这样:
你是一名资深 Go 工程师。
编码风格:
- 优先简单
- 避免过度设计
回答方式:
- 先给结论
- 再解释原因
工具权限:
- 可以读取代码
- 可以执行终端命令
Agent 回答的是这样一个问题:AI 应该以什么身份工作?
所以你会看到各种各样的 Agent:
- Go 开发 Agent
- 产品经理 Agent
- 测试工程师 Agent
- 架构师 Agent
切换 Agent,相当于换一个人格。 它决定的是"这个人是谁、用什么风格、有哪些权限"。
二、Skill:定义「怎么完成某件事」
Skill 则更像是一个可复用的工作流。它不描述"我是谁",而是描述"遇到某类任务该怎么做"。
比如一个 release-note skill:
当用户要求生成 Release Note 时:
1. 查找最近的 Git Commit
2. 分类:Feature / Fix / Refactor
3. 输出 Markdown
再比如一个 code-review skill:
当用户要求 Code Review 时:
1. 查找变更文件
2. 检查:Bug / 性能问题 / 安全问题
3. 给出建议
Skill 回答的是另一个问题:遇到某种任务时,应该怎么做?
它本身不绑定身份。同一个 code-review skill,既可以被 Go Agent 用,也可以被前端 Agent 用。
三、两个类比,一眼看懂分工
如果把这类工具看成一家公司:
| Agent = 员工 | Skill = SOP(标准作业流程) |
|---|---|
|
后端工程师
前端工程师
测试工程师
决定的是:这个人是谁。
|
发布流程
Code Review 流程
故障排查流程
决定的是:这件事怎么做。
|
如果你更习惯软件工程的说法,这个对应关系会更精确:
| 概念 | 软件工程类比 |
|---|---|
| Agent | main prompt / 系统角色 / 程序入口配置 |
| Skill | 可复用的 prompt module / 函数实现 |
| Agent 调用 Skill | 函数调用 |
所以可以这样记:Agent 是“角色定义”,Skill 是“能力插件”。 两者都可能以 Markdown 形式存在,但 Skill 不一定只有 Prompt;它还可以带脚本、模板、参考资料。Agent 负责定义是谁,Skill 负责定义遇到某类任务时怎么做。
四、Agent 可以挂多个 Skill
理清了定位,它们的组合关系就很自然了。一个 Agent 通常会挂载多个 Skill:
Go Backend Agent
├── code-review skill
├── write-test skill
├── release-note skill
└── debug skill
当你说"帮我 review 一下这个 PR",Agent 会判断:这件事需要用到 code-review skill。
然后把对应的 Markdown 内容动态加载进上下文,按里面的流程执行。
注意这里的关键词:动态加载。Skill 平时并不占用上下文,只有命中时才被展开。这也引出了下一个问题——为什么非要拆成 Agent 和 Skill?
五、为什么要拆开?
假设我们不拆,把所有东西都塞进一个 Agent 的 Prompt 里:
你是 Go 工程师。
如果用户要 review:
...
如果用户要写测试:
...
如果用户要发布:
...
如果用户要排查问题:
...
随着场景变多,这个 Prompt 会迅速膨胀成一个巨无霸,比如超过几千行。每次对话都要把所有流程一股脑塞进上下文,又贵又难维护。
拆开之后就清爽了,需要哪个,临时加载哪个:
Agent: 你是 Go 工程师
review skill: review 流程
test skill: 测试编写流程
release skill: 发布流程
这有点像写程序里的类(Class)和函数(Function):把通用角色抽成主体,把可复用的具体流程拆成独立模块,按需调用。既省上下文,也好维护和复用。
六、关键澄清:都是「配置」,不是「状态」
讲到这里,还有一个特别容易混淆的点,值得单独拎出来说——它也是真正把 Agent / Skill 和上一篇的 Runtime 区分开的地方。
很多人会下意识觉得 Agent “记得"自己干过什么。但在 one-shot 命令模式下,比如:
claude -p "1+1等于几" # 输出:2
claude -p "刚才那个问题是什么" # Claude 并不知道
第二条命令里,模型完全不记得第一条。因为每次执行其实是:
进程启动 → 构造 Prompt → 调用模型 → 退出进程
历史在进程退出时就丢了。 这种模式下的 Agent,本质更接近 Unix 工具——像 grep、sed、awk,执行一次,退出一次。
那为什么换了一天,codex run 写代码时,“你是 Go 专家、必须写单测"这些设定还在生效?
因为那不是会话历史,而是固定配置。每次启动都会重新加载一遍:
| 内容 | 是否跨命令保留 |
|---|---|
| AGENTS.md / CLAUDE.md | ✅ |
| Skill | ✅ |
| Rules | ✅ |
| 上一次聊天内容 | ❌(默认) |
| 上一次推理过程 | ❌(默认) |
这张表道出了本质:Agent 和 Skill 属于"配置”,每次启动重新加载;而会话历史、推理过程属于"状态”,默认不保留。
那 Agent 想"记得"上次聊了什么,怎么办?通常有三种做法,而它们都不在 Agent / Skill 这层:
- 调用方维护:把对话存进
session.json,下次启动时读出来拼进 Prompt。状态在文件里,不在模型里。 - 工作目录记忆:Claude Code 偏爱这种,靠
CLAUDE.md、history/、state.json等本地文件,启动时读取项目状态,营造"它记得我"的体验。 - 长期 Memory:LangGraph、OpenAI Agents SDK、CrewAI、AutoGen 这类框架,把记忆放进 SQLite / Postgres / Redis / 向量库,启动时检索历史、恢复 Session。
发现没有——这三种"记住状态"的能力,基本都属于 Runtime / 调用方 / 框架层要解决的问题。
七、放回三层模型
到这里,正好可以把上一篇和这一篇串成一个完整的三层模型:
Runtime = 让它跑起来,并管理状态 / Session / Memory
Agent = 我是谁(角色 + 策略 + 权限)
Skill = 某件事怎么做(可复用的工作流 / 能力包)
各自的边界也就清楚了:
- Agent 和 Skill 都是 声明式配置,以 Markdown 形式存在,每次启动被加载进上下文。
- 它们本身 不持有状态。Session、历史、长期记忆是 Runtime 的职责。
所以,Agent 和 Skill 形式上像,是因为它们都是"喂给模型的静态声明";定位上不同,是因为一个回答"我是谁",一个回答"这件事怎么做"。而真正让它们跑起来、并记住跑到哪儿了的,是它们下面那层 Runtime。
总结
Agent 定义角色,Skill 定义流程,Runtime 负责执行与记忆。
三者都可能以 Markdown 的形式出现在你的项目里,但它们解决的是完全不同的问题:
- 看到一个 md 在描述"我是一个怎样的 AI、有什么权限"——那是 Agent。
- 看到一个 md 在描述"遇到某个任务,第一步、第二步该怎么做"——那是 Skill。
- 而当你发现它"居然记得上次聊了什么"——那已经不是某个 md 的功劳,是 Runtime 在背后兜底。
后面再看 LangGraph、OpenAI Agents SDK、Mastra 这类 Agent Runtime / Agent Framework 时,也可以沿用这套分层:Agent 和 Skill 多数是声明与能力包,真正负责循环、状态、工具执行和协作编排的,是 Runtime 这一层。
