Day1讲了什么是Agentic AI,Day2讲了如何用OpenClaw搭建Agent。

今天进入更具体的领域:自定义Skill开发。

Skill是OpenClaw的能力扩展单元。每个Skill是一个独立的功能模块,让Agent能够执行特定任务。开发一个自定义Skill,你就是在为Agent添加新的能力。

一、Skill是什么

1.1 概念解析

在OpenClaw中,Skill是一种可插拔的能力扩展机制。

你可以把Agent理解为一个人,Skill就是这个人掌握的技能。一个人在工作时,需要调用不同的技能来完成不同的任务。Agent也一样,通过调用不同的Skill来扩展自己的能力。

OpenClaw自带了很多内置Skill,比如:

  • weather:查询天气
  • calculator:数学计算
  • browser-automation:浏览器自动化
  • feishu-doc:飞书文档操作

你也可以开发自己的Skill,让Agent完成特定业务场景的任务。

1.2 Skill的组成

一个Skill包含以下部分:

skill-name/
├── SKILL.md # 必选,技能定义文件
├── scripts/ # 可选,执行脚本
├── references/ # 可选,参考资料
└── assets/ # 可选,资源文件

SKILL.md是核心文件,包含:

  • YAML头信息:name和description
  • Markdown正文:使用说明和工作流程

description字段非常重要,因为Agent根据这个字段判断什么时候该调用这个Skill。

1.3 Skill与Agent的关系

当用户提出一个需求时,Agent会:

  1. 理解用户需求
  2. 判断需要调用哪个Skill
  3. 根据Skill的使用说明执行任务
  4. 返回结果给用户

Skill提供了”做什么”和”怎么做”的信息,Agent负责”什么时候做”和”协调调度”。

二、Skill开发入门

2.1 开发一个天气查询Skill

我们从头开始,开发一个简单的天气查询Skill。

第一步:创建Skill目录

mkdir -p ~/.openclaw/workspace/skills/my-weather/scripts
mkdir -p ~/.openclaw/workspace/skills/my-weather/references

第二步:编写SKILL.md

name: my-weather
description: 查询指定城市的天气信息。当用户询问天气、温度、湿度、穿衣建议时使用此技能。

# 天气查询Skill

## 使用方法

用户说"北京天气怎么样"时,调用此Skill。

## 工具

使用心知天气API获取实时天气数据。

## 工作流程

1. 提取用户提到的城市名称
2. 调用天气API获取数据
3. 格式化结果返回给用户

## 输出格式

返回格式:
– 城市:xxx
– 天气:xxx
– 温度:xxx°C
– 湿度:xxx%
– 建议:xxx

第三步:编写执行脚本

创建scripts/query_weather.py

#!/usr/bin/env python3
import requests
import sys
import json

def get_weather(city):
"""获取天气数据"""
# 这里使用心知天气API作为示例
api_key = "YOUR_API_KEY" # 需要替换为实际API Key
url = f"https://api.seniverse.com/v3/weather/now.json?key={api_key}&location={city}&language=zh-Hans&unit=c"

try:
response = requests.get(url, timeout=10)
data = response.json()

if 'results' in data:
result = data['results'][0]
now = result['now']
location = result['location']

return f"{location['name']}:{now['text']},温度{now['temperature']}°C,湿度{now['humidity']}%"
else:
return f"未找到{city}的天气数据"
except Exception as e:
return f"查询失败:{str(e)}"

if __name__ == "__main__":
if len(sys.argv) > 1:
city = sys.argv[1]
print(get_weather(city))
else:
print("请提供城市名称")

赋予执行权限:

chmod +x scripts/query_weather.py

2.2 注册Skill

编辑OpenClaw配置文件~/.openclaw/openclaw.json

{
skills: {
load: {
extraDirs: ["~/.openclaw/workspace/skills"]
},
entries: {
"my-weather": {
enabled: true
}
}
}
}

重启Gateway:

openclaw gateway restart

2.3 测试Skill

在控制台发送消息:

北京天气怎么样

Agent应该能识别需要调用my-weather Skill,并返回天气信息。

三、Skill开发进阶

