> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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](/docs/js/cancellation).

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Agent[Agent] --> Tools[Tools]
    Tools --> Action([Action])

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef tool fill:#189AB4,stroke:#7C90A0,color:#fff

    class Agent agent
    class Tools,Action tool
    classDef agent fill:#8B0000,color:#fff
    classDef tool fill:#189AB4,color:#fff
```

<Note>
  Tools work on **every provider** the TS SDK supports — `openai/...`, `anthropic/...`, `google/...`, `groq/...`, `mistral/...`, `ollama/...`, and more. The same `tools: [...]` you set on the Agent is formatted once and translated per-provider by the AI SDK backend, matching the Python SDK's litellm-backed contract. Cross-provider tool support landed in [PraisonAI PR #4412](https://github.com/MervinPraison/PraisonAI/pull/4412).
</Note>

## Quick Start

<Steps>
  <Step title="Simple Usage">
    ```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    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"
    ```
  </Step>

  <Step title="With Configuration">
    Use tool registries and categories — see sections below.
  </Step>
</Steps>

***

## Agent with Simple Function Tools

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

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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)
```

<Note>
  **Plain-function tools now work as advertised.** The model returns tool arguments as a named object; the runtime maps them onto your function's positional parameters — so `getWeather` receives `"Paris"`, not `"[object Object]"`. Tool return values are serialised as **JSON** (no more `.toString()`), and your `tools` array is never mutated — the constructor iterates a snapshot.
</Note>

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

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
// 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
// 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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');
```

<Warning>
  The global `register_tool` **skips** a name that is already registered (Python parity) — pass `{ overwrite: true }` to replace it. The class method `ToolRegistry.register` below **throws** on a duplicate instead.
</Warning>

### `register` options

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

| Option                   | Type                      | Description                                          |
| ------------------------ | ------------------------- | ---------------------------------------------------- |
| `name`                   | `string`                  | Register under this name instead of the tool's own   |
| `overwrite`              | `boolean`                 | Replace an existing registration under the same name |
| `trustLevel`             | `'trusted' \| 'external'` | Where the tool came from — invalid values throw      |
| `dynamicSchemaOverrides` | `(schema) => schema`      | Reshape 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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

<CardGroup cols={2}>
  <Card title="Custom Tools" icon="screwdriver-wrench" href="/docs/js/customtools">Build custom tools</Card>
  <Card title="Factory Registry" icon="industry" href="/docs/js/tools/factory-registry">Build instances from config</Card>
  <Card title="Tool Errors" icon="triangle-exclamation" href="/docs/js/tools/errors">Missing vs broken tools</Card>
  <Card title="MCP Tools" icon="plug" href="/docs/js/mcp-tools">MCP integration</Card>
</CardGroup>
