尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

OpenClaw技能部署核心:YAML驱动的Agent运行时解析与避坑指南

OpenClaw技能部署核心:YAML驱动的Agent运行时解析与避坑指南
📅 发布时间:2026/6/24 21:42:27

1. OpenClaw不是“另一个AI工具”,它是Agent时代的YAML操作系统

最近两周,朋友圈、技术群、甚至非技术向的效率社群里,“OpenClaw”三个字出现频率陡增。有人晒出用它三分钟接入飞书审批流,有人靠一个ppt skill自动生成周报PPT,还有人把yolo数据集定义了类别数量还要在yaml文件里面改吗这种硬核问题直接扔进ClawHub仓库,两小时就收到带注释的修复版YAML。但很快,一批人开始困惑:装完OpenClaw,敲openclaw --version能跑,可openclaw run skill:weather却报错;有人照着教程拉下Docker镜像,docker run -p 8080:8080 openclaw启动成功,但浏览器打不开控制台——页面空白,控制台只有一行undefined reference to 'yaml'。

这根本不是安装失败,而是技能(Skill)认知错位。OpenClaw本身不提供任何功能,它是一套运行时环境,一个YAML驱动的Agent调度内核。它的全部价值,取决于你装对、配准、调通的Skill。就像Linux发行版不等于Linux内核,Ubuntu的价值不在/boot/vmlinuz,而在apt源里那上万个经过签名验证、版本兼容、依赖清晰的deb包。OpenClaw的“真・效率神器”属性,90%由Skill生态决定,剩下10%才是CLI命令和Docker容器的封装。我上周帮一位做智能硬件的客户部署OpenClaw,他们团队花两天时间反复重装Docker、升级glibc、排查端口冲突,最后发现核心问题只是superpowers skill的YAML里少了一个缩进——timeout_ms:字段被写成了timeout_ms :,多了一个空格。YAML解析器静默失败,OpenClaw启动时跳过该Skill,但日志里只有一行[WARN] Skill 'superpowers' load skipped,没人注意。这就是为什么标题强调“装对Skill才是真・效率神器”:OpenClaw是引擎,Skill是燃料,而YAML语法就是点火开关。你手里的mobilenetv2 yaml文件、comet skill、frontend-design skill,每一个都是可执行的、带上下文感知的微型Agent,它们通过YAML声明式地定义输入、输出、依赖、超时、重试策略——这不是配置文件,这是Agent的“基因序列”。

提示:所有热词中,“yaml”出现频次远超“openclaw”本身。这不是偶然。OpenClaw的底层解析器直接调用libyaml C库,undefined reference to 'yaml'错误本质是链接时找不到libyaml.so符号,而非Python的PyYAML包缺失。这意味着你的Skill YAML文件哪怕语法100%正确,只要OpenClaw二进制未正确链接libyaml,整个Skill系统就瘫痪。理解这一点,是避开90%“OpenClaw为什么会延迟”“启动关闭OpenClaw失败”类问题的第一步。

2. Skill的本质:YAML定义的、可热加载的微型Agent服务

很多人把Skill简单理解为“插件”或“脚本”,这是最危险的认知偏差。在OpenClaw架构里,Skill是一个自治的、有状态的、可独立部署的微服务单元,其生命周期完全由YAML元数据驱动。以workbuddy skill为例,它的YAML文件(假设名为workbuddy.yaml)绝不是一段配置,而是一份完整的Service Contract:

# workbuddy.yaml name: "workbuddy" version: "1.3.2" description: "自动同步Jira任务到Notion看板,支持每日摘要邮件" author: "ClawHub Team" license: "MIT" # 这是Skill的“入口协议”,定义它如何被调用 trigger: type: "webhook" # 支持 webhook / cron / event / manual 四种触发方式 endpoint: "/jira-sync" # 对外暴露的HTTP路径 method: "POST" auth: "bearer" # 认证方式,OpenClaw自动注入token校验逻辑 # 这是Skill的“能力契约”,定义它能做什么 capabilities: - "jira:read:issues" - "notion:write:pages" - "email:send:digest" # 这是Skill的“资源契约”,定义它需要什么才能跑起来 resources: cpu: "500m" # 请求CPU资源 memory: "512Mi" # 请求内存 volumes: - name: "jira-config" mountPath: "/etc/claw/skills/workbuddy/jira.yaml" readOnly: true # 这是Skill的“行为契约”,定义它怎么应对异常 lifecycle: timeout_ms: 30000 retry: max_attempts: 3 backoff_factor: 2.0 jitter: true

