[转][译] 从零开始构建 OpenClaw — 第一部分(智能体核心)
[转][译] 从零开始构建 OpenClaw — 第二部分(技能插件系统)
[转][译] 从零开始构建 OpenClaw — 第三部分(元技能)
如果你的 AI 编码智能体能在对话中自行学习新技巧,无需重启会怎样?
这就是我们在 openclaw-mini 第 3 部分所构建的:一个捆绑的“元技能”,允许智能体即时创建新技能。让它构建一个技能,10 秒后该技能即可启用并准备使用。
本文将介绍我们是如何实现的——从基础智能体循环,到技能插件系统,再到元技能和使这一切运行的热重载机制。
快速回顾:基础
第一部分:智能体核心
openclaw-mini 是基于 PI SDK 构建的终端 AI 编码智能体。其核心是一个 REPL 循环:你输入一个提示词,LLM 调用工具( read , write , edit , bash , web_fetch , web_search ),结果反馈回来,循环继续直到任务完成。它支持多个 LLM 提供商(Anthropic、OpenAI、Google 等),自动从你的项目根目录加载上下文文件,并在会话之间持久化对话。
第二部分:技能插件系统
第二部分增加了一个可扩展的技能系统。技能是定义为 Markdown 文件的可用工作流——无需代码。每个技能是一个包含单个 SKILL.md 文件的目录:
---
name: git-commit
description: Create well-structured git commits with conventional commit messages
---
When asked to commit changes, follow this workflow:
1. Run `git status` to see modified, added, and deleted files
2. Run `git diff --staged` to review what's staged
3. Analyze the changes and determine the conventional commit type
4. Write a commit message
5. Run `git commit -m "<message>"`
6. Show `git log --oneline -1` to confirm
这是一个完整的技能。YAML 前置部分提供了名称和描述(这是告诉智能体何时使用它的内容),Markdown 正文提供了逐步说明。
技能会自动从三个目录中按优先级顺序发现:
如果同一技能名称在多个位置存在,最高优先级的源将胜出。这意味着你可以用你自己的版本覆盖任何捆绑的技能。
系统采用渐进式披露——只有技能名称和描述会放入系统提示词中。完整指令会在技能实际触发时按需加载。这使提示词保持简洁。
我们发布了 4 个捆绑技能: git-commit 、 code-review 、 summarize 和 weather 。
第 3 部分:元技能
问题
技能系统运行得很好,但创建新技能意味着:
- 在正确的位置手动创建目录
- 手动编写格式正确的
SKILL.md文件 - 重启智能体,以便它发现新技能
步骤 1 和 2 正是 AI 智能体擅长的类型。而步骤 3 只是阻力。我们希望智能体能处理整个流程——并且希望结果能立即获得。
解决方案:两个改变
我们做了两个改变:
- 一个
skill-creator捆绑技能——一个其工作是为其他技能创建技能 - 热重载 — 技能在每次提示词时都会重新发现,因此新创建的技能可以立即使用
让我们逐一查看。
技能创建器:一个编写技能的技能
技能创建器本身就是一个 SKILL.md 文件。在机制上它并没有什么特别之处 — 它与其他技能的格式相同。使其“元”的是它的指令告诉智能体如何创建新的技能。
这是完整的文件:
---
name: skill-creator
description: Create new skills for openclaw-mini. Use when the user wants to
create, design, or build a custom skill, workflow, or automation.
---
When asked to create a skill, follow these steps:## 1. UnderstandAsk the user:
- What should the skill do? Get 1-2 concrete usage examples.
- Should it be a **user skill** (available in all projects) or
**project skill** (shared with the team)?Default to user skill if not specified.## 2. CreateA skill is a directory with a single `SKILL.md` file: skill-name/
└── SKILL.md**Naming rules:**
- Lowercase letters, digits, and hyphens only
- No leading, trailing, or consecutive hyphens
- Max 64 characters
- Directory name must match the `name` in frontmatter**SKILL.md format:** ---
name: skill-name
description: What the skill does and WHEN to use it
--- Instructions in Markdown for an AI agent. 1. Step one — which tools to use and how
2. Step two — what to check or analyze
3. Step three — how to present the output**Writing tips:**
- The `description` triggers the skill — be specific about WHEN to use it
- Write in imperative form for another AI agent, not a human
- Reference tools by name: read, write, edit, bash, web_fetch, web_search
- Keep it concise — only include what the agent wouldn't already know**Write the skill:**
- mkdir -p <skills-dir>/<skill-name>
- Then use `write` to create SKILL.md in that directoryPaths:
- User skills: ~/.openclaw-mini/agents/main/agent/skills/<name>/SKILL.md
- Project skills: <workspace>/.openclaw-mini/skills/<name>/SKILL.md## 3. Verify1. Read back the file to confirm correctness
2. Tell the user the skill is available on the next prompt
大约 60 行。它教智能体:
- 先问——在写任何东西之前,先理解用户想要什么
- 格式——YAML 前导部分带有
name和description,Markdown 正文包含步骤 - 命名规则 — 使用小写字母和连字符,与目录名匹配
- 存放位置 — 个人技能目录用于个人,项目目录用于团队共享
- 验证 — 重新读取文件以确认其是否正确写入
智能体已经拥有 bash 和 write 工具,因此它可以创建目录并写入文件。无需新工具。技能创建器纯粹是指导 — 它只是告诉智能体如何使用它已有的工具。
热重载:4 行代码改变一切
在磁盘上创建技能只是故事的一半。如果没有热重载,用户需要在新的技能可用之前重启智能体。这破坏了魔法。
修复方案出人意料地小。以下是技能发现之前的样貌:
// Runs once at startup
const { skills } = discoverSkills(workspaceDir);
const skillsPrompt = skills.length > 0
? formatSkillsForPrompt(skills) : undefined;
技能只被发现一次,存储在 const 中,并用于每个后续的提示词。启动后创建的任何内容都是不可见的。
改动:使变量可变,并在每次提示词周期顶部重新发现技能。
// At startup (changed const → let)
let { skills } = discoverSkills(workspaceDir);
let skillsPrompt = skills.length > 0
? formatSkillsForPrompt(skills) : undefined;
// Inside the REPL loop, before each prompt is processed
const freshSkills = discoverSkills(workspaceDir);
skills = freshSkills.skills;
skillsPrompt = skills.length > 0
? formatSkillsForPrompt(skills) : undefined;
就这样。在 REPL 循环中添加了四行代码。在每次提示词时,我们会重新扫描三个技能目录,重新构建技能目录,并将新的元数据注入系统提示词中。
这很昂贵吗?不。 discoverSkills() 对三个小目录(每个通常有 5-10 个条目)执行 readdirSync 操作,并解析几个小的 Markdown 文件。它是亚毫秒级的——与后续的 LLM API 循环相比完全可以忽略不计。
DefaultResourceLoader (处理 /skill:name 命令扩展)已经按提示词重新创建,因此它可以通过其 reload() 调用自动获取新技能。那里不需要做任何改动。
观看实际效果
这是一个实际会话。我们要求智能体创建一个“hello-world”技能,然后立即使用它:
┌ openclaw-mini
│ model: anthropic/claude-sonnet-4-20250514
│ workspace: /Users/you/project
│ skills: git-commit, code-review, skill-creator, summarize, weather
└ /new /think /model /skills /quit
> create a skill called hello-world that greets the user with a fun fact
Before I create it:
1) Do you want this as a user skill (available in all projects)
or a project skill (only in this repo/team)?
2) Give me 1-2 example prompts you expect to trigger it.
If you don't care, I'll default to a user skill and make it trigger
on prompts like: "hello", "greet me", "say hi", "hello world".
(4.7s)
> user skill
Created the user skill `hello-world`:
~/.openclaw-mini/agents/main/agent/skills/hello-world/SKILL.md
It will trigger when you ask for a hello/greeting and will reply
with a concise greeting plus exactly one fun fact.
The skill is available starting on your next prompt.
(8.2s)
> Hey
Hi! Hope you're having a good day.
Fun fact: Honey never spoils — edible honey has been found in
ancient Egyptian tombs thousands of years old.
(1.5s)
三个提示词。第一个创建技能,第二个使用它。无需重启,无需手动文件编辑,无需配置。智能体询问了我们的需求,编写了 SKILL.md ,在下一个提示词中,热重载立即捕获了它,它就正常工作了。
为什么这种模式很重要
元技能模式很有趣,因为它具有递归性——一种创建技能的技能,使用与其他所有技能相同的格式和发现机制。没有特殊的 API,没有独立的“技能管理器”服务,没有管理界面。它只是一个恰好包含编写 SKILL.md 文件指令的 SKILL.md 文件。
这意味着:
- 你可以覆盖它。不喜欢智能体创建技能的方式?将你自己的
skill-creator/SKILL.md文件放入你的用户技能目录。你的版本将生效。 - 它可以组合。技能创建者使用与其他所有技能相同的工具(
bash,write)。不需要新的功能。 - 它很透明。输出是一个普通的 Markdown 文件,你可以阅读、编辑或删除。没有任何隐藏的内容。
热重载功能是关键。没有它,元技能只是创建文件的便利功能。有了它,智能体可以在实时扩展其自身能力——这是一种根本不同的体验。