2025 年,AI 应用迎来了爆发式增长,每两周都有新的 AI 产品发布和新的技术突破,好像不跟上就要被时代抛弃了。然后大家都产生了一种 AI 时代特有的焦虑 FOMO(Fear of Missing Out)。看了很多文章、教程,总感觉隔靴搔痒——知道 Agent 很厉害,知道 MCP 和 Skill 很神奇,然而看多了也只是徒增焦虑而已。
后来笔者悟了:与其接收那些零碎的信息,不如自己动手实现一个自己的 Agent。这才是程序员面对未知的正确姿势。于是笔者做了这个项目:mini-agent-ts。
这是一个能在终端运行的 Coding Agent,它的核心特性包括:
- 支持一个简单的 ReAct 循环
- 内置基础工具:提供了文件操作(读取、写入、搜索)、Bash 命令执行等基本工具,让 Agent - 能够操作你的本地环境。
- 支持 MCP 和 Agent Skill
可以把它理解为一个极简版的 Claude Code。它的代码量不大,非常适合作为学习Agent的实验平台。你可以在这个基础上做各种魔改, 改Prompt、加工具等等…总之,怎么折腾都行。 另外此项目是模仿 MiniMax 的 mini-agent 项目,不过 mini-agent 是用 Python 实现的,但是市面上大部分类似的成熟项目都是用 TS 写的, 比如 OpenCode 和 Claude Code,因此笔者想用 TS 来实现。 亲手构建一个这样的项目之后,你就会对Agent有个更好的了解。关于AI能做什么,不能做什么,哪些地方需要人工介入,这些问题在实践过程中会一点点变清楚。
Agent 就是个简单的循环
很多文章把 Agent 讲得天花乱坠,其实它的核心逻辑非常简单,就是 ReAct(Reasoning and Acting)循环。这是 OpenAI 的姚顺宇在 2023 年提出的 Agent 范式,至今依旧是 Agent 应用的基石. 具体来说,就是 Agent 根据任务目标决定要调用什么工具,接着观察工具返回的结果,根据结果再调用工具。就这么不断循环,直到任务完成。
上伪代码:
for step in 1 to maxSteps: toolList = listTools() // 接收LLM API的输出 for chunk in llmClient.generateStream(messages, toolList): 输出 chunk.thinking 输出 chunk.content 收集 chunk.tool_calls // 如果无工具调用 → 任务完成 if toolCalls 为空: return fullContent // 如果有工具调用 执行工具 for each toolCall: result = executeTool(toolCall.function.name, toolCall.function.arguments) // 观察:将结果加入消息历史 messages.push({ role: 'tool', content: result, tool_call_id: toolCall.id, tool_name: toolCall.function.name }) return "超过最大步数"
一个 for 循环,最多执行 maxSteps 次。在每一轮循环中:
- 调用 LLM,让它思考并决定是否需要使用工具
- 如果不需要工具,说明任务完成,返回结果
- 如果需要工具,执行工具调用
- 把工具执行结果加入对话历史
- 进入下一轮循环,LLM 会根据结果继续思考
Agent Skill:给 Agent 配工具包
Agent Skill 的概念更简单,就是Prompt和脚本的集合。
一个最简单的 Skill 示例——”本地时间 Skill”。这个Skill 有啥用呢?因为你如果直接问大模型”现在几点了”,它通常会回答自己服务器的时间。比如你在国内问 ChatGPT 现在几点,它反馈的是美国时间。这会导致严重的后果——如果你让 Agent 帮你看看今天有什么最新的邮件,它可能会因为时差去查找昨天的内容。有这个Skill 之后,Agent 会调用你本地电脑的时间和时区来回答问题,用户体验会得到极大的提升。下面是这个 Skill 的内容:
---name: local-timedescription: 获取用户本地时间和时区。当用户询问「现在几点了」、「今天日期」、「当前时区」等问题时使用此技能。-------------------------------------------------------------------------------------------------------------# 本地时间 Skill## 使用方法使用 bash 命令获取本地时间和时区:```bash# 获取当前时间date# 获取时区信息date +「%Z %z」```## 使用场景当用户请求以下任务时,主动使用此技能:- 「现在几点了?」- 「今天几号?」- 「我现在在哪个时区?」- 任何涉及「今天」、「现在」等时间相关的问题
就是这么简单!一个 Markdown 文件,加上开头的 YAML 格式的元数据(name 和 description),附上详细的 Prompt 指南,就构成了一个简单的 Skill。
Skill 是怎么被使用的呢?Agent 启动时,会把所有 Skill 的元数据插入到 System Prompt 中。这样 LLM 就知道有哪些 Skill 可用,以及每个 Skill 是用来做什么的。当 LLM 判断需要使用某个 Skill 时,它会调用内置的 `get_skill`工具,传入 Skill 的名称。这个工具会返回该 Skill.md 的完整内容。LLM 拿到完整的 Skill 内容后,就能根据里面的指导来执行具体任务了。这种设计的好处是:初始时只占用很少的上下文空间(只有简短的元数据),只有在真正需要时才加载完整内容,大大提高了上下文的利用效率。
上面展示的只是一个最简单的 Skill 示例。实际上,一个完整的、复杂的 Skill 不仅仅是一个 Markdown 文件,它还可以包含更多组成部分。比如
-
脚本工具(scripts/):包含 Python、Bash 等脚本,甚至可以与 MCP 结合调用各种 API。
-
详细指南(references/):将操作说明、API 文档、最佳实践等直接编写在 Skill 内部
-
数据存储(assets/):配备数据库或文件来存储数据,比如你想创建一个记录卡路里消耗的 Skill,就可以通过 CSV 文件或 SQLite 数据库来保存每天的饮食记录。
因此,一个复杂的 Skill 目录结构可能是这样的:
my-skill/├── SKILL.md # 主文件(必需)├── scripts/ # 脚本工具│ └── process.py├── references/ # 参考资料│ └── api-docs.md└── assets/ # 资源文件└── template.json
Agent Skill vs MCP
你可能会问:为什么要有 Skill?MCP 不是已经能提供工具了吗?核心原因是:Skill 能够节省大量的上下文空间。
如果你用过 MCP,就会发现它会把所有工具的名字和描述全部一次性载入到上下文里。以 GitHub 的官方 MCP 为例,它拥有二十几个工具:提交 Issue、管理 Branch、查看登录状态、创建 Pull Request…这些工具的描述如果一股脑全部堆在上下文里,从而压缩 Agent 的记忆能力。Agent 能记住的对话历史就会变少,处理复杂任务的能力就会下降。
而Skill 在初始加载时,只会在上下文中插入一段很简短的元数据。比如:
---name: local-timedescription: 这里有一个 GitHub Skill,可以用来管理 Repository、提交 Issue 或查看登录状态----------------------------------------------------------------------------------------
当 Agent 需要使用这个 Skill 时,它会通过内置的 get_skill 工具来获取该 Skill.md 的完整内容。这种”按需加载”的设计,既保证了 Agent 能获得足够的信息,又避免了上下文空间的浪费。
而且相比 MCP,Skill 更加灵活且简单。MCP 需要定义严格的JSON接口规范、参数类型、返回格式,而 Skill 只需要用自然语言写的 Prompt 就可以了.
当然,Skill 更依赖大模型本身的智能。MCP 通过明确的接口定义保证了执行的可靠性,而 Skill 需要大模型理解指令并正确执行。但随着技术的发展,大模型的智能水平在不断提升,能够理解和执行越来越复杂的指令,我想这也是 Skill 应运而生的原因。
展望未来
这个简单的 Agent 循环可以说是 LLM 应用的 Hello World,还有很多提升空间。比如单循环的 Agent 能做的事情有限,如果能实现 Multi-Agent 协作,就能处理更复杂的任务。这涉及到不同 Agent 之间的任务分配和协作机制、Agent 之间的通信和状态共享,以及如何避免上下文爆炸等问题。这些都是值得探索的方向。
还有目前只是一个简单的命令行工具,你可以给它加上更友好的界面。桌面端 UI 可以使用 Electron 或 Tauri 构建,Terminal UI 可以使用 Ink 构建更美观的命令行界面,手机移动端 UI 可以使用 React Native 或 Flutter 构建移动应用。不同的界面适合不同的使用场景。
以这个项目为基础,相信大家可以开发出更多有意思的东西。被称为 Agent 元年的 2025 年就要过去了, 相信 2026 年 LLM 应用会释放更多想象力, 我们拭目以待。