Using Tools in YAML

Reference built-in tools by name in your YAML configuration files

How It Works

Diagram
Using Tools in YAMLAgentUserUsing Tools in YAMLAgentUserRequestProcess requestResultResponse

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.

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

Diagram

agents.yaml

Agent

🤖 Agent with Tools

Tool Resolution

Unsupported markdown: list
Unsupported markdown: list
Unsupported markdown: list

tools: [tavily_search]

Quick Start

  1. 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
  2. Run Your Agents

    No tools.py needed – tools are auto-resolved:

    bash
    praisonai run agents.yaml

Tool Sources

Resolution Order

Tools are resolved in this order (first match wins):

Diagram

Result

3️⃣ External Tools

2️⃣ Built-in Tools

1️⃣ Local tools.py

Tool Name: tavily_search

Not Found

Found

Not Found

Found

Found

‘tavily_search’

Check local file

Check praisonaiagents.tools

Check praisonai-tools

✅ Callable Function

Available Built-in Tools

Search Tools
ToolDescription
tavily_searchAI-powered web search
tavily_extractExtract content from URLs
internet_searchDuckDuckGo search
exa_searchExa semantic search
search_webUnified search (auto-fallback)
File Tools
ToolDescription
read_fileRead file contents
write_fileWrite to files
list_filesList directory contents
copy_fileCopy files
delete_fileDelete files
Shell Tools
ToolDescription
execute_commandRun shell commands
list_processesList running processes
kill_processTerminate processes
get_system_infoSystem information
Web Crawling
ToolDescription
crawl4aiAsync web crawling
crawl4ai_extractExtract with CSS selectors
scrape_pageSpider page scraping
extract_linksExtract page links

CLI Commands

List Available Tools

bash
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

bash
praisonai tools validate agents.yaml

Valid

✓ All tools in agents.yaml are valid!
Tools found: internet_search, tavily_search

Invalid

✗ Missing tools in agents.yaml:
  • nonexistent_tool

Hint: Run 'praisonai tools list' to see available tools.

Get Tool Info

bash
praisonai tools info tavily_search

Custom Tools (tools.py)

For custom logic or variables, create a tools.py file:

tools.py
# 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:

agents.yaml
roles:
  researcher:
    tools:
      - my_custom_tool    # From local tools.py
      - api_search        # From local tools.py
      - tavily_search     # Built-in (still works!)

Examples

Simple Search Agent
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 summary
Multi-Tool Agent
framework: 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 guide
With Custom Tools
framework: 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 report

Troubleshooting

Tool not found
  1. Check the tool name spelling
  2. Run praisonai tools list to see available tools
  3. If using external tools, ensure praisonai-tools is installed:
bash
pip install praisonai-tools
Tool not working as expected
  1. Check if the tool requires an API key (e.g., TAVILY_API_KEY)
  2. Run praisonai tools info <tool_name> for details
  3. 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:

python
def tavily_search(query: str) -> str:
    """My custom tavily_search implementation."""
    # Your code here
    return "custom result"

Per-Agent Tool Resolution

python
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:

Diagram

Multi-Agent Tool Isolation

🤖 Agent A

🔧 Resolver A

🤖 Agent B

🔧 Resolver B

📂 tools_a.py

📂 tools_b.py

python
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.py is only read once, praisonai-tools is only probed once.
  • CWD-anchored — the cached resolver picks up ./tools.py from whatever directory was active when the first call happened.
  • Need isolation? Pass an explicit resolver=ToolResolver(...) instance — the cached default is bypassed.
python
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"))
Diagram

No

Yes

Need test isolation
or per-agent tools.py?

Use convenience functions
e.g. resolve_tool name

Construct ToolResolver and
pass via resolver= argument

⚡ Cached default – fast

🔒 Isolated – explicit


Configuration Options

Convenience Functions (with optional resolver parameter)

FunctionSignatureDescription
resolve_toolresolve_tool(name: str, resolver: Optional[ToolResolver] = None) -> Optional[Callable]Resolve single tool
resolve_toolsresolve_tools(names: List[str], resolver: Optional[ToolResolver] = None) -> List[Callable]Resolve multiple tools
list_available_toolslist_available_tools(resolver: Optional[ToolResolver] = None) -> Dict[str, str]List all available tools
has_toolhas_tool(name: str, resolver: Optional[ToolResolver] = None) -> boolCheck if tool exists
validate_yaml_toolsvalidate_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

MethodDescriptionThread 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

python
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"])

Related