The official Go SDK for FlowDSL — the open specification for executable event-driven flows.
Build FlowDSL node handlers, parse and validate FlowDSL documents, and implement custom runtimes. Zero external dependencies.
go get github.com/flowdsl/flowdsl-goRequires Go 1.23+.
| Package | Import | What it does |
|---|---|---|
| pkg/node | github.com/flowdsl/flowdsl-go/pkg/node |
Node handler interfaces, Packet, Settings, errors, manifest loader |
| pkg/spec | github.com/flowdsl/flowdsl-go/pkg/spec |
FlowDSL document types, JSON parser, structural validator |
| pkg/runtime | github.com/flowdsl/flowdsl-go/pkg/runtime |
Abstract runtime interfaces (Engine, Checkpoint, DeliveryAdapter) |
| cmd/flowdsl-validate | CLI | Validate .flowdsl.json files from the command line |
Every FlowDSL node implements the NodeHandler interface:
package main
import (
"context"
"github.com/flowdsl/flowdsl-go/pkg/node"
)
type UppercaseNode struct{}
func (n *UppercaseNode) OperationID() string { return "uppercase" }
func (n *UppercaseNode) Init(settings node.Settings) error { return nil }
func (n *UppercaseNode) Handle(ctx context.Context, input node.NodeInput) (node.NodeOutput, error) {
pkt, err := input.Packet("in")
if err != nil {
return node.NodeOutput{}, err
}
text := pkt.GetStringOr("text", "")
return node.NodeOutput{}.SendMap("out", map[string]any{
"text": strings.ToUpper(text),
}), nil
}Router nodes send packets to different output ports based on logic:
func (n *FilterNode) Handle(ctx context.Context, input node.NodeInput) (node.NodeOutput, error) {
pkt, _ := input.Packet("in")
priority := pkt.GetStringOr("priority", "low")
if priority == "P0" || priority == "P1" {
return node.NodeOutput{}.Send("urgent", pkt), nil
}
return node.NodeOutput{}.Send("normal", pkt), nil
}Return typed errors so the runtime knows whether to retry:
return node.NodeOutput{}, node.NewNodeError(
node.ErrCodeRateLimited, // retriable
"API rate limit hit",
originalErr,
)| Code | Retriable | Use case |
|---|---|---|
ErrCodeValidation |
No | Bad input data |
ErrCodeInputMissing |
No | Required port missing |
ErrCodePermanent |
No | Unrecoverable failure |
ErrCodeTimeout |
Yes | Deadline exceeded |
ErrCodeRateLimited |
Yes | Upstream throttling |
ErrCodeTemporary |
Yes | Transient failure |
import "github.com/flowdsl/flowdsl-go/pkg/spec"
// Load a .flowdsl.json file
doc, err := spec.Load("my-flow.flowdsl.json")
// Validate structure and references
result := spec.Validate(doc)
if result.HasErrors() {
for _, d := range result.Errors() {
fmt.Println(d) // [error] flows.main.nodes.x.operationId: operationId is required (FDL020)
}
}The validator checks document structure, node operationId format, edge reference integrity, delivery mode validity, server protocols, and component $ref resolution. Diagnostic codes range from FDL001 to FDL050.
Load, parse, and write .flowdsl-node.json manifest files:
import "github.com/flowdsl/flowdsl-go/pkg/node"
// Load from file
manifest, err := node.LoadManifest("my-node.flowdsl-node.json")
// Load all manifests from a directory
manifests, err := node.LoadManifestsFromDir("./nodes/")
// Write a manifest
err = node.WriteManifest(manifest, "output.flowdsl-node.json")The SDK includes mock utilities — no runtime needed:
func TestUppercase(t *testing.T) {
n := &UppercaseNode{}
_ = n.Init(nil)
input := node.NewMockInput("in", map[string]any{"text": "hello"})
out, err := n.Handle(context.Background(), input)
if err != nil {
t.Fatal(err)
}
result := out.Packet("out")
if v, _ := result.GetString("text"); v != "HELLO" {
t.Errorf("got %q", v)
}
}For multi-port inputs and custom execution context:
input := node.NewMockInputMulti(map[string]map[string]any{
"data": {"value": float64(42)},
"config": {"mode": "fast"},
}).WithContext(node.ExecutionContext{
FlowID: "my-flow",
ExecutionID: "exec-001",
NodeID: "my-node",
})Validate FlowDSL documents from the command line:
go install github.com/flowdsl/flowdsl-go/cmd/flowdsl-validate@latest
flowdsl-validate my-flow.flowdsl.json
# exit 0 = valid, 1 = errors found, 2 = file read failureThe pkg/runtime package defines abstract interfaces for building FlowDSL execution engines. These have no concrete implementation in this SDK — they establish the contract that runtimes must satisfy.
type Engine interface {
Start(ctx context.Context, flow *spec.Flow, input map[string]any) (*ExecutionRecord, error)
Resume(ctx context.Context, executionID string) (*ExecutionRecord, error)
Status(ctx context.Context, executionID string) (*ExecutionRecord, error)
}
type Checkpoint interface { /* Save, Load, SaveStep */ }
type DeliveryAdapter interface { /* Deliver, Mode */ }
type NodeRegistry interface { /* Lookup, Register */ }Concrete implementations:
- redelay/go-flowdsl — Full runtime using MongoDB, Redis, Kafka via the redelay framework
- cloud-runtime (coming soon) — Managed FlowDSL hosting
This SDK is a specification and abstraction layer with zero external dependencies. It intentionally does not include concrete transport or storage implementations (MongoDB, Redis, Kafka, ClickHouse). Those belong in integration repos that import this SDK.
flowdsl-go (this repo) Integration repos
┌─────────────────────┐ ┌──────────────────────┐
│ pkg/node │◄────────│ redelay/go-flowdsl │
│ pkg/spec │ │ (Mongo, Redis, │
│ pkg/runtime │ │ Kafka, ClickHouse) │
│ cmd/flowdsl-validate│ ├──────────────────────┤
└─────────────────────┘ │ cloud-runtime │
│ (managed platform) │
└──────────────────────┘
| Project | Description |
|---|---|
| flowdsl/spec | JSON Schema specification |
| flowdsl/studio | Visual flow editor (React + React Flow) |
| flowdsl/flowdsl-go | Go SDK (this repo) |
| flowdsl/flowdsl-py | Python SDK |
| flowdsl/flowdsl-js | JavaScript/TypeScript SDK |
| flowdsl/examples | Example flows |
| flowdsl/website | flowdsl.com |
- Go SDK Reference — full API reference
- Writing a Go Node — step-by-step tutorial
- FlowDSL Specification — the canonical spec
Apache License 2.0 — see LICENSE.