C3 AI Documentation Home

Create Custom Tools

You can perform specialized tasks such as calling an external API or accessing a data store in response to user queries using an agentic tool in C3 Generative AI. These tools let agents delegate low-level operations to defined tool logic.

C3 Generative AI provides several built-in tools. You can extend its capabilities further by creating and deploying your own custom tools.

This guide explains how to develop, upload, integrate, and optionally remove a custom tool from an agent toolkit.

Tool logic

Each custom tool defines three key methods:

  • initialize() (optional): Defines any setup logic needed before using the tool.
  • call() (required): Executes the tool’s core logic in response to agent calls.
  • terminate() (optional): Performs cleanup operations when the tool is terminated.

Each tool can also include a toolConfigurationParams object. This JSON field on Genai.Agent.Dynamic.Tool lets you pass configuration parameters to your custom tool without hardcoding values in the Python source file. It is automatically injected as a global variable in your tool’s execution context.

You can use toolConfigurationParams to:

  • Configure tool behavior without modifying the code (for example, model names, API endpoints, thresholds).
  • Pass environment-specific settings (for example, development vs. production configurations).
  • Enable or disable features dynamically (for example, enableProfiling: false).
  • Provide initialization values that differ between tool instances.

Using toolConfigurationParams improves maintainability and reusability by keeping configuration separate from implementation logic. It's available at runtime and can be accessed within the initialize(), call(), and terminate() methods of the tool.

Use the following example to define your tool logic in a Python file.

Python
from typing import TYPE_CHECKING
import requests
import json
import logging

tool_logger = logging.getLogger(__name__)
tool_logger.debug("Initializing book lookup tool...")

if TYPE_CHECKING:
    toolConfigurationParams: dict = {}

SOME_VAR = None


def initialize():
    """
    Initializes the book lookup tool by setting a global variable
    with an initialization message.

    Global Variables:
        SOME_VAR (str): Holds the initialization message.

    Returns:
        None
    """
    global SOME_VAR
    init_config = toolConfigurationParams.get("initializeConfig", "default_value")
    SOME_VAR = "Initialize set." + init_config
    print(f"Initializing {SOME_VAR}")


def call(query: str) -> str:
    """
    Use this tool to look up books using the Open Library API.

    It fetches books matching a query (title, author, subject, etc.)
    and returns the JSON response as a string.

    Parameters:
        query (str): The book title, author, or subject to look up.

    Returns:
        str: The list of matching books as a JSON string.

    Raises:
        ValueError: If the request fails or the response is invalid JSON.
    """
    url = f"https://openlibrary.org/search.json?q={query}"
    try:
        resp = requests.get(url, timeout=10)
        resp.raise_for_status()

        try:
            data = resp.json()
        except ValueError:
            raise ValueError("Invalid JSON response received from server.")

        books = data.get("docs", [])[:5]
        return json.dumps(books, indent=2)

    except requests.exceptions.RequestException as e:
        tool_logger.error(f"book_lookup_tool: Unable to fetch data: {e}")
        raise ValueError(f"Error fetching books: {e}")


def terminate():
    """
    Teardown logic to clean up resources and indicate termination.

    Global Variables:
        SOME_VAR (str): Holds the termination message.

    Returns:
        None
    """
    global SOME_VAR
    terminate_config = toolConfigurationParams.get("terminateConfig", "default_value")
    SOME_VAR = "tool terminated." + terminate_config
    print(f"Terminating {SOME_VAR}")

Save the file as book_lookup.py.

