Files
2026-07-13 13:34:48 +08:00

113 lines
3.4 KiB
TypeScript

/**
* Example 19: Tool Wrapping and Enhancement
*
* This example demonstrates advanced tool composition patterns using tool wrapping.
* It shows how to:
* - Create enhanced versions of existing tools using clone()
* - Extend tool output schemas with additional fields
* - Implement decorator patterns for tool functionality
* - Chain tool execution with pre/post processing
* - Build composable tool architectures
*
* Key concepts:
* - Tool cloning and enhancement
* - Schema extension and composition
* - Decorator pattern implementation
* - Tool execution chaining
* - Composable tool design patterns
*/
import { Client } from '@botpress/client'
import { z } from '@bpinternal/zui'
import chalk from 'chalk'
import { execute, Exit, Tool } from 'llmz'
import { box } from '../utils/box'
// Initialize Botpress client
const client = new Client({
botId: process.env.BOTPRESS_BOT_ID!,
token: process.env.BOTPRESS_TOKEN!,
})
// Exit condition to capture the final result
const exit = new Exit({
name: 'exit',
description: 'Exit the program',
schema: z.object({
result: z.number(),
}),
})
// Original base tool with simple greeting functionality
// This demonstrates the tool that will be enhanced through wrapping
const normalTool = new Tool({
name: 'greet',
description: 'A tool that greets the user',
input: z.object({
greeting: z.string(),
}),
output: z.object({
message: z.string(),
}),
async handler(input) {
console.log(chalk.green('✓') + ` Original tool executed with input: ${input.greeting}`)
return { message: `Hello, ${input.greeting}!` }
},
})
// Enhanced tool created by wrapping the original tool
// This demonstrates the decorator pattern for tool enhancement
const wrappedTool = normalTool.clone({
// Extend the output schema to include additional fields
// This shows how to compose and extend existing schemas
output: (schema) =>
schema!.extend({
added: z.number().describe('Tool confirmation number'),
}),
// Enhanced handler that calls the original tool and adds functionality
async handler(input, ctx) {
console.log(chalk.blue('✓') + ` Wrapped tool executed with input: ${input.greeting}`)
// Execute the original tool to get its result
// This demonstrates composition and delegation patterns
const result = await normalTool.execute(input, ctx)
// Return enhanced result with additional data
// This shows how to augment tool outputs with new information
return {
message: `Wrapped tool executed with input: ${input.greeting}. Original message: ${result.message}`,
added: 666, // Additional confirmation code
}
},
})
// Execute using the wrapped tool
const result = await execute({
instructions: 'Greet the user and return the confirmation code',
exits: [exit],
// Use the wrapped tool instead of the original
// The LLM will see the enhanced schema and functionality
tools: [wrappedTool],
client,
})
// Display the results showing the enhanced functionality
if (result.is(exit)) {
console.log(
box(
[
'The LLM wrote this code:',
// Show the generated code that used the wrapped tool
...result.iteration.code!.split('\n'),
'',
'It then executed it and returned the result:',
// Display the confirmation code from the wrapped tool
chalk.cyan.bold(result.output.result.toString()),
],
80
)
)
}