| title | AI Agents with Tools |
|---|---|
| sidebarTitle | Tools |
| description | Learn how to create AI agents that can use tools to interact with external systems and perform actions. |
| icon | screwdriver-wrench |
flowchart TB
subgraph Tools
direction TB
T3[Internet Search]
T1[Code Execution]
T2[Formatting]
end
Input[Input] ---> Agents
subgraph Agents
direction LR
A1[Agent 1]
A2[Agent 2]
A3[Agent 3]
end
Agents ---> Output[Output]
T3 --> A1
T1 --> A2
T2 --> A3
style Tools fill:#189AB4,color:#fff
style Agents fill:#8B0000,color:#fff
style Input fill:#8B0000,color:#fff
style Output fill:#8B0000,color:#fff
| Feature | Knowledge | Tools |
|---|---|---|
| Purpose | Static reference information | Dynamic interaction capabilities |
| Access | Read-only reference | Execute actions and commands |
| Updates | Manual through files | Real-time through tool calls |
| Storage | Knowledge base | Assigned to specific agents |
| Persistence | Permanent until changed | Available during agent execution |
Tools are functions that agents can use to interact with external systems and perform actions. They are essential for creating agents that can do more than just process text.
Install the core package: ```bash Terminal pip install praisonaiagents duckduckgo-search ``` ```bash Terminal export OPENAI_API_KEY=your_openai_key ``` Generate your OpenAI API key from [OpenAI](https://platform.openai.com/api-keys) Use other LLM providers like Ollama, Anthropic, Groq, Google, etc. Please refer to the [Models](/models) for more information. Create `app.py` ```python Single Agent from praisonaiagents import Agent from duckduckgo_search import DDGSdef internet_search_tool(query: str): results = [] ddgs = DDGS() for result in ddgs.text(keywords=query, max_results=5): results.append({ "title": result.get("title", ""), "url": result.get("href", ""), "snippet": result.get("body", "") }) return results
search_agent = Agent( instructions="Perform internet searches to collect relevant information.", tools=[internet_search_tool] # <--- Tool Assignment )
search_agent.start("Search about AI job trends in 2025")
```python Multiple Agents
from praisonaiagents import Agent, PraisonAIAgents
from duckduckgo_search import DDGS
# 1. Define the tool
def internet_search_tool(query: str):
results = []
ddgs = DDGS()
for result in ddgs.text(keywords=query, max_results=5):
results.append({
"title": result.get("title", ""),
"url": result.get("href", ""),
"snippet": result.get("body", "")
})
return results
# 2. Assign the tool to an agent
search_agent = Agent(
instructions="Search about AI job trends in 2025",
tools=[internet_search_tool] # <--- Tool Assignment
)
blog_agent = Agent(
instructions="Write a blog article based on the previous agent's search results."
)
# 3. Start Agents
agents = PraisonAIAgents(agents=[search_agent, blog_agent])
agents.start()
def internet_search_tool(query: str) -> List[Dict]: """ Perform Internet Search """ results = [] ddgs = DDGS() for result in ddgs.text(keywords=query, max_results=5): results.append({ "title": result.get("title", ""), "url": result.get("href", ""), "snippet": result.get("body", "") }) return results
</Step>
<Step title="Create Agent">
Create a new file `agents.yaml` with the following content:
```yaml
framework: praisonai
topic: create movie script about cat in mars
roles:
scriptwriter:
backstory: Expert in dialogue and script structure, translating concepts into
scripts.
goal: Write a movie script about a cat in Mars
role: Scriptwriter
tools:
- internet_search_tool # <-- Tool assigned to Agent here
tasks:
scriptwriting_task:
description: Turn the story concept into a production-ready movie script,
including dialogue and scene details.
expected_output: Final movie script with dialogue and scene details.
Execute your script:
praisonai agents.yamldef internet_search_tool(query: str): results = [] ddgs = DDGS() for result in ddgs.text(keywords=query, max_results=5): results.append({ "title": result.get("title", ""), "url": result.get("href", ""), "snippet": result.get("body", "") }) return results
</Step>
<Step>
Assign the tool to an agent
```python
data_agent = Agent(
instructions="Search about AI job trends in 2025",
tools=[internet_search_tool], # <-- Tool Assignment
)
def internet_search_tool(query: str): results = [] ddgs = DDGS() for result in ddgs.text(keywords=query, max_results=5): results.append({ "title": result.get("title", ""), "url": result.get("href", ""), "snippet": result.get("body", "") }) return results
data_agent = Agent( name="DataCollector", role="Search Specialist", goal="Perform internet searches to collect relevant information.", backstory="Expert in finding and organising internet data.", tools=[internet_search_tool], self_reflect=False )
collect_task = Task( description="Perform an internet search using the query: 'AI job trends in 2024'. Return results as a list of title, URL, and snippet.", expected_output="List of search results with titles, URLs, and snippets.", agent=data_agent, name="collect_data", )
agents = PraisonAIAgents( agents=[data_agent], tasks=[collect_task], process="sequential" )
agents.start()
</Step>
<Step title="Start Agents">
Execute your script:
```bash Terminal
python app.py
def internet_search_tool(query: str) -> List[Dict]: """ Perform Internet Search """ results = [] ddgs = DDGS() for result in ddgs.text(keywords=query, max_results=5): results.append({ "title": result.get("title", ""), "url": result.get("href", ""), "snippet": result.get("body", "") }) return results
</Step>
<Step title="Create Agent">
Create a new file `agents.yaml` with the following content:
```yaml
framework: praisonai
topic: create movie script about cat in mars
roles:
scriptwriter:
backstory: Expert in dialogue and script structure, translating concepts into
scripts.
goal: Write a movie script about a cat in Mars
role: Scriptwriter
tools:
- internet_search_tool # <-- Tool assigned to Agent here
tasks:
scriptwriting_task:
description: Turn the story concept into a production-ready movie script,
including dialogue and scene details.
expected_output: Final movie script with dialogue and scene details.
Execute your script:
praisonai agents.yaml<Card title="File Tools" icon="file" iconType="solid"
Tools for reading, writing, and manipulating files
<Card title="API Tools" icon="code" iconType="solid"
Tools for interacting with external APIs and services
Args:
query (str): Search query
max_results (int): Maximum number of results
timeout (int): Request timeout in seconds
Returns:
List[Dict]: Search results
"""
# Tool implementation
pass
</Frame>
### Tool Chaining
<Frame>
```python
def chain_tools(input_data: str) -> Dict:
"""
Example of chaining multiple tools
Args:
input_data (str): Input data
Returns:
Dict: Processed results
"""
# 1. Search for data
search_results = internet_search_tool(input_data)
# 2. Process results
processed_data = process_tool(search_results)
# 3. Format output
return format_tool(processed_data)
Args:
data (Dict): Input data
Returns:
Dict: Processed data
"""
try:
import required_library
# Tool implementation
return processed_result
except ImportError:
raise Exception("Required library not installed")
</Frame>
## Tool Guidelines
<CardGroup cols={2}>
<Card title="Best Practices">
1. **Type Hints**
- Use Python type hints
- Define clear input/output types
- Document complex types
2. **Documentation**
- Write clear docstrings
- Explain parameters
- Provide usage examples
3. **Error Handling**
- Handle exceptions gracefully
- Return meaningful errors
- Validate inputs
</Card>
<Card title="Tool Types">
1. **Search Tools**
- Web search
- Database queries
- Document search
2. **File Tools**
- Read/write operations
- File conversion
- Data extraction
3. **API Tools**
- REST API calls
- GraphQL queries
- Service integration
</Card>
</CardGroup>
## Best Practices Summary
<Note>
Following these best practices will help you create robust, efficient, and secure tools in PraisonAI.
</Note>
<CardGroup cols={1}>
<Card title="Design Principles" icon="compass-drafting" iconType="solid">
<AccordionGroup>
<Accordion title="Single Responsibility">
Each tool should have one clear purpose and do it well. Avoid creating tools that try to do too many things.
```python
# Good Example
def process_image(image: np.array) -> np.array:
return processed_image
# Avoid
def process_and_save_and_upload(image):
# Too many responsibilities
pass
```
</Accordion>
<Accordion title="Clear Interfaces">
Define explicit input/output types and maintain consistent parameter naming.
```python
def search_tool(
query: str,
max_results: int = 10
) -> List[Dict[str, Any]]:
"""
Search for information with clear parameters
"""
pass
```
</Accordion>
<Accordion title="Documentation">
Always include detailed docstrings and type hints.
```python
def analyze_text(
text: str,
language: str = "en"
) -> Dict[str, float]:
"""
Analyze text sentiment and emotions.
Args:
text: Input text to analyze
language: ISO language code
Returns:
Dict with sentiment scores
"""
pass
```
</Accordion>
</AccordionGroup>
</Card>
</CardGroup>
<br />
<CardGroup cols={1}>
<Card title="Performance Optimization" icon="bolt" iconType="solid">
<AccordionGroup>
<Accordion title="Efficient Processing">
Optimize resource usage and processing time.
```python
# Use generators for large datasets
def process_large_data():
for chunk in data_generator():
yield process_chunk(chunk)
```
</Accordion>
<Accordion title="Resource Management">
Properly handle resource allocation and cleanup.
```python
async with aiohttp.ClientSession() as session:
# Resource automatically managed
await process_data(session)
```
</Accordion>
<Accordion title="Caching">
Implement caching for frequently accessed data.
```python
@cache.memoize(timeout=300)
def expensive_operation(data: str) -> Dict:
return process_expensive(data)
```
</Accordion>
<Accordion title="Async Operations">
Use async/await for I/O-bound operations.
```python
async def fetch_data(urls: List[str]):
async with aiohttp.ClientSession() as session:
tasks = [fetch_url(session, url) for url in urls]
return await asyncio.gather(*tasks)
```
</Accordion>
</AccordionGroup>
</Card>
</CardGroup>
<br />
<CardGroup cols={1}>
<Card title="Security Best Practices" icon="shield-check" iconType="solid">
<AccordionGroup>
<Accordion title="Input Validation">
Always validate and sanitize inputs to prevent security vulnerabilities.
```python
def process_user_input(data: str) -> str:
if not isinstance(data, str):
raise ValueError("Input must be string")
return sanitize_input(data.strip())
```
</Accordion>
<Accordion title="Rate Limiting">
Implement rate limiting for API calls to prevent abuse.
```python
@rate_limit(calls=100, period=60)
async def api_call():
return await make_request()
```
</Accordion>
<Accordion title="API Key Management">
Securely handle API keys and credentials using environment variables.
```python
# Use environment variables
api_key = os.getenv('API_KEY')
if not api_key:
raise ConfigError("API key not found")
```
</Accordion>
<Accordion title="Error Masking">
Hide sensitive information in error messages to prevent information leakage.
```python
try:
result = process_sensitive_data()
except Exception as e:
# Log detailed error internally
logger.error(f"Detailed error: {str(e)}")
# Return sanitized error to user
raise PublicError("Processing failed")
```
</Accordion>
</AccordionGroup>
</Card>
</CardGroup>
<br />
<Tip>
**Pro Tip**: Start with these practices from the beginning of your project. It's easier to maintain good practices than to retrofit them later.
</Tip>