Workflow Engine Exports¶
PIDL process specifications can be exported to workflow orchestration platforms for execution. This guide covers the available exporters and how to use them.
Supported Platforms¶
| Platform | Language | Export Format | Use Case |
|---|---|---|---|
| Temporal | Go | .go |
Durable workflow orchestration |
| Prefect | Python | .py |
Data pipeline orchestration |
| BPMN 2.0 | XML | .bpmn |
Standard interchange format |
| AWS Step Functions | JSON | .json |
Serverless workflow orchestration |
Go Library Usage¶
import "github.com/grokify/pidl/export"
// Load your process specification
p, _ := pidl.ParseFile("pipeline.pidl.json")
// Export to Temporal
temporal := export.NewTemporalExporter()
goCode, _ := temporal.Export(p)
// Export to Prefect
prefect := export.NewPrefectExporter()
pythonCode, _ := prefect.Export(p)
// Export to BPMN
bpmn := export.NewBPMNExporter()
xml, _ := bpmn.Export(p)
// Export to AWS Step Functions
stepfn := export.NewStepFunctionsExporter()
asl, _ := stepfn.Export(p)
Temporal Export¶
The Temporal exporter generates Go code with workflow and activity stubs.
Configuration¶
exporter := export.NewTemporalExporter()
exporter.PackageName = "myworkflow" // Go package name
exporter.WorkflowName = "ProcessData" // Override workflow function name
exporter.IncludeActivities = true // Generate activity stubs
Generated Code Structure¶
// Code generated by PIDL. DO NOT EDIT.
package workflow
import (
"context"
"time"
"go.temporal.io/sdk/activity"
"go.temporal.io/sdk/workflow"
)
func ProcessDataWorkflow(ctx workflow.Context, input interface{}) (interface{}, error) {
ao := workflow.ActivityOptions{
StartToCloseTimeout: 10 * time.Minute,
RetryPolicy: &temporal.RetryPolicy{
MaximumAttempts: 3,
},
}
ctx = workflow.WithActivityOptions(ctx, ao)
// ... workflow logic
}
// Activities with step-type-specific patterns
func ExtractDataActivity(ctx context.Context, input interface{}) (interface{}, error) {
// External service call pattern for "external" step type
return input, nil
}
func TransformDataActivity(ctx context.Context, input interface{}) (interface{}, error) {
// LLM processing pattern for "llm" step type
return input, nil
}
Step Type Mapping¶
| PIDL Step Type | Temporal Pattern |
|---|---|
deterministic |
Standard activity with deterministic logic |
llm |
Activity with LLM API call pattern |
human |
Signal-based human approval pattern |
external |
HTTP/API call with error handling |
tool |
Tool/function invocation pattern |
Prefect Export¶
The Prefect exporter generates Python code with async/sync flow and task definitions.
Configuration¶
exporter := export.NewPrefectExporter()
exporter.FlowName = "process_data" // Override flow function name
exporter.IncludeTasks = true // Generate task stubs
exporter.UseAsync = true // Generate async functions (default)
Generated Code Structure¶
"""
process_data_flow - Generated by PIDL
Source: etl-pipeline
"""
from prefect import flow, task
import asyncio
from typing import Any, Dict
@task(name="Extract Data", tags=["external"])
async def extract_data_task(data: Dict[str, Any]) -> Dict[str, Any]:
"""Extract data from source."""
# External service call pattern
return data
@task(name="Transform Data", tags=["llm"])
async def transform_data_task(data: Dict[str, Any]) -> Dict[str, Any]:
"""Transform data using LLM."""
# LLM processing pattern
return data
@flow(name="process_data_flow")
async def process_data_flow(input_data: Dict[str, Any]) -> Dict[str, Any]:
"""
ETL Pipeline
Generated from PIDL process specification: etl-pipeline
"""
result = input_data
result = await extract_data_task(result)
result = await transform_data_task(result)
return result
if __name__ == "__main__":
asyncio.run(process_data_flow({}))
Sync Mode¶
For synchronous flows:
This generates standard def functions instead of async def.
BPMN 2.0 Export¶
The BPMN exporter generates standard BPMN 2.0 XML for use with workflow engines like Camunda, Activiti, or for import into modeling tools.
Configuration¶
exporter := export.NewBPMNExporter()
exporter.ProcessID = "my-process" // Override process ID
exporter.ProcessName = "My Process" // Override process name
Generated XML Structure¶
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI">
<process id="etl-pipeline" name="ETL Pipeline" isExecutable="true">
<startEvent id="start" name="Start"/>
<serviceTask id="extract" name="Extract Data">
<documentation>Extract data from source</documentation>
</serviceTask>
<serviceTask id="transform" name="Transform Data">
<documentation>Transform using LLM</documentation>
</serviceTask>
<endEvent id="end" name="End"/>
<sequenceFlow sourceRef="start" targetRef="extract"/>
<sequenceFlow sourceRef="extract" targetRef="transform"/>
<sequenceFlow sourceRef="transform" targetRef="end"/>
</process>
</definitions>
Step Type Mapping¶
| PIDL Step Type | BPMN Element |
|---|---|
deterministic |
<serviceTask> |
llm |
<serviceTask> with AI annotation |
human |
<userTask> |
external |
<serviceTask> |
tool |
<serviceTask> |
AWS Step Functions Export¶
The Step Functions exporter generates Amazon States Language (ASL) JSON for AWS Step Functions.
Configuration¶
exporter := export.NewStepFunctionsExporter()
exporter.StateMachineName = "MyPipeline" // Override name
exporter.Comment = "Data processing" // Add comment
exporter.TimeoutSeconds = 3600 // State machine timeout
Generated JSON Structure¶
{
"Comment": "Generated from PIDL: ETL Pipeline",
"StartAt": "extract",
"States": {
"extract": {
"Type": "Task",
"Resource": "arn:aws:states:::http:invoke",
"Comment": "Extract data from source",
"Next": "transform"
},
"transform": {
"Type": "Task",
"Resource": "arn:aws:states:::bedrock:invokeModel",
"Comment": "Transform using LLM",
"Next": "load",
"Retry": [
{
"ErrorEquals": ["States.ALL"],
"IntervalSeconds": 1,
"MaxAttempts": 3,
"BackoffRate": 2.0
}
]
},
"load": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Comment": "Load to database",
"End": true
}
},
"TimeoutSeconds": 3600
}
Step Type to AWS Resource Mapping¶
| PIDL Step Type | AWS Resource ARN |
|---|---|
deterministic |
arn:aws:states:::lambda:invoke |
llm |
arn:aws:states:::bedrock:invokeModel |
human |
arn:aws:states:::activity:HumanReview |
external |
arn:aws:states:::http:invoke |
tool |
arn:aws:states:::lambda:invoke |
Parallel Execution¶
PIDL parallel blocks are converted to Step Functions Parallel states:
{
"parallel_block": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "branch_a",
"States": { "branch_a": { "Type": "Task", "End": true } }
},
{
"StartAt": "branch_b",
"States": { "branch_b": { "Type": "Task", "End": true } }
}
],
"Next": "join_step"
}
}
Best Practices¶
1. Define Step Types¶
Always set step_type on process entities for accurate export:
2. Add Retry Strategies¶
Configure retry behavior in PIDL for it to be reflected in exports:
{
"id": "api_call",
"step_type": "external",
"retry_strategy": {
"max_attempts": 3,
"initial_delay": "1s",
"backoff_multiplier": 2.0
}
}
3. Set Timeouts¶
Define processing timeouts for proper timeout handling:
4. Use Descriptive Names¶
Entity names become activity/task names in generated code:
Limitations¶
- Generated code contains stubs that need implementation
- Parallel blocks require manual configuration in some platforms
- Complex conditional logic may need manual adjustment
- Human approval patterns vary by platform
See Also¶
- Process Specifications - Process spec fundamentals
- Cost Tracking - Execution cost analysis
- Data Lineage - Data flow tracking