Skip to main content

Quick Start (60 Seconds)

Get a working Conductor project instantly: Your project includes working examples of pages, workflows, and agents!

Prerequisites

You need:
  • Node.js 18+ (nodejs.org)
  • A Cloudflare account (free tier works - only needed for deployment)
Check Node.js:
node --version  # Should be 18+

Understanding Your Project

The init command creates a complete, ready-to-run project:
my-conductor-app/
├── conductor.config.ts    # Project settings & observability
├── wrangler.toml         # Cloudflare Workers config
├── src/
│   └── index.ts          # Entry point (custom endpoints)
├── ensembles/            # 🎭 Workflows & Pages (auto-discovered)
│   ├── pages/            # HTTP endpoints that render HTML
│   │   ├── home.yaml         # GET /
│   │   ├── dashboard.yaml    # GET /dashboard
│   │   ├── login.yaml        # GET/POST /login
│   │   └── blog-post.yaml    # GET /blog/:slug
│   ├── api/              # JSON API endpoints
│   │   └── users.yaml
│   └── hello-world.yaml  # CLI workflow example
├── agents/               # 🤖 Agents (auto-discovered)
│   ├── hello/
│   │   ├── agent.yaml        # Agent configuration
│   │   └── index.ts          # Agent implementation
│   └── docs-*/           # Documentation agent examples
├── docs/                 # 📄 Markdown documentation (auto-discovered)
│   └── getting-started.md
└── tests/                # ✅ Test files
    └── basic.test.ts

Explore the Examples

Your project includes working examples for all major features.

Try the Example Pages

Start the dev server:
Dev Container Users: Add --ip 0.0.0.0 to bind to all interfaces:
npx wrangler dev --local-protocol http --ip 0.0.0.0
Local Development: Use the standard command:
npx wrangler dev --local-protocol http
Visit these URLs:

Run the Tests

pnpm test
All tests should pass! The template includes examples of:
  • Ensemble execution
  • Agent testing
  • Error handling

Your First Page

Let’s create a simple page using an ensemble with an HTTP trigger. Step 1: Create the ensemble file Create ensembles/hello.yaml:
name: hello-page
description: Simple hello world page

trigger:
  - type: http
    path: /hello
    methods: [GET]
    public: true

flow:
  - operation: html
    config:
      templateEngine: liquid
      template: |
        <!DOCTYPE html>
        <html>
          <head>
            <title>Hello Page</title>
          </head>
          <body>
            <h1>Hello from Conductor!</h1>
            <p>This page was auto-discovered.</p>
            <p>Current time: {{ "now" | date: "%Y-%m-%d %H:%M:%S" }}</p>
          </body>
        </html>

output:
  format: html
  rawBody: ${html.output}
Step 2: Rebuild
pnpm run build
The dev server will automatically reload. Step 3: Visit Open http://localhost:8787/hello

Add Dynamic Data

Make your page dynamic by adding an agent that fetches data. Create ensembles/hello-dynamic.yaml:
name: hello-dynamic
description: Hello page with dynamic data

trigger:
  - type: http
    path: /hello-dynamic
    methods: [GET]
    public: true

agents:
  - name: get_data
    operation: code
    config:
      handler: |
        export default async function({ input, ctx }) {
          return {
            message: 'Hello from the handler!',
            timestamp: new Date().toISOString(),
            userAgent: input.headers?.['user-agent'] || 'Unknown'
          };
        }

flow:
  - agent: get_data

  - operation: html
    config:
      templateEngine: liquid
      template: |
        <!DOCTYPE html>
        <html>
          <head>
            <title>Hello Page</title>
          </head>
          <body>
            <h1>{{ message }}</h1>
            <p>Timestamp: {{ timestamp }}</p>
            <p>Your browser: {{ userAgent }}</p>
          </body>
        </html>
      data:
        message: ${get_data.output.message}
        timestamp: ${get_data.output.timestamp}
        userAgent: ${get_data.output.userAgent}

output:
  format: html
  rawBody: ${html.output}
Rebuild and refresh - your dynamic data now appears in the page!

Your First Workflow

The template includes ensembles/hello-world.yaml. Let’s explore it:
name: hello-world
description: Simple greeting workflow

trigger:
  - type: cli
    command: hello

