Skip to content

Python Docstring and Decorators

A docstring in Python is a string literal that appears as the first statement in a module, function, class, or method definition. It is used to document the purpose, behavior, parameters, and return values of the code object. Python docstrings are enclosed by triple quotes (""" or ''') and can span multiple lines.

When working with AI agents (particularly in frameworks like LangChain or SmoLAgents), the @tool decorator or annotation near a docstring is a special decorator or marker that designates a function as being callable by an agent. This process typically works as follows:

  1. Function Definition: Create a Python function with clearly defined inputs and outputs.

  2. Docstring Documentation: Write a comprehensive docstring that describes:

  3. What the function does
  4. The parameters it accepts
  5. The return value and type
  6. Any exceptions it might raise

  7. @tool Annotation: Include the @tool marker within the docstring or as a decorator above the function definition.

  8. Registration: The function is automatically registered in the agent's available toolset.

  9. Discovery and Usage: When the agent needs to perform a task related to the function's capability, it can discover and call this function based on the description in the docstring.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def search_database(query: str) -> list:
    """
    @tool
    Search the database for information matching the query string.

    Args:
        query: The search term to look for in the database

    Returns:
        A list of matching records from the database
    """
    # Implementation details
    results = db.execute_search(query)
    return results

This approach allows agents to understand not just what functions are available, but when and how to use them appropriately based on their documented purpose and parameters.

Decorators

A decorator is a design pattern in Python implemented as a special syntax that allows a function, method, or class to be modified or extended without changing its source code.

Decorators use the @ symbol followed by a decorator name placed above the definition of the function to be decorated. They effectively wrap the target function, enabling pre-processing of arguments, post-processing of return values, modification of behavior, or registration within a larger system.

Decorators in SmoLAgents for Tool Identification

In the SmoLAgents library, decorators are commonly used to identify and register functions as tools that can be discovered and used by agents. Here are examples of how decorators are used in this context:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from smolagents import tool

@tool
def search_web(query: str) -> list:
    """
    Search the web for information related to the query.

    Args:
        query: The search terms to look for

    Returns:
        A list of search results
    """
    # Implementation details
    return web_search_implementation(query)

More specific decorator examples in SmoLAgents might include:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from smolagents import final_answer_tool

@final_answer_tool
def provide_solution(answer: str) -> str:
    """
    Provide the final answer to the user's question.

    Args:
        answer: The complete solution to return to the user

    Returns:
        Confirmation message
    """
    # Implementation details
    return f"Final answer recorded: {answer}"

The SmoLAgents library might also support specialized tool decorators for different capabilities:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from smolagents import data_tool, code_tool, io_tool

@data_tool
def analyze_dataset(file_path: str) -> dict:
    """Process and analyze the dataset at the given path."""
    # Implementation

@code_tool
def execute_python(code_snippet: str) -> dict:
    """Execute the provided Python code snippet."""
    # Implementation

@io_tool
def save_result(filename: str, content: str) -> bool:
    """Save content to a file with the given filename."""
    # Implementation

These decorators serve multiple purposes: 1. Registering the function in the agent's available toolset 2. Providing metadata about the tool's purpose and usage patterns 3. Potentially applying input validation or output formatting 4. Enabling the agent to reason about which tool to use based on its current task