![]() |
VOOZH | about |
We’re so glad you’re here. You can expect all the best TNS content to arrive Monday through Friday to keep you on top of the news and at the top of your game.
Check your inbox for a confirmation email where you can adjust your preferences and even join additional groups.
Follow TNS on your favorite social media networks.
Become a TNS follower on LinkedIn.
Check out the latest featured and trending stories while you wait for your first TNS newsletter.
In the process of developing a framework for implementing AI agents, we have explored core components like personas, instructions, tasks, and execution strategies. These elements shape the cognitive processes of the agents. However, in the modern interconnected enterprise environment, cognitive processes alone are insufficient. Agents must be able to act, extending beyond their internal knowledge to interact with the external world.
This is where tools come into play — they are the hands and eyes of our AI agents, extending their capabilities far beyond simple text generation and static knowledge cutoffs. Just as human employees rely on various software tools, databases, and APIs to accomplish their tasks, AI agents need similar capabilities to be truly effective in an enterprise setting.
The impact of tool integration cannot be overstated. With properly implemented tool support, agents transform from simple chat interfaces into capable digital workers that can:
However, implementing tool support isn’t just about connecting APIs — it requires careful consideration of architecture, security, error handling, and user experience. In this article, we’ll explore how to design and implement a robust tool system for AI agents, using practical examples that you can adapt for your own enterprise applications.
At its core, tool support consists of three main components:
Let’s break down each component and see how they work together.
First, let’s look at the abstract base class that all tools must implement:
from abc import ABC, abstractmethod
from typing import Any, Dict, Optional
from dataclasses import dataclass
@dataclass
class ToolResult:
"""Represents the result of a tool execution."""
success: bool
data: Any
error: Optional[str] = None
class Tool(ABC):
"""Base class for all tools."""
@property
@abstractmethod
def name(self) -> str:
"""The name of the tool."""
pass
@property
@abstractmethod
def description(self) -> str:
"""Description of what the tool does."""
pass
@property
@abstractmethod
def parameters(self) -> Dict[str, str]:
"""Dictionary of parameter names and their descriptions."""
pass
@abstractmethod
def execute(self, **kwargs) -> ToolResult:
"""Execute the tool with the given parameters."""
pass
def to_prompt_format(self) -> str:
"""Convert tool information to a format suitable for prompts."""
params_str = "\n".join(f" - {name}: {desc}" for name, desc in self.parameters.items())
return f"""Tool: {self.name}
Description: {self.description}
Parameters:
{params_str}"""
The tool registry manages the available tools and provides methods to access them:
class ToolRegistry:
"""Registry for managing available tools."""
def __init__(self):
self._tools: Dict[str, Tool] = {}
def register(self, tool: Tool) -> None:
"""Register a new tool."""
if not isinstance(tool, Tool):
raise TypeError("Tool must be an instance of Tool class")
self._tools[tool.name] = tool
def get_tool(self, name: str) -> Optional[Tool]:
"""Get a tool by name."""
return self._tools.get(name)
def list_tools(self) -> List[str]:
"""List all registered tool names."""
return list(self._tools.keys())
def get_tools_prompt(self) -> str:
"""Get a formatted string of all tools for use in prompts."""
if not self._tools:
return "No tools available."
tools_str = "\n\n".join(tool.to_prompt_format() for tool in self._tools.values())
return f"""Available Tools:
{tools_str}
To use a tool, specify it in your response as:
Tool: [tool_name]
Parameters:
- param1: value1
- param2: value2
"""
Let’s now look at two concrete tool implementations: Wikipedia search and web search.
import wikipedia
from typing import Dict, Any
from tools import Tool, ToolResult
class WikipediaTool(Tool):
"""Tool for searching Wikipedia"""
@property
def name(self) -> str:
return "wikipedia_search"
@property
def description(self) -> str:
return "Search Wikipedia for information about a topic"
@property
def parameters(self) -> Dict[str, Dict[str, Any]]:
return {
"query": {
"type": "string",
"description": "The Wikipedia search query"
}
}
def execute(self, **kwargs) -> ToolResult:
try:
query = kwargs.get("query")
print(f"Searching Wikipedia for: {query}")
search_results = wikipedia.search(query)
if not search_results:
return ToolResult(
success=True,
data="No Wikipedia articles found for the query."
)
page = wikipedia.page(search_results[0])
summary = page.summary[:500] + "..."
return ToolResult(
success=True,
data=f"Title: {page.title}\nSummary: {summary}"
)
except Exception as e:
return ToolResult(
success=False,
data="",
error=f"Wikipedia search failed: {str(e)}"
)
import os
from typing import Dict, Any
from tools import Tool, ToolResult
from tavily import TavilyClient
class WebSearchTool(Tool):
"""Tool for performing web searches using Tavily API"""
def __init__(self):
"""Initialize the web search tool with API key."""
self.api_key = os.getenv('TAVILY_API_KEY', '')
if not self.api_key:
raise ValueError("TAVILY_API_KEY environment variable not set")
@property
def name(self) -> str:
return "web_search"
@property
def description(self) -> str:
return "Search the web for information about a topic"
@property
def parameters(self) -> Dict[str, Dict[str, Any]]:
return {
"query": {
"type": "string",
"description": "The search query to look up"
}
}
def execute(self, **kwargs) -> ToolResult:
try:
query = kwargs.get("query")
if not query:
return ToolResult(
success=False,
data="",
error="No query provided"
)
client = TavilyClient(api_key=self.api_key)
search_response = client.search(query=query)
# Take the top 3 results
results = search_response['results'][:3]
# Format results
formatted_results = []
for result in results:
formatted_results.append({
"title": result.get('title', 'No title'),
"content": result.get('content', 'No content'),
"url": result.get('url', 'No URL')
})
formatted_output = self._format_search_results(formatted_results)
return ToolResult(
success=True,
data=formatted_output
)
except Exception as e:
return ToolResult(
success=False,
data="",
error=f"Web search failed: {str(e)}"
)
Here’s how to integrate tools with an agent:
from agent import Agent
from wikipedia_tool import WikipediaTool
from websearch_tool import WebSearchTool
# Initialize agent and tools
agent = Agent("research_agent")
wiki_tool = WikipediaTool()
web_tool = WebSearchTool()
# Register tools with the agent
agent.tools = [wiki_tool, web_tool]
# Set up agent persona
agent.persona = """I am a research assistant with access to both Wikipedia and web search.
I can find information from multiple sources to provide comprehensive answers."""
# Execute a task
response = agent.execute("What are the latest developments in quantum computing?")
print(response)
When an agent uses a tool, the process follows these steps:
CopyTool: [tool_name]
Parameters:
- param1: value1
The parse_tool_usage function handles extracting tool information from the agent’s response:
def parse_tool_usage(response: str) -> Optional[Dict[str, Any]]:
"""Parse a response string to extract tool usage information."""
try:
if "Tool:" not in response:
return None
lines = response.split('\n')
tool_info = {}
# Find tool name
for i, line in enumerate(lines):
if line.startswith("Tool:"):
tool_info["name"] = line.replace("Tool:", "").strip()
break
# Find parameters
params = {}
for line in lines:
if ":" in line and "-" in line:
param_line = line.split(":", 1)
param_name = param_line[0].replace("-", "").strip()
param_value = param_line[1].strip()
params[param_name] = param_value
tool_info["parameters"] = params
return tool_info
except Exception:
return None
Tool support is a crucial feature that makes AI agents more capable and practical for real-world applications. By following the patterns and practices outlined in this article, you can create a robust and extensible tool system for your agents. The combination of a clear base interface, an efficient registry system, and well-implemented concrete tools provides a solid foundation for building sophisticated agent capabilities.
Remember that tools should be designed to be:
With these principles in mind, you can create powerful tools that enhance your agents’ capabilities and make them more useful for real-world tasks.
This concludes the series on AI agents, where we implemented an end-to-end framework to explore crucial capabilities and functions agents.