Skip to main content

Tools API Reference

Tools enable agents to execute Python functions and integrate external capabilities.

FunctionTool

A tool that wraps a Python function to make it callable by AI models.
from agent_framework import FunctionTool

Constructor

tool = FunctionTool(
    name="get_weather",
    description="Get the weather for a location",
    func=my_function,
    input_model=WeatherArgs,
    approval_mode="never_require",
    max_invocations=10
)
name
str
required
The name of the function.
description
str
default:""
A description of the function.
approval_mode
Literal['always_require', 'never_require'] | None
default:"never_require"
Whether approval is required to run this tool.
kind
str | None
Optional provider-agnostic tool classification (e.g., “shell”).
max_invocations
int | None
Maximum number of times this function can be invoked across the lifetime of this tool instance. If None, there is no limit.Note: This counter lives on the tool instance and is never automatically reset. For per-request limits, use FunctionInvocationConfiguration["max_function_calls"] instead.
max_invocation_exceptions
int | None
Maximum number of exceptions allowed during invocations. If None, there is no limit.
additional_properties
dict[str, Any] | None
Additional properties to set on the function.
func
Callable[..., Any] | None
The function to wrap. When None, creates a declaration-only tool that has no implementation.
input_model
type[BaseModel] | Mapping[str, Any] | None
The Pydantic model that defines the input parameters, or a JSON schema dictionary. If not provided and func is not None, it will be inferred from the function signature.
result_parser
Callable[[Any], str] | None
Optional callable to convert raw function return value to string. When provided, overrides the default parse_result() logic.
**kwargs
Any
Additional keyword arguments.

Properties

declaration_only
bool
Indicates whether the function is declaration only (has no implementation).
invocation_count
int
Current number of times this function has been invoked.
invocation_exception_count
int
Current number of exceptions that occurred during invocations.

Methods

invoke()

Run the function with provided arguments.
result = await tool.invoke(
    arguments={"location": "Seattle", "unit": "celsius"}
)
arguments
BaseModel | Mapping[str, Any] | None
A mapping or model instance containing the arguments for the function.
**kwargs
Any
Keyword arguments to pass to the function (used if arguments is not provided).
return
str
The parsed result as a string - either plain text or serialized JSON.

parameters()

Get the JSON schema of the parameters.
schema = tool.parameters()
return
dict[str, Any]
A dictionary containing the JSON schema for the function’s parameters. The result is cached after the first call.

to_json_schema_spec()

Convert the FunctionTool to JSON Schema function specification format.
spec = tool.to_json_schema_spec()
return
dict[str, Any]
A dictionary containing the function specification in JSON Schema format.

parse_result() (static)

Convert a raw function return value to a string representation.
result_str = FunctionTool.parse_result(result)
result
Any
required
The raw return value from the wrapped function.
return
str
A string representation of the result, either plain text or serialized JSON.

Example: Direct Instantiation

from typing import Annotated
from pydantic import BaseModel, Field
from agent_framework import FunctionTool

class WeatherArgs(BaseModel):
    location: Annotated[str, Field(description="The city name")]
    unit: Annotated[str, Field(description="Temperature unit")] = "celsius"

def get_weather_impl(location: str, unit: str = "celsius") -> str:
    return f"Weather in {location}: 22°{unit[0].upper()}"

weather_tool = FunctionTool(
    name="get_weather",
    description="Get the weather for a location",
    func=get_weather_impl,
    approval_mode="never_require",
    input_model=WeatherArgs
)

# Use with an agent
agent = Agent(client=client, tools=[weather_tool])

# Or invoke directly
result = await weather_tool.invoke(
    arguments=WeatherArgs(location="Seattle")
)
print(result)  # "Weather in Seattle: 22°C"

Example: Declaration-Only Tool

from agent_framework import FunctionTool

# Create a tool without implementation
# Useful for testing agent reasoning or client-side execution
declaration_tool = FunctionTool(
    name="get_current_time",
    description="Get the current time in ISO 8601 format.",
    func=None,  # No implementation
    input_model=None  # No parameters
)

assert declaration_tool.declaration_only == True

@tool Decorator

Decorate a function to turn it into a FunctionTool.
from agent_framework import tool
from typing import Annotated

Usage

@tool(approval_mode="never_require")
def get_weather(
    location: Annotated[str, "The city name"],
    unit: Annotated[str, "Temperature unit"] = "celsius"
) -> str:
    """Get the weather for a location."""
    return f"Weather in {location}: 22°{unit[0].upper()}"

Parameters