看到这里,你应该明白为什么openclaw install skill:workbuddy命令背后是如此复杂的流程:OpenClaw不是复制一个py文件,而是:

  1. 下载workbuddy.yaml及其所有依赖文件(如jira.yaml配置模板、notion_schema.json结构定义);
  2. 校验YAML语法(用libyaml C API,非Python PyYAML);
  3. 解析resources段,向宿主机申请对应CPU/Memory配额(Docker模式下即--cpus和--memory参数);
  4. 挂载volumes指定的配置卷;
  5. 启动一个隔离的容器(或进程),注入trigger.endpoint对应的Web服务器;
  6. 将该Skill的trigger.endpoint注册到OpenClaw内部的路由表,对外暴露/skills/workbuddy/jira-sync。

这个过程,和Kubernetes部署一个Deployment几乎一致。区别在于,K8s的YAML描述的是基础设施,而OpenClaw的YAML描述的是业务逻辑的执行契约。这也是为什么continue (yaml 配置)成为高频热词——当你想让Skill在失败后继续执行下一个步骤,不是写if-else代码,而是修改YAML里的lifecycle.retry字段。nature skill之所以能“模拟自然语言对话流”,不是因为它用了更高级的LLM,而是它的YAML里定义了state_machine字段,将对话拆解为intent_recognition → context_retrieval → response_generation → sentiment_adjustment四个状态节点,每个节点都关联一个独立的子Skill。YAML在这里,是比代码更高级的抽象层。

注意:impeccable skill的流行,恰恰印证了这一设计哲学。它的YAML文件里没有一行业务代码,只有极致的lifecycle配置:timeout_ms: 100(100毫秒超时)、retry.max_attempts: 0(绝不重试)、resources.cpu: "100m"(极低资源占用)。它存在的唯一目的,就是作为“健康检查探针”,被其他Skill调用以验证OpenClaw运行时是否存活。一个纯YAML定义的、零代码的“心跳服务”,这就是OpenClaw对Skill的终极诠释。

3. 装对Skill的三大生死线:YAML解析、依赖注入、环境隔离

“装对Skill”不是指openclaw install命令执行成功,而是指Skill在OpenClaw运行时中可加载、可触发、可稳定执行。这背后横亘着三条技术生死线,任何一条断裂,Skill就会变成“幽灵插件”——列表里能看到,但永远无法调用。

3.1 生死线一:YAML解析必须通过libyaml C API,而非Python PyYAML

这是所有undefined reference to 'yaml'错误的根源,也是OpenClaw与传统Python工具链的根本分野。OpenClaw的二进制是用Rust编写的,其YAML解析模块直接绑定系统级的libyaml C库(libyaml-0.so.2)。这意味着:

  • 你的系统必须预装libyaml开发包(如Ubuntu的libyaml-dev,CentOS的libyaml-devel);
  • openclaw二进制在编译时必须链接-lyaml,否则运行时找不到yaml_parser_initialize等符号;
  • 即使你用pip install pyyaml装了Python版YAML库,对OpenClaw完全无效。

我实测过一个典型场景:在群晖DS920+上,Docker默认基础镜像是Alpine Linux,而Alpine的apk add yaml安装的是musl libc版本的libyaml,与OpenClaw编译时链接的glibc版本不兼容。结果就是openclaw list skills能显示所有Skill,但openclaw run skill:weather必报undefined reference to 'yaml_parser_initialize'。解决方案不是重装PyYAML,而是换用Debian系的基础镜像(如debian:bookworm-slim),并确保apt-get install libyaml-dev在构建阶段执行。

验证方法极其简单,无需启动OpenClaw:

