Skip to content

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:

exporter := export.NewPrefectExporter()
exporter.UseAsync = false

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:

{
  "id": "validate",
  "name": "Validate Input",
  "step_type": "deterministic"
}

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:

{
  "id": "llm_step",
  "step_type": "llm",
  "processing": {
    "timeout": "300s"
  }
}

4. Use Descriptive Names

Entity names become activity/task names in generated code:

{
  "id": "extract_customer_data",
  "name": "Extract Customer Data from CRM"
}

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