DEV Community

Cover image for Tool Use AI Agents Python: Build Function-Calling Bots
Iniyarajan
Iniyarajan

Posted on

Tool Use AI Agents Python: Build Function-Calling Bots

Misconception Alert: Many developers think AI agents are just chatbots that can search the web. In reality, modern AI agents are sophisticated systems that can execute functions, manipulate databases, control APIs, and perform complex multi-step workflows — all through structured tool use patterns in Python.

We're living in the golden age of AI agents in 2026. The combination of advanced language models, robust Python frameworks, and standardized tool protocols has transformed how we build autonomous systems. But here's what most tutorials miss: the real power isn't in the AI model itself — it's in how we design and implement tool use patterns.

AI agents tools
Photo by Daniil Komov on Pexels

Table of Contents

Understanding Tool Use in AI Agents

When we talk about tool use AI agents in Python, we're referring to systems that can dynamically select and execute functions based on user requests or autonomous decision-making. Think of it as giving your AI agent a Swiss Army knife — but instead of physical tools, we're talking about Python functions, API calls, and data manipulation operations.

Related: Tool Use AI Agents Python: Build Smart Agents That Call Functions

The magic happens through function calling (also known as tool calling). Modern language models like GPT-4, Claude, and others can analyze a user's request, determine which functions are needed, extract the required parameters, and structure the response appropriately.

Also read: Complete RAG Tutorial Python: Build Your First Agent

Here's the basic flow we'll implement:

System Architecture

Python Frameworks for Tool-Enabled Agents

We have several excellent options for building tool use AI agents in Python. Each framework has its strengths:

LangChain remains the most popular choice for tool integration. Its extensive ecosystem and pre-built tools make it ideal for rapid prototyping.

LlamaIndex excels at RAG-based agents that need to work with large document collections while maintaining tool access.

CrewAI and AutoGen shine for multi-agent systems where different agents have specialized tool sets.

For this tutorial, we'll focus on LangChain because of its mature tool ecosystem and excellent documentation.

Building Your First Function-Calling Agent

Let's build a practical agent that can handle file operations, web searches, and basic calculations. This agent will demonstrate the core patterns you'll use in more complex systems.

from langchain.agents import create_openai_tools_agent, AgentExecutor
from langchain_openai import ChatOpenAI
from langchain.tools import Tool
from langchain_core.prompts import ChatPromptTemplate
import requests
import os
import json
from datetime import datetime

# Define custom tools
def search_web(query: str) -> str:
    """Search the web for information about a query."""
    # Using a simple search API (replace with your preferred service)
    try:
        # Placeholder for actual web search implementation
        return f"Search results for '{query}': [Relevant information would be returned here]"
    except Exception as e:
        return f"Search failed: {str(e)}"

def calculate_math(expression: str) -> str:
    """Safely evaluate mathematical expressions."""
    try:
        # Simple math evaluation (be careful with eval in production!)
        result = eval(expression.replace('^', '**'))  # Handle exponents
        return f"Result: {result}"
    except Exception as e:
        return f"Calculation error: {str(e)}"

def write_file(filename: str, content: str) -> str:
    """Write content to a file in the current directory."""
    try:
        with open(filename, 'w') as f:
            f.write(content)
        return f"Successfully wrote to {filename}"
    except Exception as e:
        return f"File write error: {str(e)}"

# Create tools list
tools = [
    Tool(
        name="web_search",
        func=search_web,
        description="Search the web for current information about any topic"
    ),
    Tool(
        name="calculator",
        func=calculate_math,
        description="Perform mathematical calculations. Use standard math notation."
    ),
    Tool(
        name="file_writer",
        func=write_file,
        description="Write text content to a file. Requires filename and content parameters."
    )
]

# Initialize the language model
llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)

# Create the agent prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant with access to tools. Use them when needed to complete tasks effectively."),
    ("user", "{input}"),
    ("placeholder", "{agent_scratchpad}")
])

# Create and configure the agent
agent = create_openai_tools_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# Example usage
if __name__ == "__main__":
    # Test the agent with different types of requests
    response = agent_executor.invoke({
        "input": "Calculate 15 * 23 + 87, then write the result to a file called 'calculation_result.txt'"
    })
    print(response["output"])
