Skip to content

Integrate Your Custom Python Functions with the Tool Use Agent

Overview

The Tool Use Agent is a utility agent designed to perform function calls using provided tools. It enables dynamic execution of functions based on user queries, allowing for a flexible and extensible system. By integrating both built-in and custom tools, the agent can process a wide range of tasksβ€”from simple calculations to complex data processing.

Configuration

To utilize the Tool Use Agent, you need to define its configuration in a YAML file. This configuration specifies the agent's settings and the tools it can access.

Configuration Parameters

  • agent_class: The class name of the agent. For the Tool Use Agent, this should be ToolUseAgent.
  • config: Configuration settings for the agent.
  • wait_time: The maximum time (in seconds) to wait for an external function call to complete.
  • enable_interpreter: A boolean indicating whether to use the Interpreter Agent to process function outputs before returning them to the user.
  • builtin_tools: A list of built-in tool names that the agent can use.
  • custom_tools: A list of custom tool definitions (as JSON strings) that the agent can use.

Here's an example configuration (example.yaml):

utility_agents:  
  - agent_class: ToolUseAgent  
    agent_name: "Tool Use Agent"  
    agent_description: "An agent that performs function calling using provided tools."  
    config:  
      wait_time: 120  
      enable_interpreter: true  
      builtin_tools:  
        - "calculate_expression"  
      custom_tools:  
        - |  
          {  
            "type": "function",  
            "function": {  
              "name": "generate_password",  
              "description": "Generate a random password of specified length.",  
              "parameters": {  
                "type": "object",  
                "properties": {  
                  "length": {  
                    "type": "integer",  
                    "description": "Length of the password to generate. Default is 12.",  
                    "default": 12  
                  }  
                },  
                "required": []  
              }  
            }  
          }  
        - |  
          {  
            "type": "function",  
            "function": {  
              "name": "convert_temperature",  
              "description": "Convert temperature between Celsius and Fahrenheit.",  
              "parameters": {  
                "type": "object",  
                "properties": {  
                  "value": {  
                    "type": "float",  
                    "description": "The temperature value to convert."  
                  },  
                  "to_scale": {  
                    "type": "string",  
                    "description": "The scale to convert the temperature to ('Celsius' or 'Fahrenheit').",  
                    "enum": ["Celsius", "Fahrenheit"],  
                    "default": "Celsius"  
                  }  
                },  
                "required": ["value"]  
              }  
            }  
          }  

Built-in Tools

The builtin_tools parameter allows you to specify which predefined tools the agent can access. In the example above, the agent has access to the calculate_expression tool, which evaluates mathematical expressions. We plan to add more built-in tools in the future to extend the agent's capabilities, providing even greater functionality.

Custom Tools

You can provide custom Python functions to the Tool Use Agent using the custom_tools parameter. To do this, you need to:

  1. Add your custom functions to the custom_agent_gallery: This is a dictionary that maps function names to their implementations.
  2. Provide the JSON schema of each function in the configuration: This lets the agent understand how to call your custom functions and what parameters they expect.

This ensures that the agent can correctly interpret user queries and map them to the appropriate custom functions.

Example Usage

Here's how to use the Tool Use Agent with your custom Python functions:

Define Your Custom Python Function

First, define your custom function. For example, a function to generate a random password:

import random  
import string  

async def generate_password(length: int = 12) -> str:  
    """  
    Generate a random password of specified length.  

    Args:  
        length (int, optional): The total length of the password to generate.  
            Must be at least 4 to include one of each required character type.  
            Defaults to 12.  

    Returns:  
        str: A randomly generated password string.  
    """  
    if length < 4:  
        raise ValueError("Password length should be at least 4 characters.")  

    password_chars = [  
        random.choice(string.ascii_uppercase),  
        random.choice(string.ascii_lowercase),  
        random.choice(string.digits),  
        random.choice(string.punctuation),  
    ]  

    if length > 4:  
        all_chars = string.ascii_letters + string.digits + string.punctuation  
        password_chars.extend(random.choice(all_chars) for _ in range(length - 4))  

    random.shuffle(password_chars)  
    password = "".join(password_chars)  
    return password  

Initialize the Distiller Client and Add Your Function

Next, initialize the DistillerClient and add your function to the custom_agent_gallery:

async def tool_use_demo():  
    # Initialize the DistillerClient  
    distiller_client = DistillerClient()  

    # Register a new project with your configuration  
    distiller_client.create_project(config_path="example.yaml", project="example")  

    # Map custom agent names to their corresponding functions  
    custom_agent_gallery = {  
        "generate_password": generate_password,  
    }  

    async with distiller_client(  
        project="example",  
        uuid="test_user",  
        custom_agent_gallery=custom_agent_gallery,  
    ) as dc:  
        # List of queries to process  
        queries = [  
            "Generate a safe password with 23 chars.",  
        ]  

        for query in queries:  
            # Send the query and print responses  
            responses = await dc.query(query=query)  
            print(f"----\nQuery: {query}")  
            async for response in responses:  
                print(f"Response: {response['content']}")  

In this example:

  • DistillerClient: Connects to the distiller server.
  • create_project: Sets up a new project using your configuration file (example.yaml).
  • custom_agent_gallery: Links custom agent names to their corresponding Python functions.
  • queries: A list of user queries for the agent to process.
  • Processing Queries: The agent handles each query, invokes the appropriate functions as needed, and returns the responses.

Expected Output

After running the code above, you can expect the following outputs:

With Interpreter Agent

If enable_interpreter is set to true, the Interpreter Agent processes the function's output to make it more user-friendly. The response might look like:

----  
Query: Generate a safe password with 23 chars.  
Response: Sure! Here's a randomly generated safe password with 23 characters:  

`g@5Yq^12Bz&Mn8$!j0Rc)w#`  

This password includes uppercase letters, lowercase letters, digits, and special characters to enhance security.  

Without Interpreter Agent

If enable_interpreter is set to false, the raw output from the function is returned. The response might look like:

----  
Query: Generate a safe password with 23 chars.  
Response: g@5Yq^12Bz&Mn8$!j0Rc)w#  

In the raw output, the password is provided without any additional explanation or formatting.