@foresthubai/workflow-cli 0.4.2 → 0.4.4

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,895 +1,912 @@
1
- openapi: 3.0.3
2
- info:
3
- title: ForestHub Workflow Contract
4
- version: 1.0.0
5
- description: OpenAPI schema definition for the ForestHub workflow format.
6
-
7
- components:
8
- schemas:
9
- DataType:
10
- type: string
11
- enum: [int, float, bool, string]
12
-
13
- SignalType:
14
- type: string
15
- enum: [digital, analog]
16
-
17
- EdgeType:
18
- type: string
19
- enum: [control, tool, agentTask, agentChoice, agentDelegate]
20
-
21
- NodePosition:
22
- type: object
23
- required: [x, y]
24
- properties:
25
- x:
26
- type: number
27
- y:
28
- type: number
29
-
30
- Workflow:
31
- type: object
32
- description: Workflow represents the deployment format of a project, passed to agents.
33
- required:
34
- [
35
- schemaVersion,
36
- nodes,
37
- edges,
38
- functions,
39
- declaredVariables,
40
- channels,
41
- memory,
42
- models,
43
- ]
44
- properties:
45
- schemaVersion:
46
- type: integer
47
- format: int32
48
- minimum: 1
49
- description: Monotonic version of the persisted workflow format, bumped when the serialized shape changes.
50
- nodes:
51
- type: array
52
- items:
53
- $ref: "#/components/schemas/Node"
54
- edges:
55
- type: array
56
- items:
57
- $ref: "#/components/schemas/Edge"
58
- functions:
59
- type: array
60
- items:
61
- $ref: "#/components/schemas/Function"
62
- declaredVariables:
63
- type: array
64
- items:
65
- $ref: "#/components/schemas/Variable"
66
- channels:
67
- type: array
68
- items:
69
- $ref: "#/components/schemas/Channel"
70
- memory:
71
- type: array
72
- items:
73
- $ref: "#/components/schemas/Memory"
74
- models:
75
- type: array
76
- description: Declared custom/self-hosted models; referenced from nodes by id. Static catalog models need no declaration.
77
- items:
78
- $ref: "#/components/schemas/Model"
79
-
80
- Edge:
81
- type: object
82
- required: [id, type, from, to]
83
- properties:
84
- id:
85
- type: string
86
- type:
87
- $ref: "#/components/schemas/EdgeType"
88
- from:
89
- $ref: "#/components/schemas/Vertex"
90
- to:
91
- $ref: "#/components/schemas/Vertex"
92
- prompt:
93
- $ref: "#/components/schemas/Expression"
94
- description: >
95
- Prompt expression sent to the agent. Present on `agentTask` (required)
96
- and `agentDelegate` (optional).
97
- description:
98
- type: string
99
- description: LLM-readable explanation of when the edge should fire. Present on `agentChoice` and `agentDelegate`.
100
-
101
- Vertex:
102
- type: object
103
- required:
104
- - nodeId
105
- - port
106
- properties:
107
- nodeId:
108
- type: string
109
- port:
110
- type: string
111
-
112
- Function:
113
- type: object
114
- required:
115
- [functionInfo, outputAssignments, nodes, edges, declaredVariables]
116
- properties:
117
- functionInfo:
118
- $ref: "#/components/schemas/FunctionInfo"
119
- outputAssignments:
120
- type: object
121
- description: Maps return variable uid to its Expression
122
- additionalProperties:
123
- $ref: "#/components/schemas/Expression"
124
- nodes:
125
- type: array
126
- items:
127
- $ref: "#/components/schemas/Node"
128
- edges:
129
- type: array
130
- items:
131
- $ref: "#/components/schemas/Edge"
132
- declaredVariables:
133
- type: array
134
- items:
135
- $ref: "#/components/schemas/Variable"
136
-
137
- FunctionInfo:
138
- type: object
139
- required: [id, version, name, arguments, returns]
140
- properties:
141
- id:
142
- type: string
143
- version:
144
- type: integer
145
- format: int32
146
- minimum: 0
147
- name:
148
- type: string
149
- arguments:
150
- type: array
151
- items:
152
- $ref: "#/components/schemas/Variable"
153
- returns:
154
- type: array
155
- items:
156
- $ref: "#/components/schemas/Variable"
157
-
158
- Variable:
159
- description: A named, typed variable with a stable uid that can be referenced throughout the workflow.
160
- required: [uid, name, dataType]
161
- properties:
162
- uid:
163
- type: string
164
- description: Stable identifier that survives renames
165
- name:
166
- type: string
167
- dataType:
168
- $ref: "#/components/schemas/DataType"
169
- initialValue:
170
- description: Initial value matching the dataType (number, boolean, or string). Only used by declared variables.
171
-
172
- Expression:
173
- type: object
174
- required: [expression, references, dataType]
175
- properties:
176
- expression:
177
- type: string
178
- references:
179
- description: A list of referenced variable IDs used in the expression
180
- type: array
181
- items:
182
- $ref: "#/components/schemas/Reference"
183
- dataType:
184
- $ref: "#/components/schemas/DataType"
185
-
186
- Reference:
187
- type: object
188
- required: [srcId, varId]
189
- properties:
190
- srcId:
191
- type: string
192
- varId:
193
- type: string
194
-
195
- OutputBinding:
196
- type: object
197
- required: [active, mode]
198
- properties:
199
- active:
200
- type: boolean
201
- description: Discard the output if false; route it according to `mode` if true
202
- mode:
203
- type: string
204
- enum: [emit, assign]
205
- # mode=emit
206
- name:
207
- type: string
208
- description: Variable name (when mode=emit)
209
- # mode=assign
210
- target:
211
- $ref: "#/components/schemas/Reference"
212
- description: Existing variable to route to (when mode=assign)
213
-
214
- OutputDeclaration:
215
- type: object
216
- required: [mode, name, dataType]
217
- properties:
218
- mode:
219
- type: string
220
- enum: [emit, assign]
221
- name:
222
- type: string
223
- description: JSON property name of the declared output
224
- dataType:
225
- $ref: "#/components/schemas/DataType"
226
- # mode=emit
227
- uid:
228
- type: string
229
- description: New variable uid (when mode=emit)
230
- # mode=assign
231
- target:
232
- $ref: "#/components/schemas/Reference"
233
- description: Existing variable to route to (when mode=assign)
234
-
235
- # ====== Memory ======
236
-
237
- Memory:
238
- oneOf:
239
- - $ref: "#/components/schemas/MemoryFile"
240
- - $ref: "#/components/schemas/VectorDatabase"
241
- discriminator:
242
- propertyName: type
243
- mapping:
244
- MemoryFile: "#/components/schemas/MemoryFile"
245
- VectorDatabase: "#/components/schemas/VectorDatabase"
246
-
247
- MemoryFile:
248
- type: object
249
- description: One .md file that agent nodes can read and write to.
250
- required: [type, id, label, description, content]
251
- properties:
252
- type: { type: string, enum: [MemoryFile] }
253
- id:
254
- type: string
255
- description: Stable identifier that survives renames; referenced from MemoryRef.
256
- label:
257
- type: string
258
- description: Display name. Unique per agent (LLM tool enums use it).
259
- description:
260
- type: string
261
- content:
262
- type: string
263
- maxSizeBytes:
264
- type: integer
265
- nullable: true
266
- description: Byte cap; null means unlimited.
267
-
268
- VectorDatabase:
269
- type: object
270
- description: A vector database for retrieval-augmented generation (RAG).
271
- required: [type, id, label]
272
- properties:
273
- type: { type: string, enum: [VectorDatabase] }
274
- id:
275
- type: string
276
- description: Stable identifier; referenced from Retriever nodes.
277
- label:
278
- type: string
279
- description: Display name.
280
- description:
281
- type: string
282
-
283
- MemoryRef:
284
- type: object
285
- description: Reference from an LLM agent node to a declared MemoryFile with an access mode.
286
- required: [id, mode]
287
- properties:
288
- id:
289
- type: string
290
- description: id of the referenced MemoryFile.
291
- mode:
292
- type: string
293
- enum: [r, rw]
294
- description: r = read-only; rw = read + write.
295
-
296
- # ====== Models ======
297
-
298
- Model:
299
- oneOf:
300
- - $ref: "#/components/schemas/LLMModel"
301
- discriminator:
302
- propertyName: type
303
- mapping:
304
- LLMModel: "#/components/schemas/LLMModel"
305
-
306
- LLMModel:
307
- type: object
308
- description: A custom or self-hosted language model that agent nodes can reference.
309
- required: [type, id, label, capabilities]
310
- properties:
311
- type: { type: string, enum: [LLMModel] }
312
- id:
313
- type: string
314
- description: Stable identifier; this is the ModelID nodes reference.
315
- label:
316
- type: string
317
- description: Display name.
318
- capabilities:
319
- type: array
320
- description: Capabilities this model supports (used to filter model pickers).
321
- items:
322
- $ref: "llmproxy.yaml#/components/schemas/ModelCapability"
323
-
324
- # ====== Nodes ======
325
-
326
- Node:
327
- oneOf:
328
- - $ref: "#/components/schemas/ReadPinNode"
329
- - $ref: "#/components/schemas/WritePinNode"
330
- - $ref: "#/components/schemas/AgentNode"
331
- - $ref: "#/components/schemas/IfNode"
332
- - $ref: "#/components/schemas/SerialReadNode"
333
- - $ref: "#/components/schemas/SerialWriteNode"
334
- - $ref: "#/components/schemas/RetrieverNode"
335
- - $ref: "#/components/schemas/WebFetchNode"
336
- - $ref: "#/components/schemas/FunctionCallNode"
337
- - $ref: "#/components/schemas/OnFunctionCallNode"
338
- - $ref: "#/components/schemas/DelayNode"
339
- - $ref: "#/components/schemas/TickerNode"
340
- - $ref: "#/components/schemas/AlarmNode"
341
- - $ref: "#/components/schemas/WebSearchToolNode"
342
- - $ref: "#/components/schemas/OnStartupNode"
343
- - $ref: "#/components/schemas/OnPinEdgeNode"
344
- - $ref: "#/components/schemas/OnSerialReceiveNode"
345
- - $ref: "#/components/schemas/OnThresholdNode"
346
- - $ref: "#/components/schemas/SetVariableNode"
347
- - $ref: "#/components/schemas/MqttPublishNode"
348
- - $ref: "#/components/schemas/OnMqttMessageNode"
349
- discriminator:
350
- propertyName: type
351
- mapping:
352
- ReadPin: "#/components/schemas/ReadPinNode"
353
- WritePin: "#/components/schemas/WritePinNode"
354
- Agent: "#/components/schemas/AgentNode"
355
- If: "#/components/schemas/IfNode"
356
- SerialRead: "#/components/schemas/SerialReadNode"
357
- SerialWrite: "#/components/schemas/SerialWriteNode"
358
- Retriever: "#/components/schemas/RetrieverNode"
359
- WebFetch: "#/components/schemas/WebFetchNode"
360
- FunctionCall: "#/components/schemas/FunctionCallNode"
361
- OnFunctionCall: "#/components/schemas/OnFunctionCallNode"
362
- Delay: "#/components/schemas/DelayNode"
363
- Ticker: "#/components/schemas/TickerNode"
364
- Alarm: "#/components/schemas/AlarmNode"
365
- WebSearchTool: "#/components/schemas/WebSearchToolNode"
366
- OnStartup: "#/components/schemas/OnStartupNode"
367
- OnPinEdge: "#/components/schemas/OnPinEdgeNode"
368
- OnSerialReceive: "#/components/schemas/OnSerialReceiveNode"
369
- OnThreshold: "#/components/schemas/OnThresholdNode"
370
- SetVariable: "#/components/schemas/SetVariableNode"
371
- MqttPublish: "#/components/schemas/MqttPublishNode"
372
- OnMqttMessage: "#/components/schemas/OnMqttMessageNode"
373
-
374
- WebSearchToolNode:
375
- type: object
376
- required: [id, type, arguments, position]
377
- properties:
378
- id: { type: string }
379
- type: { type: string, enum: [WebSearchTool] }
380
- label: { type: string }
381
- position: { $ref: "#/components/schemas/NodePosition" }
382
- arguments:
383
- type: object
384
- properties:
385
- maxResults:
386
- type: integer
387
- description: Maximum number of search results to return per call. Defaults to 5 when omitted or non-positive. Capped at 20.
388
- minimum: 1
389
-
390
- DelayNode:
391
- type: object
392
- required: [id, type, arguments, position]
393
- properties:
394
- id: { type: string }
395
- type: { type: string, enum: [Delay] }
396
- label: { type: string }
397
- position: { $ref: "#/components/schemas/NodePosition" }
398
- arguments:
399
- type: object
400
- properties:
401
- delayMs:
402
- type: integer
403
- description: Time in milliseconds to pause execution
404
-
405
- TickerNode:
406
- type: object
407
- required: [id, type, arguments, position]
408
- properties:
409
- id: { type: string }
410
- type: { type: string, enum: [Ticker] }
411
- label: { type: string }
412
- position: { $ref: "#/components/schemas/NodePosition" }
413
- arguments:
414
- type: object
415
- required: [intervalUnit]
416
- properties:
417
- intervalValue:
418
- type: integer
419
- description: How many units between ticks
420
- intervalUnit:
421
- type: string
422
- enum: [milliseconds, seconds, minutes, hours]
423
- description: Time unit for the interval
424
-
425
- AlarmNode:
426
- type: object
427
- required: [id, type, arguments, position]
428
- properties:
429
- id: { type: string }
430
- type: { type: string, enum: [Alarm] }
431
- label: { type: string }
432
- position: { $ref: "#/components/schemas/NodePosition" }
433
- arguments:
434
- type: object
435
- required: [days]
436
- properties:
437
- time:
438
- type: string
439
- description: "Time of day to fire (HH:MM, 24h format)"
440
- days:
441
- type: array
442
- items:
443
- type: string
444
- description: "Days of the week to fire on (empty = every day)"
445
-
446
- FunctionCallNode:
447
- type: object
448
- required: [id, type, arguments, position, functionId]
449
- properties:
450
- id: { type: string }
451
- type: { type: string, enum: [FunctionCall] }
452
- label: { type: string }
453
- position: { $ref: "#/components/schemas/NodePosition" }
454
- functionId:
455
- type: string
456
- description: Id of the function this node calls. The signature is resolved from the workflow's functions table.
457
- arguments:
458
- type: object
459
- properties:
460
- inputBindings:
461
- type: object
462
- additionalProperties:
463
- $ref: "#/components/schemas/Expression"
464
- outputBindings:
465
- type: object
466
- additionalProperties:
467
- $ref: "#/components/schemas/OutputBinding"
468
- toolDescription:
469
- type: string
470
- description: >
471
- Description exposed to the LLM when this function is wired as
472
- a tool. Ignored in exec mode.
473
-
474
- OnFunctionCallNode:
475
- type: object
476
- required: [id, type, position]
477
- properties:
478
- id: { type: string }
479
- type: { type: string, enum: [OnFunctionCall] }
480
- label: { type: string }
481
- position: { $ref: "#/components/schemas/NodePosition" }
482
-
483
- OnStartupNode:
484
- type: object
485
- required: [id, type, position]
486
- properties:
487
- id: { type: string }
488
- type: { type: string, enum: [OnStartup] }
489
- label: { type: string }
490
- position: { $ref: "#/components/schemas/NodePosition" }
491
-
492
- OnPinEdgeNode:
493
- type: object
494
- required: [id, type, arguments, position]
495
- properties:
496
- id: { type: string }
497
- type: { type: string, enum: [OnPinEdge] }
498
- label: { type: string }
499
- position: { $ref: "#/components/schemas/NodePosition" }
500
- arguments:
501
- type: object
502
- required: [edge]
503
- properties:
504
- pinReference:
505
- type: string
506
- description: IO variable ID of the digital pin to watch
507
- edge:
508
- type: string
509
- enum: [rising, falling, both]
510
- description: Edge transition that fires the trigger
511
-
512
- OnSerialReceiveNode:
513
- type: object
514
- required: [id, type, arguments, position]
515
- properties:
516
- id: { type: string }
517
- type: { type: string, enum: [OnSerialReceive] }
518
- label: { type: string }
519
- position: { $ref: "#/components/schemas/NodePosition" }
520
- arguments:
521
- type: object
522
- required: [output]
523
- properties:
524
- portReference:
525
- type: string
526
- description: Reference to an IO variable ID (the serial port to listen on)
527
- output:
528
- $ref: "#/components/schemas/OutputBinding"
529
-
530
- OnThresholdNode:
531
- type: object
532
- required: [id, type, arguments, position]
533
- properties:
534
- id: { type: string }
535
- type: { type: string, enum: [OnThreshold] }
536
- label: { type: string }
537
- position: { $ref: "#/components/schemas/NodePosition" }
538
- arguments:
539
- type: object
540
- required: [direction, output]
541
- properties:
542
- variable:
543
- $ref: "#/components/schemas/Reference"
544
- description: Numeric variable to watch for threshold crossings
545
- threshold:
546
- type: number
547
- description: Value the variable crosses to fire the trigger
548
- direction:
549
- type: string
550
- enum: [rising, falling, both]
551
- description: Crossing direction to fire on (default both)
552
- deadband:
553
- type: number
554
- description: Hysteresis band width around threshold; 0 disables (default 0)
555
- output:
556
- $ref: "#/components/schemas/OutputBinding"
557
- description: Optional binding for the triggering value
558
-
559
- RetrieverNode:
560
- type: object
561
- required: [id, type, arguments, position]
562
- properties:
563
- id: { type: string }
564
- type: { type: string, enum: [Retriever] }
565
- label: { type: string }
566
- position: { $ref: "#/components/schemas/NodePosition" }
567
- arguments:
568
- type: object
569
- required: [query, output]
570
- properties:
571
- memoryReference:
572
- type: string
573
- description: Reference to a declared VectorDatabase memory id
574
- topK:
575
- type: integer
576
- description: Number of results to return
577
- query:
578
- $ref: "#/components/schemas/Expression"
579
- description: Search query expression
580
- output:
581
- $ref: "#/components/schemas/OutputBinding"
582
- toolDescription:
583
- type: string
584
- description: Description exposed to the LLM when this node is wired as a tool. Ignored in exec mode.
585
-
586
- WebFetchNode:
587
- type: object
588
- required: [id, type, arguments, position]
589
- properties:
590
- id: { type: string }
591
- type: { type: string, enum: [WebFetch] }
592
- label: { type: string }
593
- position: { $ref: "#/components/schemas/NodePosition" }
594
- arguments:
595
- type: object
596
- required: [url, output]
597
- properties:
598
- url:
599
- $ref: "#/components/schemas/Expression"
600
- description: URL expression to fetch (http or https)
601
- maxChars:
602
- type: integer
603
- description: Maximum characters of extracted text to return. Defaults to 50000 when omitted or non-positive.
604
- minimum: 1
605
- output:
606
- $ref: "#/components/schemas/OutputBinding"
607
-
608
- ReadPinNode:
609
- type: object
610
- required: [id, type, arguments, position]
611
- properties:
612
- id: { type: string }
613
- type: { type: string, enum: [ReadPin] }
614
- label: { type: string }
615
- position: { $ref: "#/components/schemas/NodePosition" }
616
- arguments:
617
- type: object
618
- required: [signalType, output]
619
- properties:
620
- pinReference:
621
- type: string
622
- description: Reference to an IO variable ID
623
- signalType:
624
- $ref: "#/components/schemas/SignalType"
625
- output:
626
- $ref: "#/components/schemas/OutputBinding"
627
- toolDescription:
628
- type: string
629
- description: Description exposed to the LLM when this node is wired as a tool. Ignored in exec mode.
630
-
631
- WritePinNode:
632
- type: object
633
- required: [id, type, arguments, position]
634
- properties:
635
- id: { type: string }
636
- type: { type: string, enum: [WritePin] }
637
- label: { type: string }
638
- position: { $ref: "#/components/schemas/NodePosition" }
639
- arguments:
640
- type: object
641
- required: [signalType, value]
642
- properties:
643
- pinReference:
644
- type: string
645
- description: Reference to an IO variable ID
646
- signalType:
647
- $ref: "#/components/schemas/SignalType"
648
- value:
649
- $ref: "#/components/schemas/Expression"
650
-
651
- AgentNode:
652
- type: object
653
- required: [id, type, arguments, position]
654
- properties:
655
- id: { type: string }
656
- type: { type: string, enum: [Agent] }
657
- label: { type: string }
658
- position: { $ref: "#/components/schemas/NodePosition" }
659
- arguments:
660
- type: object
661
- required: [answer, outputDeclarations, memoryRefs]
662
- properties:
663
- name:
664
- type: string
665
- description: Name of the agent
666
- model:
667
- type: string
668
- instructions:
669
- type: string
670
- maxTurns:
671
- type: integer
672
- description: Maximum number of agent runner turns
673
- answer:
674
- $ref: "#/components/schemas/OutputBinding"
675
- outputDeclarations:
676
- type: array
677
- description: Ordered list of structured-output declarations. Names must be unique within this list
678
- items:
679
- $ref: "#/components/schemas/OutputDeclaration"
680
- memoryRefs:
681
- type: array
682
- description: Memory files this agent can access, each with an access mode.
683
- items:
684
- $ref: "#/components/schemas/MemoryRef"
685
- toolDescription:
686
- type: string
687
- description: Description exposed to the LLM when this node is wired as a tool. Ignored in exec mode.
688
-
689
- IfNode:
690
- type: object
691
- required: [id, type, arguments, position]
692
- properties:
693
- id: { type: string }
694
- type: { type: string, enum: [If] }
695
- label: { type: string }
696
- position: { $ref: "#/components/schemas/NodePosition" }
697
- arguments:
698
- type: object
699
- required: [condition]
700
- properties:
701
- condition:
702
- $ref: "#/components/schemas/Expression"
703
-
704
- SerialReadNode:
705
- type: object
706
- required: [id, type, arguments, position]
707
- properties:
708
- id: { type: string }
709
- type: { type: string, enum: [SerialRead] }
710
- label: { type: string }
711
- position: { $ref: "#/components/schemas/NodePosition" }
712
- arguments:
713
- type: object
714
- required: [output]
715
- properties:
716
- portReference:
717
- type: string
718
- description: Reference to an UART ID (the serial port to read from)
719
- prompt:
720
- type: string
721
- output:
722
- $ref: "#/components/schemas/OutputBinding"
723
-
724
- SerialWriteNode:
725
- type: object
726
- required: [id, type, arguments, position]
727
- properties:
728
- id: { type: string }
729
- type: { type: string, enum: [SerialWrite] }
730
- label: { type: string }
731
- position: { $ref: "#/components/schemas/NodePosition" }
732
- arguments:
733
- type: object
734
- required: [value]
735
- properties:
736
- portReference:
737
- type: string
738
- description: Reference to a UART channel ID (the serial port to write to)
739
- value:
740
- $ref: "#/components/schemas/Expression"
741
-
742
- SetVariableNode:
743
- type: object
744
- required: [id, type, arguments, position]
745
- properties:
746
- id: { type: string }
747
- type: { type: string, enum: [SetVariable] }
748
- label: { type: string }
749
- position: { $ref: "#/components/schemas/NodePosition" }
750
- arguments:
751
- type: object
752
- required: [value]
753
- properties:
754
- variable:
755
- $ref: "#/components/schemas/Reference"
756
- value:
757
- $ref: "#/components/schemas/Expression"
758
-
759
- MqttPublishNode:
760
- type: object
761
- required: [id, type, arguments, position]
762
- properties:
763
- id: { type: string }
764
- type: { type: string, enum: [MqttPublish] }
765
- label: { type: string }
766
- position: { $ref: "#/components/schemas/NodePosition" }
767
- arguments:
768
- type: object
769
- required: [dataType, value, qos, retain]
770
- properties:
771
- channelReference:
772
- type: string
773
- description: Reference to an MQTT channel ID (the channel carries the topic; resolved to a broker at deploy time)
774
- dataType:
775
- $ref: "#/components/schemas/DataType"
776
- value:
777
- $ref: "#/components/schemas/Expression"
778
- qos:
779
- type: integer
780
- enum: [0, 1, 2]
781
- description: MQTT Quality of Service level
782
- retain:
783
- type: boolean
784
- description: Whether the broker should retain the message
785
-
786
- OnMqttMessageNode:
787
- type: object
788
- required: [id, type, arguments, position]
789
- properties:
790
- id: { type: string }
791
- type: { type: string, enum: [OnMqttMessage] }
792
- label: { type: string }
793
- position: { $ref: "#/components/schemas/NodePosition" }
794
- arguments:
795
- type: object
796
- required: [dataType, output]
797
- properties:
798
- channelReference:
799
- type: string
800
- description: Reference to an MQTT channel ID (the channel carries the topic filter; resolved to a broker at deploy time)
801
- dataType:
802
- $ref: "#/components/schemas/DataType"
803
- output:
804
- $ref: "#/components/schemas/OutputBinding"
805
-
806
- # ====== Channels ======
807
-
808
- Channel:
809
- oneOf:
810
- - $ref: "#/components/schemas/GPIOINChannel"
811
- - $ref: "#/components/schemas/GPIOOUTChannel"
812
- - $ref: "#/components/schemas/ADCChannel"
813
- - $ref: "#/components/schemas/PWMChannel"
814
- - $ref: "#/components/schemas/DACChannel"
815
- - $ref: "#/components/schemas/UARTChannel"
816
- - $ref: "#/components/schemas/MQTTChannel"
817
- discriminator:
818
- propertyName: type
819
- mapping:
820
- GPIOIN: "#/components/schemas/GPIOINChannel"
821
- GPIOOUT: "#/components/schemas/GPIOOUTChannel"
822
- ADC: "#/components/schemas/ADCChannel"
823
- PWM: "#/components/schemas/PWMChannel"
824
- DAC: "#/components/schemas/DACChannel"
825
- UART: "#/components/schemas/UARTChannel"
826
- MQTT: "#/components/schemas/MQTTChannel"
827
-
828
- GPIOINChannel:
829
- type: object
830
- required: [type, id, label, bias, debounceMs]
831
- properties:
832
- type: { type: string, enum: [GPIOIN] }
833
- id: { type: string }
834
- label: { type: string }
835
- bias:
836
- type: string
837
- enum: [none, pullup, pulldown]
838
- description: Pin bias configuration
839
- debounceMs:
840
- type: integer
841
- description: Debounce window in milliseconds
842
-
843
- GPIOOUTChannel:
844
- type: object
845
- required: [type, id, label]
846
- properties:
847
- type: { type: string, enum: [GPIOOUT] }
848
- id: { type: string }
849
- label: { type: string }
850
-
851
- ADCChannel:
852
- type: object
853
- required: [type, id, label]
854
- properties:
855
- type: { type: string, enum: [ADC] }
856
- id: { type: string }
857
- label: { type: string }
858
-
859
- PWMChannel:
860
- type: object
861
- required: [type, id, label, frequency]
862
- properties:
863
- type: { type: string, enum: [PWM] }
864
- id: { type: string }
865
- label: { type: string }
866
- frequency:
867
- type: integer
868
- description: PWM frequency in Hz
869
-
870
- DACChannel:
871
- type: object
872
- required: [type, id, label]
873
- properties:
874
- type: { type: string, enum: [DAC] }
875
- id: { type: string }
876
- label: { type: string }
877
-
878
- UARTChannel:
879
- type: object
880
- required: [type, id, label]
881
- properties:
882
- type: { type: string, enum: [UART] }
883
- id: { type: string }
884
- label: { type: string }
885
-
886
- MQTTChannel:
887
- type: object
888
- required: [type, id, label, topic]
889
- properties:
890
- type: { type: string, enum: [MQTT] }
891
- id: { type: string }
892
- label: { type: string }
893
- topic:
894
- type: string
895
- description: Topic this channel publishes to / subscribes on. The engine wraps it with the bound broker's prefix at runtime.
1
+ openapi: 3.0.3
2
+ info:
3
+ title: ForestHub Workflow Contract
4
+ version: 1.0.0
5
+ description: OpenAPI schema definition for the ForestHub workflow format.
6
+
7
+ components:
8
+ schemas:
9
+ DataType:
10
+ type: string
11
+ enum: [int, float, bool, string]
12
+
13
+ SignalType:
14
+ type: string
15
+ enum: [digital, analog]
16
+
17
+ EdgeType:
18
+ type: string
19
+ enum: [control, tool, agentTask, agentChoice, agentDelegate]
20
+
21
+ NodePosition:
22
+ type: object
23
+ required: [x, y]
24
+ properties:
25
+ x:
26
+ type: number
27
+ y:
28
+ type: number
29
+
30
+ Workflow:
31
+ type: object
32
+ description: Workflow represents the deployment format of a project, passed to agents.
33
+ required:
34
+ [
35
+ schemaVersion,
36
+ nodes,
37
+ edges,
38
+ functions,
39
+ declaredVariables,
40
+ channels,
41
+ memory,
42
+ models,
43
+ ]
44
+ properties:
45
+ schemaVersion:
46
+ type: integer
47
+ format: int32
48
+ minimum: 1
49
+ description: Monotonic version of the persisted workflow format, bumped when the serialized shape changes.
50
+ nodes:
51
+ type: array
52
+ items:
53
+ $ref: "#/components/schemas/Node"
54
+ edges:
55
+ type: array
56
+ items:
57
+ $ref: "#/components/schemas/Edge"
58
+ functions:
59
+ type: array
60
+ items:
61
+ $ref: "#/components/schemas/Function"
62
+ declaredVariables:
63
+ type: array
64
+ items:
65
+ $ref: "#/components/schemas/Variable"
66
+ channels:
67
+ type: array
68
+ items:
69
+ $ref: "#/components/schemas/Channel"
70
+ memory:
71
+ type: array
72
+ items:
73
+ $ref: "#/components/schemas/Memory"
74
+ models:
75
+ type: array
76
+ description: Declared custom/self-hosted models; referenced from nodes by id. Static catalog models need no declaration.
77
+ items:
78
+ $ref: "#/components/schemas/Model"
79
+
80
+ Edge:
81
+ type: object
82
+ required: [id, type, from, to]
83
+ properties:
84
+ id:
85
+ type: string
86
+ type:
87
+ $ref: "#/components/schemas/EdgeType"
88
+ from:
89
+ $ref: "#/components/schemas/Vertex"
90
+ to:
91
+ $ref: "#/components/schemas/Vertex"
92
+ prompt:
93
+ $ref: "#/components/schemas/Expression"
94
+ description: >
95
+ Prompt expression sent to the agent. Present on `agentTask` (required)
96
+ and `agentDelegate` (optional).
97
+ description:
98
+ type: string
99
+ description: LLM-readable explanation of when the edge should fire. Present on `agentChoice` and `agentDelegate`.
100
+
101
+ Vertex:
102
+ type: object
103
+ required:
104
+ - nodeId
105
+ - port
106
+ properties:
107
+ nodeId:
108
+ type: string
109
+ port:
110
+ type: string
111
+
112
+ Function:
113
+ type: object
114
+ required:
115
+ [functionInfo, outputAssignments, nodes, edges, declaredVariables]
116
+ properties:
117
+ functionInfo:
118
+ $ref: "#/components/schemas/FunctionInfo"
119
+ outputAssignments:
120
+ type: object
121
+ description: Maps return variable uid to its Expression
122
+ additionalProperties:
123
+ $ref: "#/components/schemas/Expression"
124
+ nodes:
125
+ type: array
126
+ items:
127
+ $ref: "#/components/schemas/Node"
128
+ edges:
129
+ type: array
130
+ items:
131
+ $ref: "#/components/schemas/Edge"
132
+ declaredVariables:
133
+ type: array
134
+ items:
135
+ $ref: "#/components/schemas/Variable"
136
+
137
+ FunctionInfo:
138
+ type: object
139
+ required: [id, version, name, arguments, returns]
140
+ properties:
141
+ id:
142
+ type: string
143
+ version:
144
+ type: integer
145
+ format: int32
146
+ minimum: 0
147
+ name:
148
+ type: string
149
+ arguments:
150
+ type: array
151
+ items:
152
+ $ref: "#/components/schemas/Variable"
153
+ returns:
154
+ type: array
155
+ items:
156
+ $ref: "#/components/schemas/Variable"
157
+
158
+ Variable:
159
+ description: A named, typed variable with a stable uid that can be referenced throughout the workflow.
160
+ required: [uid, name, dataType]
161
+ properties:
162
+ uid:
163
+ type: string
164
+ description: Stable identifier that survives renames
165
+ name:
166
+ type: string
167
+ dataType:
168
+ $ref: "#/components/schemas/DataType"
169
+ initialValue:
170
+ description: Initial value matching the dataType (number, boolean, or string). Only used by declared variables.
171
+
172
+ Expression:
173
+ type: object
174
+ required: [expression, references, dataType]
175
+ properties:
176
+ expression:
177
+ type: string
178
+ references:
179
+ description: A list of referenced variable IDs used in the expression
180
+ type: array
181
+ items:
182
+ $ref: "#/components/schemas/Reference"
183
+ dataType:
184
+ $ref: "#/components/schemas/DataType"
185
+
186
+ Reference:
187
+ type: object
188
+ required: [srcId, varId]
189
+ properties:
190
+ srcId:
191
+ type: string
192
+ varId:
193
+ type: string
194
+
195
+ OutputBinding:
196
+ type: object
197
+ required: [active, mode]
198
+ properties:
199
+ active:
200
+ type: boolean
201
+ description: Discard the output if false; route it according to `mode` if true
202
+ mode:
203
+ type: string
204
+ enum: [emit, assign]
205
+ # mode=emit
206
+ name:
207
+ type: string
208
+ description: Variable name (when mode=emit)
209
+ # mode=assign
210
+ target:
211
+ $ref: "#/components/schemas/Reference"
212
+ description: Existing variable to route to (when mode=assign)
213
+
214
+ OutputDeclaration:
215
+ type: object
216
+ required: [mode, name, dataType]
217
+ properties:
218
+ mode:
219
+ type: string
220
+ enum: [emit, assign]
221
+ name:
222
+ type: string
223
+ description: JSON property name of the declared output
224
+ dataType:
225
+ $ref: "#/components/schemas/DataType"
226
+ # mode=emit
227
+ uid:
228
+ type: string
229
+ description: New variable uid (when mode=emit)
230
+ # mode=assign
231
+ target:
232
+ $ref: "#/components/schemas/Reference"
233
+ description: Existing variable to route to (when mode=assign)
234
+
235
+ # ====== Memory ======
236
+
237
+ Memory:
238
+ oneOf:
239
+ - $ref: "#/components/schemas/MemoryFile"
240
+ - $ref: "#/components/schemas/VectorDatabase"
241
+ discriminator:
242
+ propertyName: type
243
+ mapping:
244
+ MemoryFile: "#/components/schemas/MemoryFile"
245
+ VectorDatabase: "#/components/schemas/VectorDatabase"
246
+
247
+ MemoryFile:
248
+ type: object
249
+ description: One .md file that agent nodes can read and write to.
250
+ required: [type, id, label, description, content]
251
+ properties:
252
+ type: { type: string, enum: [MemoryFile] }
253
+ id:
254
+ type: string
255
+ description: Stable identifier that survives renames; referenced from MemoryRef.
256
+ label:
257
+ type: string
258
+ description: Display name. Unique per agent (LLM tool enums use it).
259
+ description:
260
+ type: string
261
+ content:
262
+ type: string
263
+ maxSizeBytes:
264
+ type: integer
265
+ nullable: true
266
+ description: Byte cap; null means unlimited.
267
+
268
+ VectorDatabase:
269
+ type: object
270
+ description: A vector database for retrieval-augmented generation (RAG).
271
+ required: [type, id, label]
272
+ properties:
273
+ type: { type: string, enum: [VectorDatabase] }
274
+ id:
275
+ type: string
276
+ description: Stable identifier; referenced from Retriever nodes.
277
+ label:
278
+ type: string
279
+ description: Display name.
280
+ description:
281
+ type: string
282
+
283
+ MemoryRef:
284
+ type: object
285
+ description: Reference from an LLM agent node to a declared MemoryFile with an access mode.
286
+ required: [id, mode]
287
+ properties:
288
+ id:
289
+ type: string
290
+ description: id of the referenced MemoryFile.
291
+ mode:
292
+ type: string
293
+ enum: [r, rw]
294
+ description: r = read-only; rw = read + write.
295
+
296
+ # ====== Models ======
297
+
298
+ Model:
299
+ oneOf:
300
+ - $ref: "#/components/schemas/LLMModel"
301
+ discriminator:
302
+ propertyName: type
303
+ mapping:
304
+ LLMModel: "#/components/schemas/LLMModel"
305
+
306
+ LLMModel:
307
+ type: object
308
+ description: A custom or self-hosted language model that agent nodes can reference.
309
+ required: [type, id, label, capabilities]
310
+ properties:
311
+ type: { type: string, enum: [LLMModel] }
312
+ id:
313
+ type: string
314
+ description: Stable identifier; this is the ModelID nodes reference.
315
+ label:
316
+ type: string
317
+ description: Display name.
318
+ capabilities:
319
+ type: array
320
+ description: Capabilities this model supports (used to filter model pickers).
321
+ items:
322
+ $ref: "llmproxy.yaml#/components/schemas/ModelCapability"
323
+
324
+ # ====== Nodes ======
325
+
326
+ Node:
327
+ oneOf:
328
+ - $ref: "#/components/schemas/ReadPinNode"
329
+ - $ref: "#/components/schemas/WritePinNode"
330
+ - $ref: "#/components/schemas/AgentNode"
331
+ - $ref: "#/components/schemas/IfNode"
332
+ - $ref: "#/components/schemas/SerialReadNode"
333
+ - $ref: "#/components/schemas/SerialWriteNode"
334
+ - $ref: "#/components/schemas/RetrieverNode"
335
+ - $ref: "#/components/schemas/WebFetchNode"
336
+ - $ref: "#/components/schemas/FunctionCallNode"
337
+ - $ref: "#/components/schemas/OnFunctionCallNode"
338
+ - $ref: "#/components/schemas/DelayNode"
339
+ - $ref: "#/components/schemas/TickerNode"
340
+ - $ref: "#/components/schemas/AlarmNode"
341
+ - $ref: "#/components/schemas/WebSearchToolNode"
342
+ - $ref: "#/components/schemas/OnStartupNode"
343
+ - $ref: "#/components/schemas/OnPinEdgeNode"
344
+ - $ref: "#/components/schemas/OnSerialReceiveNode"
345
+ - $ref: "#/components/schemas/OnThresholdNode"
346
+ - $ref: "#/components/schemas/SetVariableNode"
347
+ - $ref: "#/components/schemas/MqttPublishNode"
348
+ - $ref: "#/components/schemas/OnMqttMessageNode"
349
+ discriminator:
350
+ propertyName: type
351
+ mapping:
352
+ ReadPin: "#/components/schemas/ReadPinNode"
353
+ WritePin: "#/components/schemas/WritePinNode"
354
+ Agent: "#/components/schemas/AgentNode"
355
+ If: "#/components/schemas/IfNode"
356
+ SerialRead: "#/components/schemas/SerialReadNode"
357
+ SerialWrite: "#/components/schemas/SerialWriteNode"
358
+ Retriever: "#/components/schemas/RetrieverNode"
359
+ WebFetch: "#/components/schemas/WebFetchNode"
360
+ FunctionCall: "#/components/schemas/FunctionCallNode"
361
+ OnFunctionCall: "#/components/schemas/OnFunctionCallNode"
362
+ Delay: "#/components/schemas/DelayNode"
363
+ Ticker: "#/components/schemas/TickerNode"
364
+ Alarm: "#/components/schemas/AlarmNode"
365
+ WebSearchTool: "#/components/schemas/WebSearchToolNode"
366
+ OnStartup: "#/components/schemas/OnStartupNode"
367
+ OnPinEdge: "#/components/schemas/OnPinEdgeNode"
368
+ OnSerialReceive: "#/components/schemas/OnSerialReceiveNode"
369
+ OnThreshold: "#/components/schemas/OnThresholdNode"
370
+ SetVariable: "#/components/schemas/SetVariableNode"
371
+ MqttPublish: "#/components/schemas/MqttPublishNode"
372
+ OnMqttMessage: "#/components/schemas/OnMqttMessageNode"
373
+
374
+ WebSearchToolNode:
375
+ type: object
376
+ required: [id, type, arguments, position]
377
+ properties:
378
+ id: { type: string }
379
+ type: { type: string, enum: [WebSearchTool] }
380
+ label: { type: string }
381
+ position: { $ref: "#/components/schemas/NodePosition" }
382
+ arguments:
383
+ type: object
384
+ properties:
385
+ maxResults:
386
+ type: integer
387
+ description: Maximum number of search results to return per call. Defaults to 5 when omitted or non-positive. Capped at 20.
388
+ minimum: 1
389
+
390
+ DelayNode:
391
+ type: object
392
+ required: [id, type, arguments, position]
393
+ properties:
394
+ id: { type: string }
395
+ type: { type: string, enum: [Delay] }
396
+ label: { type: string }
397
+ position: { $ref: "#/components/schemas/NodePosition" }
398
+ arguments:
399
+ type: object
400
+ properties:
401
+ delayMs:
402
+ type: integer
403
+ description: Time in milliseconds to pause execution
404
+
405
+ TickerNode:
406
+ type: object
407
+ required: [id, type, arguments, position]
408
+ properties:
409
+ id: { type: string }
410
+ type: { type: string, enum: [Ticker] }
411
+ label: { type: string }
412
+ position: { $ref: "#/components/schemas/NodePosition" }
413
+ arguments:
414
+ type: object
415
+ required: [intervalUnit]
416
+ properties:
417
+ intervalValue:
418
+ type: integer
419
+ description: How many units between ticks
420
+ intervalUnit:
421
+ type: string
422
+ enum: [milliseconds, seconds, minutes, hours]
423
+ description: Time unit for the interval
424
+
425
+ AlarmNode:
426
+ type: object
427
+ required: [id, type, arguments, position]
428
+ properties:
429
+ id: { type: string }
430
+ type: { type: string, enum: [Alarm] }
431
+ label: { type: string }
432
+ position: { $ref: "#/components/schemas/NodePosition" }
433
+ arguments:
434
+ type: object
435
+ required: [days]
436
+ properties:
437
+ time:
438
+ type: string
439
+ description: "Time of day to fire (HH:MM, 24h format)"
440
+ days:
441
+ type: array
442
+ items:
443
+ type: string
444
+ description: "Days of the week to fire on (empty = every day)"
445
+
446
+ FunctionCallNode:
447
+ type: object
448
+ required: [id, type, arguments, position, functionId]
449
+ properties:
450
+ id: { type: string }
451
+ type: { type: string, enum: [FunctionCall] }
452
+ label: { type: string }
453
+ position: { $ref: "#/components/schemas/NodePosition" }
454
+ functionId:
455
+ type: string
456
+ description: Id of the function this node calls. The signature is resolved from the workflow's functions table.
457
+ arguments:
458
+ type: object
459
+ properties:
460
+ inputBindings:
461
+ type: object
462
+ additionalProperties:
463
+ $ref: "#/components/schemas/Expression"
464
+ outputBindings:
465
+ type: object
466
+ additionalProperties:
467
+ $ref: "#/components/schemas/OutputBinding"
468
+ toolDescription:
469
+ type: string
470
+ description: >
471
+ Description exposed to the LLM when this function is wired as
472
+ a tool. Ignored in exec mode.
473
+
474
+ OnFunctionCallNode:
475
+ type: object
476
+ required: [id, type, position]
477
+ properties:
478
+ id: { type: string }
479
+ type: { type: string, enum: [OnFunctionCall] }
480
+ label: { type: string }
481
+ position: { $ref: "#/components/schemas/NodePosition" }
482
+
483
+ OnStartupNode:
484
+ type: object
485
+ required: [id, type, position]
486
+ properties:
487
+ id: { type: string }
488
+ type: { type: string, enum: [OnStartup] }
489
+ label: { type: string }
490
+ position: { $ref: "#/components/schemas/NodePosition" }
491
+
492
+ OnPinEdgeNode:
493
+ type: object
494
+ required: [id, type, arguments, position]
495
+ properties:
496
+ id: { type: string }
497
+ type: { type: string, enum: [OnPinEdge] }
498
+ label: { type: string }
499
+ position: { $ref: "#/components/schemas/NodePosition" }
500
+ arguments:
501
+ type: object
502
+ required: [edge]
503
+ properties:
504
+ pinReference:
505
+ type: string
506
+ description: IO variable ID of the digital pin to watch
507
+ edge:
508
+ type: string
509
+ enum: [rising, falling, both]
510
+ description: Edge transition that fires the trigger
511
+
512
+ OnSerialReceiveNode:
513
+ type: object
514
+ required: [id, type, arguments, position]
515
+ properties:
516
+ id: { type: string }
517
+ type: { type: string, enum: [OnSerialReceive] }
518
+ label: { type: string }
519
+ position: { $ref: "#/components/schemas/NodePosition" }
520
+ arguments:
521
+ type: object
522
+ required: [output]
523
+ properties:
524
+ portReference:
525
+ type: string
526
+ description: Reference to an IO variable ID (the serial port to listen on)
527
+ output:
528
+ $ref: "#/components/schemas/OutputBinding"
529
+
530
+ OnThresholdNode:
531
+ type: object
532
+ required: [id, type, arguments, position]
533
+ properties:
534
+ id: { type: string }
535
+ type: { type: string, enum: [OnThreshold] }
536
+ label: { type: string }
537
+ position: { $ref: "#/components/schemas/NodePosition" }
538
+ arguments:
539
+ type: object
540
+ required: [direction, output]
541
+ properties:
542
+ variable:
543
+ $ref: "#/components/schemas/Reference"
544
+ description: Numeric variable to watch for threshold crossings
545
+ threshold:
546
+ type: number
547
+ description: Value the variable crosses to fire the trigger
548
+ direction:
549
+ type: string
550
+ enum: [rising, falling, both]
551
+ description: Crossing direction to fire on (default both)
552
+ deadband:
553
+ type: number
554
+ description: Hysteresis band width around threshold; 0 disables (default 0)
555
+ output:
556
+ $ref: "#/components/schemas/OutputBinding"
557
+ description: Optional binding for the triggering value
558
+
559
+ RetrieverNode:
560
+ type: object
561
+ required: [id, type, arguments, position]
562
+ properties:
563
+ id: { type: string }
564
+ type: { type: string, enum: [Retriever] }
565
+ label: { type: string }
566
+ position: { $ref: "#/components/schemas/NodePosition" }
567
+ arguments:
568
+ type: object
569
+ required: [query, output]
570
+ properties:
571
+ memoryReference:
572
+ type: string
573
+ description: Reference to a declared VectorDatabase memory id
574
+ topK:
575
+ type: integer
576
+ description: Number of results to return
577
+ query:
578
+ $ref: "#/components/schemas/Expression"
579
+ description: Search query expression
580
+ output:
581
+ $ref: "#/components/schemas/OutputBinding"
582
+ toolDescription:
583
+ type: string
584
+ description: Description exposed to the LLM when this node is wired as a tool. Ignored in exec mode.
585
+
586
+ WebFetchNode:
587
+ type: object
588
+ required: [id, type, arguments, position]
589
+ properties:
590
+ id: { type: string }
591
+ type: { type: string, enum: [WebFetch] }
592
+ label: { type: string }
593
+ position: { $ref: "#/components/schemas/NodePosition" }
594
+ arguments:
595
+ type: object
596
+ required: [url, output]
597
+ properties:
598
+ url:
599
+ $ref: "#/components/schemas/Expression"
600
+ description: URL expression to fetch (http or https)
601
+ maxChars:
602
+ type: integer
603
+ description: Maximum characters of extracted text to return. Defaults to 50000 when omitted or non-positive.
604
+ minimum: 1
605
+ output:
606
+ $ref: "#/components/schemas/OutputBinding"
607
+
608
+ ReadPinNode:
609
+ type: object
610
+ required: [id, type, arguments, position]
611
+ properties:
612
+ id: { type: string }
613
+ type: { type: string, enum: [ReadPin] }
614
+ label: { type: string }
615
+ position: { $ref: "#/components/schemas/NodePosition" }
616
+ arguments:
617
+ type: object
618
+ required: [signalType, output]
619
+ properties:
620
+ pinReference:
621
+ type: string
622
+ description: Reference to an IO variable ID
623
+ signalType:
624
+ $ref: "#/components/schemas/SignalType"
625
+ output:
626
+ $ref: "#/components/schemas/OutputBinding"
627
+ toolDescription:
628
+ type: string
629
+ description: Description exposed to the LLM when this node is wired as a tool. Ignored in exec mode.
630
+
631
+ WritePinNode:
632
+ type: object
633
+ required: [id, type, arguments, position]
634
+ properties:
635
+ id: { type: string }
636
+ type: { type: string, enum: [WritePin] }
637
+ label: { type: string }
638
+ position: { $ref: "#/components/schemas/NodePosition" }
639
+ arguments:
640
+ type: object
641
+ required: [signalType, value]
642
+ properties:
643
+ pinReference:
644
+ type: string
645
+ description: Reference to an IO variable ID
646
+ signalType:
647
+ $ref: "#/components/schemas/SignalType"
648
+ value:
649
+ $ref: "#/components/schemas/Expression"
650
+
651
+ AgentNode:
652
+ type: object
653
+ required: [id, type, arguments, position]
654
+ properties:
655
+ id: { type: string }
656
+ type: { type: string, enum: [Agent] }
657
+ label: { type: string }
658
+ position: { $ref: "#/components/schemas/NodePosition" }
659
+ arguments:
660
+ type: object
661
+ required: [answer, outputDeclarations, memoryRefs]
662
+ properties:
663
+ name:
664
+ type: string
665
+ description: Name of the agent
666
+ model:
667
+ type: string
668
+ instructions:
669
+ type: string
670
+ maxTurns:
671
+ type: integer
672
+ description: Maximum number of agent runner turns
673
+ answer:
674
+ $ref: "#/components/schemas/OutputBinding"
675
+ outputDeclarations:
676
+ type: array
677
+ description: Ordered list of structured-output declarations. Names must be unique within this list
678
+ items:
679
+ $ref: "#/components/schemas/OutputDeclaration"
680
+ memoryRefs:
681
+ type: array
682
+ description: Memory files this agent can access, each with an access mode.
683
+ items:
684
+ $ref: "#/components/schemas/MemoryRef"
685
+ toolDescription:
686
+ type: string
687
+ description: Description exposed to the LLM when this node is wired as a tool. Ignored in exec mode.
688
+
689
+ IfNode:
690
+ type: object
691
+ required: [id, type, arguments, position]
692
+ properties:
693
+ id: { type: string }
694
+ type: { type: string, enum: [If] }
695
+ label: { type: string }
696
+ position: { $ref: "#/components/schemas/NodePosition" }
697
+ arguments:
698
+ type: object
699
+ required: [condition]
700
+ properties:
701
+ condition:
702
+ $ref: "#/components/schemas/Expression"
703
+
704
+ SerialReadNode:
705
+ type: object
706
+ required: [id, type, arguments, position]
707
+ properties:
708
+ id: { type: string }
709
+ type: { type: string, enum: [SerialRead] }
710
+ label: { type: string }
711
+ position: { $ref: "#/components/schemas/NodePosition" }
712
+ arguments:
713
+ type: object
714
+ required: [output]
715
+ properties:
716
+ portReference:
717
+ type: string
718
+ description: Reference to an UART ID (the serial port to read from)
719
+ prompt:
720
+ type: string
721
+ output:
722
+ $ref: "#/components/schemas/OutputBinding"
723
+
724
+ SerialWriteNode:
725
+ type: object
726
+ required: [id, type, arguments, position]
727
+ properties:
728
+ id: { type: string }
729
+ type: { type: string, enum: [SerialWrite] }
730
+ label: { type: string }
731
+ position: { $ref: "#/components/schemas/NodePosition" }
732
+ arguments:
733
+ type: object
734
+ required: [value]
735
+ properties:
736
+ portReference:
737
+ type: string
738
+ description: Reference to a UART channel ID (the serial port to write to)
739
+ value:
740
+ $ref: "#/components/schemas/Expression"
741
+
742
+ SetVariableNode:
743
+ type: object
744
+ required: [id, type, arguments, position]
745
+ properties:
746
+ id: { type: string }
747
+ type: { type: string, enum: [SetVariable] }
748
+ label: { type: string }
749
+ position: { $ref: "#/components/schemas/NodePosition" }
750
+ arguments:
751
+ type: object
752
+ required: [value]
753
+ properties:
754
+ variable:
755
+ $ref: "#/components/schemas/Reference"
756
+ value:
757
+ $ref: "#/components/schemas/Expression"
758
+
759
+ MqttPublishNode:
760
+ type: object
761
+ required: [id, type, arguments, position]
762
+ properties:
763
+ id: { type: string }
764
+ type: { type: string, enum: [MqttPublish] }
765
+ label: { type: string }
766
+ position: { $ref: "#/components/schemas/NodePosition" }
767
+ arguments:
768
+ type: object
769
+ required: [dataType, value, qos, retain]
770
+ properties:
771
+ channelReference:
772
+ type: string
773
+ description: Reference to an MQTT channel ID (the channel carries the topic; resolved to a broker at deploy time)
774
+ dataType:
775
+ $ref: "#/components/schemas/DataType"
776
+ value:
777
+ $ref: "#/components/schemas/Expression"
778
+ qos:
779
+ type: integer
780
+ enum: [0, 1, 2]
781
+ description: MQTT Quality of Service level
782
+ retain:
783
+ type: boolean
784
+ description: Whether the broker should retain the message
785
+
786
+ OnMqttMessageNode:
787
+ type: object
788
+ required: [id, type, arguments, position]
789
+ properties:
790
+ id: { type: string }
791
+ type: { type: string, enum: [OnMqttMessage] }
792
+ label: { type: string }
793
+ position: { $ref: "#/components/schemas/NodePosition" }
794
+ arguments:
795
+ type: object
796
+ required: [dataType, output]
797
+ properties:
798
+ channelReference:
799
+ type: string
800
+ description: Reference to an MQTT channel ID (the channel carries the topic filter; resolved to a broker at deploy time)
801
+ dataType:
802
+ $ref: "#/components/schemas/DataType"
803
+ output:
804
+ $ref: "#/components/schemas/OutputBinding"
805
+
806
+ # ====== Channels ======
807
+
808
+ Channel:
809
+ oneOf:
810
+ - $ref: "#/components/schemas/GPIOINChannel"
811
+ - $ref: "#/components/schemas/GPIOOUTChannel"
812
+ - $ref: "#/components/schemas/ADCChannel"
813
+ - $ref: "#/components/schemas/PWMChannel"
814
+ - $ref: "#/components/schemas/DACChannel"
815
+ - $ref: "#/components/schemas/UARTChannel"
816
+ - $ref: "#/components/schemas/MQTTChannel"
817
+ - $ref: "#/components/schemas/LOGChannel"
818
+ discriminator:
819
+ propertyName: type
820
+ mapping:
821
+ GPIOIN: "#/components/schemas/GPIOINChannel"
822
+ GPIOOUT: "#/components/schemas/GPIOOUTChannel"
823
+ ADC: "#/components/schemas/ADCChannel"
824
+ PWM: "#/components/schemas/PWMChannel"
825
+ DAC: "#/components/schemas/DACChannel"
826
+ UART: "#/components/schemas/UARTChannel"
827
+ MQTT: "#/components/schemas/MQTTChannel"
828
+ LOG: "#/components/schemas/LOGChannel"
829
+
830
+ GPIOINChannel:
831
+ type: object
832
+ required: [type, id, label, bias, debounceMs]
833
+ properties:
834
+ type: { type: string, enum: [GPIOIN] }
835
+ id: { type: string }
836
+ label: { type: string }
837
+ bias:
838
+ type: string
839
+ enum: [none, pullup, pulldown]
840
+ description: Pin bias configuration
841
+ debounceMs:
842
+ type: integer
843
+ description: Debounce window in milliseconds
844
+
845
+ GPIOOUTChannel:
846
+ type: object
847
+ required: [type, id, label]
848
+ properties:
849
+ type: { type: string, enum: [GPIOOUT] }
850
+ id: { type: string }
851
+ label: { type: string }
852
+
853
+ ADCChannel:
854
+ type: object
855
+ required: [type, id, label]
856
+ properties:
857
+ type: { type: string, enum: [ADC] }
858
+ id: { type: string }
859
+ label: { type: string }
860
+
861
+ PWMChannel:
862
+ type: object
863
+ required: [type, id, label, frequency]
864
+ properties:
865
+ type: { type: string, enum: [PWM] }
866
+ id: { type: string }
867
+ label: { type: string }
868
+ frequency:
869
+ type: integer
870
+ description: PWM frequency in Hz
871
+
872
+ DACChannel:
873
+ type: object
874
+ required: [type, id, label]
875
+ properties:
876
+ type: { type: string, enum: [DAC] }
877
+ id: { type: string }
878
+ label: { type: string }
879
+
880
+ UARTChannel:
881
+ type: object
882
+ required: [type, id, label]
883
+ properties:
884
+ type: { type: string, enum: [UART] }
885
+ id: { type: string }
886
+ label: { type: string }
887
+
888
+ MQTTChannel:
889
+ type: object
890
+ required: [type, id, label, topic]
891
+ properties:
892
+ type: { type: string, enum: [MQTT] }
893
+ id: { type: string }
894
+ label: { type: string }
895
+ topic:
896
+ type: string
897
+ description: Topic this channel publishes to / subscribes on. The engine wraps it with the bound broker's prefix at runtime.
898
+
899
+ LOGChannel:
900
+ type: object
901
+ required: [type, id, label, level]
902
+ properties:
903
+ type: { type: string, enum: [LOG] }
904
+ id: { type: string }
905
+ label: { type: string }
906
+ level:
907
+ type: string
908
+ enum: [debug, info, warn, error]
909
+ description: Severity the engine records messages written to this channel at.
910
+ tag:
911
+ type: string
912
+ description: Optional category stamped on each line so the backend can group workflow-emitted logs apart from engine diagnostics.