Python Functions as Tools

Turn any Python function into an agent tool.

Before running the examples:

pip install agno openai httpx
export OPENAI_API_KEY="your-api-key"

Any python function can be used as a tool by an Agent.

For example, here's how to use a get_top_hackernews_stories function as a tool:

hn_agent.py
import json
import httpx

from agno.agent import Agent

def get_top_hackernews_stories(num_stories: int = 10) -> str:
    """
    Use this function to get top stories from Hacker News.

    Args:
        num_stories (int): Number of stories to return. Defaults to 10.

    Returns:
        str: JSON string of top stories.
    """

    # Fetch top story IDs
    response = httpx.get('https://hacker-news.firebaseio.com/v0/topstories.json')
    story_ids = response.json()

    # Fetch story details
    stories = []
    for story_id in story_ids[:num_stories]:
        story_response = httpx.get(f'https://hacker-news.firebaseio.com/v0/item/{story_id}.json')
        story = story_response.json()
        if "text" in story:
            story.pop("text", None)
        stories.append(story)
    return json.dumps(stories)

agent = Agent(tools=[get_top_hackernews_stories], markdown=True)
agent.print_response("Summarize the top 5 stories on HackerNews?", stream=True)

Accessing built-in parameters in Tools

Agno automatically injects some built-in parameters into your tool functions, so you can easily gain access to important information and objects in your tools.

These built-in parameters are:

  • run_context: The run context object from where you can access the session state, dependencies, metadata, etc.
  • agent: The agent object.
  • team: The team object.
  • images: The images object.
  • videos: The videos object.
  • audios: The audios object.
  • files: The files object.

For example, to access the agent in a tool, you can do:

from agno.agent import Agent
from agno.models.openai import OpenAIResponses

def get_agent_model(agent: Agent) -> str:
    """Get the model of the agent."""
    return agent.model.id

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[get_agent_model],
)

agent.print_response("What is the model of the agent?", stream=True)

See Tool Built-in Parameters for more details on run_context, agent, team, and media parameters.

Magic of the @tool decorator

To modify the behavior of a tool, use the @tool decorator. Some notable features:

  • requires_confirmation=True: Requires user confirmation before execution.
  • requires_user_input=True: Requires user input before execution. Use user_input_fields to specify which fields require user input.
  • external_execution=True: The tool will be executed outside of the agent's control.
  • show_result=True: Show the output of the tool call in the Agent's response. False by default. The result of the tool call is always sent to the model for further processing.
  • stop_after_tool_call=True: Stop the agent run after the tool call.
  • tool_hooks: Run custom logic before and after this tool call.
  • cache_results=True: Cache the tool result to avoid repeating the same call. Use cache_dir and cache_ttl to configure the cache.

Here's an example that uses many possible parameters on the @tool decorator.

advanced_tool.py
import httpx
from agno.agent import Agent
from agno.tools import tool
from typing import Any, Callable, Dict

def logger_hook(function_name: str, function_call: Callable, arguments: Dict[str, Any]):
    """Hook function that wraps the tool execution"""
    print(f"About to call {function_name} with arguments: {arguments}")
    result = function_call(**arguments)
    print(f"Function call completed with result: {result}")
    return result

@tool(
    name="fetch_hackernews_stories",                # Custom name for the tool (otherwise the function name is used)
    description="Get top stories from Hacker News",  # Custom description (otherwise the function docstring is used)
    stop_after_tool_call=True,                      # Return the result immediately after the tool call and stop the agent
    tool_hooks=[logger_hook],                       # Hook to run before and after execution
    requires_confirmation=True,                     # Requires user confirmation before execution
    cache_results=True,                             # Enable caching of results
    cache_dir="/tmp/agno_cache",                    # Custom cache directory
    cache_ttl=3600                                  # Cache TTL in seconds (1 hour)
)
def get_top_hackernews_stories(num_stories: int = 5) -> str:
    """
    Fetch the top stories from Hacker News.

    Args:
        num_stories: Number of stories to fetch (default: 5)

    Returns:
        str: The top stories in text format
    """
    # Fetch top story IDs
    response = httpx.get("https://hacker-news.firebaseio.com/v0/topstories.json")
    story_ids = response.json()

    # Get story details
    stories = []
    for story_id in story_ids[:num_stories]:
        story_response = httpx.get(f"https://hacker-news.firebaseio.com/v0/item/{story_id}.json")
        story = story_response.json()
        stories.append(f"{story.get('title')} - {story.get('url', 'No URL')}")

    return "\n".join(stories)

agent = Agent(tools=[get_top_hackernews_stories])
agent.print_response("Show me the top news from Hacker News")

This example pauses for confirmation before it fetches news. Resolve the returned requirement and continue the run as shown in User Confirmation; the initial print_response alone does not execute the pending tool.

See the @tool Decorator Reference for more details.