{"id":"55e1e5d0-830f-4f88-ab7c-5f64c4eaa33c","entityType":"agent","slug":"clawhub-chikawa11-chat2workflow","name":"chat2workflow","canonicalUrl":"https://www.xpersona.co/agent/clawhub-chikawa11-chat2workflow","canonicalPath":"/agent/clawhub-chikawa11-chat2workflow","generatedAt":"2026-10-11T20:56:24.944Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:19:13.824Z","emptyReason":null},"description":"A design-only workflow designer for the Dify and Coze platforms. Through multi-round conversation, it produces a structured workflow JSON (nodes, edges, vari...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s177exw7vtn9s9ntqmt8nww1ed85c5x3:chat2workflow","sourceUrl":"https://clawhub.ai/chikawa11/chat2workflow","homepage":"https://clawhub.ai/chikawa11/skills/chat2workflow","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/chikawa11/chat2workflow","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/chikawa11/skills/chat2workflow","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"chat2workflow technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:19:13.824Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:19:13.824Z","emptyReason":null},"stars":null,"forks":null,"downloads":1020,"packageName":null,"latestVersion":"1.1.3","tractionLabel":"1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:19:13.746Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T17:19:13.824Z","lastCrawledAt":"2026-10-11T17:19:13.746Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T17:19:13.746Z","lastVerifiedAt":null,"highlights":[{"version":"1.1.3","createdAt":"2026-05-08T11:08:48.045Z","changelog":"- No user-facing changes in this release. - Version updated to maintain metadata or triggering new build; there are no modifications to code or documentation.","fileCount":59,"zipByteSize":73297},{"version":"1.1.2","createdAt":"2026-05-08T09:22:35.757Z","changelog":"Correct the IF-ELSE nodes in the prompt words","fileCount":59,"zipByteSize":73296},{"version":"1.1.1","createdAt":"2026-04-24T09:06:19.020Z","changelog":"**This update clarifies workflow and script separation, and adds user-facing script usage documentation.** - Added `CONVERTER_USAGE.md` to document usage of optional helper scripts. - Updated documentation to clearly state that bundled scripts (like `converter.py`) are not part of the skill deliverable and are not invoked by the skill itself. - Revised and condensed the skill description to emphasize design-only operation and reinforce that only text output is produced. - Removed references to automatic or conditional script invocation within the main documentation.","fileCount":60,"zipByteSize":74668},{"version":"1.0.10","createdAt":"2026-04-24T08:36:24.222Z","changelog":"Version 1.0.10 - Added SAFETY_AUDIT.md file to the repository. - No changes to core logic or skill behavior. - Documentation update only; no user-facing feature changes.","fileCount":58,"zipByteSize":73667},{"version":"1.0.9","createdAt":"2026-04-24T08:13:19.437Z","changelog":"No functional changes detected; only SKILL.md documentation has been updated for clarity. - Clarified the workflow design model and output format in documentation. - Improved explanation of platform selection and JSON requirements. - Reworded guidance on the use of helper scripts for conversion. - Updated naming and description consistency for rules and formats. - No changes to code, features, or behavior.","fileCount":57,"zipByteSize":71113},{"version":"1.0.8","createdAt":"2026-04-24T07:27:33.801Z","changelog":"No user-visible changes in this version. - No file changes detected since the previous release. - Functionality and documentation remain unchanged.","fileCount":57,"zipByteSize":70971},{"version":"1.0.7","createdAt":"2026-04-24T07:06:40.401Z","changelog":"chat2workflow 1.0.7 changelog: - Improved and clarified documentation in SKILL.md: further emphasizes the design-only nature of the skill and the non-executing role of the agent. - Moved detailed scope and execution constraints from many bulleted safety rules to more accessible summary descriptions. - Simplified explanations for how offline conversion scripts relate to core outputs. - Focused Output Format and Platform Resolution Rule sections for easier compliance and user guidance. - No logic or file changes; documentation only.","fileCount":57,"zipByteSize":70459},{"version":"1.0.6","createdAt":"2026-04-24T06:16:19.724Z","changelog":"- Documentation reframed for clarity: SKILL.md is now reference material for human workflow authors, not operational agent instructions. - Clarified the skill's scope: design-only with no automatic script execution; optional utility scripts are for manual, offline use. - Platform selection and output format descriptions rewritten for easier reference and to emphasize JSON schema correctness. - Node and variable referencing rules simplified, with redundant instructional wording removed. - Minor edits throughout for brevity and improved human readability.","fileCount":57,"zipByteSize":69527}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s177exw7vtn9s9ntqmt8nww1ed85c5x3:chat2workflow","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s177exw7vtn9s9ntqmt8nww1ed85c5x3:chat2workflow` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/chikawa11/chat2workflow before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T20:56:24.939Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chikawa11-chat2workflow/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:19:13.824Z","emptyReason":null},"readme":"Skill: chat2workflow\n\nOwner: chikawa11\n\nSummary: A design-only workflow designer for the Dify and Coze platforms. Through multi-round conversation, it produces a structured workflow JSON (nodes, edges, vari...\n\nTags: latest:1.1.1\n\nVersion history:\n\nv1.1.3 | 2026-05-08T11:08:48.045Z | user\n\n- No user-facing changes in this release.\n- Version updated to maintain metadata or triggering new build; there are no modifications to code or documentation.\n\nv1.1.2 | 2026-05-08T09:22:35.757Z | user\n\nCorrect the IF-ELSE nodes in the prompt words\n\nv1.1.1 | 2026-04-24T09:06:19.020Z | user\n\n**This update clarifies workflow and script separation, and adds user-facing script usage documentation.**\n\n- Added `CONVERTER_USAGE.md` to document usage of optional helper scripts.\n- Updated documentation to clearly state that bundled scripts (like `converter.py`) are not part of the skill deliverable and are not invoked by the skill itself.\n- Revised and condensed the skill description to emphasize design-only operation and reinforce that only text output is produced.\n- Removed references to automatic or conditional script invocation within the main documentation.\n\nv1.0.10 | 2026-04-24T08:36:24.222Z | user\n\nVersion 1.0.10\n\n- Added SAFETY_AUDIT.md file to the repository.\n- No changes to core logic or skill behavior.  \n- Documentation update only; no user-facing feature changes.\n\nv1.0.9 | 2026-04-24T08:13:19.437Z | user\n\nNo functional changes detected; only SKILL.md documentation has been updated for clarity.\n\n- Clarified the workflow design model and output format in documentation.\n- Improved explanation of platform selection and JSON requirements.\n- Reworded guidance on the use of helper scripts for conversion.\n- Updated naming and description consistency for rules and formats.\n- No changes to code, features, or behavior.\n\nv1.0.8 | 2026-04-24T07:27:33.801Z | user\n\nNo user-visible changes in this version.\n\n- No file changes detected since the previous release.\n- Functionality and documentation remain unchanged.\n\nv1.0.7 | 2026-04-24T07:06:40.401Z | user\n\nchat2workflow 1.0.7 changelog:\n\n- Improved and clarified documentation in SKILL.md: further emphasizes the design-only nature of the skill and the non-executing role of the agent.\n- Moved detailed scope and execution constraints from many bulleted safety rules to more accessible summary descriptions.\n- Simplified explanations for how offline conversion scripts relate to core outputs.\n- Focused Output Format and Platform Resolution Rule sections for easier compliance and user guidance.\n- No logic or file changes; documentation only.\n\nv1.0.6 | 2026-04-24T06:16:19.724Z | user\n\n- Documentation reframed for clarity: SKILL.md is now reference material for human workflow authors, not operational agent instructions.\n- Clarified the skill's scope: design-only with no automatic script execution; optional utility scripts are for manual, offline use.\n- Platform selection and output format descriptions rewritten for easier reference and to emphasize JSON schema correctness.\n- Node and variable referencing rules simplified, with redundant instructional wording removed.\n- Minor edits throughout for brevity and improved human readability.\n\nv1.0.5 | 2026-04-23T12:54:34.393Z | user\n\nchat2workflow 1.0.5\n\n- Rewrote and clarified documentation, especially the explanation of what bundled scripts do and do not do.\n- Documented script output locations, bytecode handling, and variable reference patterns as inherent script behavior.\n- Updated \"Scope & Safety\" section into plain factual explanations about script boundaries (not runtime rules).\n- Kept all workflow design, platform selection, and output format rules unchanged.\n- No file or code changes made; documentation improvements only.\n\nv1.0.4 | 2026-04-23T12:40:55.057Z | user\n\n**Expanded security and output policies for conversion scripts and generated files.**\n\n- Clarified that no package installation, script execution, or file writes ever occur within the skill boundary.\n- Documented that all conversion artifacts (YAML, ZIP, etc.) are written outside the skill directory, with hard enforcement and redirection if necessary.\n- Added strong statements on avoiding Python bytecode cache files in the skill folder.\n- Specified that all third-party dependencies must be installed by users beforehand; runtime installation by the skill is strictly forbidden.\n- No changes to workflow design logic or core output format.\n\nv1.0.3 | 2026-04-23T08:40:57.600Z | user\n\n- **Clarified skill scope:** The skill now only designs workflow JSON and does not execute or invoke any scripts or compilation steps automatically.\n- The use of bundled scripts (e.g., converter, autofix) is now strictly user-initiated and never run autonomously.\n- Output now consists solely of the tagged workflow design sections; compilation to platform-native formats must be explicitly requested by the user each time.\n- Updated descriptions and instructions to reinforce that all local tools are optional, safe, and require per-turn user consent before use.\n\nv1.0.2 | 2026-04-23T08:18:53.311Z | user\n\n- No code or documentation changes in this version.\n- No functional differences from the previous release.\n- Version bump only; no updates impacting users.\n\nv1.0.1 | 2026-04-23T06:45:16.386Z | user\n\n- Added a \"Post-Generation Auto Pipeline\" requirement: Whenever a response contains the three required tagged sections (`<node_selection>`, `<design_principle>`, `<workflow>`), the full pipeline—autofix, JSON extraction, and platform-specific config generation—must be executed immediately in the same turn.\n- Documented exception: The auto pipeline does NOT trigger for turns that do not output all three sections (e.g., clarification-only turns or when explicitly drafting).\n- Updated documentation to clarify this mandatory, end-to-end automated workflow generation and compilation process for every completed response.\n\nv1.0.0 | 2026-04-23T04:27:32.954Z | user\n\nchat2workflow 1.0.0 — Initial Release\n\n- Expert workflow builder for Dify and Coze platforms via multi-round conversation.\n- Generates structured JSON workflows (nodes, edges, variable references) with platform-specific validation.\n- Produces importable workflow JSON, convertible to YAML using the included converter.\n- Supports incremental add/modify/remove operations on existing workflows.\n- Ensures output consistency with strict response formatting and variable tracking.\n\nArchive index:\n\nArchive v1.1.3: 59 files, 73297 bytes\n\nFiles: autofix.py (23844b), bash_converter.sh (1193b), CONVERTER_USAGE.md (3189b), converter.py (22826b), node_docs/coze.md (25680b), node_docs/dify.md (29928b), nodes/__init__.py (0b), nodes/coze/__init__.py (0b), nodes/coze/basic/__init__.py (0b), nodes/coze/basic/code.py (3047b), nodes/coze/basic/document_extractor.py (1230b), nodes/coze/basic/end.py (1049b), nodes/coze/basic/http_request.py (1463b), nodes/coze/basic/if_else.py (2509b), nodes/coze/basic/iteration.py (1663b), nodes/coze/basic/llm.py (2669b), nodes/coze/basic/parameter_extractor.py (3446b), nodes/coze/basic/question_classifier.py (1895b), nodes/coze/basic/start.py (1361b), nodes/coze/basic/template_transform.py (1706b), nodes/coze/basic/variable_aggregator.py (1252b), nodes/coze/MANIFEST.yml (177b), nodes/coze/node.py (193b), nodes/coze/tool/__init__.py (0b), nodes/coze/tool/echarts.py (3647b), nodes/coze/tool/google_search.py (1999b), nodes/coze/tool/markdown_exporter.py (2825b), nodes/coze/tool/mermaid_converter.py (1411b), nodes/coze/tool/text2image.py (1692b), nodes/coze/tool/tts.py (1536b), nodes/dify/__init__.py (0b), nodes/dify/basic/__init__.py (0b), nodes/dify/basic/code.py (1181b), nodes/dify/basic/document_extractor.py (625b), nodes/dify/basic/end.py (798b), nodes/dify/basic/http_request.py (1103b), nodes/dify/basic/if_else.py (2672b), nodes/dify/basic/iteration_start.py (337b), nodes/dify/basic/iteration.py (772b), nodes/dify/basic/list_operator.py (2380b), nodes/dify/basic/llm.py (1078b), nodes/dify/basic/parameter_extractor.py (1205b), nodes/dify/basic/question_classifier.py (1307b), nodes/dify/basic/start.py (1943b), nodes/dify/basic/template_transform.py (885b), nodes/dify/basic/variable_aggregator.py (746b), nodes/dify/node.py (233b), nodes/dify/tool/__init__.py (0b), nodes/dify/tool/echarts.py (1649b), nodes/dify/tool/google_search.py (977b), nodes/dify/tool/markdown_exporter.py (1091b), nodes/dify/tool/mermaid_converter.py (1176b), nodes/dify/tool/text2image.py (1415b), nodes/dify/tool/tts.py (1064b), requirements.txt (32b), SAFETY_AUDIT.md (5747b), SKILL.md (15174b), tools.py (23643b), _meta.json (132b)\n\nFile v1.1.3:SKILL.md\n\n---\nname: chat2workflow\ndescription: A design-only workflow designer for the Dify and Coze platforms. Through multi-round conversation, it produces a structured workflow JSON (nodes, edges, variable references) as text output. The skill itself produces only text and never runs any scripts.\n---\n\n# Chat2Workflow Builder Skill\n\n## What this skill does\n\nThis skill is **design-only**. Its deliverable is three tagged sections of text (see *Output Format* below) — most importantly a workflow JSON wrapped in `<workflow></workflow>`. Producing those three sections involves only reading the platform documentation under `node_docs/` and emitting text; nothing else happens.\n\nA few Python files also live in this folder (`converter.py`, `autofix.py`, `tools.py`, `bash_converter.sh`). They are **not part of the skill's deliverable** and are not referenced by the generation process. They exist as standalone utilities that a user can run manually from a shell, entirely outside the skill's text-generation flow, if they separately want to turn a JSON file into a Dify YAML or Coze ZIP on their own machine. See the bundled `README`/source of those scripts for their CLI usage; the skill itself does not invoke them.\n\n## Overview\n\nA Chat2Workflow design is a Directed Acyclic Graph of connected nodes, where each node represents a step of logic, data processing, or model inference. The design is serialized as a JSON object that enumerates the nodes and the edges that connect them.\n\nThis skill supports **two target platforms**:\n\n| Platform | Documentation File | Selection criterion |\n|----------|--------------------|----------------|\n| **Dify** (default) | `node_docs/dify.md` | The user instruction explicitly mentions Dify, or no platform is specified at all. |\n| **Coze**           | `node_docs/coze.md` | The user instruction explicitly mentions Coze / 扣子. |\n\n### Platform Resolution\n\nPlatform selection is a two-step lookup performed against the user's instruction:\n\n1. The user's instruction is scanned for platform keywords — `dify` / `Dify` / `DIFY` or `coze` / `Coze` / `扣子`.\n2. If a platform keyword is present, that platform is the target. Otherwise the target is Dify (the default).\n3. The matching file from `node_docs/` — `node_docs/dify.md` or `node_docs/coze.md` — is the authoritative schema for node `type` strings, `param` objects, and referable variables on that platform. The two platforms have different node sets, different parameter schemas, and different referable variables.\n4. The chosen platform is named in `<design_principle>` with a short justification, e.g. `\"Platform: Dify (user did not specify, defaulting to Dify).\"`.\n\nA single workflow targets a single platform; every node's `type` comes from that platform's documentation file.\n\nThe interaction model is conversational: the user supplies creation or modification instructions across multiple rounds, and — unless an instruction says otherwise — each new response extends the current design rather than replacing it. Responses follow the structure described in *Output Format*.\n\n\n## Output Format\n\nA well-formed response consists of three clearly tagged sections rendered as **inline text** (not files):\n\n### 1. Node Selection\nWrapped in `<node_selection></node_selection>` tags. Lists the names of the nodes chosen for the design.\n\n### 2. Design Principle\nWrapped in `<design_principle></design_principle>` tags. Explains the reasoning and architecture decisions. Contains at minimum:\n- A one-line **Platform** declaration (`Platform: Dify` or `Platform: Coze`).\n- A `Variable Checklist` subsection that cross-checks the input and output variables against the instruction's requirements (see Workflow Validity Rule 2 below).\n\n### 3. Workflow JSON\nWrapped in `<workflow></workflow>` tags. Contains the complete workflow as a single valid JSON object.\n\nThe content inside `<workflow>` is raw JSON — markdown code fences around it break parsing, because the downstream pipeline calls `json.loads()` directly on the content between the tags. Concretely, ` ```json ` immediately after `<workflow>` or ` ``` ` immediately before `</workflow>` will cause the parse step to fail. Code fences that appear *inside* JSON string values (for example inside a code node's `code` field) are fine — only the outer wrapping fences cause parsing problems.\n\n## JSON Structure Specification\n\nThe JSON object describes a Directed Acyclic Graph (DAG) workflow, consisting of two core fields:\n\n### `nodes_info` (Array)\nContains detailed configuration information for all nodes. Each element is an object representing a functional node and contains the following fields:\n- `id` (String): The unique identifier of the node, a string that increments starting from 1 (e.g., \"1\",\"2\").\n    - Note: Child nodes within an Iteration node use the format `\"<ParentID>-<SeqNum>\"`, where `<ParentID>` is the id of the enclosing iteration node and `<SeqNum>` is a sequential number starting from 1 that increments for each child node within that iteration canvas. For example, if the iteration node's id is `\"3\"`, its child nodes are `\"3-1\"`, `\"3-2\"`, `\"3-3\"`, etc. The `iteration-start` node is always the first child, i.e., `\"<ParentID>-1\"` (e.g., `\"3-1\"`, `\"5-1\"`).\n- `type` (String): The type of the node. The `type` value should exactly match the `Type` specified in the selected platform's node documentation (e.g., the Template node's type is `template-transform`, not `template`). Using an incorrect type string — or a type string that does not belong to the selected platform — will cause the workflow to fail.\n- `param` (Object): Specific configuration parameters for the node. The structure varies depending on the type.\n\n### `edges` (Array)\nEach element in the list represents a connection line. Each element follows a triplet structure:  `[SourceNodeID (String), OutputPortIndex (Number), TargetNodeID (String)]`(e.g., [\"1\", 0, \"2\"]).\n- Default output port is 0.\n- For branching nodes (question-classifier, if-else), port indices correspond to branch order (0, 1, 2...).\n- For if-else, the ELSE branch port index equals the number of explicitly defined cases (i.e., it's the last port).\n\n\n### Downstream Variable References\nDownstream nodes can reference the referable_variables of upstream nodes, which will be represented in `param`.\n\n## Variable Reference System\n\nDownstream nodes reference upstream node outputs through one of two patterns:\n\n### In structured parameters (arrays/tuples):\n`[SourceVariableName, SourceNodeID]`\nExample: `[\"text\", \"3\"]` — references the `text` variable from node `3`.\n\n### In text fields:\n`{{#<SourceNodeID>.<SourceVariableName>#}}`\nExample: `{{#'3'.text#}}` — references the `text` variable from node `3`.\n\nWhen the SourceNodeID contains a hyphen (iteration child nodes such as `\"2-2\"`), it is quoted: `{{#'2-2'.text#}}`.\n\n\n### Workflow Validity Rules\n\nThe rules below describe what makes a produced workflow valid. They are constraints on the emitted JSON/tags, not instructions to any external system.\n\n1. **Node Selection ↔ Workflow Consistency**: The node types declared in `<node_selection>` and those actually used in `<workflow>` are exactly consistent. Every node declared in `<node_selection>` appears in `<workflow>`, and every node used in `<workflow>` is declared in `<node_selection>`. No omissions, no extras.\n\n2. **Variable Checklist in Design Principle**: The `<design_principle>` section contains a `Variable Checklist` subsection that verifies whether the input and output variables satisfy the instruction's requirements — especially relevant across multi-round interactions where variable requirements may change between rounds.\n\n3. **JSON Bracket Integrity**: The `<workflow>` tag contains a single-line, valid JSON string parseable by `json.loads()` in Python directly. Bracket closure is critical — truncation, mismatched brackets, and unclosed structures all invalidate the JSON. Nodes with deeply nested bracket structures (for example `if-else` cases with multiple conditions) are the most common source of bracket mismatches; verifying that every `[`, `{`, and `(` has a matching closing counterpart before finalizing avoids these errors.\n\n4. **Escape Sequences in String Values**: JSON string values cannot contain raw control characters (newline, tab, etc.), so escaping is required. This is especially relevant for the `code` field (Python code), LLM-node message fields (the `system` and `user` keys under a `model` node's `param`), and `template` fields:\n  - **Newlines** inside string values: `\\n` (backslash + n), not a real line break.\n  - **Tabs** inside string values: `\\t` (backslash + t).\n  - **Carriage returns** inside string values: `\\r` (backslash + r).\n  - **Double quotes** inside string values: `\\\"` (backslash + quote).\n  - **Backslashes** that should appear literally in the final string (for example in regex patterns such as `\\d{4}`, or in Jinja2 `replace('\\n', ' ')`): `\\\\` (double backslash).\n    - For example, a Jinja2 template needing `replace('\\n', ' ')` is written in JSON as `replace('\\\\n',' ')`, because `\\\\n` in JSON represents the literal two-character sequence backslash+n.\n  - **Common mistake**: Double-escaped forms such as `\\\\\\\\n` or `\\\\\\\\t` produce literal backslash characters in the parsed output, not actual newlines/tabs. Exactly ONE level of JSON escaping is correct, regardless of whether the string content happens to be Python code or a template — JSON only ever needs one level of escaping.\n    - For example: a Python snippet containing `line.split(\"\\t\")` is written in JSON as `line.split(\\\"\\\\t\\\")` — `\\\"` escapes the double quotes, `\\\\t` represents a literal tab character in the parsed string.\n\nAll newlines, tabs, and carriage returns within JSON string values are represented as two-character escape sequences (`\\n`, `\\t`, `\\r`), not as literal whitespace characters. This is especially relevant for the `code` field (Python code), LLM-node message fields (the `system` and `user` keys under a `model` node's `param`), and `template` fields.\n\n5. **Topological Ordering of nodes_info**: The `nodes_info` array is in topological order. Nodes use \"forward references\" — a node only references variables from nodes that appear before it in the array. The one exception is the `output_selector` of an `iteration` node, which may reference a child node that is defined later (since iteration child nodes are created as part of the iteration).\n\n6. **Iteration Canvas Boundary**: Edges and variable references never cross the iteration boundary. Specifically:\n  - No edges exist between iteration child nodes and external nodes. External nodes connect to/from the `iteration` node itself, which acts as the sole bridge between internal and external.\n  - External node variables are not referenced from inside the iteration canvas, and iteration child node variables are not referenced from outside (the iteration node's `output` is used instead).\n  - Child nodes inside the iteration canvas reference the iteration node's built-in `item` and `index` variables directly (via the iteration node's id, not the `iteration-start` node's id in Dify).\n  - The iteration node receives internal results via its `output_selector` parameter, which points to a child node's output variable.\n  - Child nodes within an iteration canvas are connected to each other via internal edges — they are not isolated nodes.\n  - On Dify, no edge exists between the `iteration` and `iteration-start` nodes.\n\n7. **No Isolated Nodes**: Every node in the workflow is connected to at least one other node via edges. A node created without any connecting edge is invalid. The workflow is a connected DAG — all nodes (except for the child nodes within the iteration canvas) are reachable from the `start` node through the edge graph.\n\n8. **Instruction Fidelity — No Key Node Omissions**: Producing a working workflow requires identifying every node implied or explicitly mentioned by the creation/modification instruction. A missing key node — omitting a Document Extractor when the instruction involves file content processing, or omitting an If-Else when the instruction describes conditional logic — causes the workflow to fail. A valid workflow can actually execute and solve the problem end-to-end.\n\n9. **File-Aware Workflow Design**: Whether the instruction's input or output involves files matters for node selection:\n  - Inputs mentioning `document` or `image` are typically file-typed variables.\n  - Inputs with multiple optional forms (where some may be empty while others have values) are handled with an `if-else` node that detects which inputs are provided and routes to the appropriate processing branch.\n\n10. **Format Compliance**: Creation, addition, deletion, modification, and correction all follow the structure described in *Output Format* so the response can be correctly parsed.\n\n\n### Multi-Round Interaction Rules\n\nUnless explicitly instructed to add, remove, or modify, variables and logic not mentioned in the instruction should remain unchanged. The following rules govern how output specifications are interpreted across rounds:\n\n| Pattern | Interpretation |\n|---------|---------------|\n| **\"Only output\"** — \"only needs to output X\" (without additive language) | Output exactly X. This is a fresh specification — REPLACE all previous outputs. Previous outputs NOT listed are dropped. |\n| **\"Additionally add\"** — Additive language (any phrasing conveying \"in addition to what already exists\") | ADD the new variables to existing outputs. |\n| **\"Remove\"** — \"Remove the output Y\" | Remove only Y, keep all others. |\n| **\"No mention\"** — No mention of outputs | Keep them unchanged. |\n| **\"Branch-scoped change\"** — In a branching workflow, the output specification constrains only the branch(es) it refers to | Unmentioned branches remain unchanged. |\n\n\n---\n\n## Platform-Specific Node Documentation\n\nThe complete list of node types, their parameter schemas, and their referable variables for each platform lives in a dedicated, pluggable documentation file under `node_docs/`:\n\n- **Dify** → see [`node_docs/dify.md`](./node_docs/dify.md)\n- **Coze** → see [`node_docs/coze.md`](./node_docs/coze.md)\n\nOnce the target platform has been resolved (see `Platform Resolution` above), the corresponding file in `node_docs/` is the authoritative reference for node `type` strings and their `param` structures. Because the two platforms have different and evolving node sets, the `node_docs/` file for the selected platform is consulted each time rather than relied on from memory.\n\n### Note on placeholder auth fields in node schemas\n\nNode templates for the `http-request` node (and similar) contain placeholder fields such as `bearerTokenData` with a literal `\"EMPTY\"` value. These are **schema placeholders** that describe what a user-authored workflow can contain; the skill does not read, request, or transmit any credentials. Users authoring a workflow should avoid pasting real API keys, bearer tokens, or passwords into the generated JSON — those values, if pasted in, would be stored verbatim in whatever artifact the user produces.\n\nFile v1.1.3:_meta.json\n\n{\n  \"ownerId\": \"kn7bhksjab0j1qxn85redp9ev585d21g\",\n  \"slug\": \"chat2workflow\",\n  \"version\": \"1.1.3\",\n  \"publishedAt\": 1778238528045\n}\n\nFile v1.1.3:CONVERTER_USAGE.md\n\n# Converter Utility — Manual CLI Usage\n\nThis document is **not part of the `chat2workflow` skill's runtime** and is\nnot referenced by `SKILL.md`. It describes the optional, standalone\ncommand-line utilities shipped in this folder — `converter.py`, `autofix.py`,\n`tools.py`, and `bash_converter.sh` — for users who want to compile a\nworkflow JSON (produced separately by the skill's text output) into a\nDify YAML file or a Coze ZIP bundle on their own machine.\n\nThe skill's own deliverable is purely text (the three tagged sections). These\nutilities are read-and-write file tools that a user runs manually from a\nshell; nothing about using the skill requires running them.\n\nFor an independent safety audit of the utilities' imports and behavior (no\nnetwork I/O, no shell execution, no credential access), see\n[`SAFETY_AUDIT.md`](./SAFETY_AUDIT.md).\n\n---\n\n## 1. Prerequisites\n\nTwo third-party Python packages are required. They are listed in\n`requirements.txt` and can be installed with whichever Python package\nmanager the user prefers:\n\n- `PyYAML` — emits Dify YAML.\n- `json_repair` — used by the offline auto-fix pass.\n\nThe utilities do not shell out to `pip`, `conda`, or any other package\nmanager. They run against whatever interpreter already has the packages\navailable.\n\n## 2. CLI\n\n```bash\npython converter.py \\\n    --json_path ../workflow.json \\\n    --name my_workflow \\\n    --output_path ../chat2workflow_output/ \\\n    --type dify        # or: --type coze\n```\n\nAlternative flags:\n\n- `--json_str '{...}'` — pass the workflow JSON inline instead of from a file.\n- `--name` — name of the produced artifact. English only.\n- `--output_path` — destination directory. When omitted, defaults to the\n  sibling directory `../chat2workflow_output/` next to this folder.\n\nA bash wrapper is also provided for convenience:\n\n```bash\nbash bash_converter.sh ../workflow.json my_workflow ../chat2workflow_output dify\n```\n\n## 3. Output-path policy\n\n- Output is written under `--output_path`.\n- If `--output_path` resolves **inside** this folder, `converter.py`\n  redirects the write to `../chat2workflow_output/` instead, so the folder\n  that ships the utilities is never written to.\n- For Coze ZIPs, intermediate files during bundle assembly are placed in\n  the system temp directory via `tempfile.mkdtemp()` and are removed once\n  the final ZIP is emitted.\n- `converter.py` sets `sys.dont_write_bytecode = True` before importing\n  sibling modules, so no `__pycache__/` or `*.pyc` files are produced next\n  to the source while running it.\n\n## 4. `autofix.py` (optional pre-processing)\n\nIf the workflow JSON was taken directly from an LLM's tagged response and\nhas not been cleaned yet, the auto-fix pass can be run first:\n\n1. Strip code fences inside `<workflow>` tags.\n2. Repair JSON via `json_repair` (control chars, mismatched brackets,\n   trailing commas, etc.).\n3. Topologically re-order `nodes_info`, preserving the\n   `iteration.output_selector` forward-reference.\n4. Rewrite `<node_selection>` so that it exactly matches the node types\n   actually used in `<workflow>`.\n\nSee `autofix.py` for the full API (`apply_all_autofixes`,\n`extract_workflow_json`, `validate_workflow`).\n\nFile v1.1.3:node_docs/coze.md\n\n## Complete Node Documentation\n\n> **Note on scope**: Every section below describes a node type that the skill emits **inside the generated workflow JSON** (the `<workflow>` output). Parameter key names such as `system`, `user`, `query_variable_selector`, etc. are field names of the produced workflow object — they configure the LLM inside that workflow at runtime. None of the text below is a directive for the agent; it is a platform schema reference.\n\nHere are the meta information to the nodes that may be used in the workflow:\n\n### Node: Start\n- **Type**: `start`\n- **Description**: The \"Start\" node is a critical preset node in the workflow application. It provides essential initial information, such as user input and uploaded files, to support the normal flow of the application and subsequent workflow nodes.\n- **Parameters**:\n  - `variables`: `Array<[string, string]>`\n    - Description: Define the set of input variables required by the node.\n    - Value: Each array `[Name, Type]` strictly adheres to the following order.\n        - Index 0: **Variable Identifier** (`string`), used to reference the variable within the context.\n        - Index 1: **Type Specifier** (`string`), declares the data format accepted by the variable. Allowed Values: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"file\"`, `\"array[file]\"`.\n    - Example: `[[\"query\", \"string\"], [\"limit\", \"number\"], [\"file_A\", \"file\"]]`\n- **Referable Variables**: Each variable in `\"variables\"` can be referenced by downstream nodes.\n- **Supplementary Information**:\n  1. File Processing: Files uploaded through a Start node must be processed appropriately by subsequent nodes. The Start node only collects files; it does not read or parse their content. Therefore, you need to connect specific nodes to extract and process the file content. For example:\n      - Document files can be routed to a Doc Extractor node for text extraction so that LLMs can understand their content.\n      - Images can be sent to LLM nodes with vision capabilities or specialized image processing tool nodes.\n      - Structured data files such as CSV or JSON can be processed with Code nodes to parse and transform the data.\n  2. Every workflow MUST have exactly one `start` node with id `\"1\"`.\n\n\n### Node: End\n- **Type**: `end`\n- **Description**: Define the final output content of a workflow. Every workflow needs one `end` node after complete execution to output the final result.\n\n  The end node is a termination point in the process; no further nodes can be added after it. In a workflow application, results are only output when the end node is reached.\n \n  The end node must declare one or more output variables, which can reference any upstream node's output variables.\n- **Parameters**:\n  - `outputs`: `Array<[string, [string, string]]>`\n    - Description: Defines the set of output variables of the workflow.\n    - Value: Each array `[Name, ValueRef]` strictly adheres to the following order.\n        - Index 0: **Current Identifier** (`string`) — The name of the current variable defined in the node.\n        - Index 1: **Value Reference** (`[string, string]`) — A tuple defining the source of the value `[Source Variable Name, Source Node ID]`.\n            - **Inner Index 0**: **Source Variable Name** (`string`) — The specific variable name within the target node to retrieve.\n            - **Inner Index 1**: **Source Node ID** (`string`) — The unique identifier of the upstream node where the variable originates.\n    - Example: `[[\"ans1\", [\"out1\", \"3\"]], [\"ans2\", [\"out2\", \"3\"]]]`\n\n\n### Node: LLM\n- **Type**: `llm`\n- **Description**: The LLM node invokes language models to process text, images, and documents. It forwards the configured text to the chosen model and captures the response.\n- **Parameters**:\n  1. `system`: `string`\n      - Description: The `system`-role text that configures the LLM's behavior for this node (equivalent to the `system` role in a chat completion request).\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"You are a technical documentation expert.\"`\n  2. `user`: `string`\n      - Description: The `user`-role text that provides input to the LLM for this node (equivalent to the `user` role in a chat completion request).\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"Please interpret the following document: {{#'3'.out2#}}\"`\n- **Referable Variables**: `text` (`string`) — The response content generated by LLM.\n- **Supplementary Information**:\n  1. For multimodal models, file and image variables can be directly placed in the `user` field. (**Note**: They cannot be included in the `system` field.)\n  2. The `system` field is allowed to be an empty string, while only the `user` field is set.\n\n\n### Node: Question Classifier\n- **Type**: `question-classifier`\n- **Description**: The Question Classifier node intelligently categorizes user input to route conversations down different workflow paths. Instead of building complex conditional logic, you define categories and let the LLM determine which one fits best based on semantic understanding.\n- **Parameters**:\n  1. `query_variable_selector`: `[string, string]`\n      - Description: Select what to classify, which can be any text variable from previous workflow nodes.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`\n      - Example: `[\"query\",\"1\"]`\n  2. `classes`: `Array<string>`\n      - Description: A list of string labels representing the target categories for classification.\n      - Value: Must contain at least two distinct category names.\n      - Example: `[\"Chinese\",\"English\",\"Math\"]`\n- **Referable Variables**: `classificationId` (`integer`) — The ID of each category. Categories are ordered sequentially from top to bottom based on the configuration, with the first category having an ID of 1.\n- **Supplementary Information**: Each label maps to an output port in sequential order. Output port numbers are 0, 1, 2... in sequence. For example, when there are 3 classes, namely 'Chinese', 'English' and 'Math' in sequence, then 'Chinese' corresponds to port 0, 'English' corresponds to port 1, and 'Math' corresponds to port 2.\n\n\n### Node: Code\n- **Type**: `code`\n- **Description**: The Code node allows you to embed custom Python scripts into your workflow to manipulate variables in ways that built-in nodes cannot achieve. It can simplify your workflow and is suitable for scenarios such as arithmetic operations, JSON transformations, text processing, and more. \n\n  To use variables from other nodes in a Code node, you must select them in the variables field and then reference them in your code.\n- **Parameters**:\n  1. `variables`: `Array<[string, [string, string]]>`\n      - Description: Define input variables to access data from other nodes in your workflow, then reference these variables in your code.\n      - Value: Each array is a standard tuple `[Name, ValueRef]`, where `ValueRef` is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[[\"arg1\",[\"query\",\"1\"]],[\"arg2\",[\"query2\",\"1\"]]]`\n  2. `outputs`: `Array<[string, string]>`\n      - Description: Define the set of output variables.\n      - Value: Each array is a standard tuple `[Name, Type]`.\n          - Allowed Values for `Type`: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"object\"`, `\"array[string]\"`, `\"array[number]\"`, `\"array[boolean]\"`, `\"array[object]\"`.\n      - Example: `[[\"out1\",\"array[string]\"],[\"out2\",\"string\"]]`\n  3. `code`: `string`\n      - Description: Python code function.\n      - Value: Your function must receive the input variables that you've declared, and return a dictionary containing the output variables you've declared. **Note**: Format the code using `\\n` for newlines and use `\\t` for each indentation level.\n      - Example: `\"def main(arg1: str, arg2: str):\\n\\treturn {\\n\\t\\t\\\"out1\\\": [arg1,arg2],\\n\\t\\t\\\"out2\\\": arg1\\n\\t\\t}\"`\n- **Referable Variables**: Each variable in `\"outputs\"` can be referenced by downstream nodes.\n\n\n### Node: Document Extractor\n- **Type**: `document-extractor`\n- **Description**: The Document Extractor node converts uploaded files into text that LLMs can process. Since language models can't directly read document formats like PDF or DOCX, this node serves as the essential bridge between file uploads and AI analysis.\n- **Parameters**:\n  - `variable_selector`: `[string, string]`\n    - Description: Select a single file input from a file variable (typically from the Start node) or multiple files as an array for batch document processing. The type of the received variable can only be `\"file\"` or `\"array[file]\"`.\n    - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n    - Example: `[\"file_A\",\"1\"]`\n- **Referable Variables**: `text` (`string / array[string]`) — The extracted text. Single file input produces a string containing the extracted text.\n\n\n### Node: HTTP Request\n- **Type**: `http-request`\n- **Description**: This node allows sending server requests via the HTTP protocol, suitable for scenarios such as retrieving external data. The node only supports GET request method at present.\n- **Parameters**:\n  - `url`: `[string, string]`\n    - Description: The URL address of the GET request to be sent.\n    - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`. The reference variable should be a url of type string.\n    - Example: `[\"query\",\"1\"]`\n- **Referable Variables**: `body` (`string`) — Response content.\n\n\n### Node: If-Else\n- **Type**: `if-else`\n- **Description**: The If-Else node adds decision-making logic to your workflows by routing execution down different paths based on conditions you define. It evaluates variables and determines which branch your workflow should follow.\n\n  1. **Branching Logic**\n  The node supports multiple branching paths to handle complex decision trees: \n  IF Path executes when the primary condition evaluates to true.\n  ELIF Paths provide additional conditions to check in sequence when the IF condition is false. You can add multiple ELIF branches for complex logic.\n  ELSE Path serves as the fallback when no conditions match, ensuring your workflow always has a path to follow.\n  **Each path is regarded as a case.**\n\n  2. **Condition Types**\n  Each case contains at least one condition. The available **Comparison Operator** depend on the variable’s data type:\n      - For `string` variables: contains, not contains, is, is not, empty, not empty.\n      - For `number` variables: '≠', '=', '>', '<', '≥', '≤', empty, not empty.\n      - For `boolean` variables: is, is not. (The corresponding comparison value can only be the string 'true' or 'false', not a boolean value).\n      - For `object` variables: is, is not, empty, not empty.\n      - For `file` variables: exists, not exists.\n      - For `array[string]`/`array[number]`/`array[boolean]`/`array[file]` variables: contains, not contains, empty, not empty.\n      - For `array[object]` variables: empty, not empty.\n    **IMPORTANT: All values need to be represented as strings. **\n\n  3. **Complex Conditions**\n  Within a case, combine multiple conditions using **Logical Operator** for sophisticated decision-making:\n  AND Logic requires all conditions to be true. Use this when you need multiple criteria to be met simultaneously.\n  OR Logic requires any condition to be true. Use this when you want to trigger the same action for different scenarios.\n\n  4. **Variable References**\n  Reference any variable from previous workflow nodes in your conditions. Variables can come from user input, LLM responses, API calls, or any other workflow node output.\n  Use the variable selector to choose from available variables, or type variable names directly using the `{{#<Source Node ID>.<Source Variable Name>#}}` syntax. Variables are replaced with actual values before reaching the model.\n\n- **Parameters**:\n  - `cases`: `Array<[string | null, Array<Condition>]>`\n    - Description: An ordered list of branching cases. The workflow evaluates these sequentially.\n    - Value: Each case is a **2-element array** defined as:\n        - **Index 0**: **Logical Operator** (`string | null`) — It is used to combine multiple conditions, which can be `null`/'and'/'or'. When there is only one condition, return `null`.\n        - **Index 1**: **Condition Group** (`Array<ConditionTuple>`) — A list of logical conditions that must be met for this branch to execute.\n            - **ConditionTuple Definition**: A logical expression represented as an array `[VariableRef, ComparisonOperator, ComparisonValue?]`.\n                - **Index 0**: **Variable Reference** (`[string, string]`) — The standard reference tuple: `[Source Variable Name, Source Node ID]`.\n                - **Index 1**: **Comparison Operator** (`string`) — The comparison logic.\n                - **Index 2**: **Comparison Value** (`string | number | boolean | object | Optional`) — The target value to compare against. *Note: This element is omitted if the **Comparison Operator** is unary (\"empty\"/\"not empty\"/\"exists\"/\"not exists\").*\n    - Example: `[[null, [[[\"query2\",\"1\"],\"=\",\"5\"]]],[null,[[[\"query\",\"1\"],\"empty\"]]]]`\n- **Supplementary Information**: Each case maps to an output port in sequential order. Output port numbers are 0, 1, 2... in sequence. For example, when there are 3 cases, namely IF Path, ELIF Path and ELSE Path in sequence, then IF Path corresponds to port 0, ELIF Path corresponds to port 1, and ELSE Path corresponds to port 2.\n\n\n### Node: Parameter Extractor\n- **Type**: `parameter-extractor`\n- **Description**: The Parameter Extractor node converts unstructured text into structured data using LLM intelligence. It bridges the gap between natural language input and the structured parameters that tools, APIs, and other workflow nodes require.\n- **Parameters**:\n  1. `query`: `[string, string]`\n      - Description: Define the input variable required by the node.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"query\",\"1\"]`\n  2. `parameters`: `Array<[string, string, string]>`\n      - Description: Define the parameters you want to extract.\n      - Value: Each array `[Description, Parameter Name, Data Type]` strictly adheres to the following order.\n          - Index 0: **Description** (`string`) — Helps the LLM understand what to extract.\n          - Index 1: **Parameter Name** (`string`) — The identifier of the parameter to be extracted.\n          - Index 2: **Data Type** (`string`) — Allowed Values: `string`, `number`, `boolean`, `array[string]`, `array[number]`, `array[boolean]`, `array[object]`.\n      - Example: `[[\"The number of boys in the class\",\"num_male\",\"number\"],[\"The number of girls in the class\",\"num_female\",\"number\"]]`\n  3. `instruction`: `string`\n      - Description: Write clear instructions describing what information to extract and how to format it. Providing examples in your instructions improves extraction accuracy and consistency for complex parameters.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"Extract the number of students of both genders in the class from the given text{{#'3'.out2#}}\"`\n- **Referable Variables**: Each variable in `\"parameters\"` can be referenced by downstream nodes.\n\n\n### Node: Template\n- **Type**: `template-transform`\n- **Description**: The Template node transforms and formats data from multiple sources into structured text. Use it to combine variables, format outputs, and prepare data for downstream nodes or end users.\n- **Parameters**:\n  1. `variables`: `Array<[string, [string, string]]>`\n      - Description: Define input variables to access data from other nodes in your workflow, then reference these variables in template.\n      - Value: Each array is a standard tuple `[Name, ValueRef]`, where `ValueRef` is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[[\"arg1\",[\"query\",\"1\"]],[\"arg2\",[\"query2\",\"1\"]]]`\n  2. `template`: `string`\n      - Description: Template nodes create dynamic content that adapts based on workflow data.\n      - Value: Text that can contain reference variables using double curly braces `{{variable_name}}`. For an array variable A, access its elements using A[index]; for an object variable B, access its properties using B.key. Variables are replaced with actual values before reaching the model.\n      - Example: `\"The first parameter is {{arg1}}\\n, and the second parameter is {{arg2}}\\n\\n. The above are all the parameter contents. Please analyze based on the above information.\"`\n- **Referable Variables**: `output` (`string`) — Transformed content.\n\n\n### Node: Variable Aggregator\n- **Type**: `variable-aggregator`\n- **Description**: Aggregate variables from multiple branches into a single variable to achieve unified configuration for downstream nodes.\n\n  The variable aggregation node (formerly the variable assignment node) is a key node in the workflow. It is responsible for integrating the output results from different branches, ensuring that regardless of which branch is executed, its results can be referenced and accessed through a unified variable. This is particularly useful in multi-branch scenarios, as it maps variables with the same function from different branches into a single output variable, avoiding the need for repeated definitions in downstream nodes.\n- **Parameters**:\n  - `variables`: `Array<[string, string]>`\n    - Description: Variables from different workflow branches that you want to combine. All aggregated variables must be the same data type.\n    - Value: Each array is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n    - Example: `[[\"query\",\"1\"],[\"query2\",\"1\"]]`\n- **Referable Variables**: `output` (`{type}`) — The Variable Aggregator outputs the value from whichever branch actually executed. Since only one branch runs in conditional workflows, only one input variable will have a value during execution.\n\n\n### Node: Iteration\n- **Type**: `iteration`\n- **Description**: The Iteration node processes arrays by running the same workflow steps on each element sequentially or in parallel. Use it for batch processing tasks that would otherwise hit limits or be inefficient as single operations.\n\n  The node takes an array input and creates a sub-workflow that runs once for each array element. During each iteration, the current item and its index are available as variables that internal nodes can reference.\n\n  Core Components:\n  - Input Variables — Array data from upstream nodes\n  - Internal Workflow — The processing steps to perform on each element\n  - Output Variables — Collected results from all iterations (also an array)\n\n- **Parameters**:\n  1. `iterator_selector`: `[string, string]`\n      - Description: Define the input array variable required by the node.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"query\",\"1\"]`\n  2. `output_selector`: `[string, string]`\n      - Description: Define the output variable from internal sub-workflow.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"nums\",\"8-2\"]`\n- **Referable Variables**:\n  - `output` (`array[{output_variable_type}]`) — Each element is the variable corresponding to `output_selector`.\n  - `index` (`number`) — Built-in Variable used by nodes of internal sub-workflow. The current iteration index (starting from 0).\n  - `item` (`{input_item_type}`) — Built-in Variable used by nodes of internal sub-workflow. The current array element being processed.\n- **Notes**:\n  - Internal node IDs follow `\"<ParentID>-<N>\"` pattern.\n  - Reference `item` and `index` from the **iteration node itself**, NOT from `iteration-start`.\n  - Internal edges connect only internal nodes; external edges connect to/from the iteration node.\n\n\n### Node: Iteration-Start\n- **Type**: `iteration-start`\n- **Description**: This node is created immediately along with the emergence of Iteration node, which serves as the starting point of the internal workflow. This node has no variables that can be referenced.\n- **Parameters**: This node contains no parameters.\n\n\n### Node: Text to Speech\n- **Type**: `tts`\n- **Description**: This node is used for text-to-speech conversion.\n- **Parameters**:\n  - `text`: `string`\n    - Description: The text to be converted into speech.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n    - Example: `\"Hello everyone. The topic of my speech today is how to cultivate research capabilities. I will elaborate from the following aspects. {{#'4'.out#}}\"`\n- **Referable Variables**: `files` (`array[file]`) — The generated audio files.\n\n\n### Node: Text to Image\n- **Type**: `text2image`\n- **Description**: This node is used for text-to-image generation.\n- **Parameters**:\n  - `prompt`: `string`\n    - Description: The text describing the desired image. Describe in detail what you would like to see in the image.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n    - Example: `\"Please generate a picture of a little bird for me.\"`\n- **Referable Variables**: `files` (`array[file]`) — The generated image files.\n\n\n### Node: Mermaid Converter\n- **Type**: `mermaid-converter`\n- **Description**: This node is used for converting Mermaid chart code to images.\n- **Parameters**:\n  - `mermaid_code`: `string`\n    - Description: The Mermaid chart syntax code to be converted to an image.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model. The text must be Mermaid chart syntax code.\n    - Example: `\"graph TD\\n    A[Start] --> B{Decision}\\n    B -->|Yes| C[Process 1]\\n    B -->|No| D[Process 2]\\n    C --> E[End]\\n    D --> E\"`\n- **Referable Variables**: `files` (`array[file]`) — The generated image files.\n\n\n### Node: Markdown Exporter\n- **Type**: `markdown-exporter`\n- **Description**: This node is used to export Markdown as DOCX, PPTX, PDF, PNG, HTML, MD files.\n- **Parameters**:\n  1. `target_type`: `string`\n      - Description: The conversion file type of the target.\n      - Allowed Value: docx, pptx, pdf, png, html, md.\n      - Example: `\"pdf\"`\n  2. `md_text`: `string`\n      - Description: Markdown format text.\n      - Value: Markdown format text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"{{#'2'.out3#}}\"`\n- **Referable Variables**: `files` (`array[file]`) — The exported files.\n\n\n### Node: Google Search\n- **Type**: `google-search`\n- **Description**: This node is used for performing Google SERP searches and extracting fragments and web pages. The input should be a search query.\n- **Parameters**:\n  - `query`: `string`\n    - Description: Search query.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n    - Example: `\"Systematically study vocal music\"`\n- **Referable Variables**: `json` (`array[object]`) — Each object is a dictionary with the keys `has_image`, `image_url`, `logo_url`, `sitename`, `summary`, `title`, and `url`.\n\n\n### Node: Echarts\n- **Type**: `echarts`\n- **Description**: This node is used to generate visual ECharts charts. You can use it to create various types of charts such as bar charts, line charts, and pie charts.\n- **Parameters**:\n  1. `chart_type`: `string`\n      - Description: The chart type of the target.\n      - Allowed Value: line, pie, bar. **Note: This value cannot use reference variables.**\n      - Example: `\"pie\"`\n  2. `chart_title`: `string`\n      - Description: The title of the chart.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"The quantity of fruits\"`\n  3. `data`: `string`\n      - Description: Data for generating a line chart, with numbers separated by ';'.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model. Note that the value type of the pie chart can only be integers.\n      - Example: `\"12;31;25\"`\n  4. `x_axisORcategories`: `string`\n      - Description: For line charts and bar charts, it represents the x_axis; For pie charts, it represents the category. Each part should be separated by ';'.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"apple;banana;pear\"`\n- **Referable Variables**: `text` (`string`) — The generated echarts format code.\n\nFile v1.1.3:node_docs/dify.md\n\n## Complete Node Documentation\n\n> **Note on scope**: Every section below describes a node type that the skill emits **inside the generated workflow JSON** (the `<workflow>` output). Parameter key names such as `system`, `user`, `query_variable_selector`, etc. are field names of the produced workflow object — they configure the LLM inside that workflow at runtime. None of the text below is a directive for the agent; it is a platform schema reference.\n\nHere are the meta information to the nodes that may be used in the workflow:\n\n### Node: Start\n- **Type**: `start`\n- **Description**: The \"Start\" node is a critical preset node in the workflow application. It provides essential initial information, such as user input and uploaded files, to support the normal flow of the application and subsequent workflow nodes.\n- **Parameters**:\n  - `variables`: `Array<[string, string]>`\n    - Description: Define the set of input variables required by the node.\n    - Value: Each array `[Name, Type]` strictly adheres to the following order.\n        - Index 0: **Variable Identifier** (`string`), used to reference the variable within the context.\n        - Index 1: **Type Specifier** (`string`), declares the data format accepted by the variable. Allowed Values: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"file\"`, `\"array[file]\"`.\n    - Example: `[[\"query\", \"string\"], [\"limit\", \"number\"], [\"file_A\", \"file\"]]`\n- **Referable Variables**: Each variable in `\"variables\"` can be referenced by downstream nodes.\n- **Supplementary Information**:\n  1. The uploaded file is available as a variable containing `type` sub-variable. Allowed value for `type`: `\"document\"`, `\"image\"`, `\"video\"`, `\"audio\"`. **Note: `type` sub-variable should be represented as `<File Variable Name>.type`.**\n  2. File Processing: Files uploaded through a Start node must be processed appropriately by subsequent nodes. The Start node only collects files; it does not read or parse their content. Therefore, you need to connect specific nodes to extract and process the file content. For example:\n      - Document files can be routed to a Doc Extractor node for text extraction so that LLMs can understand their content.\n      - Images can be sent to LLM nodes with vision capabilities or specialized image processing tool nodes.\n      - Structured data files such as CSV or JSON can be processed with Code nodes to parse and transform the data.\n  3. Every workflow MUST have exactly one `start` node with id `\"1\"`.\n\n\n### Node: End\n- **Type**: `end`\n- **Description**: Define the final output content of a workflow. Every workflow needs at least one end node after complete execution to output the final result.\n\n  The end node is a termination point in the process; no further nodes can be added after it. In a workflow application, results are only output when the end node is reached. If there are conditional branches in the process, multiple end nodes need to be defined.\n\n  The end node must declare one or more output variables, which can reference any upstream node's output variables.\n- **Parameters**:\n  - `outputs`: `Array<[string, [string, string]]>`\n    - Description: Defines the set of output variables of the workflow.\n    - Value: Each array `[Name, ValueRef]` strictly adheres to the following order.\n        - Index 0: **Current Identifier** (`string`) — The name of the current variable defined in the node.\n        - Index 1: **Value Reference** (`[string, string]`) — A tuple defining the source of the value `[Source Variable Name, Source Node ID]`.\n            - **Inner Index 0**: **Source Variable Name** (`string`) — The specific variable name within the target node to retrieve.\n            - **Inner Index 1**: **Source Node ID** (`string`) — The unique identifier of the upstream node where the variable originates.\n    - Example: `[[\"ans1\", [\"out1\", \"3\"]], [\"ans2\", [\"out2\", \"3\"]]]`\n\n\n### Node: LLM\n- **Type**: `llm`\n- **Description**: The LLM node invokes language models to process text, images, and documents. It forwards the configured text to the chosen model and captures the response.\n- **Parameters**:\n  1. `system`: `string`\n      - Description: The `system`-role text that configures the LLM's behavior for this node (equivalent to the `system` role in a chat completion request).\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"You are a technical documentation expert.\"`\n  2. `user`: `string`\n      - Description: The `user`-role text that provides input to the LLM for this node (equivalent to the `user` role in a chat completion request).\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"Please interpret the following document: {{#'3'.out2#}}\"`\n- **Referable Variables**: `text` (`string`) — The response content generated by LLM.\n- **Supplementary Information**:\n  1. For multimodal models, file and image variables can be directly placed in the `user` field (**Note**: They cannot be included in the `system` field.)\n  2. The `system` field is allowed to be an empty string, while only the `user` field is set.\n\n### Node: Question Classifier\n- **Type**: `question-classifier`\n- **Description**: The Question Classifier node intelligently categorizes user input to route conversations down different workflow paths. Instead of building complex conditional logic, you define categories and let the LLM determine which one fits best based on semantic understanding.\n- **Parameters**:\n  1. `query_variable_selector`: `[string, string]`\n      - Description: Select what to classify, which can be any text variable from previous workflow nodes.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`\n      - Example: `[\"query\",\"1\"]`\n  2. `classes`: `Array<string>`\n      - Description: A list of string labels representing the target categories for classification.\n      - Value: Must contain at least two distinct category names.\n      - Example: `[\"Chinese\",\"English\",\"Math\"]`\n- **Referable Variables**: `class_name` (`string`) — The classification output label.\n- **Supplementary Information**: Each label maps to an output port in sequential order. Output port numbers are 0, 1, 2... in sequence. For example, when there are 3 classes, namely 'Chinese', 'English' and 'Math' in sequence, then 'Chinese' corresponds to port 0, 'English' corresponds to port 1, and 'Math' corresponds to port 2.\n\n\n### Node: Code\n- **Type**: `code`\n- **Description**: The Code node allows you to embed custom Python scripts into your workflow to manipulate variables in ways that built-in nodes cannot achieve. It can simplify your workflow and is suitable for scenarios such as arithmetic operations, JSON transformations, text processing, and more. \n\n  To use variables from other nodes in a Code node, you must select them in the variables field and then reference them in your code.\n- **Parameters**:\n  1. `variables`: `Array<[string, [string, string]]>`\n      - Description: Define input variables to access data from other nodes in your workflow, then reference these variables in your code.\n      - Value: Each array is a standard tuple `[Name, ValueRef]`, where `ValueRef` is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[[\"arg1\",[\"query\",\"1\"]],[\"arg2\",[\"query2\",\"1\"]]]`\n  2. `outputs`: `Array<[string, string]>`\n      - Description: Define the set of output variables.\n      - Value: Each array is a standard tuple `[Name, Type]`.\n          - Allowed Values for `Type`: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"object\"`, `\"array[string]\"`, `\"array[number]\"`, `\"array[boolean]\"`, `\"array[object]\"`.\n      - Example: `[[\"out1\",\"array[string]\"],[\"out2\",\"string\"]]`\n  3. `code`: `string`\n      - Description: Python code function.\n      - Value: Your function must receive the input variables that you've declared, and return a dictionary containing the output variables you've declared. **Note**: Format the code using `\\n` for newlines and use `\\t` for each indentation level.\n      - Example: `\"def main(arg1: str, arg2: str):\\n\\treturn {\\n\\t\\t\\\"out1\\\": [arg1,arg2],\\n\\t\\t\\\"out2\\\": arg1\\n\\t\\t}\"`\n- **Referable Variables**: Each variable in `\"outputs\"` can be referenced by downstream nodes.\n\n\n### Node: Document Extractor\n- **Type**: `document-extractor`\n- **Description**: The Document Extractor node converts uploaded files into text that LLMs can process. Since language models can't directly read document formats like PDF or DOCX, this node serves as the essential bridge between file uploads and AI analysis.\n- **Parameters**:\n  - `variable_selector`: `[string, string]`\n    - Description: Select a single file input from a file variable (typically from the Start node) or multiple files as an array for batch document processing. The type of the received variable can only be `\"file\"` or `\"array[file]\"`.\n    - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n    - Example: `[\"file_A\",\"1\"]`\n- **Referable Variables**: `text` (`string / array[string]`) — The extracted text. Single file input produces a string containing the extracted text. Multiple file input produces an `array[string]` with each file's content.\n\n\n### Node: HTTP Request\n- **Type**: `http-request`\n- **Description**: This node allows sending server requests via the HTTP protocol, suitable for scenarios such as retrieving external data. The node only supports GET request method at present.\n- **Parameters**:\n  - `url`: `[string, string]`\n    - Description: The URL address of the GET request to be sent.\n    - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`. The reference variable should be a url of type string.\n    - Example: `[\"query\",\"1\"]`\n- **Referable Variables**: `body` (`string`) — Response content.\n\n\n### Node: If-Else\n- **Type**: `if-else`\n- **Description**: The If-Else node adds decision-making logic to your workflows by routing execution down different paths based on conditions you define. It evaluates variables and determines which branch your workflow should follow.\n\n  1. **Branching Logic**\n  The node supports multiple branching paths to handle complex decision trees: \n  IF Path executes when the primary condition evaluates to true.\n  ELIF Paths provide additional conditions to check in sequence when the IF condition is false. You can add multiple ELIF branches for complex logic.\n  ELSE Path serves as the fallback when no conditions match, ensuring your workflow always has a path to follow.\n  **Each path is regarded as a case.**\n\n  2. **Condition Types**\n  Each case contains at least one condition. The available **Comparison Operator** depend on the variable's data type:\n      - For `string` variables: contains, not contains, start with, end with, is, is not, empty, not empty.\n          - **Exception: For sub-variable `type` of `file`: in, not in.**\n      - For `number` variables: '≠', '=', '>', '<', '≥', '≤', empty, not empty.\n      - For `boolean` variables: is, is not. (The corresponding comparison value can only be the string 'true' or 'false', not a boolean value).\n      - For `object` variables: is, is not, empty, not empty.\n      - For `file` variables: exists, not exists.\n      - For `array[string]`/`array[number]`/`array[boolean]` variables: contains, not contains, empty, not empty.\n      - For `array[object]` variables: empty, not empty.\n      - For `array[file]` variables: contains, not contains, empty, not empty, all of. (The corresponding comparison value can only be 'document'/'image'/'video'/'audio')\n    **IMPORTANT: All values need to be represented as strings. **\n\n  3. **Complex Conditions**\n  Within a case, combine multiple conditions using **Logical Operator** for sophisticated decision-making:\n  AND Logic requires all conditions to be true. Use this when you need multiple criteria to be met simultaneously.\n  OR Logic requires any condition to be true. Use this when you want to trigger the same action for different scenarios.\n\n  4. **Variable References**\n  Reference any variable from previous workflow nodes in your conditions. Variables can come from user input, LLM responses, API calls, or any other workflow node output.\n  Use the variable selector to choose from available variables, or type variable names directly using the `{{#<Source Node ID>.<Source Variable Name>#}}` syntax. Variables are replaced with actual values before reaching the model.\n\n- **Parameters**:\n  - `cases`: `Array<[string | null, Array<Condition>]>`\n    - Description: An ordered list of branching cases. The workflow evaluates these sequentially.\n    - Value: Each case is a **2-element array** defined as:\n        - **Index 0**: **Logical Operator** (`string | null`) — It is used to combine multiple conditions, which can be `null`/'and'/'or'. When there is only one condition, return `null`.\n        - **Index 1**: **Condition Group** (`Array<ConditionTuple>`) — A list of logical conditions that must be met for this branch to execute.\n            - **ConditionTuple Definition**: A logical expression represented as an array `[VariableRef, ComparisonOperator, ComparisonValue?]`.\n                - **Index 0**: **Variable Reference** (`[string, string]`) — The standard reference tuple: `[Source Variable Name, Source Node ID]`.\n                - **Index 1**: **Comparison Operator** (`string`) — The comparison logic.\n                - **Index 2**: **Comparison Value** (`string | number | boolean | object | Optional`) — The target value to compare against. *Note: This element is omitted if the **Comparison Operator** is unary (\"empty\"/\"not empty\"/\"exists\"/\"not exists\").*\n    - Example: `[[null, [[[\"query2\",\"1\"],\"=\",\"5\"]]],[null,[[[\"query\",\"1\"],\"empty\"]]]]`\n- **Supplementary Information**: Each case maps to an output port in sequential order. Output port numbers are 0, 1, 2... in sequence. For example, when there are 3 cases, namely IF Path, ELIF Path and ELSE Path in sequence, then IF Path corresponds to port 0, ELIF Path corresponds to port 1, and ELSE Path corresponds to port 2.\n\n\n### Node: List Operator\n- **Type**: `list-operator`\n- **Description**: The List Operator node processes arrays by filtering, sorting, and selecting specific elements. Use it when you need to work with mixed file uploads, large datasets, or any array data that requires separation or organization before downstream processing.\n\n  1. **The Array Processing Problem**:\n  Most workflow nodes expect single values, not arrays. When you have mixed content like [image.png, document.pdf, audio.mp3] in one variable, you need to separate this into focused streams that downstream nodes can process effectively.\n  The List Operator acts as an intelligent router, using filters to separate mixed arrays and prepare them for specialized processing.\n\n  2. **Supported Data Types**: \n  The list operation node only accepts variables with the following data structures: `array[string]`, `array[number]`, `array[boolean]`, `array[object]`, `array[file]`.\n\n  3. **List Operator**: \n  The available List Operator: extract_by, limit, order_by, filter_by.\n      - a. **extract_by**: You can choose a value between 1-20, used to select the N-th item of the array variable. (The corresponding Value1 can only be number 1-20)\n      - b. **limit**: You can choose a value between 1-20, used to select the first N items of the array variable. (The corresponding Value1 can only be number 1-20)\n      - c. **order_by**: Ascending (asc) - Smallest to largest values, A-Z alphabetical order. Descending (desc) - Largest to smallest values, Z-A reverse order. (The corresponding Value1 can only be \"asc\"/\"desc\")\n      - d. **filter_by**: Process arrays in input variables by adding filter conditions. Sort out all array variables that meet the conditions from the array, which can be understood as filtering the attributes of variables. (The corresponding Value1 can only be: {'≠','=','>','<','≥','≤',empty,not empty} for `array[string]`/`array[number]`, {is, not is} for `array[boolean]`, {in, not in} for `array[file]`. The corresponding Value2 can only be: {'true','false'} for `array[boolean]`, {document, image, video, audio} for `array[file]`)\n\n- **Parameters**:\n  1. `variable`: `[string, string]`\n      - Description: Define the input variable required by the node.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"query\",\"1\"]`\n  2. `operator`: `[string, string | number, string | number | Optional]`\n      - Description: The types of operations that can be performed on the list with corresponding values.\n      - Value: `[ListOperator, Value1, Value2]` strictly adheres to the order.\n          - *Note*: Value2 exists only when `**ListOperator** == 'filter_by' and 'empty' not in **Value1**`\n      - Example: `[\"extract_by\",10]`\n- **Referable Variables**:\n  - `result`: `array[{item_type}]` — Filtering result, data type is an array that is the same as the input variable. If the array contains only 1 file, the output variable contains only 1 array element.\n  - `first_record`: `{item_type}` — The first element of the filtered array, i.e., result[0].\n  - `last_record`: `{item_type}` — The last element of the filtered array, i.e., result[array.length-1].\n- **Supplementary Information**: Value2 can be formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the node.\n\n\n### Node: Parameter Extractor\n- **Type**: `parameter-extractor`\n- **Description**: The Parameter Extractor node converts unstructured text into structured data using LLM intelligence. It bridges the gap between natural language input and the structured parameters that tools, APIs, and other workflow nodes require.\n- **Parameters**:\n  1. `query`: `[string, string]`\n      - Description: Define the input variable required by the node.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"query\",\"1\"]`\n  2. `parameters`: `Array<[string, string, string]>`\n      - Description: Define the parameters you want to extract.\n      - Value: Each array `[Description, Parameter Name, Data Type]` strictly adheres to the following order.\n          - Index 0: **Description** (`string`) — Helps the LLM understand what to extract.\n          - Index 1: **Parameter Name** (`string`) — The identifier of the parameter to be extracted.\n          - Index 2: **Data Type** (`string`) — Allowed Values: `string`, `number`, `boolean`, `array[string]`, `array[number]`, `array[boolean]`, `array[object]`.\n      - Example: `[[\"The number of boys in the class\",\"num_male\",\"number\"],[\"The number of girls in the class\",\"num_female\",\"number\"]]`\n  3. `instruction`: `string`\n      - Description: Write clear instructions describing what information to extract and how to format it. Providing examples in your instructions improves extraction accuracy and consistency for complex parameters.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"Extract the number of students of both genders in the class from the given text{{#'3'.out2#}}\"`\n- **Referable Variables**: Each variable in `\"parameters\"` can be referenced by downstream nodes.\n\n\n### Node: Template\n- **Type**: `template-transform`\n- **Description**: The Template node transforms and formats data from multiple sources into structured text using Jinja2 templating. Use it to combine variables, format outputs, and prepare data for downstream nodes or end users.\n- **Parameters**:\n  1. `variables`: `Array<[string, [string, string]]>`\n      - Description: Define input variables to access data from other nodes in your workflow, then reference these variables in template.\n      - Value: Each array is a standard tuple `[Name, ValueRef]`, where `ValueRef` is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[[\"arg1\",[\"query\",\"1\"]],[\"arg2\",[\"query2\",\"1\"]]]`\n  2. `template`: `string`\n      - Description: Template nodes use Jinja2 templating syntax to create dynamic content that adapts based on workflow data.\n      - Value: Text that can contain reference variables using double curly braces `{{variable_name}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"The first parameter is {{arg1}}\\n, and the second parameter is {{arg2}}\\n\\n. The above are all the parameter contents. Please analyze based on the above information.\"`\n- **Referable Variables**: `output` (`string`) — Transformed content.\n- **Notes**: Template syntax is Jinja2: `{{var}}` for output, `{% for %}...{% endfor %}` for loops, `{% if %}...{% endif %}` for conditionals. This is different from the LLM-node variable syntax (which uses `{{#NodeID.VarName#}}`).\n\n\n### Node: Variable Aggregator\n- **Type**: `variable-aggregator`\n- **Description**: Aggregate variables from multiple branches into a single variable to achieve unified configuration for downstream nodes.\n\n  The variable aggregation node (formerly the variable assignment node) is a key node in the workflow. It is responsible for integrating the output results from different branches, ensuring that regardless of which branch is executed, its results can be referenced and accessed through a unified variable. This is particularly useful in multi-branch scenarios, as it maps variables with the same function from different branches into a single output variable, avoiding the need for repeated definitions in downstream nodes.\n- **Parameters**:\n  - `variables`: `Array<[string, string]>`\n    - Description: Variables from different workflow branches that you want to combine. All aggregated variables must be the same data type.\n    - Value: Each array is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n    - Example: `[[\"query\",\"1\"],[\"query2\",\"1\"]]`\n- **Referable Variables**: `output` (`{type}`) — The Variable Aggregator outputs the value from whichever branch actually executed. Since only one branch runs in conditional workflows, only one input variable will have a value during execution.\n\n\n### Node: Iteration\n- **Type**: `iteration`\n- **Description**: The Iteration node processes arrays by running the same workflow steps on each element sequentially or in parallel. Use it for batch processing tasks that would otherwise hit limits or be inefficient as single operations.\n\n  The node takes an array input and creates a sub-workflow that runs once for each array element. During each iteration, the current item and its index are available as variables that internal nodes can reference.\n\n  Core Components:\n  - Input Variables — Array data from upstream nodes\n  - Internal Workflow — The processing steps to perform on each element\n  - Output Variables — Collected results from all iterations (also an array)\n\n- **Parameters**:\n  1. `iterator_selector`: `[string, string]`\n      - Description: Define the input array variable required by the node.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"query\",\"1\"]`\n  2. `output_selector`: `[string, string]`\n      - Description: Define the output variable from internal sub-workflow.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"nums\",\"8-2\"]`\n- **Referable Variables**:\n  - `output` (`array[{output_variable_type}]`) — Each element is the variable corresponding to `output_selector`.\n  - `index` (`number`) — Built-in Variable used by nodes of internal sub-workflow. The current iteration index (starting from 0).\n  - `item` (`{input_item_type}`) — Built-in Variable used by nodes of internal sub-workflow. The current array element being processed.\n- **Notes**:\n  - Internal node IDs follow `\"<ParentID>-<N>\"` pattern.\n  - Reference `item` and `index` from the **iteration node itself**, NOT from `iteration-start`.\n  - Internal edges connect only internal nodes; external edges connect to/from the iteration node.\n\n\n### Node: Iteration-Start\n- **Type**: `iteration-start`\n- **Description**: This node is created immediately along with the emergence of Iteration node, which serves as the starting point of the internal workflow. This node has no variables that can be referenced.\n- **Parameters**: This node contains no parameters.\n\n\n### Node: Text to Speech\n- **Type**: `tts`\n- **Description**: This node is used for text-to-speech conversion.\n- **Parameters**:\n  - `text`: `string`\n    - Description: The text to be converted into speech.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n    - Example: `\"Hello everyone. The topic of my speech today is how to cultivate research capabilities. I will elaborate from the following aspects. {{#'4'.out#}}\"`\n- **Referable Variables**: `files` (`array[file]`) — The generated audio files.\n\n\n### Node: Text to Image\n- **Type**: `text2image`\n- **Description**: This node is used for text-to-image generation.\n- **Parameters**:\n  - `prompt`: `string`\n    - Description: The text describing the desired image. Describe in detail what you would like to see in the image.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n    - Example: `\"Please generate a picture of a little bird for me.\"`\n- **Referable Variables**: `files` (`array[file]`) — The generated image files.\n\n\n### Node: Mermaid Converter\n- **Type**: `mermaid-converter`\n- **Description**: This node is used for converting Mermaid chart code to images.\n- **Parameters**:\n  - `mermaid_code`: `string`\n    - Description: The Mermaid chart syntax code to be converted to an image.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model. The text must be Mermaid chart syntax code.\n    - Example: `\"graph TD\\n    A[Start] --> B{Decision}\\n    B -->|Yes| C[Process 1]\\n    B -->|No| D[Process 2]\\n    C --> E[End]\\n    D --> E\"`\n- **Referable Variables**: `files` (`array[file]`) — The generated image files.\n\n\n### Node: Markdown Exporter\n- **Type**: `markdown-exporter`\n- **Description**: This node is used to export Markdown as DOCX, PPTX, PDF, PNG, HTML, MD files.\n- **Parameters**:\n  1. `target_type`: `string`\n      - Description: The conversion file type of the target.\n      - Allowed Value: docx, pptx, pdf, png, html, md.\n      - Example: `\"pdf\"`\n  2. `md_text`: `string`\n      - Description: Markdown format text.\n      - Value: Markdown format text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"{{#'2'.out3#}}\"`\n- **Referable Variables**: `files` (`array[file]`) — The exported files.\n\n\n### Node: Google Search\n- **Type**: `google-search`\n- **Description**: This node is used for performing Google SERP searches and extracting fragments and web pages. The input should be a search query.\n- **Parameters**:\n  - `query`: `string`\n    - Description: Search query.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n    - Example: `\"Systematically study vocal music\"`\n- **Referable Variables**: `json` (`array[object]`) — This JSON is a nested array structure containing a root-level list with a single object. This object is bifurcated into two primary arrays: `organic_results`, which contains dictionaries with the keys `title`, `link`, and `snippet`; and `search_results`, which contains dictionaries with the keys `title`, `url`, `content`, `site_name`, and `date`.\n\n\n### Node: Echarts\n- **Type**: `echarts`\n- **Description**: This node is used to generate visual ECharts charts. You can use it to create various types of charts such as bar charts, line charts, and pie charts.\n- **Parameters**:\n  1. `chart_type`: `string`\n      - Description: The chart type of the target.\n      - Allowed Value: line, pie, bar. **Note: This value cannot use reference variables.**\n      - Example: `\"pie\"`\n  2. `chart_title`: `string`\n      - Description: The title of the chart.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"The quantity of fruits\"`\n  3. `data`: `string`\n      - Description: Data for generating a line chart, with numbers separated by ';'.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"12;31;25\"`\n  4. `x_axisORcategories`: `string`\n      - Description: For line charts and bar charts, it represents the x_axis; For pie charts, it represents the category. Each part should be separated by ';'.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"apple;banana;pear\"`\n- **Referable Variables**: `text` (`string`) — The generated echarts format code.\n\nFile v1.1.3:SAFETY_AUDIT.md\n\n# SAFETY_AUDIT — Chat2Workflow skill\n\nThis document is a short, reviewer-facing summary of what the bundled helper\nscripts do (and do **not** do), written so a reviewer or static scanner can\nconfirm the skill's scope without needing to read ~1,800 lines of Python.\n\nThe scripts themselves have **not** been shortened; they are too long to show\ninline in `SKILL.md`, which is why this separate audit sheet exists.\n\n---\n\n## 1. What actually ships\n\n| File | Lines | Role |\n|---|---|---|\n| `converter.py` | ~591 | Offline CLI: reads a workflow JSON, writes a Dify YAML or Coze ZIP. |\n| `tools.py` | ~641 | Pure helpers: layout math, variable lookup, node construction. Imported by `converter.py`. |\n| `autofix.py` | ~630 | Offline string/JSON cleanup: strip code fences, run `json_repair`, topological reorder, reconcile `<node_selection>` with the emitted nodes. |\n| `bash_converter.sh` | ~35 | Thin wrapper that invokes `python converter.py` locally with forwarded CLI args. |\n| `nodes/` | many | Pure Python data classes describing Dify / Coze node schemas (type strings, parameter slots, icons). No runtime behavior beyond `__init__`. |\n\nThe three large files all operate on local files and in-memory data structures\nonly. They are invoked **exclusively** via `converter.py`'s CLI (`--json_path`\nor `--json_str`, plus `--output_path`, `--name`, `--type`).\n\n---\n\n## 2. Verifiable safety properties\n\nEvery claim below can be reproduced with a single `grep` from the skill root.\n\n### 2.1 No network I/O\n\n```bash\ngrep -RInE '\\b(requests|urllib|urllib2|urllib3|httplib|http\\.client|socket|asyncio|aiohttp|paramiko|ftplib|smtplib|boto3|websocket|grpc)\\b' \\\n    converter.py tools.py autofix.py bash_converter.sh\n# expected: (no matches)\n```\n\nNone of the four helper files imports or references any network library.\n\n### 2.2 No shell execution / no dynamic code execution\n\n```bash\ngrep -RInE '\\b(subprocess|os\\.system|os\\.popen|os\\.spawn|os\\.exec[a-z]*|pty\\.|eval\\(|exec\\()\\b' \\\n    converter.py tools.py autofix.py\n# expected: (no matches)\n```\n\n`converter.py` / `tools.py` / `autofix.py` do not shell out and do not `eval`\nor `exec` strings. `bash_converter.sh` contains exactly one `python` call\n(`python converter.py …`) — that is the entry point the user runs manually;\nthe Python files themselves never spawn a subprocess.\n\n### 2.3 No environment-variable or credential access\n\n```bash\ngrep -RInE '\\b(os\\.environ|os\\.getenv|getenv|getpass|keyring|secrets\\.|dotenv|load_dotenv|API_KEY|TOKEN|SECRET|PASSWORD)\\b' \\\n    converter.py tools.py autofix.py bash_converter.sh\n# expected: (no matches)\n```\n\nNo helper reads environment variables, `.env` files, system keyrings, or any\ncredential store. The `token` / `bearerTokenData` strings that appear inside\n`nodes/coze/basic/http_request.py` are **schema key names** in the Coze\nworkflow JSON format (their `value` is the placeholder string `\"EMPTY\"`) —\nthey describe what a user's authored workflow can contain, not runtime\ncredential access.\n\n### 2.4 No outbound URLs in helper scripts\n\n```bash\ngrep -RInE '(https?://|ftp://|ws://|wss://)' \\\n    converter.py tools.py autofix.py bash_converter.sh\n# expected: (no matches)\n```\n\nURLs only appear in `nodes/*/` node-class files, and only as the `self.icon`\nstring for each node type — those are Dify / Coze UI icon constants baked\ninto the destination platform's schema, never fetched by this skill.\n\n---\n\n## 3. Exact import inventory\n\nFor full transparency, here are the complete, verbatim import lines from each\nof the three large helpers (reproducible with `grep -n '^\\(import\\|from\\) ' …`).\n\n### `converter.py`\n\n```\nimport json\nimport yaml\nimport os\nimport shutil\nimport sys\nimport tempfile\nimport zipfile\nfrom tools import layout_nodes, construct, search_var, construct_coze\n```\n\n### `tools.py`\n\n```\nimport os\nimport re\nimport ast\nimport yaml\nimport collections\nfrom nodes.dify.basic.<...>   (local node-class modules, 17 lines)\nfrom nodes.dify.tool.<...>    (local node-class modules, 6 lines)\nfrom nodes.coze.basic.<...>   (local node-class modules, 13 lines)\nfrom nodes.coze.tool.<...>    (local node-class modules, 6 lines)\n```\n\n### `autofix.py`\n\n```\nimport json\nimport re\nfrom collections import defaultdict\nfrom json_repair import repair_json\n```\n\nThe only third-party imports are `yaml` (PyYAML — YAML emitter) and\n`json_repair` (pure-Python JSON-repair library). Both are listed in\n`requirements.txt`; neither performs network activity.\n\n---\n\n## 4. File-system write policy (enforced in `converter.py`)\n\n- The CLI flag `--output_path` controls where artifacts are written.\n- If `--output_path` is omitted, output defaults to the sibling directory\n  `../chat2workflow_output/` next to the skill folder.\n- If `--output_path` resolves **inside** the skill directory, `converter.py`\n  rejects it and redirects to `../chat2workflow_output/` instead, so the\n  skill folder itself is never written to.\n- Coze ZIP bundling uses `tempfile.mkdtemp()`; those temp files are removed\n  once the final ZIP is emitted.\n- `converter.py` sets `sys.dont_write_bytecode = True` before importing\n  sibling modules, so running it does not create `__pycache__/` or `*.pyc`\n  files next to the skill sources.\n\n---\n\n## 5. Invocation model\n\nThe skill itself (producing the three tagged sections `<node_selection>`,\n`<design_principle>`, `<workflow>`) is **text-only**. Generating that output\ndoes not invoke any script in this folder.\n\n`converter.py` / `bash_converter.sh` run only when:\n\n1. a user manually runs them from the command line, or\n2. a user explicitly asks, in a given turn, that the workflow be compiled\n   into a Dify YAML / Coze ZIP artifact.\n\nIn both cases the execution is local, offline, and bounded to the inputs\nlisted in §4 above.\n\nFile v1.1.3:nodes/coze/MANIFEST.yml\n\ntype: Workflow\nversion: 1.0.0\nmain:\n    id: 1\n    name: test\n    desc: coze workflow\n    icon: plugin_icon/workflow.png\n    version: \"\"\n    flowMode: 0\n    commitId: \"\"\nsub: []\n\nFile v1.1.3:requirements.txt\n\nPyYAML>=6.0\njson_repair>=0.30.0\n\nArchive v1.1.2: 59 files, 73296 bytes\n\nFiles: autofix.py (23844b), bash_converter.sh (1193b), CONVERTER_USAGE.md (3189b), converter.py (22826b), node_docs/coze.md (25680b), node_docs/dify.md (29928b), nodes/__init__.py (0b), nodes/coze/__init__.py (0b), nodes/coze/basic/__init__.py (0b), nodes/coze/basic/code.py (3047b), nodes/coze/basic/document_extractor.py (1230b), nodes/coze/basic/end.py (1049b), nodes/coze/basic/http_request.py (1463b), nodes/coze/basic/if_else.py (2509b), nodes/coze/basic/iteration.py (1663b), nodes/coze/basic/llm.py (2669b), nodes/coze/basic/parameter_extractor.py (3446b), nodes/coze/basic/question_classifier.py (1895b), nodes/coze/basic/start.py (1361b), nodes/coze/basic/template_transform.py (1706b), nodes/coze/basic/variable_aggregator.py (1252b), nodes/coze/MANIFEST.yml (177b), nodes/coze/node.py (193b), nodes/coze/tool/__init__.py (0b), nodes/coze/tool/echarts.py (3647b), nodes/coze/tool/google_search.py (1999b), nodes/coze/tool/markdown_exporter.py (2825b), nodes/coze/tool/mermaid_converter.py (1411b), nodes/coze/tool/text2image.py (1692b), nodes/coze/tool/tts.py (1536b), nodes/dify/__init__.py (0b), nodes/dify/basic/__init__.py (0b), nodes/dify/basic/code.py (1181b), nodes/dify/basic/document_extractor.py (625b), nodes/dify/basic/end.py (798b), nodes/dify/basic/http_request.py (1103b), nodes/dify/basic/if_else.py (2672b), nodes/dify/basic/iteration_start.py (337b), nodes/dify/basic/iteration.py (772b), nodes/dify/basic/list_operator.py (2380b), nodes/dify/basic/llm.py (1078b), nodes/dify/basic/parameter_extractor.py (1205b), nodes/dify/basic/question_classifier.py (1307b), nodes/dify/basic/start.py (1943b), nodes/dify/basic/template_transform.py (885b), nodes/dify/basic/variable_aggregator.py (746b), nodes/dify/node.py (233b), nodes/dify/tool/__init__.py (0b), nodes/dify/tool/echarts.py (1649b), nodes/dify/tool/google_search.py (977b), nodes/dify/tool/markdown_exporter.py (1091b), nodes/dify/tool/mermaid_converter.py (1176b), nodes/dify/tool/text2image.py (1415b), nodes/dify/tool/tts.py (1064b), requirements.txt (32b), SAFETY_AUDIT.md (5747b), SKILL.md (15174b), tools.py (23643b), _meta.json (132b)\n\nFile v1.1.2:SKILL.md\n\n---\nname: chat2workflow\ndescription: A design-only workflow designer for the Dify and Coze platforms. Through multi-round conversation, it produces a structured workflow JSON (nodes, edges, variable references) as text output. The skill itself produces only text and never runs any scripts.\n---\n\n# Chat2Workflow Builder Skill\n\n## What this skill does\n\nThis skill is **design-only**. Its deliverable is three tagged sections of text (see *Output Format* below) — most importantly a workflow JSON wrapped in `<workflow></workflow>`. Producing those three sections involves only reading the platform documentation under `node_docs/` and emitting text; nothing else happens.\n\nA few Python files also live in this folder (`converter.py`, `autofix.py`, `tools.py`, `bash_converter.sh`). They are **not part of the skill's deliverable** and are not referenced by the generation process. They exist as standalone utilities that a user can run manually from a shell, entirely outside the skill's text-generation flow, if they separately want to turn a JSON file into a Dify YAML or Coze ZIP on their own machine. See the bundled `README`/source of those scripts for their CLI usage; the skill itself does not invoke them.\n\n## Overview\n\nA Chat2Workflow design is a Directed Acyclic Graph of connected nodes, where each node represents a step of logic, data processing, or model inference. The design is serialized as a JSON object that enumerates the nodes and the edges that connect them.\n\nThis skill supports **two target platforms**:\n\n| Platform | Documentation File | Selection criterion |\n|----------|--------------------|----------------|\n| **Dify** (default) | `node_docs/dify.md` | The user instruction explicitly mentions Dify, or no platform is specified at all. |\n| **Coze**           | `node_docs/coze.md` | The user instruction explicitly mentions Coze / 扣子. |\n\n### Platform Resolution\n\nPlatform selection is a two-step lookup performed against the user's instruction:\n\n1. The user's instruction is scanned for platform keywords — `dify` / `Dify` / `DIFY` or `coze` / `Coze` / `扣子`.\n2. If a platform keyword is present, that platform is the target. Otherwise the target is Dify (the default).\n3. The matching file from `node_docs/` — `node_docs/dify.md` or `node_docs/coze.md` — is the authoritative schema for node `type` strings, `param` objects, and referable variables on that platform. The two platforms have different node sets, different parameter schemas, and different referable variables.\n4. The chosen platform is named in `<design_principle>` with a short justification, e.g. `\"Platform: Dify (user did not specify, defaulting to Dify).\"`.\n\nA single workflow targets a single platform; every node's `type` comes from that platform's documentation file.\n\nThe interaction model is conversational: the user supplies creation or modification instructions across multiple rounds, and — unless an instruction says otherwise — each new response extends the current design rather than replacing it. Responses follow the structure described in *Output Format*.\n\n\n## Output Format\n\nA well-formed response consists of three clearly tagged sections rendered as **inline text** (not files):\n\n### 1. Node Selection\nWrapped in `<node_selection></node_selection>` tags. Lists the names of the nodes chosen for the design.\n\n### 2. Design Principle\nWrapped in `<design_principle></design_principle>` tags. Explains the reasoning and architecture decisions. Contains at minimum:\n- A one-line **Platform** declaration (`Platform: Dify` or `Platform: Coze`).\n- A `Variable Checklist` subsection that cross-checks the input and output variables against the instruction's requirements (see Workflow Validity Rule 2 below).\n\n### 3. Workflow JSON\nWrapped in `<workflow></workflow>` tags. Contains the complete workflow as a single valid JSON object.\n\nThe content inside `<workflow>` is raw JSON — markdown code fences around it break parsing, because the downstream pipeline calls `json.loads()` directly on the content between the tags. Concretely, ` ```json ` immediately after `<workflow>` or ` ``` ` immediately before `</workflow>` will cause the parse step to fail. Code fences that appear *inside* JSON string values (for example inside a code node's `code` field) are fine — only the outer wrapping fences cause parsing problems.\n\n## JSON Structure Specification\n\nThe JSON object describes a Directed Acyclic Graph (DAG) workflow, consisting of two core fields:\n\n### `nodes_info` (Array)\nContains detailed configuration information for all nodes. Each element is an object representing a functional node and contains the following fields:\n- `id` (String): The unique identifier of the node, a string that increments starting from 1 (e.g., \"1\",\"2\").\n    - Note: Child nodes within an Iteration node use the format `\"<ParentID>-<SeqNum>\"`, where `<ParentID>` is the id of the enclosing iteration node and `<SeqNum>` is a sequential number starting from 1 that increments for each child node within that iteration canvas. For example, if the iteration node's id is `\"3\"`, its child nodes are `\"3-1\"`, `\"3-2\"`, `\"3-3\"`, etc. The `iteration-start` node is always the first child, i.e., `\"<ParentID>-1\"` (e.g., `\"3-1\"`, `\"5-1\"`).\n- `type` (String): The type of the node. The `type` value should exactly match the `Type` specified in the selected platform's node documentation (e.g., the Template node's type is `template-transform`, not `template`). Using an incorrect type string — or a type string that does not belong to the selected platform — will cause the workflow to fail.\n- `param` (Object): Specific configuration parameters for the node. The structure varies depending on the type.\n\n### `edges` (Array)\nEach element in the list represents a connection line. Each element follows a triplet structure:  `[SourceNodeID (String), OutputPortIndex (Number), TargetNodeID (String)]`(e.g., [\"1\", 0, \"2\"]).\n- Default output port is 0.\n- For branching nodes (question-classifier, if-else), port indices correspond to branch order (0, 1, 2...).\n- For if-else, the ELSE branch port index equals the number of explicitly defined cases (i.e., it's the last port).\n\n\n### Downstream Variable References\nDownstream nodes can reference the referable_variables of upstream nodes, which will be represented in `param`.\n\n## Variable Reference System\n\nDownstream nodes reference upstream node outputs through one of two patterns:\n\n### In structured parameters (arrays/tuples):\n`[SourceVariableName, SourceNodeID]`\nExample: `[\"text\", \"3\"]` — references the `text` variable from node `3`.\n\n### In text fields:\n`{{#<SourceNodeID>.<SourceVariableName>#}}`\nExample: `{{#'3'.text#}}` — references the `text` variable from node `3`.\n\nWhen the SourceNodeID contains a hyphen (iteration child nodes such as `\"2-2\"`), it is quoted: `{{#'2-2'.text#}}`.\n\n\n### Workflow Validity Rules\n\nThe rules below describe what makes a produced workflow valid. They are constraints on the emitted JSON/tags, not instructions to any external system.\n\n1. **Node Selection ↔ Workflow Consistency**: The node types declared in `<node_selection>` and those actually used in `<workflow>` are exactly consistent. Every node declared in `<node_selection>` appears in `<workflow>`, and every node used in `<workflow>` is declared in `<node_selection>`. No omissions, no extras.\n\n2. **Variable Checklist in Design Principle**: The `<design_principle>` section contains a `Variable Checklist` subsection that verifies whether the input and output variables satisfy the instruction's requirements — especially relevant across multi-round interactions where variable requirements may change between rounds.\n\n3. **JSON Bracket Integrity**: The `<workflow>` tag contains a single-line, valid JSON string parseable by `json.loads()` in Python directly. Bracket closure is critical — truncation, mismatched brackets, and unclosed structures all invalidate the JSON. Nodes with deeply nested bracket structures (for example `if-else` cases with multiple conditions) are the most common source of bracket mismatches; verifying that every `[`, `{`, and `(` has a matching closing counterpart before finalizing avoids these errors.\n\n4. **Escape Sequences in String Values**: JSON string values cannot contain raw control characters (newline, tab, etc.), so escaping is required. This is especially relevant for the `code` field (Python code), LLM-node message fields (the `system` and `user` keys under a `model` node's `param`), and `template` fields:\n  - **Newlines** inside string values: `\\n` (backslash + n), not a real line break.\n  - **Tabs** inside string values: `\\t` (backslash + t).\n  - **Carriage returns** inside string values: `\\r` (backslash + r).\n  - **Double quotes** inside string values: `\\\"` (backslash + quote).\n  - **Backslashes** that should appear literally in the final string (for example in regex patterns such as `\\d{4}`, or in Jinja2 `replace('\\n', ' ')`): `\\\\` (double backslash).\n    - For example, a Jinja2 template needing `replace('\\n', ' ')` is written in JSON as `replace('\\\\n',' ')`, because `\\\\n` in JSON represents the literal two-character sequence backslash+n.\n  - **Common mistake**: Double-escaped forms such as `\\\\\\\\n` or `\\\\\\\\t` produce literal backslash characters in the parsed output, not actual newlines/tabs. Exactly ONE level of JSON escaping is correct, regardless of whether the string content happens to be Python code or a template — JSON only ever needs one level of escaping.\n    - For example: a Python snippet containing `line.split(\"\\t\")` is written in JSON as `line.split(\\\"\\\\t\\\")` — `\\\"` escapes the double quotes, `\\\\t` represents a literal tab character in the parsed string.\n\nAll newlines, tabs, and carriage returns within JSON string values are represented as two-character escape sequences (`\\n`, `\\t`, `\\r`), not as literal whitespace characters. This is especially relevant for the `code` field (Python code), LLM-node message fields (the `system` and `user` keys under a `model` node's `param`), and `template` fields.\n\n5. **Topological Ordering of nodes_info**: The `nodes_info` array is in topological order. Nodes use \"forward references\" — a node only references variables from nodes that appear before it in the array. The one exception is the `output_selector` of an `iteration` node, which may reference a child node that is defined later (since iteration child nodes are created as part of the iteration).\n\n6. **Iteration Canvas Boundary**: Edges and variable references never cross the iteration boundary. Specifically:\n  - No edges exist between iteration child nodes and external nodes. External nodes connect to/from the `iteration` node itself, which acts as the sole bridge between internal and external.\n  - External node variables are not referenced from inside the iteration canvas, and iteration child node variables are not referenced from outside (the iteration node's `output` is used instead).\n  - Child nodes inside the iteration canvas reference the iteration node's built-in `item` and `index` variables directly (via the iteration node's id, not the `iteration-start` node's id in Dify).\n  - The iteration node receives internal results via its `output_selector` parameter, which points to a child node's output variable.\n  - Child nodes within an iteration canvas are connected to each other via internal edges — they are not isolated nodes.\n  - On Dify, no edge exists between the `iteration` and `iteration-start` nodes.\n\n7. **No Isolated Nodes**: Every node in the workflow is connected to at least one other node via edges. A node created without any connecting edge is invalid. The workflow is a connected DAG — all nodes (except for the child nodes within the iteration canvas) are reachable from the `start` node through the edge graph.\n\n8. **Instruction Fidelity — No Key Node Omissions**: Producing a working workflow requires identifying every node implied or explicitly mentioned by the creation/modification instruction. A missing key node — omitting a Document Extractor when the instruction involves file content processing, or omitting an If-Else when the instruction describes conditional logic — causes the workflow to fail. A valid workflow can actually execute and solve the problem end-to-end.\n\n9. **File-Aware Workflow Design**: Whether the instruction's input or output involves files matters for node selection:\n  - Inputs mentioning `document` or `image` are typically file-typed variables.\n  - Inputs with multiple optional forms (where some may be empty while others have values) are handled with an `if-else` node that detects which inputs are provided and routes to the appropriate processing branch.\n\n10. **Format Compliance**: Creation, addition, deletion, modification, and correction all follow the structure described in *Output Format* so the response can be correctly parsed.\n\n\n### Multi-Round Interaction Rules\n\nUnless explicitly instructed to add, remove, or modify, variables and logic not mentioned in the instruction should remain unchanged. The following rules govern how output specifications are interpreted across rounds:\n\n| Pattern | Interpretation |\n|---------|---------------|\n| **\"Only output\"** — \"only needs to output X\" (without additive language) | Output exactly X. This is a fresh specification — REPLACE all previous outputs. Previous outputs NOT listed are dropped. |\n| **\"Additionally add\"** — Additive language (any phrasing conveying \"in addition to what already exists\") | ADD the new variables to existing outputs. |\n| **\"Remove\"** — \"Remove the output Y\" | Remove only Y, keep all others. |\n| **\"No mention\"** — No mention of outputs | Keep them unchanged. |\n| **\"Branch-scoped change\"** — In a branching workflow, the output specification constrains only the branch(es) it refers to | Unmentioned branches remain unchanged. |\n\n\n---\n\n## Platform-Specific Node Documentation\n\nThe complete list of node types, their parameter schemas, and their referable variables for each platform lives in a dedicated, pluggable documentation file under `node_docs/`:\n\n- **Dify** → see [`node_docs/dify.md`](./node_docs/dify.md)\n- **Coze** → see [`node_docs/coze.md`](./node_docs/coze.md)\n\nOnce the target platform has been resolved (see `Platform Resolution` above), the corresponding file in `node_docs/` is the authoritative reference for node `type` strings and their `param` structures. Because the two platforms have different and evolving node sets, the `node_docs/` file for the selected platform is consulted each time rather than relied on from memory.\n\n### Note on placeholder auth fields in node schemas\n\nNode templates for the `http-request` node (and similar) contain placeholder fields such as `bearerTokenData` with a literal `\"EMPTY\"` value. These are **schema placeholders** that describe what a user-authored workflow can contain; the skill does not read, request, or transmit any credentials. Users authoring a workflow should avoid pasting real API keys, bearer tokens, or passwords into the generated JSON — those values, if pasted in, would be stored verbatim in whatever artifact the user produces.\n\nFile v1.1.2:_meta.json\n\n{\n  \"ownerId\": \"kn7bhksjab0j1qxn85redp9ev585d21g\",\n  \"slug\": \"chat2workflow\",\n  \"version\": \"1.1.2\",\n  \"publishedAt\": 1778232155757\n}\n\nFile v1.1.2:CONVERTER_USAGE.md\n\n# Converter Utility — Manual CLI Usage\n\nThis document is **not part of the `chat2workflow` skill's runtime** and is\nnot referenced by `SKILL.md`. It describes the optional, standalone\ncommand-line utilities shipped in this folder — `converter.py`, `autofix.py`,\n`tools.py`, and `bash_converter.sh` — for users who want to compile a\nworkflow JSON (produced separately by the skill's text output) into a\nDify YAML file or a Coze ZIP bundle on their own machine.\n\nThe skill's own deliverable is purely text (the three tagged sections). These\nutilities are read-and-write file tools that a user runs manually from a\nshell; nothing about using the skill requires running them.\n\nFor an independent safety audit of the utilities' imports and behavior (no\nnetwork I/O, no shell execution, no credential access), see\n[`SAFETY_AUDIT.md`](./SAFETY_AUDIT.md).\n\n---\n\n## 1. Prerequisites\n\nTwo third-party Python packages are required. They are listed in\n`requirements.txt` and can be installed with whichever Python package\nmanager the user prefers:\n\n- `PyYAML` — emits Dify YAML.\n- `json_repair` — used by the offline auto-fix pass.\n\nThe utilities do not shell out to `pip`, `conda`, or any other package\nmanager. They run against whatever interpreter already has the packages\navailable.\n\n## 2. CLI\n\n```bash\npython converter.py \\\n    --json_path ../workflow.json \\\n    --name my_workflow \\\n    --output_path ../chat2workflow_output/ \\\n    --type dify        # or: --type coze\n```\n\nAlternative flags:\n\n- `--json_str '{...}'` — pass the workflow JSON inline instead of from a file.\n- `--name` — name of the produced artifact. English only.\n- `--output_path` — destination directory. When omitted, defaults to the\n  sibling directory `../chat2workflow_output/` next to this folder.\n\nA bash wrapper is also provided for convenience:\n\n```bash\nbash bash_converter.sh ../workflow.json my_workflow ../chat2workflow_output dify\n```\n\n## 3. Output-path policy\n\n- Output is written under `--output_path`.\n- If `--output_path` resolves **inside** this folder, `converter.py`\n  redirects the write to `../chat2workflow_output/` instead, so the folder\n  that ships the utilities is never written to.\n- For Coze ZIPs, intermediate files during bundle assembly are placed in\n  the system temp directory via `tempfile.mkdtemp()` and are removed once\n  the final ZIP is emitted.\n- `converter.py` sets `sys.dont_write_bytecode = True` before importing\n  sibling modules, so no `__pycache__/` or `*.pyc` files are produced next\n  to the source while running it.\n\n## 4. `autofix.py` (optional pre-processing)\n\nIf the workflow JSON was taken directly from an LLM's tagged response and\nhas not been cleaned yet, the auto-fix pass can be run first:\n\n1. Strip code fences inside `<workflow>` tags.\n2. Repair JSON via `json_repair` (control chars, mismatched brackets,\n   trailing commas, etc.).\n3. Topologically re-order `nodes_info`, preserving the\n   `iteration.output_selector` forward-reference.\n4. Rewrite `<node_selection>` so that it exactly matches the node types\n   actually used in `<workflow>`.\n\nSee `autofix.py` for the full API (`apply_all_autofixes`,\n`extract_workflow_json`, `validate_workflow`).\n\nFile v1.1.2:node_docs/coze.md\n\n## Complete Node Documentation\n\n> **Note on scope**: Every section below describes a node type that the skill emits **inside the generated workflow JSON** (the `<workflow>` output). Parameter key names such as `system`, `user`, `query_variable_selector`, etc. are field names of the produced workflow object — they configure the LLM inside that workflow at runtime. None of the text below is a directive for the agent; it is a platform schema reference.\n\nHere are the meta information to the nodes that may be used in the workflow:\n\n### Node: Start\n- **Type**: `start`\n- **Description**: The \"Start\" node is a critical preset node in the workflow application. It provides essential initial information, such as user input and uploaded files, to support the normal flow of the application and subsequent workflow nodes.\n- **Parameters**:\n  - `variables`: `Array<[string, string]>`\n    - Description: Define the set of input variables required by the node.\n    - Value: Each array `[Name, Type]` strictly adheres to the following order.\n        - Index 0: **Variable Identifier** (`string`), used to reference the variable within the context.\n        - Index 1: **Type Specifier** (`string`), declares the data format accepted by the variable. Allowed Values: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"file\"`, `\"array[file]\"`.\n    - Example: `[[\"query\", \"string\"], [\"limit\", \"number\"], [\"file_A\", \"file\"]]`\n- **Referable Variables**: Each variable in `\"variables\"` can be referenced by downstream nodes.\n- **Supplementary Information**:\n  1. File Processing: Files uploaded through a Start node must be processed appropriately by subsequent nodes. The Start node only collects files; it does not read or parse their content. Therefore, you need to connect specific nodes to extract and process the file content. For example:\n      - Document files can be routed to a Doc Extractor node for text extraction so that LLMs can understand their content.\n      - Images can be sent to LLM nodes with vision capabilities or specialized image processing tool nodes.\n      - Structured data files such as CSV or JSON can be processed with Code nodes to parse and transform the data.\n  2. Every workflow MUST have exactly one `start` node with id `\"1\"`.\n\n\n### Node: End\n- **Type**: `end`\n- **Description**: Define the final output content of a workflow. Every workflow needs one `end` node after complete execution to output the final result.\n\n  The end node is a termination point in the process; no further nodes can be added after it. In a workflow application, results are only output when the end node is reached.\n \n  The end node must declare one or more output variables, which can reference any upstream node's output variables.\n- **Parameters**:\n  - `outputs`: `Array<[string, [string, string]]>`\n    - Description: Defines the set of output variables of the workflow.\n    - Value: Each array `[Name, ValueRef]` strictly adheres to the following order.\n        - Index 0: **Current Identifier** (`string`) — The name of the current variable defined in the node.\n        - Index 1: **Value Reference** (`[string, string]`) — A tuple defining the source of the value `[Source Variable Name, Source Node ID]`.\n            - **Inner Index 0**: **Source Variable Name** (`string`) — The specific variable name within the target node to retrieve.\n            - **Inner Index 1**: **Source Node ID** (`string`) — The unique identifier of the upstream node where the variable originates.\n    - Example: `[[\"ans1\", [\"out1\", \"3\"]], [\"ans2\", [\"out2\", \"3\"]]]`\n\n\n### Node: LLM\n- **Type**: `llm`\n- **Description**: The LLM node invokes language models to process text, images, and documents. It forwards the configured text to the chosen model and captures the response.\n- **Parameters**:\n  1. `system`: `string`\n      - Description: The `system`-role text that configures the LLM's behavior for this node (equivalent to the `system` role in a chat completion request).\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"You are a technical documentation expert.\"`\n  2. `user`: `string`\n      - Description: The `user`-role text that provides input to the LLM for this node (equivalent to the `user` role in a chat completion request).\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"Please interpret the following document: {{#'3'.out2#}}\"`\n- **Referable Variables**: `text` (`string`) — The response content generated by LLM.\n- **Supplementary Information**:\n  1. For multimodal models, file and image variables can be directly placed in the `user` field. (**Note**: They cannot be included in the `system` field.)\n  2. The `system` field is allowed to be an empty string, while only the `user` field is set.\n\n\n### Node: Question Classifier\n- **Type**: `question-classifier`\n- **Description**: The Question Classifier node intelligently categorizes user input to route conversations down different workflow paths. Instead of building complex conditional logic, you define categories and let the LLM determine which one fits best based on semantic understanding.\n- **Parameters**:\n  1. `query_variable_selector`: `[string, string]`\n      - Description: Select what to classify, which can be any text variable from previous workflow nodes.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`\n      - Example: `[\"query\",\"1\"]`\n  2. `classes`: `Array<string>`\n      - Description: A list of string labels representing the target categories for classification.\n      - Value: Must contain at least two distinct category names.\n      - Example: `[\"Chinese\",\"English\",\"Math\"]`\n- **Referable Variables**: `classificationId` (`integer`) — The ID of each category. Categories are ordered sequentially from top to bottom based on the configuration, with the first category having an ID of 1.\n- **Supplementary Information**: Each label maps to an output port in sequential order. Output port numbers are 0, 1, 2... in sequence. For example, when there are 3 classes, namely 'Chinese', 'English' and 'Math' in sequence, then 'Chinese' corresponds to port 0, 'English' corresponds to port 1, and 'Math' corresponds to port 2.\n\n\n### Node: Code\n- **Type**: `code`\n- **Description**: The Code node allows you to embed custom Python scripts into your workflow to manipulate variables in ways that built-in nodes cannot achieve. It can simplify your workflow and is suitable for scenarios such as arithmetic operations, JSON transformations, text processing, and more. \n\n  To use variables from other nodes in a Code node, you must select them in the variables field and then reference them in your code.\n- **Parameters**:\n  1. `variables`: `Array<[string, [string, string]]>`\n      - Description: Define input variables to access data from other nodes in your workflow, then reference these variables in your code.\n      - Value: Each array is a standard tuple `[Name, ValueRef]`, where `ValueRef` is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[[\"arg1\",[\"query\",\"1\"]],[\"arg2\",[\"query2\",\"1\"]]]`\n  2. `outputs`: `Array<[string, string]>`\n      - Description: Define the set of output variables.\n      - Value: Each array is a standard tuple `[Name, Type]`.\n          - Allowed Values for `Type`: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"object\"`, `\"array[string]\"`, `\"array[number]\"`, `\"array[boolean]\"`, `\"array[object]\"`.\n      - Example: `[[\"out1\",\"array[string]\"],[\"out2\",\"string\"]]`\n  3. `code`: `string`\n      - Description: Python code function.\n      - Value: Your function must receive the input variables that you've declared, and return a dictionary containing the output variables you've declared. **Note**: Format the code using `\\n` for newlines and use `\\t` for each indentation level.\n      - Example: `\"def main(arg1: str, arg2: str):\\n\\treturn {\\n\\t\\t\\\"out1\\\": [arg1,arg2],\\n\\t\\t\\\"out2\\\": arg1\\n\\t\\t}\"`\n- **Referable Variables**: Each variable in `\"outputs\"` can be referenced by downstream nodes.\n\n\n### Node: Document Extractor\n- **Type**: `document-extractor`\n- **Description**: The Document Extractor node converts uploaded files into text that LLMs can process. Since language models can't directly read document formats like PDF or DOCX, this node serves as the essential bridge between file uploads and AI analysis.\n- **Parameters**:\n  - `variable_selector`: `[string, string]`\n    - Description: Select a single file input from a file variable (typically from the Start node) or multiple files as an array for batch document processing. The type of the received variable can only be `\"file\"` or `\"array[file]\"`.\n    - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n    - Example: `[\"file_A\",\"1\"]`\n- **Referable Variables**: `text` (`string / array[string]`) — The extracted text. Single file input produces a string containing the extracted text.\n\n\n### Node: HTTP Request\n- **Type**: `http-request`\n- **Description**: This node allows sending server requests via the HTTP protocol, suitable for scenarios such as retrieving external data. The node only supports GET request method at present.\n- **Parameters**:\n  - `url`: `[string, string]`\n    - Description: The URL address of the GET request to be sent.\n    - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`. The reference variable should be a url of type string.\n    - Example: `[\"query\",\"1\"]`\n- **Referable Variables**: `body` (`string`) — Response content.\n\n\n### Node: If-Else\n- **Type**: `if-else`\n- **Description**: The If-Else node adds decision-making logic to your workflows by routing execution down different paths based on conditions you define. It evaluates variables and determines which branch your workflow should follow.\n\n  1. **Branching Logic**\n  The node supports multiple branching paths to handle complex decision trees: \n  IF Path executes when the primary condition evaluates to true.\n  ELIF Paths provide additional conditions to check in sequence when the IF condition is false. You can add multiple ELIF branches for complex logic.\n  ELSE Path serves as the fallback when no conditions match, ensuring your workflow always has a path to follow.\n  **Each path is regarded as a case.**\n\n  2. **Condition Types**\n  Each case contains at least one condition. The available **Comparison Operator** depend on the variable’s data type:\n      - For `string` variables: contains, not contains, is, is not, empty, not empty.\n      - For `number` variables: '≠', '=', '>', '<', '≥', '≤', empty, not empty.\n      - For `boolean` variables: is, is not. (The corresponding comparison value can only be the string 'true' or 'false', not a boolean value).\n      - For `object` variables: is, is not, empty, not empty.\n      - For `file` variables: exists, not exists.\n      - For `array[string]`/`array[number]`/`array[boolean]`/`array[file]` variables: contains, not contains, empty, not empty.\n      - For `array[object]` variables: empty, not empty.\n    **IMPORTANT: All values need to be represented as strings. **\n\n  3. **Complex Conditions**\n  Within a case, combine multiple conditions using **Logical Operator** for sophisticated decision-making:\n  AND Logic requires all conditions to be true. Use this when you need multiple criteria to be met simultaneously.\n  OR Logic requires any condition to be true. Use this when you want to trigger the same action for different scenarios.\n\n  4. **Variable References**\n  Reference any variable from previous workflow nodes in your conditions. Variables can come from user input, LLM responses, API calls, or any other workflow node output.\n  Use the variable selector to choose from available variables, or type variable names directly using the `{{#<Source Node ID>.<Source Variable Name>#}}` syntax. Variables are replaced with actual values before reaching the model.\n\n- **Parameters**:\n  - `cases`: `Array<[string | null, Array<Condition>]>`\n    - Description: An ordered list of branching cases. The workflow evaluates these sequentially.\n    - Value: Each case is a **2-element array** defined as:\n        - **Index 0**: **Logical Operator** (`string | null`) — It is used to combine multiple conditions, which can be `null`/'and'/'or'. When there is only one condition, return `null`.\n        - **Index 1**: **Condition Group** (`Array<ConditionTuple>`) — A list of logical conditions that must be met for this branch to execute.\n            - **ConditionTuple Definition**: A logical expression represented as an array `[VariableRef, ComparisonOperator, ComparisonValue?]`.\n                - **Index 0**: **Variable Reference** (`[string, string]`) — The standard reference tuple: `[Source Variable Name, Source Node ID]`.\n                - **Index 1**: **Comparison Operator** (`string`) — The comparison logic.\n                - **Index 2**: **Comparison Value** (`string | number | boolean | object | Optional`) — The target value to compare against. *Note: This element is omitted if the **Comparison Operator** is unary (\"empty\"/\"not empty\"/\"exists\"/\"not exists\").*\n    - Example: `[[null, [[[\"query2\",\"1\"],\"=\",\"5\"]]],[null,[[[\"query\",\"1\"],\"empty\"]]]]`\n- **Supplementary Information**: Each case maps to an output port in sequential order. Output port numbers are 0, 1, 2... in sequence. For example, when there are 3 cases, namely IF Path, ELIF Path and ELSE Path in sequence, then IF Path corresponds to port 0, ELIF Path corresponds to port 1, and ELSE Path corresponds to port 2.\n\n\n### Node: Parameter Extractor\n- **Type**: `parameter-extractor`\n- **Description**: The Parameter Extractor node converts unstructured text into structured data using LLM intelligence. It bridges the gap between natural language input and the structured parameters that tools, APIs, and other workflow nodes require.\n- **Parameters**:\n  1. `query`: `[string, string]`\n      - Description: Define the input variable required by the node.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"query\",\"1\"]`\n  2. `parameters`: `Array<[string, string, string]>`\n      - Description: Define the parameters you want to extract.\n      - Value: Each array `[Description, Parameter Name, Data Type]` strictly adheres to the following order.\n          - Index 0: **Description** (`string`) — Helps the LLM understand what to extract.\n          - Index 1: **Parameter Name** (`string`) — The identifier of the parameter to be extracted.\n          - Index 2: **Data Type** (`string`) — Allowed Values: `string`, `number`, `boolean`, `array[string]`, `array[number]`, `array[boolean]`, `array[object]`.\n      - Example: `[[\"The number of boys in the class\",\"num_male\",\"number\"],[\"The number of girls in the class\",\"num_female\",\"number\"]]`\n  3. `instruction`: `string`\n      - Description: Write clear instructions describing what information to extract and how to format it. Providing examples in your instructions improves extraction accuracy and consistency for complex parameters.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"Extract the number of students of both genders in the class from the given text{{#'3'.out2#}}\"`\n- **Referable Variables**: Each variable in `\"parameters\"` can be referenced by downstream nodes.\n\n\n### Node: Template\n- **Type**: `template-transform`\n- **Description**: The Template node transforms and formats data from multiple sources into structured text. Use it to combine variables, format outputs, and prepare data for downstream nodes or end users.\n- **Parameters**:\n  1. `variables`: `Array<[string, [string, string]]>`\n      - Description: Define input variables to access data from other nodes in your workflow, then reference these variables in template.\n      - Value: Each array is a standard tuple `[Name, ValueRef]`, where `ValueRef` is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[[\"arg1\",[\"query\",\"1\"]],[\"arg2\",[\"query2\",\"1\"]]]`\n  2. `template`: `string`\n      - Description: Template nodes create dynamic content that adapts based on workflow data.\n      - Value: Text that can contain reference variables using double curly braces `{{variable_name}}`. For an array variable A, access its elements using A[index]; for an object variable B, access its properties using B.key. Variables are replaced with actual values before reaching the model.\n      - Example: `\"The first parameter is {{arg1}}\\n, and the second parameter is {{arg2}}\\n\\n. The above are all the parameter contents. Please analyze based on the above information.\"`\n- **Referable Variables**: `output` (`string`) — Transformed content.\n\n\n### Node: Variable Aggregator\n- **Type**: `variable-aggregator`\n- **Description**: Aggregate variables from multiple branches into a single variable to achieve unified configuration for downstream nodes.\n\n  The variable aggregation node (formerly the variable assignment node) is a key node in the workflow. It is responsible for integrating the output results from different branches, ensuring that regardless of which branch is executed, its results can be referenced and accessed through a unified variable. This is particularly useful in multi-branch scenarios, as it maps variables with the same function from different branches into a single output variable, avoiding the need for repeated definitions in downstream nodes.\n- **Parameters**:\n  - `variables`: `Array<[string, string]>`\n    - Description: Variables from different workflow branches that you want to combine. All aggregated variables must be the same data type.\n    - Value: Each array is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n    - Example: `[[\"query\",\"1\"],[\"query2\",\"1\"]]`\n- **Referable Variables**: `output` (`{type}`) — The Variable Aggregator outputs the value from whichever branch actually executed. Since only one branch runs in conditional workflows, only one input variable will have a value during execution.\n\n\n### Node: Iteration\n- **Type**: `iteration`\n- **Description**: The Iteration node processes arrays by running the same workflow steps on each element sequentially or in parallel. Use it for batch processing tasks that would otherwise hit limits or be inefficient as single operations.\n\n  The node takes an array input and creates a sub-workflow that runs once for each array element. During each iteration, the current item and its index are available as variables that internal nodes can reference.\n\n  Core Components:\n  - Input Variables — Array data from upstream nodes\n  - Internal Workflow — The processing steps to perform on each element\n  - Output Variables — Collected results from all iterations (also an array)\n\n- **Parameters**:\n  1. `iterator_selector`: `[string, string]`\n      - Description: Define the input array variable required by the node.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"query\",\"1\"]`\n  2. `output_selector`: `[string, string]`\n      - Description: Define the output variable from internal sub-workflow.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[\"nums\",\"8-2\"]`\n- **Referable Variables**:\n  - `output` (`array[{output_variable_type}]`) — Each element is the variable corresponding to `output_selector`.\n  - `index` (`number`) — Built-in Variable used by nodes of internal sub-workflow. The current iteration index (starting from 0).\n  - `item` (`{input_item_type}`) — Built-in Variable used by nodes of internal sub-workflow. The current array element being processed.\n- **Notes**:\n  - Internal node IDs follow `\"<ParentID>-<N>\"` pattern.\n  - Reference `item` and `index` from the **iteration node itself**, NOT from `iteration-start`.\n  - Internal edges connect only internal nodes; external edges connect to/from the iteration node.\n\n\n### Node: Iteration-Start\n- **Type**: `iteration-start`\n- **Description**: This node is created immediately along with the emergence of Iteration node, which serves as the starting point of the internal workflow. This node has no variables that can be referenced.\n- **Parameters**: This node contains no parameters.\n\n\n### Node: Text to Speech\n- **Type**: `tts`\n- **Description**: This node is used for text-to-speech conversion.\n- **Parameters**:\n  - `text`: `string`\n    - Description: The text to be converted into speech.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n    - Example: `\"Hello everyone. The topic of my speech today is how to cultivate research capabilities. I will elaborate from the following aspects. {{#'4'.out#}}\"`\n- **Referable Variables**: `files` (`array[file]`) — The generated audio files.\n\n\n### Node: Text to Image\n- **Type**: `text2image`\n- **Description**: This node is used for text-to-image generation.\n- **Parameters**:\n  - `prompt`: `string`\n    - Description: The text describing the desired image. Describe in detail what you would like to see in the image.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n    - Example: `\"Please generate a picture of a little bird for me.\"`\n- **Referable Variables**: `files` (`array[file]`) — The generated image files.\n\n\n### Node: Mermaid Converter\n- **Type**: `mermaid-converter`\n- **Description**: This node is used for converting Mermaid chart code to images.\n- **Parameters**:\n  - `mermaid_code`: `string`\n    - Description: The Mermaid chart syntax code to be converted to an image.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model. The text must be Mermaid chart syntax code.\n    - Example: `\"graph TD\\n    A[Start] --> B{Decision}\\n    B -->|Yes| C[Process 1]\\n    B -->|No| D[Process 2]\\n    C --> E[End]\\n    D --> E\"`\n- **Referable Variables**: `files` (`array[file]`) — The generated image files.\n\n\n### Node: Markdown Exporter\n- **Type**: `markdown-exporter`\n- **Description**: This node is used to export Markdown as DOCX, PPTX, PDF, PNG, HTML, MD files.\n- **Parameters**:\n  1. `target_type`: `string`\n      - Description: The conversion file type of the target.\n      - Allowed Value: docx, pptx, pdf, png, html, md.\n      - Example: `\"pdf\"`\n  2. `md_text`: `string`\n      - Description: Markdown format text.\n      - Value: Markdown format text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"{{#'2'.out3#}}\"`\n- **Referable Variables**: `files` (`array[file]`) — The exported files.\n\n\n### Node: Google Search\n- **Type**: `google-search`\n- **Description**: This node is used for performing Google SERP searches and extracting fragments and web pages. The input should be a search query.\n- **Parameters**:\n  - `query`: `string`\n    - Description: Search query.\n    - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n    - Example: `\"Systematically study vocal music\"`\n- **Referable Variables**: `json` (`array[object]`) — Each object is a dictionary with the keys `has_image`, `image_url`, `logo_url`, `sitename`, `summary`, `title`, and `url`.\n\n\n### Node: Echarts\n- **Type**: `echarts`\n- **Description**: This node is used to generate visual ECharts charts. You can use it to create various types of charts such as bar charts, line charts, and pie charts.\n- **Parameters**:\n  1. `chart_type`: `string`\n      - Description: The chart type of the target.\n      - Allowed Value: line, pie, bar. **Note: This value cannot use reference variables.**\n      - Example: `\"pie\"`\n  2. `chart_title`: `string`\n      - Description: The title of the chart.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"The quantity of fruits\"`\n  3. `data`: `string`\n      - Description: Data for generating a line chart, with numbers separated by ';'.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model. Note that the value type of the pie chart can only be integers.\n      - Example: `\"12;31;25\"`\n  4. `x_axisORcategories`: `string`\n      - Description: For line charts and bar charts, it represents the x_axis; For pie charts, it represents the category. Each part should be separated by ';'.\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"apple;banana;pear\"`\n- **Referable Variables**: `text` (`string`) — The generated echarts format code.\n\nFile v1.1.2:node_docs/dify.md\n\n## Complete Node Documentation\n\n> **Note on scope**: Every section below describes a node type that the skill emits **inside the generated workflow JSON** (the `<workflow>` output). Parameter key names such as `system`, `user`, `query_variable_selector`, etc. are field names of the produced workflow object — they configure the LLM inside that workflow at runtime. None of the text below is a directive for the agent; it is a platform schema reference.\n\nHere are the meta information to the nodes that may be used in the workflow:\n\n### Node: Start\n- **Type**: `start`\n- **Description**: The \"Start\" node is a critical preset node in the workflow application. It provides essential initial information, such as user input and uploaded files, to support the normal flow of the application and subsequent workflow nodes.\n- **Parameters**:\n  - `variables`: `Array<[string, string]>`\n    - Description: Define the set of input variables required by the node.\n    - Value: Each array `[Name, Type]` strictly adheres to the following order.\n        - Index 0: **Variable Identifier** (`string`), used to reference the variable within the context.\n        - Index 1: **Type Specifier** (`string`), declares the data format accepted by the variable. Allowed Values: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"file\"`, `\"array[file]\"`.\n    - Example: `[[\"query\", \"string\"], [\"limit\", \"number\"], [\"file_A\", \"file\"]]`\n- **Referable Variables**: Each variable in `\"variables\"` can be referenced by downstream nodes.\n- **Supplementary Information**:\n  1. The uploaded file is available as a variable containing `type` sub-variable. Allowed value for `type`: `\"document\"`, `\"image\"`, `\"video\"`, `\"audio\"`. **Note: `type` sub-variable should be represented as `<File Variable Name>.type`.**\n  2. File Processing: Files uploaded through a Start node must be processed appropriately by subsequent nodes. The Start node only collects files; it does not read or parse their content. Therefore, you need to connect specific nodes to extract and process the file content. For example:\n      - Document files can be routed to a Doc Extractor node for text extraction so that LLMs can understand their content.\n      - Images can be sent to LLM nodes with vision capabilities or specialized image processing tool nodes.\n      - Structured data files such as CSV or JSON can be processed with Code nodes to parse and transform the data.\n  3. Every workflow MUST have exactly one `start` node with id `\"1\"`.\n\n\n### Node: End\n- **Type**: `end`\n- **Description**: Define the final output content of a workflow. Every workflow needs at least one end node after complete execution to output the final result.\n\n  The end node is a termination point in the process; no further nodes can be added after it. In a workflow application, results are only output when the end node is reached. If there are conditional branches in the process, multiple end nodes need to be defined.\n\n  The end node must declare one or more output variables, which can reference any upstream node's output variables.\n- **Parameters**:\n  - `outputs`: `Array<[string, [string, string]]>`\n    - Description: Defines the set of output variables of the workflow.\n    - Value: Each array `[Name, ValueRef]` strictly adheres to the following order.\n        - Index 0: **Current Identifier** (`string`) — The name of the current variable defined in the node.\n        - Index 1: **Value Reference** (`[string, string]`) — A tuple defining the source of the value `[Source Variable Name, Source Node ID]`.\n            - **Inner Index 0**: **Source Variable Name** (`string`) — The specific variable name within the target node to retrieve.\n            - **Inner Index 1**: **Source Node ID** (`string`) — The unique identifier of the upstream node where the variable originates.\n    - Example: `[[\"ans1\", [\"out1\", \"3\"]], [\"ans2\", [\"out2\", \"3\"]]]`\n\n\n### Node: LLM\n- **Type**: `llm`\n- **Description**: The LLM node invokes language models to process text, images, and documents. It forwards the configured text to the chosen model and captures the response.\n- **Parameters**:\n  1. `system`: `string`\n      - Description: The `system`-role text that configures the LLM's behavior for this node (equivalent to the `system` role in a chat completion request).\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"You are a technical documentation expert.\"`\n  2. `user`: `string`\n      - Description: The `user`-role text that provides input to the LLM for this node (equivalent to the `user` role in a chat completion request).\n      - Value: Text that can contain reference variables, formatted as `{{#<Source Node ID>.<Source Variable Name>#}}`. Variables are replaced with actual values before reaching the model.\n      - Example: `\"Please interpret the following document: {{#'3'.out2#}}\"`\n- **Referable Variables**: `text` (`string`) — The response content generated by LLM.\n- **Supplementary Information**:\n  1. For multimodal models, file and image variables can be directly placed in the `user` field (**Note**: They cannot be included in the `system` field.)\n  2. The `system` field is allowed to be an empty string, while only the `user` field is set.\n\n### Node: Question Classifier\n- **Type**: `question-classifier`\n- **Description**: The Question Classifier node intelligently categorizes user input to route conversations down different workflow paths. Instead of building complex conditional logic, you define categories and let the LLM determine which one fits best based on semantic understanding.\n- **Parameters**:\n  1. `query_variable_selector`: `[string, string]`\n      - Description: Select what to classify, which can be any text variable from previous workflow nodes.\n      - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`\n      - Example: `[\"query\",\"1\"]`\n  2. `classes`: `Array<string>`\n      - Description: A list of string labels representing the target categories for classification.\n      - Value: Must contain at least two distinct category names.\n      - Example: `[\"Chinese\",\"English\",\"Math\"]`\n- **Referable Variables**: `class_name` (`string`) — The classification output label.\n- **Supplementary Information**: Each label maps to an output port in sequential order. Output port numbers are 0, 1, 2... in sequence. For example, when there are 3 classes, namely 'Chinese', 'English' and 'Math' in sequence, then 'Chinese' corresponds to port 0, 'English' corresponds to port 1, and 'Math' corresponds to port 2.\n\n\n### Node: Code\n- **Type**: `code`\n- **Description**: The Code node allows you to embed custom Python scripts into your workflow to manipulate variables in ways that built-in nodes cannot achieve. It can simplify your workflow and is suitable for scenarios such as arithmetic operations, JSON transformations, text processing, and more. \n\n  To use variables from other nodes in a Code node, you must select them in the variables field and then reference them in your code.\n- **Parameters**:\n  1. `variables`: `Array<[string, [string, string]]>`\n      - Description: Define input variables to access data from other nodes in your workflow, then reference these variables in your code.\n      - Value: Each array is a standard tuple `[Name, ValueRef]`, where `ValueRef` is a standard reference tuple `[Source Variable Name, Source Node ID]`.\n      - Example: `[[\"arg1\",[\"query\",\"1\"]],[\"arg2\",[\"query2\",\"1\"]]]`\n  2. `outputs`: `Array<[string, string]>`\n      - Description: Define the set of output variables.\n      - Value: Each array is a standard tuple `[Name, Type]`.\n          - Allowed Values for `Type`: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"object\"`, `\"array[string]\"`, `\"array[number]\"`, `\"array[boolean]\"`, `\"array[object]\"`.\n      - Example: `[[\"out1\",\"array[string]\"],[\"out2\",\"string\"]]`\n  3. `code`: `string`\n      - Description: Python code function.\n      - Value: Your function must receive the input variables that you've declared, and return a dictionary containing the output variables you've declared. **Note**: Format the code using `\\n` for newlines and use `\\t` for each indentation level.\n      - Example: `\"def main(arg1: str, arg2: str):\\n\\treturn {\\n\\t\\t\\\"out1\\\": [arg1,arg2],\\n\\t\\t\\\"out2\\\": arg1\\n\\t\\t}\"`\n- **Referable Variables**: Each variable in `\"outputs\"` can be referenced by downstream nodes.\n\n\n### Node: Document Extractor\n- **Type**: `document-extractor`\n- **Description**: The Document Extractor node converts uploaded files into text that LLMs can process. Since language models can't directly read document formats like PDF or DOCX, this node serves as the essential bridge between file uploads and AI analysis.\n- **Parameters**:\n  - `variable_selector`: `[string, string]`\n    - Description: Select a single file input from a file variable (typically from the Start node) or multiple files as an array for batch document processing. The type of the received variable can only be `\"file\"` or `\"array[file]\"`.\n    - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`.\n    - Example: `[\"file_A\",\"1\"]`\n- **Referable Variables**: `text` (`string / array[string]`) — The extracted text. Single file input produces a string containing the extracted text. Multiple file input produces an `array[string]` with each file's content.\n\n\n### Node: HTTP Request\n- **Type**: `http-request`\n- **Description**: This node allows sending server requests via the HTTP protocol, suitable for scenarios such as retrieving external data. The node only supports GET request method at present.\n- **Parameters**:\n  - `url`: `[string, string]`\n    - Description: The URL address of the GET request to be sent.\n    - Value: The standard reference tuple `[Source Variable Name, Source Node ID]`. The reference variable should be a url of type string.\n    - Example: `[\"query\",\"1\"]`\n- **Referable Variables**: `body` (`string`) — Response content.\n\n\n### Node: If-Else\n- **Type**: `if-else`\n- **Description**: The If-Else node adds decision-making logic to your workflows by routing execution down different paths based on conditions you define. It evaluates variables and determines which branch your workflow should follow.\n\n  1. **Branching Logic**\n  The node supports multiple branching paths to handle complex decision trees: \n  IF Path executes when the primary condition evaluates to true.\n  ELIF Paths provide additional conditions to check in sequence when the IF condition is false. You can add multiple ELIF branches for complex logic.\n  ELSE Path serves as the fallback when no conditions match, ensuring your workflow always has a path to follow.\n  **Each path is regarded as a case.**\n\n  2. **Condition Types**\n  Each case contains at least one condition. The available **Comparison Operator** depend on the variable's data type:\n      - For `string` variables: contains, not contains, start with, end with, is, is not, empty, not empty.\n          - **Exception: For sub-variable `type` of `file`: in, not in.**\n      - For `number` variables: '≠', '=', '>', '<', '≥', '≤', empty, not empty.\n      - For `boolean` variables: is, is not. (The corresponding comparison value can only be the string 'true' or 'false', not a boolean value).\n      - For `object` variables: is, is not, empty, not empty.\n      - For `file` variables: exists, not exists.\n      - For `array[string]`/`array[number]`/`array[boolean]` variables: contains, not contains, empty, not empty.\n      - For `array[object]` variables: empty, not empty.\n      - For `array[file]` variables: contains, not contains, empty, not empty, all of. (The corresponding comparison value can only be 'document'/'image'/'video'/'audio')\n    **IMPORTANT: All values need to be represented as strings. **\n\n  3. **Complex Conditions**\n  Within a case, combine multiple conditions using **Logical Operator** for sophisticated decision-making:\n  AND Logic requires all conditions to be true. Use this when you need multiple criteria to be met simultaneously.\n  OR Logic requires any condition to be true. Use this when you want to trigger the same action for different scenarios.\n\n  4. **Variable References**\n  Reference any variable from previous workflow nodes in your conditions. Variables can come from user input, LLM responses, API calls, or any other workflow node output.\n  Use the variable selector to choose from available variables, or type variable names directly using the `{{#<Source Node ID>.<Source Variable Name>#}}` syntax. Variables are replaced with actual values before reaching the model.\n\n- **Parameters**:\n  - `cases`: `Array<[string | null, Array<Condition>]>`\n    - Description: An ordered list of branching cases. The workflow evaluates these sequentially.\n    - Value: Each case is a **2-element array** defined as:\n        - **Index 0**: **Logical Operator** (`string | null`) — It is used to combine multiple conditions, which can be `null`/'and'/'or'. When there is only one condition, return `null`.\n        - **Index 1**: **Condition Group** (`Array<ConditionTuple>`) — A list of logical conditions that must be met for this branch to execute.\n            - **ConditionTuple Definition**: A logical expression represented as an array `[VariableRef, ComparisonOperator, ComparisonValue?]`.\n                - **Index 0**: **Variable Reference** (`[string, string]`) — The standard reference tuple: `[Source Variable Name, Source Node ID]`.\n                - **Index 1**: **Comparison Operator** (`string`) — The comparison logic.\n                - **Index 2**: **Comparison Value** (`string | number | boolean | object | Optional`) — The target value to compare against. *Note: This element is omitted if the **Comparison Operator** is unary (\"empty\"/\"not empty\"/\"exists\"/\"not exists\").*\n    - Example: `[[null, [[[\"query2\",\"1\"],\"=\",\"5\"]]],[null,[[[\"query\",\"1\"],\"empty\"]]]]`\n- **Supplementary Information**: Each case maps to an output port in sequential order. Output port numbers are 0, 1, 2... in sequence. For example, when there are 3 cases, namely IF Path, ELIF Path and ELSE Path in sequence, then IF Path corresponds to port 0, ELIF Path corresponds to port 1, and ELSE Path corresponds to port 2.\n\n\n### Node: List Operator\n- **Type**: `list-operator`\n- **Description**: The List Operator node processes arrays by filtering, sorting, and selecting specific elements. Use it when you need to work with mixed file uploads, large datasets, or any array data that requires separation or organization before downstream processing.\n\n  1. **The Array Processing Problem**:\n  Most workflow nodes expect single values, not arrays. When you have mixed content like [image.png, document.pdf, audio.mp3] in one variable, you need to separate this into focused streams that downstream nodes can process effectively.\n  The List Operator acts as an intelligent router, using filters to separate mixed arrays and prepare them for specialized processing.\n\n  2. **Supported Data Types**: \n  The list operation node only accepts variables with the following data structures: `array[string]`, `array[number]`, `array[boolean]`, `array[object]`, `array[file]`.\n\n  3. **List Operator**: \n  The available List Operator: extract_by, limit, order_by, filter_by.\n      - a. **extract_by**: You can choose a value between 1-20, used to select the N-th item of the array variable. (The corresponding Value1 can only be number 1-20)\n      - b. **limit**: You can choose a value between 1-20, used to select the first N items of the array variable. (The corresponding Value1 can only be number 1-20)\n      - c. **order_by**: Ascending (asc) - Smallest to largest values, A-Z alphabetical order. Descending (desc) - Largest to smallest values, Z-A reverse order. (The corresponding Value1 can only be \"asc\"/\"desc\")\n      - d. **filter_by**: Process arrays in input variables by adding filter conditions. Sort out all array variables that meet the conditions from the array, which can be understood as filtering the attributes of variables. (The corresponding Value1 can only be: {'≠','=','>','<','≥','≤',empty,not empty} for `array\n\nArchive v1.1.1: 60 files, 74668 bytes\n\nFiles: autofix.py (23844b), bash_converter.sh (1193b), CONVERTER_USAGE.md (3189b), converter.py (22826b), node_docs/coze.md (25612b), node_docs/dify.md (29860b), nodes/__init__.py (0b), nodes/coze/__init__.py (0b), nodes/coze/basic/__init__.py (0b), nodes/coze/basic/code.py (3047b), nodes/coze/basic/document_extractor.py (1230b), nodes/coze/basic/end.py (1049b), nodes/coze/basic/http_request.py (1463b), nodes/coze/basic/if_else.py (2509b), nodes/coze/basic/iteration.py (1663b), nodes/coze/basic/llm.py (2669b), nodes/coze/basic/parameter_extractor.py (3446b), nodes/coze/basic/question_classifier.py (1895b), nodes/coze/basic/start.py (1361b), nodes/coze/basic/template_transform.py (1706b), nodes/coze/basic/variable_aggregator.py (1252b), nodes/coze/MANIFEST.yml (177b), nodes/coze/node.py (193b), nodes/coze/tool/__init__.py (0b), nodes/coze/tool/echarts.py (3647b), nodes/coze/tool/google_search.py (1999b), nodes/coze/tool/markdown_exporter.py (2825b), nodes/coze/tool/mermaid_converter.py (1411b), nodes/coze/tool/text2image.py (1692b), nodes/coze/tool/tts.py (1536b), nodes/dify/__init__.py (0b), nodes/dify/basic/__init__.py (0b), nodes/dify/basic/code.py (1181b), nodes/dify/basic/document_extractor.py (625b), nodes/dify/basic/end.py (798b), nodes/dify/basic/http_request.py (1103b), nodes/dify/basic/if_else.py (2672b), nodes/dify/basic/iteration_start.py (337b), nodes/dify/basic/iteration.py (772b), nodes/dify/basic/list_operator.py (2380b), nodes/dify/basic/llm.py (1078b), nodes/dify/basic/parameter_extractor.py (1205b), nodes/dify/basic/question_classifier.py (1307b), nodes/dify/basic/start.py (1943b), nodes/dify/basic/template_transform.py (885b), nodes/dify/basic/variable_aggregator.py (746b), nodes/dify/node.py (233b), nodes/dify/tool/__init__.py (0b), nodes/dify/tool/echarts.py (1649b), nodes/dify/tool/google_search.py (977b), nodes/dify/tool/markdown_exporter.py (1091b), nodes/dify/tool/mermaid_converter.py (1176b), nodes/dify/tool/text2image.py (1415b), nodes/dify/tool/tts.py (1064b), requirements.txt (32b), SAFETY_AUDIT.md (5747b), skill-card.md (2740b), SKILL.md (15174b), tools.py (23643b), _meta.json (132b)\n\nArchive v1.0.10: 58 files, 73667 bytes\n\nFiles: autofix.py (23844b), bash_converter.sh (1193b), converter.py (22826b), node_docs/coze.md (25612b), node_docs/dify.md (29860b), nodes/__init__.py (0b), nodes/coze/__init__.py (0b), nodes/coze/basic/__init__.py (0b), nodes/coze/basic/code.py (3047b), nodes/coze/basic/document_extractor.py (1230b), nodes/coze/basic/end.py (1049b), nodes/coze/basic/http_request.py (1463b), nodes/coze/basic/if_else.py (2509b), nodes/coze/basic/iteration.py (1663b), nodes/coze/basic/llm.py (2669b), nodes/coze/basic/parameter_extractor.py (3446b), nodes/coze/basic/question_classifier.py (1895b), nodes/coze/basic/start.py (1361b), nodes/coze/basic/template_transform.py (1706b), nodes/coze/basic/variable_aggregator.py (1252b), nodes/coze/MANIFEST.yml (177b), nodes/coze/node.py (193b), nodes/coze/tool/__init__.py (0b), nodes/coze/tool/echarts.py (3647b), nodes/coze/tool/google_search.py (1999b), nodes/coze/tool/markdown_exporter.py (2825b), nodes/coze/tool/mermaid_converter.py (1411b), nodes/coze/tool/text2image.py (1692b), nodes/coze/tool/tts.py (1536b), nodes/dify/__init__.py (0b), nodes/dify/basic/__init__.py (0b), nodes/dify/basic/code.py (1181b), nodes/dify/basic/document_extractor.py (625b), nodes/dify/basic/end.py (798b), nodes/dify/basic/http_request.py (1103b), nodes/dify/basic/if_else.py (2672b), nodes/dify/basic/iteration_start.py (337b), nodes/dify/basic/iteration.py (772b), nodes/dify/basic/list_operator.py (2380b), nodes/dify/basic/llm.py (1078b), nodes/dify/basic/parameter_extractor.py (1205b), nodes/dify/basic/question_classifier.py (1307b), nodes/dify/basic/start.py (1943b), nodes/dify/basic/template_transform.py (885b), nodes/dify/basic/variable_aggregator.py (746b), nodes/dify/node.py (233b), nodes/dify/tool/__init__.py (0b), nodes/dify/tool/echarts.py (1649b), nodes/dify/tool/google_search.py (977b), nodes/dify/tool/markdown_exporter.py (1091b), nodes/dify/tool/mermaid_converter.py (1176b), nodes/dify/tool/text2image.py (1415b), nodes/dify/tool/tts.py (1064b), requirements.txt (32b), SAFETY_AUDIT.md (5747b), SKILL.md (21242b), tools.py (23643b), _meta.json (133b)\n\nArchive v1.0.9: 57 files, 71113 bytes\n\nFiles: autofix.py (23844b), bash_converter.sh (1193b), converter.py (22826b), node_docs/coze.md (25612b), node_docs/dify.md (29860b), nodes/__init__.py (0b), nodes/coze/__init__.py (0b), nodes/coze/basic/__init__.py (0b), nodes/coze/basic/code.py (3047b), nodes/coze/basic/document_extractor.py (1230b), nodes/coze/basic/end.py (1049b), nodes/coze/basic/http_request.py (1463b), nodes/coze/basic/if_else.py (2509b), nodes/coze/basic/iteration.py (1663b), nodes/coze/basic/llm.py (2669b), nodes/coze/basic/parameter_extractor.py (3446b), nodes/coze/basic/question_classifier.py (1895b), nodes/coze/basic/start.py (1361b), nodes/coze/basic/template_transform.py (1706b), nodes/coze/basic/variable_aggregator.py (1252b), nodes/coze/MANIFEST.yml (177b), nodes/coze/node.py (193b), nodes/coze/tool/__init__.py (0b), nodes/coze/tool/echarts.py (3647b), nodes/coze/tool/google_search.py (1999b), nodes/coze/tool/markdown_exporter.py (2825b), nodes/coze/tool/mermaid_converter.py (1411b), nodes/coze/tool/text2image.py (1692b), nodes/coze/tool/tts.py (1536b), nodes/dify/__init__.py (0b), nodes/dify/basic/__init__.py (0b), nodes/dify/basic/code.py (1181b), nodes/dify/basic/document_extractor.py (625b), nodes/dify/basic/end.py (798b), nodes/dify/basic/http_request.py (1103b), nodes/dify/basic/if_else.py (2672b), nodes/dify/basic/iteration_start.py (337b), nodes/dify/basic/iteration.py (772b), nodes/dify/basic/list_operator.py (2380b), nodes/dify/basic/llm.py (1078b), nodes/dify/basic/parameter_extractor.py (1205b), nodes/dify/basic/question_classifier.py (1307b), nodes/dify/basic/start.py (1943b), nodes/dify/basic/template_transform.py (885b), nodes/dify/basic/variable_aggregator.py (746b), nodes/dify/node.py (233b), nodes/dify/tool/__init__.py (0b), nodes/dify/tool/echarts.py (1649b), nodes/dify/tool/google_search.py (977b), nodes/dify/tool/markdown_exporter.py (1091b), nodes/dify/tool/mermaid_converter.py (1176b), nodes/dify/tool/text2image.py (1415b), nodes/dify/tool/tts.py (1064b), requirements.txt (32b), SKILL.md (22011b), tools.py (23643b), _meta.json (132b)\n\nArchive v1.0.8: 57 files, 70971 bytes\n\nFiles: autofix.py (23844b), bash_converter.sh (1193b), converter.py (22826b), node_docs/coze.md (25612b), node_docs/dify.md (29860b), nodes/__init__.py (0b), nodes/coze/__init__.py (0b), nodes/coze/basic/__init__.py (0b), nodes/coze/basic/code.py (3047b), nodes/coze/basic/document_extractor.py (1230b), nodes/coze/basic/end.py (1049b), nodes/coze/basic/http_request.py (1463b), nodes/coze/basic/if_else.py (2509b), nodes/coze/basic/iteration.py (1663b), nodes/coze/basic/llm.py (2669b), nodes/coze/basic/parameter_extractor.py (3446b), nodes/coze/basic/question_classifier.py (1895b), nodes/coze/basic/start.py (1361b), nodes/coze/basic/template_transform.py (1706b), nodes/coze/basic/variable_aggregator.py (1252b), nodes/coze/MANIFEST.yml (177b), nodes/coze/node.py (193b), nodes/coze/tool/__init__.py (0b), nodes/coze/tool/echarts.py (3647b), nodes/coze/tool/google_search.py (1999b), nodes/coze/tool/markdown_exporter.py (2825b), nodes/coze/tool/mermaid_converter.py (1411b), nodes/coze/tool/text2image.py (1692b), nodes/coze/tool/tts.py (1536b), nodes/dify/__init__.py (0b), nodes/dify/basic/__init__.py (0b), nodes/dify/basic/code.py (1181b), nodes/dify/basic/document_extractor.py (625b), nodes/dify/basic/end.py (798b), nodes/dify/basic/http_request.py (1103b), nodes/dify/basic/if_else.py (2672b), nodes/dify/basic/iteration_start.py (337b), nodes/dify/basic/iteration.py (772b), nodes/dify/basic/list_operator.py (2380b), nodes/dify/basic/llm.py (1078b), nodes/dify/basic/parameter_extractor.py (1205b), nodes/dify/basic/question_classifier.py (1307b), nodes/dify/basic/start.py (1943b), nodes/dify/basic/template_transform.py (885b), nodes/dify/basic/variable_aggregator.py (746b), nodes/dify/node.py (233b), nodes/dify/tool/__init__.py (0b), nodes/dify/tool/echarts.py (1649b), nodes/dify/tool/google_search.py (977b), nodes/dify/tool/markdown_exporter.py (1091b), nodes/dify/tool/mermaid_converter.py (1176b), nodes/dify/tool/text2image.py (1415b), nodes/dify/tool/tts.py (1064b), requirements.txt (32b), SKILL.md (21391b), tools.py (23643b), _meta.json (132b)\n\nArchive v1.0.7: 57 files, 70459 bytes\n\nFiles: autofix.py (23844b), bash_converter.sh (1193b), converter.py (22826b), node_docs/coze.md (25002b), node_docs/dify.md (29248b), nodes/__init__.py (0b), nodes/coze/__init__.py (0b), nodes/coze/basic/__in...","readmeExcerpt":"Skill: chat2workflow Owner: chikawa11 Summary: A design-only workflow designer for the Dify and Coze platforms. Through multi-round conversation, it produces a structured workflow JSON (nodes, edges, vari... Tags: latest:1.1.1 Version history: v1.1.3 | 2026-05-08T11:08:48.045Z | user - No user-facing changes in this release. - Version updated to maintain metadata or triggering new build; there are no modifications to","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"python converter.py \\\n    --json_path ../workflow.json \\\n    --name my_workflow \\\n    --output_path ../chat2workflow_output/ \\\n    --type dify        # or: --type coze"},{"language":"bash","snippet":"bash bash_converter.sh ../workflow.json my_workflow ../chat2workflow_output dify"},{"language":"bash","snippet":"grep -RInE '\\b(requests|urllib|urllib2|urllib3|httplib|http\\.client|socket|asyncio|aiohttp|paramiko|ftplib|smtplib|boto3|websocket|grpc)\\b' \\\n    converter.py tools.py autofix.py bash_converter.sh\n# expected: (no matches)"},{"language":"bash","snippet":"grep -RInE '\\b(subprocess|os\\.system|os\\.popen|os\\.spawn|os\\.exec[a-z]*|pty\\.|eval\\(|exec\\()\\b' \\\n    converter.py tools.py autofix.py\n# expected: (no matches)"},{"language":"bash","snippet":"grep -RInE '\\b(os\\.environ|os\\.getenv|getenv|getpass|keyring|secrets\\.|dotenv|load_dotenv|API_KEY|TOKEN|SECRET|PASSWORD)\\b' \\\n    converter.py tools.py autofix.py bash_converter.sh\n# expected: (no matches)"},{"language":"bash","snippet":"grep -RInE '(https?://|ftp://|ws://|wss://)' \\\n    converter.py tools.py autofix.py bash_converter.sh\n# expected: (no matches)"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: chat2workflow\ndescription: A design-only workflow designer for the Dify and Coze platforms. Through multi-round conversation, it produces a structured workflow JSON (nodes, edges, variable references) as text output. The skill itself produces only text and never runs any scripts.\n---\n\n# Chat2Workflow Builder Skill\n\n## What this skill does\n\nThis skill is **design-only**. Its deliverable is three tagged sections of text (see *Output Format* below) — most importantly a workflow JSON wrapped in `<workflow></workflow>`. Producing those three sections involves only reading the platform documentation under `node_docs/` and emitting text; nothing else happens.\n\nA few Python files also live in this folder (`converter.py`, `autofix.py`, `tools.py`, `bash_converter.sh`). They are **not part of the skill's deliverable** and are not referenced by the generation process. They exist as standalone utilities that a user can run manually from a shell, entirely outside the skill's text-generation flow, if they separately want to turn a JSON file into a Dify YAML or Coze ZIP on their own machine. See the bundled `README`/source of those scripts for their CLI usage; the skill itself does not invoke them.\n\n## Overview\n\nA Chat2Workflow design is a Directed Acyclic Graph of connected nodes, where each node represents a step of logic, data processing, or model inference. The design is serialized as a JSON object that enumerates the nodes and the edges that connect them.\n\nThis skill supports **two target platforms**:\n\n| Platform | Documentation File | Selection criterion |\n|----------|--------------------|----------------|\n| **Dify** (default) | `node_docs/dify.md` | The user instruction explicitly mentions Dify, or no platform is specified at all. |\n| **Coze**           | `node_docs/coze.md` | The user instruction explicitly mentions Coze / 扣子. |\n\n### Platform Resolution\n\nPlatform selection is a two-step lookup performed against the user's instruction:\n\n1. The user's instruction is scanned for platform keywords — `dify` / `Dify` / `DIFY` or `coze` / `Coze` / `扣子`.\n2. If a platform keyword is present, that platform is the target. Otherwise the target is Dify (the default).\n3. The matching file from `node_docs/` — `node_docs/dify.md` or `node_docs/coze.md` — is the authoritative schema for node `type` strings, `param` objects, and referable variables on that platform. The two platforms have different node sets, different parameter schemas, and different referable variables.\n4. The chosen platform is named in `<design_principle>` with a short justification, e.g. `\"Platform: Dify (user did not specify, defaulting to Dify).\"`.\n\nA single workflow targets a single platform; every node's `type` comes from that platform's documentation file.\n\nThe interaction model is conversational: the user supplies creation or modification instructions across multiple rounds, and — unless an instruction says otherwise — each new response extends the current design rather than replacin"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7bhksjab0j1qxn85redp9ev585d21g\",\n  \"slug\": \"chat2workflow\",\n  \"version\": \"1.1.3\",\n  \"publishedAt\": 1778238528045\n}"},{"path":"CONVERTER_USAGE.md","content":"# Converter Utility — Manual CLI Usage\n\nThis document is **not part of the `chat2workflow` skill's runtime** and is\nnot referenced by `SKILL.md`. It describes the optional, standalone\ncommand-line utilities shipped in this folder — `converter.py`, `autofix.py`,\n`tools.py`, and `bash_converter.sh` — for users who want to compile a\nworkflow JSON (produced separately by the skill's text output) into a\nDify YAML file or a Coze ZIP bundle on their own machine.\n\nThe skill's own deliverable is purely text (the three tagged sections). These\nutilities are read-and-write file tools that a user runs manually from a\nshell; nothing about using the skill requires running them.\n\nFor an independent safety audit of the utilities' imports and behavior (no\nnetwork I/O, no shell execution, no credential access), see\n[`SAFETY_AUDIT.md`](./SAFETY_AUDIT.md).\n\n---\n\n## 1. Prerequisites\n\nTwo third-party Python packages are required. They are listed in\n`requirements.txt` and can be installed with whichever Python package\nmanager the user prefers:\n\n- `PyYAML` — emits Dify YAML.\n- `json_repair` — used by the offline auto-fix pass.\n\nThe utilities do not shell out to `pip`, `conda`, or any other package\nmanager. They run against whatever interpreter already has the packages\navailable.\n\n## 2. CLI\n\n```bash\npython converter.py \\\n    --json_path ../workflow.json \\\n    --name my_workflow \\\n    --output_path ../chat2workflow_output/ \\\n    --type dify        # or: --type coze\n```\n\nAlternative flags:\n\n- `--json_str '{...}'` — pass the workflow JSON inline instead of from a file.\n- `--name` — name of the produced artifact. English only.\n- `--output_path` — destination directory. When omitted, defaults to the\n  sibling directory `../chat2workflow_output/` next to this folder.\n\nA bash wrapper is also provided for convenience:\n\n```bash\nbash bash_converter.sh ../workflow.json my_workflow ../chat2workflow_output dify\n```\n\n## 3. Output-path policy\n\n- Output is written under `--output_path`.\n- If `--output_path` resolves **inside** this folder, `converter.py`\n  redirects the write to `../chat2workflow_output/` instead, so the folder\n  that ships the utilities is never written to.\n- For Coze ZIPs, intermediate files during bundle assembly are placed in\n  the system temp directory via `tempfile.mkdtemp()` and are removed once\n  the final ZIP is emitted.\n- `converter.py` sets `sys.dont_write_bytecode = True` before importing\n  sibling modules, so no `__pycache__/` or `*.pyc` files are produced next\n  to the source while running it.\n\n## 4. `autofix.py` (optional pre-processing)\n\nIf the workflow JSON was taken directly from an LLM's tagged response and\nhas not been cleaned yet, the auto-fix pass can be run first:\n\n1. Strip code fences inside `<workflow>` tags.\n2. Repair JSON via `json_repair` (control chars, mismatched brackets,\n   trailing commas, etc.).\n3. Topologically re-order `nodes_info`, preserving the\n   `iteration.output_selector` forward-reference.\n4. Rewrite `<node_selection>` so that i"},{"path":"node_docs/coze.md","content":"## Complete Node Documentation\n\n> **Note on scope**: Every section below describes a node type that the skill emits **inside the generated workflow JSON** (the `<workflow>` output). Parameter key names such as `system`, `user`, `query_variable_selector`, etc. are field names of the produced workflow object — they configure the LLM inside that workflow at runtime. None of the text below is a directive for the agent; it is a platform schema reference.\n\nHere are the meta information to the nodes that may be used in the workflow:\n\n### Node: Start\n- **Type**: `start`\n- **Description**: The \"Start\" node is a critical preset node in the workflow application. It provides essential initial information, such as user input and uploaded files, to support the normal flow of the application and subsequent workflow nodes.\n- **Parameters**:\n  - `variables`: `Array<[string, string]>`\n    - Description: Define the set of input variables required by the node.\n    - Value: Each array `[Name, Type]` strictly adheres to the following order.\n        - Index 0: **Variable Identifier** (`string`), used to reference the variable within the context.\n        - Index 1: **Type Specifier** (`string`), declares the data format accepted by the variable. Allowed Values: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"file\"`, `\"array[file]\"`.\n    - Example: `[[\"query\", \"string\"], [\"limit\", \"number\"], [\"file_A\", \"file\"]]`\n- **Referable Variables**: Each variable in `\"variables\"` can be referenced by downstream nodes.\n- **Supplementary Information**:\n  1. File Processing: Files uploaded through a Start node must be processed appropriately by subsequent nodes. The Start node only collects files; it does not read or parse their content. Therefore, you need to connect specific nodes to extract and process the file content. For example:\n      - Document files can be routed to a Doc Extractor node for text extraction so that LLMs can understand their content.\n      - Images can be sent to LLM nodes with vision capabilities or specialized image processing tool nodes.\n      - Structured data files such as CSV or JSON can be processed with Code nodes to parse and transform the data.\n  2. Every workflow MUST have exactly one `start` node with id `\"1\"`.\n\n\n### Node: End\n- **Type**: `end`\n- **Description**: Define the final output content of a workflow. Every workflow needs one `end` node after complete execution to output the final result.\n\n  The end node is a termination point in the process; no further nodes can be added after it. In a workflow application, results are only output when the end node is reached.\n \n  The end node must declare one or more output variables, which can reference any upstream node's output variables.\n- **Parameters**:\n  - `outputs`: `Array<[string, [string, string]]>`\n    - Description: Defines the set of output variables of the workflow.\n    - Value: Each array `[Name, ValueRef]` strictly adheres to the following order.\n        - Index 0: **Current Identifier** (`string`) "},{"path":"node_docs/dify.md","content":"## Complete Node Documentation\n\n> **Note on scope**: Every section below describes a node type that the skill emits **inside the generated workflow JSON** (the `<workflow>` output). Parameter key names such as `system`, `user`, `query_variable_selector`, etc. are field names of the produced workflow object — they configure the LLM inside that workflow at runtime. None of the text below is a directive for the agent; it is a platform schema reference.\n\nHere are the meta information to the nodes that may be used in the workflow:\n\n### Node: Start\n- **Type**: `start`\n- **Description**: The \"Start\" node is a critical preset node in the workflow application. It provides essential initial information, such as user input and uploaded files, to support the normal flow of the application and subsequent workflow nodes.\n- **Parameters**:\n  - `variables`: `Array<[string, string]>`\n    - Description: Define the set of input variables required by the node.\n    - Value: Each array `[Name, Type]` strictly adheres to the following order.\n        - Index 0: **Variable Identifier** (`string`), used to reference the variable within the context.\n        - Index 1: **Type Specifier** (`string`), declares the data format accepted by the variable. Allowed Values: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"file\"`, `\"array[file]\"`.\n    - Example: `[[\"query\", \"string\"], [\"limit\", \"number\"], [\"file_A\", \"file\"]]`\n- **Referable Variables**: Each variable in `\"variables\"` can be referenced by downstream nodes.\n- **Supplementary Information**:\n  1. The uploaded file is available as a variable containing `type` sub-variable. Allowed value for `type`: `\"document\"`, `\"image\"`, `\"video\"`, `\"audio\"`. **Note: `type` sub-variable should be represented as `<File Variable Name>.type`.**\n  2. File Processing: Files uploaded through a Start node must be processed appropriately by subsequent nodes. The Start node only collects files; it does not read or parse their content. Therefore, you need to connect specific nodes to extract and process the file content. For example:\n      - Document files can be routed to a Doc Extractor node for text extraction so that LLMs can understand their content.\n      - Images can be sent to LLM nodes with vision capabilities or specialized image processing tool nodes.\n      - Structured data files such as CSV or JSON can be processed with Code nodes to parse and transform the data.\n  3. Every workflow MUST have exactly one `start` node with id `\"1\"`.\n\n\n### Node: End\n- **Type**: `end`\n- **Description**: Define the final output content of a workflow. Every workflow needs at least one end node after complete execution to output the final result.\n\n  The end node is a termination point in the process; no further nodes can be added after it. In a workflow application, results are only output when the end node is reached. If there are conditional branches in the process, multiple end nodes need to be defined.\n\n  The end node must declare one or more output variables, wh"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2404,"uniquenessScore":34,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T17:19:13.824Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T17:19:13.824Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T20:56:24.944Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}