Skip to main content
Starter Kit - Ships with your template. You own it - modify freely.

Overview

The documentation feature provides a complete, self-hosted documentation system for your Conductor project. It automatically generates:
  • Landing page - Overview with project statistics
  • Agent documentation - Browse all agents with schemas and examples
  • Ensemble documentation - Explore workflows with triggers and flow steps
  • OpenAPI specification - Auto-generated API reference from your agents and ensembles
  • Interactive API viewer - Choose from 5 different UI renderers
  • Custom markdown pages - Add your own documentation pages
All documentation is served at /docs and updates automatically as you add or modify agents and ensembles.

Key Features

  • Zero configuration required - works out of the box
  • Multiple OpenAPI UI options (Stoplight, Redoc, Swagger, Scalar, RapiDoc)
  • Build-time generation for static deployments
  • CLI commands for docs generation
  • Customizable themes and branding
  • Folder-based API organization

Quick Start

The documentation system is pre-configured and ready to use:
  1. Start your Conductor dev server:
    ensemble conductor dev
    
  2. Visit the docs:
    http://localhost:8787/docs
    
  3. Explore the sections:
    • /docs - Landing page with overview
    • /docs/agents - List of all agents
    • /docs/agents/{name} - Agent detail pages
    • /docs/ensembles - List of all ensembles
    • /docs/ensembles/{name} - Ensemble detail pages
    • /docs/api - Interactive OpenAPI viewer
    • /docs/openapi.json - OpenAPI spec (JSON)
    • /docs/openapi.yaml - OpenAPI spec (YAML)

Ensembles

The documentation feature consists of two ensembles:

Serve Ensemble

