Files
skill-template/references/ACTIONS.md
chendelian d35d04f779
All checks were successful
技能自动化发布 / release (push) Successful in 5s
Release v1.0.98: data management filter and global search contract
2026-08-23 17:10:52 +08:00

58 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。

先读产品入口: 对话 / 数据管理 / 定时任务在宿主上平级,何时挂哪个入口见 ../development/PRODUCT_SURFACES.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 / 命令
  6. 若处理的是业务队列表中的一行:遵守 WORK_ITEM_STATUS.md——默认只捞可操作角色;开始抢占为进行中;结束回写成功/失败(失败带原因);确认文案写清仅可操作态可处理

默认模板 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 是否提供、挂哪些 placements,由本技能 入口定位表决定(见 ../development/PRODUCT_SURFACES.md),不是「可有可无的附属能力」:

  • 定位需要出现在数据管理按钮、技能详情、定时任务或 Agent 直接调用中时,必须提供 assets/actions.json 并声明对应入口。
  • 定位确认无任何宿主结构化入口时,可以不提供 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。可选 Data Policy 见 POLICY.md 与 assets/schemas/skill-policy-snapshot.schema.json。可选单元格呈现见 CELL_PRESENTATION.md 与 assets/schemas/skill-cell-presentation.schema.json。

六职责正交(必读)

字段 / 层 只决定什么 不决定什么
placements Action 出现在哪里(toolbar / row / batch / cron / agent / skill-detail;row=行级入口,壳由宿主呈现) 不决定 sync/async,不决定点了是否弹窗,不决定行级用操作列还是右键,不决定谁能点
replaces 可选:接管数据管理默认「新增 / 编辑 / 删除 / 导入」 不强制;无配置时宿主仍直写 SQLite;import 时 UI 仍用宿主「导入数据」面板
bind.tables 数据管理里出现在哪些业务表 不决定业务实现
executionProfile 宿主是同步等待还是异步 Job 不限制可展示入口,不决定是否弹窗
interaction 可点击入口(数据管理 toolbar/row/batch、默认 CRUD 接管、未来 skill-detail)点了怎么交互 不决定 sync/async;cron 触发与 agent 忽略
hoverHint 可选:数据管理工具栏悬停文案 不决定短按钮名;不决定点下去弹不弹窗;不回退 description / confirmation.message;省略 = 不显示悬停。当前宿主实现为顶栏技能按钮
inputSchema.visibleWhen 可选:Action 参数表单字段条件显隐(先选模式再出对应参数) 不是 Data Policy L3 行态 visibleWhen;不决定 placements;旧宿主忽略则字段平铺全显
hostEffects / steps 可选:数据管理交互跑完前后,宿主要不要刷新表 / 清选区 / 级联删等 不决定业务写什么;省略 = 宿主不额外改 UI(≥2.8.5 起不再硬编码 mutation 后刷新);cron/agent 忽略
cellPresentation 可选:某表某行某列的语义标色/强调(tone + 说明) 不替代业务列;不下发 CSS;用途不限(超时、预警、驳回等);见 CELL_PRESENTATION.md
policy / Snapshot 可选:当前身份在数据管理下允许哪些 Action / 宿主内置能力 / 行列范围 不替代 placements;不替代 domain 写路径鉴权;多数技能不配 = L0 全开
entrypoint 实际执行哪个 CLI 命令与参数 不写业务逻辑
domain service 真正完成什么业务 不感知 toolbar / cron / agent 来源

一个业务能力通常只定义一个 Action,用 placements 同时挂到多个入口。不要拆成 sync-records-toolbar / sync-records-cron 等副本,除非语义确实不同;即便拆分,也必须调用同一个领域业务内核。需要按用户/角色藏按钮或滤行时,不要按角色复制 Action,应启用顶层 policy 并由技能算出 Snapshot(见 POLICY.md)。

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

