sim icon indicating copy to clipboard operation
sim copied to clipboard

feat(export): Add workflow export as standalone Python/FastAPI service

Open aadamsx opened this issue 1 month ago • 2 comments

Summary

Adds the ability to export Sim Studio workflows as standalone, self-contained Python services that can be deployed independently via Docker, Railway, or any container platform.

Features

Multi-Provider LLM Support

  • Anthropic: Claude 3/4 models (Opus, Sonnet, Haiku)
  • OpenAI: GPT-4, GPT-4o, o1, o3 models
  • Google: Gemini Pro, Gemini Flash models
  • Automatic provider detection from model name
  • Provider-specific API key environment variables

Supported Block Types

  • Start/Trigger blocks
  • Agent blocks (with multi-provider support)
  • Function blocks (JavaScript transpiled to Python)
  • Condition/Router blocks
  • API blocks (HTTP requests)
  • Loop blocks (for, forEach, while, doWhile)
  • Variables blocks
  • Response blocks

File Operations

Agents can perform file operations in two ways:

Option 1: Local File Tools (WORKSPACE_DIR)

Set the WORKSPACE_DIR environment variable to enable local file operations:

# In .env
WORKSPACE_DIR=./workspace

When enabled, agents automatically get access to these tools:

Tool Description
local_write_file Write text content to a file
local_write_bytes Write binary data (images, PDFs) as base64
local_append_file Append text to a file (creates if not exists)
local_read_file Read text content from a file
local_read_bytes Read binary data as base64
local_delete_file Delete a file
local_list_directory List files with metadata (size, modified time)

Enable Command Execution (opt-in for security):

# In .env
WORKSPACE_DIR=./workspace
ENABLE_COMMAND_EXECUTION=true

When enabled, agents also get:

Tool Description
local_execute_command Run commands like python script.py or node process.js

Shell operators (|, >, &&, etc.) are blocked for security.

File Size Limits:

# Default: 100MB. Set custom limit in bytes:
MAX_FILE_SIZE=52428800  # 50MB

All paths are sandboxed to WORKSPACE_DIR - agents cannot access files outside this directory. Path traversal attacks (../) and symlink escapes are blocked.

With Docker: The docker-compose.yml mounts ./output to the container workspace:

docker compose up -d
# Files written by agents appear in ./output/

Option 2: MCP Filesystem Tools

If your workflow uses MCP filesystem servers, those tools work as configured. MCP servers handle file operations on their own systems - paths and permissions are determined by the MCP server's configuration.

Using Both

You can use both options together. If WORKSPACE_DIR is set, agents will have access to both local file tools AND any MCP tools configured in the workflow. Tool descriptions help the LLM choose the appropriate tool for each operation.

Health Check with Workspace Status

The /health endpoint returns workspace configuration status:

{
  "status": "healthy",
  "workspace": {
    "enabled": true,
    "workspace_dir": "/app/workspace",
    "command_execution_enabled": false,
    "max_file_size": 104857600
  }
}

Export Validation

  • Pre-export validation for unsupported block types
  • Pre-export validation for unsupported providers
  • Clear error messages shown to users via notification system
  • Prevents silent failures with actionable feedback

Security

  • No eval(): All condition evaluation uses safe AST-based parsing
  • No shell=True: Commands executed without shell to prevent injection
  • File operations sandboxed to WORKSPACE_DIR
  • Shell operators rejected with clear error messages
  • Path traversal attacks blocked (no .. or symlink escapes)
  • File size limits (configurable, default 100MB)
  • Command execution is opt-in (disabled by default)

Production Features

  • FastAPI server with /execute, /health, /ready endpoints
  • Rate limiting (configurable, default 60 req/min)
  • Request size limits (configurable, default 10MB)
  • Automatic retry with exponential backoff
  • MCP tool support via official Python SDK
  • Docker and docker-compose configuration
  • Environment variable management (.env, .env.example)

