Knowledge Base

Designing Effective Tools for AI Agents

An AI agent’s effectiveness is directly tied to the quality of its tools. Tools are functions an agent can invoke to interact with the outside world, from searching a database to calling an API. Simply providing a list of functions is not enough; how you design, document, and manage these tools is critical for building high-performing, reliable agents.

This guide covers the essential principles for building effective agent tools, inspired by best practices in software engineering and agent development.

[!tip] The Golden Rule of Tool Design
“Tools should be defined in such a way that it’s easy for a human to understand and utilize them.” If a person can’t easily grasp a tool’s purpose from its definition, an LLM will struggle even more.


1. Proper Tool Definitions: The Docstring is the UI

The way you define a tool—its name, parameters, and description—is the primary interface the agent uses to understand it. Clarity here is non-negotiable.

Key Components:

  • Clear Naming: The function name should be specific and unambiguous. Avoid generic names like search in favor of descriptive ones like keyword_database_search or semantic_vector_search.
  • Descriptive Docstrings: The docstring is the most critical piece of context for the agent. It must clearly explain:
    • The tool’s exact purpose.
    • A description of each input parameter, including its data type.
    • A clear definition of what the tool returns, including the structure and data types.
  • Strict Typing: Use type hints for all inputs and outputs. For complex outputs, use data classes (like Pydantic models or Python’s @dataclass) to define a clear schema.

Example: Bad vs. Good Tool Definition

❌ Bad Definition: Lacks clarity, types, and a descriptive docstring.

# Ambiguous name, no types, no docstring
def search(query):
    results = search_database() 
    return results
````

** Good Definition:** Specific, well-documented, and strongly typed.

```python
from dataclasses import dataclass

@dataclass
class KeywordSearchResult:
    """Data schema for a single keyword search result."""
    id: str
    filename: str
    document_content: str

def keyword_search(query: str) -> list[KeywordSearchResult]:
    """
    Performs a keyword search against the internal document database.

    Args:
        query (str): The keywords to search for.

    Returns:
        list[KeywordSearchResult]: A list of documents matching the query,
        each containing an ID, filename, and content.
    """
    results = search_database(query)
    # Logic to parse results into KeywordSearchResult objects
    return parsed_results

2. Tool Functionality: Specificity and Robustness

Beyond the definition, the tool’s internal logic should be designed to support the agent’s reasoning process.

Make Tools Specific

A tool should have one, clear purpose. Vague, multi-purpose tools confuse the agent, leading it to use them at the wrong time or with incorrect parameters.

  • Instead of: A single update_database tool that can add, edit, or delete.
  • Prefer: Three separate tools: add_recordedit_record, and delete_record.

Provide Clean, Parsed Outputs

Don’t return raw API responses or database dumps directly to the agent. The tool itself should process, clean, and format the output into a simple, structured string that contains only the necessary information. This reduces the cognitive load on the agent.

def _parse_search_results_for_agent(results: list[KeywordSearchResult]) -> str:
    """Parses search results into a clean string for the agent's context."""
    if not results:
        return "No results found."

    output_string = f"Found {len(results)} documents:\n"
    for i, res in enumerate(results):
        output_string += f"\nDocument {i+1}:\n"
        output_string += f"- ID: {res.id}\n"
        output_string += f"- Filename: {res.filename}\n"
        output_string += f"- Content Snippet: {res.document_content[:100]}...\n"

    return output_string

Avoid Context Overload

Tools can sometimes return thousands of results, which will overwhelm the agent’s context window. Implement controls within the tool to manage output size.

  • Add a max_results parameter (e.g., defaulting to 10).
  • Implement sorting parameters (sort_bysort_order) so the agent can request the most relevant information first.

Use Informative Error Handling

When a tool fails, the error message is a critical piece of feedback for the agent. Generic errors are useless. Good error handling tells the agent what went wrong and how to potentially fix it.

def keyword_search(query: str) -> str:
    try:
        # ... search logic ...
    except RatelimitError as e:
        raise RuntimeError(
            f"API rate limit hit. Wait 60 seconds before retrying this action."
        )
    except APINotAvailableError as e:
        raise RuntimeError(
            f"The API is currently unavailable. Inform the user and try again later."
        )
    except Exception as e:
        raise RuntimeError(f"An unexpected error occurred: {e}. Please try a different approach.")

3. Context Management: Making Tools Available

Finally, consider how and when you present tools to the agent.

  • Limit the Number of Tools: Don’t overwhelm the agent with dozens of tools if only a few are relevant to the task. A smaller, well-chosen toolset leads to better performance.
  • Conditional Availability: If possible, dynamically provide tools based on the task. For a summarization task, the agent doesn’t need access to a send_email tool.
  • Structured Prompting: In your agent’s system prompt, dedicate a specific section for tools, often using Markdown headings (## Tools) or XML tags (<tools>). This helps the model clearly distinguish tools from other instructions.

By investing time in designing high-quality tools, you provide the foundation for a more capable, reliable, and autonomous AI agent.


Integration and Cross-Linking

After creating this new note, I suggest making the following minor updates to existing documents to link everything together:

  1. In 00_introduction-to-ai-agents:

    • Add a sentence in the section about how agents work, linking to the new note.
    • Example: “To achieve its goals, an agent uses a set of predefined functions, or ‘tools,’ to interact with its environment. The design of these tools is critical to the agent’s success. (See Designing Effective Tools for AI Agents)”
  2. In 01_ai-agents-running-workflows:

    • When discussing the “actions” in a workflow, link to the new note.
    • Example: “Each action in a workflow typically involves the agent selecting and executing a tool. Building robust and well-defined tools is a foundational step in creating reliable workflows. (See Designing Effective Tools for AI Agents)”

This approach will seamlessly integrate this crucial information into your knowledge base, creating a more comprehensive and structured learning path on AI agents.

Advanced Tool Patterns: User Interaction Tools

Beyond data retrieval and action execution, a powerful pattern is designing tools that allow the agent to interact with the user through a graphical interface. Instead of relying on text, the agent can call a “tool” that renders a UI.

Google’s A2UI is a formal specification for this pattern. An agent can use it to request complex UI elements like forms, cards, and buttons. In this model, the “tool” isn’t an API call but a structured request for a user interface, which the client application is responsible for rendering. This is a highly effective way to handle tasks that require structured user input.

About the Author: Adam Bernard

Designing Effective Tools for AI Agents
Adam Bernard is a digital marketing strategist and SEO specialist building AI-powered business intelligence systems. He's the creator of the Strategic Intelligence Engine (SIE), a multi-agent framework that transforms business knowledge into autonomous, AI-driven competitive advantages.

Let’s Connect

Ready to Build Your Own Intelligence Engine?

If you’re ready to move from theory to implementation and build a Knowledge Core for your own business, I can help you design the engine to power it. Let’s discuss how these principles can be applied to your unique challenges and goals.