Anycross creator
Reverse-engineered documentation and tooling for Lark AnyCross flow.json — connector IDs, schema, validator. Works as an AI agent skill or standalone Python.
npx -y skills add helleOPP/anycross-skill-creator --skill anycross-creatorAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 22 days oldThe repository was created 22 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Build, validate, and package AnyCross workflow files (the Lark/Feishu automation platform) — produces an importable .zip via a Python generator script. Covers the real flow.json schema (structure/steps, operation objects, the four spel types), connector/operation IDs harvested from verified exports, LarkBase field read/write formats, container nodes (loop/branch/while), and a diagnose-then-learn loop for import and run errors. Use this whenever the user mentions AnyCross, asks to build/create/generate an AnyCross workflow or flow.json, wants a Lark automation packaged as a zip, pastes an AnyCross error message or a failing node, or types '/anycross-creator' — even if they only describe the automation (webhook to Bitable to Google Docs, cron to Bitable to Lark card) without naming the platform. Vietnamese speakers phrase this as 'tao/sinh/dung workflow anycross' or 'flow anycross'. Also use when an AnyCross import fails ('Unable to parse uploaded file', URLFieldConvFail) or a node errors at runtime. NOT for n8n workflows or Lark Approval definitions.
SKILL.md
10.7 KB, ~2.3k tokens by cl100k_base, as published. Nobody here has run it
AnyCross Creator
Build AnyCross workflows as flow.json inside a .zip, generated by a Python script so the output is reproducible and reviewable.
The hard part of AnyCross is not the logic — it is that every connector ID, operation ID, credential ID, and parameter shape is tenant- and version-specific. Two Bitable connectors exist in the wild (7241926900765982725 v2.0 and 7576576101812538807 v2.7) with different operation IDs and different parameter names for the same action. Guessing these produces a zip that imports but silently fails, or fails to import at all. So the workflow below is built around one rule: copy IDs from a real export, never from memory.
Step 0 — Ask for a template before building anything
Before writing a single line of generator code, ask the user:
Do you have an AnyCross workflow that already runs in this tenant? Export it to .zip and give me the path — I'll take the real connectorId / operationId / credentials / parameter shapes from it instead of guessing.
If you don't have one: which tenant is this, and is there any other workflow on the same tenant I could look at?
This question is not a formality — it is the single highest-leverage step. A template export gives, for free: the exact connector versions this tenant has installed, working credential IDs, the parameter names for each operation, and the spel paths that actually resolve.
Run the inspector on any template the user provides:
python <skill-dir>/scripts/inspect_export.py "<path-to.zip>"
python <skill-dir>/scripts/inspect_export.py "<path-to.zip>" --spel # also list every reference
It prints the node inventory (connector name/version/IDs), parameter keys per node, credential IDs, and spel references. Copy from that output.
If no template exists, say so plainly and fall back to references/connectors.md — but tell the user those IDs came from other tenants' exports and may not match theirs, so the first import is a probe, not a delivery. Then Step 4's error loop matters even more.
Any AnyCross export already on disk is a legitimate template — search before asking the user to go export something:
find . -iname "*.zip" | head -20
Step 1 — Handle the tenant constants
Every workflow needs values that belong to a project, not to this skill: app_token, table_id, credential IDs, subflow IDs, folder IDs, chat IDs. There are two places to put them, and the better one is easy to miss.
Prefer AnyCross project variables. AnyCross has first-class project-level config, referenced as $.config.<name> via a project_var spel. The value lives in project settings; the flow file only names it. Ask the user whether these variables already exist — inspect_export.py --spel on a template shows which ones a working flow uses. The payoff: the JSON carries no tenant identifiers, moves between environments unedited, and a base migration becomes one settings change instead of a hunt through every node. The cost: the variable must exist in the target project before the flow runs, so list the ones the flow expects when handing over. See references/flow-schema.md.
Otherwise, named constants at the top of the generator script — so a reader sees in one glance which tenant the flow touches.
Either way, never write them into this skill's own files. This skill is shared across tenants and across people; a credential or app_token left in a reference file is both a leak and a trap, because the next build will copy it and quietly point at the wrong base. If a set of constants is worth keeping, it belongs in the project's own notes, keyed by tenant.
Step 2 — Write the generator script
Start from assets/generator_skeleton.py — it has the value-type helpers (s(), n(), b(), spel(), pvar(), fvar(), cred()), the node builder, and the UTF-8 write already wired.
Read the reference for whatever the build touches:
| Need | Read |
|---|---|
| Top-level shape, node shape, value types, spel types, loop/branch/while | references/flow-schema.md |
| connectorId / operationId / parameter keys per connector | references/connectors.md |
Reading and writing LarkBase fields, filters, extract() helpers | references/larkbase.md |
| HTTP, Lark messages and cards, Google Docs/Drive, e-signature, subflows, cron | references/integrations.md |
| An error you have hit before | references/known-errors.md — read this before debugging anything |
Three things bite every time and are worth internalizing rather than looking up:
- Script node output is namespaced under
.result— a handler returning{rows: [...]}in nodescript-2is referenced as$.script-2.result.rows, not$.script-2.rows. - Only
json_pathspel repeats the full path inexpression.project_varandflow_variablepaths are relative ($.config.x.ypairs with pathx.y), which looks like a bug and is not. Check the node_tree table inflow-schema.mdbefore "fixing" one. - The file must be valid UTF-8 — write with
encoding="utf-8".ensure_ascii=Trueis the recommended default because it sidesteps platform codec bugs for free, but raw non-ASCII is legal: AnyCross's own exports contain plenty of it. Do not treat non-ASCII as a defect.
Step 3 — Validate before handing over
python <skill-dir>/scripts/validate_flow.py <flow.json>
python <skill-dir>/scripts/pack_flow.py <flow.json> "<output-dir>/<Workflow Name>.zip"
The validator checks what is cheap here and expensive in the UI: UTF-8 validity, structure ↔ steps parity (including nested subSteps), node shape (operation object present, js_code not code, credentials under auth not parameters), and spel drift per node_tree type. pack_flow.py runs it and refuses to pack a failing flow.
It is calibrated against real production exports, so an error from it means a real defect, not a style opinion. If it ever fails a flow that demonstrably runs, the validator is wrong: fix the rule, not the flow, and record it in known-errors.md.
A clean run means the zip will import. It does not mean the flow is correct — wrong operation IDs and wrong field names pass validation and fail at runtime. That is what Step 4 is for.
Step 4 — The error loop (this is where the skill gets better)
When you hand over the zip, the user is your only sensor: you cannot see the AnyCross UI. So make reporting back cheap and precise. Ask for exactly this:
Please import and test-run it. If anything fails, copy it to me verbatim — don't translate or summarise:
1. Import fails → the text in the red banner, word for word (e.g.
Unable to parse uploaded file).2. A node shows red in the editor, or publish is blocked → the node name plus the red text under the field.
3. It fails at run time → open the run history, click into the failed run, click the red node, and send me:
- the node name and its connector
- the full Error / message, including any code (e.g.
URLFieldConvFail)- that node's Input panel (JSON)
- the Output panel of the node immediately before it (JSON)
The Input/Output panels matter most — they show me the real shape of the data, which is the part I'm otherwise guessing at.
A screenshot works, but copyable text is better.
Those panel names are the usual ones; if the UI in front of the user reads differently, take what they give and do not argue about wording.
Then close the loop. Once you diagnose the error, and before moving on, append an entry to references/known-errors.md in the format documented at the top of that file. This is the step that makes the next build cheaper, and it is easy to skip precisely because the user's problem is already solved by then. Don't skip it.
Record the class of mistake, not the incident. "Wrote a plain string into a URL field, got URLFieldConvFail, URL fields need {link, text}" generalizes to every future build. "Fixed the document link on the booking flow" helps nobody, and drags a client's name into a skill that gets shared.
If the fix reveals that a reference file is wrong — a connector ID that does not exist in this tenant, a parameter renamed in a newer connector version — fix the reference too, and note which connector version it applies to. A wrong ID in connectors.md gets copied confidently by every future run, which is worse than no entry at all.
Step 5 — Report
Tell the user what was built, where the zip is, which constants or project variables it depends on, and what could not be verified without a real run. Be explicit about the last one: if an operation ID was guessed because no template covered that connector, name the node so they test it first.
Reference files
references/flow-schema.md— flow.json anatomy: top level,structurevssteps, node shape, value types, the four spel types, container nodesreferences/connectors.md— verified connector/operation inventory, and how to harvest more from an exportreferences/larkbase.md— Bitable field read/write formats, filter builders, theextract()helper familyreferences/integrations.md— HTTP, Lark message/card, Google Docs/Drive, e-signature, subflow, cron trigger patternsreferences/known-errors.md— the error ledger; read before debugging, append after diagnosing
Scripts
scripts/inspect_export.py— dump a real export's nodes, IDs, params, creds, spel paths (Step 0)scripts/validate_flow.py— pre-import checks (UTF-8, structure parity, node shape, spel drift)scripts/pack_flow.py— validate, then wrap flow.json into an importable zip
Assets
assets/generator_skeleton.py— starting point for the generator script
What ships with it: 9 files
59.1 KB alongside SKILL.md, 4 of them executable
assets/
- generator_skeleton.pyruns8.0 KB
references/
- connectors.md7.9 KB
- flow-schema.md8.4 KB
- integrations.md6.8 KB
- known-errors.md8.2 KB
- larkbase.md6.6 KB
scripts/
- inspect_export.pyruns3.8 KB
- pack_flow.pyruns1.4 KB
- validate_flow.pyruns8.0 KB