Production Configuration

Environment Variable Default Description
HOST 0.0.0.0 Server bind address
PORT 8080 Server port
WORKSPACE_DIR (disabled) Enable local file tools with sandbox path
ENABLE_COMMAND_EXECUTION false Allow agents to execute commands
MAX_FILE_SIZE 104857600 (100MB) Maximum file size in bytes
WORKFLOW_PATH workflow.json Path to workflow definition
RATE_LIMIT_REQUESTS 60 Max requests per rate limit window
RATE_LIMIT_WINDOW 60 Rate limit window in seconds
MAX_REQUEST_SIZE 10485760 (10MB) Maximum HTTP request body size
LOG_LEVEL INFO Logging level

UI Integration

  • "Export as Service" context menu option
  • Single workflow export only (no bulk)
  • Error notifications via existing notification system
  • Uses ref pattern to avoid stale closure issues

Architecture

┌────────────────────────────────────────────────────────────────┐
│                    File Operations                              │
├────────────────────────────────────────────────────────────────┤
│                                                                 │
│  WORKSPACE_DIR set in .env?                                     │
│       │                                                         │
│       ├─ YES → Local tools auto-registered (7-8 tools):        │
│       │        • local_write_file (sandboxed)                   │
│       │        • local_write_bytes (binary/base64)              │
│       │        • local_append_file (sandboxed)                  │
│       │        • local_read_file (sandboxed)                    │
│       │        • local_read_bytes (binary/base64)               │
│       │        • local_delete_file (sandboxed)                  │
│       │        • local_list_directory (with metadata)           │
│       │        • local_execute_command (if ENABLE_COMMAND_      │
│       │          EXECUTION=true)                                │
│       │                                                         │
│       └─ NO  → Local tools disabled, returns helpful error:    │
│                "Set WORKSPACE_DIR or use MCP filesystem tools"  │
│                                                                 │
│  MCP tools in workflow? → Always available, hit external server │
│                                                                 │
│  Both enabled? → LLM picks based on tool descriptions           │
└────────────────────────────────────────────────────────────────┘

Files Changed

  • apps/sim/app/api/workflows/[id]/export-service/route.ts - API endpoint (refactored to 161 lines)
  • apps/sim/app/api/workflows/[id]/export-service/validate.ts - Workflow validation
  • apps/sim/app/api/workflows/[id]/export-service/transpile.ts - JS to Python transpilation
  • apps/sim/app/api/workflows/[id]/export-service/generate-zip.ts - ZIP generation
  • apps/sim/app/api/workflows/[id]/export-service/templates/ - 16 Python template files
  • apps/sim/app/api/workflows/[id]/export-service/route.test.ts - 13 unit tests
  • apps/sim/app/workspace/.../hooks/use-export-service.ts - React hook
  • apps/sim/app/workspace/.../context-menu/context-menu.tsx - UI menu
  • apps/sim/app/workspace/.../workflow-item/workflow-item.tsx - UI wiring
  • README.md - Updated with comprehensive export documentation

Testing

cd apps/sim && bun run vitest run "export-service"
# 13 tests passing

Usage

  1. Right-click workflow in sidebar
  2. Select "Export as Service"
  3. Extract ZIP and configure .env with API keys
  4. Optionally set WORKSPACE_DIR for local file operations
  5. Optionally set ENABLE_COMMAND_EXECUTION=true for command execution
  6. Run: docker compose up or uvicorn main:app
  7. Call: POST /execute with workflow inputs

aadamsx avatar Dec 27 '25 02:12 aadamsx

@aadamsx is attempting to deploy a commit to the Sim Team on Vercel.

A member of the Team first needs to authorize it.

vercel[bot] avatar Dec 27 '25 02:12 vercel[bot]

Greptile Summary

