Skip to main content

Quick Start

Get started with Moco in 5 minutes! This guide will walk you through creating and running your first workflow.

Prerequisites

  • Python 3.10 or higher
  • Node.js 18 or higher (for CLI tools)
  • Docker (optional, for Temporal.io runtime)

Installation

1. Clone the Repository

git clone https://github.com/moco-workflow/moco.git
cd moco-workspace

2. Initialize Submodules

Moco uses git submodules for some components:

git submodule update --init --recursive

3. Set Up Python Environment

The workspace uses a shared virtual environment:

# The virtual environment should already exist at .venv/
# Install dependencies
.venv/bin/pip install -r moco-core/requirements.txt
.venv/bin/pip install -e moco-core/

4. Install CLI Tools (Optional)

cd moco-tools
npm install
npm run build
npm run pack

# Install globally
npm i -g moco-lib-0.1.0.tgz moco-cli-0.1.0.tgz

Your First Workflow

Create a file called hello-world.yaml:

wfspec_name: hello-world
wfspec_version: 1.0.0

context:
greeting: "Hello"

input_data:
name: "World"

output_name: message

body:
transform:
output_data:
- message: "{{ greeting }}, {{ name }}!"

Running the Workflow

Using Python

Create a Python script run_workflow.py:

import asyncio
from moco.core.workflow.client.client import WorkflowClient
from moco.core.workflow.runtime.runtime_builder import RuntimeBuilder

async def main():
# Build in-memory runtime
runtime_builder = RuntimeBuilder()
runtime = runtime_builder.build_in_memory_runtime()

# Create client
client = WorkflowClient(runtime)

# Load and execute workflow
with open('hello-world.yaml', 'r') as f:
wfspec_yaml = f.read()

result = await client.execute_workflow_from_yaml(
wfspec_yaml=wfspec_yaml,
input_data={'name': 'Moco'}
)

print(f"Result: {result}")

if __name__ == "__main__":
asyncio.run(main())

Run it:

.venv/bin/python run_workflow.py

Output:

Result: Hello, Moco!

Using CLI (if installed)

moco run hello-world.yaml --input '{"name": "Moco"}'

Next Example: Data Processing

Create process-data.yaml:

wfspec_name: process-data
wfspec_version: 1.0.0

input_data:
numbers: [1, 2, 3, 4, 5]

output_name: result

body:
sequence:
elements:
# Calculate statistics
- transform:
output_data:
- total: "{{ sum(numbers) }}"
- average: "{{ sum(numbers) / len(numbers) }}"
- max_value: "{{ max(numbers) }}"
- min_value: "{{ min(numbers) }}"

# Double each number
- iteration:
iter_type: sequence
input_data: "{{ numbers }}"
body:
transform:
output_data:
- doubled: "{{ iter_item * 2 }}"

# Create result
- transform:
output_data:
- result:
original: "{{ numbers }}"
stats:
total: "{{ total }}"
average: "{{ average }}"
max: "{{ max_value }}"
min: "{{ min_value }}"

Using Activities

Activities allow you to interact with external systems. Here's an example with HTTP requests:

wfspec_name: fetch-data
wfspec_version: 1.0.0

input_data:
api_url: https://api.github.com/users/github

output_name: user_info

body:
sequence:
elements:
# Fetch user data
- activity:
type: builtin.http_request
input_data:
method: GET
url: "{{ api_url }}"
headers:
Accept: application/json
timeout_sec: 30
output_name: response

# Extract relevant info
- transform:
output_data:
- user_info:
name: "{{ response.get('name', 'Unknown') }}"
company: "{{ response.get('company', 'N/A') }}"
followers: "{{ response.get('followers', 0) }}"

Running Tests

Moco includes comprehensive tests:

# Run all tests
.venv/bin/pytest moco-core/

# Run specific tests
.venv/bin/pytest moco-core/tests/unit/
.venv/bin/pytest moco-core/tests/integration/

Using Temporal.io Runtime (Advanced)

For production workloads, use the Temporal.io runtime:

1. Start Infrastructure

docker compose -f docker-compose-env.yml up -d

This starts:

  • Temporal server (localhost:8234 for UI, localhost:7234 for gRPC)
  • PostgreSQL
  • Kafka
  • RabbitMQ

2. Set Environment Variables

export MOCO_RUNTIME_TYPE=temporal
export MOCO_TEMPORALIO_ENDPOINT=localhost:7234
export MOCO_TEMPORALIO_NAMESPACE=moco
export MOCO_TEMPORALIO_TASK_QUEUE=default

3. Start a Worker

.venv/bin/python -m moco_worker.main

4. Execute Workflow

Your client code remains the same, but now workflows run on Temporal:

# The RuntimeBuilder will automatically use Temporal based on environment variables
runtime = runtime_builder.build_runtime()

Next Steps

Now that you've run your first workflows, explore: