在AI Agent飞速发展的当下,CoPaw、OpenClaw等平台已沉淀了大量实用Skill(技能)——小到搜索推特热点、读取B站字幕,大到公众号全流程写作、多平台内容聚合,这些Skill本质上是精心设计的Prompt文件(SKILL.md),是扩展Agent能力的核心。
但一个尴尬的现实是:这些强大的Skill,大多只有开发者和技术用户能熟练使用。普通用户想上手,往往要面对复杂的自然语言指令、繁琐的参数记忆,学习成本极高。如何打破这道壁垒,让Skill真正走进普通用户,提升CAW平台的易用性与定制化效率?今天找到开源工程github.com/aitoearn/co… UI Generator的功能,用AI自动生成可视化界面,让Skill操作从「命令行」变成「填表点击」,一下子解决了我的痛点。
一、痛点直击:强大的Skill,为何普通用户用不了?
CoPaw、OpenClaw平台的Skill生态越来越丰富,但「能力强大」与「易用性差」的矛盾日益突出,核心痛点集中在3点:
1. 自然语言指令的记忆负担
使用Skill需要记住繁琐且不统一的自然语言指令,以「agent-reach」技能为例,用户需手动输入类似这样的指令:
搜索推特上关于 AI 的讨论,返回 10 条
读取这条推特 https://twitter.com/xxx/status/123456
搜索小红书 "年终总结" 的笔记,关键词过滤
用 Exa 搜索 "Claude 最新进展" 的网页
这些指令语法不统一、参数形式各异,即便技术用户也需频繁查阅文档,普通用户更是望而却步。
2. 平台能力的认知门槛
一个Skill往往支持十多个平台(Twitter、YouTube、B站、小红书等),每个平台又有多个操作。用户使用前,必须先摸清「支持哪些平台→每个平台能做什么→对应指令格式」,这种「先学习、再使用」的模式,严重阻碍了Skill的普及。
3. 核心矛盾:Skill生态与用户群体脱节
无论是CoPaw还是OpenClaw,Skill的主要使用者仍是开发者和技术用户,普通用户难以触及。如何让普通用户无需掌握技术,也能轻松调用这些强大的AI技能,成为提升平台易用性的关键。
二、核心方案:让AI读懂Skill,自动生成可视化界面
Skill UI Generator的核心思路非常简单:既然Skill是用自然语言描述的(SKILL.md),那我们就用AI读懂它,自动生成可视化操作表单,彻底替代繁琐的命令行指令。
从「命令行」到「填表点击」,只需3步就能实现:
1. 理解:LLM提取结构化信息
让大语言模型(LLM)读取SKILL.md文件,自动提取其中的「平台、操作、参数」等结构化信息——比如某个Skill支持哪些平台、每个平台有哪些操作、每个操作需要填写哪些参数。
2. 生成:输出标准界面定义文件
LLM将提取的信息,转化为标准的「ui-schema.json」文件(界面定义文件),这个文件会明确表单的布局、组件类型(输入框、下拉框、开关等)、参数要求等。
3. 渲染:动态生成可视化表单
前端根据ui-schema.json,自动渲染出可视化表单。用户只需填写参数、点击「执行」,系统就会自动拼装成自然语言指令,发送给Agent完成任务——全程无需输入任何命令。
系统架构与执行流程
整个方案的架构清晰易懂,以CoPaw平台为例:
三、普通用户用法:三步开启可视化操作,零命令门槛
无论你是完全不懂技术的普通用户,还是不想记命令的技术用户,只需2步,就能轻松使用任意Skill,以CoPaw平台为例:
Step 1:聊天下载和安装
打开CoPaw控制台,进入「聊天」页面,找到你想使用的Skill(如bilibili-subtitle-download-skill),然后输入“下载安装 skill: github.com/DavinciEvan…, 然后使用 Skill UI Generator生成skill ui页面”就完成安装。安装成功如下(如果左侧没有显示,刷新下页面)
Step 2:点击使用
点击技能UI操控区对应skill的菜单,显示该skill生成可视化界面。按照界面进行相关的操作就可以完成对应工作,无需记任何命令,填完表单点击「执行」,系统会自动完成后续操作。
另外:控制显示和已安装的skill ui生成
从侧边栏“技能”菜单进入技能该列表页,找到安装的bilibili-subtitle-download-skill,点击它显示如图的控制“显示UI”,关闭它,对应的技能UI操控区就不显示该技能。
如果有skill没有生成ui ,第一次打开“显示UI”开关会自动生成UI操控页面,并在技能UI操控区显示该skill菜单;
四、CoPaw平台详细技术方案(含核心代码片段)
Skill UI Generator的核心实现的基于CoPaw平台开发,技术栈为Python(后端)+ React(前端),核心分为5个模块,以下是关键实现细节和代码片段。
4.1 UI Schema 结构设计(核心基础)
Schema采用「技能→平台→操作→参数」四层嵌套结构,是连接LLM与前端渲染的核心,格式统一且平台中立,示例如下:
{
"skill_id": "agent-reach",
"display_name": "多平台内容获取",
"description": "支持 13+ 平台的内容搜索、读取与互动",
"platforms": [
{
"id": "twitter",
"label": "Twitter/X",
"icon": "🐦",
"description": "搜索和读取推文",
"operations": [
{
"id": "search_tweets",
"label": "搜索推文",
"description": "搜索匹配关键词的推文",
"parameters": [
{
"name": "query",
"label": "搜索关键词",
"type": "text",
"required": true,
"placeholder": "输入搜索内容"
},
{
"name": "count",
"label": "返回数量",
"type": "number",
"required": false,
"default": "10"
}
],
"instruction_template": "搜索 Twitter,关键词 "{{query}}",返回 {{count}} 条结果"
}
]
}
]
}
参数支持6种类型,对应不同的前端组件,适配各类使用场景:
| 类型 | 渲染组件 | 适用场景 |
|---|---|---|
| text | 单行输入框 | 关键词、标题 |
| textarea | 多行文本框 | 长文本、文章内容 |
| number | 数字输入 | 数量、轮数、分页 |
| select | 下拉选择 | 类型、主题、语言 |
| toggle | 开关 | 布尔选项、是否开启 |
| url | URL输入框 | 链接地址 |
4.2 后端核心API设计(FastAPI)
后端基于FastAPI开发,提供4个核心接口,覆盖「技能查询、Schema生成、指令执行」全流程:
GET /skill-ui/skills → 列出所有已安装且有SKILL.md的技能
GET /skill-ui/{skill_id}/schema → 返回已缓存的ui-schema.json
POST /skill-ui/{skill_id}/generate-schema → LLM读取SKILL.md生成schema
POST /skill-ui/{skill_id}/execute → 执行技能操作(渲染模板→发给Agent)
技能查找优先级为「活跃>自定义>内置」,支持用户自定义技能覆盖内置技能,核心代码如下:
# src/copaw/app/routers/skill_ui.py
def _get_skill_dir(skill_id: str) -> Path | None:
"""技能目录查找,优先级:活跃 > 自定义 > 内置"""
# 1. 活跃技能(已启用)
active_skill_dir = ACTIVE_SKILLS_DIR / skill_id
if active_skill_dir.exists() and (active_skill_dir / "SKILL.md").exists():
return active_skill_dir
# 2. 用户自定义技能
customized_skill_dir = CUSTOMIZED_SKILLS_DIR / skill_id
if customized_skill_dir.exists() and (customized_skill_dir / "SKILL.md").exists():
return customized_skill_dir
# 3. 平台内置技能
builtin_skill_dir = _BUILTIN_SKILLS_DIR / skill_id
if builtin_skill_dir.exists() and (builtin_skill_dir / "SKILL.md").exists():
return builtin_skill_dir
return None
4.3 LLM Schema生成核心实现(最关键模块)
这是整个方案的核心:通过精心设计的System Prompt,驱动LLM从SKILL.md中提取结构化信息,生成标准ui-schema.json,核心代码如下:
@router.post("/{skill_id}/generate-schema")
async def generate_schema(skill_id: str, force: bool = False) -> dict:
"""从 SKILL.md 生成 UI Schema"""
# 读取 SKILL.md 文件内容
skill_content = skill_md.read_text(encoding="utf-8")
# 构造LLM对话,指定生成规则
messages = [
Msg(name="system", role="system",
content=_SCHEMA_GENERATION_SYSTEM_PROMPT),
Msg(name="user", role="user",
content=f"请为以下 SKILL.md 生成 ui-schema.json:\n\n{skill_content}"),
]
# 调用配置的LLM模型(支持GPT-4、Claude、Gemini等)
model, formatter = create_model_and_formatter()
formatted = await formatter.format(messages)
response_gen = await model(formatted)
# 收集LLM流式响应,提取纯JSON内容
last_text = ""
async for chunk in response_gen:
for block in getattr(chunk, "content", []):
if isinstance(block, dict) and block.get("type") == "text":
last_text = block.get("text", "")
# 处理LLM可能包裹的markdown格式,提取纯JSON
raw_text = last_text.strip()
if raw_text.startswith("```"):
lines = raw_text.split("\n")
inner = lines[1:-1] if lines[-1].strip() == "```" else lines[1:]
raw_text = "\n".join(inner).strip()
# 解析JSON并持久化保存
schema = json.loads(raw_text)
with open(ui_schema_file, "w", encoding="utf-8") as f:
json.dump(schema, f, ensure_ascii=False, indent=2)
return schema
其中,System Prompt的设计至关重要,核心约束两点:输出纯JSON(无多余解释)、用户可见文本用中文,确保可机器解析和中文用户友好,Prompt核心内容如下:
You are a UI Schema Generator. Your job is to read a SKILL.md file that describes
an AI agent skill, and extract a structured ui-schema.json that allows a frontend
to render visual operation panels — replacing natural language commands with forms
and buttons that ordinary users can understand.
Output ONLY valid JSON. No markdown fences, no explanation.
Rules:
- All user-facing text MUST be in Chinese
- skill_id, platform id, operation id, parameter name use English
- "type" must be one of: text, textarea, number, select, toggle, url
- "instruction_template" must produce valid natural language commands
- Extract ALL platforms described in the SKILL.md
- Each platform should have 1-4 of its most useful operations
4.4 模板渲染与Agent执行
用户填写参数后,系统通过模板渲染引擎,将Schema中的「instruction_template」占位符替换为实际参数,生成自然语言指令,核心代码如下:
def _render_template(template: str, params: dict[str, Any]) -> str:
"""将 {{param_name}} 占位符替换为实际参数值,移除未填充的可选参数"""
result = template
for key, value in params.items():
if value is not None and value != "" and value is not False:
result = result.replace(f"{{{{{key}}}}}", str(value))
# 移除未填充的占位符(含前缀空格,避免残留)
result = re.sub(r"\s*{{[^}]+}}", "", result)
return result.strip()
渲染后的指令,通过Agent Runner的流式接口发送给Agent执行,核心代码片段如下:
@router.post("/{skill_id}/execute")
async def execute_operation(skill_id: str, body: ExecuteRequest, request: Request) -> ExecuteResponse:
# 从Schema中查找对应操作模板
platform = next((p for p in schema["platforms"] if p["id"] == body.platform_id), None)
operation = next((op for op in platform["operations"] if op["id"] == body.operation_id), None)
# 渲染自然语言指令
template = operation.get("instruction_template", "")
instruction = _render_template(template, body.parameters)
# 构造Agent请求,发送指令并获取流式结果
req = {
"input": [{"role": "user", "content": [{"type": "text", "text": instruction}]}},
"session_id": body.session_id,
"user_id": body.user_id,
}
result_parts = []
async for event in runner.stream_query(req):
if getattr(event, "object", None) == "message" and getattr(event, "status", None) == RunStatus.Completed:
for c in getattr(event, "content", []):
if "text" in str(getattr(c, "type", "")).lower():
result_parts.append(getattr(c, "text", ""))
return ExecuteResponse(instruction=instruction, result="".join(result_parts))
4.5 前端动态表单渲染(React + Ant Design)
前端无需关注具体Skill细节,只需根据ui-schema.json,按参数类型动态渲染对应组件,核心代码如下:
// console/src/pages/Content/SkillUi/index.tsx
function ParamField({ param }: { param: ParameterSchema }) {
switch (param.type) {
case "textarea":
return (
<Form.Item name={param.name} label={param.label} rules={param.required ? [{ required: true }] : []}>
<TextArea rows={4} placeholder={param.placeholder} />
</Form.Item>
);
case "select":
return (
<Form.Item name={param.name} label={param.label}>
<Select placeholder={param.placeholder}>
{param.options?.map(opt => (
<Select.Option key={opt} value={opt}>{opt}</Select.Option>
))}
</Select>
</Form.Item>
);
case "toggle":
return (<Form.Item name={param.name} label={param.label} valuePropName="checked">
<Switch />
</Form.Item>
);
default: // text / number / url
return (
<Form.Item name={param.name} label={param.label} rules={param.required ? [{ required: true }] : []}><Input type={param.type === "number" ? "number" : "text"} placeholder={param.placeholder} />
</Form.Item>
);
}
}
五、OpenClaw平台移植可行性分析
很多同学会问:这套方案能用到OpenClaw平台吗?答案是:完全可行!虽然CoPaw和OpenClaw是两套独立平台,技术栈不同,但核心思路和关键格式可完全复用。
5.1 两个平台的核心差异
两套平台技术栈不同,无法直接共用代码,但Skill格式完全一致,具体差异如下:
| 维度 | CoPaw | OpenClaw |
|---|---|---|
| 主语言 | Python | TypeScript / Node.js |
| Agent框架 | AgentScope + AgentScope-Runtime | pi-agent SDK |
| 后端框架 | FastAPI | Node.js HTTP |
| 前端 | React(Web Console) | 无内置Web Console |
| Skill格式 | SKILL.md(自然语言描述) | SKILL.md(相同格式) |
5.2 移植核心思路与最小可行路径
由于两套平台的SKILL.md格式完全一致,核心思路(LLM生成Schema→渲染表单→执行指令)可直接复用,只需用TypeScript重新实现对应模块,移植对应关系如下:
CoPaw 实现(Python) 对应 OpenClaw 移植(TypeScript)
───────────────────── ────────────────────────────────
skill_ui.py (FastAPI) → skill-ui.ts (Express / Fastify)
_render_template() → renderTemplate()(逻辑完全相同)
LLM 调用 (AgentScope) → LLM 调用 (pi-agent SDK 或直接调OpenAI API)
React 表单渲染 → React / Vue 表单渲染(schema结构不变)
ui-schema.json → 完全复用,格式无需改动
如果想快速验证功能,最小可行路径只需3步:
- 复用Schema:将CoPaw生成的ui-schema.json直接放入OpenClaw的Skill目录,零成本复用;
- 实现模板渲染:用TypeScript写一个简单的渲染函数(约20行代码),逻辑与Python版本完全一致;
- 对接Agent执行:将渲染后的指令通过pi-agent SDK的接口发送给Agent,完成执行。
六、总结:让AI技能真正走进普通用户
Skill UI Generator解决的核心问题,是AI Agent平台「能力强大但门槛高」的长期矛盾。它没有改变Skill的核心能力,而是通过「AI生成可视化界面」的方式,搭建了一座连接「AI技能」与「普通用户」的桥梁。
对比传统使用方式,它的优势一目了然:
| 传统方式 | Skill UI Generator |
|---|---|
| 记忆繁琐的自然语言指令 | 填表点击,零记忆成本 |
| 查阅文档才能使用 | 界面即文档,即开即用 |
| 技术用户专属 | 普通用户也能轻松上手 |
| 手动拼接命令参数 | 系统自动渲染指令 |
| 新技能需单独学习 | 新技能自动生成UI,无需学习 |
更重要的是,这套方案的扩展成本几乎为零:只要一个Skill有合规的SKILL.md,就能一键生成可视化界面。无论是CoPaw还是OpenClaw,只要完成对应移植,就能让平台的Skill生态真正落地,提升易用性与定制化效率。
让技能操作从「命令行」变成「填表点击」,这不只是UI层面的改进,更是AI Agent平台走向大众化的必经之路。