# 检查openclaw二进制链接了哪些库 ldd $(which openclaw) | grep yaml # 正常输出应为:libyaml-0.so.2 => /usr/lib/x86_64-linux-gnu/libyaml-0.so.2 (0x00007f...) # 如果输出为空或显示"not found",说明链接失败 # 检查系统是否存在libyaml-0.so.2 find /usr -name "libyaml-0.so.*" 2>/dev/null # 正常应返回类似:/usr/lib/x86_64-linux-gnu/libyaml-0.so.2

3.2 生死线二:Skill依赖必须通过YAML显式声明,禁止隐式全局依赖

很多用户尝试手动安装codex skill时,会先pip install codex,再openclaw install skill:codex,结果失败。这是因为Codex Skill的YAML文件里明确写了:

dependencies: - "python:3.11" - "package:codex==2.4.0" - "system:libssl1.1"

OpenClaw在安装时,会严格按此声明去拉取对应Python环境、安装codex包、检查libssl版本。如果你提前全局pip install codex,反而可能造成版本冲突——比如你装了codex 3.0.0,而Skill要求2.4.0,OpenClaw会拒绝加载,并在日志中记录[ERROR] Dependency 'codex==2.4.0' not satisfied, found '3.0.0'。

更隐蔽的坑在frontend-design skill。它的YAML里有一行:

resources: volumes: - name: "figma-token" mountPath: "/run/secrets/figma_token" readOnly: true

这表示它需要Docker Secrets机制挂载一个名为figma_token的密钥。如果你没创建这个Secret(echo "your_token" | docker secret create figma_token -),Skill虽然能加载,但首次调用时会因读取/run/secrets/figma_token失败而崩溃。OpenClaw不会提前校验Secret是否存在,它只在Skill实际执行时才挂载——这就是“装对”和“能用”的鸿沟。

3.3 生死线三:Skill环境必须绝对隔离,禁止共享进程空间

这是openclaw 为什么会延迟问题的终极答案。OpenClaw默认为每个Skill分配独立的cgroup和网络命名空间。但如果你在Docker模式下使用--network host启动OpenClaw,所有Skill将共享宿主机网络栈。当comet skill(一个实时日志分析工具)开启长连接监听端口8081,而superpowers skill(一个系统监控工具)也试图监听8081时,后者会因端口被占而无限重试,导致整个OpenClaw的事件循环被阻塞,表现为所有Skill响应延迟。

正确的做法,是在openclaw.yaml主配置中强制指定网络模式:

# openclaw.yaml runtime: network_mode: "bridge" # 强制使用Docker桥接网络,每个Skill获得独立IP cgroup_parent: "openclaw.slice" # 所有Skill进程归入同一cgroup,便于统一资源管控

然后重启OpenClaw。此时comet skill和superpowers skill会被分配不同端口(如comet用8081,superpowers用8082),互不干扰。我在客户现场实测,将network_mode从host改为bridge后,平均响应延迟从12秒降至180毫秒,且不再出现随机超时。

提示:openclaw卸载命令之所以存在,是因为Skill卸载不是简单删除文件。它会执行三步:1. 停止Skill进程;2. 卸载其挂载的所有volume(包括Docker volume和hostPath);3. 清理cgroup中该Skill的资源配额。如果手动rm -rf ~/.claw/skills/comet,会导致cgroup残留,下次启动OpenClaw时可能因资源配额超限而失败。

4. 从零构建一个Production级Skill:以ppt skill为例的全链路拆解

理论讲完,现在动手。我们以高频热词ppt skill为例,完整走一遍从YAML编写、本地调试、到生产部署的全流程。这不是一个“Hello World”,而是一个能真实生成专业PPT的Skill,它将调用python-pptx库,根据JSON输入数据渲染幻灯片,并支持飞书/微信消息回调。

4.1 第一步:定义Skill契约(ppt.yaml)

创建ppt.yaml,这是整个Skill的宪法:

