Skip to main content

Convert YAML workflow files to LangGraph implementations

Project description

YAML to LangGraph Converter

A powerful tool for converting Defy YAML workflow files to LangGraph implementations with comprehensive validation, beautiful CLI output, and professional workflow visualization.

Features

  • ๐Ÿ” YAML Schema Validation: Comprehensive validation of workflow structure
  • ๐ŸŽจ Rich CLI Interface: Beautiful command-line interface with Click
  • โšก Fast Conversion: Efficient parsing and code generation
  • ๐Ÿงช Comprehensive Testing: Full test suite with pytest
  • ๐Ÿ“ฆ Modern Packaging: Standard Python package structure
  • ๐Ÿ› ๏ธ Extensible: Easy to customize and extend
  • ๐ŸŽจ Professional Visualization: High-quality workflow diagrams using Mermaid + Pyppeteer
  • ๐Ÿ”„ Advanced Loop Support: Proper handling of complex loop structures with break conditions
  • ๐Ÿ“Š State Management: Intelligent variable reference handling and state tracking
  • ๐ŸŽฏ Multiple Themes: Default, dark, forest, and neutral visualization themes

Installation

From Source

git clone https://github.com/example/yaml-to-langgraph.git
cd yaml-to-langgraph
pip install -e .

With Development Dependencies

pip install -e ".[dev]"

With LangChain Dependencies

pip install -e ".[langchain]"

Usage

Command Line Interface

Basic Commands

# Validate YAML workflow file
yaml-to-langgraph validate workflow.yml

# Convert YAML to LangGraph implementation
yaml-to-langgraph convert workflow.yml

# Convert with custom output directory
yaml-to-langgraph convert workflow.yml --output my_workflow

# Convert with verbose output
yaml-to-langgraph convert workflow.yml --verbose

# Skip validation (not recommended)
yaml-to-langgraph convert workflow.yml --skip-validation

# List all nodes in the workflow
yaml-to-langgraph list-nodes workflow.yml

# Dry run to see what would be generated
yaml-to-langgraph dry-run workflow.yml

# Get help for any command
yaml-to-langgraph --help
yaml-to-langgraph convert --help
yaml-to-langgraph validate --help

๐ŸŽจ Workflow Visualization

# Generate a visual representation of the workflow
yaml-to-langgraph visualize workflow.yml

# Visualize with different themes
yaml-to-langgraph visualize workflow.yml --theme dark
yaml-to-langgraph visualize workflow.yml --theme forest
yaml-to-langgraph visualize workflow.yml --theme neutral

# Customize visualization output
yaml-to-langgraph visualize workflow.yml --output my_workflow.png
yaml-to-langgraph visualize workflow.yml --format svg
yaml-to-langgraph visualize workflow.yml --size 30 20
yaml-to-langgraph visualize workflow.yml --dpi 300

# Generate high-resolution (HD) visualization
yaml-to-langgraph visualize workflow.yml --size 30 20 --dpi 300 --output workflow_hd.png

# Different layout algorithms
yaml-to-langgraph visualize workflow.yml --layout hierarchical
yaml-to-langgraph visualize workflow.yml --layout flowchart
yaml-to-langgraph visualize workflow.yml --layout graph

# Show edge labels (can make complex graphs cluttered)
yaml-to-langgraph visualize workflow.yml --show-edge-labels

# Disable loop grouping
yaml-to-langgraph visualize workflow.yml --no-loops

Validation Examples

# Basic validation
yaml-to-langgraph validate workflow.yml

# Strict validation (treats warnings as errors)
yaml-to-langgraph validate workflow.yml --strict

# Validate with detailed output
yaml-to-langgraph validate workflow.yml --verbose

Conversion Examples

# Simple conversion (includes automatic visualization)
yaml-to-langgraph convert sample_workflow.yml

# Convert without visualization
yaml-to-langgraph convert sample_workflow.yml --no-visualization

# Convert to specific directory
yaml-to-langgraph convert sample_workflow.yml --output generated_workflow

# Convert with verbose output to see all generated files
yaml-to-langgraph convert sample_workflow.yml --verbose

# Convert multiple workflows
for file in workflows/*.yml; do
    yaml-to-langgraph convert "$file" --output "generated_$(basename "$file" .yml)"
done

Python API

Basic Usage

from yaml_to_langgraph import YAMLToLangGraphConverter
from yaml_to_langgraph.schema_validator import validate_yaml_workflow

# Validate a workflow
result = validate_yaml_workflow("workflow.yml")
if result.is_valid:
    print("Workflow is valid!")
    if result.warnings:
        print(f"Warnings: {[w.message for w in result.warnings]}")
else:
    print(f"Validation failed: {[e.message for e in result.errors]}")

# Convert YAML workflow to LangGraph
converter = YAMLToLangGraphConverter("workflow.yml", "output_dir")
output_path = converter.convert()
print(f"Generated workflow at: {output_path}")

Advanced Usage

from yaml_to_langgraph import YAMLToLangGraphConverter
from yaml_to_langgraph.yaml_parser import YAMLWorkflowParser
from yaml_to_langgraph.code_generator import LangGraphCodeGenerator

# Parse YAML workflow
parser = YAMLWorkflowParser("workflow.yml")
workflow_data = parser.parse()

# Generate code
generator = LangGraphCodeGenerator(workflow_data)
code_files = generator.generate_code("output_dir")

# Access specific components
print(f"Workflow name: {workflow_data.app.name}")
print(f"Number of nodes: {len(workflow_data.graph.nodes)}")
print(f"Number of edges: {len(workflow_data.graph.edges)}")

# Get LLM nodes
llm_nodes = [node for node in workflow_data.graph.nodes if node.type == "llm"]
print(f"LLM nodes: {[node.id for node in llm_nodes]}")

# Access loop information
for loop in workflow_data.loops:
    print(f"Loop {loop.id}: {loop.title}")
    print(f"  Max iterations: {loop.max_iterations}")
    print(f"  Break conditions: {loop.break_conditions}")
    print(f"  Child nodes: {[node.id for node in loop.child_nodes]}")

# Access state variables
for var in workflow_data.state_variables:
    print(f"State variable: {var.node_id}.{var.variable_name} ({var.variable_type})")

๐ŸŽจ Visualization API

from yaml_to_langgraph.graph_visualizer import GraphVisualizer, VisualizationConfig
from yaml_to_langgraph.yaml_parser import YAMLWorkflowParser

# Parse workflow
parser = YAMLWorkflowParser("workflow.yml")
workflow_info = parser.parse()

# Create visualization config
config = VisualizationConfig(
    output_format="png",           # png, svg, pdf
    layout_algorithm="hierarchical", # hierarchical, flowchart, graph
    figure_size=(24, 16),          # width, height in inches
    dpi=300,                       # resolution
    theme="default",               # default, dark, forest, neutral
    show_edge_labels=False,        # show edge labels
    show_loops=True,               # enable loop grouping
    loop_grouping=True,            # group loop nodes
    max_label_length=20            # truncate long labels
)

# Generate visualization
visualizer = GraphVisualizer(config)
output_path = visualizer.visualize_workflow(workflow_info, "workflow_diagram.png")
print(f"Visualization saved to: {output_path}")

# Generate high-resolution (HD) visualization
hd_config = VisualizationConfig(
    output_format="png",
    layout_algorithm="hierarchical",
    figure_size=(30, 20),          # Large size for HD
    dpi=300,                       # High resolution
    theme="default",
    show_edge_labels=False,
    show_loops=True,
    loop_grouping=True,
    max_label_length=20
)

hd_visualizer = GraphVisualizer(hd_config)
hd_output_path = hd_visualizer.visualize_workflow(workflow_info, "workflow_hd.png")
print(f"HD visualization saved to: {hd_output_path}")

Error Handling

from yaml_to_langgraph import YAMLToLangGraphConverter
from yaml_to_langgraph.schema_validator import ValidationError

try:
    converter = YAMLToLangGraphConverter("invalid_workflow.yml", "output")
    output_path = converter.convert()
except ValidationError as e:
    print(f"Validation error: {e.message}")
    print(f"Path: {e.path}")
except FileNotFoundError:
    print("YAML file not found")
except Exception as e:
    print(f"Unexpected error: {e}")

Generated Code Structure

When you convert a YAML workflow, the following structure is generated:

generated_workflow/
โ”œโ”€โ”€ prompts/                    # Prompt templates for LLM nodes
โ”‚   โ”œโ”€โ”€ node1_prompt.py
โ”‚   โ”œโ”€โ”€ node2_prompt.py
โ”‚   โ””โ”€โ”€ ...
โ”œโ”€โ”€ nodes/                      # Node implementations
โ”‚   โ”œโ”€โ”€ workflow_nodes.py
โ”‚   โ”œโ”€โ”€ llm_node.py            # Enhanced LLM nodes with state management
โ”‚   โ””โ”€โ”€ custom_nodes.py
โ”œโ”€โ”€ edges/                      # Edge definitions and routing logic
โ”‚   โ”œโ”€โ”€ routing.py
โ”‚   โ””โ”€โ”€ conditions.py
โ”œโ”€โ”€ workflow_graph.py          # Main graph assembly
โ”œโ”€โ”€ loop_aware_graph.py        # Advanced loop handling with LangGraph For constructs
โ”œโ”€โ”€ example_usage.py           # Usage example
โ”œโ”€โ”€ requirements.txt           # Dependencies
โ”œโ”€โ”€ workflow_graph.png         # Professional workflow visualization
โ””โ”€โ”€ README.md                  # Generated documentation

Using the Generated Workflow

# After conversion, use the generated workflow
from workflow_graph import create_workflow_graph, run_workflow
from langchain_openai import ChatOpenAI

# Initialize your model
model = ChatOpenAI(model="gpt-4", temperature=0.7)

# Create the workflow graph
graph = create_workflow_graph(model)

# Run the workflow
result = run_workflow(
    graph=graph,
    input_data={"user_input": "Hello, world!"}
)

print(result)

Real-World Examples

Example 1: Simple Chat Workflow

# simple_chat.yml
app:
  name: "simple-chat"
  description: "A simple chat workflow"

workflow:
  graph:
    nodes:
      - id: "start"
        type: "start"
        data:
          type: "start"
          title: "Start"
      - id: "chat"
        type: "llm"
        data:
          type: "llm"
          title: "Chat Response"
          model:
            provider: "openai"
            name: "gpt-4"
          prompt_template:
            - role: "user"
              content: "{{user_input}}"
      - id: "end"
        type: "end"
        data:
          type: "end"
          title: "End"
    edges:
      - id: "edge1"
        source: "start"
        target: "chat"
        data:
          label: "always"
      - id: "edge2"
        source: "chat"
        target: "end"
        data:
          label: "always"

Convert and use:

yaml-to-langgraph convert simple_chat.yml --output simple_chat_workflow
cd simple_chat_workflow
pip install -r requirements.txt
python example_usage.py

Example 2: Multi-Step Processing Workflow

# processing_workflow.yml
app:
  name: "data-processor"
  description: "Multi-step data processing workflow"

workflow:
  graph:
    nodes:
      - id: "start"
        type: "start"
        data:
          type: "start"
      - id: "analyze"
        type: "llm"
        data:
          type: "llm"
          title: "Data Analyzer"
          model:
            provider: "openai"
            name: "gpt-4"
          prompt_template:
            - role: "system"
              content: "Analyze the following data: {{input_data}}"
      - id: "process"
        type: "llm"
        data:
          type: "llm"
          title: "Data Processor"
          model:
            provider: "openai"
            name: "gpt-4"
          prompt_template:
            - role: "system"
              content: "Process the analyzed data: {{analyze.output}}"
      - id: "validate"
        type: "llm"
        data:
          type: "llm"
          title: "Data Validator"
          model:
            provider: "openai"
            name: "gpt-4"
          prompt_template:
            - role: "system"
              content: "Validate the processed data: {{process.output}}"
      - id: "end"
        type: "end"
        data:
          type: "end"
    edges:
      - id: "e1"
        source: "start"
        target: "analyze"
        data:
          label: "always"
      - id: "e2"
        source: "analyze"
        target: "process"
        data:
          label: "success"
      - id: "e3"
        source: "process"
        target: "validate"
        data:
          label: "success"
      - id: "e4"
        source: "validate"
        target: "end"
        data:
          label: "valid"

Example 3: Complex Loop Workflow

# loop_workflow.yml
app:
  name: "iterative-processor"
  description: "Workflow with iterative processing loop"

workflow:
  graph:
    nodes:
      - id: "start"
        type: "start"
        data:
          type: "start"
          title: "Start Processing"
      - id: "main_loop"
        type: "loop"
        data:
          type: "loop"
          title: "Main Processing Loop"
          loop_config:
            max_iterations: 5
            break_conditions:
              - condition: "{{Objection}} == 'resolved'"
                description: "Stop when objection is resolved"
            loop_variables:
              - name: "iteration_count"
                initial_value: 0
              - name: "Objection"
                initial_value: "pending"
        children:
          - id: "loop_start"
            type: "loop-start"
            data:
              type: "loop-start"
              title: "Loop Start"
          - id: "process_item"
            type: "llm"
            data:
              type: "llm"
              title: "Process Item"
              model:
                provider: "openai"
                name: "gpt-4"
              prompt_template:
                - role: "system"
                  content: "Process item {{iteration_count}}: {{input_data}}"
          - id: "check_objection"
            type: "llm"
            data:
              type: "llm"
              title: "Check for Objections"
              model:
                provider: "openai"
                name: "gpt-4"
              prompt_template:
                - role: "system"
                  content: "Check if there are objections: {{process_item.output}}"
      - id: "end"
        type: "end"
        data:
          type: "end"
          title: "End"
    edges:
      - id: "e1"
        source: "start"
        target: "main_loop"
        data:
          label: "always"
      - id: "e2"
        source: "main_loop"
        target: "end"
        data:
          label: "loop_complete"

Using Make Commands

The project includes a comprehensive Makefile for development:

# Development setup
make dev-setup          # Install in development mode
make test               # Run all tests
make demo               # Convert sample workflow
make validate-demo      # Validate sample workflow

# Code quality
make format             # Format code
make lint               # Run linting
make check              # Run all quality checks

# Package management
make build              # Build package
make publish-token TOKEN=your-token  # Publish to PyPI
make pypi-help          # Show PyPI setup instructions

# UV commands
make uv-sync            # Sync dependencies
make uv-add PACKAGE=requests  # Add new package
make uv-update          # Update dependencies

Quick Reference

Common Commands

Command Description
yaml-to-langgraph validate workflow.yml Validate YAML workflow
yaml-to-langgraph convert workflow.yml Convert to LangGraph
yaml-to-langgraph convert workflow.yml --output my_dir Convert to specific directory
yaml-to-langgraph visualize workflow.yml Generate workflow diagram
yaml-to-langgraph visualize workflow.yml --theme dark Generate dark theme diagram
yaml-to-langgraph visualize workflow.yml --size 30 20 --dpi 300 Generate HD diagram
yaml-to-langgraph list-nodes workflow.yml List all nodes
yaml-to-langgraph dry-run workflow.yml Preview what would be generated

Visualization Options

Option Description Default
--theme Theme: default, dark, forest, neutral default
--layout Layout: hierarchical, flowchart, graph hierarchical
--format Output format: png, svg, pdf png
--size Figure size (width height) 24 16
--dpi Resolution 300
--show-edge-labels Show edge labels false
--no-loops Disable loop grouping false

Make Commands

Command Description
make help Show all available commands
make test Run all tests
make demo Convert sample workflow
make build Build package
make publish-token TOKEN=xxx Publish to PyPI
make pypi-help Show PyPI setup help

YAML Structure

app:
  name: "workflow-name"
  description: "Workflow description"

workflow:
  graph:
    nodes:
      - id: "node_id"
        type: "llm|start|end|code|loop|loop-start|assigner"
        data:
          type: "llm|start|end|code|loop|loop-start|assigner"
          title: "Node Title"
          # ... node-specific data
    edges:
      - id: "edge_id"
        source: "source_node"
        target: "target_node"
        data:
          label: "condition"

Generated Files

  • workflow_graph.py - Main graph implementation
  • loop_aware_graph.py - Advanced loop handling
  • prompts/ - LLM prompt templates
  • nodes/ - Node implementations
  • edges/ - Routing logic
  • example_usage.py - Usage example
  • requirements.txt - Dependencies
  • workflow_graph.png - Professional workflow visualization

Advanced Features

๐Ÿ”„ Loop Support

The converter provides advanced loop handling:

  • Hierarchical Loop Structure: Proper handling of loop containers with loop-start nodes
  • Break Conditions: Support for conditional loop exit based on state variables
  • Loop Variables: Automatic tracking of loop-specific state variables
  • LangGraph Integration: Generates proper For constructs for LangGraph execution

๐Ÿ“Š State Management

Intelligent state management features:

  • Variable References: Automatic detection of {{#node_id.field#}} patterns in prompts
  • State Variable Tracking: Comprehensive tracking of all state variables across the workflow
  • Dependency Analysis: Automatic detection of node dependencies based on variable usage
  • Enhanced LLM Nodes: LLM nodes automatically update state with multiple output keys

๐ŸŽจ Professional Visualization

High-quality workflow visualization using Mermaid + Pyppeteer:

  • Multiple Themes: Default, dark, forest, and neutral themes
  • Loop Grouping: Visual grouping of loop nodes with subgraphs
  • Emoji Icons: Visual node type identification (๐Ÿš€ Start, ๐Ÿ End, ๐Ÿค– LLM, etc.)
  • Compact Output: Small file sizes (90%+ smaller than previous backends)
  • Scalable Quality: Vector-based rendering maintains perfect quality at any size

Development

Setup Development Environment

# Clone repository
git clone https://github.com/example/yaml-to-langgraph.git
cd yaml-to-langgraph

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=src/yaml_to_langgraph --cov-report=html

Code Quality

# Format code
black src/ tests/

# Sort imports
isort src/ tests/

# Lint code
ruff check src/ tests/

# Type checking
mypy src/

Project Structure

yaml_to_langgraph/
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ yaml_to_langgraph/
โ”‚       โ”œโ”€โ”€ __init__.py
โ”‚       โ”œโ”€โ”€ cli.py              # Command-line interface
โ”‚       โ”œโ”€โ”€ converter.py        # Main converter logic
โ”‚       โ”œโ”€โ”€ schema_validator.py # YAML validation
โ”‚       โ”œโ”€โ”€ yaml_parser.py      # YAML parsing with loop/state support
โ”‚       โ”œโ”€โ”€ code_generator.py   # Code generation with loop awareness
โ”‚       โ””โ”€โ”€ graph_visualizer.py # Mermaid + Pyppeteer visualization
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ conftest.py
โ”‚   โ”œโ”€โ”€ test_sample_workflow.py
โ”‚   โ”œโ”€โ”€ test_cli.py
โ”‚   โ”œโ”€โ”€ test_converter.py
โ”‚   โ””โ”€โ”€ test_schema_validation.py
โ”œโ”€โ”€ pyproject.toml
โ””โ”€โ”€ README.md

Testing

The project includes a comprehensive test suite covering:

  • Schema Validation: YAML structure validation
  • CLI Functionality: Command-line interface testing
  • Core Converter: Conversion logic testing
  • Sample Workflow: Real-world workflow testing
  • Loop Handling: Complex loop structure testing
  • State Management: Variable reference and state tracking testing
  • Visualization: Mermaid diagram generation testing
# Run all tests
pytest tests/ -v

# Run specific test categories
pytest tests/test_schema_validation.py -v
pytest tests/test_cli.py -v
pytest tests/test_converter.py -v
pytest tests/test_sample_workflow.py -v

Publishing

The package can be published to PyPI using several methods:

Using UV (Recommended)

# Build the package
make build

# Publish with environment variables
export UV_PUBLISH_USERNAME=your-username
export UV_PUBLISH_PASSWORD=your-password
make publish

# Or publish with token
make publish-token TOKEN=your-pypi-token

# Publish to Test PyPI first
make publish-test TOKEN=your-testpypi-token

Using Twine (Fallback)

If you prefer to use your existing ~/.pypirc configuration:

# Build the package
make build

# Publish using twine (reads ~/.pypirc)
make publish-twine

# Publish to Test PyPI using twine
make publish-test-twine

Manual Publishing

# Build
uv build

# Publish with uv
uv publish --token your-token

# Or with twine
python -m twine upload dist/*

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass
  6. Submit a pull request

License

MIT License - see LICENSE file for details.

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yaml_to_langgraph-1.0.3.tar.gz (38.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yaml_to_langgraph-1.0.3-py3-none-any.whl (33.7 kB view details)

Uploaded Python 3

File details

Details for the file yaml_to_langgraph-1.0.3.tar.gz.

File metadata

  • Download URL: yaml_to_langgraph-1.0.3.tar.gz
  • Upload date:
  • Size: 38.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.14

File hashes

Hashes for yaml_to_langgraph-1.0.3.tar.gz
Algorithm Hash digest
SHA256 2eda2ca5712d604c11ceb96502cad78c97d1416adc8df2681d530b157849d8ea
MD5 a7dfe0a71bd74fb07c25cbaabaaa1942
BLAKE2b-256 2d6f935a7e2f3e73c0dc210eea561cad7a0ff61ab867a7bd97b4b591731530bb

See more details on using hashes here.

File details

Details for the file yaml_to_langgraph-1.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for yaml_to_langgraph-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 62b904130c3d94aa472c7b705dfe506635e6c9645348f06f4c5d35cb6cf854aa
MD5 260bb48e2c31fffc002123a4273a5f6c
BLAKE2b-256 e022654144e2e884cdaa0d5592f43aad0e3ece32b66772ac4228f92ff921ffea

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page