Skip to content

Tool

class versionhq.tool.model.Tool

A Pydantic class to store the tool object.

Quick Start

By defining the function, you can let the agent start to use it when they get an approval.

import versionhq as vhq

def demo_func(message: str) -> str:
    return message + "_demo"

my_tool = vhq.Tool(func=demo_func)
res = my_tool.run(params=dict(message="Hi!"))

assert res == "Hi!_demo"

e.g. Build an agent with a simple tool

The tool result will be considered in the context when the agent call LLM.

import versionhq as vhq

def demo_func() -> str:
    return "demo"

my_tool = vhq.Tool(func=demo_func)

agent = vhq.Agent(
    role="Tool Handler",
    goal="efficiently use the given tools",
    tools=[my_tool, ]
)
assert agent.tools == [my_tool]

ToolSet

class versionhq.tool.model.ToolSet

To add args to the tool and record the usage, use toolset instance.

from versionhq import Tool, ToolSet, Agent

def demo_func(message: str) -> str:
    return message + "_demo"

tool_a = Tool(func=demo_func)
toolset = ToolSet(tool=tool_a, kwargs={"message": "Hi"})

agent = Agent(
    role="Tool Handler",
    goal="efficiently use the given tools",
    tools=[toolset,]
)
assert agent.tools == [toolset]

Customization

Tool name

[var]name: Optional[str] = None

By default, the tool name will be set as a function name, but you can also define a specific name for your tool.

from versionhq import Tool

def demo_func() -> str:
    return "demo"

my_tool = Tool(func=demo_func)

assert my_tool.name == "demo_func"
from versionhq import Tool

my_tool = Tool(name="my empty tool", func=lambda x: x)

assert my_tool.name == "my empty tool"

Tool names are used to call cached tools later.

Tool Execution

[var][REQUIRED] func: [Callable | Any] = None

[abstract class method]_run(self, *args, **kwargs) -> Any

Simple function calling can be handled using an abstract class method _run().

Following is the simplest way to define a quick function and execute it with the method.

from versionhq import Tool

my_tool = Tool(func=lambda x: f"demo-{x}")
res = my_tool._run(x="TESTING")

assert res == "demo-TESTING"

Another way to define the logic is to add a function to the func field.

Functions are useful for defining more complex execution flows and reusing among multiple tools.

from versionhq import Tool

def demo_func() -> str:
    """...some complex execution..."""
    return "demo"

my_tool = Tool(func=demo_func)
res = my_tool._run()

assert res == "demo"

You can also pass parameters using the class method.

from versionhq import Tool

def demo_func(message: str) -> str:
    return message + "_demo"

my_tool = Tool(func=demo_func)
res = my_tool._run(message="Hi!")

assert res == "Hi!_demo"

Custom tool execution

[abstract class method]_run**(self, *args, **kwargs) -> Any

You can also use the class method to execute your custom tool inherited from Tool instance.

from typing import Callable
from versionhq import Tool

class MyCustomTool(Tool):
  name: str = "custom tool"
  func: Callable

my_custom_tool = MyCustomTool(func=lambda x: len(x))
res = my_custom_tool._run(["demo1", "demo2"])

assert res == 2

Cached tool execution

[class_method]run(self, params: Dict[str, Any]) -> Any

To use cached tools, call the class method run instead of _run.

from typing import List, Any, Callable
from versionhq import Tool

class CustomTool(Tool):
    name: str = "custom tool"
    func: Callable

def demo_func(demo_list: List[Any]) -> int:
    return len(demo_list)

my_tool = CustomTool(func=demo_func)
res = my_tool.run(params=dict(demo_list=["demo1", "demo2"]))

assert res == 2
assert isinstance(my_tool.tool_handler, vhq.ToolHandler)

*Reference: ToolHandler class

Cache

[var]cache_function: Callable[..., Any] = None

Define a cache function to call.

[var]cache_handler: InstanceOf[CacheHandler] = None

Define how to handle cache.

[var]should_cache: bool = True

Define if the tool name and arguments should be cached or not.

  • Reference: Cache Handler class

Function Calling LLM

To use the tools with LLM, make sure the LLM supports function calling, then add the tool to the agent or task.

1. Use the agent's tools

When the agent has tools, the tools will be applicable across multiple tasks that the agent will handle with approval of can_use_agent_tools on Task instance.

i.e., Return the agent’s tools result as a final result:

from versionhq import Tool, Agent, Task

my_tool = Tool(name="demo tool", func=lambda x: "demo func")

agent = Agent(
    role="demo",
    goal="execute tools",
    func_calling_llm="gpt-4o",
    tools=[my_tool]
)

task = Task(
    description="execute tools",
    can_use_agent_tools=True, # if False, the agent's tools will NOT be called.
    tool_res_as_final=True
)

res = task.execute(agent=agent)
assert res == "demo func"

When the function calling LLM is not provided, we use the main model or default model gpt-4o .

from versionhq import Tool, Agent, Task

def demo_func(): return "demo func"
my_tool = Tool(name="demo tool", func=demo_func)

agent = Agent(
    role="demo",
    goal="execute the given tools",
    llm="gemini-2.0", # this model will be set as a function calling LLM.
    tools=[my_tool]
)

task = Task(
    description="execute the given tools",
    can_use_agent_tools=True,
    tool_res_as_final=True
)

res = task.execute(agent=agent)
assert res.tool_output == "demo func"
from versionhq import Tool, Agent, Task

my_tool = Tool(name="demo tool", func=lambda x: "demo func")

agent = Agent(
    role="Demo Tool Handler",
    goal="execute tools",
    tools=[my_tool]
)

task = Task(
    description="execute tools",
    can_use_agent_tools=True,
    tool_res_as_final=True
)

res = task.execute(agent=agent)
assert res.tool_output == "demo func"
assert agent.key in task.processed_agents

Function calling LLM

By default, the agent will prioritize the given func_calling_llm over its main llm when it uses tools.

When you build the agent, it will check if the model acutally supports function callings, and if not, func_calling_llm will be switched to main llm or default model.

If you want to see if the model of your choice supports function calling explicitly, run the following:

from versionhq.llm.model import LLM
llm = LLM(model="<MODEL_NAME_OF_YOUR_CHOICE>")
res = llm._supports_function_calling()

assert type(res) == bool

2. Add tools to the task

This is a more explicit way to call tools on a specific task.

Note your agent will NOT own the tool after the task execution.

from versionhq import Tool, ToolSet, Task, Agent

def random_func(message: str) -> str:
    return message + "_demo"

tool = Tool(name="tool", func=random_func)

tool_set = ToolSet(
    tool=tool,
    kwargs=dict(message="empty func")
)

agent = Agent(
    role="Tool Handler",
    goal="execute tools"
)

task = Task(
    description="execute the function",
    tools=[tool_set,], # use ToolSet to call args
    tool_res_as_final=True
)

res = task.execute(agent=agent)
assert res == "empty func_demo"

Decorator

[decorator]@tool[name: str]: Callable[..., Any] -> Any

When you want to use an exsiting function as a tool, you can simply add a decorator to the function.

from versionhq.tool.decorator import tool

@tool("demo")
def my_tool(test_words: str) -> str:
"""Test a tool decorator."""
return test_words

assert my_tool.name == "demo"
assert "Tool: demo" in my_tool.description and "'test_words': {'description': '', 'type': 'str'" in my_tool.description
assert my_tool.func("testing") == "testing"