@foresthubai/workflow-cli 0.4.3 → 0.4.5

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