Skip to main content
Every agent uses operations to do work. Each operation does one thing well.

Core Operations

Documentation: The docs/ directory is a first-class component for API documentation. See Building Documentation.

Operation Basics

Declaration

Operations are declared in agents:
agent: my-agent

operations:
  - name: generate-text
    operation: think
    config:
      provider: openai
      model: gpt-4o-mini
      prompt: ${input.text}

  - name: process
    operation: code
    config:
      script: scripts/uppercase-text
    input:
      text: ${generate-text.output}
// scripts/uppercase-text.ts
import type { AgentExecutionContext } from '@ensemble-edge/conductor'

export default function uppercaseText(context: AgentExecutionContext) {
  const { text } = context.input
  return { result: text.toUpperCase() }
}

Execution

Operations run when the agent executes:
const result = await conductor.executeAgent('my-agent', { text: 'hello' });
// result.output contains the final output

Chaining

Operations reference each other’s outputs:
operations:
  - name: step1
    operation: http
    config:
      url: https://api.example.com/data

  - name: step2
    operation: think
    config:
      prompt: Analyze: ${step1.output.body}

  - name: step3
    operation: code
    config:
      script: scripts/combine-results
    input:
      analysis: ${step2.output}
      rawData: ${step1.output.body}
// scripts/combine-results.ts
import type { AgentExecutionContext } from '@ensemble-edge/conductor'

export default function combineResults(context: AgentExecutionContext) {
  const { analysis, rawData } = context.input
  return {
    analysis,
    raw_data: rawData
  }
}

Operation Categories

1. Compute Operations

Execute logic and transform data. think - AI reasoning:
- name: analyze
  operation: think
  config:
    provider: openai
    model: gpt-4o
    prompt: Analyze this data: ${input.data}
code - JavaScript/TypeScript:
- name: transform
  operation: code
  config:
    script: scripts/transform-data
  input:
    data: ${input.data}
// scripts/transform-data.ts
import type { AgentExecutionContext } from '@ensemble-edge/conductor'

export default function transformData(context: AgentExecutionContext) {
  const { data } = context.input
  return { transformed: data.map((x: number) => x * 2) }
}

2. Data Operations

Access and manipulate data stores. storage - All Cloudflare storage:
# KV
- name: cache-get
  operation: storage
  config:
    type: kv
    action: get
    key: result-${input.query}

# D1
- name: query-db
  operation: data
  config:
    backend: d1
    binding: DB
    operation: query
    sql: SELECT * FROM users WHERE id = ?
    params: [${input.user_id}]

# R2
- name: get-file
  operation: storage
  config:
    type: r2
    action: get
    key: documents/${input.filename}

# Vectorize
- name: search-vectors
  operation: data
  config:
    backend: vectorize
    binding: VECTORIZE
    operation: query
    vector: ${embed.output}
    topK: 5

3. Communication Operations

Send messages and notifications. http - HTTP requests:
- name: fetch-data
  operation: http
  config:
    url: https://api.example.com/data
    method: POST
    headers:
      Authorization: Bearer ${env.API_KEY}
    body:
      query: ${input.query}
email - Send emails:
- name: send-notification
  operation: email
  config:
    to: ${input.recipient}
    subject: Your report is ready
    body: ${generate-report.output}
sms - Send SMS:
- name: send-alert
  operation: sms
  config:
    to: ${input.phone}
    body: Alert: ${input.message}

4. Presentation Operations

Render content for users. html - HTML rendering:
- name: render-page
  operation: html
  config:
    template: dashboard
    data:
      user: ${fetch-user.output}
      stats: ${fetch-stats.output}
pdf - PDF generation:
- name: generate-pdf
  operation: pdf
  config:
    html: ${render-report.output}
    filename: report-${input.id}.pdf
form - Form generation:
- name: contact-form
  operation: form
  config:
    fields:
      - name: email
        type: email
        required: true
      - name: message
        type: textarea
        required: true
    csrf: true

5. Async Operations

Process background jobs and messages. queue - Message queue processing:
- name: process-job
  operation: queue
  config:
    action: send
    queue: background-jobs
    body:
      task: ${input.task}
      priority: high

6. Extension Operations

Extend functionality with external tools. tools - MCP tools and skills:
- name: use-tool
  operation: tools
  config:
    tool: search-web
    params:
      query: ${input.query}

Operation Features

Conditional Execution

