> ## 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.

# Low Code Custom Tools

> Step-by-step guide for creating and implementing custom tools in PraisonAI, including examples and configuration instructions

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, tool

@tool
def weather(city: str) -> str:
    """Return a short weather summary for a city."""
    return f"Sunny in {city}"

agent = Agent(name="Assistant", tools=[weather])
agent.start("What is the weather in London?")
```

The user asks in plain language; custom tools extend what the agent can do beyond built-ins.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    U[Input] --> A[Agent]
    A --> T[Tool]
    T --> O[Output]

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

    class A agent
    class U,O tool
    class T tool
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Feature as Low Code Custom Tools

    User->>Agent: Request
    Agent->>Feature: Process request
    Feature-->>Agent: Result
    Agent-->>User: Response
```

# Create Custom Tools

<div className="relative w-full aspect-video">
  <iframe className="absolute top-0 left-0 w-full h-full" src="https://www.youtube.com/embed/JSU2Rndh06c" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />
</div>

## Quick Start

<Steps>
  <Step title="Install">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    pip install praisonaiagents
    ```
  </Step>

  <Step title="Create a custom tool">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    def get_weather(city: str) -> str:
        return f'Weather in {city}: Sunny, 22 degrees'

    agent = Agent(
        name="WeatherAgent",
        instructions="Provide weather information using the weather tool.",
        tools=[get_weather],
    )

    agent.start("What is the weather in London?")
    ```
  </Step>
</Steps>

## Step 1: Install the `praisonai` Package

First, you need to install the `praisonai` package. Open your terminal and run the following command:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
pip install praisonai
```

## Step 2: Create the `InternetSearchTool`

Next, create a file named `tools.py` and add the following code to define the `InternetSearchTool`:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from duckduckgo_search import DDGS
from praisonai_tools import BaseTool

class InternetSearchTool(BaseTool):
    name: str = "Internet Search Tool"
    description: str = "Search Internet for relevant information based on a query or latest news"

    def _run(self, query: str):
        ddgs = DDGS()
        results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
        return results
```

## Step 3: Define the Agent Configuration

Create a file named `agents.yaml` and add the following content to configure the agent:

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
framework: crewai
topic: research about the causes of lung disease
agents:  # Canonical: use 'agents' instead of 'roles'
  research_analyst:
    instructions:  # Canonical: use 'instructions' instead of 'backstory' Experienced in analyzing scientific data related to respiratory health.
    goal: Analyze data on lung diseases
    role: Research Analyst
    tasks:
      data_analysis:
        description: Gather and analyze data on the causes and risk factors of lung diseases.
        expected_output: Report detailing key findings on lung disease causes.
    tools:
    - InternetSearchTool
```

## Step 4: Run the PraisonAI Tool

To run the PraisonAI tool, simply type the following command in your terminal:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai
```

If you want to run the AG2 framework (Formerly AutoGen), use:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai --framework autogen
```

## Prerequisites

Ensure you have the `duckduckgo_search` package installed. If not, you can install it using:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
pip install duckduckgo_search
```

That's it! You should now have the PraisonAI tool installed and configured.

## Other information

### TL;DR to Create a Custom Tool

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
pip install praisonai duckduckgo-search
export OPENAI_API_KEY="Enter your API key"
praisonai --init research about the latest AI News and prepare a detailed report
```

* Add `- InternetSearchTool` in the agents.yaml file in the tools section.
* Create a file called tools.py and add this code [tools.py](tools.py)

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai
```

### Pre-requisite to Create a Custom Tool

`agents.yaml` file should be present in the current directory.

If it doesn't exist, create it by running the command `praisonai --init research about the latest AI News and prepare a detailed report`.

#### Step 1 to Create a Custom Tool

Create a file called tools.py in the same directory as the agents.yaml file.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# example tools.py
from duckduckgo_search import DDGS
from praisonai_tools import BaseTool

class InternetSearchTool(BaseTool):
    name: str = "InternetSearchTool"
    description: str = "Search Internet for relevant information based on a query or latest news"

    def _run(self, query: str):
        ddgs = DDGS()
        results = ddgs.text(keywords=query, region='wt-wt', safesearch='moderate', max_results=5)
        return results
```

#### Step 2 to Create a Custom Tool

Add the tool to the agents.yaml file as show below under the tools section `- InternetSearchTool`.

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
framework: crewai
topic: research about the latest AI News and prepare a detailed report
agents:  # Canonical: use 'agents' instead of 'roles'
  research_analyst:
    instructions:  # Canonical: use 'instructions' instead of 'backstory' Experienced in gathering and analyzing data related to AI news trends.
    goal: Analyze AI News trends
    role: Research Analyst
    tasks:
      gather_data:
        description: Conduct in-depth research on the latest AI News trends from reputable
          sources.
        expected_output: Comprehensive report on current AI News trends.
    tools:
    - InternetSearchTool
```