name: "ppt" version: "2.1.0" description: "根据JSON Schema生成PPTX文件,支持飞书/微信消息通知" author: "Your Name" license: "Apache-2.0" # 触发方式:仅支持Webhook,因为需要接收JSON数据 trigger: type: "webhook" endpoint: "/generate-ppt" method: "POST" auth: "api_key" # 使用API Key认证,Key存于环境变量OPENCLAW_PPT_API_KEY # 能力声明:它需要写文件、发HTTP请求 capabilities: - "filesystem:write:/tmp/ppt/" - "http:post:https://open.feishu.cn/open-apis/" # 资源需求:生成PPT是CPU密集型,需保证足够算力 resources: cpu: "1000m" # 1个CPU核心 memory: "1024Mi" # 1GB内存 volumes: - name: "templates" mountPath: "/opt/claw/skills/ppt/templates/" readOnly: true - name: "output" mountPath: "/tmp/ppt/" readOnly: false # 生命周期:生成PPT可能耗时,设30秒超时,失败不重试(幂等性由上游保证) lifecycle: timeout_ms: 30000 retry: max_attempts: 0 # 依赖:明确指定Python版本和包 dependencies: - "python:3.11" - "package:python-pptx==0.6.21" - "package:jinja2==3.1.3" # 环境变量:敏感信息不硬编码,通过Secret注入 environment: - name: "FEISHU_WEBHOOK_URL" valueFrom: secretKeyRef: name: "feishu-webhook" key: "url" - name: "PPT_TEMPLATE_PATH" value: "/opt/claw/skills/ppt/templates/default.pptx"

4.2 第二步:编写Skill逻辑(main.py)

在/opt/claw/skills/ppt/目录下创建main.py。注意:OpenClaw不执行任意Python文件,它只执行YAML中entrypoint指定的文件。因此我们需要在YAML中补充:

# 在ppt.yaml末尾添加 entrypoint: "main.py"

main.py内容如下,关键点已加注释:

#!/usr/bin/env python3 import json import os import sys import tempfile from pptx import Presentation from pptx.util import Inches from jinja2 import Template # OpenClaw会将Webhook请求体作为stdin传入 # 这是Skill与OpenClaw的标准通信协议 try: input_data = json.loads(sys.stdin.read()) except json.JSONDecodeError as e: print(f"[ERROR] Invalid JSON input: {e}") sys.exit(1) # 1. 从环境变量获取配置 template_path = os.getenv("PPT_TEMPLATE_PATH", "/opt/claw/skills/ppt/templates/default.pptx") feishu_url = os.getenv("FEISHU_WEBHOOK_URL") # 2. 验证必要字段 required_fields = ["title", "slides"] if not all(field in input_data for field in required_fields): print("[ERROR] Missing required fields: title or slides") sys.exit(1) # 3. 创建临时PPT文件 with tempfile.NamedTemporaryFile(suffix=".pptx", delete=False) as tmp: ppt_path = tmp.name try: # 加载模板 prs = Presentation(template_path) # 渲染标题页 title_slide = prs.slides[0] title_slide.shapes.title.text = input_data["title"] # 渲染内容页 for i, slide_data in enumerate(input_data["slides"]): if i == 0: continue # 跳过标题页 if i >= len(prs.slides): blank_slide_layout = prs.slide_layouts[6] slide = prs.slides.add_slide(blank_slide_layout) else: slide = prs.slides[i] # 使用Jinja2渲染文本框内容(支持简单模板语法) if "content" in slide_data: template = Template(slide_data["content"]) rendered_content = template.render(**input_data) # 这里简化:将渲染后的内容写入第一个文本框 if slide.shapes and slide.shapes[0].has_text_frame: slide.shapes[0].text_frame.text = rendered_content prs.save(ppt_path) # 4. 构造飞书消息(如果配置了) if feishu_url: import requests message = { "msg_type": "text", "content": { "text": f"✅ PPT生成成功!文件已保存至 {ppt_path}。标题:{input_data['title']}" } } try: requests.post(feishu_url, json=message, timeout=5) except Exception as e: print(f"[WARN] Failed to send Feishu notification: {e}") # 5. 输出结果给OpenClaw(标准输出JSON) print(json.dumps({ "status": "success", "file_path": ppt_path, "download_url": f"http://localhost:8080/download/{os.path.basename(ppt_path)}" })) except Exception as e: print(f"[ERROR] PPT generation failed: {e}") sys.exit(1)

