Guides
Building and Publishing FlowDSL Nodes
How to develop, test, version, and publish FlowDSL nodes to the node registry.
A FlowDSL node is a small service with two parts: a handler (the business logic) and a manifest (the identity document). This guide covers the full development lifecycle from local implementation to registry publication.
Node anatomy
text
my-node/
├── main.go (or main.py) # Node server entry point
├── node.go (or node.py) # NodeHandler implementation
├── flowdsl-node.json # Manifest
└── go.mod / requirements.txt
The flowdsl-node.json manifest
The manifest is the node's identity document — it describes the node to the runtime and registry:
json
{
"operationId": "send_sms_alert",
"name": "SMS Alert",
"version": "2.1.0",
"description": "Sends an SMS alert via Twilio to a configured phone number",
"runtime": "go",
"inputs": [
{
"name": "in",
"packet": "AlertPayload",
"description": "The alert to send"
}
],
"outputs": [
{
"name": "out",
"packet": "SmsResult",
"description": "SMS delivery result"
}
],
"settings": {
"type": "object",
"properties": {
"fromNumber": { "type": "string", "description": "Twilio sender number" },
"toNumber": { "type": "string", "description": "Recipient number" }
},
"required": ["fromNumber", "toNumber"]
},
"repository": "https://github.com/myorg/flowdsl-nodes",
"author": "My Team",
"license": "MIT",
"tags": ["sms", "notifications", "twilio"]
}
Local development workflow
1. Write the handler
See Write a Go Node or Write a Python Node for complete implementation tutorials.
2. Register locally
yaml
# node-registry.yaml
nodes:
send_sms_alert:
address: localhost:8083
version: "2.1.0"
runtime: go
3. Test in isolation
go
func TestSmsAlertNode(t *testing.T) {
node := &SmsAlertNode{}
err := node.Init(flowdsl.Settings{"fromNumber": "+15550100200", "toNumber": "+15550100300"})
require.NoError(t, err)
input := flowdsl.MockNodeInput("in", map[string]any{
"message": "Production alert",
"severity": "high",
})
output, err := node.Handle(context.Background(), input)
require.NoError(t, err)
assert.Equal(t, "delivered", output.Packet("out").GetStringOr("status", ""))
}
4. Test with a live flow
shell
# Start your node
./sms-alert-node
# Start the runtime with your test flow
FLOWDSL_REGISTRY_FILE=./node-registry.yaml \
flowdsl-runtime start test-flow.flowdsl.yaml
# Trigger the flow
curl -X POST http://localhost:8081/flows/test_flow/trigger \
-d '{"message": "test", "severity": "high"}'
Node versioning
Node versions follow semver (major.minor.patch):
- Patch (1.0.x) — bug fixes, no contract changes
- Minor (1.x.0) — new optional inputs/outputs, backwards compatible
- Major (x.0.0) — breaking changes: renamed ports, removed outputs, changed packet types
When you bump the major version, update all FlowDSL flows that reference this operationId before deploying.
Node documentation best practices
Write a clear description in the manifest and a README.md:
markdown
# send_sms_alert
Sends an SMS alert via Twilio.
## Inputs
| Port | Packet | Description |
|------|--------|-------------|
| `in` | `AlertPayload` | The alert to send |
## Outputs
| Port | Packet | Description |
|------|--------|-------------|
| `out` | `SmsResult` | Delivery result with Twilio SID |
## Settings
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `fromNumber` | string | Yes | Twilio sender number in E.164 format |
| `toNumber` | string | Yes | Recipient number in E.164 format |
## Example
\`\`\`yaml
nodes:
AlertEngineer:
operationId: send_sms_alert
kind: action
settings:
fromNumber: "+15550100200"
toNumber: "+15550100300"
\`\`\`
Publishing to repo.flowdsl.com (coming soon)
The public node registry at repo.flowdsl.com is coming in a future release. When available:
shell
# Authenticate
flowdsl auth login
# Publish
flowdsl publish --manifest flowdsl-node.json --tag latest
# Published nodes are resolvable by operationId
registry: https://repo.flowdsl.com
Summary
| Step | Tool |
|---|---|
| Implement handler | flowdsl-go or flowdsl-py SDK |
| Write manifest | flowdsl-node.json |
| Register locally | node-registry.yaml |
| Test | Go test / pytest + MockNodeInput |
| Version | Semver: breaking changes → major bump |
| Publish | flowdsl publish (coming soon) |
Next steps
- Write a Go Node — implementation tutorial
- Write a Python Node — implementation tutorial
- Node Manifest reference — full manifest field reference

