API Orchestration Playbook
Call multiple APIs, handle auth, retries, and transform responses. Build API workflows that just work.Basic Pattern
Copy
ensemble: api-workflow
agents:
# Call APIs in sequence or parallel
- name: api-1
agent: fetcher
inputs:
url: https://api1.example.com/data
- name: api-2
agent: fetcher
inputs:
url: https://api2.example.com/data
body: ${api-1.output.body}
# Transform and combine
- name: combine
agent: transformer
inputs:
data:
source1: ${api-1.output.body}
source2: ${api-2.output.body}
OAuth Flow
Copy
ensemble: oauth-api-call
agents:
# Get access token
- name: get-token
agent: fetcher
inputs:
url: https://auth.example.com/oauth/token
method: POST
body:
grant_type: client_credentials
client_id: ${env.CLIENT_ID}
client_secret: ${env.CLIENT_SECRET}
cache:
ttl: 3600
key: oauth-token
# Use token
- name: api-call
agent: fetcher
inputs:
url: https://api.example.com/data
headers:
Authorization: Bearer ${get-token.output.body.access_token}
Parallel API Aggregation
Copy
ensemble: aggregate-apis
agents:
# Call multiple APIs in parallel
- name: weather
agent: fetcher
inputs:
url: https://api.weather.com/current?city=${input.city}
- name: news
agent: fetcher
inputs:
url: https://api.news.com/local?city=${input.city}
- name: events
agent: fetcher
inputs:
url: https://api.events.com/upcoming?city=${input.city}
# Combine results
- name: combine
operation: code
config:
code: |
return {
city: ${input.city},
weather: ${weather.output.body},
news: ${news.output.body.articles}.slice(0, 5),
events: ${events.output.body.events}.slice(0, 10)
};
Webhook Handling
Copy
ensemble: process-webhook
agents:
# Validate webhook signature
- name: validate
operation: code
config:
code: |
const crypto = require('crypto');
const signature = crypto
.createHmac('sha256', ${env.WEBHOOK_SECRET})
.update(JSON.stringify(${input.body}))
.digest('hex');
return {
valid: signature === ${input.headers['x-signature']}
};
# Process if valid
- name: process
condition: ${validate.output.valid}
operation: code
config:
code: |
// Process webhook data
return { processed: true };
# Forward to internal API
- name: forward
condition: ${process.executed}
agent: fetcher
inputs:
url: ${env.INTERNAL_API_URL}
method: POST
body: ${input.body}
Rate Limiting
Copy
ensemble: rate-limited-api
agents:
# Check rate limit
- name: check-limit
operation: storage
config:
type: kv
action: get
key: rate-limit-${input.user_id}
# Allow if under limit
- name: allow
condition: ${!check-limit.output || check-limit.output.count < 100}
agent: fetcher
inputs:
url: https://api.example.com/data
# Update counter
- name: update-limit
condition: ${allow.executed}
operation: storage
config:
type: kv
action: put
key: rate-limit-${input.user_id}
value:
count: ${(check-limit.output?.count || 0) + 1}
reset_at: ${Date.now() + 3600000}
ttl: 3600
# Reject if over limit
- name: reject
condition: ${check-limit.output && check-limit.output.count >= 100}
operation: code
config:
code: |
return {
error: 'Rate limit exceeded',
retry_after: ${check-limit.output.reset_at}
};
Circuit Breaker
Copy
ensemble: circuit-breaker
agents:
# Check circuit state
- name: check-circuit
operation: storage
config:
type: kv
action: get
key: circuit-${input.service}
# Call if circuit closed
- name: call-api
condition: ${!check-circuit.output || check-circuit.output.state !== 'open'}
agent: fetcher
inputs:
url: ${input.url}
retry:
maxAttempts: 3
# Open circuit on failure
- name: open-circuit
condition: ${call-api.failed}
operation: storage
config:
type: kv
action: put
key: circuit-${input.service}
value:
state: open
opened_at: ${Date.now()}
ttl: 60
# Use fallback if circuit open
- name: fallback
condition: ${check-circuit.output?.state === 'open'}
operation: code
config:
code: |
return {
error: 'Service unavailable',
fallback: true
};

