> ## Documentation Index
> Fetch the complete documentation index at: https://genai.codewithsiva.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 5. Tool Decorator

> Define custom tools using the @tool decorator and Pydantic schema validation

In this section, you will learn how to define custom tools using LangChain's decorator approach, which simplifies tool configuration by automatically deriving descriptions and names from function docstrings.

## Objectives

1. Declare custom tools by adding the `@tool` decorator to Python functions.
2. Bind Pydantic model schemas to the decorator using the `args_schema` property.
3. Combine decorated functions into a tools array and load them inside a tool-calling agent.

## Implementation Plan

#### Goal

Build and execute a tools agent utilizing decorated tools for greeting, reversing strings, and concatenating values.

#### Sample Input

```python theme={null}
"Reverse the string 'hello'"
```

#### Sample Output

```python theme={null}
"olleh"
```

#### Plan

1. Define a simple function `greet_user` decorated with `@tool()`.
2. Define Pydantic argument structures: `ReverseStringArgs` and `ConcatenateStringsArgs`.
3. Decorate `reverse_string` with `@tool(args_schema=ReverseStringArgs)`.
4. Decorate `concatenate_strings` with `@tool(args_schema=ConcatenateStringsArgs)`.
5. Group the decorated functions in a list: `tools = [greet_user, reverse_string, concatenate_strings]`.
6. Initialize the agent executor using `create_tool_calling_agent` and test the agent.

## Step-by-Step Implementation

### Step 1: Define Simple Decorated Tool

We write a simple greeting tool. The docstring `"""Greets the user by name."""` acts as the tool description.

```python theme={null}
from langchain.tools import tool

@tool()
def greet_user(name: str) -> str:
    """Greets the user by name."""
    return f"Hello, {name}!"
```

### Step 2: Define Structured Tools with Schemas

We bind Pydantic argument classes to decorated functions.

```python theme={null}
from langchain.pydantic_v1 import BaseModel, Field

class ReverseStringArgs(BaseModel):
    text: str = Field(description="Text to be reversed")

@tool(args_schema=ReverseStringArgs)
def reverse_string(text: str) -> str:
    """Reverses the given string."""
    return text[::-1]

class ConcatenateStringsArgs(BaseModel):
    a: str = Field(description="First string")
    b: str = Field(description="Second string")

@tool(args_schema=ConcatenateStringsArgs)
def concatenate_strings(a: str, b: str) -> str:
    """Concatenates two strings."""
    return a + b
```

### Step 3: Run Agent

We combine the tools list and execute the agent.

```python theme={null}
from langchain import hub
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain.chat_models import init_chat_model

tools = [greet_user, reverse_string, concatenate_strings]

llm = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")
prompt = hub.pull("hwchase17/openai-tools-agent")
agent = create_tool_calling_agent(llm=llm, tools=tools, prompt=prompt)
agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=True)
```

## Complete Combined Code

Below is the complete, consolidated Python script uniting all of the steps above:

```python theme={null}
# Import necessary libraries
from langchain import hub
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain.pydantic_v1 import BaseModel, Field
from langchain.tools import tool
from langchain.chat_models import init_chat_model


# Simple Tool with one parameter without args_schema
@tool()
def greet_user(name: str) -> str:
    """Greets the user by name."""
    return f"Hello, {name}!"


# Pydantic models for tool arguments
class ReverseStringArgs(BaseModel):
    text: str = Field(description="Text to be reversed")


# Tool with One Parameter using args_schema
@tool(args_schema=ReverseStringArgs)
def reverse_string(text: str) -> str:
    """Reverses the given string."""
    return text[::-1]


# Another Pydantic model for tool arguments
class ConcatenateStringsArgs(BaseModel):
    a: str = Field(description="First string")
    b: str = Field(description="Second string")


# Tool with Two Parameters using args_schema
@tool(args_schema=ConcatenateStringsArgs)
def concatenate_strings(a: str, b: str) -> str:
    """Concatenates two strings."""
    print("a", a)
    print("b", b)
    return a + b


# Create tools using the @tool decorator
tools = [
    greet_user,  # Simple tool without args_schema
    reverse_string,  # Tool with one parameter using args_schema
    concatenate_strings,  # Tool with two parameters using args_schema
]

# Initialize a Groq model using core abstractions
llm = init_chat_model("llama-3.3-70b-versatile", model_provider="groq")

# Pull the prompt template from the hub
prompt = hub.pull("hwchase17/openai-tools-agent")

# Create the ReAct agent using the create_tool_calling_agent function
agent = create_tool_calling_agent(
    llm=llm,  # Language model to use
    tools=tools,  # List of tools available to the agent
    prompt=prompt,  # Prompt template to guide the agent's responses
)

# Create the agent executor
agent_executor = AgentExecutor.from_agent_and_tools(
    agent=agent,  # The agent to execute
    tools=tools,  # List of tools available to the agent
    verbose=True,  # Enable verbose logging
    handle_parsing_errors=True,  # Handle parsing errors gracefully
)

# Test the agent with sample queries
response = agent_executor.invoke({"input": "Greet Alice"})
print("Response for 'Greet Alice':", response)

response = agent_executor.invoke({"input": "Reverse the string 'hello'"})
print("Response for 'Reverse the string hello':", response)

response = agent_executor.invoke({"input": "Concatenate 'hello' and 'world'"})
print("Response for 'Concatenate hello and world':", response)
```

## Practice & Exercises

To practice setting up tools using decorators, open the interactive notebook:

<CardGroup cols={1}>
  <Card title="Practice & Exercises" icon="laptop-code">
    Practice defining custom tools using the @tool decorator.

    [💻 VS Code](vscode://file/Users/sivaprasad/Downloads/GenAI%20With%20Python/public/notebooks/langchain/5_tool_decorator.ipynb) | [🚀 Colab](https://colab.research.google.com/github/prasad230776/genai-course/blob/master/public/notebooks/langchain/5_tool_decorator.ipynb) | <a href="/public/notebooks/langchain/5_tool_decorator.ipynb" download>📥 Download</a>
  </Card>
</CardGroup>
