Agentic Assistant
Multi-step task execution with autonomous tool use and conversation memory.
Features
- Agentic Mode - Autonomous multi-step tool execution
- Built-in Tools - Calculator, web search, weather, notes, tasks
- Conversation Memory - Persistent history across sessions
- Streaming Responses - Real-time output as the agent works
- Execution Limits - Configurable max tool rounds
- Error Recovery - Graceful handling of tool failures
Quick Start
bash
export OPENAI_API_KEY=your_key
npm run recipe:agentic-assistantHow It Works
This recipe creates an autonomous AI assistant that can execute multi-step tasks using tools, with persistent memory across sessions.
Key capabilities:
- Automatically selects and chains tools to complete tasks
- Remembers context from previous conversations
- Limits execution rounds to prevent runaway loops
Flow:
- User submits a request
- Agent analyzes what tools (if any) are needed
- Executes tools in sequence, processing results
- Loops until task is complete or max rounds reached
- Returns final response with results
Available Tools
| Tool | Description |
|---|---|
calculator | Perform mathematical calculations |
web_search | Search the web for information |
get_weather | Get current weather for a location |
create_note | Save a note for later reference |
list_notes | View all saved notes |
create_task | Create a new todo task |
list_tasks | View all tasks with status |
complete_task | Mark a task as completed |
Example Session
You: What's 15% of 847 and create a note about it?
🔧 calculator("847 * 15 / 100")
→ = 127.05
🔧 create_note("15% of 847 Calculation")
→ Note saved with ID: k3m9x2p1
Assistant: 15% of 847 is 127.05. I have saved this calculation as a note
for your reference. You can view it anytime with the "notes" command.Code Walkthrough
Creating the Agent
typescript
/**
* Agentic Assistant Library
*
* Exported functions for the Agentic Assistant recipe.
* Snippet markers allow VitePress to extract code for documentation.
*/
import * as fs from 'fs';
import { ChatClient, ToolRegistry, FileStorage, ChatError } from '../../../src';
// [start:config]
export const STORAGE_DIR = './.agent-memory';
export const CONVERSATION_ID = 'agent-session';
export const NOTES_FILE = `${STORAGE_DIR}/notes.json`;
export const TASKS_FILE = `${STORAGE_DIR}/tasks.json`;
export const MAX_TOOL_ROUNDS = 10;
export const MODEL = 'gpt-4o-mini';
// [end:config]
// [start:colors]
export const colors = {
reset: '\x1b[0m',
dim: '\x1b[2m',
bold: '\x1b[1m',
red: '\x1b[31m',
yellow: '\x1b[33m',
green: '\x1b[32m',
cyan: '\x1b[36m',
magenta: '\x1b[35m',
blue: '\x1b[34m',
gray: '\x1b[90m'
};
// [end:colors]
// [start:types]
export interface Note {
id: string;
title: string;
content: string;
createdAt: string;
}
export interface Task {
id: string;
title: string;
completed: boolean;
createdAt: string;
}
export interface SearchResult {
title: string;
snippet: string;
url: string;
}
// [end:types]
export function generateId(): string {
return Math.random().toString(36).substring(2, 10);
}
export function log(
level: 'info' | 'tool' | 'result' | 'error' | 'success',
message: string
): void {
const prefix = {
info: `${colors.cyan}ℹ${colors.reset}`,
tool: `${colors.magenta}🔧${colors.reset}`,
result: `${colors.blue}→${colors.reset}`,
error: `${colors.red}✗${colors.reset}`,
success: `${colors.green}✓${colors.reset}`
};
console.log(`${prefix[level]} ${message}`);
}
// [start:persistence]
export function ensureStorageDir(): void {
if (!fs.existsSync(STORAGE_DIR)) {
fs.mkdirSync(STORAGE_DIR, { recursive: true });
}
}
export function loadNotes(): Note[] {
try {
if (fs.existsSync(NOTES_FILE)) {
return JSON.parse(fs.readFileSync(NOTES_FILE, 'utf-8'));
}
} catch (error) {
if (error instanceof Error && !error.message.includes('ENOENT')) {
console.error('Failed to load notes:', error.message);
}
}
return [];
}
export function saveNotes(notes: Note[]): void {
ensureStorageDir();
fs.writeFileSync(NOTES_FILE, JSON.stringify(notes, null, 2));
}
export function loadTasks(): Task[] {
try {
if (fs.existsSync(TASKS_FILE)) {
return JSON.parse(fs.readFileSync(TASKS_FILE, 'utf-8'));
}
} catch (error) {
if (error instanceof Error && !error.message.includes('ENOENT')) {
console.error('Failed to load tasks:', error.message);
}
}
return [];
}
export function saveTasks(tasks: Task[]): void {
ensureStorageDir();
fs.writeFileSync(TASKS_FILE, JSON.stringify(tasks, null, 2));
}
// [end:persistence]
// [start:create-tools]
export function createToolRegistry(): ToolRegistry {
const registry = new ToolRegistry();
// Calculator tool
// NOTE: Uses eval() for demo simplicity. For production, use 'mathjs' or 'expr-eval'.
registry.registerTool(
'calculator',
async (args: { expression: string }) => {
log('tool', `calculator("${args.expression}")`);
try {
const sanitized = args.expression.replace(/[^0-9+\-*/().%\s]/g, '');
const result = eval(sanitized);
log('result', `= ${result}`);
return { result, expression: args.expression };
} catch {
return { error: 'Invalid mathematical expression' };
}
},
{
description: 'Perform mathematical calculations. Supports +, -, *, /, %, and parentheses.',
parameters: {
type: 'object',
properties: {
expression: {
type: 'string',
description: 'Mathematical expression to evaluate (e.g., "15 * 847 / 100")'
}
},
required: ['expression']
}
}
);
// Web search tool (simulated)
registry.registerTool(
'web_search',
async (args: { query: string }) => {
log('tool', `web_search("${args.query}")`);
const results: SearchResult[] = [];
const query = args.query.toLowerCase();
if (query.includes('ai') || query.includes('artificial intelligence')) {
results.push(
{
title: 'Latest AI Developments in 2026',
snippet: 'Major breakthroughs in multimodal AI systems and reasoning capabilities...',
url: 'https://example.com/ai-news'
},
{
title: 'AI in Enterprise: Adoption Trends',
snippet: 'Enterprise AI adoption reaches 78% as companies integrate automation...',
url: 'https://example.com/enterprise-ai'
}
);
} else {
results.push({
title: `Search results for: ${args.query}`,
snippet: `Found relevant information about "${args.query}". Simulated result.`,
url: 'https://example.com/search'
});
}
log('result', `Found ${results.length} results`);
return { results, query: args.query };
},
{
description: 'Search the web for information on any topic.',
parameters: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' }
},
required: ['query']
}
}
);
// Weather tool (simulated)
registry.registerTool(
'get_weather',
async (args: { location: string }) => {
log('tool', `get_weather("${args.location}")`);
const weatherData: Record<
string,
{ temperature: number; condition: string; humidity: number }
> = {
tokyo: { temperature: 22, condition: 'Partly Cloudy', humidity: 65 },
'new york': { temperature: 18, condition: 'Sunny', humidity: 45 },
london: { temperature: 12, condition: 'Rainy', humidity: 80 }
};
const location = args.location.toLowerCase();
const weather = weatherData[location] || {
temperature: 20,
condition: 'Clear',
humidity: 50
};
log('result', `${weather.temperature}°C, ${weather.condition}`);
return {
location: args.location,
temperature: weather.temperature,
temperatureUnit: 'Celsius',
condition: weather.condition,
humidity: weather.humidity
};
},
{
description: 'Get current weather information for a location.',
parameters: {
type: 'object',
properties: {
location: { type: 'string', description: 'City name (e.g., "Tokyo", "New York")' }
},
required: ['location']
}
}
);
// Note tools
registry.registerTool(
'create_note',
async (args: { title: string; content: string }) => {
log('tool', `create_note("${args.title}")`);
const notes = loadNotes();
const note: Note = {
id: generateId(),
title: args.title,
content: args.content,
createdAt: new Date().toISOString()
};
notes.push(note);
saveNotes(notes);
log('result', `Note saved with ID: ${note.id}`);
return { success: true, note };
},
{
description: 'Create and save a note for later reference.',
parameters: {
type: 'object',
properties: {
title: { type: 'string', description: 'Note title' },
content: { type: 'string', description: 'Note content' }
},
required: ['title', 'content']
}
}
);
registry.registerTool(
'list_notes',
async () => {
log('tool', 'list_notes()');
const notes = loadNotes();
log('result', `Found ${notes.length} notes`);
return { notes, count: notes.length };
},
{ description: 'List all saved notes.' }
);
// Task tools
registry.registerTool(
'create_task',
async (args: { title: string }) => {
log('tool', `create_task("${args.title}")`);
const tasks = loadTasks();
const task: Task = {
id: generateId(),
title: args.title,
completed: false,
createdAt: new Date().toISOString()
};
tasks.push(task);
saveTasks(tasks);
log('result', `Task created with ID: ${task.id}`);
return { success: true, task };
},
{
description: 'Create a new todo task.',
parameters: {
type: 'object',
properties: {
title: { type: 'string', description: 'Task description' }
},
required: ['title']
}
}
);
registry.registerTool(
'list_tasks',
async () => {
log('tool', 'list_tasks()');
const tasks = loadTasks();
const pending = tasks.filter((t) => !t.completed);
const completed = tasks.filter((t) => t.completed);
log('result', `${pending.length} pending, ${completed.length} completed`);
return { tasks, pending: pending.length, completed: completed.length };
},
{ description: 'List all tasks with their status.' }
);
registry.registerTool(
'complete_task',
async (args: { taskId: string }) => {
log('tool', `complete_task("${args.taskId}")`);
const tasks = loadTasks();
const task = tasks.find((t) => t.id === args.taskId);
if (!task) {
log('result', 'Task not found');
return { success: false, error: 'Task not found' };
}
task.completed = true;
saveTasks(tasks);
log('result', `Task "${task.title}" marked complete`);
return { success: true, task };
},
{
description: 'Mark a task as completed.',
parameters: {
type: 'object',
properties: {
taskId: { type: 'string', description: 'ID of the task to complete' }
},
required: ['taskId']
}
}
);
return registry;
}
// [end:create-tools]
// [start:create-client]
export function createAgentClient(apiKey: string): ChatClient {
const storage = new FileStorage(STORAGE_DIR);
const tools = createToolRegistry();
return new ChatClient({
provider: 'openai',
model: MODEL,
apiKey,
storage,
conversationId: CONVERSATION_ID,
tools,
agenticMode: true,
maxToolRounds: MAX_TOOL_ROUNDS,
systemPrompt: `You are a helpful AI assistant with access to various tools.
You can perform calculations, search the web, check weather, and manage notes and tasks.
When a user asks you to do something, use the appropriate tools to help them.
For multi-step tasks, break them down and use tools as needed.
Always explain what you're doing and provide helpful responses.
Be concise but thorough.`
});
}
// [end:create-client]
// [start:streaming]
export async function streamResponse(
client: ChatClient,
message: string,
onChunk: (content: string) => void
): Promise<void> {
for await (const chunk of client.stream(message)) {
onChunk(chunk.content);
}
}
// [end:streaming]
// [start:error-handling]
export function handleError(error: unknown): string {
if (error instanceof ChatError) {
return `Error: ${error.message}`;
} else if (error instanceof Error) {
return `Error: ${error.message}`;
} else {
return 'An unexpected error occurred';
}
}
// [end:error-handling]
export function printBanner(): void {
console.log(`
${colors.cyan}╭─────────────────────────────────────────────╮
│ ${colors.reset}${colors.bold}Agentic Assistant${colors.reset}${colors.cyan} │
│ ${colors.dim}Multi-step task execution with tools${colors.reset}${colors.cyan} │
│ ${colors.dim}Type 'exit' to quit, 'help' for commands${colors.reset}${colors.cyan} │
╰─────────────────────────────────────────────╯${colors.reset}
`);
}
export function printHelp(): void {
console.log(`
${colors.yellow}Commands:${colors.reset}
${colors.bold}exit${colors.reset} - Quit the assistant
${colors.bold}clear${colors.reset} - Clear conversation history
${colors.bold}notes${colors.reset} - View all saved notes
${colors.bold}tasks${colors.reset} - View all tasks
${colors.bold}help${colors.reset} - Show this help message
${colors.yellow}Available Tools:${colors.reset}
${colors.cyan}calculator${colors.reset} - Perform mathematical calculations
${colors.cyan}web_search${colors.reset} - Search the web for information
${colors.cyan}get_weather${colors.reset} - Get current weather for a location
${colors.cyan}create_note${colors.reset} - Save a note for later
${colors.cyan}list_notes${colors.reset} - View all saved notes
${colors.cyan}create_task${colors.reset} - Create a todo task
${colors.cyan}list_tasks${colors.reset} - View all tasks
${colors.cyan}complete_task${colors.reset} - Mark a task as complete
`);
}Registering Tools
typescript
/**
* Agentic Assistant Library
*
* Exported functions for the Agentic Assistant recipe.
* Snippet markers allow VitePress to extract code for documentation.
*/
import * as fs from 'fs';
import { ChatClient, ToolRegistry, FileStorage, ChatError } from '../../../src';
// [start:config]
export const STORAGE_DIR = './.agent-memory';
export const CONVERSATION_ID = 'agent-session';
export const NOTES_FILE = `${STORAGE_DIR}/notes.json`;
export const TASKS_FILE = `${STORAGE_DIR}/tasks.json`;
export const MAX_TOOL_ROUNDS = 10;
export const MODEL = 'gpt-4o-mini';
// [end:config]
// [start:colors]
export const colors = {
reset: '\x1b[0m',
dim: '\x1b[2m',
bold: '\x1b[1m',
red: '\x1b[31m',
yellow: '\x1b[33m',
green: '\x1b[32m',
cyan: '\x1b[36m',
magenta: '\x1b[35m',
blue: '\x1b[34m',
gray: '\x1b[90m'
};
// [end:colors]
// [start:types]
export interface Note {
id: string;
title: string;
content: string;
createdAt: string;
}
export interface Task {
id: string;
title: string;
completed: boolean;
createdAt: string;
}
export interface SearchResult {
title: string;
snippet: string;
url: string;
}
// [end:types]
export function generateId(): string {
return Math.random().toString(36).substring(2, 10);
}
export function log(
level: 'info' | 'tool' | 'result' | 'error' | 'success',
message: string
): void {
const prefix = {
info: `${colors.cyan}ℹ${colors.reset}`,
tool: `${colors.magenta}🔧${colors.reset}`,
result: `${colors.blue}→${colors.reset}`,
error: `${colors.red}✗${colors.reset}`,
success: `${colors.green}✓${colors.reset}`
};
console.log(`${prefix[level]} ${message}`);
}
// [start:persistence]
export function ensureStorageDir(): void {
if (!fs.existsSync(STORAGE_DIR)) {
fs.mkdirSync(STORAGE_DIR, { recursive: true });
}
}
export function loadNotes(): Note[] {
try {
if (fs.existsSync(NOTES_FILE)) {
return JSON.parse(fs.readFileSync(NOTES_FILE, 'utf-8'));
}
} catch (error) {
if (error instanceof Error && !error.message.includes('ENOENT')) {
console.error('Failed to load notes:', error.message);
}
}
return [];
}
export function saveNotes(notes: Note[]): void {
ensureStorageDir();
fs.writeFileSync(NOTES_FILE, JSON.stringify(notes, null, 2));
}
export function loadTasks(): Task[] {
try {
if (fs.existsSync(TASKS_FILE)) {
return JSON.parse(fs.readFileSync(TASKS_FILE, 'utf-8'));
}
} catch (error) {
if (error instanceof Error && !error.message.includes('ENOENT')) {
console.error('Failed to load tasks:', error.message);
}
}
return [];
}
export function saveTasks(tasks: Task[]): void {
ensureStorageDir();
fs.writeFileSync(TASKS_FILE, JSON.stringify(tasks, null, 2));
}
// [end:persistence]
// [start:create-tools]
export function createToolRegistry(): ToolRegistry {
const registry = new ToolRegistry();
// Calculator tool
// NOTE: Uses eval() for demo simplicity. For production, use 'mathjs' or 'expr-eval'.
registry.registerTool(
'calculator',
async (args: { expression: string }) => {
log('tool', `calculator("${args.expression}")`);
try {
const sanitized = args.expression.replace(/[^0-9+\-*/().%\s]/g, '');
const result = eval(sanitized);
log('result', `= ${result}`);
return { result, expression: args.expression };
} catch {
return { error: 'Invalid mathematical expression' };
}
},
{
description: 'Perform mathematical calculations. Supports +, -, *, /, %, and parentheses.',
parameters: {
type: 'object',
properties: {
expression: {
type: 'string',
description: 'Mathematical expression to evaluate (e.g., "15 * 847 / 100")'
}
},
required: ['expression']
}
}
);
// Web search tool (simulated)
registry.registerTool(
'web_search',
async (args: { query: string }) => {
log('tool', `web_search("${args.query}")`);
const results: SearchResult[] = [];
const query = args.query.toLowerCase();
if (query.includes('ai') || query.includes('artificial intelligence')) {
results.push(
{
title: 'Latest AI Developments in 2026',
snippet: 'Major breakthroughs in multimodal AI systems and reasoning capabilities...',
url: 'https://example.com/ai-news'
},
{
title: 'AI in Enterprise: Adoption Trends',
snippet: 'Enterprise AI adoption reaches 78% as companies integrate automation...',
url: 'https://example.com/enterprise-ai'
}
);
} else {
results.push({
title: `Search results for: ${args.query}`,
snippet: `Found relevant information about "${args.query}". Simulated result.`,
url: 'https://example.com/search'
});
}
log('result', `Found ${results.length} results`);
return { results, query: args.query };
},
{
description: 'Search the web for information on any topic.',
parameters: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' }
},
required: ['query']
}
}
);
// Weather tool (simulated)
registry.registerTool(
'get_weather',
async (args: { location: string }) => {
log('tool', `get_weather("${args.location}")`);
const weatherData: Record<
string,
{ temperature: number; condition: string; humidity: number }
> = {
tokyo: { temperature: 22, condition: 'Partly Cloudy', humidity: 65 },
'new york': { temperature: 18, condition: 'Sunny', humidity: 45 },
london: { temperature: 12, condition: 'Rainy', humidity: 80 }
};
const location = args.location.toLowerCase();
const weather = weatherData[location] || {
temperature: 20,
condition: 'Clear',
humidity: 50
};
log('result', `${weather.temperature}°C, ${weather.condition}`);
return {
location: args.location,
temperature: weather.temperature,
temperatureUnit: 'Celsius',
condition: weather.condition,
humidity: weather.humidity
};
},
{
description: 'Get current weather information for a location.',
parameters: {
type: 'object',
properties: {
location: { type: 'string', description: 'City name (e.g., "Tokyo", "New York")' }
},
required: ['location']
}
}
);
// Note tools
registry.registerTool(
'create_note',
async (args: { title: string; content: string }) => {
log('tool', `create_note("${args.title}")`);
const notes = loadNotes();
const note: Note = {
id: generateId(),
title: args.title,
content: args.content,
createdAt: new Date().toISOString()
};
notes.push(note);
saveNotes(notes);
log('result', `Note saved with ID: ${note.id}`);
return { success: true, note };
},
{
description: 'Create and save a note for later reference.',
parameters: {
type: 'object',
properties: {
title: { type: 'string', description: 'Note title' },
content: { type: 'string', description: 'Note content' }
},
required: ['title', 'content']
}
}
);
registry.registerTool(
'list_notes',
async () => {
log('tool', 'list_notes()');
const notes = loadNotes();
log('result', `Found ${notes.length} notes`);
return { notes, count: notes.length };
},
{ description: 'List all saved notes.' }
);
// Task tools
registry.registerTool(
'create_task',
async (args: { title: string }) => {
log('tool', `create_task("${args.title}")`);
const tasks = loadTasks();
const task: Task = {
id: generateId(),
title: args.title,
completed: false,
createdAt: new Date().toISOString()
};
tasks.push(task);
saveTasks(tasks);
log('result', `Task created with ID: ${task.id}`);
return { success: true, task };
},
{
description: 'Create a new todo task.',
parameters: {
type: 'object',
properties: {
title: { type: 'string', description: 'Task description' }
},
required: ['title']
}
}
);
registry.registerTool(
'list_tasks',
async () => {
log('tool', 'list_tasks()');
const tasks = loadTasks();
const pending = tasks.filter((t) => !t.completed);
const completed = tasks.filter((t) => t.completed);
log('result', `${pending.length} pending, ${completed.length} completed`);
return { tasks, pending: pending.length, completed: completed.length };
},
{ description: 'List all tasks with their status.' }
);
registry.registerTool(
'complete_task',
async (args: { taskId: string }) => {
log('tool', `complete_task("${args.taskId}")`);
const tasks = loadTasks();
const task = tasks.find((t) => t.id === args.taskId);
if (!task) {
log('result', 'Task not found');
return { success: false, error: 'Task not found' };
}
task.completed = true;
saveTasks(tasks);
log('result', `Task "${task.title}" marked complete`);
return { success: true, task };
},
{
description: 'Mark a task as completed.',
parameters: {
type: 'object',
properties: {
taskId: { type: 'string', description: 'ID of the task to complete' }
},
required: ['taskId']
}
}
);
return registry;
}
// [end:create-tools]
// [start:create-client]
export function createAgentClient(apiKey: string): ChatClient {
const storage = new FileStorage(STORAGE_DIR);
const tools = createToolRegistry();
return new ChatClient({
provider: 'openai',
model: MODEL,
apiKey,
storage,
conversationId: CONVERSATION_ID,
tools,
agenticMode: true,
maxToolRounds: MAX_TOOL_ROUNDS,
systemPrompt: `You are a helpful AI assistant with access to various tools.
You can perform calculations, search the web, check weather, and manage notes and tasks.
When a user asks you to do something, use the appropriate tools to help them.
For multi-step tasks, break them down and use tools as needed.
Always explain what you're doing and provide helpful responses.
Be concise but thorough.`
});
}
// [end:create-client]
// [start:streaming]
export async function streamResponse(
client: ChatClient,
message: string,
onChunk: (content: string) => void
): Promise<void> {
for await (const chunk of client.stream(message)) {
onChunk(chunk.content);
}
}
// [end:streaming]
// [start:error-handling]
export function handleError(error: unknown): string {
if (error instanceof ChatError) {
return `Error: ${error.message}`;
} else if (error instanceof Error) {
return `Error: ${error.message}`;
} else {
return 'An unexpected error occurred';
}
}
// [end:error-handling]
export function printBanner(): void {
console.log(`
${colors.cyan}╭─────────────────────────────────────────────╮
│ ${colors.reset}${colors.bold}Agentic Assistant${colors.reset}${colors.cyan} │
│ ${colors.dim}Multi-step task execution with tools${colors.reset}${colors.cyan} │
│ ${colors.dim}Type 'exit' to quit, 'help' for commands${colors.reset}${colors.cyan} │
╰─────────────────────────────────────────────╯${colors.reset}
`);
}
export function printHelp(): void {
console.log(`
${colors.yellow}Commands:${colors.reset}
${colors.bold}exit${colors.reset} - Quit the assistant
${colors.bold}clear${colors.reset} - Clear conversation history
${colors.bold}notes${colors.reset} - View all saved notes
${colors.bold}tasks${colors.reset} - View all tasks
${colors.bold}help${colors.reset} - Show this help message
${colors.yellow}Available Tools:${colors.reset}
${colors.cyan}calculator${colors.reset} - Perform mathematical calculations
${colors.cyan}web_search${colors.reset} - Search the web for information
${colors.cyan}get_weather${colors.reset} - Get current weather for a location
${colors.cyan}create_note${colors.reset} - Save a note for later
${colors.cyan}list_notes${colors.reset} - View all saved notes
${colors.cyan}create_task${colors.reset} - Create a todo task
${colors.cyan}list_tasks${colors.reset} - View all tasks
${colors.cyan}complete_task${colors.reset} - Mark a task as complete
`);
}Commands
| Command | Description |
|---|---|
exit | Quit the assistant |
clear | Clear conversation history |
notes | View all saved notes |
tasks | View all tasks |
help | Show help message |
Configuration
| Option | Default | Description |
|---|---|---|
agenticMode | true | Enable autonomous tool execution |
maxToolRounds | 10 | Maximum tool execution rounds |
storage | FileStorage | Persistence for conversation history |
conversationId | agent-session | ID for conversation persistence |
Environment Variables
| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY | Yes | OpenAI API key (GPT-4 recommended) |
Use Cases
Personal Assistant
Manage notes, tasks, and calculations in natural conversation.
Research Helper
Search for information and save relevant findings.
Task Automation
Chain multiple tools together for complex workflows.
