Files
skill-template/references/ACTIONS.md
chendelian 8878a90315
All checks were successful
技能自动化发布 / release (push) Successful in 7s
docs: align toolbar button layout with host (no more-menu)
2026-08-08 19:32:46 +08:00

25 KiB
Raw Blame History

Skill Action Manifest(匠厂宿主)

本文件说明 assets/actions.json 与 scripts/main.py CLI 的对应关系,供 Agent 编排与宿主 Skill Action Runtime 使用。这是 Agent 侧关于 Action / 任务中心的主契约;实现细节与开发规范见 ../development/SKILL_ACTION_RUNTIME.md。

边界: 用户市场四 Tab 见根目录 README.md / TUTORIAL.md / DEMO.md / CHANGELOG.md;CLI 参数见 CLI.md。

Agent 何时用 Action(与 CLI 的分工)

场景 做法
短查询 / 只读 / 秒级 bash + 共享 Python CLI(见 CLI.md);不必强行走 Action
数据管理按钮 / 定时任务 / 技能详情按钮 必须在 actions.json 声明对应 Action
长耗时 / RPA / 需要进度与取消 必须 run_skill_action;对应 Action 一般为 executionProfile: "async"
已声明的 sync Action run_skill_action 当场返回结果,不进任务中心
已声明的 async Action run_skill_action 立即返回 jobId,进入任务中心

进不进任务中心只取决于该 Action 的 executionProfile,与从数据管理、定时任务还是 Agent 触发无关。

禁止对长任务 exec/bash + process poll 干等 CLI。禁止 uv run python 跑技能脚本。

async 副作用 Action 最小组合(复制验收 checklist)

对每个「会开浏览器 / 长耗时 / 需进度或取消」的 Action,声明时建议同时满足:

  1. executionProfile: "async"(进入任务中心)
  2. 若要让 Agent 触发:placements 含 agent
  3. 有可感知副作用时:提供 confirmation.message
  4. 需要用户/Agent 入参时:简单 inputSchema + entrypoint 中的 {{fieldName}}
  5. SKILL.md「用户意图路由表」与 CLI.md「Action 强制黑名单」出现同一 action id / 命令

默认模板 assets/actions.json 仅含诊断类 sync Action,不要为通过本 checklist 而塞假业务 Action;业务技能按需添加。完整字段见下文 Phase 1。

可选:域前缀 CLI(嵌套子命令)

小技能可继续扁平:entrypoint.command = "run"。
命令变多时,可采用域前缀:command 为域(如 <domain>),业务动词与参数放在 args 数组(如 ["<verb>", "--flag", "{{field}}"])。与扁平入口等价,须仍指向同一 domain service。

模板严格规范 vs 宿主向后兼容

角色 定位
skill-template 新技能推荐的严格规范:必填字段、明确类型、additionalProperties: false
宿主运行时 向后兼容的历史 manifest 解析器:可能接受部分缺省字段(如 description、placements、entrypoint.args、缺失的 bind.tables)

新技能不应依赖宿主缺省行为。 复制模板后按 assets/schemas/skill-actions.schema.json 与本文完整填写 manifest。

JSON Schema 使用 additionalProperties: false 表达模板严格边界;这与宿主共享类型中的可选字段并不矛盾——宿主为兼容旧技能可能更宽松,模板为防漂移要求更严。

Action 是否必需

Action 是可选能力:

  • 没有宿主直接操作需求的技能,可以不提供 actions.json。
  • 需要出现在数据管理按钮、技能详情、定时任务或 Agent 直接调用中的技能,必须提供 assets/actions.json。
  • 含浏览器 RPA / 长耗时任务的技能:必须提供至少一条 executionProfile: "async" 且 placements 含 agent 的 action(见 POLICY-SKILL-ACTION-001)。

文件位置

{skill_root}/assets/actions.json

宿主扫描路径示例:

~/.openclaw/skills/your-skill-slug/assets/actions.json

顶层结构