agents:
  - name: hello
    operation: code

flow:
  - agent: hello

output:
  greeting: ${hello.output.message}
This workflow calls the hello agent (from agents/examples/hello/) and returns its output.

Create a New Ensemble

Create ensembles/my-workflow.yaml:
name: my-workflow
description: Custom greeting with timestamp

trigger:
  - type: cli
    command: greet

agents:
  # Call existing hello agent
  - name: greeter
    operation: code
    config:
      handler: hello  # Reference to agents/examples/hello/

flow:
  - agent: greeter

output:
  greeting: ${greeter.output.message}
  timestamp: ${Date.now()}

Execute from a Page

Create an ensemble that renders the workflow result as HTML: Create ensembles/workflow-demo.yaml:
name: workflow-demo
description: Display workflow result as a page

trigger:
  - type: http
    path: /workflow
    methods: [GET]
    public: true

agents:
  - name: greeter
    operation: code
    config:
      handler: |
        export default async function({ input }) {
          return {
            message: 'Hello from the workflow!',
            timestamp: new Date().toISOString()
          };
        }

flow:
  - agent: greeter

  - operation: html
    config:
      templateEngine: liquid
      template: |
        <!DOCTYPE html>
        <html>
          <head>
            <title>Workflow Demo</title>
          </head>
          <body>
            <h1>Workflow Result</h1>
            <p>{{ greeting }}</p>
            <p>Timestamp: {{ timestamp }}</p>
          </body>
        </html>
      data:
        greeting: ${greeter.output.message}
        timestamp: ${greeter.output.timestamp}

output:
  format: html
  rawBody: ${html.output}
Visit http://localhost:8787/workflow - your ensemble runs on every page load!

Project Configuration

wrangler.toml

The init command creates a properly configured wrangler.toml:
name = "my-conductor-project"
main = "dist/index.mjs"  # Built output, not source!
compatibility_date = "2025-10-29"
compatibility_flags = ["nodejs_compat"]

[build]
command = "pnpm run build"
watch_dirs = ["src", "agents", "ensembles", "docs"]
Important: Conductor uses Vite/Rolldown to build your project. The output is dist/index.mjs, not src/index.ts.

conductor.config.ts

This file controls project settings, observability, and API execution controls. Use defineConfig() for full TypeScript autocomplete:
import { defineConfig } from '@ensemble-edge/conductor';

export default defineConfig({
  name: 'my-conductor-project',
  version: '1.0.0',

  // Documentation UI settings
  docs: {
    ui: 'stoplight',
    cache: { enabled: true, ttl: 3600 }
  },

  // Observability
  observability: {
    logging: { enabled: true, level: 'info' },
    metrics: { enabled: true }
  },

  // API execution controls (optional)
  api: {
    execution: {
      // When true, agents/ensembles must have apiExecutable: true
      agents: { requireExplicit: false },
      ensembles: { requireExplicit: false }
    }
  }
});
The defineConfig() helper provides TypeScript autocomplete and validation for all configuration options.
Note: Authentication is configured per-route in each ensemble’s trigger: config using public: true/false. See the examples above.

Deploy to Cloudflare

Step 1: Login to Cloudflare

npx wrangler login
This opens your browser to authorize Wrangler.

Step 2: Build

pnpm run build

Step 3: Deploy

npx wrangler deploy
Output:
Published my-conductor-app (0.5 sec)
  https://my-conductor-app.your-subdomain.workers.dev
Your app is now live at the edge in 300+ cities worldwide! Test it:
curl https://my-conductor-app.your-subdomain.workers.dev/hello

Development Workflow

# Start dev server (with network binding)
npx wrangler dev --local-protocol http

# Run tests
pnpm test

# Build for production
pnpm run build

# Deploy
npx wrangler deploy

# View live logs
npx wrangler tail

# Check deployments
npx wrangler deployments list

Troubleshooting

