Skip to main content

Unified workflow orchestration system with LLM, Python, and MCP support

Project description

Gleitzeit

A workflow orchestration system for coordinating LLM tasks, Python code execution, and tool integrations. Supports parallel task execution, dependency management, and batch file processing.

Quick Start

Get up and running with Gleitzeit in 5 minutes!

Prerequisites

  • Python 3.8 or higher
  • Ollama installed (for LLM features)
  • Redis (optional, for production persistence)
  • Docker (optional, for isolated Python execution)

Installation

git clone https://github.com/leifmarkthaler/gleitzeit.git
cd gleitzeit
uv pip install -e .

Step 1: Start Ollama

# Start Ollama server
ollama serve

# In another terminal, pull a model
ollama pull llama3.2

Step 2: Create Your First Workflow

Create hello_workflow.yaml:

name: "Hello World Workflow"
tasks:
  - id: "greeting"
    method: "llm/chat"
    parameters:
      model: "llama3.2"
      messages:
        - role: "user"
          content: "Say hello and tell me an interesting fact!"

  - id: "followup"
    method: "llm/chat"
    dependencies: ["greeting"]
    parameters:
      model: "llama3.2"
      messages:
        - role: "user"
          content: "That's interesting! Now tell me more about: ${greeting.response}"

Step 3: Run the Workflow

Using CLI

gleitzeit run hello_workflow.yaml

Or using Python

import asyncio
from gleitzeit import GleitzeitClient

async with GleitzeitClient() as client:
    result = await client.run_workflow("workflow.yaml")

Core Concepts

Protocols & Providers

  • Protocols: Define standardized interfaces (LLM, Python, MCP)
  • Providers: Implement protocol methods (OllamaProvider, PythonProvider, MCPHubProvider)
  • Registry: Maps methods to providers and validates calls

Resource Management

  • Hubs: Manage compute resources (OllamaHub for LLM servers, DockerHub for containers)
  • ResourceManager: Orchestrates multiple hubs and allocates resources
  • Auto-discovery: Automatically finds available Ollama instances

Workflow Execution

  • ExecutionEngine: Central orchestrator for workflow execution
  • TaskQueue: Manages task scheduling with dependency resolution
  • Parallel Execution: Independent tasks run concurrently
  • Parameter Substitution: Pass results between tasks using ${task_id.field}

Persistence

Gleitzeit includes a unified persistence layer with automatic fallback:

  • Redis (if available) - High performance
  • SQLite (fallback) - Local database
  • Memory (last resort) - In-process storage

Python Client

Using GleitzeitClient

from gleitzeit import GleitzeitClient

async with GleitzeitClient() as client:
    # Auto-detects API or native mode
    result = await client.run_workflow("workflow.yaml")
    
    # Force specific mode
    async with GleitzeitClient(mode="api") as client:
        # Uses REST API
        pass
    
    async with GleitzeitClient(mode="native") as client:
        # Direct execution engine
        pass

How It Works Internally

The GleitzeitClient handles all the complexity for you. When you use it in native mode, it automatically:

  1. Creates and configures the ExecutionEngine
  2. Registers all necessary providers
  3. Starts the engine (no manual start needed!)
  4. Submits your workflow
  5. Handles cleanup on exit

Here's what happens under the hood:

# This is what GleitzeitClient does internally (you don't need to do this!)
async with GleitzeitClient(mode="native") as client:
    # Client automatically:
    # - Creates ExecutionEngine
    # - Registers providers (Ollama, Python, MCP, etc.)
    # - Starts the engine
    # - Now you just submit workflows:
    
    result = await client.run_workflow("workflow.yaml")
    # The engine is already running, workflow executes automatically!

Available Client Methods

# Run workflows
result = await client.run_workflow("workflow.yaml")
result = await client.run_workflow(workflow_dict)

# Chat with LLMs (via Ollama)
response = await client.chat("Hello", model="llama3.2")

# Execute Python scripts
result = await client.execute_python_script("script.py", args={"key": "value"})

# Batch process files
results = await client.batch_process(
    directory="docs",
    pattern="*.txt",
    prompt="Summarize",
    model="llama3.2"
)

# Direct task execution
task_result = await client.execute_task(task)