3.1 多工具协作

一个复杂的Skill通常需要多个工具协作。

配图

假设我们要开发一个”旅行助手”Skill,功能包括:

  • 查天气
  • 订机票
  • 订酒店
  • 生成行程

目录结构

travel-assistant/
├── SKILL.md
├── scripts/
│ ├── weather.py
│ ├── flights.py
│ ├── hotels.py
│ └── itinerary.py
└── references/
└── cities.json

SKILL.md示例

name: travel-assistant
description: 旅行助手。当用户需要查询航班、酒店、天气或规划行程时使用此技能。

# 旅行助手Skill

## 功能

1. 查询天气
2. 搜索航班
3. 搜索酒店
4. 生成行程

## 使用场景

– "帮我查一下下周去上海的航班"
– "北京有哪些五星级酒店"
– "上海三天行程怎么安排"

## 工作流程

根据用户需求选择对应工具:
1. 天气查询 → weather.py
2. 航班搜索 → flights.py
3. 酒店搜索 → hotels.py
4. 行程生成 → itinerary.py

## 参数

– origin:出发城市
– destination:目的地
– date:日期
– budget:预算

3.2 参考资料的使用

当Skill需要特定领域的知识时,可以通过references目录提供。

例如,开发一个”代码审查”Skill:

code-review/
├── SKILL.md
├── scripts/
│ └── review.py
└── references/
├── best-practices.md
└── common-issues.md

SKILL.md中引用参考资料:

## 代码审查标准

参考 `references/best-practices.md` 获取详细的代码规范。
参考 `references/common-issues.md` 了解常见问题清单。

3.3 输出资源

如果Skill需要生成文件,可以通过assets目录提供模板:

report-generator/
├── SKILL.md
├── scripts/
│ └── generate.py
└── assets/
└── template.xlsx

生成脚本中引用模板:

import shutil
import os

template_path = os.path.join(os.path.dirname(__file__), '../assets/template.xlsx')
output_path = 'report.xlsx'
shutil.copy(template_path, output_path)
# 然后打开文件进行填充

四、Skill触发机制

4.1 description的重要性

Skill的description字段决定了它什么时候被触发。

好的description示例

description: 当用户需要查询天气、获取穿衣建议、或了解某地气候时使用此技能。

差的description示例

description: 天气相关的技能。

好的description要具体说明使用场景,让Agent能准确判断何时调用。

4.2 关键词匹配

Agent会根据description中的关键词进行匹配:

  • “天气” → 触发天气Skill
  • “航班”、”机票” → 触发旅行Skill
  • “代码”、”审查” → 触发代码审查Skill

4.3 多Skill协作

有时一个任务需要多个Skill协作完成。

例如用户说”帮我查查上海后天飞北京的航班,顺便看看天气”。

Agent会:

  1. 调用天气Skill查询上海天气
  2. 调用航班Skill查询航班信息
  3. 整合结果返回给用户

五、Skill开发最佳实践

5.1 目录结构规范

保持目录结构清晰:

skill-name/
├── SKILL.md # 必须,技能定义
├── scripts/ # 推荐,可执行脚本
├── references/ # 按需,参考资料
└── assets/ # 按需,输出模板

5.2 错误处理

每个脚本都要有完善的错误处理:

def main():
try:
# 业务逻辑
pass
except ValueError as e:
print(f"参数错误:{str(e)}")
sys.exit(1)
except requests.RequestException as e:
print(f"网络错误:{str(e)}")
sys.exit(2)
except Exception as e:
print(f"未知错误:{str(e)}")
sys.exit(99)

5.3 日志记录

关键操作要记录日志:

import logging

logging.basicConfig(
level=logging.INFO,
format='%(asctime)s – %(name)s – %(levelname)s – %(message)s'
)
logger = logging.getLogger(__name__)

def query_weather(city):
logger.info(f"查询城市:{city}")
# 执行查询
logger.info(f"查询成功:{result}")

5.4 依赖管理

如果Skill需要额外的Python包,创建requirements.txt:

requests>=2.28.0
python-dateutil>=2.8.0

安装依赖:

