RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Eruo Fredoline
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /How-to
  5. /How to Implement Tool Use in AI Agents
HOW-TO · RAG

How to Implement Tool Use in AI Agents

intermediate·20 min·By Eruo Fredoline
Target environment
Ubuntu 24.04 · Ollama 0.4.x
PREREQUISITES

Agent framework set up, tool functions defined, Python 3.10+

What this does

Tool use enables agents to go beyond text generation by calling external functions — APIs, databases, calculators — and incorporating the results into their reasoning. This guide integrates tools into the agent decision loop.

Steps

  • Define tools as callable functions with metadata. Each tool needs a name, description, and parameter schema.
def search_web(query: str, max_results: int = 5) -> list[dict]:
    """Search the web for a query."""
    # Implementation: call search API
    return [{"title": "Result 1", "url": "https://example.com"}]

def calculate(expression: str) -> str:
    """Evaluate a mathematical expression."""
    return str(eval(expression))

TOOL_SCHEMAS = [
    {
        "type": "function",
        "function": {
            "name": "search_web",
            "description": "Search the web for information",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "Search query"},
                    "max_results": {"type": "integer", "default": 5}
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "Evaluate a math expression",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {"type": "string"}
                },
                "required": ["expression"]
            }
        }
    }
]
  • Map tool names to functions.
TOOL_MAP = {
    "search_web": search_web,
    "calculate": calculate,
}
  • Process tool calls in the agent loop. After the LLM responds, check for tool calls.
def process_tool_calls(message, messages):
    for tc in message.tool_calls:
        func = TOOL_MAP.get(tc.function.name)
        if not func:
            result = {"error": f"Unknown tool: {tc.function.name}"}
        else:
            args = json.loads(tc.function.arguments)
            try:
                result = func(**args)
            except Exception as e:
                result = {"error": str(e)}

        messages.append({
            "role": "tool",
            "tool_call_id": tc.id,
            "content": json.dumps(result)
        })
  • Add tool output formatting. Convert complex results to text the LLM can understand.
def format_tool_result(result) -> str:
    if isinstance(result, list):
        items = "\n".join(f"- {r['title']}: {r['url']}" for r in result[:5])
        return f"Search results:\n{items}"
    return str(result)
  • Handle parallel tool calls. The LLM may request multiple tools in one response. Execute them concurrently.
import asyncio

async def process_parallel_tool_calls(tool_calls):
    async def call(tc):
        func = TOOL_MAP[tc.function.name]
        args = json.loads(tc.function.arguments)
        return tc.id, await asyncio.to_thread(func, **args)

    tasks = [call(tc) for tc in tool_calls]
    results = await asyncio.gather(*tasks)
    return [{"tool_call_id": tid, "content": str(r)} for tid, r in results]

Verification

python -c "
from langchain.tools import tool
@tool
def double(n: int) -> int:
    '''Double a number.'''
    return n * 2
print(double.invoke({'n': 21}))
# Expected: 42
"

Common failures

  • Tool function signature mismatch. The LLM may pass string arguments when the function expects integers. Add type coercion.
  • No error handling in tool execution. A tool that raises an unhandled exception breaks the agent loop. Wrap all tool bodies in try/except.
  • Side effects without confirmation. Tools that modify state (delete, write) should require explicit user confirmation before execution.
  • Version mismatch - The installed package or runtime differs from the command shown; check the version first and rerun the smallest verification command.
  • Local environment drift - Another service, virtual environment, model, or path is being used; print the active binary path and configuration before changing the guide steps.

Related guides

  • How to Build Core AI Agent Architecture
  • How to Create Agent Decision-Making Logic
← All how-to guidesCourses →