层级 稳定字段 / 能力
顶层 schemaVersion、skill、actions;可选 policy(Data Policy 启用块);可选 cellPresentation(单元格呈现启用块)
action id、label、description、placements、entrypoint、executionProfile(必填);可选 hoverHint、inputSchema、confirmation、interaction、interactionByPlacement、bind、replaces、hostEffects、steps、authz(仅文档提示)
entrypoint type = cli、command、args(必填 JSON 数组,项为 string / number / boolean)
placements toolbar、row、batch、skill-detail、agent、cron;仅 replaces 时可为空数组
replaces 可选 "create" | "update" | "delete" | "import" — 接管默认新增/编辑/删除/导入(须 bind.tables)
bind { "tables": ["business_table"] };可选 inputMapping(行内/批量预填,见下节)
policy 可选;enabled + entrypoint(推荐 policy CLI);见 POLICY.md。未启用 = L0
cellPresentation 可选;{ "enabled": true } 时宿主应加载单元格呈现;见 CELL_PRESENTATION.md。未启用 = P0
inputSchema 根 type: object;properties 使用 string / number / boolean;支持 enum、default、required、sensitive、readOnly;可选 display_type / format(textarea / date / datetime_unix_seconds / url / email / lookup);可选 visibleWhen(字段条件显隐,见专节)
confirmation { "message": "..." } — 风险文案(confirm/form 弹窗黄条;agent 元数据);不是「要不要弹窗」的开关
hoverHint 可选字符串。数据管理工具栏悬停文案;与 description / confirmation.message 独立。省略则不显示悬停,不回退。短名已够懂时不要写。需宿主已支持该字段;当前实现为顶栏技能按钮,不含宿主内置删除/刷新/新增/导入/导出
visibleWhen 可选。写在 property 上(非 action 顶层):依赖同表单其它字段值决定是否展示;隐藏字段不提交、不校验 required。勿与 POLICY.md L3 行态 visibleWhen 混淆
executionProfile "sync" | "async"(必须显式写出,禁止依赖缺省)
interaction "auto" | "direct" | "confirm" | "form"(可选;省略≈auto)
interactionByPlacement 可选;按 placement 覆盖为 direct/confirm/form(不可写 auto)
hostEffects 可选;onSuccess / onFailure → reloadTable | refreshCatalog | clearSelection(匠厂宿主 ≥2.8.5)
steps 可选;有序 { when, do, table?, fk? },when=before|afterSuccess|afterFailure;新技能优先(≥2.8.5)

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。此时可为该表声明 replaces,用户仍点宿主默认按钮,由技能 CLI 完成写入。

怎么选

场景 建议
纯表字段、无副作用 不配 replaces,宿主直写即可
单条新增/编辑/删除有副作用 replaces: create / update / delete
批量导入也有副作用(推荐) 另配 replaces: import(与 create 可同表并存)
只有 create、暂无 import 宿主「导入」面板确认后会逐行调 create(兼容);正式产品应补 import

导入分流(必读)

点工具栏「导入」时:

  1. UI 一律打开宿主「导入数据」面板(下载模板 → 选文件 → 映射 → 出错规则 → 预览)。
  2. 写库按表能力分流:
    • 有 replaces: import → 把选中文件路径 + 出错规则交给该 Action(技能解析并写入)
    • 仅有 replaces: create → 宿主按行调用 create(兼容)
    • 都没有 → 宿主直写 SQLite

不要再做一张技能自己的「开始执行」导入表单来冒充导入体验。placements 对 import 保持 [];description 写明「由宿主导入面板调用」。

可抄文件见 assets/examples/:replaces-*.action.example.json。

示例:create

{
  "id": "item-create",
  "label": "新增记录",
  "description": "新增业务记录并执行领域副作用(走技能 CLI,非宿主直写库)。",
  "replaces": "create",
  "placements": [],
  "executionProfile": "sync",
  "interaction": "form",
  "bind": { "tables": ["items"] },
  "hostEffects": { "onSuccess": ["reloadTable"] },
  "inputSchema": {
    "type": "object",
    "required": ["name"],
    "properties": {
      "name": { "type": "string", "title": "名称" },
      "note": { "type": "string", "title": "备注" }
    }
  },
  "entrypoint": {
    "type": "cli",
    "command": "item",
    "args": ["create", "--name", "{{name}}", "--note", "{{note}}"]
  }
}

示例:update

{
  "id": "item-update",
  "label": "编辑记录",
  "description": "编辑业务记录并重算派生字段。",
  "replaces": "update",
  "placements": [],
  "executionProfile": "sync",
  "interaction": "form",
  "bind": {
    "tables": ["items"],
    "inputMapping": {
      "id": "$row.$pk",
      "name": "$row.name",
      "note": "$row.note"
    }
  },
  "hostEffects": { "onSuccess": ["reloadTable"] },
  "inputSchema": {
    "type": "object",
    "required": ["id", "name"],
    "properties": {
      "id": { "type": "number", "title": "编号", "readOnly": true },
      "name": { "type": "string", "title": "名称" },
      "note": { "type": "string", "title": "备注" }
    }
  },
  "entrypoint": {
    "type": "cli",
    "command": "item",
    "args": ["update", "--id", "{{id}}", "--name", "{{name}}", "--note", "{{note}}"]
  }
}

示例:delete

{
  "id": "item-delete",
  "label": "删除记录",
  "description": "删除业务记录并清理关联副作用。",
  "replaces": "delete",
  "placements": [],
  "executionProfile": "sync",
  "interaction": "confirm",
  "confirmation": { "message": "确定删除该记录?关联数据将一并清理。" },
  "bind": {
    "tables": ["items"],
    "inputMapping": { "id": "$row.$pk" }
  },
  "hostEffects": { "onSuccess": ["reloadTable", "clearSelection"] },
  "inputSchema": {
    "type": "object",
    "required": ["id"],
    "properties": {
      "id": { "type": "number", "title": "编号", "readOnly": true }
    }
  },
  "entrypoint": {
    "type": "cli",
    "command": "item",
    "args": ["delete", "--id", "{{id}}"]
  }
}

