# Skill Action Manifest(匠厂宿主) 本文件说明 `assets/actions.json` 与 `scripts/main.py` CLI 的对应关系,供 Agent 编排与宿主 **Skill Action Runtime** 使用。 **权威运行时契约(sync/async、任务中心、单内核编排)见 [`../development/SKILL_ACTION_RUNTIME.md`](../development/SKILL_ACTION_RUNTIME.md)。** **边界:** 用户市场说明见根目录 [`README.md`](../README.md);CLI 参数与错误码细节见 [`CLI.md`](CLI.md)。 ## 模板严格规范 vs 宿主向后兼容 | 角色 | 定位 | |------|------| | **skill-template** | 新技能推荐的**严格规范**:必填字段、明确类型、`additionalProperties: false` | | **宿主运行时** | **向后兼容**的历史 manifest 解析器:可能接受部分缺省字段(如 `description`、`placements`、`entrypoint.args`、缺失的 `bind.tables`) | **新技能不应依赖宿主缺省行为。** 复制模板后按 [`assets/schemas/skill-actions.schema.json`](../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`)。 ## 文件位置 ```text {skill_root}/assets/actions.json ``` 宿主扫描路径示例: ```text ~/.openclaw/skills/your-skill-slug/assets/actions.json ``` ## 顶层结构 | 字段 | 必填 | 说明 | |------|------|------| | `schemaVersion` | 是 | 当前固定为 `1` | | `skill` | 是 | 必须与 `SKILL.md` 的 `metadata.openclaw.slug` 一致 | | `actions` | 是 | Action 数组,每项 `id` 唯一 | 模板最小示例见 [`assets/actions.json`](../assets/actions.json);JSON Schema 见 [`assets/schemas/skill-actions.schema.json`](../assets/schemas/skill-actions.schema.json)。 ## 五职责正交(必读) | 字段 / 层 | 只决定什么 | 不决定什么 | |-----------|------------|------------| | **`placements`** | Action **出现在哪里**(toolbar / cron / agent / skill-detail …) | 不决定 sync/async | | **`bind.tables`** | 数据管理里出现在**哪些业务表** | 不决定业务实现 | | **`executionProfile`** | 宿主是**同步等待**还是**异步 Job** | 不限制可展示入口 | | **`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`、**`bind`** | | entrypoint | `type = cli`、`command`、`args`(**必填** JSON 数组,项为 `string` / `number` / `boolean`) | | placements | `toolbar`、`skill-detail`、`agent`、`cron` | | **bind** | `{ "tables": ["business_table"] }`(见下节) | | inputSchema | 根 `type: object`;properties 使用 `string` / `number` / `boolean`;支持 `enum`、`default`、`required`、`sensitive` | | confirmation | `{ "message": "..." }` | | **executionProfile** | `"sync"` \| `"async"`(**必须显式写出**,禁止依赖缺省) | ## `bind.tables`(表级绑定) ```json { "bind": { "tables": ["business_table"] } } ``` 规则: - `bind` 为 object,`additionalProperties: false`;当前只允许 `tables`。 - `tables` 非空数组、元素唯一、英文 **snake_case**、不得为空字符串。 - **`placements` 含 `toolbar` 时必须显式声明非空 `bind.tables`**(模板 Schema `if/then` + 自动测试强制)。 - 表名须真实存在于技能 SQLite 与 `_jiangchang_tables`。 - 希望出现在多张表时,显式列出所有表;**不要**依赖「无 bind 则全表展示」——那是宿主对**旧技能**的兼容,不是新技能标准。 - 本阶段**不**扩展 `selection` / `inputMapping` / `columns` / row binding / concurrency / locks。 默认模板 `actions.json` 仅含 `health` / `version` / `config-path`,不放在 toolbar,故无需 `bind` 示例污染默认 manifest。业务示例: ```json { "id": "sync-records", "label": "同步记录", "description": "从外部来源同步到技能本地数据库,不生成导出文件。", "placements": ["toolbar", "cron", "agent", "skill-detail"], "executionProfile": "async", "bind": { "tables": ["business_records"] }, "entrypoint": { "type": "cli", "command": "sync-records", "args": [] } } ``` ## 预留能力(当前不可当作已实现能力) | 类别 | 预留项 | 说明 | |------|--------|------| | placements | `row`、`batch` | 行内 / 批量入口,未来扩展;新技能示例不得使用 | | action 字段 | `concurrency`、`locks` | 并发与锁控制,未稳定开放 | | inputSchema | `array`、nested `object`、`oneOf` 等 | 复杂表单,不属于当前推荐范围 | `bind` **不是**保留字段;已作为 Phase 1 表级绑定正式能力。 ## 执行模型 宿主将 action 转为 argv,再执行: ```text python {skill_root}/scripts/main.py ``` - `entrypoint.type` 当前只支持 `cli` - `entrypoint.command` → CLI 子命令(须真实存在) - `entrypoint.args` → 子命令参数(**必须为 JSON 数组**) - `{{fieldName}}` → 来自 `inputSchema` 用户输入的简单模板替换 完整子命令定义见 [`scripts/cli/app.py`](../scripts/cli/app.py)。 ### `executionProfile`(仅 sync / async) 模板与新技能**只允许**这两种值;禁止发明 `auto` / `background` / `deferred` 等第三种模式。 | 值 | 宿主行为 | 任务中心 | |----|----------|----------| | `sync` | 调用方等待结束,直接返回结构化结果或结构化错误;**不**创建后台 Job | 不进 | | `async` | 宿主创建后台 Job,立即返回 `jobId`;用 `emit` / `checkpoint` / `finish` 报告进度与终态 | **进入** | 合法组合(全部允许):`sync|async` × `toolbar|cron|agent|skill-detail`。 经验建议(**不是** placement 硬限制):耗时不可预测、需要暂停/停止/进度展示的任务,建议用 `async`。 直接执行 CLI 时,终端自然等待进程结束;宿主通过 Action 调用同一 CLI 时,再按 `executionProfile` 决定同步等待还是建 Job。技能**不得**自行实现第二套任务中心或后台队列。 ### CLI 输出契约 技能 CLI 必须: - 使用稳定的退出码 - 成功时输出可解析的结构化结果 - 失败时输出稳定错误信息 - 对可预期错误提供稳定错误码 - 对用户可处理的问题提供 `HINT` - 不依赖 Agent 连续对话才能完成 - 不自行实现宿主任务中心 - 不在 CLI 中硬编码宿主安装目录 - 不直接依赖某个具体 UI 页面 建议错误输出格式: ```text ERROR:: HINT: ``` ## placements(入口位置) | 值 | 含义 | |----|------| | `toolbar` | 数据管理第一排技能按钮(须配合 `bind.tables`) | | `skill-detail` | 技能详情或技能市场详情页 | | `agent` | Agent 可直接调用(`run_skill_action`) | | `cron` | 定时任务可直接调用 | **预留(模板示例请勿使用):** `row`、`batch`。 ### 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 | 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`](SCHEMA.md) 与 [`../development/SKILL_ACTION_RUNTIME.md`](../development/SKILL_ACTION_RUNTIME.md)。 ## inputSchema 与参数表单 当前宿主稳定支持: - `object` / `string` / `number` / `boolean` - `enum` / `default` / `required` / `sensitive` - 简单模板替换(`{{fieldName}}`) 示例: ```json { "inputSchema": { "type": "object", "required": ["query"], "properties": { "query": { "type": "string", "title": "查询条件" }, "limit": { "type": "number", "title": "返回数量", "default": 50 } } } } ``` 批量 pick 参数约定(有队列表时): ```json { "pickCount": { "type": "number", "title": "处理数量", "description": "从队列选取 pending 记录条数", "default": 1, "minimum": 1 } } ``` 约定: - `boolean` 在宿主中渲染为开关 - `enum` 在宿主中渲染为选择框 - `required` 字段在提交前校验 - `sensitive` 字段不得出现在低信任入口 - 需要确认的副作用操作使用 `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 契约稳定。