Tool Calling Architecture

Tool Execution Flow:
Intent Recognition → Tool Selection → Parameter Extraction → Execution → Result Integration
Analyze
Select
Execute
Integrate
Key Components:
  • Tool Registry and Discovery
  • Parameter Validation and Mapping
  • Execution Engine and Error Handling
  • Result Processing and Integration
Tool Implementation Example
from langchain.tools import BaseTool
from typing import Optional, Type
from pydantic import BaseModel, Field

class CalculatorInput(BaseModel):
    expression: str = Field(description="Mathematical expression to evaluate")

class CalculatorTool(BaseTool):
    name = "calculator"
    description = "Useful for mathematical calculations"
    args_schema: Type[BaseModel] = CalculatorInput
    
    def _run(self, expression: str) -> str:
        try:
            # Safe evaluation of mathematical expressions
            result = eval(expression, {"__builtins__": {}}, {})
            return f"Result: {result}"
        except Exception as e:
            return f"Error: {str(e)}"
    
    async def _arun(self, expression: str) -> str:
        return self._run(expression)

class DatabaseQueryTool(BaseTool):
    name = "database_query"
    description = "Query database for information"
    
    def __init__(self, connection_string: str):
        super().__init__()
        self.db = Database(connection_string)
    
    def _run(self, query: str) -> str:
        try:
            # Validate query for safety
            if not self.is_safe_query(query):
                return "Error: Unsafe query detected"
            
            results = self.db.execute(query)
            return self.format_results(results)
        except Exception as e:
            return f"Database error: {str(e)}"
    
    def is_safe_query(self, query: str) -> bool:
        # Implement query validation logic
        forbidden_keywords = ['DROP', 'DELETE', 'UPDATE', 'INSERT']
        return not any(keyword in query.upper() for keyword in forbidden_keywords)

class APICallTool(BaseTool):
    name = "api_call"
    description = "Make HTTP API calls to external services"
    
    def __init__(self, base_url: str, api_key: str):
        super().__init__()
        self.base_url = base_url
        self.api_key = api_key
        self.session = requests.Session()
        self.session.headers.update({"Authorization": f"Bearer {api_key}"})
    
    def _run(self, endpoint: str, method: str = "GET", data: dict = None) -> str:
        try:
            url = f"{self.base_url}/{endpoint}"
            
            # Rate limiting
            if not self.check_rate_limit():
                return "Error: Rate limit exceeded"
            
            response = self.session.request(method, url, json=data)
            response.raise_for_status()
            
            return json.dumps(response.json(), indent=2)
        except Exception as e:
            return f"API error: {str(e)}"
    
    def check_rate_limit(self) -> bool:
        # Implement rate limiting logic
        return True

# Tool orchestration with LangChain
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_openai import ChatOpenAI

def create_agent_with_tools():
    # Initialize LLM
    llm = ChatOpenAI(model="gpt-4", temperature=0)
    
    # Create tools
    tools = [
        CalculatorTool(),
        DatabaseQueryTool("postgresql://localhost/mydb"),
        APICallTool("https://api.example.com", "your-api-key"),
        # Add more tools as needed
    ]
    
    # Create agent
    agent = create_tool_calling_agent(llm, tools, prompt_template)
    
    # Create executor with error handling
    agent_executor = AgentExecutor(
        agent=agent,
        tools=tools,
        verbose=True,
        max_iterations=10,
        handle_parsing_errors=True
    )
    
    return agent_executor

# Usage example
agent = create_agent_with_tools()
result = agent.invoke({
    "input": "Calculate the square root of 144 and then query the database for users with that ID"
})