pip install -r requirements.txt

六、调试与优化

6.1 本地测试

开发完Skill后,先在本地测试:

cd ~/.openclaw/workspace/skills/my-weather
python scripts/query_weather.py 北京

确保脚本能正常运行。

6.2 查看日志

调试时查看OpenClaw日志:

openclaw logs –follow | grep my-weather

6.3 性能优化

如果Skill执行慢,检查:

  1. 网络请求是否超时
  2. 是否可以缓存结果
  3. 脚本是否有不必要的循环

6.4 优化description

如果Agent没有正确触发Skill,调整description:

  • 增加更多关键词
  • 明确使用场景
  • 说明边界情况

七、发布与分享

7.1 打包Skill

将Skill打包分享给其他人:

cd ~/.openclaw/workspace/skills/my-weather
tar -czvf my-weather.tar.gz *

7.2 安装他人Skill

从tar包安装:

openclaw skills install /path/to/my-weather.tar.gz

7.3 发布到社区

通过GitHub分享Skill:

  1. 创建仓库:skill-name
  2. 包含SKILL.md和必要的脚本
  3. 编写README说明使用方法

八、实战案例:开发一个提醒Skill

8.1 需求分析

我们需要开发一个”智能提醒”Skill,功能包括:

配图

  • 设置一次性提醒
  • 设置周期性提醒
  • 列出所有提醒
  • 取消提醒

8.2 目录结构

smart-reminder/
├── SKILL.md
├── scripts/
│ ├── set_reminder.py
│ ├── list_reminders.py
│ └── cancel_reminder.py
└── references/
└── time_formats.md

8.3 SKILL.md

name: smart-reminder
description: 智能提醒助手。当用户需要设置提醒、查看提醒列表、取消提醒、或询问"几点了"时使用此技能。

# 智能提醒Skill

## 功能

1. 设置提醒(一次性或周期性)
2. 查看所有活跃提醒
3. 取消指定提醒

## 使用示例

– "明天上午9点提醒我开会"
– "每周五下午3点提醒我周报"
– "我有哪些提醒"
– "取消明天9点的提醒"

## 参数

– time:时间(支持自然语言,如"明天9点"、"下周一")
– content:提醒内容
– repeat:重复周期(daily/weekly/monthly或不设置)

## 数据存储

提醒数据存储在 `~/.openclaw/reminders.json`

8.4 核心脚本

创建scripts/set_reminder.py

#!/usr/bin/env python3
import json
import sys
import os
from datetime import datetime, timedelta

REMINDERS_FILE = os.path.expanduser("~/.openclaw/reminders.json")

def load_reminders():
if os.path.exists(REMINDERS_FILE):
with open(REMINDERS_FILE, 'r') as f:
return json.load(f)
return []

def save_reminders(reminders):
os.makedirs(os.path.dirname(REMINDERS_FILE), exist_ok=True)
with open(REMINDERS_FILE, 'w') as f:
json.dump(reminders, f, ensure_ascii=False, indent=2)

def parse_time(time_str):
"""解析时间字符串"""
now = datetime.now()

if "明天" in time_str:
return (now + timedelta(days=1)).replace(hour=9, minute=0, second=0)
elif "下周" in time_str:
return now + timedelta(days=7)
elif "下个月" in time_str:
return now + timedelta(days=30)
else:
# 简单解析小时
try:
hour = int(time_str.split("点")[0][-2:])
return now.replace(hour=hour, minute=0, second=0)
except:
return None

def main():
if len(sys.argv) < 3:
print("用法:set_reminder.py <时间> <内容>")
sys.exit(1)

time_str = sys.argv[1]
content = sys.argv[2]

remind_time = parse_time(time_str)
if not remind_time:
print("无法解析时间,请使用自然语言如'明天9点'")
sys.exit(1)

reminder = {
"id": len(load_reminders()) + 1,
"time": remind_time.isoformat(),
"content": content,
"done": False
}

reminders = load_reminders()
reminders.append(reminder)
save_reminders(reminders)

print(f"提醒已设置:{remind_time.strftime('%Y-%m-%d %H:%M')} – {content}")