Creating and Submitting Tasks Programmatically

from gleitzeit import GleitzeitClient

async with GleitzeitClient() as client:
    # Submit individual task
    result = await client.execute_task({
        "method": "llm/chat",
        "parameters": {
            "model": "llama3.2",
            "messages": [{"role": "user", "content": "Hello!"}]
        }
    })
    
    # Or create a workflow programmatically
    workflow = {
        "name": "My Dynamic Workflow",
        "tasks": [
            {
                "id": "task1",
                "method": "llm/chat",
                "parameters": {
                    "model": "llama3.2",
                    "messages": [{"role": "user", "content": "Write a haiku"}]
                }
            },
            {
                "id": "task2",
                "method": "python/execute",
                "dependencies": ["task1"],
                "parameters": {
                    "code": "print('Task 1 result:', '${task1.response}')"
                }
            }
        ]
    }
    
    # Submit the workflow
    results = await client.run_workflow(workflow)

Workflow Examples

Basic Workflow with Dependencies

name: "Analysis Pipeline"
tasks:
  - id: "load_data"
    method: "python/execute"
    parameters:
      script: "scripts/load_data.py"
      args:
        input: "data.csv"
  
  - id: "analyze"
    method: "llm/chat"
    dependencies: ["load_data"]
    parameters:
      model: "llama3.2"
      messages:
        - role: "user"
          content: "Analyze this data: ${load_data.result}"
  
  - id: "save_results"
    method: "python/execute"
    dependencies: ["analyze"]
    parameters:
      script: "scripts/save_results.py"
      args:
        content: "${analyze.response}"
        output: "report.md"

Chain Task Results

Create a story by chaining LLM responses:

name: "Story Chain"
tasks:
  - id: "character"
    method: "llm/chat"
    parameters:
      model: "llama3.2"
      messages:
        - role: "user"
          content: "Create a unique character for a story in one sentence"

  - id: "setting"
    method: "llm/chat"
    dependencies: ["character"]
    parameters:
      model: "llama3.2"
      messages:
        - role: "user"
          content: "Create a setting for this character: ${character.response}"

  - id: "plot"
    method: "llm/chat"
    dependencies: ["character", "setting"]
    parameters:
      model: "llama3.2"
      messages:
        - role: "user"
          content: |
            Write a short story plot with:
            Character: ${character.response}
            Setting: ${setting.response}

MCP (Model Context Protocol) Integration

Use external MCP server tools (requires server configuration):

name: "MCP Tools Example"
tasks:
  # Read file using filesystem MCP server
  - id: "read_config"
    method: "mcp/tool.fs.read"
    parameters:
      path: "./config.json"
  
  # Write file using filesystem MCP server
  - id: "save_output"
    method: "mcp/tool.fs.write"
    dependencies: ["read_config"]
    parameters:
      path: "./output.json"
      content: "Processed: ${read_config.content}"
  
  # Combine with LLM for analysis
  - id: "analyze"
    method: "llm/chat"
    dependencies: ["read_config"]
    parameters:
      model: "llama3.2"
      messages:
        - role: "user"
          content: "Analyze this configuration: ${read_config.content}"

Multi-Model Workflow

Use different models for different tasks:

name: "Multi-Model Analysis"
tasks:
  - id: "fast_response"
    method: "llm/chat"
    parameters:
      model: "llama3.2:1b"  # Fast small model
      messages:
        - role: "user"
          content: "Quick summary of quantum computing"

  - id: "detailed_response"
    method: "llm/chat"
    parameters:
      model: "llama3.2:7b"  # Larger model for detail
      messages:
        - role: "user"
          content: "Explain quantum computing in detail with examples"

  - id: "combine"
    method: "llm/chat"
    dependencies: ["fast_response", "detailed_response"]
    parameters:
      model: "llama3.2"
      messages:
        - role: "user"
          content: |
            Combine these two explanations into one comprehensive summary:
            Quick: ${fast_response.response}
            Detailed: ${detailed_response.response}

Supported Protocols

LLM Protocol (llm/v1)

Provider: OllamaProvider
Methods:

  • llm/chat - Text generation with conversation history
  • llm/vision - Image analysis with vision models
  • llm/generate - Direct text generation
  • llm/embeddings - Generate text embeddings

