foliko 1.1.72 → 1.1.73

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.
@@ -1,646 +1,646 @@
1
- ---
2
- name: workflow-guide
3
- description: 工作流与多步任务指南。当用户说"创建工作流"、"多步任务"、"自动化流程"时立即调用。
4
- allowed-tools: execute_workflow,reloadWorkflows
5
- ---
6
-
7
- # 工作流(Workflow)开发指南
8
-
9
- ## 概述
10
-
11
- 工作流引擎用于处理多步骤任务,通过 `execute_workflow` 工具执行。工作流由多个步骤组成,支持脚本、条件分支、循环、延时、工具调用等类型。
12
-
13
- ## 工作流存放位置
14
-
15
- ```
16
- 项目目录/
17
- └── .foliko/
18
- └── workflows/ # 工作流定义目录
19
- └── my-workflow.json # 工作流 JSON 定义
20
- └── another.js # 或 JS 文件(导出 default 工作流)
21
- ```
22
-
23
- ## 自动加载与注册
24
-
25
- 将工作流文件放入 `.foliko/workflows/` 目录后,系统会自动:
26
-
27
- 1. 加载所有 `.json` 和 `.js` 文件
28
- 2. 将工作流注册为 `workflow_<文件名>` 工具
29
-
30
- 例如 `my-workflow.json` 会注册为 `workflow_my_workflow` 工具,可直接调用。
31
-
32
- ## 重载工作流
33
-
34
- 创建或修改工作流后,调用 `reloadWorkflows` 重载:
35
-
36
- ```json
37
- {
38
- "tool": "reloadWorkflows",
39
- "args": {}
40
- }
41
- ```
42
-
43
- ## 使用方式
44
-
45
- ### 方式一:直接执行(任意工作流)
46
-
47
- ```json
48
- {
49
- "tool": "execute_workflow",
50
- "args": {
51
- "workflow": "my-workflow", // 工作流名称(自动从 .foliko/workflows/ 加载)
52
- "input": { "变量名": "值" }
53
- }
54
- }
55
- ```
56
-
57
- ### 方式二:执行已注册的工作流工具
58
-
59
- ```json
60
- {
61
- "tool": "workflow_my_workflow",
62
- "args": {
63
- "input": { "变量名": "值" }
64
- }
65
- }
66
- ```
67
-
68
- ## 重要注意事项
69
-
70
- 1. **script 必须用 return 返回值**:`script` 是函数体,不是表达式
71
- 2. **JSON 中不能使用多行字符串**:所有 script 内容写成单行,用分号分隔
72
- 3. **JSON 中不能有注释**:注释会导致 JSON 解析失败
73
-
74
- ## 工作流步骤类型
75
-
76
- ### 支持的步骤类型
77
-
78
- | 类型 | 说明 | 自动推断 |
79
- | ------------ | --------------- | ------------------------------------------- |
80
- | `tool` | 工具调用 | 有 `tool` 字段 |
81
- | `script` | JavaScript 脚本 | 有 `code` 或 `script` 字段 |
82
- | `condition` | 条件分支 | 有 `branches` 字段 |
83
- | `switch` | 开关分支 | 有 `value` + `branches` |
84
- | `try` | 异常捕获 | 有 `try` 或 `catch` 字段 |
85
- | `parallel` | 并行执行 | `"parallel": true` 或 `"mode": "parallel"` |
86
- | `sequential` | 顺序执行 | 有 `steps` 字段 |
87
- | `loop` | 循环执行 | 有 `steps` + `loopVariable`/`maxIterations` |
88
- | `delay` | 延时等待 | 有 `delayMs` 字段 |
89
- | `workflow` | 嵌套工作流 | 有 `workflow` 字段 |
90
- | `message` | 发送消息 | 有 `message` 字段 |
91
- | `think` | 主动思考 | 有 `topic` 字段 |
92
-
93
- ### 1. script - 脚本步骤
94
-
95
- 执行 JavaScript 脚本,**必须用 return 返回值**:
96
-
97
- ```json
98
- {
99
- "type": "script",
100
- "name": "步骤名称",
101
- "outputVariable": "result",
102
- "script": "var x=10; context.variables.count=x+1; return context.variables.count;"
103
- }
104
- ```
105
-
106
- **正确写法**:
107
-
108
- ```json
109
- { "script": "return context.variables.value + 1;" }
110
- ```
111
-
112
- **错误写法**(缺少 return):
113
-
114
- ```json
115
- { "script": "context.variables.value + 1;" }
116
- ```
117
-
118
- - `outputVariable`: 可选,将返回值存入 `context.variables`
119
- - `context.variables`: 所有步骤共享的变量对象
120
- - `context.lastResult`: 上一步的输出结果
121
-
122
- ### 2. tool - 工具调用步骤
123
-
124
- 在工作流中调用框架注册的工具:
125
-
126
- ```json
127
- {
128
- "type": "tool",
129
- "name": "发送通知",
130
- "tool": "notification_send",
131
- "args": {
132
- "title": "标题",
133
- "message": "内容"
134
- },
135
- "outputVariable": "result"
136
- }
137
- ```
138
-
139
- **参数说明**:
140
-
141
- | 字段 | 类型 | 必填 | 说明 |
142
- | ---------------- | ------ | ---- | ------------------ |
143
- | `tool` | string | 是 | 工具名称 |
144
- | `args` | object | 否 | 工具参数 |
145
- | `outputVariable` | string | 否 | 结果保存到的变量名 |
146
-
147
- **args 中支持变量引用**:
148
-
149
- 使用 `{{variableName}}` 语法引用 context.variables 中的变量:
150
-
151
- ```json
152
- {
153
- "type": "tool",
154
- "name": "发送通知",
155
- "tool": "notification_send",
156
- "args": {
157
- "title": "IP 信息",
158
- "message": "当前公网IP: {{currentIp}}"
159
- }
160
- }
161
- ```
162
-
163
- **重要:使用 `{{result}}` 引用上一步结果(推荐)**
164
-
165
- 上一步骤的结果自动保存在 `{{result}}` 中,可以直接提取字段:
166
-
167
- ```json
168
- {
169
- "type": "tool",
170
- "name": "获取IP",
171
- "tool": "fetch",
172
- "args": {
173
- "url": "https://api.ipify.org?format=json"
174
- }
175
- },
176
- {
177
- "type": "tool",
178
- "name": "发送通知",
179
- "tool": "notification_send",
180
- "args": {
181
- "title": "IP 信息",
182
- "message": "当前公网IP: {{result.body.ip}}"
183
- }
184
- }
185
- ```
186
-
187
- 支持的引用格式:
188
-
189
- | 格式 | 说明 |
190
- | ------------------------------ | -------------------------- |
191
- | `{{result}}` | 上一步完整结果 |
192
- | `{{result.body}}` | 提取 body 字段 |
193
- | `{{result.body.ip}}` | 从 body 提取嵌套字段 |
194
- | `{{result.body.data[0].name}}` | 支持数组索引 |
195
- | `{{lastResult}}` | result 的别名 |
196
- | `{{lastResult.error}}` | 从错误对象提取信息 |
197
- | `{{variables.xxx}}` | 显式引用 context.variables |
198
- | `{{input.xxx}}` | 引用工作流输入参数 |
199
-
200
- **自动 JSON 解析**:如果字段值是 JSON 字符串,会自动解析为对象后再提取嵌套字段。
201
-
202
- ### 3. loop - 循环步骤
203
-
204
- 重复执行一组步骤:
205
-
206
- ```json
207
- {
208
- "type": "loop",
209
- "name": "循环3次",
210
- "maxIterations": 3,
211
- "loopVariable": "i",
212
- "steps": [{ "type": "script", "name": "执行内容", "script": "..." }]
213
- }
214
- ```
215
-
216
- - `maxIterations`: 最大迭代次数
217
- - `loopVariable`: 循环计数器变量名(从 0 开始)
218
-
219
- ### 4. condition - 条件分支
220
-
221
- 根据条件选择执行分支:
222
-
223
- ```json
224
- {
225
- "type": "condition",
226
- "name": "判断条件",
227
- "branches": [
228
- {
229
- "name": "条件1",
230
- "condition": "context.variables.value > 10",
231
- "steps": [...]
232
- },
233
- {
234
- "name": "条件2",
235
- "condition": "context.variables.value <= 10",
236
- "steps": [...]
237
- }
238
- ]
239
- }
240
- ```
241
-
242
- ### 5. switch - 开关分支
243
-
244
- 根据值匹配执行对应分支(类似编程语言的 switch-case):
245
-
246
- ```json
247
- {
248
- "type": "switch",
249
- "value": "{{status}}",
250
- "branches": [
251
- { "case": "success", "steps": [...] },
252
- { "case": "error", "steps": [...] },
253
- { "case": "pending", "steps": [...] }
254
- ],
255
- "default": { "steps": [...] }
256
- }
257
- ```
258
-
259
- - `value`: 要匹配的值,支持 `{{variable}}` 引用
260
- - `branches`: 分支数组,匹配第一个 `case` 等于 `value` 的分支
261
- - `default`: 默认分支(可选)
262
-
263
- ### 6. try - 异常捕获
264
-
265
- 尝试执行,失败时执行 catch 分支:
266
-
267
- ```json
268
- {
269
- "type": "try",
270
- "name": "尝试执行",
271
- "try": {
272
- "steps": [
273
- { "type": "tool", "tool": "可能失败的工具", "args": {...} }
274
- ]
275
- },
276
- "catch": {
277
- "steps": [
278
- { "type": "tool", "tool": "notification_send", "args": {"message": "执行失败: {{lastError}}"} }
279
- ]
280
- }
281
- }
282
- ```
283
-
284
- - `try`: 尝试执行的步骤
285
- - `catch`: 捕获异常后执行的步骤
286
-
287
- ### 7. parallel - 并行执行
288
-
289
- 多个步骤同时并行执行:
290
-
291
- ```json
292
- {
293
- "type": "parallel",
294
- "name": "并行获取数据",
295
- "steps": [
296
- { "type": "tool", "tool": "fetch", "args": { "url": "https://api1.com" }, "output": "data1" },
297
- { "type": "tool", "tool": "fetch", "args": { "url": "https://api2.com" }, "output": "data2" },
298
- { "type": "tool", "tool": "fetch", "args": { "url": "https://api3.com" }, "output": "data3" }
299
- ]
300
- }
301
- ```
302
-
303
- 返回数组形式的执行结果。
304
-
305
- ### 8. workflow - 嵌套工作流
306
-
307
- 在一个工作流中调用另一个工作流:
308
-
309
- ```json
310
- {
311
- "type": "workflow",
312
- "name": "调用子工作流",
313
- "workflow": {
314
- "name": "子工作流名称",
315
- "steps": [...]
316
- },
317
- "input": {
318
- "param1": "{{parentVar}}"
319
- }
320
- }
321
- ```
322
-
323
- 子工作流的输出会合并到父工作流的上下文变量中。
324
-
325
- ### 9. delay - 延时步骤
326
-
327
- 等待指定毫秒数:
328
-
329
- ```json
330
- {
331
- "type": "delay",
332
- "name": "等待1秒",
333
- "delayMs": 1000
334
- }
335
- ```
336
-
337
- ### 10. sequential - 顺序步骤
338
-
339
- 将多个步骤组合为顺序执行(可嵌套使用):
340
-
341
- ```json
342
- {
343
- "type": "sequential",
344
- "name": "顺序执行",
345
- "steps": [
346
- { "type": "script", "name": "步骤1", "script": "return 1;" },
347
- { "type": "script", "name": "步骤2", "script": "return 2;" }
348
- ]
349
- }
350
- ```
351
-
352
- ## sessionId 传递
353
-
354
- 工作流执行时会自动获取当前 sessionId,所有 tool 调用都会使用该 sessionId,确保通知发送到当前会话。
355
-
356
- ## 完整示例
357
-
358
- ### 示例:获取IP并发送通知
359
-
360
- **推荐写法**(使用 `{{result}}` 直接引用上一步结果):
361
-
362
- ```json
363
- {
364
- "name": "get-ip-notify",
365
- "description": "获取本机IP并发送通知",
366
- "steps": [
367
- {
368
- "type": "tool",
369
- "name": "获取IP信息",
370
- "tool": "fetch",
371
- "args": {
372
- "url": "https://api.ipify.org?format=json",
373
- "proxy": true
374
- }
375
- },
376
- {
377
- "type": "tool",
378
- "name": "发送通知",
379
- "tool": "notification_send",
380
- "args": {
381
- "title": "IP 信息",
382
- "message": "当前公网IP: {{result.body.ip}}"
383
- }
384
- }
385
- ]
386
- }
387
- ```
388
-
389
- **旧写法**(仍支持,但不推荐):
390
-
391
- ```json
392
- {
393
- "name": "get-ip-notify-old",
394
- "steps": [
395
- {
396
- "type": "tool",
397
- "tool": "fetch",
398
- "args": { "url": "https://api.ipify.org?format=json" },
399
- "outputVariable": "ipResult"
400
- },
401
- {
402
- "type": "script",
403
- "outputVariable": "currentIp",
404
- "script": "var r=context.variables.ipResult; return (r&&r.success&&r.body)?(typeof r.body==='object'?r.body.ip:r.body.trim()):'获取失败';"
405
- },
406
- {
407
- "type": "tool",
408
- "tool": "notification_send",
409
- "args": { "message": "当前公网IP: {{currentIp}}" }
410
- }
411
- ]
412
- }
413
- ```
414
-
415
- ### 示例:循环处理任务列表
416
-
417
- ```json
418
- {
419
- "name": "process-items",
420
- "description": "循环处理列表中的每个项目",
421
- "steps": [
422
- {
423
- "type": "script",
424
- "name": "初始化列表",
425
- "outputVariable": "items",
426
- "script": "context.variables.items=['任务A','任务B','任务C']; return context.variables.items;"
427
- },
428
- {
429
- "type": "loop",
430
- "name": "处理每个任务",
431
- "maxIterations": 3,
432
- "loopVariable": "i",
433
- "steps": [
434
- {
435
- "type": "script",
436
- "name": "处理任务",
437
- "outputVariable": "processed",
438
- "script": "var item=context.variables.items[context.variables.i]; context.variables.processed=(context.variables.processed||[]); context.variables.processed.push(item+'_完成'); return item;"
439
- }
440
- ]
441
- }
442
- ]
443
- }
444
- ```
445
-
446
- ### 示例:并行获取多个数据源
447
-
448
- ```json
449
- {
450
- "name": "multi-source-fetch",
451
- "description": "并行获取多个数据源",
452
- "steps": [
453
- {
454
- "type": "parallel",
455
- "name": "并行获取数据",
456
- "steps": [
457
- {
458
- "type": "tool",
459
- "tool": "fetch",
460
- "args": { "url": "https://api.baidu.com" },
461
- "output": "baiduData"
462
- },
463
- {
464
- "type": "tool",
465
- "tool": "fetch",
466
- "args": { "url": "https://api.bbc.com" },
467
- "output": "bbcData"
468
- },
469
- {
470
- "type": "tool",
471
- "tool": "fetch",
472
- "args": { "url": "https://api.reddit.com" },
473
- "output": "redditData"
474
- }
475
- ]
476
- },
477
- {
478
- "type": "tool",
479
- "tool": "notification_send",
480
- "args": {
481
- "message": "数据获取完成: 百度 {{result[0].length}} 字节, BBC {{result[1].length}} 字节"
482
- }
483
- }
484
- ]
485
- }
486
- ```
487
-
488
- ### 示例:try-catch 异常处理
489
-
490
- ```json
491
- {
492
- "name": "safe-execute",
493
- "description": "带异常处理的工作流",
494
- "steps": [
495
- {
496
- "type": "try",
497
- "name": "尝试执行",
498
- "try": {
499
- "steps": [
500
- { "type": "tool", "tool": "fetch", "args": { "url": "https://可能失败的api.com" } }
501
- ]
502
- },
503
- "catch": {
504
- "steps": [
505
- {
506
- "type": "script",
507
- "outputVariable": "errorMsg",
508
- "script": "return 'API 调用失败,使用备用数据';"
509
- }
510
- ]
511
- }
512
- },
513
- {
514
- "type": "tool",
515
- "tool": "notification_send",
516
- "args": {
517
- "message": "结果: {{result.result || result.error}}"
518
- }
519
- }
520
- ]
521
- }
522
- ```
523
-
524
- ### 示例:switch 分支处理
525
-
526
- ```json
527
- {
528
- "name": "status-handler",
529
- "description": "根据状态分发处理",
530
- "steps": [
531
- {
532
- "type": "script",
533
- "outputVariable": "status",
534
- "script": "return 'success';"
535
- },
536
- {
537
- "type": "switch",
538
- "value": "{{status}}",
539
- "branches": [
540
- {
541
- "case": "success",
542
- "steps": [
543
- { "type": "tool", "tool": "notification_send", "args": { "message": "操作成功" } }
544
- ]
545
- },
546
- {
547
- "case": "error",
548
- "steps": [
549
- { "type": "tool", "tool": "notification_send", "args": { "message": "操作失败" } }
550
- ]
551
- },
552
- {
553
- "case": "pending",
554
- "steps": [
555
- { "type": "tool", "tool": "notification_send", "args": { "message": "操作进行中" } }
556
- ]
557
- }
558
- ],
559
- "default": {
560
- "steps": [
561
- { "type": "tool", "tool": "notification_send", "args": { "message": "未知状态" } }
562
- ]
563
- }
564
- }
565
- ]
566
- }
567
- ```
568
-
569
- ## 注意事项
570
-
571
- 1. **优先使用 `{{result}}` 引用**:上一步结果直接用 `{{result.field}}` 提取,比 script 更简洁
572
- 2. **script 必须 return**:`script` 是函数体,必须用 return 返回值
573
- 3. **JSON 中 script 单行写**:用分号分隔多个语句,不要换行
574
- 4. **JSON 中不能有注释**:注释会导致 JSON 解析失败
575
- 5. **context.variables** 在所有步骤间共享,可存储中间结果
576
- 6. **context.input** 是工作流的输入参数
577
- 7. 循环变量 `i` 从 0 开始计数
578
- 8. 条件分支的 `condition` 是 JavaScript 表达式字符串
579
- 9. **自动 JSON 解析**:`{{result.body}}` 如果是 JSON 字符串会自动解析
580
- 10. **类型自动推断**:如果步骤没有指定 `type`,会根据字段自动推断类型
581
- 11. **`${stepId.output}` 引用**:可引用指定 id 步骤的输出(兼容旧格式)
582
- 12. **`input` 字段**:可传递上一步输出给工具(兼容旧格式)
583
- 13. **try-catch 异常处理**:使用 try 包裹可能失败的步骤,catch 捕获错误
584
-
585
- ## 最佳实践
586
-
587
- 1. 为每个步骤设置有意义的 `name`
588
- 2. 使用 `outputVariable` 保存需要跨步骤共享的数据
589
- 3. 循环前确保有合理的 `maxIterations` 限制
590
- 4. 条件分支要有兜底的 `condition: "true"` 分支
591
- 5. 复杂的业务逻辑优先使用脚本步骤
592
- 6. **script 必须 return**:`script` 是函数体,必须用 return 返回值
593
- 7. **JSON 中 script 单行写**:用分号分隔多个语句,不要换行
594
- 8. **并行获取独立数据**:使用 `parallel` 同时获取多个数据源,节省时间
595
- 9. **使用 try-catch**:对可能失败的步骤使用异常捕获,避免整个工作流中断
596
- 10. **嵌套工作流**:将复杂工作流拆分为子工作流,提高复用性和可维护性
597
-
598
- **错误示例**:
599
-
600
- ```json
601
- // ❌ 错误 - script 没有 return
602
- { "type": "script", "script": "context.variables.count + 1;" }
603
-
604
- // ❌ 错误 - JSON 多行字符串
605
- {
606
- "script": "
607
- const a = 10;
608
- return a + 1;
609
- "
610
- }
611
-
612
- // ❌ 错误 - JSON 中有注释
613
- {
614
- "script": "return 1; // 这是注释"
615
- }
616
-
617
- // ❌ 错误 - switch 缺少 default 兜底
618
- {
619
- "type": "switch",
620
- "value": "{{status}}",
621
- "branches": [
622
- { "case": "success", "steps": [...] }
623
- ]
624
- // 没有 default 分支,匹配不到会静默忽略
625
- }
626
- ```
627
-
628
- **正确示例**:
629
-
630
- ```json
631
- // ✅ 正确
632
- { "type": "script", "outputVariable": "count", "script": "return (context.variables.count||0) + 1;" }
633
-
634
- // ✅ 正确 - 复杂逻辑拆成多步
635
- { "type": "script", "script": "context.variables.a=10; context.variables.b=20; return context.variables.a+context.variables.b;" }
636
-
637
- // ✅ 正确 - switch 有 default 兜底
638
- {
639
- "type": "switch",
640
- "value": "{{status}}",
641
- "branches": [
642
- { "case": "success", "steps": [...] }
643
- ],
644
- "default": { "steps": [{ "type": "tool", "tool": "notification_send", "args": {"message": "未知状态"} }] }
645
- }
646
- ```
1
+ ---
2
+ name: workflow-guide
3
+ description: 工作流与多步任务指南。当用户说"创建工作流"、"多步任务"、"自动化流程"时立即调用。
4
+ allowed-tools: execute_workflow,reloadWorkflows
5
+ ---
6
+
7
+ # 工作流(Workflow)开发指南
8
+
9
+ ## 概述
10
+
11
+ 工作流引擎用于处理多步骤任务,通过 `execute_workflow` 工具执行。工作流由多个步骤组成,支持脚本、条件分支、循环、延时、工具调用等类型。
12
+
13
+ ## 工作流存放位置
14
+
15
+ ```
16
+ 项目目录/
17
+ └── .foliko/
18
+ └── workflows/ # 工作流定义目录
19
+ └── my-workflow.json # 工作流 JSON 定义
20
+ └── another.js # 或 JS 文件(导出 default 工作流)
21
+ ```
22
+
23
+ ## 自动加载与注册
24
+
25
+ 将工作流文件放入 `.foliko/workflows/` 目录后,系统会自动:
26
+
27
+ 1. 加载所有 `.json` 和 `.js` 文件
28
+ 2. 将工作流注册为 `workflow_<文件名>` 工具
29
+
30
+ 例如 `my-workflow.json` 会注册为 `workflow_my_workflow` 工具,可直接调用。
31
+
32
+ ## 重载工作流
33
+
34
+ 创建或修改工作流后,调用 `reloadWorkflows` 重载:
35
+
36
+ ```json
37
+ {
38
+ "tool": "reloadWorkflows",
39
+ "args": {}
40
+ }
41
+ ```
42
+
43
+ ## 使用方式
44
+
45
+ ### 方式一:直接执行(任意工作流)
46
+
47
+ ```json
48
+ {
49
+ "tool": "execute_workflow",
50
+ "args": {
51
+ "workflow": "my-workflow", // 工作流名称(自动从 .foliko/workflows/ 加载)
52
+ "input": { "变量名": "值" }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ### 方式二:执行已注册的工作流工具
58
+
59
+ ```json
60
+ {
61
+ "tool": "workflow_my_workflow",
62
+ "args": {
63
+ "input": { "变量名": "值" }
64
+ }
65
+ }
66
+ ```
67
+
68
+ ## 重要注意事项
69
+
70
+ 1. **script 必须用 return 返回值**:`script` 是函数体,不是表达式
71
+ 2. **JSON 中不能使用多行字符串**:所有 script 内容写成单行,用分号分隔
72
+ 3. **JSON 中不能有注释**:注释会导致 JSON 解析失败
73
+
74
+ ## 工作流步骤类型
75
+
76
+ ### 支持的步骤类型
77
+
78
+ | 类型 | 说明 | 自动推断 |
79
+ | ------------ | --------------- | ------------------------------------------- |
80
+ | `tool` | 工具调用 | 有 `tool` 字段 |
81
+ | `script` | JavaScript 脚本 | 有 `code` 或 `script` 字段 |
82
+ | `condition` | 条件分支 | 有 `branches` 字段 |
83
+ | `switch` | 开关分支 | 有 `value` + `branches` |
84
+ | `try` | 异常捕获 | 有 `try` 或 `catch` 字段 |
85
+ | `parallel` | 并行执行 | `"parallel": true` 或 `"mode": "parallel"` |
86
+ | `sequential` | 顺序执行 | 有 `steps` 字段 |
87
+ | `loop` | 循环执行 | 有 `steps` + `loopVariable`/`maxIterations` |
88
+ | `delay` | 延时等待 | 有 `delayMs` 字段 |
89
+ | `workflow` | 嵌套工作流 | 有 `workflow` 字段 |
90
+ | `message` | 发送消息 | 有 `message` 字段 |
91
+ | `think` | 主动思考 | 有 `topic` 字段 |
92
+
93
+ ### 1. script - 脚本步骤
94
+
95
+ 执行 JavaScript 脚本,**必须用 return 返回值**:
96
+
97
+ ```json
98
+ {
99
+ "type": "script",
100
+ "name": "步骤名称",
101
+ "outputVariable": "result",
102
+ "script": "var x=10; context.variables.count=x+1; return context.variables.count;"
103
+ }
104
+ ```
105
+
106
+ **正确写法**:
107
+
108
+ ```json
109
+ { "script": "return context.variables.value + 1;" }
110
+ ```
111
+
112
+ **错误写法**(缺少 return):
113
+
114
+ ```json
115
+ { "script": "context.variables.value + 1;" }
116
+ ```
117
+
118
+ - `outputVariable`: 可选,将返回值存入 `context.variables`
119
+ - `context.variables`: 所有步骤共享的变量对象
120
+ - `context.lastResult`: 上一步的输出结果
121
+
122
+ ### 2. tool - 工具调用步骤
123
+
124
+ 在工作流中调用框架注册的工具:
125
+
126
+ ```json
127
+ {
128
+ "type": "tool",
129
+ "name": "发送通知",
130
+ "tool": "notification_send",
131
+ "args": {
132
+ "title": "标题",
133
+ "message": "内容"
134
+ },
135
+ "outputVariable": "result"
136
+ }
137
+ ```
138
+
139
+ **参数说明**:
140
+
141
+ | 字段 | 类型 | 必填 | 说明 |
142
+ | ---------------- | ------ | ---- | ------------------ |
143
+ | `tool` | string | 是 | 工具名称 |
144
+ | `args` | object | 否 | 工具参数 |
145
+ | `outputVariable` | string | 否 | 结果保存到的变量名 |
146
+
147
+ **args 中支持变量引用**:
148
+
149
+ 使用 `{{variableName}}` 语法引用 context.variables 中的变量:
150
+
151
+ ```json
152
+ {
153
+ "type": "tool",
154
+ "name": "发送通知",
155
+ "tool": "notification_send",
156
+ "args": {
157
+ "title": "IP 信息",
158
+ "message": "当前公网IP: {{currentIp}}"
159
+ }
160
+ }
161
+ ```
162
+
163
+ **重要:使用 `{{result}}` 引用上一步结果(推荐)**
164
+
165
+ 上一步骤的结果自动保存在 `{{result}}` 中,可以直接提取字段:
166
+
167
+ ```json
168
+ {
169
+ "type": "tool",
170
+ "name": "获取IP",
171
+ "tool": "fetch",
172
+ "args": {
173
+ "url": "https://api.ipify.org?format=json"
174
+ }
175
+ },
176
+ {
177
+ "type": "tool",
178
+ "name": "发送通知",
179
+ "tool": "notification_send",
180
+ "args": {
181
+ "title": "IP 信息",
182
+ "message": "当前公网IP: {{result.body.ip}}"
183
+ }
184
+ }
185
+ ```
186
+
187
+ 支持的引用格式:
188
+
189
+ | 格式 | 说明 |
190
+ | ------------------------------ | -------------------------- |
191
+ | `{{result}}` | 上一步完整结果 |
192
+ | `{{result.body}}` | 提取 body 字段 |
193
+ | `{{result.body.ip}}` | 从 body 提取嵌套字段 |
194
+ | `{{result.body.data[0].name}}` | 支持数组索引 |
195
+ | `{{lastResult}}` | result 的别名 |
196
+ | `{{lastResult.error}}` | 从错误对象提取信息 |
197
+ | `{{variables.xxx}}` | 显式引用 context.variables |
198
+ | `{{input.xxx}}` | 引用工作流输入参数 |
199
+
200
+ **自动 JSON 解析**:如果字段值是 JSON 字符串,会自动解析为对象后再提取嵌套字段。
201
+
202
+ ### 3. loop - 循环步骤
203
+
204
+ 重复执行一组步骤:
205
+
206
+ ```json
207
+ {
208
+ "type": "loop",
209
+ "name": "循环3次",
210
+ "maxIterations": 3,
211
+ "loopVariable": "i",
212
+ "steps": [{ "type": "script", "name": "执行内容", "script": "..." }]
213
+ }
214
+ ```
215
+
216
+ - `maxIterations`: 最大迭代次数
217
+ - `loopVariable`: 循环计数器变量名(从 0 开始)
218
+
219
+ ### 4. condition - 条件分支
220
+
221
+ 根据条件选择执行分支:
222
+
223
+ ```json
224
+ {
225
+ "type": "condition",
226
+ "name": "判断条件",
227
+ "branches": [
228
+ {
229
+ "name": "条件1",
230
+ "condition": "context.variables.value > 10",
231
+ "steps": [...]
232
+ },
233
+ {
234
+ "name": "条件2",
235
+ "condition": "context.variables.value <= 10",
236
+ "steps": [...]
237
+ }
238
+ ]
239
+ }
240
+ ```
241
+
242
+ ### 5. switch - 开关分支
243
+
244
+ 根据值匹配执行对应分支(类似编程语言的 switch-case):
245
+
246
+ ```json
247
+ {
248
+ "type": "switch",
249
+ "value": "{{status}}",
250
+ "branches": [
251
+ { "case": "success", "steps": [...] },
252
+ { "case": "error", "steps": [...] },
253
+ { "case": "pending", "steps": [...] }
254
+ ],
255
+ "default": { "steps": [...] }
256
+ }
257
+ ```
258
+
259
+ - `value`: 要匹配的值,支持 `{{variable}}` 引用
260
+ - `branches`: 分支数组,匹配第一个 `case` 等于 `value` 的分支
261
+ - `default`: 默认分支(可选)
262
+
263
+ ### 6. try - 异常捕获
264
+
265
+ 尝试执行,失败时执行 catch 分支:
266
+
267
+ ```json
268
+ {
269
+ "type": "try",
270
+ "name": "尝试执行",
271
+ "try": {
272
+ "steps": [
273
+ { "type": "tool", "tool": "可能失败的工具", "args": {...} }
274
+ ]
275
+ },
276
+ "catch": {
277
+ "steps": [
278
+ { "type": "tool", "tool": "notification_send", "args": {"message": "执行失败: {{lastError}}"} }
279
+ ]
280
+ }
281
+ }
282
+ ```
283
+
284
+ - `try`: 尝试执行的步骤
285
+ - `catch`: 捕获异常后执行的步骤
286
+
287
+ ### 7. parallel - 并行执行
288
+
289
+ 多个步骤同时并行执行:
290
+
291
+ ```json
292
+ {
293
+ "type": "parallel",
294
+ "name": "并行获取数据",
295
+ "steps": [
296
+ { "type": "tool", "tool": "fetch", "args": { "url": "https://api1.com" }, "output": "data1" },
297
+ { "type": "tool", "tool": "fetch", "args": { "url": "https://api2.com" }, "output": "data2" },
298
+ { "type": "tool", "tool": "fetch", "args": { "url": "https://api3.com" }, "output": "data3" }
299
+ ]
300
+ }
301
+ ```
302
+
303
+ 返回数组形式的执行结果。
304
+
305
+ ### 8. workflow - 嵌套工作流
306
+
307
+ 在一个工作流中调用另一个工作流:
308
+
309
+ ```json
310
+ {
311
+ "type": "workflow",
312
+ "name": "调用子工作流",
313
+ "workflow": {
314
+ "name": "子工作流名称",
315
+ "steps": [...]
316
+ },
317
+ "input": {
318
+ "param1": "{{parentVar}}"
319
+ }
320
+ }
321
+ ```
322
+
323
+ 子工作流的输出会合并到父工作流的上下文变量中。
324
+
325
+ ### 9. delay - 延时步骤
326
+
327
+ 等待指定毫秒数:
328
+
329
+ ```json
330
+ {
331
+ "type": "delay",
332
+ "name": "等待1秒",
333
+ "delayMs": 1000
334
+ }
335
+ ```
336
+
337
+ ### 10. sequential - 顺序步骤
338
+
339
+ 将多个步骤组合为顺序执行(可嵌套使用):
340
+
341
+ ```json
342
+ {
343
+ "type": "sequential",
344
+ "name": "顺序执行",
345
+ "steps": [
346
+ { "type": "script", "name": "步骤1", "script": "return 1;" },
347
+ { "type": "script", "name": "步骤2", "script": "return 2;" }
348
+ ]
349
+ }
350
+ ```
351
+
352
+ ## sessionId 传递
353
+
354
+ 工作流执行时会自动获取当前 sessionId,所有 tool 调用都会使用该 sessionId,确保通知发送到当前会话。
355
+
356
+ ## 完整示例
357
+
358
+ ### 示例:获取IP并发送通知
359
+
360
+ **推荐写法**(使用 `{{result}}` 直接引用上一步结果):
361
+
362
+ ```json
363
+ {
364
+ "name": "get-ip-notify",
365
+ "description": "获取本机IP并发送通知",
366
+ "steps": [
367
+ {
368
+ "type": "tool",
369
+ "name": "获取IP信息",
370
+ "tool": "fetch",
371
+ "args": {
372
+ "url": "https://api.ipify.org?format=json",
373
+ "proxy": true
374
+ }
375
+ },
376
+ {
377
+ "type": "tool",
378
+ "name": "发送通知",
379
+ "tool": "notification_send",
380
+ "args": {
381
+ "title": "IP 信息",
382
+ "message": "当前公网IP: {{result.body.ip}}"
383
+ }
384
+ }
385
+ ]
386
+ }
387
+ ```
388
+
389
+ **旧写法**(仍支持,但不推荐):
390
+
391
+ ```json
392
+ {
393
+ "name": "get-ip-notify-old",
394
+ "steps": [
395
+ {
396
+ "type": "tool",
397
+ "tool": "fetch",
398
+ "args": { "url": "https://api.ipify.org?format=json" },
399
+ "outputVariable": "ipResult"
400
+ },
401
+ {
402
+ "type": "script",
403
+ "outputVariable": "currentIp",
404
+ "script": "var r=context.variables.ipResult; return (r&&r.success&&r.body)?(typeof r.body==='object'?r.body.ip:r.body.trim()):'获取失败';"
405
+ },
406
+ {
407
+ "type": "tool",
408
+ "tool": "notification_send",
409
+ "args": { "message": "当前公网IP: {{currentIp}}" }
410
+ }
411
+ ]
412
+ }
413
+ ```
414
+
415
+ ### 示例:循环处理任务列表
416
+
417
+ ```json
418
+ {
419
+ "name": "process-items",
420
+ "description": "循环处理列表中的每个项目",
421
+ "steps": [
422
+ {
423
+ "type": "script",
424
+ "name": "初始化列表",
425
+ "outputVariable": "items",
426
+ "script": "context.variables.items=['任务A','任务B','任务C']; return context.variables.items;"
427
+ },
428
+ {
429
+ "type": "loop",
430
+ "name": "处理每个任务",
431
+ "maxIterations": 3,
432
+ "loopVariable": "i",
433
+ "steps": [
434
+ {
435
+ "type": "script",
436
+ "name": "处理任务",
437
+ "outputVariable": "processed",
438
+ "script": "var item=context.variables.items[context.variables.i]; context.variables.processed=(context.variables.processed||[]); context.variables.processed.push(item+'_完成'); return item;"
439
+ }
440
+ ]
441
+ }
442
+ ]
443
+ }
444
+ ```
445
+
446
+ ### 示例:并行获取多个数据源
447
+
448
+ ```json
449
+ {
450
+ "name": "multi-source-fetch",
451
+ "description": "并行获取多个数据源",
452
+ "steps": [
453
+ {
454
+ "type": "parallel",
455
+ "name": "并行获取数据",
456
+ "steps": [
457
+ {
458
+ "type": "tool",
459
+ "tool": "fetch",
460
+ "args": { "url": "https://api.baidu.com" },
461
+ "output": "baiduData"
462
+ },
463
+ {
464
+ "type": "tool",
465
+ "tool": "fetch",
466
+ "args": { "url": "https://api.bbc.com" },
467
+ "output": "bbcData"
468
+ },
469
+ {
470
+ "type": "tool",
471
+ "tool": "fetch",
472
+ "args": { "url": "https://api.reddit.com" },
473
+ "output": "redditData"
474
+ }
475
+ ]
476
+ },
477
+ {
478
+ "type": "tool",
479
+ "tool": "notification_send",
480
+ "args": {
481
+ "message": "数据获取完成: 百度 {{result[0].length}} 字节, BBC {{result[1].length}} 字节"
482
+ }
483
+ }
484
+ ]
485
+ }
486
+ ```
487
+
488
+ ### 示例:try-catch 异常处理
489
+
490
+ ```json
491
+ {
492
+ "name": "safe-execute",
493
+ "description": "带异常处理的工作流",
494
+ "steps": [
495
+ {
496
+ "type": "try",
497
+ "name": "尝试执行",
498
+ "try": {
499
+ "steps": [
500
+ { "type": "tool", "tool": "fetch", "args": { "url": "https://可能失败的api.com" } }
501
+ ]
502
+ },
503
+ "catch": {
504
+ "steps": [
505
+ {
506
+ "type": "script",
507
+ "outputVariable": "errorMsg",
508
+ "script": "return 'API 调用失败,使用备用数据';"
509
+ }
510
+ ]
511
+ }
512
+ },
513
+ {
514
+ "type": "tool",
515
+ "tool": "notification_send",
516
+ "args": {
517
+ "message": "结果: {{result.result || result.error}}"
518
+ }
519
+ }
520
+ ]
521
+ }
522
+ ```
523
+
524
+ ### 示例:switch 分支处理
525
+
526
+ ```json
527
+ {
528
+ "name": "status-handler",
529
+ "description": "根据状态分发处理",
530
+ "steps": [
531
+ {
532
+ "type": "script",
533
+ "outputVariable": "status",
534
+ "script": "return 'success';"
535
+ },
536
+ {
537
+ "type": "switch",
538
+ "value": "{{status}}",
539
+ "branches": [
540
+ {
541
+ "case": "success",
542
+ "steps": [
543
+ { "type": "tool", "tool": "notification_send", "args": { "message": "操作成功" } }
544
+ ]
545
+ },
546
+ {
547
+ "case": "error",
548
+ "steps": [
549
+ { "type": "tool", "tool": "notification_send", "args": { "message": "操作失败" } }
550
+ ]
551
+ },
552
+ {
553
+ "case": "pending",
554
+ "steps": [
555
+ { "type": "tool", "tool": "notification_send", "args": { "message": "操作进行中" } }
556
+ ]
557
+ }
558
+ ],
559
+ "default": {
560
+ "steps": [
561
+ { "type": "tool", "tool": "notification_send", "args": { "message": "未知状态" } }
562
+ ]
563
+ }
564
+ }
565
+ ]
566
+ }
567
+ ```
568
+
569
+ ## 注意事项
570
+
571
+ 1. **优先使用 `{{result}}` 引用**:上一步结果直接用 `{{result.field}}` 提取,比 script 更简洁
572
+ 2. **script 必须 return**:`script` 是函数体,必须用 return 返回值
573
+ 3. **JSON 中 script 单行写**:用分号分隔多个语句,不要换行
574
+ 4. **JSON 中不能有注释**:注释会导致 JSON 解析失败
575
+ 5. **context.variables** 在所有步骤间共享,可存储中间结果
576
+ 6. **context.input** 是工作流的输入参数
577
+ 7. 循环变量 `i` 从 0 开始计数
578
+ 8. 条件分支的 `condition` 是 JavaScript 表达式字符串
579
+ 9. **自动 JSON 解析**:`{{result.body}}` 如果是 JSON 字符串会自动解析
580
+ 10. **类型自动推断**:如果步骤没有指定 `type`,会根据字段自动推断类型
581
+ 11. **`${stepId.output}` 引用**:可引用指定 id 步骤的输出(兼容旧格式)
582
+ 12. **`input` 字段**:可传递上一步输出给工具(兼容旧格式)
583
+ 13. **try-catch 异常处理**:使用 try 包裹可能失败的步骤,catch 捕获错误
584
+
585
+ ## 最佳实践
586
+
587
+ 1. 为每个步骤设置有意义的 `name`
588
+ 2. 使用 `outputVariable` 保存需要跨步骤共享的数据
589
+ 3. 循环前确保有合理的 `maxIterations` 限制
590
+ 4. 条件分支要有兜底的 `condition: "true"` 分支
591
+ 5. 复杂的业务逻辑优先使用脚本步骤
592
+ 6. **script 必须 return**:`script` 是函数体,必须用 return 返回值
593
+ 7. **JSON 中 script 单行写**:用分号分隔多个语句,不要换行
594
+ 8. **并行获取独立数据**:使用 `parallel` 同时获取多个数据源,节省时间
595
+ 9. **使用 try-catch**:对可能失败的步骤使用异常捕获,避免整个工作流中断
596
+ 10. **嵌套工作流**:将复杂工作流拆分为子工作流,提高复用性和可维护性
597
+
598
+ **错误示例**:
599
+
600
+ ```json
601
+ // ❌ 错误 - script 没有 return
602
+ { "type": "script", "script": "context.variables.count + 1;" }
603
+
604
+ // ❌ 错误 - JSON 多行字符串
605
+ {
606
+ "script": "
607
+ const a = 10;
608
+ return a + 1;
609
+ "
610
+ }
611
+
612
+ // ❌ 错误 - JSON 中有注释
613
+ {
614
+ "script": "return 1; // 这是注释"
615
+ }
616
+
617
+ // ❌ 错误 - switch 缺少 default 兜底
618
+ {
619
+ "type": "switch",
620
+ "value": "{{status}}",
621
+ "branches": [
622
+ { "case": "success", "steps": [...] }
623
+ ]
624
+ // 没有 default 分支,匹配不到会静默忽略
625
+ }
626
+ ```
627
+
628
+ **正确示例**:
629
+
630
+ ```json
631
+ // ✅ 正确
632
+ { "type": "script", "outputVariable": "count", "script": "return (context.variables.count||0) + 1;" }
633
+
634
+ // ✅ 正确 - 复杂逻辑拆成多步
635
+ { "type": "script", "script": "context.variables.a=10; context.variables.b=20; return context.variables.a+context.variables.b;" }
636
+
637
+ // ✅ 正确 - switch 有 default 兜底
638
+ {
639
+ "type": "switch",
640
+ "value": "{{status}}",
641
+ "branches": [
642
+ { "case": "success", "steps": [...] }
643
+ ],
644
+ "default": { "steps": [{ "type": "tool", "tool": "notification_send", "args": {"message": "未知状态"} }] }
645
+ }
646
+ ```