@thinkingai/ae-cli 1.0.1 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/README.md +38 -64
  2. package/README.zh.md +203 -0
  3. package/dist/{auth-JXELJNDS.js → auth-4GAHTBVH.js} +2 -2
  4. package/dist/{auth-L3G3A74I.js → auth-U2GHFMFY.js} +20 -6
  5. package/dist/{chunk-OVQOK35G.js → chunk-EBFUVWIZ.js} +25 -6
  6. package/dist/{chunk-3GM5LJZR.js → chunk-OQ4XEG77.js} +7 -4
  7. package/dist/{chunk-JD5DXMKL.js → chunk-TJIMDNAU.js} +10 -8
  8. package/dist/{chunk-RJNLN3KQ.js → chunk-UK6HO5O5.js} +7 -6
  9. package/dist/{client-5QSQBBDB.js → client-HU63573O.js} +3 -3
  10. package/dist/{config-Q7J3Z7Z2.js → config-OLF7RBPM.js} +5 -5
  11. package/dist/index.js +18 -17
  12. package/dist/{raw-ZNVURYMR.js → raw-GDO4IWNW.js} +8 -6
  13. package/dist/{te-analysis-7NN3SY3I.js → te-analysis-ZDJXMWZY.js} +64 -26
  14. package/dist/{te-audience-P43BWMHM.js → te-audience-T5B52EEB.js} +65 -25
  15. package/dist/{te-common-H3IPTI2I.js → te-common-BPTXXTHQ.js} +11 -38
  16. package/dist/{community-GMALVSRF.js → te-community-FPB5LH56.js} +59 -59
  17. package/dist/{te-dataops-WCGDBJLF.js → te-dataops-2NUJVG47.js} +3 -28
  18. package/dist/{te-engage-UTRVNTGU.js → te-engage-K3EANZ5P.js} +502 -520
  19. package/dist/{te-meta-HGYNXVGF.js → te-meta-JJMV75KB.js} +88 -20
  20. package/package.json +9 -7
  21. package/skills/ae-analysis/SKILL.md +229 -0
  22. package/skills/{te-meta/references/batch-create-metadata.md → ae-analysis/references/batch_create_metadata.md} +5 -5
  23. package/skills/{te-meta/references/batch-edit-metadata.md → ae-analysis/references/batch_edit_metadata.md} +4 -4
  24. package/skills/{te-analysis/references/build-entity-details-sql.md → ae-analysis/references/build_entity_details_sql.md} +14 -14
  25. package/skills/{te-analysis/references/build-event-details-sql.md → ae-analysis/references/build_event_details_sql.md} +14 -14
  26. package/skills/{te-analysis/references/create-alert.md → ae-analysis/references/create_alert.md} +7 -7
  27. package/skills/{te-audience/references/create-cluster.md → ae-analysis/references/create_cluster.md} +26 -22
  28. package/skills/{te-analysis/references/create-dashboard.md → ae-analysis/references/create_dashboard.md} +5 -5
  29. package/skills/{te-meta/references/create-metric.md → ae-analysis/references/create_metric.md} +16 -16
  30. package/skills/{te-analysis/references/create-or-update-dashboard-note.md → ae-analysis/references/create_or_update_dashboard_note.md} +5 -5
  31. package/skills/{te-meta/references/create-project-mark-time.md → ae-analysis/references/create_project_mark_time.md} +5 -5
  32. package/skills/{te-analysis/references/create-public-access-link.md → ae-analysis/references/create_public_access_link.md} +5 -5
  33. package/skills/{te-analysis/references/create-report.md → ae-analysis/references/create_report.md} +14 -14
  34. package/skills/{te-analysis/references/create-result-cluster.md → ae-analysis/references/create_result_cluster.md} +8 -8
  35. package/skills/{te-audience/references/create-tag.md → ae-analysis/references/create_tag.md} +18 -17
  36. package/skills/{te-meta/references/create-virtual-event.md → ae-analysis/references/create_virtual_event.md} +14 -14
  37. package/skills/{te-meta/references/create-virtual-property.md → ae-analysis/references/create_virtual_property.md} +11 -11
  38. package/skills/{te-meta/references/delete-project-mark-times.md → ae-analysis/references/delete_project_mark_times.md} +4 -4
  39. package/skills/{te-meta/references/delete-track-items.md → ae-analysis/references/delete_track_items.md} +4 -4
  40. package/skills/{te-analysis/references/drilldown-user-events.md → ae-analysis/references/drilldown_user_events.md} +11 -11
  41. package/skills/{te-analysis/references/drilldown-users.md → ae-analysis/references/drilldown_users.md} +12 -9
  42. package/skills/ae-analysis/references/generate_track_program.md +51 -0
  43. package/skills/ae-analysis/references/generate_track_sdk_sample.md +43 -0
  44. package/skills/{te-analysis/references/get-alert.md → ae-analysis/references/get_alert.md} +4 -4
  45. package/skills/{te-analysis/references/get-alert-definition-schema.md → ae-analysis/references/get_alert_definition_schema.md} +4 -4
  46. package/skills/ae-analysis/references/get_analysis_query_schema.md +61 -0
  47. package/skills/ae-analysis/references/get_cluster_definition_schema.md +53 -0
  48. package/skills/ae-analysis/references/get_clusters_by_name.md +69 -0
  49. package/skills/{te-analysis/references/get-filter-schema.md → ae-analysis/references/get_filter_schema.md} +4 -4
  50. package/skills/{te-analysis/references/get-groupby-schema.md → ae-analysis/references/get_groupby_schema.md} +4 -4
  51. package/skills/{te-meta/references/get-metric.md → ae-analysis/references/get_metric.md} +4 -4
  52. package/skills/{te-meta/references/get-project-config.md → ae-analysis/references/get_project_config.md} +4 -4
  53. package/skills/{te-analysis/references/get-report-definition.md → ae-analysis/references/get_report_definition.md} +4 -4
  54. package/skills/{te-common/references/get-resource-url.md → ae-analysis/references/get_resource_url.md} +7 -7
  55. package/skills/{te-analysis/references/get-table-columns.md → ae-analysis/references/get_table_columns.md} +4 -4
  56. package/skills/ae-analysis/references/get_tag_definition_schema.md +49 -0
  57. package/skills/ae-analysis/references/get_tags_by_name.md +69 -0
  58. package/skills/{te-meta/references/get-track-program.md → ae-analysis/references/get_track_program.md} +4 -4
  59. package/skills/{te-analysis/references/list-alerts.md → ae-analysis/references/list_alerts.md} +8 -5
  60. package/skills/{te-audience/references/list-cluster-members.md → ae-analysis/references/list_cluster_members.md} +13 -6
  61. package/skills/{te-audience/references/list-clusters.md → ae-analysis/references/list_clusters.md} +12 -6
  62. package/skills/{te-analysis/references/list-dashboards.md → ae-analysis/references/list_dashboards.md} +10 -6
  63. package/skills/{te-meta/references/list-entities.md → ae-analysis/references/list_entities.md} +12 -5
  64. package/skills/{te-meta/references/list-events.md → ae-analysis/references/list_events.md} +10 -7
  65. package/skills/ae-analysis/references/list_metrics.md +41 -0
  66. package/skills/ae-analysis/references/list_project_mark_times.md +42 -0
  67. package/skills/{te-meta/references/list-project-users.md → ae-analysis/references/list_project_users.md} +4 -4
  68. package/skills/{te-common/references/list-projects.md → ae-analysis/references/list_projects.md} +9 -7
  69. package/skills/{te-meta/references/list-properties.md → ae-analysis/references/list_properties.md} +11 -6
  70. package/skills/ae-analysis/references/list_public_access_links.md +41 -0
  71. package/skills/{te-analysis/references/list-reports.md → ae-analysis/references/list_reports.md} +10 -6
  72. package/skills/{te-audience/references/list-tag-members.md → ae-analysis/references/list_tag_members.md} +13 -6
  73. package/skills/{te-audience/references/list-tags.md → ae-analysis/references/list_tags.md} +12 -6
  74. package/skills/{te-analysis/references/load-filters.md → ae-analysis/references/load_filters.md} +5 -5
  75. package/skills/{te-analysis/references/query-adhoc.md → ae-analysis/references/query_adhoc.md} +19 -14
  76. package/skills/{te-analysis/references/query-dashboard-detail.md → ae-analysis/references/query_dashboard_detail.md} +4 -4
  77. package/skills/{te-analysis/references/query-dashboard-report-data.md → ae-analysis/references/query_dashboard_report_data.md} +13 -13
  78. package/skills/{te-analysis/references/query-entity-details.md → ae-analysis/references/query_entity_details.md} +15 -15
  79. package/skills/{te-analysis/references/query-event-details.md → ae-analysis/references/query_event_details.md} +17 -17
  80. package/skills/{te-analysis/references/query-report-data.md → ae-analysis/references/query_report_data.md} +16 -16
  81. package/skills/{te-audience/references/refresh-cluster.md → ae-analysis/references/refresh_cluster.md} +4 -4
  82. package/skills/{te-audience/references/refresh-tag.md → ae-analysis/references/refresh_tag.md} +4 -4
  83. package/skills/{te-meta/references/save-track-items.md → ae-analysis/references/save_track_items.md} +4 -4
  84. package/skills/{te-analysis/references/update-alert.md → ae-analysis/references/update_alert.md} +7 -7
  85. package/skills/{te-audience/references/update-cluster.md → ae-analysis/references/update_cluster.md} +17 -15
  86. package/skills/{te-analysis/references/update-dashboard.md → ae-analysis/references/update_dashboard.md} +5 -5
  87. package/skills/{te-meta/references/update-metric.md → ae-analysis/references/update_metric.md} +14 -14
  88. package/skills/{te-meta/references/update-project-mark-time.md → ae-analysis/references/update_project_mark_time.md} +5 -5
  89. package/skills/{te-analysis/references/update-public-access-link.md → ae-analysis/references/update_public_access_link.md} +5 -5
  90. package/skills/{te-audience/references/update-tag.md → ae-analysis/references/update_tag.md} +17 -16
  91. package/skills/ae-community/SKILL.md +305 -0
  92. package/skills/ae-community/references/community-activity-analysis.md +67 -0
  93. package/skills/ae-community/references/community-analyzing-official-content.md +71 -0
  94. package/skills/ae-community/references/community-analyzing-theme-comment.md +123 -0
  95. package/skills/ae-community/references/community-character-analysis.md +70 -0
  96. package/skills/ae-community/references/community-daily-report.md +84 -0
  97. package/skills/ae-community/references/community-hottopic-insight.md +113 -0
  98. package/skills/ae-community/references/community-weekly-report.md +84 -0
  99. package/skills/ae-community/references/get_channel_info.md +20 -0
  100. package/skills/ae-community/references/get_comment_tag_analysis.md +29 -0
  101. package/skills/ae-community/references/get_comments_summary.md +32 -0
  102. package/skills/ae-community/references/get_corpus_tags.md +20 -0
  103. package/skills/ae-community/references/get_daily_summary.md +22 -0
  104. package/skills/ae-community/references/get_hot_topics.md +25 -0
  105. package/skills/ae-community/references/get_livestream_analysis.md +22 -0
  106. package/skills/ae-community/references/get_livestream_detail.md +33 -0
  107. package/skills/ae-community/references/get_livestream_list.md +25 -0
  108. package/skills/ae-community/references/get_livestream_overview.md +24 -0
  109. package/skills/ae-community/references/get_livestream_room_metrics.md +25 -0
  110. package/skills/ae-community/references/get_livestream_rooms.md +25 -0
  111. package/skills/ae-community/references/get_overview_metrics.md +25 -0
  112. package/skills/ae-community/references/get_post_detail.md +37 -0
  113. package/skills/ae-community/references/get_risk_content.md +42 -0
  114. package/skills/ae-community/references/get_sentiment_overview.md +33 -0
  115. package/skills/ae-community/references/get_tag_trends.md +27 -0
  116. package/skills/ae-community/references/get_topic_detail.md +26 -0
  117. package/skills/ae-community/references/search_posts.md +47 -0
  118. package/skills/ae-dataops/SKILL.md +706 -0
  119. package/skills/ae-dataops/references/dataops-flow-create.md +163 -0
  120. package/skills/ae-dataops/references/dataops-flow-monitor.md +118 -0
  121. package/skills/ae-dataops/references/dataops-integration.md +251 -0
  122. package/skills/ae-dataops/references/dataops-query.md +111 -0
  123. package/skills/ae-dataops/references/dataops-table.md +122 -0
  124. package/skills/ae-engage/SKILL.md +311 -0
  125. package/skills/ae-engage/references/add-approver.md +24 -0
  126. package/skills/ae-engage/references/add-channel.md +74 -0
  127. package/skills/ae-engage/references/approver-list.md +19 -0
  128. package/skills/ae-engage/references/cancel-query-by-request-id.md +23 -0
  129. package/skills/ae-engage/references/channel-detail.md +52 -0
  130. package/skills/ae-engage/references/channel-list.md +41 -0
  131. package/skills/ae-engage/references/config-channel-detail.md +32 -0
  132. package/skills/ae-engage/references/config-channel-list.md +27 -0
  133. package/skills/ae-engage/references/config-item-analysis-report.md +34 -0
  134. package/skills/ae-engage/references/config-item-detail.md +30 -0
  135. package/skills/ae-engage/references/config-item-list.md +19 -0
  136. package/skills/ae-engage/references/config-item-strategy-comparison.md +25 -0
  137. package/skills/ae-engage/references/config-item-trigger-report.md +42 -0
  138. package/skills/ae-engage/references/copy-config-template.md +29 -0
  139. package/skills/ae-engage/references/delete-channel.md +24 -0
  140. package/skills/ae-engage/references/delete-config-channel.md +24 -0
  141. package/skills/ae-engage/references/delete-config-item.md +25 -0
  142. package/skills/ae-engage/references/delete-flow.md +24 -0
  143. package/skills/ae-engage/references/flow-ab-split-node-report.md +54 -0
  144. package/skills/ae-engage/references/flow-detail.md +79 -0
  145. package/skills/ae-engage/references/flow-list.md +19 -0
  146. package/skills/ae-engage/references/flow-node-config-schema.md +44 -0
  147. package/skills/ae-engage/references/flow-node-detail-report.md +55 -0
  148. package/skills/ae-engage/references/flow-node-overview-report.md +52 -0
  149. package/skills/ae-engage/references/flow-process-report.md +59 -0
  150. package/skills/ae-engage/references/manage-flow.md +94 -0
  151. package/skills/ae-engage/references/manage-strategy.md +74 -0
  152. package/skills/ae-engage/references/manage-task.md +37 -0
  153. package/skills/ae-engage/references/modify-flow-base-info.md +27 -0
  154. package/skills/ae-engage/references/save-flow.md +871 -0
  155. package/skills/ae-engage/references/strategy-detail.md +73 -0
  156. package/skills/ae-engage/references/strategy-list.md +21 -0
  157. package/skills/ae-engage/references/task-data-detail.md +74 -0
  158. package/skills/ae-engage/references/task-data-overview.md +42 -0
  159. package/skills/ae-engage/references/task-detail.md +61 -0
  160. package/skills/ae-engage/references/task-experiment-report.md +45 -0
  161. package/skills/ae-engage/references/task-list.md +91 -0
  162. package/skills/ae-engage/references/task-metric-detail.md +50 -0
  163. package/skills/ae-engage/references/task-stats.md +89 -0
  164. package/skills/ae-engage/references/update-channel-status.md +32 -0
  165. package/skills/ae-engage/references/update-config-channel-status.md +32 -0
  166. package/skills/ae-engage/references/validate-flow-node-config.md +52 -0
  167. package/skills/ae-engage/references/whitelist-list.md +19 -0
  168. package/skills/te-analysis/SKILL.md +0 -107
  169. package/skills/te-analysis/references/get-analysis-query-schema.md +0 -36
  170. package/skills/te-analysis/references/list-public-access-links.md +0 -31
  171. package/skills/te-audience/SKILL.md +0 -63
  172. package/skills/te-audience/references/get-cluster-definition-schema.md +0 -37
  173. package/skills/te-audience/references/get-clusters-by-name.md +0 -32
  174. package/skills/te-audience/references/get-tag-definition-schema.md +0 -32
  175. package/skills/te-audience/references/get-tags-by-name.md +0 -32
  176. package/skills/te-common/SKILL.md +0 -135
  177. package/skills/te-community/SKILL.md +0 -133
  178. package/skills/te-community/references/community-activity-analysis.md +0 -68
  179. package/skills/te-community/references/community-analyzing-official-content.md +0 -72
  180. package/skills/te-community/references/community-analyzing-theme-comment.md +0 -124
  181. package/skills/te-community/references/community-character-analysis.md +0 -71
  182. package/skills/te-community/references/community-daily-report.md +0 -82
  183. package/skills/te-community/references/community-hottopic-insight.md +0 -120
  184. package/skills/te-community/references/community-release-analysis.md +0 -79
  185. package/skills/te-community/references/community-weekly-report.md +0 -84
  186. package/skills/te-community/references/get_channel_info.md +0 -21
  187. package/skills/te-community/references/get_comment_tag_analysis.md +0 -30
  188. package/skills/te-community/references/get_comments_summary.md +0 -33
  189. package/skills/te-community/references/get_corpus_tags.md +0 -21
  190. package/skills/te-community/references/get_daily_summary.md +0 -23
  191. package/skills/te-community/references/get_hot_topics.md +0 -26
  192. package/skills/te-community/references/get_livestream_analysis.md +0 -23
  193. package/skills/te-community/references/get_livestream_detail.md +0 -34
  194. package/skills/te-community/references/get_livestream_list.md +0 -26
  195. package/skills/te-community/references/get_livestream_overview.md +0 -25
  196. package/skills/te-community/references/get_livestream_room_metrics.md +0 -26
  197. package/skills/te-community/references/get_livestream_rooms.md +0 -26
  198. package/skills/te-community/references/get_overview_metrics.md +0 -26
  199. package/skills/te-community/references/get_post_detail.md +0 -38
  200. package/skills/te-community/references/get_risk_content.md +0 -43
  201. package/skills/te-community/references/get_sentiment_overview.md +0 -34
  202. package/skills/te-community/references/get_tag_trends.md +0 -28
  203. package/skills/te-community/references/get_topic_detail.md +0 -27
  204. package/skills/te-community/references/search_posts.md +0 -48
  205. package/skills/te-dataops/SKILL.md +0 -645
  206. package/skills/te-dataops/references/dataops-flow-create.md +0 -163
  207. package/skills/te-dataops/references/dataops-flow-monitor.md +0 -118
  208. package/skills/te-dataops/references/dataops-integration.md +0 -246
  209. package/skills/te-dataops/references/dataops-operations.md +0 -107
  210. package/skills/te-dataops/references/dataops-query.md +0 -111
  211. package/skills/te-dataops/references/dataops-table.md +0 -122
  212. package/skills/te-engage/SKILL.md +0 -211
  213. package/skills/te-engage/references/add-approver.md +0 -24
  214. package/skills/te-engage/references/add-channel.md +0 -74
  215. package/skills/te-engage/references/approver-list.md +0 -19
  216. package/skills/te-engage/references/cancel-query-by-request-id.md +0 -23
  217. package/skills/te-engage/references/channel-detail.md +0 -52
  218. package/skills/te-engage/references/channel-list.md +0 -41
  219. package/skills/te-engage/references/config-channel-detail.md +0 -32
  220. package/skills/te-engage/references/config-channel-list.md +0 -27
  221. package/skills/te-engage/references/config-item-analysis-report.md +0 -34
  222. package/skills/te-engage/references/config-item-detail.md +0 -30
  223. package/skills/te-engage/references/config-item-list.md +0 -19
  224. package/skills/te-engage/references/config-item-strategy-comparison.md +0 -25
  225. package/skills/te-engage/references/config-item-trigger-report.md +0 -42
  226. package/skills/te-engage/references/copy-config-template.md +0 -29
  227. package/skills/te-engage/references/delete-channel.md +0 -24
  228. package/skills/te-engage/references/delete-config-channel.md +0 -24
  229. package/skills/te-engage/references/delete-config-item.md +0 -25
  230. package/skills/te-engage/references/delete-flow.md +0 -24
  231. package/skills/te-engage/references/flow-ab-split-node-report.md +0 -54
  232. package/skills/te-engage/references/flow-detail.md +0 -79
  233. package/skills/te-engage/references/flow-list.md +0 -19
  234. package/skills/te-engage/references/flow-node-config-schema.md +0 -44
  235. package/skills/te-engage/references/flow-node-detail-report.md +0 -55
  236. package/skills/te-engage/references/flow-node-overview-report.md +0 -52
  237. package/skills/te-engage/references/flow-process-report.md +0 -59
  238. package/skills/te-engage/references/manage-flow.md +0 -94
  239. package/skills/te-engage/references/manage-strategy.md +0 -74
  240. package/skills/te-engage/references/manage-task.md +0 -37
  241. package/skills/te-engage/references/modify-flow-base-info.md +0 -27
  242. package/skills/te-engage/references/save-flow.md +0 -870
  243. package/skills/te-engage/references/strategy-detail.md +0 -73
  244. package/skills/te-engage/references/strategy-list.md +0 -21
  245. package/skills/te-engage/references/task-data-detail.md +0 -81
  246. package/skills/te-engage/references/task-data-overview.md +0 -48
  247. package/skills/te-engage/references/task-detail.md +0 -61
  248. package/skills/te-engage/references/task-experiment-report.md +0 -51
  249. package/skills/te-engage/references/task-list.md +0 -91
  250. package/skills/te-engage/references/task-metric-detail.md +0 -56
  251. package/skills/te-engage/references/task-stats.md +0 -89
  252. package/skills/te-engage/references/update-channel-status.md +0 -32
  253. package/skills/te-engage/references/update-config-channel-status.md +0 -32
  254. package/skills/te-engage/references/validate-flow-node-config.md +0 -52
  255. package/skills/te-engage/references/whitelist-list.md +0 -19
  256. package/skills/te-meta/SKILL.md +0 -71
  257. package/skills/te-meta/references/list-metrics.md +0 -33
  258. package/skills/te-meta/references/list-project-mark-times.md +0 -33
  259. package/skills/te-shared/SKILL.md +0 -115