4.3 第三步:本地调试与打包

OpenClaw提供openclaw dev命令进行本地调试,无需启动完整服务:

# 1. 将ppt.yaml和main.py放在同一目录 # 2. 准备模板文件(default.pptx)放入templates/子目录 # 3. 运行调试(模拟Webhook POST请求) echo '{"title":"Q3销售报告","slides":[{"content":"销售额:{{q3_revenue}}万元"}]}' | \ OPENCLAW_PPT_API_KEY="test-key" \ FEISHU_WEBHOOK_URL="https://open.feishu.cn/xxx" \ openclaw dev --skill-dir ./ppt/ --input-json # 输出应为:{"status":"success","file_path":"/tmp/xxx.pptx",...}

调试通过后,打包为Skill包:

# 创建Skill包(tar.gz格式) tar -czf ppt-2.1.0.claw ppt.yaml main.py templates/ # 上传到ClawHub或私有仓库 openclaw publish --file ppt-2.1.0.claw --token YOUR_CLAWHUB_TOKEN

4.4 第四步:生产部署与飞书接入

在目标服务器上:

# 1. 安装Skill openclaw install skill:ppt@2.1.0 # 2. 创建飞书Webhook Secret echo "https://open.feishu.cn/open-apis/bot/v2/hook/xxx" | docker secret create feishu-webhook - # 3. 重启OpenClaw以加载新Skill openclaw restart # 4. 测试(用curl模拟飞书机器人发送的JSON) curl -X POST http://localhost:8080/skills/ppt/generate-ppt \ -H "Authorization: Bearer test-key" \ -H "Content-Type: application/json" \ -d '{"title":"测试PPT","slides":[{"content":"Hello World!"}]}'

此时,OpenClaw会返回PPT文件路径,飞书群也会收到成功通知。整个过程,YAML是唯一的真理来源,所有配置、依赖、安全策略都由此定义。ppt skill的成功,不在于Python代码多精妙,而在于YAML契约的完备性。

经验:openclaw接入飞书和openclaw接入微信的差异,只体现在YAML的environment段。飞书用FEISHU_WEBHOOK_URL,微信用WECHAT_WEBHOOK_URL,OpenClaw运行时会自动注入对应值。同一个ppt skill,只需更换Secret,就能无缝切换通知渠道。这才是YAML驱动的真正威力——基础设施即代码,通知渠道即配置。

5. 高阶避坑指南:那些只在生产环境才爆发的Skill陷阱

前面讲的是“如何正确”,现在说“如何避免错误”。这些坑,99%的教程不会提,但每一个都足以让你在凌晨三点对着日志抓狂。

5.1 陷阱一:YAML中的!!str强制类型转换,引发yaml::dump与yaml::loadfile不一致

这是一个C++开发者才会踩的深坑。OpenClaw底层用yaml-cpp库,其yaml::dump函数默认会为数字加引号,而yaml::loadfile读取时,如果数字被引号包围,会被解析为字符串而非整数。例如:

# bad.yaml timeout_ms: "30000" # yaml::dump生成的,带引号 # good.yaml timeout_ms: 30000 # 手动写的,无引号

bad.yaml在OpenClaw中加载后,timeout_ms的值是字符串"30000",当运行时尝试std::stoi(timeout_ms)时抛出std::invalid_argument异常,Skill静默失败。而good.yaml则一切正常。

解决方案:永远不要用yaml::dump生成生产YAML。所有Skill的YAML文件,必须手写,或用yq等工具生成:

# 用yq生成无引号数字的YAML echo '{"timeout_ms": 30000}' | yq -P # 输出:timeout_ms: 30000 (无引号)

5.2 陷阱二:in spring中的yaml文件中配置密码是否属于硬编码的类比误区

很多Java开发者看到OpenClaw的YAML,第一反应是“这不就是Spring Boot的application.yml?密码不能硬编码!”于是他们把FEISHU_WEBHOOK_URL写成:

