helleOPP/anycross-skill-creator

GitHub: helleOPP/anycross-skill-creator

通过对飞书 AnyCross 工作流文件格式进行逆向工程,提供完整的 schema 文档、校验脚本和 AI Agent Skill,帮助开发者和 AI 可靠地生成、验证和导入自动化工作流。

Stars: 1 | Forks: 0

# AnyCross Creator — 从 `flow.json` 构建 Lark AnyCross 工作流 这是针对 **AnyCross** 工作流文件格式(`flow.json`)的文档和工具集,被打包为一个 **AI agent skill**,用于生成、验证 AnyCross 工作流,并将其打包为可导入的 `.zip` 文件。 AnyCross 是 Lark/飞书的自动化平台(类似于 Zapier 或 Make)。它没有针对导出的工作流文件提供公开的 schema 文档——所以这里的一切都是从**真实运行中的导出文件逆向工程**得出的:connector ID、operation ID、节点结构、四种 spel 引用类型、LarkBase 字段的读写格式,以及你在此过程中会遇到的各种错误信息。 ## 兼容任何 AI 编程 agent — 也可完全脱离 AI 使用 其打包方式遵循 [Agent Skills](https://code.claude.com/docs/en/skills) 规范(一个 `SKILL.md` 加上辅助文件),[Claude Code](https://claude.com/claude-code) 会自动加载它。但**内部没有任何内容是 Claude 专属的**: | 层级 | 内容 | 可移植性 | |---|---|---| | `SKILL.md` | 纯 Markdown 格式的构建流程 | 任何能读取指令的 agent — Cursor、Copilot、Codex、Gemini CLI、Windsurf、Cline。将其作为上下文或系统提示词粘贴即可。 | | `references/` | AnyCross schema 文档 | 任何环境。它只是 Markdown。你可以将其输入给你的模型,或者自己阅读。 | | `scripts/` | `inspect_export.py`, `validate_flow.py`, `pack_flow.py` | 纯 Python 3.8+,仅使用标准库。不涉及 AI — 从终端或 CI 任务中运行它们即可。 | 因此你可以通过三种方式使用它:让一个 agent 驱动整个流程、将参考文件作为上下文交给你的模型,或者完全忽略 AI 部分,手动使用这些脚本和文档。 这是一个**文档优先**的项目,只是碰巧以 skill 的形式发布 — schema 知识才是核心资产,无论你将它指向哪个 agent,这些知识都能长久适用。 ## 为什么会有这个项目 手动编写 AnyCross 的 `flow.json` 非常困难且容错率极低。逻辑部分其实很简单——真正的陷阱在于**每个 connector ID、operation ID、credential ID 和参数结构都是特定于租户和版本的**。 实际环境中存在两个 Bitable connector: | 版本 | connectorId | “更新记录 (update a record)” 的 operationId | |---|---|---| | v2.0 | `7241926900765982725` | `7241926901814525957` | | v2.7 | `7576576101812538807` | `7576576102517181878` | 不同的 ID、不同的 operation ID,*同一个操作对应的参数名也各不相同*。LLM 如果靠猜来生成这些 ID,产出的 zip 文件要么无法导入,要么——更糟糕的是——顺利导入却在暗中执行错误的操作。 因此,这个 skill 的核心原则只有一条:**从真实的导出文件中复制 ID,永远不要依赖记忆。** 其中的所有内容都是从真实运行中的 AnyCross 导出文件逆向工程得出的,而不是仅仅依赖文档。 ## 安装 ``` git clone https://github.com/helleOPP/anycross-skill-creator.git ``` 环境要求:**Python 3.8+**。无需第三方包 — 仅使用标准库。 **Claude Code** — 将文件夹放入 skills 目录中,它会自动加载: ``` cp -r anycross-skill-creator/anycross-creator ~/.claude/skills/ # every project cp -r anycross-skill-creator/anycross-creator /path/to/project/.claude/skills/ # one project ``` 检查是否已通过 `/anycross-creator` 注册。 **Cursor / Copilot / Codex / Gemini CLI / 其他任何 agent** — 无需安装插件。只需将你的模型指向这些文件: - 将 `anycross-creator/SKILL.md` 作为上下文、系统提示词或规则文件(如 `.cursorrules` 等)粘贴进去。 - 当它开始构建时,把相关的 `references/*.md` 也提供给它 — `connectors.md` 和 `flow-schema.md` 包含了各种 ID 和结构,如果不提供,模型可能会自己凭空捏造(产生幻觉)。 **完全不用 agent** — 这些脚本完全可以独立运行: ``` python anycross-creator/scripts/inspect_export.py "My Flow.zip" ``` ## 使用方法 只需描述你想要的自动化流程即可。当你提到 AnyCross、`flow.json` 或 Lark 自动化时,该 skill 就会自动触发: 然后 Claude 会执行一个包含五个步骤的循环流程: | 步骤 | 具体内容 | 重要性说明 | |---|---|---| | **0. 请求模板** | Claude 要求你提供当前租户中已在运行的任意工作流的 `.zip` 导出文件 | 这是最关键的一步 — 见下文 | | **1. 常量** | 收集 `app_token`、`table_id`、凭证 — 或者将它们关联到 AnyCross **项目变量**,这样文件中就不会残留任何租户 ID | 保持工作流的可移植性且不泄露机密信息 | | **2. 生成** | 编写一个生成 `flow.json` 的 Python 生成器脚本 | 与手动编辑的 JSON 相比,这种方式具备可复现性且易于审查 | | **3. 验证** | 运行导入前的检查项(见下文) | 能在几秒钟内发现那些在 UI 中需要花好几分钟才能找到的问题 | | **4. 测试与学习** | 你导入文件并逐字报告任何错误;Claude 负责诊断、修复,**并将经验教训写入 skill 中** | skill 在每次失败后都会变得更聪明 | | **5. 报告** | 告诉你构建了什么、依赖哪些内容,以及哪些部分尚未验证 | 绝不做无声的猜测 | ### 第 0 步是重中之重 如果你在同一租户中已经有*任何*正在运行的 AnyCross 工作流,请将其导出并提供文件路径。这能让 Claude 免费获取: - 你的租户中已安装的确切 connector 版本 - 可用的 credential ID - 每个操作真实的参数名 - 能够真正解析的 spel 引用路径 如果没有模板,Claude 会退而使用内置清单,并且会坦白地告诉你,第一次导入只是一次试探,而不是最终交付。 ### 第 4 步是促使它不断改进的关键 Claude 无法看到 AnyCross 的 UI — 你是它唯一的感知来源。当出现错误时,它会要求你提供具体信息(红色横幅上的原样文本、失败节点的 **Input** 面板、上一个节点的 **Output** 面板),因为这些信息能展示数据的真实形态,而不是它的猜测。 一旦诊断出问题,该经验教训就会作为一类错误(而不是个别偶然事件)被追加到 `references/known-errors.md` 中,这样下一次构建时就能避开它,而不是重新踩坑。 ## 这些脚本 这三个脚本都是独立运行的 — 无需 Claude 即可使用。 **检查真实导出文件** — 这是防止模型幻觉的工具。它会打印出每个节点的 connector 名称/版本、connectorId、operationId、参数键、凭证,以及可选的每一个 spel 引用: ``` python anycross-creator/scripts/inspect_export.py "My Flow.zip" python anycross-creator/scripts/inspect_export.py "My Flow.zip" --spel python anycross-creator/scripts/inspect_export.py "My Flow.zip" --node bitable-1 ``` **导入前验证** — 检查 UTF-8 编码有效性、`structure` 与 `steps` 的一致性(包括嵌套的 `subSteps`)、节点结构(是否存在 `operation`,是 `js_code` 而不是 `code`,凭证是否位于 `auth` 下而不是 `parameters` 下),以及每个 node_tree 类型的 spel 偏差: ``` python anycross-creator/scripts/validate_flow.py out/flow.json ``` 它是根据真实的生成环境导出文件进行校准的,因此报错意味着存在真正的缺陷,而不是某种代码风格的主观意见。顺利通过验证意味着 zip 文件**可以导入** — 但这并不代表工作流本身是*正确无误的*;错误的 operation ID 和错误的字段名能通过所有的静态检查,但在运行时就会报错。 **打包** — 验证通过后,将其封装为可导入的 zip 文件(并且会拒绝打包未通过验证的工作流): ``` python anycross-creator/scripts/pack_flow.py out/flow.json "out/My Workflow.zip" ``` ## 目录结构 ``` anycross-creator/ ├── SKILL.md # the workflow Claude follows ├── references/ │ ├── flow-schema.md # flow.json anatomy: structure/steps, node shape, │ │ # value types, the four spel types, loop/branch/while │ ├── connectors.md # verified connector/operation inventory │ ├── larkbase.md # Bitable field read/write formats, filters, extract() helpers │ ├── integrations.md # HTTP, Lark card, Google Docs, e-signature, subflow, cron │ └── known-errors.md # the error ledger — read before debugging, append after ├── scripts/ │ ├── inspect_export.py # harvest IDs from a real export │ ├── validate_flow.py # pre-import checks │ └── pack_flow.py # validate + zip └── assets/ └── generator_skeleton.py # starting point, with all the value-type helpers ``` ## 那些花了很多时间才学到的经验 - **Node ID 存放在 `operation` 对象内部** — 即 `{connectorId, operationId, connectorName, connectorVersion}` — 而不是在节点的最外层。 - **Script 节点的输出会统一放在 `.result` 命名空间下。** 如果在 `script-2` 中某个 handler 返回了 `{rows: [...]}`,它会被解析为 `$.script-2.result.rows`,而不是 `$.script-2.rows`。如果弄错了,引用会被静默解析为 null — 不会报错,但下游获取到的数据全都是空的。 - **spel 有四种 `node_tree` 类型**,只有 `json_path` 会在 `expression` 中重复完整路径。`project_var` 和 `flow_variable` 的路径是相对的(例如 `$.config.x.y` 对应的路径是 `x.y`),这看起来像是个 bug,但其实不是。 - **`$.config.*` 项目变量**能让你彻底将 `app_token`/`table_id` 从工作流文件中剥离出来 — 它们的值保存在 AnyCross 项目设置中,因此同一份 JSON 可以原封不动地在不同环境间迁移。 - **非 ASCII 字符*不是*导致导入失败的原因。** 一个广为流传的说法称,越南语字符或 emoji 会导致 `Unable to parse uploaded file`。这是错误的 — AnyCross 自己的 UI 导出文件里就包含大量原始的非 ASCII 字符。真正的限制条件是**有效的 UTF-8 编码**;通常的罪魁祸首是在写入文件时使用了系统区域设置的编解码器(例如 Windows 上的 cp1252)。`ensure_ascii=True` 依然是个不错的默认选项,但这只是一种廉价的防御措施,而不是什么禁忌。 - **LarkBase 的读取结构并不等于写入结构。** 一个 Person(人员)类型的字段在写入时必须作为原始的对象数组传回,而不能只传提取出来的名字。URL 字段则需要传入 `{link, text}` — 如果只传一个纯字符串会返回 `URLFieldConvFail`。 更多内容请见 `references/known-errors.md`,里面的每一条记录都是作为可复用的错误类型来编写的。 ## AnyCross 错误排查 以下这些错误都曾耗费了我们大量的时间去排查,这里提供的是真正的原因,而不是那些道听途说的传闻。完整的记录及背后的推理过程,请见 [`references/known-errors.md`](anycross-creator/references/known-errors.md)。 ### "Unable to parse uploaded file"(无法解析上传的文件) 你的 `flow.json` 不是有效的 UTF-8 编码。在 Windows 上,通常是因为使用了没有加 `encoding=` 参数的 `open(path, "w")`,这会通过 cp1252 区域编解码器写入文件,从而损坏任何非拉丁语系的文本。 **这*不是*由非 ASCII 字符引起的**,尽管这个说法被广泛流传。AnyCross 自己的 UI 导出文件里就充满了原始的越南语和 emoji。请使用 `encoding="utf-8"` 写入,或者如果你想让编解码器问题彻底不复存在,可以使用 `ensure_ascii=True` 进行转储。 ### `URLFieldConvFail` 你往 LarkBase 的 URL 字段里写入了一个纯字符串。它需要的是一个对象: ``` {link: "https://example.com", text: "Open"} // even when link and text are identical ``` ### Person 字段写入后变成空白,或者节点直接拒绝了该值 你读取了 Person 字段,通过 `extract()` 将其转为了显示名称,然后又把这个字符串写了回去。LarkBase 需要的是它当初给你的那个对象数组 — 请将 `f[''] || []` 原封不动地传过去。读取结构和写入结构是完全不同的两码事。 ### spel 引用被静默解析为 null 没有报错,但下游数据为空。通常有三种原因: 1. **缺少了 `.result`** — script 节点的输出带有命名空间。如果 handler 在 `script-2` 中返回了 `{rows: [...]}`,那么对应的引用是 `$.script-2.result.rows`,而不是 `$.script-2.rows`。 2. **`expression` 和 `node_tree.path` 不一致**,因为只修改了其中一个。应该从同一个变量生成这两者。 3. 引用的节点 ID 不存在 — 可能是拼写错误,或者是代码重构时重新编了号。 `validate_flow.py` 可以捕获第 (2) 和第 (3) 种情况。 ### Script 节点导入后内容为空 参数的键名应该是 `js_code`,而不是 `code`。 ### 在一个明显有数据的 Bitable 表中搜索却什么也没返回 要么是 operation ID 属于另一个版本的 Bitable connector(v2.0 和 v2.7 对应同一个操作的 ID *和* 参数名都不一样),要么是你的过滤器中包含一个空的 `conditions` 数组 — 空数组的意思是“没有过滤条件,返回所有数据”,而不是“什么都不匹配”。 ### `im` 节点无法向群组发送消息 该凭证背后的机器人并不是目标会话的成员。再怎么修改 JSON 都无济于事 — 请在 Lark 中将该机器人添加到目标群组里。 ## 已验证 vs. 未验证 该 skill 对自身的置信度非常明确, README 也是如此: - **已验证**(经过真实导出文件验证):Bitable(包含两个版本的 connector)、script、http-client GET、cronjob、webhook、im(Lark 卡片)、card_helper、contact、subflow、loop/branch/while、variable、delay、terminate。 - **未验证** — 继承自早期版本,且从未通过真实导出文件进行过验证:`http-client` 的 POST/PUT operation ID、Google Docs、Google Drive 以及 Zoho Sign 相关的模式。 如果你有使用任何未经证实的 connector 的导出文件,提一个 issue 或包含 `inspect_export.py` 输出结果的 PR,这将有助于为所有人确认这些信息的可靠性。 ## 许可证 [MIT](LICENSE) — 随你使用、分支、修改,无论是否用于商业用途,都可以在你自己的项目中发布。只需保留版权声明即可。不提供任何担保。 ## 联系方式 在工作流上遇到困难,或者想为你定制构建一个工作流?请随时联系 — **phucvn2019@gmail.com** 我为中小企业构建自动化和分析系统:Lark/飞书(AnyCross、Lark Base)、n8n 以及 BI/报表 — 主要围绕**供应链和运营管理**,因为在这些领域,工作流必须能够在真实业务人员的实际操作中稳定运行,而不仅仅是为了通过一次演示。 — Phuc
标签:Python, 云资产清单, 文档, 无后门, 网络调试, 自动化, 逆向工具, 逆向工程, 防御加固, 飞书