字段 必填 说明
schemaVersion 是 当前固定为 1
skill 是 必须与 SKILL.md 的 metadata.openclaw.slug 一致
actions 是 Action 数组,每项 id 唯一;数组相对顺序决定数据管理 toolbar / row / batch 技能按钮的展示顺序(见下节)

模板最小示例见 assets/actions.json;JSON Schema 见 assets/schemas/skill-actions.schema.json。

五职责正交(必读)

字段 / 层 只决定什么 不决定什么
placements Action 出现在哪里(toolbar / row / batch / cron / agent / skill-detail) 不决定 sync/async,不决定点了是否弹窗
replaces 可选:接管数据管理默认「新增 / 编辑 / 删除」 不强制;无配置时宿主仍直写 SQLite
bind.tables 数据管理里出现在哪些业务表 不决定业务实现
executionProfile 宿主是同步等待还是异步 Job 不限制可展示入口,不决定是否弹窗
interaction 可点击入口(数据管理 toolbar/row/batch、默认 CRUD 接管、未来 skill-detail)点了怎么交互 不决定 sync/async;cron 触发与 agent 忽略
entrypoint 实际执行哪个 CLI 命令与参数 不写业务逻辑
domain service 真正完成什么业务 不感知 toolbar / cron / agent 来源

一个业务能力通常只定义一个 Action,用 placements 同时挂到多个入口。不要拆成 sync-records-toolbar / sync-records-cron 等副本,除非语义确实不同;即便拆分,也必须调用同一个领域业务内核。

Phase 1 当前稳定支持(新技能应只使用这些)

层级 稳定字段 / 能力
顶层 schemaVersion、skill、actions
action id、label、description、placements、entrypoint、executionProfile(必填);可选 inputSchema、confirmation、interaction、interactionByPlacement、bind、replaces
entrypoint type = cli、command、args(必填 JSON 数组,项为 string / number / boolean)
placements toolbar、row、batch、skill-detail、agent、cron;仅 replaces 时可为空数组
replaces 可选 "create" | "update" | "delete" — 接管默认新增/编辑/删除(须 bind.tables)
bind { "tables": ["business_table"] };可选 inputMapping(行内/批量预填,见下节)
inputSchema 根 type: object;properties 使用 string / number / boolean;支持 enum、default、required、sensitive、readOnly
confirmation { "message": "..." } — 风险文案(confirm/form 弹窗黄条;agent 元数据);不是「要不要弹窗」的开关
executionProfile "sync" | "async"(必须显式写出,禁止依赖缺省)
interaction "auto" | "direct" | "confirm" | "form"(可选;省略≈auto)
interactionByPlacement 可选;按 placement 覆盖为 direct/confirm/form(不可写 auto)

bind.tables(表级绑定)

{
  "bind": {
    "tables": ["business_table"]
  }
}

规则:

  • bind 为 object,additionalProperties: false;当前允许 tables(必填键当存在 bind 时)与可选 inputMapping。
  • tables 非空数组、元素唯一、英文 snake_case、不得为空字符串。
  • placements 含 toolbar 时必须显式声明非空 bind.tables(模板 Schema if/then + 自动测试强制)。
  • row / batch 建议同样声明 bind.tables,避免在无关表上露出按钮;未声明时宿主可能按兼容逻辑在更多表上展示。
  • 表名须真实存在于技能 SQLite 与 _jiangchang_tables。
  • 希望出现在多张表时,显式列出所有表;不要依赖「无 bind 则全表展示」——那是宿主对旧技能的兼容,不是新技能标准。
  • inputMapping(可选):把行/勾选映射到 inputSchema 字段,例如 "leadId": "$row.$pk"、"ids": "$selection.ids"。适合 row / batch。宿主仍会提交这些字段;可用 inputSchema.properties.*.readOnly: true 在表单中只读展示。
  • concurrency / locks 仍未稳定,不要写入新技能 manifest。

replaces(可选:接管默认新增 / 编辑 / 删除)

