open-multi-agent/examples/01-single-agent.ts

139 lines
4.7 KiB
TypeScript

/**
* Example 01 — Single Agent
*
* The simplest possible usage: one agent with bash and file tools, running
* a coding task. Then shows streaming output using the Agent class directly.
*
* Run:
* npx tsx examples/01-single-agent.ts
*
* Prerequisites:
* Ollama server running at http://localhost:11434
* OLLAMA_API_KEY env var may be set if your server requires auth.
*/
import { OpenMultiAgent, Agent, ToolRegistry, ToolExecutor, registerBuiltInTools } from '../src/index.js'
import type { OrchestratorEvent } from '../src/types.js'
const OLLAMA_MODEL = process.env.OLLAMA_MODEL ?? 'llama2'
// ---------------------------------------------------------------------------
// Part 1: Single agent via OpenMultiAgent (simplest path)
// ---------------------------------------------------------------------------
const orchestrator = new OpenMultiAgent({
defaultProvider: 'ollama',
defaultModel: OLLAMA_MODEL,
onProgress: (event: OrchestratorEvent) => {
if (event.type === 'agent_start') {
console.log(`[start] agent=${event.agent}`)
} else if (event.type === 'agent_complete') {
console.log(`[complete] agent=${event.agent}`)
}
},
})
console.log('Part 1: runAgent() — single one-shot task\n')
const result = await orchestrator.runAgent(
{
name: 'coder',
provider: 'ollama',
model: OLLAMA_MODEL,
systemPrompt: `You are a digital marketing agency.
When asked to getting clients for our cybersecurity solution company, find some startup with funding, webscarp thier niche and collect there contact info.
Use that info and send a cold eamil`,
tools: ['bash', 'file_read', 'file_write'],
maxTurns: 8,
},
`Create a small TypeScript utility function in /tmp/greet.ts that:
1. Exports a function named greet(name: string): string
2. Returns "Hello, <name>!"
3. Adds a brief usage comment at the top of the file.
Then add a default call greet("World") at the bottom and run the file with: npx tsx /tmp/greet.ts`,
)
if (result.success) {
console.log('\nAgent output:')
console.log('─'.repeat(60))
console.log(result.output)
console.log('─'.repeat(60))
} else {
console.error('Agent failed:', result.output)
process.exit(1)
}
console.log('\nToken usage:')
console.log(` input: ${result.tokenUsage.input_tokens}`)
console.log(` output: ${result.tokenUsage.output_tokens}`)
console.log(` tool calls made: ${result.toolCalls.length}`)
// ---------------------------------------------------------------------------
// Part 2: Streaming via Agent directly
//
// OpenMultiAgent.runAgent() is a convenient wrapper. When you need streaming, use
// the Agent class directly with an injected ToolRegistry + ToolExecutor.
// ---------------------------------------------------------------------------
console.log('\n\nPart 2: Agent.stream() — incremental text output\n')
// Build a registry with all built-in tools registered
const registry = new ToolRegistry()
registerBuiltInTools(registry)
const executor = new ToolExecutor(registry)
const streamingAgent = new Agent(
{
name: 'explainer',
provider: 'ollama',
model: OLLAMA_MODEL,
systemPrompt: 'You are a concise technical writer. Keep explanations brief.',
maxTurns: 3,
},
registry,
executor,
)
process.stdout.write('Streaming: ')
for await (const event of streamingAgent.stream(
'In two sentences, explain what a TypeScript generic constraint is.',
)) {
if (event.type === 'text' && typeof event.data === 'string') {
process.stdout.write(event.data)
} else if (event.type === 'done') {
process.stdout.write('\n')
} else if (event.type === 'error') {
console.error('\nStream error:', event.data)
}
}
// ---------------------------------------------------------------------------
// Part 3: Multi-turn conversation via Agent.prompt()
// ---------------------------------------------------------------------------
console.log('\nPart 3: Agent.prompt() — multi-turn conversation\n')
const conversationAgent = new Agent(
{
name: 'tutor',
provider: 'ollama',
model: OLLAMA_MODEL,
systemPrompt: 'You are a TypeScript tutor. Give short, direct answers.',
maxTurns: 2,
},
new ToolRegistry(), // no tools needed for this conversation
new ToolExecutor(new ToolRegistry()),
)
const turn1 = await conversationAgent.prompt('What is a type guard in TypeScript?')
console.log('Turn 1:', turn1.output.slice(0, 200))
const turn2 = await conversationAgent.prompt('Give me one concrete code example of what you just described.')
console.log('\nTurn 2:', turn2.output.slice(0, 300))
// History is retained between prompt() calls
console.log(`\nConversation history length: ${conversationAgent.getHistory().length} messages`)
console.log('\nDone.')