Skip operations based on conditions:
operations:
  - name: check-cache
    operation: storage
    config:
      type: kv
      action: get
      key: result-${input.query}

  # Only run if cache miss
  - name: generate
    operation: think
    condition: ${check-cache.output.value === null}
    config:
      provider: openai
      model: gpt-4o-mini
      prompt: ${input.query}

Caching

Cache operation results:
operations:
  - name: expensive-operation
    operation: think
    config:
      provider: openai
      model: gpt-4
      prompt: ${input.text}
    cache:
      ttl: 3600  # 1 hour
      key: ai-${input.text}  # Custom cache key

Retry Logic

Automatic retries on failure:
operations:
  - name: flaky-api
    operation: http
    config:
      url: https://api.example.com/data
    retry:
      maxAttempts: 3
      backoff: exponential
      initialDelay: 1000

Parallel Execution

Operations without dependencies run in parallel:
operations:
  # These 3 run in parallel
  - name: fetch-a
    operation: http
    config:
      url: https://api-a.com/data

  - name: fetch-b
    operation: http
    config:
      url: https://api-b.com/data

  - name: fetch-c
    operation: http
    config:
      url: https://api-c.com/data

  # This waits for all 3 to complete
  - name: merge
    operation: code
    config:
      script: scripts/merge-api-responses
    input:
      fetchA: ${fetch-a.output.body}
      fetchB: ${fetch-b.output.body}
      fetchC: ${fetch-c.output.body}
// scripts/merge-api-responses.ts
import type { AgentExecutionContext } from '@ensemble-edge/conductor'

export default function mergeApiResponses(context: AgentExecutionContext) {
  const { fetchA, fetchB, fetchC } = context.input
  return {
    a: fetchA,
    b: fetchB,
    c: fetchC
  }
}

Operation Reference

Common Configuration

All operations support:
operations:
  - name: my-operation
    operation: think
    config:
      # Operation-specific config
    condition: ${some.condition}  # Optional: when to run
    cache:
      ttl: 3600  # Optional: cache duration
      key: custom-key  # Optional: cache key
    retry:
      maxAttempts: 3  # Optional: retry count
      backoff: exponential  # Optional: backoff strategy
    timeout: 30000  # Optional: timeout in ms

Output Access

Access operation outputs using template syntax:
${operation-name.output}          # Full output
${operation-name.output.field}    # Specific field
${operation-name.executed}        # true if ran
${operation-name.failed}          # true if failed
${operation-name.cached}          # true if from cache
${operation-name.duration}        # Execution time in ms

Best Practices

  1. Use the Right Operation - Each operation is optimized for its use case
  2. Cache Expensive Operations - Especially AI and HTTP calls
  3. Handle Failures - Use conditions and retry logic
  4. Optimize for Parallel - Don’t create unnecessary dependencies
  5. Keep Operations Simple - Single responsibility per operation
  6. Use Built-in Features - Leverage caching, retry, and conditions
  7. Monitor Performance - Track operation execution times
  8. Test Thoroughly - Unit test each operation

Performance Tips

1. Parallel Execution

# Bad: Sequential (slow)
operations:
  - name: step1
    operation: http
    config:
      url: https://api-a.com
  - name: step2
    operation: http
    config:
      url: https://api-b.com
      data: ${step1.output}  # Creates dependency

# Good: Parallel (fast)
operations:
  - name: step1
    operation: http
    config:
      url: https://api-a.com
  - name: step2
    operation: http
    config:
      url: https://api-b.com
  - name: merge
    operation: code
    config:
      script: scripts/merge-step-outputs
    input:
      stepA: ${step1.output}
      stepB: ${step2.output}
// scripts/merge-step-outputs.ts
import type { AgentExecutionContext } from '@ensemble-edge/conductor'

export default function mergeStepOutputs(context: AgentExecutionContext) {
  const { stepA, stepB } = context.input
  return {
    a: stepA,
    b: stepB
  }
}

2. Conditional Execution

# Bad: Always runs expensive operation
operations:
  - name: expensive-ai
    operation: think
    config:
      provider: openai
      model: gpt-4
      prompt: ${input.text}

# Good: Skip if cached
operations:
  - name: check-cache
    operation: storage
    config:
      type: kv
      action: get
      key: ai-${input.text}

  - name: expensive-ai
    operation: think
    condition: ${check-cache.output.value === null}
    config:
      provider: openai
      model: gpt-4
      prompt: ${input.text}

3. Operation Caching

# Cache at operation level
operations:
  - name: scrape-website
    operation: http
    config:
      url: ${input.url}
    cache:
      ttl: 86400  # Cache for 24 hours
      key: scrape-${input.url}

Next Steps