示例:import

{
  "id": "item-import",
  "label": "导入记录",
  "description": "由宿主「导入数据」面板调用:解析 Excel/CSV 并写入业务表(含领域校验与派生字段)。",
  "replaces": "import",
  "placements": [],
  "executionProfile": "sync",
  "interaction": "form",
  "bind": { "tables": ["items"] },
  "hostEffects": { "onSuccess": ["reloadTable"] },
  "inputSchema": {
    "type": "object",
    "required": ["filePath"],
    "properties": {
      "filePath": {
        "type": "string",
        "title": "导入文件",
        "description": "由宿主导入面板传入的 Excel/CSV 路径。",
        "format": "file"
      },
      "onError": {
        "type": "string",
        "title": "导入规则(出错时)",
        "enum": ["跳过该行,继续导入", "立即停止,不再导入后续行"],
        "default": "跳过该行,继续导入"
      }
    }
  },
  "entrypoint": {
    "type": "cli",
    "command": "item",
    "args": ["import", "--file", "{{filePath}}", "--on-error", "{{onError}}"]
  }
}

规则:

  • 全可选:无 replaces 时,宿主默认按钮仍直写库,行为与以前一致。
  • 取值:create(新增)/ update(编辑)/ delete(删除)/ import(导入写库)。
  • 必须非空 bind.tables;同一技能同一表同一 replaces 至多一个 Action。
  • 与 placements 正交:可只接管默认按钮(placements: []),不必再挂 toolbar「第二个新增/导入」。
  • 点默认「新增/编辑/删除」时走该 Action 的 interaction(create/update 常用 form;delete 常用 confirm)。
  • 点默认「导入」时固定打开宿主导入面板;确认后若有 replaces:import 则调用该 Action(interaction 不决定是否再弹技能表单)。
  • update / delete 可用 inputMapping($row.$pk、$selection.ids)预填主键。
  • import 约定:filePath(或 file)+ 可选 onError(skip/abort 或上例中文枚举);技能自行解析文件与表头。
  • 整表 _jiangchang_tables.readonly=1 时仍隐藏写按钮(优先于 replaces)。
  • 列元数据复用(lookup):Action 表单(含 toolbar/batch 弹窗与 create/update 抽屉)可将 inputSchema 字段对齐业务列,复用中文名与 lookup 下拉:
    • 优先让属性名 = 物理列名(如 platform_key);
    • 或 bind.columnMapping:{ "platform": "platform_key" };
    • 或字段上写 "column": "platform_key"。
    • 当前表没有对应列时,用字段内联 lookup(见下文「跨表引用:Lookup」)。
    • 不要在 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": "打开浏览器",
  "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": ["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/预填,作者须自觉。

Action 按钮中文名(label,参考)

label 是数据管理 toolbar / row / batch 以及技能详情直调上用户看见的短按钮名。本节是参考契约,不是白名单:行业专有动作(私信、审单、报关登记等)按业务起名。同类通用动作尽量用同一动词,避免每个技能一套叫法。

写法: 短中文,动词或「动词 + 对象」(约 2~8 字)。同一能力用一个 Action 换 placements,不要为入口复制同义按钮。

以后增补:在下表加行,并在模板 CHANGELOG.md 记一笔。废弃说法挪到「不要叫」,不要直接删行。

宿主已有,技能不要再做一套同义按钮

数据管理宿主已提供:查看 / 编辑 / 删除 / 新增 / 导入 / 导出 / 刷新。

技能要用 CLI 接管增删改导入时用 replaces(见上文),不要再把同义按钮挂到 placements: ["row"] 或 toolbar(例如「编辑平台」「删除 Key」与底下宿主「编辑」「删除」叠两套)。用户仍点宿主那几个字。

建议动词(有则用之)

类型 建议 label 不要叫 说明
基础设施 运行检查、查看版本、查看配置位置、初始化数据 健康检查、版本信息、配置路径、初始化数据库 多挂 skill-detail
打开 打开浏览器、打开目录、打开文件 打开文件位置、在资源管理器中打开、用浏览器打开 见下节静默成功
改库 新增…、编辑…、删除…、启用/停用、设置默认…、加入待…、重置为待… 表记录用「添加」;无必要拆成「启用」「停用」两个按钮 对象名可带,如「新增账号」
外源入库 同步数据、全量同步、采集…、扫描… 把宿主「刷新」叫成同步;把导出 CSV 叫成同步 默认用「同步数据」;全量才写「全量同步」
队列与探测 处理待…、测试 API、测试网页、抽检本条、抽检所选、批量抽检 行 / 勾选 / 工具栏三个入口都叫「抽检」 行=本条,勾选=所选,不管勾选的批量=批量
生成发布 生成 HTML、生成…、发布到… 用「导出」代替宿主表导出 固定 id render-html 的 label 用「生成 HTML」

打开类:一点即开,成功不提示

打开目录 / 打开浏览器 / 打开文件:interaction: "direct",executionProfile 通常 "sync"。

  • 成功:不要输出用户可见成功文案。若打印 JSON,令 "message": ""(宿主据此不弹「执行成功」)。操作系统已经弹出目录或浏览器,就是反馈。
  • 失败:仍 ERROR:<CODE>:(可加 HINT:)。
  • 不要用宿主「查看」表示打开目录或浏览器——「查看」是只读详情。

hoverHint(工具栏悬停,可选)

与 label / description / confirmation.message 独立。只决定数据管理顶栏技能按钮鼠标悬停时显示什么。

  • 省略 / 空白 ⇒ 不显示悬停,不回退灰色说明或确认黄条。
  • 短按钮名已经够懂时不要写,避免噪音。适合:业务黑话、会覆盖本机/远程、不点进去看不出后果。
  • 悬停文案不要写成「确认开始?」;那是点下去之后黄条的口吻。
  • 当前宿主实现为工具栏技能按钮;宿主内置删除/刷新/新增/导入/导出不走本字段。
  • 需宿主已支持 hoverHint;更旧宿主会忽略未知字段(模板 Schema 仍会校验新技能)。
{
  "id": "kb-sync-feishu",
  "label": "拉取到本机",
  "description": "把飞书知识库覆盖到本机工作区。未发布的本地修改会丢失。",
  "hoverHint": "将用飞书覆盖本机知识库,未发布的本地修改会丢失。",
  "placements": ["toolbar"],
  "executionProfile": "async",
  "interaction": "confirm",
  "confirmation": { "message": "将用飞书覆盖本机知识库,未发布的本地修改会丢失。确认开始?" },
  "bind": { "tables": ["kb_sources"] }
}

hostEffects / steps(执行前后宿主编排,≥2.8.5)

与 placements / executionProfile / interaction 正交。决定的是:数据管理里点完 Action 之后(或之前),宿主要不要刷新当前表、刷新目录、清空多选、级联删子表等。

  • 省略 / 空 ⇒ 宿主不额外改 UI(≥2.8.5 起不再对 mutation 硬编码刷新)。本地库若已由技能写新,界面仍可能旧,直到用户点内置「刷新」或本 Action 声明了 reloadTable。
  • 仅数据管理交互路径生效(toolbar / row / batch / skill-detail / replaces);cron 与 agent 忽略(与 interaction 相同)。
  • 需匠厂宿主 ≥ 2.8.5;更旧宿主会忽略未知字段(若未做严格 Schema 校验)。
  • 新技能优先写 steps;hostEffects 仍可作为「只刷 UI」的简写。两者可并存;同一 UI 效果若两边都声明,宿主可能各跑一次。

hostEffects(UI 副作用简写)

{
  "hostEffects": {
    "onSuccess": ["reloadTable"],
    "onFailure": ["clearSelection"]
  }
}
字段 触发时机
onSuccess sync 退出码 0;或 async 任务已被任务中心接收(不是 Job 跑完)
onFailure sync 失败;或 async 启动被拒

闭集 effect id:reloadTable(重载当前表 + 常伴随 Data Policy 再拉)、refreshCatalog(刷新技能目录)、clearSelection(清空多选)。未知 id 丢弃。

async 注意:sync-data 一类长同步若写 onSuccess: ["reloadTable"],会在入队成功时就刷表,可能仍是旧数据;更适合 sync 的新建/登记,或等 Job 真正完成后再刷(若宿主后续扩展完成回调)。

steps(有序编排,推荐)

{
  "steps": [
    { "when": "before", "do": "deleteByFk", "table": "child_rows", "fk": "parent_id" },
    { "when": "afterSuccess", "do": "reloadTable" },
    { "when": "afterFailure", "do": "clearSelection" }
  ]
}
when 含义
before 调用 CLI 之前
afterSuccess 同 hostEffects.onSuccess
afterFailure 同 hostEffects.onFailure
do 说明
reloadTable / refreshCatalog / clearSelection 同 hostEffects
deleteByFk 按外键批量删子表;须 table + fk;行按钮会把当前行主键当父键
deleteRows 删指定表行;须 table

规则:单次最多 8 步;未知步骤丢弃;deleteByFk / deleteRows 仅走 Skill Action steps 路径时可删 metadata_readonly 投影表(人工 CRUD 仍守只读)。整库只读 / 视图仍禁止写。

典型:业务表「新建 / 登记 / 更新」成功后加 { "when": "afterSuccess", "do": "reloadTable" },避免用户傻等旧表格。

{
  "id": "register-one",
  "label": "登记本行",
  "description": "更新当前行业务字段。",
  "placements": ["row"],
  "executionProfile": "sync",
  "interaction": "form",
  "bind": {
    "tables": ["business_records"],
    "inputMapping": { "recordId": "$row.$pk" }
  },
  "steps": [{ "when": "afterSuccess", "do": "reloadTable" }],
  "entrypoint": {
    "type": "cli",
    "command": "register",
    "args": ["--id", "{{recordId}}"]
  }
}

默认模板 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 必须:

  • 使用稳定的退出码
  • 成功时输出可解析的结构化结果
  • 例外(打开类):打开目录 / 打开浏览器 / 打开文件成功时不要输出用户可见成功文案;若打印 JSON,令 "message": ""。失败仍走下一款错误约定
  • 失败时输出稳定错误信息
  • 对可预期错误提供稳定错误码
  • 对用户可处理的问题提供 HINT
  • 不依赖 Agent 连续对话才能完成
  • 不自行实现宿主任务中心
  • 不在 CLI 中硬编码宿主安装目录
  • 不直接依赖某个具体 UI 页面

建议错误输出格式:

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

placements(入口位置)

值 含义
toolbar 数据管理表顶栏技能按钮(须配合 bind.tables)
row 数据管理行级入口(建议 bind.tables + inputMapping;表需有主键)。技能声明后,由宿主呈现为操作列链接、行右键菜单和/或行内「⋯」等壳;不新增 row-context-menu 等 placement
batch 数据管理批量操作(需勾选行;无勾选时宿主禁用按钮)
skill-detail 技能详情页直调(与安装/四 Tab 同属技能市场详情;已声明则须自测)
agent Agent 可直接调用(run_skill_action)
cron 定时任务「技能直调」

行级入口 row(宿主呈现契约)

  • 技能决定有什么:placements 含 "row"(且通过 bind.tables / policy 等过滤)的 Action,构成该表行的技能菜单项集合;配什么就出现什么。
  • 宿主决定怎么摆:可用操作列、行右键、行内「⋯」等呈现同一批 Action;点击均走同一 launch(placement: "row"),interaction / executionProfile 与壳无关。
  • 顺序:各壳内技能项顺序 = 下方「数据管理技能按钮顺序」契约(actions 数组相对顺序)。
  • 宿主内置项:查看 / 编辑 / 删除由宿主提供,不是技能 actions.json 配置出来的;若出现在行右键,须与技能项分组(例如分隔线后),且不得要求技能再配一份菜单 DSL。
  • 禁止:为右键单独发明 placement、菜单注册表或第二套 Action 列表。

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

宿主没有单独的 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 技能按钮一律渲染(顺序仍按本契约)。行级不以「顶栏溢出菜单」模型截断;行右键是 row 的正式呈现壳之一,不是 toolbar 式「更多操作」截断。
  6. 表顶栏宽窄布局(宿主行为,技能无需配置):
    • 够宽:左右各横排一行(左技能按钮 + 右宿主工具)。
    • 不够宽:保持左右分栏,栏内按钮上下竖排(左栏技能、右栏刷新/导出等)。

禁止:

  • 臆造 sortOrder / order / priority 等字段指望宿主排序(模板 Schema additionalProperties: false 会拒收)。
  • 臆造 tooltip / title 等字段当悬停(用可选 hoverHint;不要把 confirmation.message 复用成悬停)。
  • 依赖或宣传表顶栏「更多操作」溢出菜单(宿主已取消该能力)。
  • 把「表格行数据默认排序」与按钮顺序混淆——行排序见 SCHEMA.md 的 default_sort_json。
  • 把「默认展示列」与 visible=0 硬隐藏混淆——默认展示列见 SCHEMA.md 的 default_visible_columns_json。
  • 新增 row-context-menu 等 placement,或要求技能再维护一份与 row 平行的菜单清单。

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 特殊业务报告 vs HTML 页面

不要混用「导出」一词:

能力 语义 谁负责
同步数据(sync / refresh / collect) 外部来源 → 技能本地数据库 技能 Action / domain service
导出当前数据表 技能本地数据库 → CSV/Excel 等 数据管理页宿主统一导出
生成特殊业务报告(文件) 多表合并、特殊排版或附加计算的 xlsx/csv/json 等文件 仅当系统导出无法满足时,才提供独立 export-* Action;文件落 output/
HTML 页面报告 可在数据管理侧栏预览的整页 HTML 技能写入 {skill_data}/html/*.html + Action id render-html(见下节)

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

HTML 页面报告(数据管理预览)

一句话:技能负责生成并覆盖 html/*.html;宿主负责发现、预览、用 render-html 触发重新生成。

何时用

  • 需要可浏览的整页报告(KPI + 表格 + 自带样式),而不是再导出一张表
  • 与 export-* / 宿主表导出并列:HTML 走 html/;文件型特殊报告仍走 output/ + export-*

目录与发现(宿主契约)

项 约定
路径 {skill_data}/html/*.html,只扫一层(子目录忽略)
helper util.runtime_paths.get_html_dir();写入用 service.html_page_service.write_html_page
侧栏名 取文件内 <title>(缺省则用文件名)
预览 宿主 iframe 预览;右键:重新生成 / 浏览器打开 / 刷新
模板资源 建议放 assets/html/*.html(安装包内),渲染后写出到数据目录 html/

Action:render-html(固定 id)

宿主「重新生成」硬编码查找 Action id render-html(见 service.html_page_service.HOST_HTML_RENDER_ACTION_ID)。技能未提供该 id → 提示「该技能未提供生成 HTML」。

推荐形态:

字段 建议
id 必须 render-html
executionProfile sync
interaction direct
placements toolbar + skill-detail(配合表顶栏与 HTML 右键);可选 agent
bind.tables 数据来源表(含 toolbar 时必填);宿主从 HTML 页重新生成时会用 bind 补齐跑表上下文
steps afterSuccess → refreshCatalog(重扫 htmlPages;不要只 reloadTable)
entrypoint CLI 子命令(如 render-html)调用同一写入内核

完整 JSON 形状见 ../assets/examples/render-html.action.example.json。最小页面壳见 ../assets/html/example-report.html(已含数据管理 iframe 预览的布局基线;复制后可按需扩展 {{BODY}} 内结构)。

宿主预览布局

数据管理在 iframe 内预览 html/*.html;宿主 iframe 已占满右侧预览区,技能页不应再人为收窄正文(尤其数据管理窗口通常较窄)。

级别 约定
必须 页面横向铺满 iframe 可用宽度:main { width: 100%; min-width: 0; }
必须 禁止 main(或等价正文容器)使用 max-width: Npx 且无 margin: 0 auto(宽屏会左对齐留白;窄宿主窗浪费横向空间)
必须 html / body 设 overflow-x: hidden;滚动以纵向为主,避免横向滚动条
必须 写入 {{BODY}} 的业务数据经 html.escape(或等价)转义,防 XSS
应当 header 与 main 水平内边距一致(如共用 CSS 变量或 clamp())
应当 多列表格:width: 100% + 单元格 word-break / overflow-wrap,长文本在格内换行
应当 KPI / 卡片网格用 repeat(auto-fit, minmax(…, 1fr)) 等流体列,勿死写固定列数
禁止 在 <td> 上用 max-width 限制「说明列」等业务列(易导致列宽异常或横向溢出)
禁止 依赖外链 CSS/JS 或 networkidle 式加载(iframe sandbox 仅 allow-scripts;页面应自包含)

长文阅读型报告若确需版心,可对整个 main 使用 max-width 且 margin: 0 auto,并令 header 与 main 同宽;数据看板类默认不设 max-width。

实现要点

  1. 用 load_html_template + render_html_placeholders + write_html_page(原子 *.tmp + os.replace)覆盖同名文件;不要每次另存带时间戳的副本(除非产品明确要求历史版本)。
  2. 页头时间建议用写出时刻(「报告生成于」),不要误用业务表里过期的 generated_at 冒充「刚重新生成」。
  3. 可选:数据重算成功后调用静默写入(吞掉错误),保持侧栏报告与库一致。
  4. 权限:按业务决定谁能生成(管理员 / 角色);在 CLI/cmd_render_html 内强制校验。
  5. CHANGELOG / 用户说明:模板或样式升级后,提醒「请在数据管理对报告执行一次重新生成」。

验收(复制后自测)

  • html/ 下出现 .html,数据管理侧栏能看到报告项,预览正常
  • 预览区横向铺满、无横向滚动条;拖窄侧栏后内容自适应(见上节「宿主预览布局」)
  • 表顶栏(若声明 toolbar)或报告右键「重新生成」能跑通;成功后预览刷新
  • 未登录/无权限用户被拒绝,且有可读错误
  • 成功路径带 refreshCatalog(或等价让侧栏/预览看到更新)

inputSchema 与参数表单

跨表引用:Lookup(宿主已支持;勿让用户填编号)

当 Action 参数要引用同库另一张业务表的一行(话术模板、平台、账号等)时,必须用 Lookup 下拉,禁止做成「请填写编号」的数字框(用户记不住内部 id,体验差)。

场景 怎么配 说明
当前表已有同含义列,且列上已是 CRUD lookup column / bind.columnMapping,或属性名 = 列名 toolbar/batch 弹窗与 create/update 抽屉都会复用该列已解析的选项
当前表没有该列(如在「潜客」表上选「话术模板」) display_type: "lookup" + 字段内联 lookup 对象 打开表单时宿主按当前技能库解析选项

内联 lookup 与列元数据 options_json 同构(见 SCHEMA.md「跨表引用 lookup」):

{
  "templateId": {
    "type": "number",
    "title": "话术模板",
    "description": "仅在正文留空时生效;选 -- 表示自动挑选。",
    "display_type": "lookup",
    "lookup": {
      "ref_table": "message_templates",
      "value_column": "id",
      "label_column": "name",
      "extra_column": "channel",
      "filter_column": "is_active",
      "filter_value": 1
    }
  },
  "engineIds": {
    "type": "string",
    "title": "监测引擎",
    "description": "可多选;提交为逗号分隔编号。",
    "display_type": "lookup",
    "lookup": {
      "ref_table": "engines",
      "value_column": "id",
      "label_column": "display_name",
      "filter_column": "enabled",
      "filter_value": 1,
      "multiple": true
    }
  }
}
字段 必填 说明
ref_table 是 同库被引用表
value_column 是 提交给 CLI 的值(业务 id / 编号)
label_column 是 主文案列
extra_column 否 第三展示列(任意列名,不限「备注」)
filter_column / filter_value 否 等值过滤
multiple 否 true = 多选;省略/false = 单选(默认)

下拉/选项展示(宿主统一,技能只配列): 单选为 {value} · {label};有非空 extra_column 时为 {value} · {label}({extra})。例:2 · 通用私信-留资、2 · 通用私信-留资(dm)。

多选存值与模板: Action / CRUD 存 TEXT 逗号分隔 id(如 1,2,5);{{engineIds}} 原样替换进 CLI。多选字段在 inputSchema 里用 type: "string"(逗号串),不要用尚未稳定的 JSON array 当业务控件。

多选控件(宿主策略): 选项少(建议 ≤6)用勾选列表;选项多用字段内 Chip + 可搜索下拉(不是再开业务弹窗)。

可选「自动」(单选常见): 字段不要放进 required;不要用 minimum: 1 卡死留空。宿主会省略空的可选数字参数,避免「提交的数据无效」。

反模式(勿做):

  • 标题写成「某某编号」,说明里教用户去左侧表抄 id
  • 用静态 enum 罗列会增长/变更的业务行(会过期)
  • 在技能里自己拼假 label 列代替宿主统一格式(难维护)
  • 另造 lookup_multi / 第二套 display_type(应只加 multiple: true)

形状参考:assets/examples/lookup-action.example.json。

表单字段类型对照(须与 CRUD 对称)

Skill Action 弹窗与数据管理「新增 / 编辑」使用同一套控件语义。CRUD 侧配置见 SCHEMA.md「表单与展示:稳定字段类型」;本表只写 Action 怎么配。

控件语义 Action inputSchema 怎么写 CRUD 怎么写(对照)
单行文本 type: string display_type: text 或缺省
多行文本 display_type 或 format: textarea display_type: textarea
JSON 长文本 type: object/array(以 JSON 字符串编辑)或 textarea display_type: json / textarea
数字 type: number display_type: number 或 INT/REAL/NUMERIC
开关 type: boolean display_type: boolean
枚举下拉 enum: [...] options_json 数组
关联下拉(Lookup) 内联 display_type: lookup + lookup(可选 multiple),或绑列 同左;多选存 TEXT 逗号分隔 id
密码 sensitive: true 列 sensitive
日期(日) display_type 或 format: date display_type: date → 存 YYYY-MM-DD
日期时间 display_type 或 format: datetime_unix_seconds 同左;存/传 Unix 秒
URL(薄层) display_type 或 format: url display_type: url
Email(薄层) display_type 或 format: email display_type: email
说明灰字 description _jiangchang_columns.description
表格横幅 / 列头「?」 (无;Action 不用) _jiangchang_tables.grid_help / _jiangchang_columns.grid_help
默认值 default SQLite 列 DEFAULT
只读 readOnly: true 列 editable: 0 / 宿主只读规则
条件显隐 visibleWhen(见下节) 本版 CRUD 无对称;仅 Action / 定时任务参数表单
列筛选「值」 无对称(Action 无表格筛选) 见 SCHEMA.md「数据管理:列筛选与全局搜索」:枚举 / boolean / lookup 在筛选栏用下拉 Select(非开关、非分段单选);存库仍用 value,展示与搜索认 label

本版不做(勿宣传): 文件上传、复杂 oneOf / nested object 专用表单;visibleWhen 多条件 AND/OR 树、跨 Action 依赖、CRUD 新增/编辑对称显隐;Action 参数表单的列筛选对称。
(Lookup 多选已支持:同一 lookup + multiple: true,见上文;不是任意标签数组。)

日期时间约定:

  • Action 提交与 CRUD 写库统一用 Unix 秒整数(与 SCHEMA 标准时间字段一致)
  • date 只表示日历日,值为 YYYY-MM-DD
  • 脏/无法归一的旧预设:日期控件可回退为普通文本,避免卡死表单

当前宿主稳定支持(摘要)

  • 根:object;属性:string / number / boolean(object/array 仅作 JSON 多行编辑兼容,新技能慎用)
  • enum / default / required / sensitive / readOnly
  • display_type / format:textarea | date | datetime_unix_seconds | url | email | lookup
  • 字段内联 lookup(与 CRUD options_json lookup 对象同构;可选 extra_column、multiple)
  • 属性级 description(表单标签下方灰字说明)
  • 简单模板替换({{fieldName}})
  • 可选空数字字段提交时由宿主省略,避免 "" 触发 number 校验失败
  • 字段条件显隐 visibleWhen(可选):依赖同表单其它字段值决定是否展示;隐藏字段不进提交、不校验 required

字段条件显隐(visibleWhen)

用于「先选模式,再出对应参数」类表单。写在 inputSchema.properties.<field> 上(不是 action 顶层字段)。

消歧义: 本文的 visibleWhen = Action 参数表单控件显隐。
POLICY.md L3 预留的 visibleWhen = 行态/权限策略(未冻结),不是同一能力。勿混用、勿互相替代。

"keyword": {
  "type": "string",
  "title": "关键词",
  "visibleWhen": { "field": "collectMode", "equals": "按关键词采集" }
},
"authorUrl": {
  "type": "string",
  "title": "作者主页链接",
  "visibleWhen": { "collectMode": "按作者主页采集" }
}

支持形态:

写法 含义
{ "field": "x", "equals": "a" } x === a 时显示
{ "field": "x", "in": ["a", "b"] } x 属于集合时显示
{ "x": "a" } / { "x": ["a","b"] } 单键简写,同上

宿主行为(需已支持该字段的匠厂宿主;更旧版本会忽略未知字段 → 参数平铺全显):

  • 数据管理 / 定时任务参数表单按当前值求值并隐藏
  • 若依赖字段自身因 visibleWhen 隐藏,则下游字段一并隐藏(避免切模式后残留)
  • 提交与服务端 validateActionInput 会剥离隐藏字段;隐藏字段不校验 required
  • 无 visibleWhen 的字段保持始终可见(兼容旧技能)

形状参考:assets/examples/visible-when-action.example.json。

互斥模式优先用 visibleWhen,不要只靠 description 灰字写「仅某某时填写」。

与数据管理「新增 / 编辑」表单的分工(勿混用配置入口):

表单 短标题 说明灰字 默认值 控件类型
Skill Action 弹窗 inputSchema.title inputSchema.description inputSchema.default type + display_type/format
数据管理新增/编辑 _jiangchang_columns.display_name _jiangchang_columns.description 物理列 SQLite DEFAULT display_type + 物理类型推断

数据管理表格上方说明与列头「?」用 _jiangchang_tables.grid_help / _jiangchang_columns.grid_help(空则不渲染),不要用 description。见 SCHEMA.md「表格说明 grid_help」。

CRUD 侧宿主义务与禁止事项见 SCHEMA.md「表单与展示:稳定字段类型」「新增/编辑表单:字段说明与默认值」。同一业务含义两边文案与控件应对齐,但分别配置。

示例:

{
  "inputSchema": {
    "type": "object",
    "required": ["query"],
    "properties": {
      "query": {
        "type": "string",
        "title": "查询条件",
        "description": "支持关键词或完整业务编号"
      },
      "limit": {
        "type": "number",
        "title": "返回数量",
        "description": "最多返回多少条;填 0 表示不限制(若业务支持)",
        "default": 50
      },
      "dueDate": {
        "type": "string",
        "title": "截止日期",
        "display_type": "date",
        "description": "日历日,格式 YYYY-MM-DD"
      },
      "publishAt": {
        "type": "number",
        "title": "发布时间",
        "display_type": "datetime_unix_seconds",
        "description": "提交值为 Unix 秒"
      },
      "homepage": {
        "type": "string",
        "title": "主页链接",
        "display_type": "url"
      }
    }
  }
}

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

{
  "pickCount": {
    "type": "number",
    "title": "处理数量",
    "description": "从队列选取「可操作」状态记录的条数(具体状态名由本技能定义,见 WORK_ITEM_STATUS)"
  }
}

默认不要把失败/成功/跳过混进该 pick;重做靠人工改回可操作态。详见 WORK_ITEM_STATUS.md。

若还需要默认篇数,可在同一 properties 里为 pickCount 增加 "default": 1、"minimum": 1。

约定:

  • boolean 在宿主中渲染为开关
  • enum 在宿主中渲染为选择框
  • type: number 渲染为数字输入
  • display_type/format: date 渲染为日期(日);datetime_unix_seconds 渲染为日期时间并按 Unix 秒提交
  • display_type/format: url / email 为薄层输入类型(校验从宽,勿当强校验网关)
  • required 字段在提交前校验
  • sensitive 字段不得出现在低信任入口
  • readOnly: true 时数据管理表单只读展示该字段(仍随提交传入);适合行内/勾选预填的主键、编号列表
  • placements 含 batch 的动作在数据管理表顶常驻,无勾选时禁用(与表删除一致)
  • 需要确认的副作用操作使用 confirmation.message
  • 短名看不懂或会覆盖数据时,用独立的 hoverHint;不要把确认黄条复用成悬停
  • 模板参数使用 {{fieldName}},且必须在 inputSchema.properties 中声明
  • entrypoint.args 项当前只允许 string、number、boolean;不允许对象或 null
  • 不要在当前模板中宣传文件上传、任意 JSON 多选数组、oneOf、复杂 nested object 等尚未稳定支持的能力;Lookup 多选请用 lookup.multiple

风险与入口配置

  • 查询、诊断、版本检查可以放到 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 契约稳定。