# How to Design Effective Tool Descriptions for LLM Tool Calling: 7 Patterns from ai-agent-book

> Learn to design effective LLM tool descriptions using 7 patterns from ai-agent-book. Optimize clarity, minimize token usage, and maximize actionability for better tool calling.

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

---

**Effective LLM tool descriptions separate concise metadata from detailed operational contracts, explicitly encoding what the tool does, required inputs, expected outputs, failure modes, and data provenance in a self-contained format that minimizes token usage while maximizing actionability.**

When building AI agents capable of invoking external functions, the quality of your tool descriptions determines whether the LLM selects the correct function, formats arguments properly, and handles errors gracefully. The **ai-agent-book** repository demonstrates a disciplined, layered approach to designing these descriptions, separating what the model needs to know from the operational details that ensure reliable execution.

## 1. Separate Metadata from Operational Contracts

The repository distinguishes between **metadata** (the concise summary exposed to the LLM in the prompt) and the **operational contract** (implementation details, failure modes, and provenance). This separation occurs in [`chapter4/perception-tools/src/expanded_catalog.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter4/perception-tools/src/expanded_catalog.py).

First, `register_expanded_tools` registers tools with human-readable summaries:

```python
mcp.add_tool(_make_mcp_function(spec), name=spec.name,
             description=full_description(spec))

```

(See lines 1000‑1004 of [`expanded_catalog.py`](https://github.com/bojieli/ai-agent-book/blob/main/expanded_catalog.py).)

Later, `enrich_existing_tools` appends the full operational contract containing provenance and failure conditions:

```python
tool.description = (
    f"{tool.description.rstrip()}.\n\n"
    f"Operational provenance for {name}: {provenance}. … "
    f"Tool‑specific failure conditions are {failures}."
)

```

(See lines 1016‑1028 of the same file.)

This architecture allows you to expose only essential information to the LLM by default while retaining rich, machine-readable context for debugging or advanced prompting scenarios.

## 2. Make Descriptions Self-Contained and Actionable

Every tool description must answer three questions without requiring external context: What does the tool do? What inputs are required? What does a successful response look like?

The `full_description` function generates concise summaries such as `"MCP tool that retrieves a web page and returns its HTML."` For input requirements, the `parameters` field supplies a JSON Schema. In [`chapter4/agent-with-event-trigger/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter4/agent-with-event-trigger/agent.py), the `_get_tools_description` method (lines 65‑70) extracts the schema:

```python
"parameters": getattr(mcp_tool, "inputSchema", {"type":"object","properties":{}})

```

By encoding these elements, the LLM can construct correct function call JSON without guessing parameter types or return structures.

## 3. Document Failure Modes Explicitly

LLMs often assume functions succeed by default. When a tool can fail due to network errors, rate limits, or invalid arguments, the description must spell out the failure shape so the model can decide whether to retry, fallback, or continue.

