Writing your first Go plugin
In order to create a Go plugin, you will need to create a Go module project (go mod init
) and install the Arcaflow SDK using go get go.flow.arcalot.io/pluginsdk
.
Writing a Go plugin consists of the following 4 parts:
- The input data model
- The output data model
- The callable function
- The calling scaffold
The input data model
First, we define an input data model. This must be a struct.
type Input struct {
Name string `json:"name"`
}
Note
The Arcaflow serialization does not use the built-in Go JSON marshaling, so any additional tags like omitempty
, or yaml
tags are ignored.
In addition to the struct above, we must also define a schema for the input data structure:
// We define a separate scope, so we can add sub-objects later.
var inputSchema = schema.NewScopeSchema(
// Struct-mapped object schemas are object definitions that are mapped to a specific struct (Input)
schema.NewStructMappedObjectSchema[Input](
// ID for the object:
"input",
// Properties of the object:
map[string]*schema.PropertySchema{
"name": schema.NewPropertySchema(
// Type properties:
schema.NewStringSchema(nil, nil, nil),
// Display metadata:
schema.NewDisplayValue(
schema.PointerTo("Name"),
schema.PointerTo("Name of the person to greet."),
nil,
),
// Required:
true,
// Required if:
[]string{},
// Required if not:
[]string{},
// Conflicts:
[]string{},
// Default value, JSON encoded:
nil,
//Examples:
nil,
)
},
),
)
The output data model
The output data model is similar to the input. First, we define our output struct:
type Output struct {
Message string `json:"message"`
}
Then, we have to describe the schema for this output similar to the input:
var outputSchema = schema.NewScopeSchema(
schema.NewStructMappedObjectSchema[Output](
"output",
map[string]*schema.PropertySchema{
"message": schema.NewPropertySchema(
schema.NewStringSchema(nil, nil, nil),
schema.NewDisplayValue(
schema.PointerTo("Message"),
schema.PointerTo("The resulting message."),
nil,
),
true,
nil,
nil,
nil,
nil,
nil,
)
},
),
)
The callable function
Now we can create a callable function. This function will always take one input and produce an output ID (e.g. "success"
) and an output data structure. This allows you to return one of multiple possible outputs.
func greet(input Input) (string, any) {
return "success", Output{
fmt.Sprintf("Hello, %s!", input.Name),
}
}
Finally, we can incorporate this function into a step schema:
var greetSchema = schema.NewCallableSchema(
schema.NewCallableStep[Input](
// ID of the function:
"greet",
// Add the input schema:
inputSchema,
map[string]*schema.StepOutputSchema{
// Define possible outputs:
"success": schema.NewStepOutputSchema(
// Add the output schema:
outputSchema,
schema.NewDisplayValue(
schema.PointerTo("Success"),
schema.PointerTo("Successfully created message."),
nil,
),
false,
),
},
// Metadata for the function:
schema.NewDisplayValue(
schema.PointerTo("Greet"),
schema.PointerTo("Greets the user."),
nil,
),
// Reference the function
greet,
)
)
The calling scaffold
Finally, we need to create our main function to run the plugin:
package main
import (
"go.flow.arcalot.io/pluginsdk/plugin"
)
func main() {
plugin.Run(greetSchema)
}
Running the plugin
Go plugins currently cannot run as CLI tools, so you will have to use this plugin in conjunction with the Arcaflow Engine. However, you can dump the schema by running:
go run yourplugin.go --schema
Next steps
Once you are finished with your first plugin, you should read the section about writing a schema.