if __name__ == "__main__":
main()

8.5 测试

chmod +x scripts/*.py
python scripts/set_reminder.py "明天9点" "开会"

九、总结

9.1 核心要点

  1. Skill是能力扩展单元:让Agent获得执行特定任务的能力
  2. SKILL.md是核心:description决定触发时机,正文说明使用方法
  3. 脚本实现具体功能:保持脚本职责单一,可测试
  4. 参考资料提供领域知识:复杂场景需要reference文件

9.2 下一步

Day4我们会学习多Agent协作:如何让多个Agent协同工作,完成更复杂的任务。

9.3 课后作业

  1. 创建一个天气查询Skill
  2. 创建一个提醒Skill
  3. 测试两个Skill能否被正确触发

有问题在评论区留言,我会帮忙解答。

下期预告:Day4 多Agent协作:Sub-Agent工作流配置——如何让多个Agent协同工作

来源:OpenClaw官方文档(docs.openclaw.ai)

9.4 常见问题解答

Q:Skill和Agent是什么关系?

A:Agent是执行者,Skill是工具。Agent决定什么时候做什么,Skill负责具体怎么做。

Q:可以开发多少个Skill?

A:理论上没有限制。但Skill越多,Agent判断成本越高。建议按业务领域分组,每个领域一个主Skill,下面挂子Skill。

Q:Skill可以调用其他Skill吗?

A:可以。一个Skill的脚本可以调用另一个Skill的工具,实现Skill间的协作。

Q:Skill需要认证吗?

A:如果Skill需要访问外部API(如天气、地图),需要在配置中设置API Key。敏感信息建议使用环境变量。

Q:Skill的性能如何优化?

A:主要手段包括缓存结果、减少网络请求、使用异步处理。

9.5 Skill开发检查清单

开发新Skill时,按照以下清单检查:

  • [ ] SKILL.md存在且格式正确
  • [ ] description清晰说明使用场景
  • [ ] 所有脚本有执行权限
  • [ ] 错误处理完善
  • [ ] 日志记录完整
  • [ ] 本地测试通过
  • [ ] 配置已添加到openclaw.json
  • [ ] 重启Gateway后能正常触发

9.6 进阶话题

Skill版本管理

当Skill需要升级时,注意版本兼容性:

{
skills: {
entries: {
"my-weather": {
version: "1.0.0",
enabled: true
}
}
}
}

Skill依赖管理

复杂Skill可能依赖多个Python包:

# 在Skill目录下创建虚拟环境
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Skill测试框架

为Skill编写单元测试:

import unittest
from scripts.weather import get_weather

class TestWeather(unittest.TestCase):
def test_beijing(self):
result = get_weather("北京")
self.assertIn("北京", result)

if __name__ == "__main__":
unittest.main()

9.7 社区资源

官方示例

OpenClaw官方提供了多个示例Skill,路径:/usr/lib/node_modules/openclaw/skills/

可以参考这些示例学习最佳实践。

社区Skill市场

访问clawhub.ai可以找到社区开发者分享的Skill。

技术支持

遇到问题可以在官方Discord的#skills频道提问。

9.8 写在最后

Skill开发是OpenClaw进阶的必经之路。

掌握Skill开发,你就能让Agent完成任何你需要的任务。不再受限于内置功能,而是真正实现”定制化”。

建议先从简单的天气查询开始,熟悉Skill的开发流程,然后再尝试更复杂的场景。

记住:实践是最好的老师。看十遍不如动手一遍。

下期预告:Day4 多Agent协作:Sub-Agent工作流配置——如何让多个Agent协同工作

来源:OpenClaw官方文档(docs.openclaw.ai)

9.9 Skill的生态系统

Skill市场

OpenClaw有一个活跃的Skill市场(clawhub.ai),开发者可以分享自己开发的Skill。

在Skill市场中,你可以找到:

  • 天气查询Skill
  • 日历管理Skill
  • 邮件处理Skill
  • 数据分析Skill
  • 图像处理Skill
  • 等等

安装社区Skill:

openclaw skills install <skill-url>

Skill开发规范

为了Skill能被社区广泛使用,遵循以下规范:

  1. 清晰的description:准确描述使用场景
  2. 完整的文档:README说明安装和使用方法
  3. 版本号:遵循语义化版本(SemVer)
  4. MIT许可证:允许他人自由使用

9.10 企业级Skill开发

团队协作

在企业环境中,多人协作开发Skill时:

  1. 使用Git管理Skill代码
  2. 建立Code Review流程
  3. 编写自动化测试
  4. 文档同步更新

生产环境检查清单

部署到生产环境前,检查:

  • [ ] API Key已通过环境变量配置
  • [ ] 错误日志已记录到集中式日志系统
  • [ ] 监控指标已配置
  • [ ] 超时和重试机制已设置
  • [ ] 权限控制已配置

9.11 性能调优

缓存策略

对于频繁访问的数据,使用缓存:

配图

import os
import json
import hashlib
from datetime import datetime, timedelta

CACHE_DIR = os.path.expanduser("~/.openclaw/cache")

def get_cached(key, ttl_minutes=60):
"""获取缓存数据"""
cache_file = os.path.join(CACHE_DIR, hashlib.md5(key.encode()).hexdigest() + ".json")

if os.path.exists(cache_file):
with open(cache_file, 'r') as f:
cache = json.load(f)

if datetime.now().timestamp() – cache['timestamp'] < ttl_minutes * 60:
return cache['data']

return None

def set_cache(key, data):
"""设置缓存数据"""
os.makedirs(CACHE_DIR, exist_ok=True)
cache_file = os.path.join(CACHE_DIR, hashlib.md5(key.encode()).hexdigest() + ".json")

with open(cache_file, 'w') as f:
json.dump({
'timestamp': datetime.now().timestamp(),
'data': data
}, f)

异步处理

对于耗时的操作,使用异步处理:

import asyncio
from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=4)

async def fetch_weather_async(cities):
loop = asyncio.get_event_loop()
tasks = [loop.run_in_executor(executor, get_weather, city) for city in cities]
return await asyncio.gather(*tasks)

9.12 安全考虑

输入验证

所有用户输入必须验证:

import re

def validate_city(city):
"""验证城市名称"""
if not city or len(city) > 50:
return False
# 只允许中文、英文和常见符号
if not re.match(r'^[\u4e00-\u9fa5a-zA-Z\s]+$', city):
return False
return True

防止注入

如果Skill执行系统命令,防止注入:

import shlex

def safe_execute(command, args):
"""安全执行命令"""
# 使用shlex.quote转义参数
safe_args = [shlex.quote(str(arg)) for arg in args]
full_command = f"{command} {' '.join(safe_args)}"
# 执行…

9.13 监控与告警

关键指标

监控Skill的关键指标:

  • 调用成功率
  • 平均响应时间
  • 错误类型分布
  • 资源使用率

告警规则

设置告警规则:

  • 成功率低于95%
  • 响应时间超过5秒
  • 错误率超过1%

9.14 持续改进

收集反馈

用户使用Skill后,收集反馈:

  • 是否解决了问题
  • 体验如何
  • 有什么改进建议

迭代优化

根据反馈持续优化:

  1. 分析日志,识别高频错误
  2. 简化复杂流程
  3. 补充遗漏的场景
  4. 优化性能瓶颈

下期预告:Day4 多Agent协作:Sub-Agent工作流配置——如何让多个Agent协同工作

来源:OpenClaw官方文档(docs.openclaw.ai)

9.15 与其他系统集成

Webhook集成

Skill可以调用Webhook与其他系统通信:

import requests

def send_webhook(url, data):
"""发送Webhook通知"""
try:
response = requests.post(
url,
json=data,
headers={'Content-Type': 'application/json'},
timeout=10
)
return response.status_code == 200
except Exception as e:
print(f"Webhook发送失败:{e}")
return False

数据库连接

如果Skill需要操作数据库:

import sqlite3

def query_database(sql, params=None):
"""执行数据库查询"""
db_path = os.path.expanduser("~/.openclaw/skills/my-skill/data.db")
conn = sqlite3.connect(db_path)
cursor = conn.cursor()

if params:
cursor.execute(sql, params)
else:
cursor.execute(sql)

results = cursor.fetchall()
conn.close()
return results

9.16 自然语言处理增强

意图识别

在复杂的Skill中,可能需要识别用户意图:

INTENT_PATTERNS = {
"weather": ["天气", "温度", "冷不冷", "热不热"],
"reminder": ["提醒", "闹钟", "通知"],
"calendar": ["日历", "日程", "会议", "安排"]
}

def recognize_intent(text):
"""识别用户意图"""
for intent, patterns in INTENT_PATTERNS.items():
for pattern in patterns:
if pattern in text:
return intent
return "unknown"

实体提取

提取文本中的关键实体:

import re

def extract_time(text):
"""提取时间表达式"""
patterns = [
(r'(\d+)年(\d+)月(\d+)日', 'date'),
(r'明天', 'tomorrow'),
(r'今天', 'today'),
(r'下周', 'next_week'),
(r'(\d+)点', 'hour')
]

for pattern, entity_type in patterns:
match = re.search(pattern, text)
if match:
return {"type": entity_type, "match": match.group(0)}

return None

9.17 Skill的国际化

如果Skill需要支持多语言:

TRANSLATIONS = {
"zh": {
"city_not_found": "未找到该城市",
"query_failed": "查询失败"
},
"en": {
"city_not_found": "City not found",
"query_failed": "Query failed"
}
}

def t(key, lang="zh"):
"""翻译函数"""
return TRANSLATIONS.get(lang, {}).get(key, key)

9.18 Skill的测试策略

单元测试

为每个函数编写单元测试:

import unittest

class TestWeatherSkill(unittest.TestCase):
def test_city_validation(self):
self.assertTrue(validate_city("北京"))
self.assertFalse(validate_city("北京<script>"))

def test_time_parsing(self):
result = parse_time("明天9点")
self.assertIsNotNone(result)

if __name__ == "__main__":
unittest.main()

集成测试

测试Skill与其他组件的协作:

def test_skill_trigger():
"""测试Skill触发"""
# 模拟用户输入
user_input = "北京天气怎么样"

# 验证Agent是否调用了my-weather Skill
# 检查日志或调用记录
assert was_skill_called("my-weather")

9.19 维护与更新

版本升级

当需要升级Skill时:

  1. 更新版本号
  2. 记录变更日志
  3. 测试兼容性
  4. 通知用户

数据迁移

如果Skill的数据格式需要变更:

def migrate_data():
"""迁移旧数据到新格式"""
old_file = os.path.expanduser("~/.openclaw/old_skill_data.json")
new_file = os.path.expanduser("~/.openclaw/new_skill_data.json")

if os.path.exists(old_file) and not os.path.exists(new_file):
with open(old_file, 'r') as f:
old_data = json.load(f)

new_data = transform_format(old_data)

with open(new_file, 'w') as f:
json.dump(new_data, f)

9.20 资源链接

官方文档

  • OpenClaw Skill开发文档
  • SKILL.md格式规范
  • 示例Skill库

社区资源

  • GitHub上的开源Skill
  • Discord技术讨论
  • 技术博客分享

下期预告:Day4 多Agent协作:Sub-Agent工作流配置——如何让多个Agent协同工作

来源:OpenClaw官方文档(docs.openclaw.ai)

9.21 案例:开发一个新闻聚合Skill

需求背景

用户希望每天早上收到一份个性化的新闻简报。

实现方案

创建一个新闻聚合Skill,功能包括:

  1. 从多个来源获取新闻
  2. 根据用户兴趣过滤
  3. 生成简洁的摘要

目录结构

news-aggregator/
├── SKILL.md
├── scripts/
│ ├── fetch_news.py
│ ├── filter_articles.py
│ └── generate_summary.py
└── references/
└── sources.json

核心脚本

#!/usr/bin/env python3
import requests
import json
from datetime import datetime

class NewsAggregator:
def __init__(self, interests):
self.interests = interests
self.sources = [
{"name": "科技", "url": "https://tech.example.com/rss"},
{"name": "财经", "url": "https://finance.example.com/rss"},
{"name": "体育", "url": "https://sports.example.com/rss"}
]

def fetch_articles(self, source):
"""从指定来源获取文章"""
try:
response = requests.get(source["url"], timeout=10)
articles = self.parse_rss(response.text)
return articles
except Exception as e:
print(f"获取失败:{source['name']} – {e}")
return []

def filter_by_interest(self, articles):
"""根据兴趣过滤文章"""
filtered = []
for article in articles:
for interest in self.interests:
if interest.lower() in article.get("title", "").lower():
filtered.append(article)
break
return filtered

def generate_summary(self, articles):
"""生成新闻摘要"""
if not articles:
return "今日暂无符合条件的新闻"

summary = f"今日为您筛选了{len(articles)}篇精彩文章:\n\n"
for i, article in enumerate(articles[:5], 1):
summary += f"{i}. {article['title']}\n"
summary += f" 来源:{article.get('source', '未知')}\n"
summary += f" 摘要:{article.get('description', '')[:50]}…\n\n"

return summary

def main():
interests = ["AI", "科技", "人工智能"]
aggregator = NewsAggregator(interests)

all_articles = []
for source in aggregator.sources:
articles = aggregator.fetch_articles(source)
all_articles.extend(articles)

filtered = aggregator.filter_by_interest(all_articles)
summary = aggregator.generate_summary(filtered)

print(summary)

if __name__ == "__main__":
main()

9.22 Skill的部署策略

开发环境 vs 生产环境

在开发环境中测试Skill:

openclaw skills list # 查看已安装的Skill
openclaw skills enable my-weather # 启用Skill
openclaw skills disable my-weather # 禁用Skill

在生产环境中:

  • 使用版本控制管理Skill代码
  • 通过配置管理部署
  • 监控Skill运行状态

灰度发布

当更新Skill时,采用灰度发布策略:

  1. 先更新10%的实例
  2. 观察运行状况
  3. 如果稳定,逐步更新到全部实例

回滚机制

如果新版本出现问题,快速回滚:

openclaw skills rollback my-weather # 回滚到上一版本

9.23 Skill的日志分析

日志格式

统一日志格式,便于分析:

{
"timestamp": "2026-05-23T10:00:00Z",
"skill": "my-weather",
"level": "INFO",
"message": "查询天气成功",
"params": {"city": "北京"},
"duration_ms": 150
}

日志分析示例

分析Skill调用成功率:

import re
from collections import defaultdict

def analyze_logs(log_content):
"""分析Skill调用日志"""
success = 0
failure = 0
errors = defaultdict(int)

for line in log_content.split('\n'):
if '"level":"INFO"' in line and '调用成功' in line:
success += 1
elif '"level":"ERROR"' in line:
failure += 1
# 提取错误类型
match = re.search(r'"error":"([^"]+)"', line)
if match:
errors[match.group(1)] += 1

total = success + failure
success_rate = success / total if total > 0 else 0

return {
"total": total,
"success": success,
"failure": failure,
"success_rate": success_rate,
"error_types": errors
}

9.24 性能基准测试

测试脚本

为Skill编写性能测试:

import time
from statistics import mean, stdev

def benchmark_skill(func, runs=100):
"""基准测试"""
durations = []

for _ in range(runs):
start = time.time()
try:
func()
duration = (time.time() – start) * 1000 # 毫秒
durations.append(duration)
except Exception as e:
print(f"执行失败:{e}")

return {
"mean_ms": mean(durations),
"stdev_ms": stdev(durations) if len(durations) > 1 else 0,
"min_ms": min(durations),
"max_ms": max(durations)
}

下期预告:Day4 多Agent协作:Sub-Agent工作流配置——如何让多个Agent协同工作

来源:OpenClaw官方文档(docs.openclaw.ai)

9.25 保持学习

技术发展日新月异,Skill开发也在不断进化。保持学习的几个建议:

  • 定期阅读官方文档更新
  • 关注社区的最新分享
  • 参与开源Skill项目贡献
  • 与其他开发者交流经验

只要持续实践,就能不断提升Skill开发能力。