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

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