This PR adds workflow export as standalone Python/FastAPI services. The implementation includes pre-export validation for unsupported block types and providers, JavaScript-to-Python transpilation, and comprehensive ZIP generation with all necessary runtime files.

Key Changes:

  • API endpoint (route.ts) validates workflows, transpiles JS function blocks to Python, and generates deployable service ZIP with FastAPI server, executor, Docker config, and environment files
  • React hook (use-export-service.ts) properly uses refs to avoid stale closures and integrates with notification system
  • UI integration adds "Export as Service" to context menu for single workflow selection
  • 13 comprehensive tests cover authentication, validation, provider detection, and error handling

Architecture:

  • Follows established patterns: proper import aliases, hook structure with refs for stable dependencies, TSDoc documentation
  • Security-conscious: no eval(), AST-based condition parsing, sandboxed file operations in exported Python code
  • Good error handling with user-facing notifications for validation failures

Minor Observations:

  • The 2799-line route file is very large and contains embedded Python code as template strings, which is appropriate for this use case but makes the file substantial

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk
  • Well-tested feature with comprehensive validation, proper error handling, and security measures. The code follows project patterns and includes 13 passing tests. The large route file is justified by embedded Python templates. Minor score reduction only due to the complexity and size of the implementation.
  • No files require special attention

Important Files Changed

Filename Overview
apps/sim/app/api/workflows/[id]/export-service/route.ts Adds API endpoint to export workflows as standalone Python/FastAPI services with validation, transpilation, and ZIP generation
apps/sim/app/workspace/[workspaceId]/w/hooks/use-export-service.ts React hook for exporting workflows with proper ref usage to avoid stale closures, error handling, and notification integration
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/workflow-item/workflow-item.tsx Integrates export service hook with workflow item, wires up context menu handler for single workflow exports

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as WorkflowItem
    participant Hook as useExportService
    participant API as /api/workflows/[id]/export-service
    participant DB as Database
    participant Validator as Workflow Validator
    participant Transpiler as JS→Python Transpiler
    participant ZipGen as ZIP Generator

    User->>UI: Right-click workflow
    UI->>UI: Show context menu
    User->>UI: Click "Export as Service"
    UI->>Hook: handleExportService()
    Hook->>Hook: Check isExportingRef
    Hook->>Hook: setIsExporting(true)
    
    Hook->>API: GET /api/workflows/{id}/export-service
    API->>API: Authenticate user/API key
    API->>DB: Query workflow by ID
    DB-->>API: Return workflow data
    API->>API: Fetch workflow state & variables
    
    API->>Validator: validateWorkflowForExport(state)
    Validator->>Validator: Check block types
    Validator->>Validator: Check provider support
    
    alt Has unsupported blocks/providers
        Validator-->>API: Return validation errors
        API-->>Hook: 400 with error details
        Hook->>Hook: addNotification(error)
        Hook->>Hook: setIsExporting(false)
        Hook-->>User: Show error notification
    else Validation passes
        Validator-->>API: Valid workflow
        API->>Transpiler: preTranspileWorkflow(state)
        Transpiler->>Transpiler: Convert JS blocks to Python
        Transpiler-->>API: Transpiled workflow
        
        API->>ZipGen: Generate service ZIP
        ZipGen->>ZipGen: Create workflow.json
        ZipGen->>ZipGen: Create .env with API keys
        ZipGen->>ZipGen: Add Python executor files
        ZipGen->>ZipGen: Add Dockerfile & docker-compose
        ZipGen->>ZipGen: Add README.md
        ZipGen-->>API: ZIP buffer
        
        API-->>Hook: 200 with ZIP file
        Hook->>Hook: Create blob & download link
        Hook->>Hook: Trigger browser download
        Hook->>Hook: setIsExporting(false)
        Hook->>Hook: onSuccess?.()
        Hook-->>User: Download workflow-service.zip
    end

greptile-apps[bot] avatar Dec 27 '25 02:12 greptile-apps[bot]