***

# Python Code Custom Tools

For `praisonaiagents` package users, you can create custom tools using the `@tool` decorator or `BaseTool` class.

## Using `@tool` Decorator

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, tool

@tool
def search(query: str) -> str:
    """Search the web for information."""
    return f"Results for: {query}"

@tool
def add(a: float, b: float) -> float:
    """Add two numbers (safe — no eval)."""
    return a + b

agent = Agent(
    instructions="You are a helpful assistant",
    tools=[search, add]
)
agent.start("Search for AI news and add 15 and 4")
```

## Using `BaseTool` Class

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, BaseTool

class WeatherTool(BaseTool):
    name = "weather"
    description = "Get current weather for a location"
    
    def run(self, location: str) -> str:
        return f"Weather in {location}: 72°F, Sunny"

agent = Agent(
    instructions="You are a weather assistant",
    tools=[WeatherTool()]
)
agent.start("What's the weather in Paris?")
```

## Expressive Parameter Types

Create tools with rich type annotations for better schema generation:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from typing import Optional, Literal
from praisonaiagents import Agent, tool

@tool
def configure_service(
    name: str,
    port: Optional[int] = None,
    mode: Literal["production", "development"] = "development"
) -> str:
    """Configure a service with optional port and mode."""
    config = f"Service '{name}' configured in {mode} mode"
    if port:
        config += f" on port {port}"
    return config

agent = Agent(
    instructions="You configure services",
    tools=[configure_service]
)
agent.start("Configure webapp in production mode with port 8080")
```

See the [Tool Parameter Types](/docs/tools/parameter-types) page for complete guide.

## Creating a Pip-Installable Tool Package

Create tools that auto-register when installed:

### pyproject.toml

```toml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
[project]
name = "my-praisonai-tools"
version = "1.0.0"
dependencies = ["praisonaiagents"]

[project.entry-points."praisonaiagents.tools"]
my_tool = "my_package:MyTool"
```

### my\_package/**init**.py

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import BaseTool

class MyTool(BaseTool):
    name = "my_tool"
    description = "My custom tool"
    
    def run(self, param: str) -> str:
        return f"Result: {param}"
```

### Usage

After `pip install`, tools are auto-discovered:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(tools=["my_tool"])  # Works automatically!
```

***

## What Happens During Validation

The `@tool` decorator and `BaseTool` instances now validate schemas automatically to ensure OpenAI compatibility.

**Automatic validation when using @tool:**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
@tool
def search(query: str) -> str:
    """Search the web for information."""
    return f"Results for: {query}"
# Validation runs here - check logs for warnings
```

**Important notes:**

* The `@tool` decorator validates at creation time and logs warnings (doesn't raise)
* `parameters` (if set manually) must include `properties` for OpenAI compatibility
* Validation failures are logged - scan your logs for `Tool validation warning for ...`

**Example that will raise ToolValidationError at agent creation:**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# This will raise ToolValidationError at agent creation:
class BadTool(BaseTool):
    name = "bad"
    description = "..."
    parameters = {"type": "object"}  # missing 'properties'
    def run(self, q: str) -> str: return q
```

For comprehensive validation details and error fixes, see [Tool Schema Validation](/docs/features/tool-schema-validation).

<Note>
  **Tool Name Collisions**: When developing custom tools, avoid naming conflicts with existing tools. If you have multiple environments with overlapping tool names, use the [Allowed Tools](/features/allowed-tools) feature to whitelist specific tools.
</Note>

## Best Practices

<AccordionGroup>
  <Accordion title="Use simple function signatures">
    Define tools as plain Python functions with clear type hints - `def my_tool(query: str) -> str`.
  </Accordion>

  <Accordion title="Write descriptive docstrings">
    The agent reads tool docstrings to decide when to call them - be specific about what the tool does.
  </Accordion>

  <Accordion title="Always return strings">
    Return a string from tool functions - even for errors - so the agent can process the result.
  </Accordion>

  <Accordion title="Test tools independently">
    Call your tool function directly with test inputs before adding it to an agent.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Custom Tools" icon="wrench" href="/docs/tools/custom">
    Build your own agent tools
  </Card>

  <Card title="Tools Overview" icon="toolbox" href="/docs/tools/tools">
    Browse PraisonAI tool documentation
  </Card>
</CardGroup>
