Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,590 changes: 1,590 additions & 0 deletions designs/0009-background-tasks.md

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions designs/0009-current-agent-loop.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<mxfile host="app.diagrams.net" agent="Claude">
<diagram name="Current Agent Loop" id="current-loop">
<mxGraphModel dx="1200" dy="800" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="10" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fontSize=14;fillColor=#e0e0e0;strokeColor=#333333;fontColor=#333333;strokeWidth=3;fontStyle=1;" value="start turn" vertex="1">
<mxGeometry height="50" width="160" x="370" y="120" as="geometry" />
</mxCell>
<mxCell id="11" edge="1" parent="1" source="10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#666666;" target="2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="2" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fontSize=14;fillColor=#e0e0e0;strokeColor=#999999;fontColor=#333333;" value="call model" vertex="1">
<mxGeometry height="50" width="160" x="370" y="230" as="geometry" />
</mxCell>
<mxCell id="6" edge="1" parent="1" source="2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#666666;" target="3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="3" parent="1" style="rhombus;whiteSpace=wrap;html=1;fontSize=14;fillColor=#e0e0e0;strokeColor=#999999;fontColor=#333333;" value="tool use?" vertex="1">
<mxGeometry height="80" width="120" x="390" y="340" as="geometry" />
</mxCell>
<mxCell id="4" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fontSize=14;fillColor=#e0e0e0;strokeColor=#999999;fontColor=#333333;" value="call tool(s)" vertex="1">
<mxGeometry height="50" width="160" x="160" y="480" as="geometry" />
</mxCell>
<mxCell id="5" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fontSize=14;fillColor=#e0e0e0;strokeColor=#333333;fontColor=#333333;strokeWidth=3;fontStyle=1;" value="end turn" vertex="1">
<mxGeometry height="50" width="160" x="580" y="480" as="geometry" />
</mxCell>
<mxCell id="7" edge="1" parent="1" source="3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#666666;fontSize=13;fontColor=#333333;fontStyle=1;" target="4" value="yes">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8" edge="1" parent="1" source="3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#666666;fontSize=13;fontColor=#333333;fontStyle=1;" target="5" value="no">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9" edge="1" parent="1" source="4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;strokeColor=#666666;" target="10">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="100" y="505" />
<mxPoint x="100" y="145" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
Binary file added designs/0009-current-agent-loop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 90 additions & 0 deletions designs/0009-demos/background-tasks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Getting Started — backgroundTools
*
* The simplest demo of background task scheduling. A research assistant searches
* 3 sources (web, docs, news). Each search takes 5 seconds.
*
* Standard: 3 searches run sequentially → ~15s of tool time
* Background: 3 searches run concurrently → ~5s of tool time
*/

import { Agent, BedrockModel, tool } from '@strands-agents/sdk'
import { z } from 'zod'

const modelId = process.argv.find((_, i) => process.argv[i - 1] === '--model')
const model = new BedrockModel({ ...(modelId && { modelId }), region: 'us-east-1' })

const searchWeb = tool({
name: 'search_web',
description: 'Search the web for recent information on a topic.',
inputSchema: z.object({ query: z.string() }),
callback: async (input) => {
await new Promise((r) => setTimeout(r, 5000))
return `Web results for "${input.query}": Found 3 relevant articles on recent developments in this area, including industry analysis and expert commentary.`
},
})

const searchDocs = tool({
name: 'search_docs',
description: 'Search technical documentation and reference materials.',
inputSchema: z.object({ query: z.string() }),
callback: async (input) => {
await new Promise((r) => setTimeout(r, 5000))
return `Documentation results for "${input.query}": Found official guides, API references, and best-practice recommendations from authoritative sources.`
},
})

const searchNews = tool({
name: 'search_news',
description: 'Search recent news articles and press releases.',
inputSchema: z.object({ query: z.string() }),
callback: async (input) => {
await new Promise((r) => setTimeout(r, 5000))
return `News results for "${input.query}": Found 5 recent articles covering market trends, product launches, and analyst perspectives.`
},
})

const systemPrompt =
'You are a research assistant. When asked a question, search all 3 sources ' +
'(web, docs, news) and write a brief summary of your findings.'

const prompt = 'What are the latest trends in AI agent frameworks?'

// ── Standard ────────────────────────────────────────────────────────────────

console.log('--- STANDARD (sequential) ---\n')
const standardAgent = new Agent({ model, systemPrompt, tools: [searchWeb, searchDocs, searchNews] })
const standardStart = Date.now()
const standardResult = await standardAgent.invoke(prompt)
const standardMs = Date.now() - standardStart

// ── Background ──────────────────────────────────────────────────────────────

console.log('\n--- BACKGROUND (concurrent) ---\n')
const backgroundAgent = new Agent({ model, systemPrompt, backgroundTools: [searchWeb, searchDocs, searchNews] })
const backgroundStart = Date.now()
const backgroundResult = await backgroundAgent.invoke(prompt)
const backgroundMs = Date.now() - backgroundStart

// ── Results ─────────────────────────────────────────────────────────────────

const stdUsage = standardResult.metrics?.accumulatedUsage
const bgUsage = backgroundResult.metrics?.accumulatedUsage

const pad = (s: string, n: number) => s.padEnd(n)

console.log('\n' + '='.repeat(60))
console.log(' RESULTS')
console.log('='.repeat(60))
console.log()
console.log(` ${pad('Metric', 24)} ${pad('Standard', 16)} Background`)
console.log(` ${'-'.repeat(24)} ${'-'.repeat(16)} ${'-'.repeat(16)}`)
console.log(` ${pad('Wall clock', 24)} ${pad((standardMs / 1000).toFixed(1) + 's', 16)} ${(backgroundMs / 1000).toFixed(1)}s`)
console.log(` ${pad('Speedup', 24)} ${pad('baseline', 16)} ${(standardMs / backgroundMs).toFixed(2)}x`)
console.log(` ${pad('Input tokens', 24)} ${pad(String(stdUsage?.inputTokens ?? 'N/A'), 16)} ${bgUsage?.inputTokens ?? 'N/A'}`)
console.log(` ${pad('Output tokens', 24)} ${pad(String(stdUsage?.outputTokens ?? 'N/A'), 16)} ${bgUsage?.outputTokens ?? 'N/A'}`)
console.log(` ${pad('Total tokens', 24)} ${pad(String(stdUsage?.totalTokens ?? 'N/A'), 16)} ${bgUsage?.totalTokens ?? 'N/A'}`)
console.log(` ${pad('Agent cycles', 24)} ${pad(String(standardResult.metrics?.cycleCount ?? 'N/A'), 16)} ${backgroundResult.metrics?.cycleCount ?? 'N/A'}`)
console.log(` ${pad('Output length (chars)', 24)} ${pad(String(standardResult.toString().length), 16)} ${backgroundResult.toString().length}`)
console.log()
console.log('='.repeat(60))
Loading
Loading