@foresthubai/workflow-cli 0.3.0 → 0.4.1

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,909 +1,895 @@
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
- ModelCapability:
299
- type: string
300
- enum:
301
- [
302
- chat,
303
- embedding,
304
- function_call,
305
- vision,
306
- fine_tuning,
307
- reasoning,
308
- classification,
309
- code,
310
- ]
311
-
312
- Model:
313
- oneOf:
314
- - $ref: "#/components/schemas/LLMModel"
315
- discriminator:
316
- propertyName: type
317
- mapping:
318
- LLMModel: "#/components/schemas/LLMModel"
319
-
320
- LLMModel:
321
- type: object
322
- description: A custom or self-hosted language model that agent nodes can reference.
323
- required: [type, id, label, capabilities]
324
- properties:
325
- type: { type: string, enum: [LLMModel] }
326
- id:
327
- type: string
328
- description: Stable identifier; this is the ModelID nodes reference.
329
- label:
330
- type: string
331
- description: Display name.
332
- capabilities:
333
- type: array
334
- description: Capabilities this model supports (used to filter model pickers).
335
- items:
336
- $ref: "#/components/schemas/ModelCapability"
337
-
338
- # ====== Nodes ======
339
-
340
- Node:
341
- oneOf:
342
- - $ref: "#/components/schemas/ReadPinNode"
343
- - $ref: "#/components/schemas/WritePinNode"
344
- - $ref: "#/components/schemas/AgentNode"
345
- - $ref: "#/components/schemas/IfNode"
346
- - $ref: "#/components/schemas/SerialReadNode"
347
- - $ref: "#/components/schemas/SerialWriteNode"
348
- - $ref: "#/components/schemas/RetrieverNode"
349
- - $ref: "#/components/schemas/WebFetchNode"
350
- - $ref: "#/components/schemas/FunctionCallNode"
351
- - $ref: "#/components/schemas/OnFunctionCallNode"
352
- - $ref: "#/components/schemas/DelayNode"
353
- - $ref: "#/components/schemas/TickerNode"
354
- - $ref: "#/components/schemas/AlarmNode"
355
- - $ref: "#/components/schemas/WebSearchToolNode"
356
- - $ref: "#/components/schemas/OnStartupNode"
357
- - $ref: "#/components/schemas/OnPinEdgeNode"
358
- - $ref: "#/components/schemas/OnSerialReceiveNode"
359
- - $ref: "#/components/schemas/OnThresholdNode"
360
- - $ref: "#/components/schemas/SetVariableNode"
361
- - $ref: "#/components/schemas/MqttPublishNode"
362
- - $ref: "#/components/schemas/OnMqttMessageNode"
363
- discriminator:
364
- propertyName: type
365
- mapping:
366
- ReadPin: "#/components/schemas/ReadPinNode"
367
- WritePin: "#/components/schemas/WritePinNode"
368
- Agent: "#/components/schemas/AgentNode"
369
- If: "#/components/schemas/IfNode"
370
- SerialRead: "#/components/schemas/SerialReadNode"
371
- SerialWrite: "#/components/schemas/SerialWriteNode"
372
- Retriever: "#/components/schemas/RetrieverNode"
373
- WebFetch: "#/components/schemas/WebFetchNode"
374
- FunctionCall: "#/components/schemas/FunctionCallNode"
375
- OnFunctionCall: "#/components/schemas/OnFunctionCallNode"
376
- Delay: "#/components/schemas/DelayNode"
377
- Ticker: "#/components/schemas/TickerNode"
378
- Alarm: "#/components/schemas/AlarmNode"
379
- WebSearchTool: "#/components/schemas/WebSearchToolNode"
380
- OnStartup: "#/components/schemas/OnStartupNode"
381
- OnPinEdge: "#/components/schemas/OnPinEdgeNode"
382
- OnSerialReceive: "#/components/schemas/OnSerialReceiveNode"
383
- OnThreshold: "#/components/schemas/OnThresholdNode"
384
- SetVariable: "#/components/schemas/SetVariableNode"
385
- MqttPublish: "#/components/schemas/MqttPublishNode"
386
- OnMqttMessage: "#/components/schemas/OnMqttMessageNode"
387
-
388
- WebSearchToolNode:
389
- type: object
390
- required: [id, type, arguments, position]
391
- properties:
392
- id: { type: string }
393
- type: { type: string, enum: [WebSearchTool] }
394
- label: { type: string }
395
- position: { $ref: "#/components/schemas/NodePosition" }
396
- arguments:
397
- type: object
398
- properties:
399
- maxResults:
400
- type: integer
401
- description: Maximum number of search results to return per call. Defaults to 5 when omitted or non-positive. Capped at 20.
402
- minimum: 1
403
-
404
- DelayNode:
405
- type: object
406
- required: [id, type, arguments, position]
407
- properties:
408
- id: { type: string }
409
- type: { type: string, enum: [Delay] }
410
- label: { type: string }
411
- position: { $ref: "#/components/schemas/NodePosition" }
412
- arguments:
413
- type: object
414
- properties:
415
- delayMs:
416
- type: integer
417
- description: Time in milliseconds to pause execution
418
-
419
- TickerNode:
420
- type: object
421
- required: [id, type, arguments, position]
422
- properties:
423
- id: { type: string }
424
- type: { type: string, enum: [Ticker] }
425
- label: { type: string }
426
- position: { $ref: "#/components/schemas/NodePosition" }
427
- arguments:
428
- type: object
429
- required: [intervalUnit]
430
- properties:
431
- intervalValue:
432
- type: integer
433
- description: How many units between ticks
434
- intervalUnit:
435
- type: string
436
- enum: [milliseconds, seconds, minutes, hours]
437
- description: Time unit for the interval
438
-
439
- AlarmNode:
440
- type: object
441
- required: [id, type, arguments, position]
442
- properties:
443
- id: { type: string }
444
- type: { type: string, enum: [Alarm] }
445
- label: { type: string }
446
- position: { $ref: "#/components/schemas/NodePosition" }
447
- arguments:
448
- type: object
449
- required: [days]
450
- properties:
451
- time:
452
- type: string
453
- description: "Time of day to fire (HH:MM, 24h format)"
454
- days:
455
- type: array
456
- items:
457
- type: string
458
- description: "Days of the week to fire on (empty = every day)"
459
-
460
- FunctionCallNode:
461
- type: object
462
- required: [id, type, arguments, position, functionId]
463
- properties:
464
- id: { type: string }
465
- type: { type: string, enum: [FunctionCall] }
466
- label: { type: string }
467
- position: { $ref: "#/components/schemas/NodePosition" }
468
- functionId:
469
- type: string
470
- description: Id of the function this node calls. The signature is resolved from the workflow's functions table.
471
- arguments:
472
- type: object
473
- properties:
474
- inputBindings:
475
- type: object
476
- additionalProperties:
477
- $ref: "#/components/schemas/Expression"
478
- outputBindings:
479
- type: object
480
- additionalProperties:
481
- $ref: "#/components/schemas/OutputBinding"
482
- toolDescription:
483
- type: string
484
- description: >
485
- Description exposed to the LLM when this function is wired as
486
- a tool. Ignored in exec mode.
487
-
488
- OnFunctionCallNode:
489
- type: object
490
- required: [id, type, position]
491
- properties:
492
- id: { type: string }
493
- type: { type: string, enum: [OnFunctionCall] }
494
- label: { type: string }
495
- position: { $ref: "#/components/schemas/NodePosition" }
496
-
497
- OnStartupNode:
498
- type: object
499
- required: [id, type, position]
500
- properties:
501
- id: { type: string }
502
- type: { type: string, enum: [OnStartup] }
503
- label: { type: string }
504
- position: { $ref: "#/components/schemas/NodePosition" }
505
-
506
- OnPinEdgeNode:
507
- type: object
508
- required: [id, type, arguments, position]
509
- properties:
510
- id: { type: string }
511
- type: { type: string, enum: [OnPinEdge] }
512
- label: { type: string }
513
- position: { $ref: "#/components/schemas/NodePosition" }
514
- arguments:
515
- type: object
516
- required: [edge]
517
- properties:
518
- pinReference:
519
- type: string
520
- description: IO variable ID of the digital pin to watch
521
- edge:
522
- type: string
523
- enum: [rising, falling, both]
524
- description: Edge transition that fires the trigger
525
-
526
- OnSerialReceiveNode:
527
- type: object
528
- required: [id, type, arguments, position]
529
- properties:
530
- id: { type: string }
531
- type: { type: string, enum: [OnSerialReceive] }
532
- label: { type: string }
533
- position: { $ref: "#/components/schemas/NodePosition" }
534
- arguments:
535
- type: object
536
- required: [output]
537
- properties:
538
- portReference:
539
- type: string
540
- description: Reference to an IO variable ID (the serial port to listen on)
541
- output:
542
- $ref: "#/components/schemas/OutputBinding"
543
-
544
- OnThresholdNode:
545
- type: object
546
- required: [id, type, arguments, position]
547
- properties:
548
- id: { type: string }
549
- type: { type: string, enum: [OnThreshold] }
550
- label: { type: string }
551
- position: { $ref: "#/components/schemas/NodePosition" }
552
- arguments:
553
- type: object
554
- required: [direction, output]
555
- properties:
556
- variable:
557
- $ref: "#/components/schemas/Reference"
558
- description: Numeric variable to watch for threshold crossings
559
- threshold:
560
- type: number
561
- description: Value the variable crosses to fire the trigger
562
- direction:
563
- type: string
564
- enum: [rising, falling, both]
565
- description: Crossing direction to fire on (default both)
566
- deadband:
567
- type: number
568
- description: Hysteresis band width around threshold; 0 disables (default 0)
569
- output:
570
- $ref: "#/components/schemas/OutputBinding"
571
- description: Optional binding for the triggering value
572
-
573
- RetrieverNode:
574
- type: object
575
- required: [id, type, arguments, position]
576
- properties:
577
- id: { type: string }
578
- type: { type: string, enum: [Retriever] }
579
- label: { type: string }
580
- position: { $ref: "#/components/schemas/NodePosition" }
581
- arguments:
582
- type: object
583
- required: [query, output]
584
- properties:
585
- memoryReference:
586
- type: string
587
- description: Reference to a declared VectorDatabase memory id
588
- topK:
589
- type: integer
590
- description: Number of results to return
591
- query:
592
- $ref: "#/components/schemas/Expression"
593
- description: Search query expression
594
- output:
595
- $ref: "#/components/schemas/OutputBinding"
596
- toolDescription:
597
- type: string
598
- description: Description exposed to the LLM when this node is wired as a tool. Ignored in exec mode.
599
-
600
- WebFetchNode:
601
- type: object
602
- required: [id, type, arguments, position]
603
- properties:
604
- id: { type: string }
605
- type: { type: string, enum: [WebFetch] }
606
- label: { type: string }
607
- position: { $ref: "#/components/schemas/NodePosition" }
608
- arguments:
609
- type: object
610
- required: [url, output]
611
- properties:
612
- url:
613
- $ref: "#/components/schemas/Expression"
614
- description: URL expression to fetch (http or https)
615
- maxChars:
616
- type: integer
617
- description: Maximum characters of extracted text to return. Defaults to 50000 when omitted or non-positive.
618
- minimum: 1
619
- output:
620
- $ref: "#/components/schemas/OutputBinding"
621
-
622
- ReadPinNode:
623
- type: object
624
- required: [id, type, arguments, position]
625
- properties:
626
- id: { type: string }
627
- type: { type: string, enum: [ReadPin] }
628
- label: { type: string }
629
- position: { $ref: "#/components/schemas/NodePosition" }
630
- arguments:
631
- type: object
632
- required: [signalType, output]
633
- properties:
634
- pinReference:
635
- type: string
636
- description: Reference to an IO variable ID
637
- signalType:
638
- $ref: "#/components/schemas/SignalType"
639
- output:
640
- $ref: "#/components/schemas/OutputBinding"
641
- toolDescription:
642
- type: string
643
- description: Description exposed to the LLM when this node is wired as a tool. Ignored in exec mode.
644
-
645
- WritePinNode:
646
- type: object
647
- required: [id, type, arguments, position]
648
- properties:
649
- id: { type: string }
650
- type: { type: string, enum: [WritePin] }
651
- label: { type: string }
652
- position: { $ref: "#/components/schemas/NodePosition" }
653
- arguments:
654
- type: object
655
- required: [signalType, value]
656
- properties:
657
- pinReference:
658
- type: string
659
- description: Reference to an IO variable ID
660
- signalType:
661
- $ref: "#/components/schemas/SignalType"
662
- value:
663
- $ref: "#/components/schemas/Expression"
664
-
665
- AgentNode:
666
- type: object
667
- required: [id, type, arguments, position]
668
- properties:
669
- id: { type: string }
670
- type: { type: string, enum: [Agent] }
671
- label: { type: string }
672
- position: { $ref: "#/components/schemas/NodePosition" }
673
- arguments:
674
- type: object
675
- required: [answer, outputDeclarations, memoryRefs]
676
- properties:
677
- name:
678
- type: string
679
- description: Name of the agent
680
- model:
681
- type: string
682
- instructions:
683
- type: string
684
- maxTurns:
685
- type: integer
686
- description: Maximum number of agent runner turns
687
- answer:
688
- $ref: "#/components/schemas/OutputBinding"
689
- outputDeclarations:
690
- type: array
691
- description: Ordered list of structured-output declarations. Names must be unique within this list
692
- items:
693
- $ref: "#/components/schemas/OutputDeclaration"
694
- memoryRefs:
695
- type: array
696
- description: Memory files this agent can access, each with an access mode.
697
- items:
698
- $ref: "#/components/schemas/MemoryRef"
699
- toolDescription:
700
- type: string
701
- description: Description exposed to the LLM when this node is wired as a tool. Ignored in exec mode.
702
-
703
- IfNode:
704
- type: object
705
- required: [id, type, arguments, position]
706
- properties:
707
- id: { type: string }
708
- type: { type: string, enum: [If] }
709
- label: { type: string }
710
- position: { $ref: "#/components/schemas/NodePosition" }
711
- arguments:
712
- type: object
713
- required: [condition]
714
- properties:
715
- condition:
716
- $ref: "#/components/schemas/Expression"
717
-
718
- SerialReadNode:
719
- type: object
720
- required: [id, type, arguments, position]
721
- properties:
722
- id: { type: string }
723
- type: { type: string, enum: [SerialRead] }
724
- label: { type: string }
725
- position: { $ref: "#/components/schemas/NodePosition" }
726
- arguments:
727
- type: object
728
- required: [output]
729
- properties:
730
- portReference:
731
- type: string
732
- description: Reference to an UART ID (the serial port to read from)
733
- prompt:
734
- type: string
735
- output:
736
- $ref: "#/components/schemas/OutputBinding"
737
-
738
- SerialWriteNode:
739
- type: object
740
- required: [id, type, arguments, position]
741
- properties:
742
- id: { type: string }
743
- type: { type: string, enum: [SerialWrite] }
744
- label: { type: string }
745
- position: { $ref: "#/components/schemas/NodePosition" }
746
- arguments:
747
- type: object
748
- required: [value]
749
- properties:
750
- portReference:
751
- type: string
752
- description: Reference to a UART channel ID (the serial port to write to)
753
- value:
754
- $ref: "#/components/schemas/Expression"
755
-
756
- SetVariableNode:
757
- type: object
758
- required: [id, type, arguments, position]
759
- properties:
760
- id: { type: string }
761
- type: { type: string, enum: [SetVariable] }
762
- label: { type: string }
763
- position: { $ref: "#/components/schemas/NodePosition" }
764
- arguments:
765
- type: object
766
- required: [value]
767
- properties:
768
- variable:
769
- $ref: "#/components/schemas/Reference"
770
- value:
771
- $ref: "#/components/schemas/Expression"
772
-
773
- MqttPublishNode:
774
- type: object
775
- required: [id, type, arguments, position]
776
- properties:
777
- id: { type: string }
778
- type: { type: string, enum: [MqttPublish] }
779
- label: { type: string }
780
- position: { $ref: "#/components/schemas/NodePosition" }
781
- arguments:
782
- type: object
783
- required: [dataType, value, qos, retain]
784
- properties:
785
- channelReference:
786
- type: string
787
- description: Reference to an MQTT channel ID (the channel carries the topic; resolved to a broker at deploy time)
788
- dataType:
789
- $ref: "#/components/schemas/DataType"
790
- value:
791
- $ref: "#/components/schemas/Expression"
792
- qos:
793
- type: integer
794
- enum: [0, 1, 2]
795
- description: MQTT Quality of Service level
796
- retain:
797
- type: boolean
798
- description: Whether the broker should retain the message
799
-
800
- OnMqttMessageNode:
801
- type: object
802
- required: [id, type, arguments, position]
803
- properties:
804
- id: { type: string }
805
- type: { type: string, enum: [OnMqttMessage] }
806
- label: { type: string }
807
- position: { $ref: "#/components/schemas/NodePosition" }
808
- arguments:
809
- type: object
810
- required: [dataType, output]
811
- properties:
812
- channelReference:
813
- type: string
814
- description: Reference to an MQTT channel ID (the channel carries the topic filter; resolved to a broker at deploy time)
815
- dataType:
816
- $ref: "#/components/schemas/DataType"
817
- output:
818
- $ref: "#/components/schemas/OutputBinding"
819
-
820
- # ====== Channels ======
821
-
822
- Channel:
823
- oneOf:
824
- - $ref: "#/components/schemas/GPIOINChannel"
825
- - $ref: "#/components/schemas/GPIOOUTChannel"
826
- - $ref: "#/components/schemas/ADCChannel"
827
- - $ref: "#/components/schemas/PWMChannel"
828
- - $ref: "#/components/schemas/DACChannel"
829
- - $ref: "#/components/schemas/UARTChannel"
830
- - $ref: "#/components/schemas/MQTTChannel"
831
- discriminator:
832
- propertyName: type
833
- mapping:
834
- GPIOIN: "#/components/schemas/GPIOINChannel"
835
- GPIOOUT: "#/components/schemas/GPIOOUTChannel"
836
- ADC: "#/components/schemas/ADCChannel"
837
- PWM: "#/components/schemas/PWMChannel"
838
- DAC: "#/components/schemas/DACChannel"
839
- UART: "#/components/schemas/UARTChannel"
840
- MQTT: "#/components/schemas/MQTTChannel"
841
-
842
- GPIOINChannel:
843
- type: object
844
- required: [type, id, label, bias, debounceMs]
845
- properties:
846
- type: { type: string, enum: [GPIOIN] }
847
- id: { type: string }
848
- label: { type: string }
849
- bias:
850
- type: string
851
- enum: [none, pullup, pulldown]
852
- description: Pin bias configuration
853
- debounceMs:
854
- type: integer
855
- description: Debounce window in milliseconds
856
-
857
- GPIOOUTChannel:
858
- type: object
859
- required: [type, id, label]
860
- properties:
861
- type: { type: string, enum: [GPIOOUT] }
862
- id: { type: string }
863
- label: { type: string }
864
-
865
- ADCChannel:
866
- type: object
867
- required: [type, id, label]
868
- properties:
869
- type: { type: string, enum: [ADC] }
870
- id: { type: string }
871
- label: { type: string }
872
-
873
- PWMChannel:
874
- type: object
875
- required: [type, id, label, frequency]
876
- properties:
877
- type: { type: string, enum: [PWM] }
878
- id: { type: string }
879
- label: { type: string }
880
- frequency:
881
- type: integer
882
- description: PWM frequency in Hz
883
-
884
- DACChannel:
885
- type: object
886
- required: [type, id, label]
887
- properties:
888
- type: { type: string, enum: [DAC] }
889
- id: { type: string }
890
- label: { type: string }
891
-
892
- UARTChannel:
893
- type: object
894
- required: [type, id, label]
895
- properties:
896
- type: { type: string, enum: [UART] }
897
- id: { type: string }
898
- label: { type: string }
899
-
900
- MQTTChannel:
901
- type: object
902
- required: [type, id, label, topic]
903
- properties:
904
- type: { type: string, enum: [MQTT] }
905
- id: { type: string }
906
- label: { type: string }
907
- topic:
908
- type: string
909
- 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
+ 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.