File: ensembles/system/docs/serve.yaml Serves documentation pages via HTTP. Handles all /docs/* routes.
name: docs-serve
version: 1.0.0
description: |
  Serve documentation pages via HTTP.
  Provides landing page, markdown pages, agent/ensemble docs, and OpenAPI UI.

trigger:
  - type: http
    paths:
      # Landing page
      - path: /docs
        methods: [GET]
      # Reserved routes
      - path: /docs/agents
        methods: [GET]
      - path: /docs/agents/:name
        methods: [GET]
      - path: /docs/ensembles
        methods: [GET]
      - path: /docs/ensembles/:name
        methods: [GET]
      - path: /docs/api
        methods: [GET]
      - path: /docs/openapi.json
        methods: [GET]
      - path: /docs/openapi.yaml
        methods: [GET]
      # Markdown pages (catch-all)
      - path: /docs/:slug
        methods: [GET]
    public: true

flow:
  - name: render
    agent: docs
    input:
      action: ${{
        input.path == '/docs' ? 'render-landing' :
        input.path == '/docs/agents' ? 'render-agents' :
        input.path == '/docs/ensembles' ? 'render-ensembles' :
        input.path == '/docs/api' ? 'render-api' :
        input.path == '/docs/openapi.json' ? 'generate-openapi' :
        input.path == '/docs/openapi.yaml' ? 'generate-openapi' :
        input.params.name && input.path.includes('/agents/') ? 'render-agent-detail' :
        input.params.name && input.path.includes('/ensembles/') ? 'render-ensemble-detail' :
        'render-page'
      }}
      slug: ${{ input.params.slug }}
      name: ${{ input.params.name }}
      format: ${{ input.path.endsWith('.yaml') ? 'yaml' : 'json' }}
    config:
      title: API Documentation
      basePath: /docs
      ui: stoplight
      theme:
        primaryColor: '#3b82f6'
        darkMode: false
      nav:
        showReserved:
          agents: true
          ensembles: true
          api: true

output:
  # HTML responses
  - when: ${{ flow.render.output.contentType == 'text/html' }}
    status: 200
    headers:
      Cache-Control: public, max-age=300
    format: html
    body:
      content: ${{ flow.render.output.html }}

  # JSON responses (OpenAPI)
  - when: ${{ flow.render.output.specJson }}
    status: 200
    body: ${{ flow.render.output.spec }}

  # YAML responses (OpenAPI)
  - when: ${{ flow.render.output.specYaml }}
    status: 200
    format:
      type: yaml
      extract: spec
    body:
      spec: ${{ flow.render.output.specYaml }}

  # Not found
  - when: ${{ flow.render.output.error == 'not_found' }}
    status: 404
    body:
      success: false
      error: not_found
      message: ${{ flow.render.output.errorMessage }}

  # Error fallback
  - when: ${{ !flow.render.output.success }}
    status: 500
    body:
      success: false
      error: ${{ flow.render.output.error }}
      message: ${{ flow.render.output.errorMessage }}
Key Features:
  • Multi-path HTTP trigger for all documentation routes
  • Conditional output blocks for HTML, JSON, YAML
  • Caching headers for performance
  • Public access (no authentication required)

Generate Ensemble

File: ensembles/system/docs/generate.yaml Generates static documentation artifacts (OpenAPI specs, HTML pages).
name: docs-generate
version: 1.0.0
description: |
  Generate documentation artifacts (OpenAPI spec, static pages).
  Can be triggered at build time, via CLI, or on a schedule.

trigger:
  # Build-time trigger - runs during `conductor build` or deploy
  - type: build
    enabled: true
    output: ./dist/docs

  # CLI trigger - run via `conductor run docs-generate`
  - type: cli
    command: docs-generate
    description: Generate OpenAPI documentation
    options:
      - name: format
        type: string
        default: yaml
        description: Output format (json or yaml)
      - name: output
        type: string
        description: Output directory path

  # Scheduled trigger - regenerate docs periodically (disabled by default)
  - type: cron
    cron: "0 0 * * *"
    enabled: false
    metadata:
      description: Daily docs regeneration at midnight

flow:
  - name: generate
    agent: docs
    input:
      action: generate-openapi
      format: ${{ trigger.options.format || 'yaml' }}
    config:
      title: API Documentation
      description: Auto-generated API documentation

output:
  success: ${{ flow.generate.output.success }}
  spec: ${{ flow.generate.output.spec }}
  specYaml: ${{ flow.generate.output.specYaml }}
  specJson: ${{ flow.generate.output.specJson }}
  message: ${{
    trigger.type == 'build' ? 'OpenAPI spec generated for build' :
    trigger.type == 'cron' ? 'Scheduled docs regeneration complete' :
    'Documentation generated successfully'
  }}
Key Features:
  • Build trigger for static site generation
  • CLI trigger for manual generation
  • Cron trigger for scheduled updates
  • Multiple output format support
Usage Examples:
# Generate docs via CLI (default YAML format)
ensemble conductor run docs-generate

# Generate JSON format
ensemble conductor run docs-generate --format json

# Specify output directory
ensemble conductor run docs-generate --output ./docs-export

# Enable scheduled generation (edit YAML)
# Set cron trigger enabled: true

Agent Reference

Docs Agent

File: agents/system/docs/docs.ts The core documentation generation agent. Handles all rendering and OpenAPI generation logic. Operation: code Actions:
ActionDescriptionInput
render-landingRender landing page with project stats-
render-pageRender custom markdown pageslug, pages
render-agentsList all agents-
render-agent-detailAgent detail pagename
render-ensemblesList all ensembles-
render-ensemble-detailEnsemble detail pagename
render-apiOpenAPI interactive viewer-
generate-openapiGenerate OpenAPI specformat (json/yaml)
list-pagesList available markdown pagespages
Input Schema:
interface DocsInput {
  action: DocsAction
  slug?: string        // For render-page
  name?: string        // For render-agent-detail / render-ensemble-detail
  format?: 'json' | 'yaml'  // For generate-openapi
  pages?: DocsPage[]   // For render-page / list-pages
}
Output Schema:
interface DocsOutput {
  success: boolean
  html?: string
  contentType?: string
  spec?: Record<string, unknown>
  specYaml?: string
  specJson?: string
  pages?: Array<{ slug: string; title: string; order: number }>
  error?: string
  errorMessage?: string
}
Configuration:
interface DocsConfig {
  title: string                    // Site title
  description?: string             // Site description
  logo?: string                    // Logo URL
  favicon?: string                 // Favicon URL
  ui: 'stoplight' | 'redoc' | 'swagger' | 'scalar' | 'rapidoc'
  theme: {
    primaryColor: string           // Hex color (e.g., '#3b82f6')
    darkMode: boolean              // Enable dark mode
    customCss?: string             // Custom CSS injection
  }
  nav: {
    order?: string[]               // Navigation order
    hide?: string[]                // Hidden nav items
    showReserved?: {
      agents?: boolean             // Show agents section
      ensembles?: boolean          // Show ensembles section
      api?: boolean                // Show API reference
    }
  }
  basePath: string                 // Base path (e.g., '/docs')
  cache: {
    enabled: boolean
    ttl: number                    // Cache TTL in seconds
  }
}
Default Configuration:
config:
  title: API Documentation
  ui: stoplight
  theme:
    primaryColor: '#3b82f6'
    darkMode: false
  nav:
    showReserved:
      agents: true
      ensembles: true
      api: true
  basePath: /docs
  cache:
    enabled: true
    ttl: 300

OpenAPI Generation

The docs agent automatically generates OpenAPI 3.1.0 specifications by introspecting your agents and ensembles.

Generated Endpoints

Ensemble Execution:
POST /api/v1/execute/ensemble/{name}
Agent Execution:
POST /api/v1/execute/agent/{name}
Discovery:
GET /api/v1/agents
GET /api/v1/ensembles

Folder-Based Organization

The OpenAPI spec automatically organizes endpoints by folder structure:
agents/
├── system/
│   ├── fetch/          → Tag: "Agents/system"
│   └── validate/       → Tag: "Agents/system"
└── user/
    └── my-agent/       → Tag: "Agents/user"
This creates a clean sidebar structure in the API viewer.

Security Schemes

Two authentication methods are documented:
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key

Example OpenAPI Output

openapi: 3.1.0
info:
  title: API Documentation
  version: 1.0.0
  description: Auto-generated API documentation for your Conductor project.
servers:
  - url: /
    description: Current server
tags:
  - name: Discovery
    description: Agent and ensemble discovery endpoints
  - name: Agents/system
    description: Agents in system/
  - name: Ensembles/system
    description: Ensembles in system/
paths:
  /api/v1/execute/agent/fetch:
    post:
      summary: Execute fetch agent
      operationId: execute_agent_fetch
      tags: [Agents/system]
      security:
        - bearerAuth: []
        - apiKey: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [input]
              properties:
                input:
                  type: object
                config:
                  type: object

UI Options

The docs agent supports 5 different OpenAPI UI renderers. Configure via the ui config option:

Stoplight Elements (Default)

Modern, clean UI with sidebar navigation.
config:
  ui: stoplight
Features:
  • Sidebar navigation
  • Interactive try-it console
  • Code samples in multiple languages
  • Responsive design
CDN: @stoplight/elements

Redoc

Documentation-focused renderer with beautiful typography.
config:
  ui: redoc
Features:
  • Three-column layout
  • Deep linking
  • Search functionality
  • Print-friendly
CDN: cdn.redoc.ly/redoc

Swagger UI

Classic, battle-tested API explorer.
config:
  ui: swagger
Features:
  • Interactive API testing
  • Authorization support
  • Model schema viewer
  • Request validation
CDN: unpkg.com/swagger-ui-dist

Scalar

Modern, minimalist UI with dark mode.
config:
  ui: scalar
Features:
  • Beautiful design
  • Dark mode support
  • Fast rendering
  • Code generation
CDN: cdn.jsdelivr.net/npm/@scalar/api-reference

RapiDoc

Lightweight, customizable renderer.
config:
  ui: rapidoc
Features:
  • Highly customizable
  • Three render styles
  • Theme support
  • Small bundle size
CDN: unpkg.com/rapidoc

Customization

Change UI Renderer

Edit the serve.yaml ensemble:
flow:
  - name: render
    agent: docs
    config:
      ui: redoc  # Change to: stoplight, redoc, swagger, scalar, rapidoc

Customize Theme

config:
  theme:
    primaryColor: '#10b981'  # Green
    darkMode: true
    customCss: |
      .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }
      .card { box-shadow: 0 4px 6px rgba(0,0,0,0.2); }

Hide Navigation Items

config:
  nav:
    showReserved:
      agents: false      # Hide agents section
      ensembles: true
      api: true

Change Base Path

config:
  basePath: /api-docs  # Serve at /api-docs instead of /docs
Then update the trigger paths:
trigger:
  - type: http
    paths:
      - path: /api-docs
        methods: [GET]
      # ... update all paths

Add Custom Pages

Create markdown files and pass them to the agent:
flow:
  - name: load-pages
    operation: storage
    config:
      type: kv
      action: get
      key: docs-pages

  - name: render
    agent: docs
    input:
      action: render-page
      slug: getting-started
      pages: ${{ load-pages.output.value }}
Page Format:
interface DocsPage {
  slug: string         // URL slug
  title: string        // Page title
  content: string      // Markdown content
  order: number        // Display order
  frontmatter?: Record<string, unknown>
}

Customize Agent Metadata

The docs agent reads schemas from your agent YAML files:
# agents/user/my-agent/agent.yaml
name: my-agent
description: Does something amazing  # Shows in docs

schema:
  input:
    query:
      type: string
      description: Search query  # Shows in OpenAPI
  output:
    results:
      type: array

Brand Your Docs

config:
  title: Acme Corp API
  description: Official API documentation
  logo: https://example.com/logo.png
  favicon: https://example.com/favicon.ico

Disable Caching

config:
  cache:
    enabled: false
Or adjust TTL:
config:
  cache:
    enabled: true
    ttl: 600  # 10 minutes

Authentication

By default, docs are public. To add authentication:
trigger:
  - type: http
    paths:
      - path: /docs
        methods: [GET]
    public: false  # Require auth
    auth:
      type: jwt
      secret: ${env.JWT_SECRET}

Advanced Usage

Build-Time Generation

Generate static OpenAPI specs during build:
# Runs automatically during deploy
ensemble conductor build

# Output: ./dist/docs/openapi.yaml
Then serve the static file:
# In a CDN or static host
/docs/openapi.yaml → ./dist/docs/openapi.yaml

Scheduled Regeneration

Enable the cron trigger for periodic updates:
trigger:
  - type: cron
    cron: "0 */6 * * *"  # Every 6 hours
    enabled: true