Upload the Python file

  1. In the C3 AI Console, open your C3 Generative AI application card.
  2. Select Tools > Load File.
  3. In the upload dialog:
    • Select the Python file book_lookup.py.
    • Set Destination to File System.
    • Set File System mount to datasets.
    • Select Load.
  4. After upload completes, copy and save the generated file URL (for example,
    azure://genai/envnov5/testapp504/dl/book_lookup.py). You will use this in later steps.

List the available agents

Get the config.name of the Dynamic Agent you want to configure the tool for. Run this command in your Python notebook.

Python
c3.Genai.Agent.Dynamic.Canvas.fetch()

Add the tool to an agent’s toolkit

You can configure custom tools for specific agent instances such as CanvasAgent_default or CanvasAgent_deep_research.

  1. Open Jupyter from your C3 AI Studio application card.

  2. Create a new notebook and select the py-query_orchestrator kernel.

  3. Run the following code to view and extend your agent’s toolkit.

    Python
    config = c3.Genai.Agent.Dynamic.Config.forConfigKey('<agent config.name>')
    current_toolkit = config.getConfig().toolkit.get()
    print(current_toolkit)
    
    current_tools = current_toolkit.allTools()
    for tool in current_tools:
        print(f"- {tool.id}: {tool.name}")
  4. Create and register the new tool.

    Python
    books_lookup = c3.Genai.Agent.Dynamic.Tool.make({
    "id": "books_lookup",
    "name": "books_lookup",
    "descriptionForLlm": "A tool that looks up books from the global Open Library database.",
    "pySrc": c3.File.make({"url": "azure://genai/envnov5/testapp504/dl/book_lookup.py"}),
    "toolConfigurationParams": {}
    })

    If you define configuration parameters while creating the tool, reference them in your Python code using the global variable toolConfigurationParams.

    For example, use a parameter such as apiEndpoint instead of hardcoding the URL:

    Python
    "toolConfigurationParams": {
    "apiEndpoint": "https://openlibrary.org/search.json",
    "enableProfiling": False,
    "initializeConfig": "custom_init_value"
    }
  5. Add the new tool to the existing toolkit.

    Python
    existing_tools = current_toolkit.allTools()
    tools_dict = {tool.id: {"id": tool.id} for tool in existing_tools}
    tools_dict["books_lookup"] = {"id": "books_lookup"}
    
    updated_toolkit = current_toolkit.withTools(tools_dict).merge()
    c3.Genai.Agent.Dynamic.Config.forConfigKey('<agent config.name>').setConfigValue("toolkit", updated_toolkit)

Restart the agent deployment

After updating the toolkit, restart the agent deployment for the changes to take effect. Use the agent ID (not the config.name) obtained from the earlier fetch command.

Python
def stopCoreAgentDeployment(dynamicAgentId):
    agent = c3.Genai.Agent.Dynamic.Core.forId(dynamicAgentId)
    deployment = c3.GenaiCore.Agent.Deployment.fetch({
        "filter": c3.Filter.startsWith('name', agent.name)
    }).first()
    
    if deployment:
        deployment.remove()
    
    engines = c3.Genai.PyUtil.listAllEngines()
    for engine in engines:
        if agent.name in engine.name:
            engine.terminate()


def startCoreAgentDeployment(dynamicAgentId):
    agent = c3.Genai.Agent.Dynamic.Core.forId(dynamicAgentId)
    deployment = agent.deploy(name=f"{agent.name}_deploy_{c3.Uuid.create()}")
    return deployment


def restartCoreAgentDeployment(dynamicAgentId):
    stopCoreAgentDeployment(dynamicAgentId)
    startCoreAgentDeployment(dynamicAgentId)


agent_id = "<agent-id>"

stopCoreAgentDeployment(agent_id)
startCoreAgentDeployment(agent_id)
restartCoreAgentDeployment(agent_id)

Verify in the UI

  1. Refresh your C3 AI Application UI after the deployment restart.

  2. From the Agents tab, open Dynamic Agent.

  3. Confirm that the new tool appears in the Toolkit list.

  4. To validate the tool is active, query the agent with:
    “Give me list of all the tools you have access to”

    Tool confirmation image 1

    !Tool confirmation image 2

Delete the tool

If you need to remove a tool, follow these steps:

  1. Fetch the toolkit and its tools.

    Python
    toolkit = c3.Genai.Agent.Dynamic.Toolkit.forId('<toolkit-id>').get('tools')
    print(toolkit)
  2. Filter out the tool you want to delete and update the toolkit.

    Python
    updated_tools = [tool for tool in toolkit.tools if tool.id != 'books_lookup']
    toolkit = toolkit.withTools(updated_tools).merge()
  3. Restart the deployment to apply the change. You can reuse the restart steps from the previous section. Ensure you pass the agent ID (not the config.name) when calling the deployment functions.

See also

Was this page helpful?