Skip to content

Custom Tools

Overview

Building your own tools is easy with Griptape!

Tools are nothing more than Python classes that inherit from BaseTool. Each method in the class is decorated with an activity decorator which informs the LLM how and when it should use that Tool Activity.

Random Tool

Here is a simple Tool for performing various operations with the random module.

import random

from schema import Literal, Optional, Schema

from griptape.artifacts import TextArtifact
from griptape.artifacts.list_artifact import ListArtifact
from griptape.structures import Agent
from griptape.tools import BaseTool
from griptape.utils.decorators import activity


class RandomTool(BaseTool):
    @activity(
        config={
            "description": "Can be used to generate random numbers",
        }
    )
    def generate_rand_num(self) -> TextArtifact:
        """Generate a random number between 0 and 1.

        Returns:
            TextArtifact: The random number as a Text Artifact.
        """
        return TextArtifact(random.random())

    @activity(
        config={
            "description": "Can be used to generate random numbers",
            "schema": Schema(
                {
                    Literal("start", description="The start of the rand range, inclusive."): int,
                    Literal("stop", description="The start of the rand range, exclusive."): int,
                }
            ),
        }
    )
    def generate_rand_range(self, start: int, stop: int) -> TextArtifact:
        """Generate a random number between start and stop.

        Args:
            start (int): The starting number.
            stop (int): The ending number.

        Returns:
            TextArtifact: The random number as a Text Artifact.
        """
        return TextArtifact(random.randrange(start, stop))

    @activity(
        config={
            "description": "Can be used to select a random item from a list",
            "schema": Schema(
                {
                    "items": [str],
                }
            ),
        }
    )
    def select_rand_item(self, *, values: dict) -> TextArtifact:
        """Select a random item from a list.

        Args:
            values (dict): The values declared by the schema.

        Returns:
            TextArtifact: The selected item as a Text Artifact.
        """
        items = values["items"]

        return TextArtifact(random.choice(items))

    @activity(
        config={
            "description": "Can be used to sample a list",
            "schema": Schema(
                {
                    "items": [str],
                    Optional("k"): int,
                }
            ),
        }
    )
    def sample_list(self, *, params: dict) -> ListArtifact[TextArtifact]:
        """Shuffle a list.

        Args:
            params (dict): A dictionary containing a key, `values`, which contains the values declared by the schema.

        Returns:
            TextArtifact: The sampled list as a List Artifact of Text Artifacts.
        """
        values = params["values"]

        items = values["items"]
        k = values.get("k", 5)

        sampled = random.sample(items, k)

        return ListArtifact([TextArtifact(item) for item in sampled])


agent = Agent(tools=[RandomTool()])

agent.run("Generate a number between 5 and 10, then generate that many animals, sample 3, then randomly select one.")
[02/27/25 20:26:48] INFO     PromptTask 976d49041fa0427b83ca750472759499        
                             Input: write me a haiku about griptape             
[02/27/25 20:26:49] INFO     PromptTask 976d49041fa0427b83ca750472759499        
                             Output: Beneath my worn shoes,                     
                             Griptape holds the board steady—                   
                             Silent, rough embrace.                             

Tool Activities

Activities are actions an LLM can perform with a various Tool. They pair a natural language description with some code to execute. Some examples:

  • "Can be used to create a random number" -> generate_rand_num
  • "Can be used to select a random item from a list" -> select_rand_item

Technically, each Activity is a method in the tool class that's decorated with the activity decorator.

Griptape will convert the Tool and its Activities into the appropriate format for the LLM to use. You can see the schema for a particular Activity by calling to_json_schema.

from rich.pretty import pprint

from griptape.tools import CalculatorTool

tool = CalculatorTool()

pprint(tool.to_activity_json_schema(tool.calculate, "Calculate Schema"))
{
│   'type': 'object',
│   'properties': {
│   │   'values': {
│   │   │   'type': 'object',
│   │   │   'properties': {
│   │   │   │   'expression': {
│   │   │   │   │   'description': "Arithmetic expression parsable in pure Python. Single line only. Don't use variables. Don't use any imports or external libraries",
│   │   │   │   │   'type': 'string'
│   │   │   │   }
│   │   │   },
│   │   │   'required': ['expression'],
│   │   │   'additionalProperties': False
│   │   }
│   },
│   'required': ['values'],
│   'additionalProperties': False,
│   '$id': 'Calculate Schema',
│   '$schema': 'http://json-schema.org/draft-07/schema#'
}

Each Activity takes a config keyword argument that contains the configuration for the Activity. The configuration can contain:

  • description (str): A plain text description of the Activity. Ensure that the description is clear and concise as it will help inform the LLM of when to pick this Activity.
  • schema (optional): An optional instance of Schema that defines the input values to the Activity. This field should be omitted if the Activity does not accept any input values.

Activity Methods

Activity decorated methods should return an Artifact, though Griptape will automatically convert any other return type to an InfoArtifact.

If an Activity's config declares a schema, the method should declare parameters using one of the following styles:

  • Standard python keyword arguments. See generate_random_number.
  • values (dict): A dictionary of the input values to the Activity. See select_random_item.
  • params (dict): A dictionary that will contain a single key, values. See sample_list. Other keys may be added in the future, though generally, you should prefer using one of the other styles.

Warning

Do not name any schema fields as values or params. They are reserved for the Activity method signature.

Tool Dependencies

Each Tool can also have its own dependencies. You can specify them in a requirements.txt file in the tool directory and Griptape will install them during Tool execution. To start, create a directory for your Tool inside your project. The directory must have the following structure:

griptape/tools/calculator/
├── __init__.py
├── requirements.txt # file with tool Python dependencies
└── tool.py # file with tool Python class

That's it! Import and use your Tool in your project as you would with any other Griptape Tool.

Check out other Griptape Tools to learn more about tool implementation details.