Using Tools in YAML
Reference built-in tools by name in your YAML configuration files
How It Works
When you specify tools in your YAML configuration, PraisonAI automatically resolves them from multiple sources. Only tools you list under tools: in your YAML (under each role and each task) are loaded. Misspelled or unknown tool names now produce a warning log line, not a silent skip.
from praisonaiagents import Agent
agent = Agent(name="Researcher", tools=["tavily_search"])
agent.start("Summarise today's AI headlines")The user lists tools in agents.yaml; PraisonAI resolves built-ins and runs the configured agent.
Quick Start
- Create YAML File
Reference tools by name in your
agents.yaml:agents.yaml framework: praisonai topic: "AI News" roles: researcher: role: AI Researcher goal: Search for the latest AI news backstory: Expert researcher tools: - tavily_search - internet_search tasks: search_task: description: Search for {topic} expected_output: Summary of findings - Run Your Agents
No
tools.pyneeded – tools are auto-resolved:bash praisonai run agents.yaml
Tool Sources
70+ tools from praisonaiagents.tools
tavily_searchinternet_searchexecute_commandread_file- And more…
Custom tools you create
- Takes precedence
- Full control
- Custom variables
120+ tools from praisonai-tools
EmailToolSlackToolGitHubTool- And more…
Resolution Order
Tools are resolved in this order (first match wins):
Available Built-in Tools
Search Tools
| Tool | Description |
|---|---|
tavily_search | AI-powered web search |
tavily_extract | Extract content from URLs |
internet_search | DuckDuckGo search |
exa_search | Exa semantic search |
search_web | Unified search (auto-fallback) |
File Tools
| Tool | Description |
|---|---|
read_file | Read file contents |
write_file | Write to files |
list_files | List directory contents |
copy_file | Copy files |
delete_file | Delete files |
Shell Tools
| Tool | Description |
|---|---|
execute_command | Run shell commands |
list_processes | List running processes |
kill_process | Terminate processes |
get_system_info | System information |
Web Crawling
| Tool | Description |
|---|---|
crawl4ai | Async web crawling |
crawl4ai_extract | Extract with CSS selectors |
scrape_page | Spider page scraping |
extract_links | Extract page links |
CLI Commands
List Available Tools
praisonai tools list┌─────────────────────────────────────────────────┐
│ Available Tools │
├──────────────────┬──────────┬───────────────────┤
│ Tool Name │ Source │ Description │
├──────────────────┼──────────┼───────────────────┤
│ crawl4ai │ builtin │ Built-in tool... │
│ execute_command │ builtin │ Built-in tool... │
│ internet_search │ builtin │ Built-in tool... │
│ tavily_search │ builtin │ Built-in tool... │
│ my_custom_tool │ local │ My custom tool... │
└──────────────────┴──────────┴───────────────────┘Validate YAML Tools
praisonai tools validate agents.yamlValid
✓ All tools in agents.yaml are valid!
Tools found: internet_search, tavily_searchInvalid
✗ Missing tools in agents.yaml:
• nonexistent_tool
Hint: Run 'praisonai tools list' to see available tools.Get Tool Info
praisonai tools info tavily_searchCustom Tools (tools.py)
For custom logic or variables, create a tools.py file:
# Custom tool with your own logic
def my_custom_tool(query: str) -> str:
"""Search using my custom API."""
# Your implementation
return f"Results for: {query}"
# Custom variables
API_KEY = "your-key"
BASE_URL = "https://api.example.com"
def api_search(query: str) -> dict:
"""Search with custom API."""
import requests
response = requests.get(f"{BASE_URL}/search?q={query}&key={API_KEY}")
return response.json()Then reference in YAML:
roles:
researcher:
tools:
- my_custom_tool # From local tools.py
- api_search # From local tools.py
- tavily_search # Built-in (still works!)Examples
framework: praisonai
topic: "Latest AI developments"
roles:
researcher:
role: AI Researcher
goal: Find and summarize AI news
backstory: Expert in AI research
tools:
- tavily_search
tasks:
research:
description: Search for {topic}
expected_output: Detailed summaryframework: praisonai
topic: "Python web scraping"
roles:
developer:
role: Developer
goal: Research and implement solutions
backstory: Senior Python developer
tools:
- tavily_search
- internet_search
- execute_command
- read_file
- write_file
tasks:
research:
description: Research {topic}
expected_output: Implementation guideframework: praisonai
topic: "Company data"
roles:
analyst:
role: Data Analyst
goal: Analyze company data
backstory: Expert analyst
tools:
- my_database_query # From tools.py
- tavily_search # Built-in
tasks:
analyze:
description: Analyze {topic}
expected_output: Analysis reportTroubleshooting
Tool not found
- Check the tool name spelling
- Run
praisonai tools listto see available tools - If using external tools, ensure
praisonai-toolsis installed:
pip install praisonai-toolsTool not working as expected
- Check if the tool requires an API key (e.g.,
TAVILY_API_KEY) - Run
praisonai tools info <tool_name>for details - Test the tool:
praisonai tools test <tool_name>
Want to override a built-in tool
Create a tools.py file with a function of the same name:
def tavily_search(query: str) -> str:
"""My custom tavily_search implementation."""
# Your code here
return "custom result"Per-Agent Tool Resolution
from praisonaiagents import Agent
from praisonai.tool_resolver import ToolResolver
# Single agent with default resolver
agent = Agent(
name="ResearchAgent",
instructions="Research AI topics using tools",
tools=["tavily_search", "web_scraper"]
)
agent.start("Search for latest AI developments")Multi-agent: one resolver per agent
When agents need different tools_py_path values, construct separate resolvers:
from praisonai.tool_resolver import ToolResolver, resolve_tool
resolver_a = ToolResolver(tools_py_path="agents/a/tools.py")
resolver_b = ToolResolver(tools_py_path="agents/b/tools.py")
tool_a = resolve_tool("my_tool", resolver=resolver_a)
tool_b = resolve_tool("my_tool", resolver=resolver_b)Caching Behaviour
The convenience functions (resolve_tool, resolve_tools, list_available_tools, has_tool, validate_yaml_tools) share a single cached ToolResolver for the whole process. This means:
- Fast repeated calls —
tools.pyis only read once,praisonai-toolsis only probed once. - CWD-anchored — the cached resolver picks up
./tools.pyfrom whatever directory was active when the first call happened. - Need isolation? Pass an explicit
resolver=ToolResolver(...)instance — the cached default is bypassed.
from praisonai.tool_resolver import resolve_tool, ToolResolver
# Uses cached default — fast, anchored to current working directory
tool = resolve_tool("tavily_search")
# Explicit resolver — isolated, useful in tests or multi-project CLIs
tool = resolve_tool("tavily_search", resolver=ToolResolver(tools_py_path="agents/a/tools.py"))Configuration Options
Convenience Functions (with optional resolver parameter)
| Function | Signature | Description |
|---|---|---|
resolve_tool | resolve_tool(name: str, resolver: Optional[ToolResolver] = None) -> Optional[Callable] | Resolve single tool |
resolve_tools | resolve_tools(names: List[str], resolver: Optional[ToolResolver] = None) -> List[Callable] | Resolve multiple tools |
list_available_tools | list_available_tools(resolver: Optional[ToolResolver] = None) -> Dict[str, str] | List all available tools |
has_tool | has_tool(name: str, resolver: Optional[ToolResolver] = None) -> bool | Check if tool exists |
validate_yaml_tools | validate_yaml_tools(yaml_config: Dict[str, Any], resolver: Optional[ToolResolver] = None) -> List[str] | Returns tool names in a parsed YAML config that nothing can resolve. Walks agent-level tools, task-level tasks[*].tools (since PR #5754), and toolsets. Tools in tools.py, tools/, and .praisonai/tools/ are accepted, matching the build path. |
ToolResolver Class
| Method | Description | Thread Safe |
|---|---|---|
resolve(name, instantiate=False) | Resolve single tool name. Pass instantiate=True to get an instance of class tools (BaseTool / langchain) instead of the raw class. | ✅ |
resolve_many(names) | Resolve multiple tool names | ✅ |
list_available() | List available tools | ✅ |
has_tool(name) | Check if tool exists | ✅ |
clear_cache() | Clear local tools cache | ✅ (lock-protected) |
Python Usage
from praisonai.tool_resolver import ToolResolver, resolve_tool
# Option 1: Use convenience functions with default resolver
tool = resolve_tool("tavily_search")
tools = resolve_tools(["tavily_search", "internet_search"])
available = list_available_tools()
# Option 2: Use convenience functions with custom resolver
resolver = ToolResolver(tools_py_path="custom/tools.py")
tool = resolve_tool("tavily_search", resolver=resolver)
tools = resolve_tools(["tavily_search"], resolver=resolver)
# Option 3: Use resolver instance directly
resolver = ToolResolver()
tool = resolver.resolve("tavily_search")
tools = resolver.resolve_many(["tavily_search", "internet_search"])