func
Callable[..., Any] | None
The function to decorate. Enables decorator to be used with or without parentheses.
name
str | None
The name of the function. If not provided, uses the function’s __name__.
description
str | None
A description of the function. If not provided, uses the function’s docstring.
schema
type[BaseModel] | Mapping[str, Any] | None
Explicit input schema for the function. Can be a Pydantic BaseModel subclass or a JSON schema dictionary. When provided, used instead of inferring from signature.
approval_mode
Literal['always_require', 'never_require'] | None
default:"never_require"
Whether approval is required to run this tool.
kind
str | None
Optional provider-agnostic tool classification.
max_invocations
int | None
Maximum number of times this function can be invoked across the lifetime of this tool instance.
max_invocation_exceptions
int | None
Maximum number of exceptions allowed during invocations.
additional_properties
dict[str, Any] | None
Additional properties to set on the function.
result_parser
Callable[[Any], str] | None
Optional callable to override default result parsing.
return
FunctionTool | Callable[[Callable], FunctionTool]
The decorated function as a FunctionTool, or a decorator if called without a function.

Examples

Basic Usage

from agent_framework import tool
from typing import Annotated

@tool(approval_mode="never_require")
def calculate_sum(
    a: Annotated[int, "The first number"],
    b: Annotated[int, "The second number"]
) -> int:
    """Calculate the sum of two numbers."""
    return a + b

With Pydantic Field Annotations

from agent_framework import tool
from typing import Annotated
from pydantic import Field

@tool
def search_database(
    query: Annotated[str, Field(description="Search query", min_length=1)],
    limit: Annotated[int, Field(description="Max results", ge=1, le=100)] = 10
) -> str:
    """Search the database."""
    return f"Found results for: {query}"

Async Functions

@tool(approval_mode="never_require")
async def async_get_weather(location: str) -> str:
    """Get weather asynchronously."""
    # Simulate async operation
    await asyncio.sleep(0.1)
    return f"Weather in {location}"

Custom Name and Description

@tool(name="custom_weather", description="Custom weather function")
def another_weather_func(location: str) -> str:
    return f"Weather in {location}"

With Explicit Schema

from pydantic import BaseModel, Field

class WeatherInput(BaseModel):
    location: Annotated[str, Field(description="City name")]
    unit: str = "celsius"

@tool(schema=WeatherInput)
def get_weather(location: str, unit: str = "celsius") -> str:
    """Get weather for a location."""
    return f"Weather in {location}: 22 {unit}"

With Approval Required

@tool(approval_mode="always_require")
def delete_file(path: Annotated[str, "File path to delete"]) -> str:
    """Delete a file. Requires approval before execution."""
    os.remove(path)
    return f"Deleted {path}"

Function Invocation Configuration

Configuration for automatic function invocation in chat clients.
from agent_framework import FunctionInvocationConfiguration

Configuration Dictionary

enabled
bool
default:"True"
Master switch for the function invocation loop.
max_iterations
int
default:"40"
Limits the number of LLM roundtrips (iterations). Each iteration may execute one or more function calls in parallel.
max_function_calls
int | None
default:"None"
Limits the total number of individual function invocations across all iterations within a single request.This is a best-effort limit checked after each batch of parallel tool calls completes. If the model requests 20 parallel calls in a single iteration and the limit is 10, all 20 will execute before the loop stops.
max_consecutive_errors_per_request
int
default:"3"
How many consecutive errors before abandoning the tool loop for this request.
terminate_on_unknown_calls
bool
default:"False"
Whether to raise an error when the model requests a function not in the tool map.
additional_tools
Sequence[FunctionTool]
default:"[]"
Extra tools available during execution but not advertised to the model in the tool list.
include_detailed_errors
bool
default:"False"
Whether to include exception details in the function result returned to the model.

Example

from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient(api_key="your_api_key")

# Configure function invocation limits
client.function_invocation_configuration["max_iterations"] = 5
client.function_invocation_configuration["max_function_calls"] = 20
client.function_invocation_configuration["include_detailed_errors"] = True

# Use with agent
agent = client.as_agent(tools=[my_tool])
response = await agent.run("Execute some tasks")

normalize_tools()

Normalize tool inputs while preserving non-callable tool objects.
from agent_framework import normalize_tools

normalized = normalize_tools([my_function, my_tool, tool_dict])
tools
ToolTypes | Callable | Sequence[ToolTypes | Callable] | None
required
A single tool or sequence of tools.
return
list[ToolTypes]
A normalized list where callable inputs are converted to FunctionTool using the @tool decorator, and existing tool objects are passed through unchanged.

Example

from agent_framework import normalize_tools, FunctionTool

def my_func(x: int) -> int:
    return x * 2

my_tool = FunctionTool(name="custom", func=lambda: "result")
tool_dict = {"type": "function", "function": {...}}

tools = normalize_tools([my_func, my_tool, tool_dict])
# Returns: [FunctionTool(my_func), my_tool, tool_dict]

Tool Type Aliases

from agent_framework import ToolTypes
ToolTypes: Type alias for tool inputs.
ToolTypes = FunctionTool | MCPTool | Mapping[str, Any] | object
This type alias represents all valid tool input types that can be passed to agents and chat clients.

Build docs developers (and LLMs) love