有领域副作用的表(建目录、加密、级联清理)不要依赖宿主直写 SQLite。此时可为该表声明:

{
  "id": "account-add-web",
  "label": "新增账号",
  "description": "登记网页账号并初始化 profile 目录。",
  "replaces": "create",
  "placements": [],
  "executionProfile": "sync",
  "interaction": "form",
  "bind": { "tables": ["accounts"] },
  "inputSchema": {
    "type": "object",
    "required": ["platform_key", "account_label"],
    "properties": {
      "platform_key": { "type": "string", "title": "平台" },
      "account_label": { "type": "string", "title": "账号名称" }
    }
  },
  "entrypoint": {
    "type": "cli",
    "command": "account",
    "args": ["add-web", "--platform", "{{platform_key}}", "--label", "{{account_label}}"]
  }
}

规则:

  • 全可选:无 replaces 时,宿主默认按钮仍直写库,行为与以前一致。
  • 取值:create(新增)/ update(编辑)/ delete(删除)。
  • 必须非空 bind.tables;同一技能同一表同一 replaces 至多一个 Action。
  • 与 placements 正交:可只接管默认按钮(placements: []),不必再挂 toolbar「第二个新增」。
  • 点默认按钮时走该 Action 的 interaction(create/update 常用 form;delete 常用 confirm)。
  • update / delete 可用 inputMapping($row.$pk、$selection.ids)预填主键。
  • 宿主导入仍直写:有 replaces:create 的表慎用宿主导入,或另做 import Action。
  • 整表 _jiangchang_tables.readonly=1 时仍隐藏写按钮(优先于 replaces)。
  • 列元数据复用(lookup):create/update 抽屉可将 inputSchema 字段对齐业务列,复用中文名与 lookup 下拉:
    • 优先让属性名 = 物理列名(如 platform_key);
    • 或 bind.columnMapping:{ "platform": "platform_key" };
    • 或字段上写 "column": "platform_key"。
    • 不要在 actions.json 里写死会过期的全量平台 enum。

interaction(点击交互方式)

与 executionProfile 正交:一个 Action 可以是 async + direct(一点就进任务中心),也可以是 sync + form(填参后当场返回)。

值 数据管理体验 典型场景
direct 一点即跑,无弹窗 打开文件位置、无参只读、行内主键已映射
confirm 轻量确认弹窗(无参数区;文案优先 confirmation.message) 打开浏览器、有副作用但无可编辑入参
form 完整参数表单(现状默认路径) 导入、查询条件、需用户改写的字段
auto / 省略 宿主推断:有可编辑参数 → form;仅有 confirmation → confirm;否则 → direct 旧技能兼容;新技能建议显式写出
{
  "id": "reveal-profile",
  "label": "打开文件位置",
  "description": "在资源管理器中打开 Profile 目录。",
  "placements": ["row"],
  "executionProfile": "sync",
  "interaction": "direct",
  "bind": {
    "tables": ["accounts"],
    "inputMapping": { "accountId": "$row.$pk" }
  },
  "inputSchema": {
    "type": "object",
    "required": ["accountId"],
    "properties": {
      "accountId": { "type": "number", "title": "账号 ID", "readOnly": true }
    }
  },
  "entrypoint": {
    "type": "cli",
    "command": "account",
    "args": ["reveal-profile", "{{accountId}}"]
  }
}
{
  "id": "open-browser",
  "label": "打开浏览器",
  "placements": ["row"],
  "executionProfile": "async",
  "interaction": "confirm",
  "confirmation": { "message": "将用该账号 Profile 打开浏览器,仅供查看。" },
  "bind": {
    "tables": ["accounts"],
    "inputMapping": { "accountId": "$row.$pk" }
  },
  "inputSchema": {
    "type": "object",
    "required": ["accountId"],
    "properties": {
      "accountId": { "type": "number", "readOnly": true }
    }
  },
  "entrypoint": {
    "type": "cli",
    "command": "account",
    "args": ["open", "{{accountId}}"]
  }
}