Export OpenAPI Spec

# Generate and save
ensemble conductor run docs-generate --format yaml > api-spec.yaml
ensemble conductor run docs-generate --format json > api-spec.json

Programmatic Access

# Get OpenAPI spec via HTTP
curl http://localhost:8787/docs/openapi.json

# Get agent list
curl http://localhost:8787/api/v1/agents

# Get ensemble list
curl http://localhost:8787/api/v1/ensembles

Integrate with External Tools

Use the generated OpenAPI spec with:
  • Postman - Import collections
  • Insomnia - API testing
  • API Gateway - Validation rules
  • Code Generators - Client SDKs
  • Mock Servers - Testing

Custom Agent Implementation

Fork the docs agent for custom logic:
# Copy to user agents
cp -r agents/system/docs agents/user/my-docs

# Edit agents/user/my-docs/docs.ts
# Add custom rendering logic

# Update ensemble
flow:
  - agent: my-docs  # Use your custom version

Troubleshooting

Docs not loading

Check that the ensemble is valid:
ensemble conductor validate ensembles/system/docs/serve.yaml
Verify the trigger is registered:
ensemble conductor dev --verbose
# Look for: "Registered HTTP trigger: /docs"

OpenAPI spec is empty

Ensure agents have proper schemas:
# agents/user/my-agent/agent.yaml
schema:
  input:
    field: string  # Required for OpenAPI generation
  output:
    result: string

UI not rendering

Check browser console for CDN errors. The UIs load from external CDNs:
  • Stoplight: unpkg.com/@stoplight/elements
  • Redoc: cdn.redoc.ly/redoc
  • Swagger: unpkg.com/swagger-ui-dist
  • Scalar: cdn.jsdelivr.net/npm/@scalar/api-reference
  • RapiDoc: unpkg.com/rapidoc
Ensure your environment can reach these CDNs.

404 on agent/ensemble pages

Agent/ensemble names must match exactly:
/docs/agents/fetch ✓
/docs/agents/system/fetch ✗ (if name is "fetch", not "system/fetch")
Check agent registration:
curl http://localhost:8787/api/v1/agents