Models: Any Ollama model (llama3.2, mistral, codellama, llava, etc.)

Python Protocol (python/v1)

Provider: PythonProvider
Methods:

  • python/execute - Execute Python script files
  • python/validate - Validate Python syntax
  • python/info - Get provider information

Security: Scripts run in subprocess isolation or Docker containers

MCP Protocol (mcp/v1)

Provider: MCPHubProvider
Methods:

  • mcp/tool.* - Execute MCP tools from registered servers
  • mcp/tools/list - List available tools
  • mcp/servers - List MCP servers
  • mcp/ping - Health check

External Servers: Any MCP-compliant server (stdio/websocket/HTTP)
Note: Configure servers in ~/.gleitzeit/config.yaml or via environment

CLI Commands

# Run workflows
gleitzeit run workflow.yaml
gleitzeit run workflow.yaml --local    # Force native mode
gleitzeit run workflow.yaml --watch    # Watch for changes

# Check status
gleitzeit status
gleitzeit status --resources

# Batch processing
gleitzeit batch documents --pattern "*.txt" --prompt "Summarize"

# Configuration
gleitzeit config show
gleitzeit config set default_model llama3.2

# Start API server
gleitzeit serve --port 8000

Resource Hubs

OllamaHub

Manages Ollama LLM server instances:

  • Auto-discovers running instances on configurable ports
  • Health monitoring and metrics collection
  • Model-aware load balancing
  • Connection pooling for performance

DockerHub (Optional)

Manages Docker containers for isolated Python execution:

  • Container lifecycle management
  • Resource limits enforcement
  • Security isolation

MCPHub

Manages MCP (Model Context Protocol) server instances:

  • Supports stdio, WebSocket, and HTTP connections
  • Automatic tool discovery and registration
  • Health monitoring and auto-restart
  • Tool routing and load balancing
  • Configurable via YAML or environment variables

Deployment Modes

Development Mode

# Direct execution engine, no server needed
client = GleitzeitClient(mode="native")

Production Mode

# Start API server
gleitzeit serve --port 8000

# Client connects to API
client = GleitzeitClient(mode="api", api_host="localhost", api_port=8000)

Auto Mode (Default)

# Automatically uses API if available, otherwise native
client = GleitzeitClient()  # mode="auto" is default

Configuration

Config File (~/.gleitzeit/config.yaml)

default_model: llama3.2
ollama:
  discovery_ports: [11434, 11435, 11436]
  auto_discover: true
persistence:
  type: auto
  redis:
    url: redis://localhost:6379
batch:
  max_concurrent: 5
  max_file_size: 1048576
mcp:
  auto_discover: true
  servers:
    - name: "filesystem"
      connection_type: "stdio"
      command: ["npx", "-y", "@modelcontextprotocol/server-filesystem"]
      tool_prefix: "fs."

Environment Variables

# Ollama settings
export GLEITZEIT_OLLAMA_URL=http://localhost:11434
export GLEITZEIT_DEFAULT_MODEL=llama3.2

# Persistence
export GLEITZEIT_PERSISTENCE_TYPE=auto  # auto|redis|sql|memory
export GLEITZEIT_REDIS_URL=redis://localhost:6379
export GLEITZEIT_SQL_DB_PATH=~/.gleitzeit/workflows.db


# API server
export GLEITZEIT_API_HOST=0.0.0.0
export GLEITZEIT_API_PORT=8000

Advanced Features

Parallel Task Execution

Tasks without dependencies run concurrently:

tasks:
  - id: "task1"  # Runs immediately
    method: "llm/chat"
  - id: "task2"  # Runs in parallel with task1
    method: "llm/chat"
  - id: "combine"  # Waits for both
    dependencies: ["task1", "task2"]
    method: "python/execute"

Batch Processing

Process multiple files in parallel:

Create Test Files

mkdir documents
echo "Python is a great language" > documents/python.txt
echo "JavaScript powers the web" > documents/javascript.txt
echo "Rust is fast and safe" > documents/rust.txt

Using CLI

gleitzeit batch documents \
  --pattern "*.txt" \
  --prompt "Summarize this file and rate the programming language mentioned from 1-10"

Using Python API