# 错误!OpenClaw不支持Spring风格的${}占位符 environment: - name: "FEISHU_WEBHOOK_URL" value: "${FEISHU_WEBHOOK_URL}" # OpenClaw会原样传入,不解析

结果main.py里os.getenv("FEISHU_WEBHOOK_URL")得到的是字符串"${FEISHU_WEBHOOK_URL}",而非真实URL。OpenClaw的环境变量注入机制,只支持valueFrom.secretKeyRef,不支持任何形式的占位符解析。这是设计使然——YAML是声明式契约,不是模板引擎。

5.3 陷阱三:yolo数据集定义了类别数量还要在yaml文件里面改吗的跨Skill耦合

YOLO训练需要data.yaml定义nc: 80(类别数)。如果yolo skill和train skill是两个独立Skill,它们的YAML文件里都写了nc: 80,那么当类别数变为81时,你必须同时更新两个YAML。这违反了单一职责原则。

正确解法:用OpenClaw的shared_config机制。在openclaw.yaml中定义:

shared_config: yolo: nc: 80 names: ["person", "car", ...]

然后在yolo.yaml和train.yaml中引用:

# yolo.yaml environment: - name: "YOLO_NC" valueFrom: configMapKeyRef: name: "yolo" key: "nc"

这样,只需改一处openclaw.yaml,所有Skill自动生效。shared_config是OpenClaw解决Skill间配置耦合的官方方案,却被90%的用户忽略。

5.4 陷阱四:群晖 docker openclaw 下载哪个的镜像选择谬误

群晖用户常问“下载哪个镜像”,其实问题本身是错的。OpenClaw官方只提供一个镜像openclaw/openclaw:latest,但群晖的Docker套件在拉取时,会根据CPU架构自动选择amd64或arm64变体。真正的坑在于:群晖的dockerd默认不启用cgroup v2,而OpenClaw的resources限制(cpu/memory)依赖cgroup v2。结果就是resources.cpu: "1000m"完全失效,Skill可能吃光整个NAS的CPU。

解决方案:登录群晖SSH,编辑/etc/docker/daemon.json:

{ "exec-opts": ["native.cgroupdriver=systemd"], "storage-driver": "overlay2" }

然后重启Docker:sudo synoservice --restart pkgctl-Docker重启后,cat /proc/1/cgroup | head -1应显示0::/system.slice/docker.service,证明cgroup v2已启用。

最后分享一个小技巧:openclaw 2026.2.5版本这个热词,其实是OpenClaw的“年份.月份.序号”版本命名法。2026.2.5表示2026年2月发布的第5个patch。它不意味着未来版本,而是当前最新稳定版(截至2024年,实际版本号为2024.8.3)。所有热词中的“2026.2.5”,都是用户误抄了文档里的占位符。检查版本的唯一可靠方式,是openclaw --version,它返回的是Git commit hash,而非年份字符串。

相关新闻

  • OpenClaw:本地Agent技能编排网关核心原理与实战
  • MSC711x DSP内存映射与总线架构深度解析:从统一地址空间到外设驱动实战
  • AnythingLLM API调试实战:从连接错误到模型超限的完整排错指南

最新新闻

  • Codex本地AI引擎安装配置全指南:WSL路径、沙箱策略与VS Code集成
  • AI对抗样本攻击硬件木马检测:物联网设备安全新威胁
  • LabVIEW集成C语言MD5算法:跨平台数据校验与文件完整性验证实战
  • TRAE Skills:Agent能力的可执行说明书与WASM契约设计
  • PLD实战指南:从硬件描述语言到FPGA/CPLD设计全流程解析
  • 企业微信技能调度中枢:沙箱化Skill架构与Ubuntu 20.04云端部署

日新闻

  • 终极指南:如何用shadPS4在电脑上免费畅玩PS4游戏
  • 打造个性化Instagram Clone:主题定制与用户体验优化技巧
  • 未来展望:RoseTTAFold-All-Atom的发展路线图与社区支持资源汇总

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号