Skip to content

[FEATURE] Support for Type Annotations with Descriptions in @tool Decorator Functions #511

@jawtopi

Description

@jawtopi

Problem Statement

Currently, Strands tool functions require argument descriptions to be defined in DocStrings when using the @tool decorator approach. While the tool description itself can be overridden in the decorator, there's no elegant way to handle long argument descriptions without resorting to long, unclean looking DocStrings.

Proposed Solution

Implement support for Python type + description annotations for function tool arguments. Frameworks like AutoGen already support this. Here is the AutoGen annotation feature as an example.

A Strands example could look like:

GET_STOCK_PRICE_DESCRIPTION = "Gets a random stock price for demonstration purposes"
GET_STOCK_PRICE_DATE_DESC = "Date in YYYY/MM/DD"

@tool(description=GET_STOCK_PRICE_DESCRIPTION)
async def get_stock_price(ticker: str, 
    date: Annotated[str, GET_STOCK_PRICE_DATE_DESC]
) -> float:
    return random.uniform(10, 200)

Use Case

Developers working with tools that require detailed parameter descriptions would benefit from cleaner code organization. Currently for a Python DocString, there is no method to associate specific descriptions with parameters in a structured way that tools can reliably parse.

Alternatives Solutions

One way to handle detailed parameter descriptions cleanly in Strands is to use module tools with a TOOLSPEC variable, which allows defining structured parameter descriptions separately from the function implementation. This approach enables importing description constants, and placing them into the Input Schema like this:

from random_directory import (
    ARG2_DESC
    ARG1_DESC,
    EXAMPLE_DESCRIPTION,
)

TOOL_SPEC = {
    "name": "example",
    "description": EXAMPLE_DESCRIPTION,,
    "inputSchema": {
        "json": {
            "type": "object",
            "properties": {
                "arg1": {"type": "string", "description": ARG1_DESC},
                "arg2": {"type": "string", "description": ARG2_DESC},
            },
        }
    },
}


def example(tool, **kwargs):
    return {
        "toolUseId": tool["toolUseId"],
        "status": "success",
        "content": [{"text": "just an example"}],
    }

However, module tools require each tool to be defined in a separate file with a rigid format, and sharing dependencies between tools e.g. specific class instances for per-tool state is difficult. The primary challenge is that there's no built-in mechanism for dependency injection with module tools, which makes the @tool decorator method preferrable.

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestto-refineIssue needs to be discussed with the team and the team has come to an effort estimate consensus

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions