Tool System

Give Agents tools to take actions and access external data

Tools give your Agents the ability to take actions beyond just generating text. Agents can call APIs, search the web, perform calculations, and interact with external systems.

Long-running tools receive ctx.signal on ToolExecutionContext — check it to stop early when cancelled. See Cancellation.

Diagram

Agent

Tools

Action

Quick Start

  1. Simple Usage
    typescript
    import { Agent } from 'praisonai';
    
    // Define tools as simple functions
    const getWeather = (city: string) => `Weather in ${city}: 22°C, sunny`;
    const calculate = (expression: string) => eval(expression).toString();
    
    // Agent automatically generates tool schemas from functions
    const agent = new Agent({
      name: 'Assistant',
      instructions: 'You help users with weather and calculations.',
      tools: [getWeather, calculate]
    });
    
    await agent.chat('What is the weather in Paris?');
    // Agent calls getWeather("Paris") → "Weather in Paris: 22°C, sunny"
    
    await agent.chat('What is 15 * 7?');
    // Agent calls calculate("15 * 7") → "105"
  2. With Configuration

    Use tool registries and categories — see sections below.


Agent with Simple Function Tools

The easiest way to give an Agent tools — just pass plain functions directly:

typescript
import { Agent } from 'praisonai';

function getWeather(city: string) {
  return { city, temperature: 22, condition: 'sunny' };
}

const agent = new Agent({
  instructions: 'Report the weather using the tool.',
  tools: [getWeather],
});

await agent.chat('Weather in Paris?');
// The tool receives city="Paris" (named args mapped positionally)

The same tools run on any provider — only the llm string changes:

typescript
// Same tools, different provider — no code change beyond `llm`.
const claudeAgent = new Agent({
  instructions: 'Report the weather using the tool.',
  llm: 'anthropic/claude-3-5-sonnet-latest',
  tools: [getWeather],
});

await claudeAgent.start('Weather in Paris?');

Tools + Structured Output on any provider

Combine tools and outputSchema — the agent runs the tool loop first, then returns JSON matching your schema. This works on every provider:

typescript
// Tools + structured output on a non-OpenAI provider — works from PraisonAI PR #4412 onward.
import { Agent } from 'praisonai';

const getWeather = (city: string) => ({ city, tempC: 20, condition: 'sunny' });

const agent = new Agent({
  instructions: 'Use the tool to answer, then return the result as JSON.',
  llm: 'anthropic/claude-3-5-sonnet-latest',
  tools: [getWeather],
  outputSchema: {
    type: 'object',
    properties: {
      city: { type: 'string' },
      tempC: { type: 'number' },
      condition: { type: 'string' },
    },
    required: ['city', 'tempC', 'condition'],
  },
});

const json = await agent.start('Weather in Paris?');
console.log(JSON.parse(json));
// { city: "Paris", tempC: 20, condition: "sunny" }

Agent with Typed Tools

For more control, define tools with explicit schemas:

typescript
import { Agent, createTool } from 'praisonai';

const searchTool = createTool({
  name: 'web_search',
  description: 'Search the web for information',
  parameters: {
    type: 'object',
    properties: {
      query: { type: 'string', description: 'Search query' },
      limit: { type: 'number', description: 'Max results' }
    },
    required: ['query']
  },
  execute: async ({ query, limit = 5 }) => {
    // Perform actual search
    return `Found ${limit} results for: ${query}`;
  }
});

const agent = new Agent({
  name: 'Research Agent',
  instructions: 'You research topics using web search.',
  tools: [searchTool]
});

await agent.chat('Find information about TypeScript 5.0 features');

Multi-Agent Tool Sharing

Share tools across multiple Agents:

typescript
import { Agent, Agents, createTool } from 'praisonai';

// Shared tools
const databaseTool = createTool({
  name: 'query_database',
  description: 'Query the product database',
  parameters: {
    type: 'object',
    properties: { query: { type: 'string' } },
    required: ['query']
  },
  execute: async ({ query }) => `Database results for: ${query}`
});

const emailTool = createTool({
  name: 'send_email',
  description: 'Send an email notification',
  parameters: {
    type: 'object',
    properties: { 
      to: { type: 'string' },
      subject: { type: 'string' },
      body: { type: 'string' }
    },
    required: ['to', 'subject', 'body']
  },
  execute: async ({ to, subject, body }) => `Email sent to ${to}`
});

// Agents with different tool sets
const analyst = new Agent({
  name: 'Data Analyst',
  instructions: 'Analyze data from the database.',
  tools: [databaseTool]
});

const notifier = new Agent({
  name: 'Notifier',
  instructions: 'Send notifications based on analysis.',
  tools: [emailTool]
});

const agents = new AgentTeam([analyst, notifier]);
await agents.start();

Agent with Context-Aware Tools

Tools can access Agent context:

typescript
import { Agent, createTool } from 'praisonai';

const auditTool = createTool({
  name: 'audit_log',
  description: 'Log an action for audit purposes',
  parameters: {
    type: 'object',
    properties: { action: { type: 'string' } },
    required: ['action']
  },
  execute: async ({ action }, context) => {
    // Access Agent context
    const log = {
      action,
      agent: context?.agentName,
      session: context?.sessionId,
      timestamp: new Date().toISOString()
    };
    console.log('Audit:', log);
    return `Logged: ${action}`;
  }
});

const agent = new Agent({
  name: 'Secure Agent',
  instructions: 'You perform secure operations with audit logging.',
  tools: [auditTool],
  sessionId: 'secure-session-123'
});

await agent.chat('Log that user requested a password reset');

Global Tool Registry

For the common case, register tools by name on the global registry and look them up with the Python-style register_tool / get_tool — no registry instance to pass around.

typescript
import { Agent, register_tool, get_tool, tool } from 'praisonai';

register_tool(tool({
  name: 'calculator',
  description: 'Perform calculations',
  execute: async ({ expr }: { expr: string }) => eval(expr).toString(),
}));

const mathAgent = new Agent({
  name: 'Math Agent',
  instructions: 'You solve math problems.',
  tools: [get_tool('calculator')!],
});

await mathAgent.chat('Calculate 25 * 4');

register options

register_tool(tool, options) and ToolRegistry.register(tool, options) share one options shape:

OptionTypeDescription
namestringRegister under this name instead of the tool’s own
overwritebooleanReplace an existing registration under the same name
trustLevel`’trusted’ \‘external’`Where the tool came from — invalid values throw
dynamicSchemaOverrides(schema) => schemaReshape the parameter schema at registration time

Scoped Registry for Agent Teams

Use a new ToolRegistry() only when you genuinely need a scoped, categorised registry — for example to split tools across an agent team.

typescript
import { Agent, ToolRegistry, tool } from 'praisonai';

const registry = new ToolRegistry();

// Register categorized tools — the class method throws on duplicate names.
registry.register(tool({
  name: 'calculator',
  category: 'math',
  description: 'Perform calculations',
  execute: async ({ expr }: { expr: string }) => eval(expr).toString(),
}));

registry.register(tool({
  name: 'translator',
  category: 'language',
  description: 'Translate text',
  execute: async ({ text, lang }: { text: string; lang: string }) => `[${lang}] ${text}`,
}));

// Create Agents with tools from the scoped registry
const mathAgent = new Agent({
  name: 'Math Agent',
  instructions: 'You solve math problems.',
  tools: registry.getByCategory('math'),
});

const langAgent = new Agent({
  name: 'Language Agent',
  instructions: 'You translate text.',
  tools: registry.getByCategory('language'),
});

await mathAgent.chat('Calculate 25 * 4');
await langAgent.chat('Translate "Hello" to Spanish');

Model definitions advertise the registration key, so a tool registered under { name: 'renamed' } dispatches correctly. Inspect a registry with registry.listTools(), registry.getAll(), registry.getTrustLevel(name), and registry.size.

Related