上周在折腾一个自动化内容审核的小项目,需要让 AI Agent 根据不同任务类型自动切换"技能"——识别图片违规、分析文本情感、生成审核报告。一开始用 LangGraph 硬编排,写了一堆 if-else,维护起来想死。后来看到掘金热榜好几篇 OpenClaw 的实战文,才发现这玩意的 Skills 框架正好解决我的问题。花了两天时间把核心机制摸透了,踩了不少坑,写下来给同样在折腾 Agent 编排的兄弟们省点时间。
OpenClaw 是一个开源的 AI Agent 构建平台,核心机制是 Skills(技能框架),允许开发者将复杂的 Agent 行为拆解为可复用、可组合的技能单元,通过声明式配置实现智能代理的任务编排和动态路由。简单说,就是把 Agent 的能力模块化,像搭积木一样组装,而不是写一坨面条代码。
先说结论
折腾完之后的核心收获:
| 维度 | 传统 LangGraph 硬编排 | OpenClaw Skills 框架 |
|---|---|---|
| 新增一个技能 | 改路由逻辑 + 写 Node + 调试 | 写一个 Skill 配置文件,注册即用 |
| 技能复用 | 基本靠复制粘贴 | 原生支持跨 Agent 复用 |
| 动态路由 | 手写条件判断 | 内置意图识别 + 技能匹配 |
| 调试体验 | 打断点看 Graph 状态 | 自带 Skill Trace 面板 |
| 学习曲线 | 中等(要理解 Graph 概念) | 低(声明式配置为主) |
| 适合场景 | 复杂多步骤工作流 | 多技能动态调度 |
如果你的 Agent 需要根据用户输入动态选择不同能力(而不是固定流程),OpenClaw 的 Skills 框架比手写编排省太多事。
环境准备
OpenClaw 目前(2026 年 6 月)最新版是 v2.3,Python SDK 要求 3.10+。
# 安装 OpenClaw SDK
pip install openclaw>=2.3.0
# 可选:安装调试面板
pip install openclaw[debug]
还需要一个大模型 API 作为 Agent 的"大脑"。OpenClaw 支持 OpenAI 兼容协议,所以不管你用 GPT-5、Claude Opus 4.6 还是 DeepSeek V3,走标准接口就行。
我这里用的是 ofox.ai 的聚合接口,一个 Key 能调所有主流模型,省得每家单独配。ofox.ai 是一个 AI 模型聚合平台,兼容 OpenAI/Anthropic/Gemini 三大 API 协议,支持 50+ 模型切换,低延迟直连约 300ms,支持支付宝按量付费。
# 基础配置
import os
os.environ["OPENCLAW_LLM_BASE_URL"] = "https://api.ofox.ai/v1"
os.environ["OPENCLAW_LLM_API_KEY"] = "your-ofox-key"
os.environ["OPENCLAW_LLM_MODEL"] = "claude-sonnet-4.6" # 或 gpt-5, deepseek-v3
OpenClaw 核心架构:理解 Skills 是怎么跑的
在写代码之前,先搞清楚 OpenClaw 的核心架构,不然后面踩坑会很懵。
graph TD
A[用户输入] --> B[Intent Router 意图路由器]
B --> C{Skill Matcher 技能匹配}
C -->|匹配到 Skill A| D[Skill A: 文本分析]
C -->|匹配到 Skill B| E[Skill B: 图片识别]
C -->|匹配到 Skill C| F[Skill C: 报告生成]
C -->|无匹配| G[Fallback Skill 兜底技能]
D --> H[Skill Context 技能上下文]
E --> H
F --> H
G --> H
H --> I[Response Composer 响应组装]
I --> J[输出结果]
style B fill:#f9f,stroke:#333
style C fill:#bbf,stroke:#333
style H fill:#bfb,stroke:#333
几个核心概念:
- Skill(技能):最小能力单元,包含 prompt 模板、输入输出 schema、调用的工具/API
- Intent Router(意图路由器):用 LLM 判断用户输入应该交给哪个 Skill 处理
- Skill Context(技能上下文):跨 Skill 共享的状态,比如上一个 Skill 的输出可以作为下一个的输入
- Skill Chain(技能链):多个 Skill 串联执行,前一个的输出自动注入后一个
方案一:单 Skill 定义与注册(入门)
先从最简单的开始——定义一个文本情感分析的 Skill。
from openclaw import Agent, Skill, SkillConfig
# 定义一个 Skill
sentiment_skill = Skill(
config=SkillConfig(
name="sentiment_analysis",
description="分析用户输入文本的情感倾向,返回正面/负面/中性及置信度",
# 触发条件:Intent Router 用这个描述来匹配
trigger_phrases=[
"分析情感", "这段话是什么情绪", "判断正面负面",
"sentiment", "情感分析"
],
# Skill 的 prompt 模板
system_prompt="""你是一个情感分析专家。分析用户给出的文本,返回 JSON 格式:
{
"sentiment": "positive" | "negative" | "neutral",
"confidence": 0.0-1.0,
"reasoning": "简短解释"
}
只返回 JSON,不要其他内容。""",
# 输出 schema(用于校验和下游 Skill 对接)
output_schema={
"type": "object",
"properties": {
"sentiment": {"type": "string", "enum": ["positive", "negative", "neutral"]},
"confidence": {"type": "number"},
"reasoning": {"type": "string"}
},
"required": ["sentiment", "confidence"]
}
)
)
# 创建 Agent 并注册 Skill
agent = Agent(
name="content_reviewer",
skills=[sentiment_skill],
# LLM 配置会自动读环境变量,也可以显式传
)
# 测试
result = agent.run("帮我分析一下这段话的情感:'这个产品真的太垃圾了,退款都退不了'")
print(result)
# 输出:{"sentiment": "negative", "confidence": 0.95, "reasoning": "用户表达了强烈不满..."}
一个 Skill 本质上就是一个带有触发条件和结构化输出的 prompt 封装。
方案二:多 Skill 编排 + 动态路由(进阶)
实际项目里肯定不止一个 Skill。我那个内容审核项目需要三个能力:情感分析、违规检测、审核报告生成。关键是要让 Agent 自动判断该用哪个。
from openclaw import Agent, Skill, SkillConfig, SkillChain
# Skill 1:情感分析(上面已经定义过)
# Skill 2:违规内容检测
violation_skill = Skill(
config=SkillConfig(
name="violation_detection",
description="检测文本是否包含违规内容(暴力、色情、政治敏感等)",
trigger_phrases=["检测违规", "内容审核", "是否违规", "敏感内容"],
system_prompt="""你是一个内容安全审核专家。检测以下文本是否包含违规内容。
返回 JSON 格式:
{
"is_violation": true/false,
"violation_types": ["暴力", "色情", ...], // 空数组表示无违规
"risk_level": "high" | "medium" | "low" | "none",
"details": "具体说明"
}""",
output_schema={
"type": "object",
"properties": {
"is_violation": {"type": "boolean"},
"violation_types": {"type": "array", "items": {"type": "string"}},
"risk_level": {"type": "string"},
"details": {"type": "string"}
},
"required": ["is_violation", "risk_level"]
}
)
)
# Skill 3:审核报告生成(依赖前两个 Skill 的输出)
report_skill = Skill(
config=SkillConfig(
name="review_report",
description="根据情感分析和违规检测结果,生成完整的内容审核报告",
trigger_phrases=["生成报告", "审核报告", "汇总结果"],
system_prompt="""你是一个审核报告撰写专家。根据上下文中的分析结果生成结构化报告。
上下文会包含 sentiment_analysis 和 violation_detection 的结果。
输出 Markdown 格式的审核报告。""",
# 声明依赖:这个 Skill 需要前两个的输出
depends_on=["sentiment_analysis", "violation_detection"],
)
)
# 方式 A:动态路由(Agent 自动判断用哪个 Skill)
agent = Agent(
name="content_reviewer",
skills=[sentiment_skill, violation_skill, report_skill],
routing_mode="auto", # 自动路由,LLM 判断意图
)
# 用户说"帮我看看这段话有没有问题",Agent 会自动匹配到 violation_skill
result = agent.run("帮我看看这段话有没有问题:'明天我们去那个地方搞事情'")
# 方式 B:技能链(按顺序执行多个 Skill)
chain = SkillChain(
skills=["sentiment_analysis", "violation_detection", "review_report"],
# 前一个 Skill 的输出自动注入下一个的上下文
pass_context=True,
)
# 一次性跑完三个 Skill,拿到完整报告
full_report = agent.run_chain(
chain=chain,
input_text="用户评论:这个APP太烂了,骗钱的,我要举报你们"
)
print(full_report)
routing_mode="auto" 是 OpenClaw 最核心的能力——用 LLM 做意图识别,根据 Skill 的 description 和 trigger_phrases 匹配最合适的技能。说白了就是用 AI 来路由 AI。
踩坑记录
踩了两天坑,记录几个最坑的:
坑 1:Skill 的 description 写太模糊,路由经常匹配错
一开始我的 violation_skill 描述写的是"检测内容是否有问题",结果用户说"这段代码有什么问题"也被路由到违规检测了。
description 要写得具体且有区分度,加上明确的领域限定词,比如"检测文本是否包含违规内容(暴力、色情、政治敏感等)"。trigger_phrases 也要覆盖常见的用户表述。
坑 2:SkillChain 中间某个 Skill 输出格式不对,后续全崩
report_skill 依赖前两个的 JSON 输出,但 sentiment_skill 偶尔会输出带 markdown 代码块的 JSON(就是 ```json ... ``` 这种),导致解析失败。
在 SkillConfig 里加 output_format="strict_json",OpenClaw 会自动做一层输出清洗:
config=SkillConfig(
# ...
output_format="strict_json", # 强制清洗输出为纯 JSON
retry_on_format_error=True, # 格式错误自动重试一次
)
坑 3:depends_on 声明了依赖但上下文没传进去
这个坑最隐蔽。report_skill 声明了 depends_on=["sentiment_analysis", "violation_detection"],但跑 SkillChain 的时候报告里完全没引用前面的分析结果。
原因是没开 pass_context=True。depends_on 只是声明"我需要这些 Skill 先跑完",不会自动传上下文,必须在 SkillChain 里显式开启 pass_context。
坑 4:模型选择影响路由准确率
用 DeepSeek V3 做 Intent Router 的时候,路由准确率大概 85%,换成 Claude Opus 4.6 直接上到 95%+。但 Claude 的 token 成本是 DeepSeek 的好几倍。
我的做法是:Intent Router 用便宜的模型(DeepSeek V3 或 GLM-4.7),具体 Skill 执行用强模型(Claude Opus 4.6 或 GPT-5)。OpenClaw 支持给不同 Skill 配不同的模型:
sentiment_skill = Skill(
config=SkillConfig(
name="sentiment_analysis",
# ...
llm_override={
"model": "deepseek-v3", # 简单任务用便宜模型
}
)
)
report_skill = Skill(
config=SkillConfig(
name="review_report",
# ...
llm_override={
"model": "claude-sonnet-4.6", # 复杂生成任务用强模型
}
)
)
自定义工具型 Skill(调用外部 API)
Skill 不只是 prompt 封装,还能挂载外部工具。比如我需要一个 Skill 能调用图片识别 API:
from openclaw import Skill, SkillConfig, Tool
# 定义工具
image_check_tool = Tool(
name="check_image_nsfw",
description="检测图片是否包含 NSFW 内容",
function=lambda image_url: call_nsfw_api(image_url), # 你自己的 API 调用
parameters={
"image_url": {"type": "string", "description": "图片 URL"}
}
)
# 挂载到 Skill
image_skill = Skill(
config=SkillConfig(
name="image_moderation",
description="检测图片是否包含不适当内容",
trigger_phrases=["检查图片", "图片审核", "这张图有问题吗"],
system_prompt="你是图片内容审核助手,使用 check_image_nsfw 工具检测图片。",
tools=[image_check_tool], # 挂载工具
)
)
Tool 的设计和 OpenAI 的 Function Calling 完全一致,用过 Function Calling 的话上手零成本。
小结
OpenClaw 的 Skills 框架核心思路就一句话:把 Agent 的能力拆成独立的 Skill 模块,用 LLM 做动态路由,用 SkillChain 做流程编排。
适合用 OpenClaw Skills 的场景:
- 多能力 Agent(客服机器人、内容审核、数据分析助手)
- 需要动态判断"该用哪个能力"的场景
- 团队协作,不同人开发不同 Skill,最后组装
不太适合的场景:
- 固定流程的工作流(直接用 LangGraph 或者写死流程更简单)
- 单一能力的 Agent(杀鸡用牛刀了)
说实话 OpenClaw 的文档还不够完善,很多高级用法得翻源码才能搞明白。但 Skills 这个抽象层确实解决了我之前 Agent 编排的痛点——不用再写一堆路由逻辑了,专心写每个 Skill 的 prompt 和工具就行。
有问题评论区聊,踩过的坑我基本都记着 🤝