可选 interactionByPlacement:同一 Action 在不同入口用不同交互(例如 row: "direct"、toolbar: "form")。值只能是 direct/confirm/form,不能写 auto。

边界:

  • cron 配置:仍展示可编辑参数;confirmation.message 可作为配置页风险提示(由宿主决定)。
  • cron 触发 / agent:忽略 interaction(无人值守 / 模型填参);confirmation 对 agent 仍作 requiresConfirmation 元数据。
  • 不要用 interaction: "direct" 掩盖需要用户填写的可编辑字段——宿主在 auto 下会因可编辑参数回落到 form;显式 direct + 可编辑字段时参数取 default/预填,作者须自觉。

默认模板 actions.json 仅含 health / version / config-path,不放在 toolbar/row/batch,故无需 bind 示例污染默认 manifest。业务示例:

{
  "id": "sync-records",
  "label": "同步记录",
  "description": "从外部来源同步到技能本地数据库,不生成导出文件。",
  "placements": ["toolbar", "cron", "agent", "skill-detail"],
  "executionProfile": "async",
  "bind": { "tables": ["business_records"] },
  "entrypoint": { "type": "cli", "command": "sync-records", "args": [] }
}

行内示例:

{
  "id": "retry-one",
  "label": "重试本行",
  "description": "对当前行执行一次业务重试。",
  "placements": ["row"],
  "executionProfile": "async",
  "bind": {
    "tables": ["business_records"],
    "inputMapping": { "recordId": "$row.$pk" }
  },
  "inputSchema": {
    "type": "object",
    "required": ["recordId"],
    "properties": {
      "recordId": { "type": "string", "title": "记录 ID", "readOnly": true }
    }
  },
  "entrypoint": {
    "type": "cli",
    "command": "retry",
    "args": ["--id", "{{recordId}}"]
  }
}

预留能力(当前不可当作已实现能力)

类别 预留项 说明
action 字段 concurrency、locks 并发与锁控制,未稳定开放
inputSchema array、nested object、oneOf 等 复杂表单,不属于当前推荐范围

bind、row、batch 不是保留能力;已按匠厂宿主正式支持写入本规范。

执行模型

宿主将 action 转为 argv,再用共享 Python(用户数据目录下 python-runtime/.venv)执行:

python {skill_root}/scripts/main.py <command> <args...>
  • entrypoint.type 当前只支持 cli
  • entrypoint.command → CLI 子命令(须真实存在)
  • entrypoint.args → 子命令参数(必须为 JSON 数组)
  • {{fieldName}} → 来自 inputSchema 用户输入的简单模板替换

完整子命令定义见 scripts/cli/app.py。

executionProfile(仅 sync / async)

心智:多数 Action 按 sync(短调用、不进任务中心);只有长耗时 / RPA / 需进度控制时才标 async。匠厂宿主若省略该字段,按 sync 处理;模板与新技能仍要求每个 Action 显式写出 sync 或 async,禁止发明 auto / background / deferred,也禁止赌省略行为。

值 宿主行为 任务中心
sync(或省略时的宿主缺省) 调用方等待结束,直接返回结构化结果或结构化错误;不创建后台 Job 不进
async(须显式声明) 宿主创建后台 Job,立即返回 jobId;用 emit / checkpoint / finish 报告进度与终态 进入

合法组合(全部允许):sync|async × toolbar|row|batch|cron|agent|skill-detail。

经验建议(不是 placement 硬限制):耗时不可预测、需要暂停/停止/进度展示的任务,用 async;其余默认写 sync。

直接执行短 CLI 时,终端自然等待进程结束。宿主通过 Action 调用同一 CLI 时,再按 executionProfile 决定同步等待还是建 Job。技能不得自行实现第二套任务中心或后台队列。

CLI 输出契约

