Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ensemble.ai/llms.txt

Use this file to discover all available pages before exploring further.

The html operation renders HTML templates using template engines. It’s typically used in ensemble flows when an HTTP trigger needs to return server-rendered HTML. Note: The html operation is for rendering only. HTTP routing, authentication, CORS, and middleware are configured in the trigger: section using type: http.

HTTP Middleware

When using the html operation with HTTP triggers, you can add Hono middleware for cross-cutting concerns like logging, compression, and security headers:
name: blog-post
trigger:
  - type: http
    path: /blog/:slug
    methods: [GET]
    public: true

    # Add middleware for performance and security
    middleware:
      - logger          # Log requests
      - compress        # Gzip compression
      - secure-headers  # Security headers
      - etag            # Cache validation

    responses:
      html: {enabled: true}

agents:
  - name: render-page
    operation: html
    config:
      template: |
        <article>
          <h1>{{ title }}</h1>
          <div>{{ content }}</div>
        </article>
Middleware executes before the HTML rendering, allowing you to add:
  • Request/response logging (logger)
  • Response compression for faster page loads (compress)
  • Security headers (secure-headers)
  • Cache validation with ETags (etag)
  • Custom authentication and rate limiting
See the HTTP Middleware Guide for complete documentation on using middleware with HTML responses.

Usage in Ensembles with HTTP Trigger

name: blog-post
trigger:
  - type: http
    path: /blog/:slug
    methods: [GET]
    public: true
    responses:
      html: {enabled: true}
    templateEngine: liquid

flow:
  # Fetch data
  - agent: fetch-post
    input: {slug: ${input.params.slug}}

  # Render HTML
  - operation: html
    config:
      template: |
        <article>
          <h1>{{ fetch-post.title }}</h1>
          <div>{{ fetch-post.content }}</div>
        </article>
      data: ${fetch-post}

Configuration

operation: html
config:
  template: string    # HTML template with variables
  data: object       # Data to render in template
  engine: string     # Template engine (liquid, handlebars, simple)

Template Engines

Liquid (Default)

operation: html
config:
  template: |
    <h1>{{ title }}</h1>
    {% for item in items %}
      <p>{{ item.name }}</p>
    {% endfor %}
  data: ${previous-step.output}

Handlebars

operation: html
config:
  template: |
    <h1>{{title}}</h1>
    {{#each items}}
      <p>{{name}}</p>
    {{/each}}
  data: ${previous-step.output}
  engine: handlebars

Simple (String Interpolation)

operation: html
config:
  template: |
    <h1>{{title}}</h1>
    <p>{{description}}</p>
  data: ${previous-step.output}
  engine: simple

Complete Example

name: user-dashboard
trigger:
  - type: http
    path: /dashboard/:userId
    methods: [GET]
    auth:
      type: bearer
      secret: ${env.API_KEY}
    responses:
      html: {enabled: true}
    templateEngine: liquid

flow:
  # Step 1: Fetch user data
  - agent: get-user
    input: {userId: ${input.params.userId}}

  # Step 2: Fetch user stats
  - agent: get-user-stats
    input: {userId: ${input.params.userId}}

  # Step 3: Render HTML dashboard
  - operation: html
    config:
      template: |
        <!DOCTYPE html>
        <html>
        <head>
          <title>Dashboard - {{ get-user.name }}</title>
        </head>
        <body>
          <h1>Welcome, {{ get-user.name }}</h1>
          <div class="stats">
            <p>Total Orders: {{ get-user-stats.orders }}</p>
            <p>Revenue: ${{ get-user-stats.revenue }}</p>
          </div>
        </body>
        </html>
      data:
        get-user: ${get-user}
        get-user-stats: ${get-user-stats}

Personalization with Cookies

Use cookies to personalize HTML content based on user preferences or session data:
name: personalized-page
trigger:
  - type: http
    path: /home
    methods: [GET]
    public: true
    responses:
      html: {enabled: true}

agents:
  # Check for preference cookie
  - name: get-theme
    operation: cookies
    config:
      action: get
      name: theme_preference

  # Load user session if logged in
  - name: get-session
    condition: ${input.cookies.session_id}
    operation: storage
    config:
      type: kv
      action: get
      key: session-${input.cookies.session_id}

  # Render personalized page
  - name: render
    operation: html
    config:
      template: |
        <!DOCTYPE html>
        <html data-theme="{{ theme }}">
        <head>
          <title>{% if user %}Welcome back, {{ user.name }}{% else %}Welcome{% endif %}</title>
        </head>
        <body>
          {% if user %}
            <p>Last visit: {{ user.lastVisit }}</p>
          {% else %}
            <p>Create an account for a personalized experience</p>
          {% endif %}
        </body>
        </html>
      data:
        theme: ${get-theme.output.value || 'light'}
        user: ${get-session.output.value}
Set preference cookies when users change settings:
agents:
  - name: save-theme
    operation: cookies
    config:
      action: set
      name: theme_preference
      value: ${input.body.theme}
      maxAge: 31536000  # 1 year
      purpose: personalization

Next Steps

pdf

Generate PDFs

Triggers

HTTP trigger for web routing