@@ -0,0 +1,871 @@
1
+ # ae-engage `+save_flow`
2
+
3
+ Create or update a flow canvas draft.
4
+
5
+ Mapped command: `ae-cli engage +save_flow`
6
+
7
+ This document is not only meant to explain the `save_flow` interface itself. It provides a complete path **from user requirements to CLI arguments**:
8
+
9
+ 1. Identify intent first
10
+ 2. Then map the intent to the flow canvas `req`
11
+ 3. Finally submit through the CLI
12
+
13
+ ---
14
+
15
+ ## 1. General Principles
16
+
17
+ `+save_flow` does not accept natural language or vague business descriptions directly. It accepts the **final flow canvas request payload that is ready to submit**.
18
+
19
+ Therefore, you must first organize user requirements into a unified intermediate intent structure, and then generate the payload according to the mapping rules:
20
+
21
+ - `flowName`
22
+ - `flowDesc`
23
+ - `nodeList`
24
+ - `edgeList`
25
+ - and optional `groupId`、`tzOffset`、`flowUuid`、`parentFlowUuid`、`versionType`
26
+
27
+ Then call the CLI:
28
+
29
+ ```bash
30
+ ae-cli engage +save_flow --project_id <projectId> --req '<req-json>'
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 2. Workflow
36
+
37
+ Use the following five-step workflow:
38
+
39
+ 1. Identify the flow intent from the user input and produce a unified intent JSON.
40
+ 2. Run `ae-cli analysis_audience +get_cluster_definition_schema --cluster_type condition` to obtain the condition cluster definition schema for assembling condition-related fields later.
41
+ 3. Run `ae-cli engage +channel_list --project_id <projectId>` to get the available channels in the project and match real `channelId` values for touchpoint nodes.
42
+ 4. Map the intent JSON to the final `req`: `flowName`, `flowDesc`, `nodeList`, and `edgeList`.
43
+ 5. Run `ae-cli engage +save_flow --project_id <projectId> --req '<req-json>'` to submit.
44
+
45
+ ---
46
+
47
+ ## 3. Step One: Intent Identification
48
+
49
+ ### 3.1 Information That Must Be Confirmed First
50
+
51
+ Before generating any `req`, confirm at least these four categories of information:
52
+
53
+ | Item | Description |
54
+ |---|---|
55
+ | business scenario | What kind of flow this is, for example new-user activation, churn win-back, or paid conversion |
56
+ | target users | Who can enter the flow, for example users inactive for the last 14 days or users registered today |
57
+ | touchpoint method | Which channel will be used for outreach, for example Push, WeChat subscription, or Webhook |
58
+ | branching conditions | Whether grouped handling is needed; if so, which conditions define the groups |
59
+
60
+ If any of these four categories is missing, do not build `req` directly.
61
+
62
+ ### 3.2 Intent Output Format
63
+
64
+ First organize the user requirement into the following intent JSON. This JSON is an intermediate representation, not the final `save_flow.req`.
65
+
66
+ ```json
67
+ {
68
+ "flow_type": "<string>",
69
+ "flow_name": "<string>",
70
+ "flow_desc": "<string>",
71
+ "entry": {
72
+ "type": "<single_trigger|repeat_trigger|event_trigger>",
73
+ "segment": "<string|null>",
74
+ "schedule": "<string|null>",
75
+ "start_date": "<YYYY-MM-DD|YYYY-MM-DD HH:mm|null>",
76
+ "end_date": "<YYYY-MM-DD|YYYY-MM-DD HH:mm|null>",
77
+ "trigger_event": {
78
+ "event": "<string|null>",
79
+ "op": "<string|null>",
80
+ "count": "<number|null>",
81
+ "property_filter": "<object|null>",
82
+ "time_window": "<string|null>"
83
+ }
84
+ },
85
+ "nodes": [
86
+ {
87
+ "nid": "n1",
88
+ "node_type": "<split|judge|action|wait|end>",
89
+ "type": "<specific semantic node type>",
90
+ "name": "<string|null>",
91
+ "content": "<string|null>",
92
+ "channel_name": "<string|null>",
93
+ "languages": ["default"],
94
+ "condition": "<object|null>",
95
+ "event": "<object|null>",
96
+ "wait_time": "<string|null>",
97
+ "duration": "<string|null>",
98
+ "split_flow_type": "<1|2|null>",
99
+ "branches": [
100
+ {
101
+ "bid": "b1",
102
+ "label": "<string>",
103
+ "condition": "<object|null>",
104
+ "time_limit": "<string|null>",
105
+ "percentage": "<number|null>"
106
+ }
107
+ ]
108
+ }
109
+ ],
110
+ "edges": [
111
+ {
112
+ "source": "n1",
113
+ "target": "n2",
114
+ "branch": "<branch label|null>"
115
+ }
116
+ ]
117
+ }
118
+ ```
119
+
120
+ ### 3.3 Field Meaning
121
+
122
+ - `entry`
123
+ Describes how users enter the flow.
124
+ - `nodes`
125
+ Describes business-semantic nodes; they are not yet final canvas nodes.
126
+ - `edges`
127
+ Describes the connection relationships at the business-semantics level.
128
+ - `channel_name`
129
+ Keep it as a semantic field first, then match a real `channelId` from the project channel list later.
130
+ - `branches`
131
+ Only describes branch semantics; later it will be materialized into `node.config.branchList` and `edge.sourceBranchId`.
132
+
133
+ ---
134
+
135
+ ## 4. Step Two: Required CLI Queries
136
+
137
+ ### 4.1 Query the Cluster Definition Schema
138
+
139
+ Run:
140
+
141
+ ```bash
142
+ ae-cli analysis_audience +get_cluster_definition_schema --cluster_type condition
143
+ ```
144
+
145
+ Purpose:
146
+ - Prepare the basis for building QP for condition nodes, audience nodes, and entry nodes
147
+ - Help generate `targetClusterQp`
148
+ - Help generate `triggerRule.events`
149
+
150
+ This step does not return final nodes directly. It provides the rule foundation for expressing conditions as QP or event conditions.
151
+
152
+ ### 4.2 Query Project Channels
153
+
154
+ Run:
155
+
156
+ ```bash
157
+ ae-cli engage +channel_list --project_id <projectId>
158
+ ```
159
+
160
+ Purpose:
161
+ - Get the available channels in the project
162
+ - Match a real `channelId` for touchpoint nodes based on `channel_name` in the intent
163
+ - Determine whether the node should be `message_push`, `wechat_push`, or `webhook_push` based on the channel type
164
+
165
+ If `channel_name` does not have an exact match, use this priority:
166
+
167
+ 1. exact name match
168
+ 2. name keyword match
169
+ 3. fallback match by node type and channel type
170
+
171
+ ---
172
+
173
+ ## 5. Step Three: Map the Intent to `req`
174
+
175
+ ### 5.1 Top-Level `req` Structure
176
+
177
+ The object passed to `--req` should have the following structure:
178
+
179
+ ```json
180
+ {
181
+ "flowName": "<string>",
182
+ "flowDesc": "<string>",
183
+ "groupId": 0,
184
+ "tzOffset": 8,
185
+ "flowUuid": "<string, optional>",
186
+ "parentFlowUuid": "<string, optional>",
187
+ "versionType": 1,
188
+ "nodeList": [],
189
+ "edgeList": []
190
+ }
191
+ ```
192
+
193
+ Notes:
194
+ - `projectId` does not need to be written into `--req` manually; the CLI injects it from `--project_id`
195
+ - `flowUuid` and `parentFlowUuid` are mutually exclusive
196
+ - When creating a new draft, neither of these fields should be provided
197
+
198
+ ### 5.2 Sources of Top-Level Fields
199
+
200
+ | `req` Field | Source |
201
+ |---|---|
202
+ | `flowName` | Intent field `flow_name` |
203
+ | `flowDesc` | Intent field `flow_desc`; use an empty string or a short description if absent |
204
+ | `groupId` | Default `0`, unless the business requirement specifies a group |
205
+ | `tzOffset` | User timezone or project default timezone; a common value is `8` |
206
+ | `nodeList` | Generated from intent `entry` plus `nodes` |
207
+ | `edgeList` | Generated from intent `edges` and branch structure |
208
+
209
+ ---
210
+
211
+ ## 6. Step Four: Map Intent Nodes to Canvas Nodes
212
+
213
+ ### 6.1 Entry Node Mapping
214
+
215
+ | Intent `entry.type` | Canvas node `type` |
216
+ |---|---|
217
+ | `single_trigger` | `single_trigger` |
218
+ | `repeat_trigger` | `repeat_trigger` |
219
+ | `event_trigger` | `event_trigger` |
220
+
221
+ The entry node must always be the only entry node in `nodeList`.
222
+
223
+ ### 6.2 Business Node Mapping
224
+
225
+ | Intent-node semantic meaning | Canvas node `type` |
226
+ |---|---|
227
+ | Behavioral split | `event_split_flow` |
228
+ | Feature split | `feature_split_flow` |
229
+ | A/B split | `ab_split_flow` |
230
+ | Behavioral judgment | `event_judge` |
231
+ | Feature judgment | `feature_judge` |
232
+ | Push touchpoint | `message_push` |
233
+ | WeChat touchpoint | `wechat_push` |
234
+ | Webhook / other external touchpoint | `webhook_push` |
235
+ | Wait | `time_control` |
236
+ | End | `exit_flow` |
237
+
238
+ ### 6.3 Condition Field Mapping
239
+
240
+ Condition-related semantics cannot be copied into `req` as-is. They must be materialized in the following way:
241
+
242
+ | Semantic type | Target field |
243
+ |---|---|
244
+ | Audience segmentation condition | `targetClusterQp` |
245
+ | Feature judgment condition | `targetClusterQp` |
246
+ | Feature split branch condition | `targetClusterQp` |
247
+ | Event trigger condition | `triggerRule[].events[]` |
248
+ | Behavioral judgment condition | `triggerRule[].events[]` |
249
+ | Behavioral split branch condition | `triggerRule[].events[]` |
250
+
251
+ In short:
252
+ - Conditions that judge by audience or property usually map to `targetClusterQp`
253
+ - Conditions that judge whether an event happened, or how many times it happened, usually map to `triggerRule.events`
254
+
255
+ ### 6.4 Touchpoint Node Mapping
256
+
257
+ These fields inside action-semantic nodes:
258
+
259
+ - `channel_name`
260
+ - `content`
261
+ - `languages`
262
+
263
+ need to be materialized into the push-node `config`:
264
+
265
+ - `channel_name` -> match to a real `channelId`
266
+ - `content` -> place into `contentList`
267
+ - `languages` -> determine whether multilingual `contentList` entries should be generated
268
+
269
+ ---
270
+
271
+ ## 7. Step Five: How to Build `nodeList`
272
+
273
+ Each item in `nodeList` has the following structure:
274
+
275
+ | Field | Type | Required | Description |
276
+ |---|---|---|---|
277
+ | `id` | string | Yes | Unique node ID within the request |
278
+ | `name` | string | Yes | Display name of the node |
279
+ | `type` | string | Yes | Node type |
280
+ | `config` | string | Yes | **JSON string** whose top level must be a JSON object |
281
+ | `desc` | string | No | Node description |
282
+
283
+ ### 7.1 Most Important Rules
284
+
285
+ 1. `config` must be a string, not an object.
286
+ 2. `node.id` must be unique.
287
+ 3. Any `branchId` later referenced by `edge.sourceBranchId` in split or judgment nodes must be defined in `config` first.
288
+ 4. Every path must eventually end at `exit_flow`.
289
+
290
+ ### 7.2 Common Node Types
291
+
292
+ - `single_trigger`
293
+ - `repeat_trigger`
294
+ - `event_trigger`
295
+ - `event_split_flow`
296
+ - `feature_split_flow`
297
+ - `ab_split_flow`
298
+ - `event_judge`
299
+ - `feature_judge`
300
+ - `message_push`
301
+ - `wechat_push`
302
+ - `webhook_push`
303
+ - `time_control`
304
+ - `exit_flow`
305
+
306
+ ### 7.3 Example: Simplest Node
307
+
308
+ ```json
309
+ {
310
+ "id": "node_1",
311
+ "name": "One-Time Scheduled Entry",
312
+ "type": "single_trigger",
313
+ "config": {
314
+ "triggerTime": "2026-04-10 06:35",
315
+ "flowEndDate": "2026-04-11 06:35"
316
+ }
317
+ }
318
+ ```
319
+
320
+ ### 7.4 Common `config` Templates
321
+
322
+ The templates below are the most important references when you assemble `req` directly. Build them as objects first, then wrap them with `JSON.stringify` before placing them into `nodeList[].config`.
323
+
324
+ #### `repeat_trigger`
325
+
326
+ ```json
327
+ {
328
+ "targetUserType": 1,
329
+ "startDate": "<YYYY-MM-DD>",
330
+ "endDate": "<YYYY-MM-DD>",
331
+ "flowEndDate": "<YYYY-MM-DD HH:mm>",
332
+ "crontab": "0 00 09 * * ?",
333
+ "entryControlLimits": {
334
+ "enableMultEntry": false,
335
+ "disableConcurrentEntry": false
336
+ },
337
+ "targetClusterName": null,
338
+ "clusterPredictCount": null,
339
+ "clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>",
340
+ "targetClusterQp": "<JSON.stringify(qp)>"
341
+ }
342
+ ```
343
+
344
+ Rules:
345
+ - `entry.segment` -> `targetClusterQp`
346
+ - `entry.schedule` -> `crontab`
347
+ - Common default value: `0 00 09 * * ?`
348
+
349
+ #### `event_trigger`
350
+
351
+ ```json
352
+ {
353
+ "triggerType": 3,
354
+ "targetUserType": 1,
355
+ "realtime": 0,
356
+ "clusterRefresh": 12,
357
+ "clusterRefreshTime": null,
358
+ "startDate": "<YYYY-MM-DD HH:mm>",
359
+ "endDate": "<YYYY-MM-DD HH:mm>",
360
+ "flowEndDate": "<YYYY-MM-DD HH:mm>",
361
+ "clusterPredictCount": null,
362
+ "clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>",
363
+ "triggerRule": [
364
+ {
365
+ "periodStart": "<startDate>",
366
+ "periodEnd": "<endDate>",
367
+ "periodTimeSymbol": "TS02",
368
+ "dayStartTime": null,
369
+ "startDay": null,
370
+ "eventTriggerType": 0,
371
+ "zoneoffset": 8,
372
+ "events": []
373
+ }
374
+ ],
375
+ "entryControlLimits": {
376
+ "enableMultEntry": false,
377
+ "disableConcurrentEntry": false
378
+ },
379
+ "targetClusterQp": "<JSON.stringify(qp) or null>"
380
+ }
381
+ ```
382
+
383
+ Rules:
384
+ - `entry.trigger_event` -> `triggerRule[0].events`
385
+ - Generate `targetClusterQp` only when `entry.segment` exists
386
+ - When `segment` is absent, `targetClusterQp` may be `null`
387
+
388
+ #### `event_split_flow`
389
+
390
+ ```json
391
+ {
392
+ "splitFlowType": 1,
393
+ "branchList": [
394
+ {
395
+ "branchId": "<branchId>",
396
+ "branchName": "<label>",
397
+ "branchType": 1,
398
+ "triggerRule": [
399
+ {
400
+ "delayTimeSymbol": "<minute|hour|day>",
401
+ "delayTime": "<number>",
402
+ "eventTriggerType": "<0 or -1>",
403
+ "zoneoffset": 8,
404
+ "events": []
405
+ }
406
+ ]
407
+ }
408
+ ]
409
+ }
410
+ ```
411
+
412
+ Rules:
413
+ - When `branch.condition` is an event condition, map it to `triggerRule[].events[]`
414
+ - `time_limit` -> `delayTimeSymbol` + `delayTime`
415
+ - Use `0` for happened and `-1` for not happened
416
+ - For the fallback branch, keep only:
417
+
418
+ ```json
419
+ {
420
+ "branchId": "<branchId>",
421
+ "branchType": 2
422
+ }
423
+ ```
424
+
425
+ #### `feature_split_flow`
426
+
427
+ ```json
428
+ {
429
+ "splitFlowType": 1,
430
+ "branchList": [
431
+ {
432
+ "branchId": "<branchId>",
433
+ "branchName": "<label>",
434
+ "branchType": 1,
435
+ "realtime": 0,
436
+ "clusterRefresh": 12,
437
+ "clusterPredictCount": null,
438
+ "clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>",
439
+ "targetClusterQp": "<JSON.stringify(qp)>"
440
+ }
441
+ ]
442
+ }
443
+ ```
444
+
445
+ Rules:
446
+ - Property or tag condition -> `targetClusterQp`
447
+ - For the fallback branch, also keep only `branchId` plus `branchType: 2`
448
+
449
+ #### `ab_split_flow`
450
+
451
+ ```json
452
+ {
453
+ "branchList": [
454
+ {
455
+ "branchId": "<branchId>",
456
+ "branchName": "Control Group",
457
+ "branchType": 1,
458
+ "order": 1,
459
+ "percentageInExperiment": 34
460
+ },
461
+ {
462
+ "branchId": "<branchId>",
463
+ "branchName": "Experiment Group A",
464
+ "branchType": 2,
465
+ "order": 2,
466
+ "percentageInExperiment": 33
467
+ }
468
+ ],
469
+ "indicatorsDef": [],
470
+ "activateIndicatorsDef": null
471
+ }
472
+ ```
473
+
474
+ Rules:
475
+ - If the user does not provide percentages, you may split them evenly
476
+ - For three groups, you can use `34/33/33`
477
+
478
+ #### `event_judge`
479
+
480
+ ```json
481
+ {
482
+ "transferType": 1,
483
+ "meetBranchId": "<meetBranchId>",
484
+ "notMeetBranchId": "<notMeetBranchId>",
485
+ "triggerRule": [
486
+ {
487
+ "delayTimeSymbol": "<minute|hour|day>",
488
+ "delayTime": "<number>",
489
+ "eventTriggerType": 0,
490
+ "zoneoffset": 8,
491
+ "events": []
492
+ }
493
+ ]
494
+ }
495
+ ```
496
+
497
+ Rules:
498
+ - `node.event` -> `triggerRule[].events[]`
499
+ - `wait_time` -> `delayTimeSymbol` + `delayTime`
500
+ - If no wait duration is specified, you may default to `30 minute`
501
+
502
+ #### `feature_judge`
503
+
504
+ ```json
505
+ {
506
+ "transferType": 1,
507
+ "meetBranchId": "<meetBranchId>",
508
+ "notMeetBranchId": "<notMeetBranchId>",
509
+ "clusterPredictCount": null,
510
+ "clusterPredictTime": "",
511
+ "targetClusterQp": "<JSON.stringify(qp)>"
512
+ }
513
+ ```
514
+
515
+ #### `message_push` / `webhook_push`
516
+
517
+ ```json
518
+ {
519
+ "channelId": "<matched channelId>",
520
+ "channelType": "<matched channelType>",
521
+ "enableChannelTouchLimits": false,
522
+ "isOccasionUp": false,
523
+ "contentList": [
524
+ {
525
+ "pushLanguageCode": "default",
526
+ "content": []
527
+ }
528
+ ],
529
+ "processType": 1
530
+ }
531
+ ```
532
+
533
+ Rules:
534
+ - `channel_name` -> match a real `channelId`
535
+ - `content` -> fill the parameter that best matches body text, content, or message
536
+ - When the parameter `type = TEXT`, also add:
537
+
538
+ ```json
539
+ {
540
+ "config": "[{\"type\":\"paragraph\",\"children\":[{\"text\":\"<same as value>\"}]}]"
541
+ }
542
+ ```
543
+
544
+ Multilingual Rules:
545
+ - The first entry must always use `"pushLanguageCode": "default"`
546
+ - Generate additional language versions according to `languages`
547
+ - Each language uses the same `content[]` structure; only `value` changes
548
+
549
+ #### `wechat_push`
550
+
551
+ ```json
552
+ {
553
+ "channelId": "<matched channelId>",
554
+ "enableChannelTouchLimits": false,
555
+ "isOccasionUp": false,
556
+ "contentList": [
557
+ {
558
+ "pushLanguageCode": "default",
559
+ "content": [
560
+ {
561
+ "key": "lang",
562
+ "type": "STRING",
563
+ "required": true,
564
+ "paramType": 2,
565
+ "name": "Language",
566
+ "value": "default"
567
+ },
568
+ {
569
+ "key": "page",
570
+ "type": "STRING",
571
+ "required": true,
572
+ "paramType": 2,
573
+ "name": "Destination Page",
574
+ "value": ""
575
+ },
576
+ {
577
+ "key": "miniprogramState",
578
+ "type": "STRING",
579
+ "required": true,
580
+ "paramType": 2,
581
+ "name": "Version",
582
+ "value": ""
583
+ }
584
+ ]
585
+ }
586
+ ],
587
+ "processType": 1
588
+ }
589
+ ```
590
+
591
+ #### `time_control`
592
+
593
+ ```json
594
+ {
595
+ "controlType": 1,
596
+ "timeUnit": "<minute|hour|day>",
597
+ "timeUnitNum": "<number>"
598
+ }
599
+ ```
600
+
601
+ Common parsing examples:
602
+ - `30 minutes` -> `minute` + `30`
603
+ - `2 hours` -> `hour` + `2`
604
+ - `1 day` -> `day` + `1`
605
+
606
+ #### `exit_flow`
607
+
608
+ Minimum usable `config`:
609
+
610
+ ```json
611
+ {}
612
+ ```
613
+
614
+ ---
615
+
616
+ ## 8. Step Six: How to Build `edgeList`
617
+
618
+ Each item in `edgeList` has the following structure:
619
+
620
+ | Field | Type | Required | Description |
621
+ |---|---|---|---|
622
+ | `source` | string | Yes | upstream node ID |
623
+ | `target` | string | Yes | downstream node ID |
624
+ | `edgeId` | string | No | edge ID |
625
+ | `sourceBranchId` | string | No | used for edges leaving split or judgment nodes |
626
+ | `config` | string | No | JSON string |
627
+
628
+ ### 8.1 Regular Edges
629
+
630
+ ```json
631
+ {
632
+ "source": "node_1",
633
+ "target": "node_2"
634
+ }
635
+ ```
636
+
637
+ ### 8.2 Branch Edges
638
+
639
+ ```json
640
+ {
641
+ "source": "node_split",
642
+ "target": "node_a",
643
+ "sourceBranchId": "branch_a"
644
+ }
645
+ ```
646
+
647
+ ### 8.3 Most Important Rules
648
+
649
+ 1. `source` and `target` must reference existing `node.id` values
650
+ 2. Only edges leaving split or judgment nodes need `sourceBranchId`
651
+ 3. The graph must be a DAG and cannot contain cycles
652
+ 4. For split nodes, `sourceBranchId` must come from a branchId already declared in the corresponding node `config`
653
+
654
+ ### 8.4 Standard Outgoing-Edge Rules
655
+
656
+ | node type | Number of outgoing edges | `sourceBranchId` rule |
657
+ |---|---|---|
658
+ | `single_trigger` / `repeat_trigger` / `event_trigger` | 1 | do not provide |
659
+ | `event_split_flow` / `feature_split_flow` / `ab_split_flow` | one per branch | use the corresponding `branchList[].branchId` |
660
+ | `event_judge` / `feature_judge` | 2 | use `meetBranchId` and `notMeetBranchId` respectively |
661
+ | `message_push` / `wechat_push` / `webhook_push` / `time_control` | 1 | do not provide |
662
+ | `exit_flow` | 0 | do not provide |
663
+
664
+ ---
665
+
666
+ ## 9. Step Seven: Graph Constraint Checks
667
+
668
+ Before submitting, you must self-check:
669
+
670
+ 1. `nodeList` is not empty
671
+ 2. There must be exactly one entry node
672
+ 3. There must be at least one `exit_flow`
673
+ 4. Each `exit_flow` must have exactly one incoming edge and no outgoing edges
674
+ 5. Each `node.id` must be unique
675
+ 6. Every edge must reference existing nodes
676
+ 7. The entire graph must be acyclic
677
+
678
+ If a split node uses `splitFlowType = 2`, also ensure:
679
+ - Paths from different branches must not converge again into the same node
680
+ - Each branch should independently lead to its own `exit_flow`
681
+
682
+ ---
683
+
684
+ ## 10. Step Eight: CLI Submission
685
+
686
+ ### 10.1 Top-Level Flags
687
+
688
+ | Flag | Type | Required | Description |
689
+ |---|---|---|---|
690
+ | `--project_id` / `-p` | number | Yes | Project ID |
691
+ | `--req` | json | Yes | final request-body object |
692
+
693
+ ### 10.2 Actual CLI Submission Structure
694
+
695
+ The CLI will organize the input as:
696
+
697
+ ```json
698
+ {
699
+ "projectId": 1,
700
+ "req": {
701
+ "projectId": 1,
702
+ "...": "..."
703
+ }
704
+ }
705
+ ```
706
+
707
+ In other words:
708
+ - The top-level `projectId` comes from `--project_id`
709
+ - `req.projectId` is also injected automatically by the CLI
710
+
711
+ ### 10.3 Minimum Working Example
712
+
713
+ ```bash
714
+ ae-cli engage +save_flow \
715
+ --project_id 1 \
716
+ --req '{
717
+ "flowName": "Welcome Flow",
718
+ "flowDesc": "New user welcome flow",
719
+ "groupId": 0,
720
+ "tzOffset": 8,
721
+ "nodeList": [
722
+ {
723
+ "id": "node_1",
724
+ "name": "Enter Flow",
725
+ "type": "single_trigger",
726
+ "config": "{}"
727
+ },
728
+ {
729
+ "id": "node_2",
730
+ "name": "End",
731
+ "type": "exit_flow",
732
+ "config": "{}"
733
+ }
734
+ ],
735
+ "edgeList": [
736
+ {
737
+ "source": "node_1",
738
+ "target": "node_2"
739
+ }
740
+ ]
741
+ }'
742
+ ```
743
+
744
+ ### 10.4 Output Requirements After Successful Creation
745
+
746
+ Prerequisite:
747
+ - The flow canvas was created successfully and returned the new canvas `flowUuid`
748
+
749
+ On success, you must:
750
+ - Show the creation result to the user, including at least key information such as the canvas name
751
+ - Output a **clickable Markdown link**
752
+
753
+ Link-generation Rules:
754
+ - Use standard Markdown link syntax and do not place it inside a code block
755
+ - The URL must start with `/#/`
756
+ - Do not add a domain name or any domain placeholder
757
+ - Replace the `flowUuid` returned by `save_flow` and the `projectId` used for this creation into the URL
758
+
759
+ Output template:
760
+
761
+ [Open Canvas](/#/hermes/flow/detail?flowUuid=<replace-with-actual-flowUuid>&currentProjectId=<replace-with-actual-projectId>)
762
+
763
+ Correct example:
764
+
765
+ [Open Canvas](/#/hermes/flow/detail?flowUuid=0006_831135755&currentProjectId=1)
766
+
767
+ Common mistakes:
768
+ - `❌ {domain}/#/hermes/flow/...`: do not add a domain placeholder
769
+ - `❌` putting the link inside a code block ````` : links inside code blocks are not clickable
770
+ - `❌ /#/hermes/flow/detail?flowUuid=...`: do not output a plain-text URL; you must use the `[text](URL)` format
771
+
772
+ ### 10.5 Output Requirements After Failed Creation
773
+
774
+ On failure, you must:
775
+ - Output the complete request-body JSON for debugging
776
+ - Clearly describe the failure reason
777
+
778
+ Suggested output structure:
779
+
780
+ ```json
781
+ {
782
+ "projectId": "<actual projectId>",
783
+ "req": {
784
+ "...": "complete save_flow request body"
785
+ }
786
+ }
787
+ ```
788
+
789
+ ---
790
+
791
+ ## 11. Most Common Mistakes
792
+
793
+ ### 11.1 `--req` Is an Object, but `node.config` / `edge.config` Are Strings
794
+
795
+ Correct:
796
+
797
+ ```json
798
+ {
799
+ "id": "node_1",
800
+ "name": "entry",
801
+ "type": "single_trigger",
802
+ "config": "{}"
803
+ }
804
+ ```
805
+
806
+ Incorrect:
807
+
808
+ ```json
809
+ {
810
+ "id": "node_1",
811
+ "name": "entry",
812
+ "type": "single_trigger",
813
+ "config": {}
814
+ }
815
+ ```
816
+
817
+ ### 11.2 Time Units Must Be Lowercase
818
+
819
+ Inside `time_control`, use:
820
+
821
+ - `day`
822
+ - `hour`
823
+ - `minute`
824
+ - `week`
825
+ - `month`
826
+
827
+ Do not write `DAY`, `HOUR`, or `MINUTE`.
828
+
829
+ ### 11.3 Do Not Invent `channelId`
830
+
831
+ For node types such as `message_push`, `wechat_push`, and `webhook_push`, `channelId` must come from:
832
+
833
+ ```bash
834
+ ae-cli engage +channel_list --project_id <projectId>
835
+ ```
836
+
837
+ ### 11.4 Define branch IDs Before Referencing Them
838
+
839
+ If an edge uses:
840
+
841
+ ```json
842
+ { "sourceBranchId": "branch_a" }
843
+ ```
844
+
845
+ then `"branch_a"` must already exist in the corresponding upstream node `config`.
846
+
847
+ ### 11.5 `targetClusterQp` Is Usually Also a String
848
+
849
+ Although `targetClusterQp` appears inside the JSON object of node `config`, its value is usually not a raw object. It is typically the QP object converted into a string with `JSON.stringify`.
850
+
851
+ Illustration:
852
+
853
+ ```json
854
+ { "targetClusterQp": "{\"totalCFilter\":{\"relation\":\"1\",\"filts\":[]}}" }
855
+ ```
856
+
857
+ ### 11.6 Rich-Text `config` for `TEXT` Parameters Must Also Be a String
858
+
859
+ If a push parameter uses `TEXT`, the inner rich-text `config` must not be an object. It must be stringified JSON. This is easy to miss.
860
+
861
+ ### 11.7 Do Not Merge Branches Again When `splitFlowType = 2`
862
+
863
+ "Enter whenever conditions are met" means users may enter multiple branches at the same time. In that case, later paths should not share the same downstream node, otherwise the semantics easily conflict.
864
+
865
+ ---
866
+
867
+ ## 12. One-Sentence Summary
868
+
869
+ To build `+save_flow` input parameters reliably, do not jump directly from natural language to `req`. Follow this path instead:
870
+
871
+ **User requirement -> intent JSON -> schema and channel completion -> `nodeList` / `edgeList` -> `ae-cli engage +save_flow`.**