Problem: Template tests fail with TypeError: this.ctx.waitUntil is not a functionFix: The ExecutionContext mock in tests/basic.test.ts is already fixed in v1.8.0. If you see this error, update the mock:
// Correct mock (should already be in template)
const ctx = {
  waitUntil: (promise: Promise<any>) => promise,
  passThroughOnException: () => {}
} as ExecutionContext;
Problem: wrangler dev starts but all requests hang indefinitelyFix: Use the --local-protocol http flag:
npx wrangler dev --local-protocol http
This properly binds network access for the Workers runtime.
Problem: Created a new ensemble or agent but it returns 404Fix: Trigger a rebuild. Ensembles and agents are discovered at build time:
pnpm run build
Or with wrangler running, the file watcher should auto-rebuild.
Problem: Routes with parameters like /blog/:slug are not workingStatus: Fixed in v1.8.0! Dynamic route parameters now work correctly.Make sure your ensemble has the trigger configured properly:
trigger:
  - type: http
    path: /blog/:slug  # Correct - at root level
    methods: [GET]
    public: true
Not nested in config:
config:
  trigger:  # Wrong! trigger belongs at root level
    - type: http
      path: /blog/:slug
Problem: Build fails after updating wrangler.toml or package.jsonFix: Clean rebuild:
rm -rf dist node_modules
pnpm install
pnpm run build
Problem: Build error about virtual moduleFix: This is a Vite virtual module created at build time. Make sure:
  1. ensembles/ directory exists
  2. Vite config is correct (should be in template)
  3. Clean rebuild: rm -rf dist && pnpm run build

What’s Included in the Template

The init command creates:

✅ Working Examples

  • 10+ example ensembles showing static, dynamic, forms, and SSR patterns
  • Multiple workflow ensembles demonstrating different trigger types
  • 1 hello agent showing custom code operations
  • Multiple doc agents for various operation types

✅ Development Tools

  • Vitest for testing with working examples
  • TypeScript configured correctly
  • Vite for fast builds with HMR
  • ESLint & Prettier for code quality

✅ Production Ready

  • Authentication configured in conductor.config.ts
  • Caching rules for optimal performance
  • Error handling with custom 404 page
  • Wrangler config ready for deployment

✅ Documentation

  • README.md with project overview
  • Inline comments explaining key concepts
  • Example code for common patterns

Next Steps

Your First Website

Learn how to build web applications

Your First Agent

Create custom reusable agents

Your First Ensemble

Build complex workflows

Operations Reference

Explore all available operations

Alternative: Manual Setup (Advanced)

If you need to integrate Conductor into an existing Cloudflare Workers project:

Step 1: Create Worker

npm create cloudflare@latest my-conductor-app
Select: “Hello World” Worker, TypeScript: Yes

Step 2: Install Conductor

cd my-conductor-app
pnpm add @ensemble-edge/conductor

Step 3: Update wrangler.toml

name = "my-conductor-app"
main = "dist/index.mjs"  # Important: build output!
compatibility_date = "2025-10-29"
compatibility_flags = ["nodejs_compat"]

[build]
command = "pnpm run build"
watch_dirs = ["src", "ensembles", "agents", "docs"]

Step 4: Add Vite Config

Create vite.config.ts:
import { defineConfig } from 'vite';
import { cloudflareWorker } from '@ensemble-edge/conductor/vite';

export default defineConfig({
  plugins: [
    cloudflareWorker({
      ensemblesDir: './ensembles',
      agentsDir: './agents',
      docsDir: './docs',
    }),
  ],
  build: {
    outDir: 'dist',
    lib: {
      entry: './src/index.ts',
      formats: ['es'],
      fileName: 'index',
    },
    rollupOptions: {
      external: ['node:async_hooks'],
    },
  },
});

Step 5: Create Directories

mkdir -p ensembles agents docs tests

Step 6: Update package.json

{
  "scripts": {
    "build": "vite build",
    "dev": "wrangler dev --local-protocol http",
    "deploy": "pnpm run build && wrangler deploy",
    "test": "vitest run"
  }
}
Note: Manual setup is error-prone and requires more configuration. The init command is strongly recommended.

Tips & Best Practices

  1. Always use —local-protocol http with wrangler dev to avoid network binding issues
  2. Rebuild after adding files - Ensembles and agents are discovered at build time
  3. Start with examples - Modify the included hello examples before creating new ones
  4. Test locally first - pnpm test runs your test suite instantly
  5. Check logs - npx wrangler tail shows real-time production logs
  6. Use git - The template includes .gitignore configured correctly
  7. Read the generated README.md - It includes project-specific guidance