技能 CLI 必须:

  • 使用稳定的退出码
  • 成功时输出可解析的结构化结果
  • 失败时输出稳定错误信息
  • 对可预期错误提供稳定错误码
  • 对用户可处理的问题提供 HINT
  • 不依赖 Agent 连续对话才能完成
  • 不自行实现宿主任务中心
  • 不在 CLI 中硬编码宿主安装目录
  • 不直接依赖某个具体 UI 页面

建议错误输出格式:

ERROR:<CODE>: <message>
HINT: <next step>

placements(入口位置)

值 含义
toolbar 数据管理表顶栏技能按钮(须配合 bind.tables)
row 数据管理行内操作(建议 bind.tables + inputMapping;表需有主键)
batch 数据管理批量操作(需勾选行;无勾选时宿主禁用按钮)
skill-detail 技能详情页直调(与安装/四 Tab 同属技能市场详情;已声明则须自测)
agent Agent 可直接调用(run_skill_action)
cron 定时任务「技能直调」

数据管理技能按钮顺序(宿主正式契约)

宿主没有单独的 sortOrder / uiOrder 字段。同一 placement(toolbar / row / batch)下,技能按钮的展示顺序 = actions 数组中匹配该项 placement(且通过 bind.tables 过滤)的相对先后。

规则:

  1. 想调整顺序 → 调整 actions 数组先后(不必改 id / label)。
  2. 无关 placement 的 Action(如仅 skill-detail 的 health)夹在中间不影响 toolbar/row 的相对顺序;宿主按匹配子集保序渲染。
  3. 同一 Action 可同时挂多个 placement;它在各入口的位置,分别是该入口匹配子集里的相对位置。
  4. 宿主内置按钮不参与本契约、位置固定:
    • 表顶栏右侧:删除(有勾选时)/ 刷新 / 新增 / 导入 / 导出 —— 技能 toolbar/batch 按钮在左侧,不能与右侧内置按钮混排。
    • 行内「操作」列:技能 row 按钮在前;其后固定为宿主「查看」→(非只读)「编辑」→「删除」。
  5. 表顶栏全部直接展示,无「更多操作」溢出菜单:匹配到的 toolbar/batch 技能按钮一律渲染(顺序仍按本契约)。
  6. 表顶栏宽窄布局(宿主行为,技能无需配置):
    • 够宽:左右各横排一行(左技能按钮 + 右宿主工具)。
    • 不够宽:保持左右分栏,栏内按钮上下竖排(左栏技能、右栏刷新/导出等)。

禁止:

  • 臆造 sortOrder / order / priority 等字段指望宿主排序(模板 Schema additionalProperties: false 会拒收)。
  • 依赖或宣传「更多操作」溢出菜单(宿主已取消该能力)。
  • 把「表格行数据默认排序」与按钮顺序混淆——行排序见 SCHEMA.md 的 default_sort_json。

Action 类型 × placements(常见示例,不是限制)

下表只表示常见用法示例。实际 placements 以 manifest 配置为准;sync / async 不影响展示入口。已声明的入口都要在宿主自测,不要只测其中一条。

Action 类型 常见 executionProfile 常见 placements confirmation
health / version / config-path sync skill-detail, agent 无
统计 / 只读查询 sync skill-detail, agent 无
数据同步(外源 → 本地库) sync 或 async toolbar + cron + agent + skill-detail(按需) 可选
单行重试 / 行内处理 sync 或 async row(可加 agent) 可选
批量处理勾选行 sync 或 async batch(可加 toolbar/cron) 可选
导入 / 重置 sync 或 async skill-detail, agent 可选
单条副作用 RPA async(建议) agent, skill-detail 建议
批量顺序 pick RPA async(建议) toolbar, cron, agent 建议

同步数据 vs 导出当前表 vs 特殊业务报告

不要混用「导出」一词:

能力 语义 谁负责
同步数据(sync / refresh / collect) 外部来源 → 技能本地数据库 技能 Action / domain service
导出当前数据表 技能本地数据库 → CSV/Excel 等 数据管理页宿主统一导出
生成特殊业务报告 多表合并、特殊排版或附加计算 仅当系统导出无法满足时,才提供独立 export-* Action

同步型 Action 默认:读外部数据、写技能自己的库、不生成 CSV/Excel/JSON 文件、不重复实现宿主表导出。兼容旧 export 命令若需要刷新数据,必须调用同一个 sync 业务内核。通用同步语义见 SCHEMA.md 与 ../development/SKILL_ACTION_RUNTIME.md。

inputSchema 与参数表单

当前宿主稳定支持:

  • object / string / number / boolean
  • enum / default / required / sensitive / readOnly
  • 简单模板替换({{fieldName}})

示例:

{
  "inputSchema": {
    "type": "object",
    "required": ["query"],
    "properties": {
      "query": {
        "type": "string",
        "title": "查询条件"
      },
      "limit": {
        "type": "number",
        "title": "返回数量",
        "default": 50
      }
    }
  }
}

批量 pick 参数约定(有队列表时):

{
  "pickCount": {
    "type": "number",
    "title": "处理数量",
    "description": "从队列选取 pending 记录条数",
    "default": 1,
    "minimum": 1
  }
}

约定:

  • boolean 在宿主中渲染为开关
  • enum 在宿主中渲染为选择框
  • required 字段在提交前校验
  • sensitive 字段不得出现在低信任入口
  • readOnly: true 时数据管理表单只读展示该字段(仍随提交传入);适合行内/勾选预填的主键、编号列表
  • placements 含 batch 的动作在数据管理表顶常驻,无勾选时禁用(与表删除一致)
  • 需要确认的副作用操作使用 confirmation.message
  • 模板参数使用 {{fieldName}},且必须在 inputSchema.properties 中声明
  • entrypoint.args 项当前只允许 string、number、boolean;不允许对象或 null
  • 不要在当前模板中宣传 nested object、oneOf、复杂数组等尚未稳定支持的能力

风险与入口配置

  • 查询、诊断、版本检查可以放到 skill-detail 或 agent
  • 低风险、常用动作才考虑放 toolbar(须 bind.tables;executionProfile 按耗时自选)
  • 会修改本地数据、访问外部系统、执行长时间任务的动作必须谨慎配置
  • 有副作用的动作应添加 confirmation.message
  • 高风险动作不应默认出现在 toolbar
  • 含 sensitive 参数的 action 不应放入 toolbar 或 cron,除非有明确安全设计
  • 不要为了「按钮多」而暴露所有 CLI 子命令
  • 一个 CLI 命令可以拆成多个语义清晰的 action,但每个 action 必须有明确语义,并复用同一业务内核
  • Agent 必须用 run_skill_action,禁止 exec 直跑长任务 CLI(见 SKILL_ACTION_RUNTIME.md)
  • 禁止按 source=toolbar/cron/agent/skill-detail 在业务代码中分叉业务行为

模板示例 action 一览

id CLI executionProfile placements 说明
health health sync skill-detail, agent 运行环境检查
version version sync skill-detail 版本 JSON
config-path config-path sync skill-detail 配置路径 JSON

业务技能复制后,按需增加例如:

模式 id 示例 executionProfile placements bind
数据同步 sync-records async 或 sync toolbar, cron, agent, skill-detail 必填 tables
单条 RPA your-run async(建议) agent, skill-detail 按需
队列 pick your-run-pick async(建议) toolbar, cron, agent 有 toolbar 则必填
统计 your-stats sync skill-detail, agent 无

不需要宿主入口时可删除整个 actions.json(无 RPA 长任务时)。

与宿主 API(参考)

宿主 API 用途
GET /api/skill-actions/{skillSlug} 读取 manifest
POST /api/skill-actions/run { skillSlug, actionId, input?, source? }
GET /api/skill-actions/jobs 任务中心

具体路径与字段以宿主实现为准;技能侧只需保证 manifest 与 CLI 契约稳定。