results = await client.batch_process(
    directory="documents",
    pattern="**/*.txt",  # Recursive
    prompt="Extract key points",
    model="llama3.2",
    max_concurrent=10
)

Batch Workflow

name: "Batch Document Analysis"
type: "batch"

batch:
  directory: "documents"
  pattern: "*.txt"

template:
  method: "llm/chat"
  model: "llama3.2"
  messages:
    - role: "user"
      content: "Analyze this document and provide a summary"

Dynamic Workflows with Python

Create workflows programmatically:

import asyncio
from gleitzeit import GleitzeitClient

async def dynamic_workflow():
    async with GleitzeitClient() as client:
        # Generate a question
        question = await client.execute_task({
            "method": "llm/chat",
            "parameters": {
                "model": "llama3.2",
                "messages": [
                    {"role": "user", "content": "Generate a random question about science"}
                ]
            }
        })
        
        # Answer the generated question
        answer = await client.execute_task({
            "method": "llm/chat",
            "parameters": {
                "model": "llama3.2",
                "messages": [
                    {"role": "user", "content": f"Answer this: {question['response']}"}
                ]
            }
        })
        
        # Fact-check the answer
        verification = await client.execute_task({
            "method": "llm/chat",
            "parameters": {
                "model": "llama3.2",
                "messages": [
                    {"role": "user", 
                     "content": f"Is this answer correct? {answer['response']}"}
                ]
            }
        })
        
        return {
            "question": question['response'],
            "answer": answer['response'],
            "verification": verification['response']
        }

result = asyncio.run(dynamic_workflow())
print(result)

Error Handling & Retries

tasks:
  - id: "resilient_task"
    method: "llm/chat"
    retry:
      max_attempts: 3
      delay: 2
      exponential_backoff: true
    parameters:
      timeout: 30

Testing

# Run all tests
pytest

# Run specific test suites
pytest tests/unit/
pytest tests/integration/
pytest tests/workflows/

# Test with real execution
python tests/workflow_test_suite.py --execute

Common Issues & Solutions

Ollama Connection Issues

# Check if Ollama is running
curl http://localhost:11434/api/tags

# Restart Ollama
killall ollama
ollama serve

Workflow Debugging

# Enable debug mode
export GLEITZEIT_DEBUG=true
gleitzeit run workflow.yaml

# Check task details
gleitzeit status --verbose

Performance Tips

  • Use --local flag to force native mode for development
  • Configure Redis for production persistence
  • Adjust max_concurrent for batch processing based on resources
  • Use smaller models (e.g., llama3.2:1b) for simple tasks

Documentation

Requirements

  • Python 3.8+
  • Ollama (for LLM operations)
  • Redis (optional, for persistence)
  • Docker (optional, for isolated Python execution)

License

MIT

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

gleitzeit-0.0.5.tar.gz (278.6 kB view details)

Uploaded Source

Built Distribution

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

gleitzeit-0.0.5-py3-none-any.whl (235.3 kB view details)

Uploaded Python 3

File details

Details for the file gleitzeit-0.0.5.tar.gz.

File metadata

  • Download URL: gleitzeit-0.0.5.tar.gz
  • Upload date:
  • Size: 278.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.14

File hashes

Hashes for gleitzeit-0.0.5.tar.gz
Algorithm Hash digest
SHA256 e9abf532da77bc3301d7c21f155abeede2ecc594f6fa38ed8234dfbba40d49e4
MD5 e483d2b62eb3b7f70987fdc74ff56e7b
BLAKE2b-256 1cee10b8aa8c5b25c30825f699cd901eb08f33805c98666285b798724b551bad

See more details on using hashes here.

File details

Details for the file gleitzeit-0.0.5-py3-none-any.whl.

File metadata

  • Download URL: gleitzeit-0.0.5-py3-none-any.whl
  • Upload date:
  • Size: 235.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.14

File hashes

Hashes for gleitzeit-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 2b07a130be1d785a12faa2d66316c9db540cba4d5c1147e6055b2edd0f45692d
MD5 8407bf38fe79d036aa6fadc1391a3a29
BLAKE2b-256 8a72acee59cfaaf4bce15ca40743f9661551516a71827a32c0ecd783d1a629aa

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