Skip to content

Function Tools

Allowing your agents to use your python functions as tools for your agents is quite straight forward. You can choose one of the following ways:

Docstrings

Your Python functions need to contain typehints for parameters and docstrings as that is what Railtracks automatically parses to inform your LLM about the capability of the tool. Parameter descriptions can be written as Google-style, NumPy-style, or reST/Sphinx-style docstrings. Typehints always belong on the function signature itself, whatever style you pick.

import railtracks as rt

@rt.function_node # (1)!
def tool_name(arg1: arg1_type, arg2: arg2_type)->return_type:
    """
    Information on what this tool does

    Args:
        arg1: what this arg is
        arg2: what this arg is

    Returns:
        information about return type
    """
    ...

Agent = rt.agent_node(
    ...
    tool_nodes=[rt.function_node(some_tool)]
)
  1. Simply add the railtracks.function_node decorator before the definition of your function. This transforms your function into a node type usable upon passing to any agent.
import railtracks as rt
from your_tool_module import some_tool

Agent = rt.agent_node(
    ...
    tool_nodes=[rt.function_node(some_tool)]
)

Tool names must be unique

Two different tools cannot share a name — the model would have no way to address them apart

square = rt.function_node(functools.partial(power, exp=2), name="square")
cube = rt.function_node(functools.partial(power, exp=3), name="cube")

Supported docstring styles

The same tool written in each of the three supported styles. All three produce identical parameter descriptions for the LLM.

@rt.function_node
def power(base: float, exp: float) -> float:
    """
    Raise base to the power of exp.

    Args:
        base: The number to raise.
        exp: The exponent applied to base.

    Returns:
        base raised to exp.
    """
    return base**exp
@rt.function_node
def power(base: float, exp: float) -> float:
    """
    Raise base to the power of exp.

    Parameters
    ----------
    base : float
        The number to raise.
    exp : float
        The exponent applied to base.

    Returns
    -------
    float
        base raised to exp.
    """
    return base**exp
@rt.function_node
def power(base: float, exp: float) -> float:
    """
    Raise base to the power of exp.

    :param base: The number to raise.
    :param exp: The exponent applied to base.
    :return: base raised to exp.
    """
    return base**exp

The Google Args: header can also be written as Arguments: or Parameters:, and reST accepts every Sphinx parameter field name (:param, :parameter, :arg, :argument, :key, :keyword). Use one style per docstring: if a docstring mixes them, Railtracks warns and reads only one, in the order Google, NumPy, reST.

Inspecting an agent's tools

tool_nodes() returns the tools avaliable to the agent, and tool_info() returns the tool schema that the LLM sees.

Agent = rt.agent_node("agent", llm=..., tool_nodes=[fn_a, fn_b])

Agent.tool_nodes()                            # -> [FnANode, FnBNode]
[t.tool_info() for t in Agent.tool_nodes()]   # the Tool schemas the LLM sees