From 917df04712a51253c0049047921c25161b0bdd50 Mon Sep 17 00:00:00 2001 From: chendelian <116870791@qq.com> Date: Wed, 15 Jul 2026 15:33:23 +0800 Subject: [PATCH] Precipitate generic Agent routing and how-to gold standards --- README.md | 3 ++- SKILL.md | 30 ++++++++++++++++++++++++++---- development/POLICY_MATRIX.md | 1 + references/ACTIONS.md | 17 +++++++++++++++++ references/CLI.md | 11 +++++++++++ scripts/util/constants.py | 2 +- tests/test_docs_standards.py | 31 +++++++++++++++++++++++++++++++ 7 files changed, 89 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 08b42c5..85469c1 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ description: "用用户能理解的方式说明这个技能能做什么、适合 > **模板说明(复制后删除本段)** > 本文是技能市场详情与普通用户说明,**不是** Agent 参考索引、CLI 契约或开发文档。 > frontmatter 的 `description` 必须是用户能看懂的一句话能力描述;**不得**写成 CLI、schema、references、development、契约、数据结构、开发规范或 Agent 参考索引。 -> 正文只回答用户关心的问题,**不要**把 Playwright、DOM、Python、RPA、references、development、schema 等作为面向用户的主说明内容;若业务上必须出现技术词,须用用户能理解的方式解释,且不能喧宾夺主。 +> 正文只回答用户关心的问题,**不要**把 Playwright、DOM、Python、RPA、references、development、schema 等作为面向用户的主说明内容;若业务上必须出现技术词,须用用户能理解的方式解释,且不能喧宾夺主。 +> **复制后验收章节(标题可微调,建议保留):**「能帮你做什么」「适合什么场景」「使用前需要准备什么」「你可以这样告诉 Agent」「执行后你会得到什么」「注意事项」「常见问题」。 # 【技能名称】 diff --git a/SKILL.md b/SKILL.md index 9daadbe..6827a8c 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,7 +1,7 @@ --- name: 技能开发模板(通用业务版) description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。" -version: 1.0.44 +version: 1.0.45 author: 深圳匠厂科技有限公司 metadata: openclaw: @@ -29,15 +29,28 @@ allowed-tools: - **`bind.tables`**:只决定数据管理出现在哪些表;含 `toolbar` 时**必须**显式非空绑定。 - **`executionProfile`**:只决定执行方式——`sync` 当场返回结果,`async` 进**任务中心**。与 placements / 入口**无关**;每个 Action **必须**显式写 `sync` 或 `async`。 - **同步数据**写技能本地库、不生成导出文件;**导出当前表**由宿主数据管理负责;特殊业务报告才另做 `export-*`。 +- **准备 vs 执行(适用则拆)**:若技能存在「先写入/准备本地数据」与「再对外产生副作用」两段,Agent 必须能分开触发;禁止默认绑成不可拆的一步。一键无准备态的技能可跳过本条。 -### 如何触发(决策树) +### 如何触发(能力类型) | 你要做什么 | Agent 怎么做 | 进任务中心? | |------------|--------------|--------------| | 短查询 / 只读 / 秒级(`health` / `version` / `stats` / `list` / `get` / `logs` 等) | OpenClaw bash/exec + **共享 Python** 跑 CLI(见下方「共享 Python」) | 否(CLI 当场结束) | | 已在 `actions.json` 声明且 `executionProfile: "sync"` 的能力 | 可用 `run_skill_action`,或同等效果的短 CLI(同一内核) | 否 | | 长耗时 / RPA / 浏览器 / 需要进度或取消;或 `executionProfile: "async"` | **必须** `run_skill_action`(先 `list_skill_actions` / `get_skill_action`) | **是**(仅因为该 Action 是 async) | -| 用户只问用法 / 能做什么 | 读根目录 `README.md`;技术细节读 `references/` | — | +| 用户只问用法 / 能做什么 | 读根目录 `README.md`;**不要**为答用法去列目录或默认打开 `references/` | — | + +### 用户意图路由表(业务技能复制后必改) + +复制为业务技能后,**必须**用本技能真实意图改写下表(保留三列结构)。格子写清:短 CLI 子命令,或 `run_skill_action` → **具体 action id**(及主要 `input`)。勿留模板占位语上线。 + +| 用户意图(本技能自填) | Agent 怎么做 | 进任务中心? | +|------------------------|--------------|--------------| +| (例)查询 / 统计 / 列表 | 短 CLI:`` | 否 | +| (例)写入 / 导入 / 改本地状态 | 短 CLI:`` | 否 | +| (例)长副作用 / RPA / 需进度 | `run_skill_action` → ``,`input.…` | 是(因该 Action 为 async) | + +有长任务 / RPA 时:上表至少一行指向真实的 async action id,且该 id 须出现在 `assets/actions.json`;细节分流见 `references/CLI.md`。 **硬规则:** @@ -46,6 +59,7 @@ allowed-tools: 3. **禁止** Agent 自行 `pip install`。 4. Action **可选**:无数据管理 / 定时 / Agent 结构化调用需求时可不提供 `actions.json`;有长任务 / RPA 时**必须**提供至少一条 `executionProfile: "async"` 且 `placements` 含 `agent` 的 Action。 5. **一个业务能力一个 Action**,用多个 `placements` 挂入口;底层仍是同一 `scripts/main.py` CLI。 +6. 是否进任务中心**只**看该 Action 的 `executionProfile`,与数据管理 / 定时 / Agent 入口无关。 Agent 执行契约细节:`references/CLI.md`、`references/ACTIONS.md`、`references/SCHEMA.md`(不要把 `development/` 当 Agent 主读路径)。 @@ -81,10 +95,18 @@ python {baseDir}/scripts/main.py init-db - 执行后会得到什么 - 能不能帮我完成某个业务任务 +**回答「怎么用 / 能做什么」时的要求:** + +1. 以 `README.md` 的「能帮你做什么」「你可以这样告诉 Agent」「常见问题」等章节为主组织回答。 +2. **禁止**在回答中粘贴 `python …/scripts/main.py …` 或其它命令行(除非用户明确索要命令,或自称技术人员/开发者)。 +3. **禁止**为答用法而去 `dir` / `ls` / 列技能目录,或默认打开 `references/`、`development/`;仅当用户明确问命令、参数、集成或排错时再读 `references/`。 +4. **不要**向普通用户暴露 Playwright、DOM、Python、RPA、库表名、`error_code` 等实现细节,除非用户明确询问技术实现。 + +**文档读取边界:** + - **不要**把 `SKILL.md`、`references/`、`development/` 中的技术细节直接作为用户回答。 - **只有当**用户明确询问命令、参数、输出结构、开发、调试、集成或排错时,才读取 `references/`;`development/` 主要给开发者 / 编码助手,对话 Agent **不必**默认打开。 - 若 `README.md` 与 `SKILL.md` / `references` 表述冲突:对用户展示与市场说明以 `README.md` 为准;对执行契约以 `SKILL.md` / `references` 为准。 -- 回答用户时**不要**暴露 Playwright、DOM、Python、RPA 等实现细节,除非用户明确询问技术实现。 - 用户未问技术实现时,**不要**讨论 slug 命名规则;开发者问命名或 slug 时,读取 `development/NAMING.md`。 ## 文档分工 diff --git a/development/POLICY_MATRIX.md b/development/POLICY_MATRIX.md index 9367600..fa17f60 100644 --- a/development/POLICY_MATRIX.md +++ b/development/POLICY_MATRIX.md @@ -8,6 +8,7 @@ | POLICY-RUNTIME-001 | 不得 vendored `scripts/jiangchang_skill_core/` | development/RUNTIME.md §共享 Python Runtime、§明确禁止 | hard | 目录不存在检查 | `tests/test_development_policy_guard.py::TestPolicyRuntime001`(另见 `tests/test_platform_import.py`) | | POLICY-RUNTIME-002 | `requirements.txt` 非注释依赖行不得声明 `jiangchang-platform-kit` / `playwright` | development/RUNTIME.md §共享 Python Runtime;development/DEVELOPMENT.md §3.1 requirements.txt 依赖规范 | hard | 解析依赖行 | `tests/test_development_policy_guard.py::TestPolicyRuntime002`(另见 `tests/test_platform_import.py`) | | POLICY-RUNTIME-003 | Agent/CLI 文档须要求共享 Python(python-runtime / PATH 上的 `python` + `{baseDir}`);须明确**禁止**对技能脚本使用 `uv run python` | development/RUNTIME.md;references/CLI.md;SKILL.md | hard | 文档标记扫描 | `tests/test_docs_standards.py::test_cli_md_requires_shared_python_not_uv_run`;`tests/test_docs_standards.py::test_skill_md_requires_shared_python_not_uv_run` | +| POLICY-AGENT-001 | `SKILL.md` 须含「用户意图路由表」结构;`CLI.md` 须含短 CLI 白名单 / Action 强制黑名单表;用法回答须禁止无故粘贴 CLI、禁止为答用法列目录挖 references | SKILL.md;references/CLI.md | hard | 文档标记扫描 | `tests/test_docs_standards.py::test_skill_md_has_intent_routing_table`;`tests/test_docs_standards.py::test_cli_md_has_agent_routing_tables`;`tests/test_docs_standards.py::test_skill_md_how_to_forbids_cli_paste` | | POLICY-INSTALL-001 | 交付执行文件不得含 `pip install` / `python -m pip install` / `uv pip install` / `playwright install` | development/RUNTIME.md §共享 Python Runtime;development/RPA.md §1.4 Playwright 与安装边界;development/DEVELOPMENT.md §3.1 | hard | 扫描 `scripts/**/*.py`、`*.ps1`、`*.sh`、`requirements.txt`、`.github/workflows/*`(不扫 `development/*.md`) | `tests/test_development_policy_guard.py::TestPolicyInstall001` | | POLICY-CONFIG-001 | 仓库根目录必须存在 `.env.example` | development/CONFIG.md §核心原则、§标准配置项 | hard | 文件存在性 | `tests/test_development_policy_guard.py::TestPolicyConfig001` | | POLICY-CONFIG-002 | `.gitignore` 必须忽略 `.env` 与 `*.env.local` | development/CONFIG.md §红线:敏感信息不进 .env | hard | 解析 `.gitignore` 行 | `tests/test_development_policy_guard.py::TestPolicyConfig002` | diff --git a/references/ACTIONS.md b/references/ACTIONS.md index 92a3a7d..3240f21 100644 --- a/references/ACTIONS.md +++ b/references/ACTIONS.md @@ -18,6 +18,23 @@ 禁止对长任务 `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` 为域(如 ``),业务动词与参数放在 `args` 数组(如 `["", "--flag", "{{field}}"]`)。与扁平入口等价,须仍指向同一 domain service。 + ## 模板严格规范 vs 宿主向后兼容 | 角色 | 定位 | diff --git a/references/CLI.md b/references/CLI.md index 037af2d..5e8f09d 100644 --- a/references/CLI.md +++ b/references/CLI.md @@ -18,6 +18,17 @@ python {baseDir}/scripts/main.py … **禁止**对技能脚本使用 `uv run python …`(会创建临时环境,加载不到 `jiangchang-platform-kit` / `jiangchang_skill_core`)。 **禁止** Agent 自行 `pip install` / `uv pip install` 往临时环境塞依赖。 +## Agent 分流(业务技能复制后必改) + +用本表列出**本技能**哪些子命令可走短 CLI,哪些必须走 Skill Action。默认:短查询/只读写本地可用短 CLI;长耗时 / RPA / 需进度取消进**黑名单**。有 async/RPA 的技能:**黑名单不得为空**,且黑名单命令须映射到 `actions.json` 中的 async Action。 + +| 类型 | 本技能命令(自填) | Agent | +|------|--------------------|-------| +| **短 CLI 白名单** | (例)`health` / `version` / `logs` / `` | 可用 bash/exec + 共享 `python` | +| **Action 强制黑名单** | (例)`` | **禁止** bash + `process poll`;必须 `run_skill_action` | + +细节与 Action 清单见 [`ACTIONS.md`](ACTIONS.md)。 + ## 最小命令 ```bash diff --git a/scripts/util/constants.py b/scripts/util/constants.py index 4901642..6583902 100644 --- a/scripts/util/constants.py +++ b/scripts/util/constants.py @@ -1,6 +1,6 @@ """技能标识、版本与平台公共库约束(复制后请修改 slug/version/logger)。""" SKILL_SLUG = "your-skill-slug" -SKILL_VERSION = "1.0.44" +SKILL_VERSION = "1.0.45" LOG_LOGGER_NAME = "openclaw.skill.your_skill_slug" PLATFORM_KIT_MIN_VERSION = "1.2.0" diff --git a/tests/test_docs_standards.py b/tests/test_docs_standards.py index 92123db..bcc7378 100644 --- a/tests/test_docs_standards.py +++ b/tests/test_docs_standards.py @@ -315,6 +315,12 @@ class TestDocsStandards(unittest.TestCase): msg="CLI.md must not recommend uv run for skill scripts", ) + def test_cli_md_has_agent_routing_tables(self) -> None: + text = self._read("references/CLI.md") + self.assertIn("短 CLI 白名单", text) + self.assertIn("Action 强制黑名单", text) + self.assertIn("run_skill_action", text) + def test_skill_md_requires_shared_python_not_uv_run(self) -> None: text = self._read("SKILL.md") self.assertIn("python {baseDir}/scripts/main.py", text) @@ -328,6 +334,31 @@ class TestDocsStandards(unittest.TestCase): msg="SKILL.md must state Task Center is independent of entry point", ) + def test_skill_md_has_intent_routing_table(self) -> None: + text = self._read("SKILL.md") + self.assertIn("用户意图路由表", text) + self.assertIn("用户意图", text) + self.assertIn("准备 vs 执行", text) + + def test_skill_md_how_to_forbids_cli_paste(self) -> None: + text = self._read("SKILL.md") + self.assertIn("回答「怎么用", text) + self.assertIn("禁止", text) + self.assertTrue( + "粘贴" in text and "python" in text, + msg="SKILL.md must forbid pasting python CLI when answering how-to", + ) + self.assertTrue( + "dir" in text or "列" in text, + msg="SKILL.md must discourage directory probing for how-to answers", + ) + + def test_actions_md_has_async_side_effect_checklist(self) -> None: + text = self._read("references/ACTIONS.md") + self.assertIn("最小组合", text) + self.assertIn("confirmation.message", text) + self.assertIn("用户意图路由表", text) + def test_actions_md_states_profile_not_entry_for_task_center(self) -> None: text = self._read("references/ACTIONS.md") self.assertIn("executionProfile", text)