In [`expanded_catalog.py`](https://github.com/bojieli/ai-agent-book/blob/main/expanded_catalog.py) (lines 1024‑1026), the contract explicitly states:

```python
"Tool‑specific failure conditions are {failures}."

```

This leads to structured error responses the model can parse:

```json
{
  "success": false,
  "error": "Timeout after 30 s",
  "metadata": {...}
}

```

The agent can then surface the error to the user or select an alternative tool rather than hallucinating a successful result.

## 4. Use Provenance to Avoid Hallucination

When tools return data fetched from external sources, descriptions must explicitly state that results contain **source identifiers** (URLs, timestamps, provider metadata). This discourages the model from inventing facts and enables downstream verification.

The operational contract in [`expanded_catalog.py`](https://github.com/bojieli/ai-agent-book/blob/main/expanded_catalog.py) (lines 19‑24) adds a prose block stating that the structured `ActionResponse` retains source identifiers. This pattern is reused across MCP-enabled agents in the repository to ensure the LLM understands the data lineage before synthesizing answers.

## 5. Keep the Prompt Footprint Small

Only the concise metadata enters the standard prompt. The heavier operational contract attaches only when the agent’s configuration enables tool-description enrichment. In [`agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/agent.py), the `_get_tools_description` method checks `self.config.enable_todo_list` to determine whether to include enriched descriptions.

This conditional approach preserves the token budget during normal operation while allowing on-demand detail for complex debugging scenarios or high-stakes tool invocations.

## 6. Provide a Uniform JSON Schema

All tools in the repository use the OpenAI-compatible function schema, enabling the model to reason about any tool uniformly. The conversion occurs in `_get_tools_description` (lines 60‑70 of [`chapter4/agent-with-event-trigger/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter4/agent-with-event-trigger/agent.py)):

```python
tools.append({
    "type": "function",
    "function": {
        "name": tool_key,
        "description": mcp_tool.description or mcp_tool.name,
        "parameters": getattr(mcp_tool, "inputSchema", {"type":"object","properties":{}})
    }
})

```

Adhering to a single schema simplifies few-shot prompting and tool-selection logic across diverse agent implementations.

## 7. End-to-End Implementation Flow

The repository implements a complete pipeline for designing effective tool descriptions:

1. **Registration**: `register_expanded_tools` adds 70 real-backed tools with short summaries.
2. **Enrichment**: `enrich_existing_tools` decorates each tool with a full operational contract from `EXISTING_TOOL_CONTRACTS`.
3. **Prompt Construction**: `Agent._get_tools_description` builds the list of function definitions sent to the model.
4. **Model Call**: The LLM selects a function and fills `parameters` according to the JSON schema.
5. **Error Handling**: If the response contains `"success": false`, the agent retries, chooses another tool, or surfaces the error based on the documented failure modes.

## Summary

- **Separate concerns**: Keep concise LLM-facing metadata distinct from detailed operational contracts containing failure modes and provenance.
- **Answer three questions**: Every description must clarify what the tool does, what inputs it requires, and what successful output looks like.
- **Explicit failures**: Document failure conditions so the LLM can handle errors rather than hallucinate success.
- **Source provenance**: Include data source identifiers in descriptions to prevent fact invention and enable verification.
- **Token efficiency**: Use conditional enrichment to keep prompt footprints small while retaining detailed contracts for debugging.
- **Schema standardization**: Adopt the OpenAI function-calling format in `_get_tools_description` for uniform tool reasoning across your agent fleet.

## Frequently Asked Questions

### How long should an LLM tool description be?

Tool descriptions should be concise enough to fit within your token budget while containing sufficient detail for the model to select and use the tool correctly. The ai-agent-book approach uses a short human-readable sentence for the base description (e.g., "MCP tool that retrieves a web page and returns its HTML") and appends the full operational contract only when `self.config.enable_todo_list` is activated, keeping standard prompts lean.

### What information must be included in a tool description to prevent LLM errors?

To prevent selection and formatting errors, include: (1) a clear statement of the tool's purpose, (2) a JSON Schema defining required parameters and types (as implemented in `_get_tools_description`), and (3) explicit documentation of failure modes and success response shapes. According to the [`expanded_catalog.py`](https://github.com/bojieli/ai-agent-book/blob/main/expanded_catalog.py) implementation, adding provenance details and failure conditions reduces hallucination and enables proper error recovery.

### Should tool descriptions include error handling instructions for the LLM?

Yes, effective tool descriptions explicitly document failure modes so the LLM knows how to interpret error responses. In the ai-agent-book repository, the `enrich_existing_tools` function appends strings like `"Tool‑specific failure conditions are {failures}"` to the description, allowing the model to receive structured error JSON (e.g., `{"success": false, "error": "Timeout"}`) and decide whether to retry or select an alternative tool.

### How do I convert existing MCP tools to OpenAI-compatible function descriptions?

Use a conversion method like `_get_tools_description` in [`chapter4/agent-with-event-trigger/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter4/agent-with-event-trigger/agent.py). This function iterates over your MCP tools and maps them to the OpenAI function schema by extracting the `name`, `description`, and `inputSchema` fields, ensuring the resulting JSON includes `"type": "function"` and properly nested `"function"` objects with `"parameters"` definitions.