Skip to content

Functions Runtime

The functions runtime provides a way to define and run Python functions in a way that makes it easy to operate with function-calling LLMs.

Stateless functions

Functions that have no state can be defined in a way that is compatible with the runtime in the following way:

functions_runtime.py
runtime = FunctionsRuntime()


# Define a function
@runtime.register_function  
def add(a: int, b: int) -> int:  
    """Sums two numbers.

    :param a: The first number.
    :param b: The second number.
    """  
    return a + b

Note

When using tools as part of a suite there is no need to manually instantiate the runtime and register functions with it. This is only useful if you want to run an agent that uses the functions runtime as a standalone tool.

The runtime can be used to run the function:

functions_runtime.py
result, _ = runtime.run_function(
    None,  
    "add",
    {"a": 1, "b": 2},
)
assert result == 3

Stateful functions

We can also define functions that rely on a stateful environment. This environment can't be given as argument by the LLM, so it is injected by the runtime in the function call. This is done by using the Depends class for the environment-related arguments when defining the function. Let's show an example where the environment contains a counter:

functions_runtime.py
class Counter(BaseModel):
    value: int

    def increment(self) -> int:
        self.value += 1
        return self.value

    def increment_by(self, n: int) -> int:
        self.value += n
        return self.value


class Environment(TaskEnvironment):
    counter: Counter


@runtime.register_function
def increment_counter(
    counter: Annotated[Counter, Depends("counter")],  
) -> int:
    """Increments the counter by 1."""  
    return counter.increment()


def increment_counter_by(
    counter: Annotated[Counter, Depends("counter")],
    n: int,
) -> int:
    """Increments the counter by `n`.

    :param n: The number to increment the counter by.
    """
    return counter.increment_by(n)


runtime.register_function(increment_counter_by)  

The runtime can be used to run the function:

functions_runtime.py
environment = Environment(counter=Counter(value=1))
result, _ = runtime.run_function(
    environment,  
    "increment_counter_by",
    {"n": 5},
)
assert result == 6

Error handling

By default, the runtime will catch exceptions raised by the function and return them to the LLM. This is useful to let the LLM recover from errors.

functions_runtime.py
_, error = runtime.run_function(
    None,
    "add",
    {"a": 1, "b": "hello"},
)
assert error is not None
assert "ValidationError" in error  

However, the runtime can also raise exceptions the raise_on_error to the run_function method is True:

functions_runtime.py
try:
    _, error = runtime.run_function(
        None,
        "add",
        {"a": 1, "b": "hello"},
        raise_on_error=True,
    )
except ValidationError:
    ...
else:
    assert False, "Expected a validation error"