133 lines
4.7 KiB
TypeScript
133 lines
4.7 KiB
TypeScript
/**
|
|
* Example 10 — Task Retry with Exponential Backoff
|
|
*
|
|
* Demonstrates `maxRetries`, `retryDelayMs`, and `retryBackoff` on task config.
|
|
* When a task fails, the framework automatically retries with exponential
|
|
* backoff. The `onProgress` callback receives `task_retry` events so you can
|
|
* log retry attempts in real time.
|
|
*
|
|
* Scenario: a two-step pipeline where the first task (data fetch) is configured
|
|
* to retry on failure, and the second task (analysis) depends on it.
|
|
*
|
|
* Run:
|
|
* npx tsx examples/10-task-retry.ts
|
|
*
|
|
* Prerequisites:
|
|
* ANTHROPIC_API_KEY env var must be set.
|
|
*/
|
|
|
|
import { OpenMultiAgent } from '../src/index.js'
|
|
import type { AgentConfig, OrchestratorEvent } from '../src/types.js'
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Agents
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const fetcher: AgentConfig = {
|
|
name: 'fetcher',
|
|
model: 'claude-sonnet-4-6',
|
|
systemPrompt: `You are a data-fetching agent. When given a topic, produce a short
|
|
JSON summary with 3-5 key facts. Output ONLY valid JSON, no markdown fences.
|
|
Example: {"topic":"...", "facts":["fact1","fact2","fact3"]}`,
|
|
maxTurns: 2,
|
|
}
|
|
|
|
const analyst: AgentConfig = {
|
|
name: 'analyst',
|
|
model: 'claude-sonnet-4-6',
|
|
systemPrompt: `You are a data analyst. Read the fetched data from shared memory
|
|
and produce a brief analysis (3-4 sentences) highlighting trends or insights.`,
|
|
maxTurns: 2,
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Progress handler — watch for task_retry events
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function handleProgress(event: OrchestratorEvent): void {
|
|
const ts = new Date().toISOString().slice(11, 23)
|
|
|
|
switch (event.type) {
|
|
case 'task_start':
|
|
console.log(`[${ts}] TASK START "${event.task}" (agent: ${event.agent})`)
|
|
break
|
|
case 'task_complete':
|
|
console.log(`[${ts}] TASK DONE "${event.task}"`)
|
|
break
|
|
case 'task_retry': {
|
|
const d = event.data as { attempt: number; maxAttempts: number; error: string; nextDelayMs: number }
|
|
console.log(`[${ts}] TASK RETRY "${event.task}" — attempt ${d.attempt}/${d.maxAttempts}, next in ${d.nextDelayMs}ms`)
|
|
console.log(` error: ${d.error.slice(0, 120)}`)
|
|
break
|
|
}
|
|
case 'error':
|
|
console.log(`[${ts}] ERROR "${event.task}" agent=${event.agent}`)
|
|
break
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Orchestrator + team
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const orchestrator = new OpenMultiAgent({
|
|
defaultModel: 'claude-sonnet-4-6',
|
|
onProgress: handleProgress,
|
|
})
|
|
|
|
const team = orchestrator.createTeam('retry-demo', {
|
|
name: 'retry-demo',
|
|
agents: [fetcher, analyst],
|
|
sharedMemory: true,
|
|
})
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Tasks — fetcher has retry config, analyst depends on it
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const tasks = [
|
|
{
|
|
title: 'Fetch data',
|
|
description: 'Fetch key facts about the adoption of TypeScript in open-source projects as of 2024. Output a JSON object with a "topic" and "facts" array.',
|
|
assignee: 'fetcher',
|
|
// Retry config: up to 2 retries, 500ms base delay, 2x backoff (500ms, 1000ms)
|
|
maxRetries: 2,
|
|
retryDelayMs: 500,
|
|
retryBackoff: 2,
|
|
},
|
|
{
|
|
title: 'Analyze data',
|
|
description: 'Read the fetched data from shared memory and produce a 3-4 sentence analysis of TypeScript adoption trends.',
|
|
assignee: 'analyst',
|
|
dependsOn: ['Fetch data'],
|
|
// No retry — if analysis fails, just report the error
|
|
},
|
|
]
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Run
|
|
// ---------------------------------------------------------------------------
|
|
|
|
console.log('Task Retry Example')
|
|
console.log('='.repeat(60))
|
|
console.log('Pipeline: fetch (with retry) → analyze')
|
|
console.log(`Retry config: maxRetries=2, delay=500ms, backoff=2x`)
|
|
console.log('='.repeat(60))
|
|
console.log()
|
|
|
|
const result = await orchestrator.runTasks(team, tasks)
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Summary
|
|
// ---------------------------------------------------------------------------
|
|
|
|
console.log('\n' + '='.repeat(60))
|
|
console.log(`Overall success: ${result.success}`)
|
|
console.log(`Tokens — input: ${result.totalTokenUsage.input_tokens}, output: ${result.totalTokenUsage.output_tokens}`)
|
|
|
|
for (const [name, r] of result.agentResults) {
|
|
const icon = r.success ? 'OK ' : 'FAIL'
|
|
console.log(` [${icon}] ${name}`)
|
|
console.log(` ${r.output.slice(0, 200)}`)
|
|
}
|