Enter fullscreen mode Exit fullscreen mode

This example demonstrates several key concepts:

  1. Tool Definition: Each tool is a Python function with a clear description
  2. Agent Creation: We use LangChain's built-in agent factory
  3. Execution Flow: The agent reasons about which tools to use and in what order

Advanced Tool Orchestration Patterns

Once we master basic tool use, we can implement more sophisticated patterns. Here's where multi-step reasoning and tool chaining become powerful.

Process Flowchart

Consider this advanced pattern where an agent needs to research a topic, process the information, and create a summary report:

from langchain.schema import AgentAction
from typing import List, Dict, Any
import asyncio

class ResearchAgent:
    def __init__(self, llm, tools):
        self.llm = llm
        self.tools = {tool.name: tool for tool in tools}
        self.memory = []

    async def execute_research_workflow(self, topic: str) -> Dict[str, Any]:
        """Execute a multi-step research workflow with tool orchestration."""
        workflow_steps = [
            self._gather_information,
            self._analyze_data,
            self._generate_summary,
            self._create_report
        ]

        context = {"topic": topic, "findings": [], "analysis": None}

        for step in workflow_steps:
            context = await step(context)
            self.memory.append({"step": step.__name__, "context": context.copy()})

        return context

    async def _gather_information(self, context: Dict) -> Dict:
        """Use search tools to gather information."""
        search_results = self.tools["web_search"].func(context["topic"])
        context["findings"].append(search_results)
        return context

    async def _analyze_data(self, context: Dict) -> Dict:
        """Process gathered information."""
        # Use the LLM to analyze findings
        analysis_prompt = f"Analyze these findings about {context['topic']}: {context['findings']}"
        analysis = await self.llm.ainvoke([{"role": "user", "content": analysis_prompt}])
        context["analysis"] = analysis.content
        return context

    async def _generate_summary(self, context: Dict) -> Dict:
        """Create a structured summary."""
        summary_prompt = f"Create a structured summary based on this analysis: {context['analysis']}"
        summary = await self.llm.ainvoke([{"role": "user", "content": summary_prompt}])
        context["summary"] = summary.content
        return context

    async def _create_report(self, context: Dict) -> Dict:
        """Generate final report and save to file."""
        report_content = f"""
# Research Report: {context['topic']}

## Summary
{context['summary']}

## Detailed Analysis
{context['analysis']}

## Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""

        filename = f"research_report_{context['topic'].replace(' ', '_')}.md"
        self.tools["file_writer"].func(filename, report_content)
        context["report_file"] = filename
        return context
Enter fullscreen mode Exit fullscreen mode

This pattern shows how we can chain tools together in sophisticated workflows. The agent maintains context between steps and builds up a complete picture before generating the final output.

Memory Systems and Tool Context

One challenge with tool use AI agents in Python is maintaining context across multiple tool invocations. We need systems that remember what tools were used, what results were obtained, and how that information relates to the current task.

Here's a memory-enhanced agent pattern:

from langchain.memory import ConversationBufferWindowMemory
from langchain.schema import BaseMessage
from datetime import datetime
import json

class MemoryEnhancedAgent:
    def __init__(self, llm, tools, memory_window=10):
        self.llm = llm
        self.tools = tools
        self.memory = ConversationBufferWindowMemory(
            k=memory_window,
            return_messages=True
        )
        self.tool_usage_history = []

    def execute_with_memory(self, user_input: str):
        """Execute agent with persistent memory of tool usage."""
        # Get conversation history
        history = self.memory.chat_memory.messages

        # Create context-aware prompt
        context_prompt = self._build_context_prompt(user_input, history)

        # Execute agent
        result = self._execute_agent_step(context_prompt)

        # Update memory
        self.memory.chat_memory.add_user_message(user_input)
        self.memory.chat_memory.add_ai_message(result["output"])

        return result

    def _build_context_prompt(self, user_input: str, history: List[BaseMessage]):
        """Build a context-aware prompt that includes tool usage history."""
        recent_tools = self._get_recent_tool_usage()

        context = f"""
