# How to Implement Active Tool Discovery and Selection in Self-Evolving AI Agents

> Learn to implement active tool discovery and selection for AI agents. Automatically search, reuse, and create tools for self-evolving capabilities and eliminate redundant computation.

- Repository: [Bojie Li/ai-agent-book](https://github.com/bojieli/ai-agent-book)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Active tool discovery and selection enables AI agents to automatically search existing tool libraries, reuse proven solutions when available, and dynamically create new tools when needed, implementing a self-evolving capability loop that eliminates redundant computation.**

The ai-agent-book repository demonstrates a production-ready implementation of active tool discovery and selection in Chapter 8's self-evolving tools architecture. This pattern allows agents to persistently expand their capabilities by recognizing reusable task solutions and storing them as discoverable tools for future queries, creating a virtuous cycle of capability accumulation without manual engineering.

## The Active Tool Discovery and Selection Workflow

The self-evolving agent in [[`agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/agent.py)](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/self-evolving-tools/agent.py) implements a five-step pipeline that prioritizes tool reuse over redundant computation. According to the source code comments, the workflow follows strict priority: search existing tools first (step 0️⃣), execute immediately if found (step 1️⃣), fall back to primitive methods only when necessary (step 2️⃣), register successful solutions (step 3️⃣), and validate through immediate reuse (step 4️⃣).

### Step 1: Searching the Tool Library

Before executing any external operation, the agent queries the persistent tool library using **`search_tools(query)`**. This method scans JSON definitions stored in the `tool_library/` directory and returns matching candidates based on semantic similarity to the task description.

In [[`tool_manager.py`](https://github.com/bojieli/ai-agent-book/blob/main/tool_manager.py)](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/self-evolving-tools/tool_manager.py), the `search_tools` implementation filters available tools and returns a structured response containing a `count` field and a `tools` array, indicating whether suitable candidates exist for immediate execution.

### Step 2: Executing Reusable Tools

When `search_tools` returns a match, the agent immediately invokes **`execute_tool(name, arguments)`** to run the stored implementation. This execution path bypasses web searches and code generation entirely, ensuring deterministic, tested behavior for known tasks.

The `execute_tool` method in [`tool_manager.py`](https://github.com/bojieli/ai-agent-book/blob/main/tool_manager.py) handles loading the tool's code from disk, sandboxing execution in a restricted environment, and returning structured results with a `result` key to the caller.

### Step 3: Fallback to Primitive Tools

If no existing tool addresses the current need, the agent falls back to a predefined set of primitive capabilities. The constant **`_META_TOOLS`** in [`tool_manager.py`](https://github.com/bojieli/ai-agent-book/blob/main/tool_manager.py) enumerates these baseline functions: `web_search`, `read_webpage`, and `code_interpreter` implemented in [[`base_tools.py`](https://github.com/bojieli/ai-agent-book/blob/main/base_tools.py)](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/self-evolving-tools/base_tools.py).

These primitives provide the raw capabilities needed to solve novel problems before they can be encapsulated into reusable tools, serving as the capability foundation for the self-evolving system.

### Step 4: Creating New Tools

Upon successfully solving a task with primitive tools, the agent packages the solution using **`create_tool(name, description, parameters, code)`**. This method validates the generated code syntax using Python's AST module, ensures a `def run(**kwargs)` entry point exists, and persists the tool definition to disk using JSON Schema for parameter validation.

The `create_tool` implementation in [`tool_manager.py`](https://github.com/bojieli/ai-agent-book/blob/main/tool_manager.py)—described in source comments as "封装并持久化" (encapsulate and persist)—guarantees that new tools conform to the library's interface requirements and are immediately available for subsequent discovery.

### Step 5: Validation and Immediate Reuse

After registration, the agent executes the newly created tool via `execute_tool` to verify functionality and return the final result. This completes the loop: future identical requests will discover the tool in Step 1, avoiding redundant computation and web searches.

## Code Implementation Examples

The following examples demonstrate the active tool discovery pattern using the `ToolLibrary` class and high-level agent orchestration.

### Direct Library Interaction

This example shows the complete discovery, fallback, creation, and reuse cycle:

```python
from tool_manager import ToolLibrary
import base_tools

# Initialize the tool library with persistence directory

lib = ToolLibrary(library_dir="tool_library")

# Step 1: Search for existing tool

search_result = lib.search_tools("calculate days between dates")

if search_result["count"] > 0:
    # Step 2: Execute existing tool

    tool_name = search_result["tools"][0]["name"]
    result = lib.execute_tool(
        tool_name, 
        {"start": "2023-01-01", "end": "2023-12-31"}
    )
else:
    # Step 3: Fallback to primitive code execution

    raw_output = base_tools.code_interpreter(
        "from datetime import datetime; "
        "start = datetime(2023, 1, 1); "
        "end = datetime(2023, 12, 31); "
        "print((end - start).days)"
    )
    
    # Step 4: Create new tool from successful solution

    lib.create_tool(
        name="days_between_dates",
        description="Calculate days between two ISO format dates",
        parameters={
            "type": "object",
            "properties": {
                "start": {"type": "string", "format": "date"},
                "end": {"type": "string", "format": "date"}
            },
            "required": ["start", "end"]
        },
        code="""
from datetime import datetime

def run(start: str, end: str) -> int:
    fmt = "%Y-%m-%d"
    d1 = datetime.strptime(start, fmt)
    d2 = datetime.strptime(end, fmt)
    return (d2 - d1).days
"""
    )
    
    # Step 5: Execute newly created tool

    result = lib.execute_tool(
        "days_between_dates",
        {"start": "2023-01-01", "end": "2023-12-31"}
    )

print(f"Result: {result['result']}")

```

### High-Level Agent Orchestration

For production use, the `SelfEvolvingAgent` class automates the entire workflow:

```python
from agent import SelfEvolvingAgent

# Initialize the self-evolving agent

agent = SelfEvolvingAgent()

# The agent automatically handles discovery, fallback, and creation

answer = agent.run(
    "How many days elapsed between 2020-03-15 and 2020-07-20?"
)
print(answer)

```

## Key Source Files and Architecture

Understanding the file structure helps navigate the implementation:

- **[[`tool_manager.py`](https://github.com/bojieli/ai-agent-book/blob/main/tool_manager.py)](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/self-evolving-tools/tool_manager.py)**: Core library managing `search_tools()`, `create_tool()`, and `execute_tool()`. Handles JSON persistence, code validation, and sandboxed execution.

- **[[`agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/agent.py)](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/self-evolving-tools/agent.py)**: High-level orchestration implementing the discovery-selection loop with explicit comments marking steps 0️⃣ through 4️⃣ of the workflow.

- **[[`base_tools.py`](https://github.com/bojieli/ai-agent-book/blob/main/base_tools.py)](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/self-evolving-tools/base_tools.py)**: Implements primitive `_META_TOOLS` including `web_search`, `read_webpage`, and `code_interpreter` that serve as the capability foundation for tool creation.

## Summary

- **Active tool discovery** begins with `search_tools()` querying persistent JSON definitions in the tool library before attempting any external computation.

- **Tool selection** prioritizes execution of existing tools via `execute_tool()` to ensure deterministic reuse of validated solutions.

- **Dynamic creation** occurs only after primitive tools solve novel tasks, using `create_tool()` to package solutions with validated JSON Schema parameters.

- **Immediate persistence** makes new tools available for discovery in subsequent requests, creating a self-evolving capability loop.

- **Sandboxed execution** in [`tool_manager.py`](https://github.com/bojieli/ai-agent-book/blob/main/tool_manager.py) ensures tool code runs safely while maintaining access to necessary imports and context.

## Frequently Asked Questions

### What is the difference between primitive tools and created tools in the ai-agent-book implementation?

Primitive tools are hardcoded capabilities in [`base_tools.py`](https://github.com/bojieli/ai-agent-book/blob/main/base_tools.py) (web_search, code_interpreter) that provide baseline functionality for unknown tasks. Created tools are dynamically generated Python functions persisted to the tool library that encapsulate specific, reusable task solutions discovered during agent execution.

### How does the agent prevent creating duplicate tools for the same task?

The `search_tools()` method in [`tool_manager.py`](https://github.com/bojieli/ai-agent-book/blob/main/tool_manager.py) performs semantic matching against existing tool descriptions before any creation occurs. If a matching tool exists, the agent executes it immediately via `execute_tool()`, bypassing the creation fallback entirely and preventing library bloat.

### What validation does `create_tool()` perform on generated code?

The `create_tool()` method validates that the provided code contains a `def run(**kwargs)` entry point, checks for syntax errors using Python's AST module, and ensures the parameters conform to JSON Schema standards before persisting the tool definition to the `tool_library/` directory.

### Can the tool library persist across different agent sessions?

Yes, the `ToolLibrary` class accepts a `library_dir` parameter that specifies a filesystem location for JSON tool definitions. These files persist between sessions, enabling long-term accumulation of capabilities across multiple agent runs and system restarts.