You are an AI assistant with access to tools. Here's the recent context:

Recent Tool Usage:
{json.dumps(recent_tools, indent=2)}

Conversation History:
{self._format_history(history)}

Current Request: {user_input}

Use this context to provide more informed responses and avoid redundant tool calls.
"""
        return context

    def _get_recent_tool_usage(self, limit=5):
        """Get recent tool usage for context."""
        return self.tool_usage_history[-limit:] if self.tool_usage_history else []

    def _format_history(self, messages: List[BaseMessage]):
        """Format conversation history for context."""
        formatted = []
        for msg in messages[-6:]:  # Last 6 messages
            role = "Human" if msg.type == "human" else "Assistant"
            formatted.append(f"{role}: {msg.content[:200]}...")  # Truncate long messages
        return "\n".join(formatted)
Enter fullscreen mode Exit fullscreen mode

This memory system helps agents make better decisions about tool use by understanding what's already been done and what information is already available.

Production Deployment Strategies

When deploying tool use AI agents in Python to production, we need to consider several factors: security, scalability, monitoring, and error handling.

Security First: Never execute arbitrary code or give agents access to sensitive system functions without proper sandboxing.

Rate Limiting: Implement proper rate limiting for API calls and expensive operations.

Monitoring: Track tool usage patterns, success rates, and performance metrics.

Error Recovery: Build robust error handling that gracefully degrades when tools fail.

Consider using containerization with Docker for consistent deployment environments, and implement proper logging to track agent decision-making processes.

Frequently Asked Questions

Q: How do I prevent my AI agent from making too many expensive API calls?

Implement rate limiting and cost tracking at the tool level. Use caching for repeated queries and set maximum usage limits per session. Consider implementing a "budget" system where each tool call has a cost associated with it.

Q: What's the best way to handle errors when tools fail in Python AI agents?

Implement a hierarchy of fallback strategies. First, retry with exponential backoff. If that fails, try alternative tools that might accomplish the same task. Finally, gracefully inform the user about the limitation and suggest manual alternatives.

Q: How can I test tool use AI agents effectively?

Create mock versions of your tools that return predictable responses for unit testing. Use integration tests with real APIs in staging environments. Implement logging to capture the agent's decision-making process for debugging.

Q: Should I use function calling or text-based tool descriptions?

Function calling (structured tool use) is generally more reliable and easier to debug than text-based descriptions. Modern language models handle function calling very well, and it provides better type safety and parameter validation.

The future of tool use AI agents in Python is incredibly bright in 2026. As models become more capable and frameworks mature, we're seeing agents that can handle increasingly complex workflows with minimal human intervention. The key is building robust, well-tested tool ecosystems that agents can reliably orchestrate.

Start with simple tools and gradually add complexity. Focus on creating clear, well-documented functions that do one thing well. Most importantly, always maintain human oversight for critical operations and never fully automate processes that could have significant real-world consequences without proper safeguards.

Need a server? Get $200 free credits on DigitalOcean to deploy your AI apps.

Resources I Recommend

If you're diving deep into building AI agents with tool capabilities, these AI and LLM engineering books provide excellent coverage of the architectural patterns and best practices you'll need for production systems.

For RAG integration with your tool-enabled agents, these RAG and vector database books cover the essential patterns for combining retrieval with function calling — a powerful combination for knowledge-intensive agent workflows.

You Might Also Like


📘 Go Deeper: Building AI Agents: A Practical Developer's Guide

185 pages covering autonomous systems, RAG, multi-agent workflows, and production deployment — with complete code examples.

Get the ebook →


Also check out: *AI-Powered iOS Apps: CoreML to Claude***

Enjoyed this article?

I write daily about iOS development, AI, and modern tech — practical tips you can use right away.

  • Follow me on Dev.to for daily articles
  • Follow me on Hashnode for in-depth tutorials
  • Follow me on Medium for more stories
  • Connect on Twitter/X for quick tips

If this helped you, drop a like and share it with a fellow developer!

Top comments (0)