Skip to content

Functions Runtime

FunctionsRuntime

FunctionsRuntime(functions: Sequence[Function] = [])

A runtime for functions.

Parameters:

  • functions (Sequence[Function], default: [] ) –

    A list of functions that the runtime has access to.

Source code in src/agentdojo/functions_runtime.py
181
182
def __init__(self, functions: Sequence[Function] = []) -> None:
    self.functions: dict[str, Function] = {f.name: f for f in functions}

register_function

register_function(
    function: Callable[P, T]
) -> Callable[P, T]
register_function(function: Function) -> Function
register_function(
    function: Callable[P, T] | Function
) -> Callable[P, T] | Function

Registers a function with the runtime.

If function is a function, it will be converted to a Function instance and registered, otherwise it will be registered as is. The conversion is made with make_function.

Parameters:

  • function (Callable[P, T] | Function) –

    The function to register. It can be a function or a Function instance. See make_function for more information.

Returns:

Source code in src/agentdojo/functions_runtime.py
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
def register_function(self, function: Callable[P, T] | Function) -> Callable[P, T] | Function:
    """Registers a function with the runtime.

    If `function` is a function, it will be converted to a `Function` instance and registered,
    otherwise it will be registered as is. The conversion is made with [`make_function`][agentdojo.functions_runtime.make_function].

    Args:
        function: The function to register. It can be a function or a `Function` instance. See [`make_function`][agentdojo.functions_runtime.make_function]
            for more information.

    Returns:
        The registered function.
    """
    if isinstance(function, Function):
        self.functions[function.name] = function
        return function
    try:
        f = make_function(function)
    except Exception as e:
        raise Exception(f"Error when registering function {function.__name__} in {function.__module__}.") from e
    self.functions[function.__name__] = f
    return function

run_function

run_function(
    env: TaskEnvironment | None,
    function: str,
    kwargs: Mapping[str, FunctionCallArgTypes],
    raise_on_error: bool = False,
) -> tuple[FunctionReturnType, str | None]

Runs a function with the given arguments.

If raise_on_error is True, the function will raise an exception if an error occurs. Otherwise, it will return an error message as the second argument. The error message has the format 'ErrorType: ErrorMessage'.

Parameters:

  • env (TaskEnvironment | None) –

    The environment to extract dependencies from. It can be None if the function has no dependencies.

  • function (str) –

    The name of the function to run.

  • kwargs (Mapping[str, FunctionCallArgTypes]) –

    The arguments to pass to the function.

  • raise_on_error (bool, default: False ) –

    If True, the function will raise an exception if an error occurs. Otherwise, it will return an error message.

Returns:

  • tuple[FunctionReturnType, str | None]

    A tuple containing the result of the function and an error message if an error occurred. If no error occurred, the second element will be None.

Raises:

  • ValidationError

    If the arguments are invalid and do not match the function's input schema.

  • ToolNotFoundError

    If the requested function is not available.

Source code in src/agentdojo/functions_runtime.py
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
def run_function(
    self,
    env: TaskEnvironment | None,
    function: str,
    kwargs: Mapping[str, FunctionCallArgTypes],
    raise_on_error: bool = False,
) -> tuple[FunctionReturnType, str | None]:
    """Runs a function with the given arguments.

    If `raise_on_error` is `True`, the function will raise an exception if an error occurs. Otherwise, it will return an error message as the second
    argument. The error message has the format `'ErrorType: ErrorMessage'`.

    Args:
        env: The environment to extract dependencies from. It can be `None` if the function has no dependencies.
        function: The name of the function to run.
        kwargs: The arguments to pass to the function.
        raise_on_error: If `True`, the function will raise an exception if an error occurs. Otherwise, it will return an error message.

    Returns:
        A tuple containing the result of the function and an error message if an error occurred. If no error occurred, the second element will be `None`.

    Raises:
        ValidationError: If the arguments are invalid and do not match the function's input schema.
        ToolNotFoundError: If the requested function is not available.
    """
    if function not in self.functions:
        if raise_on_error:
            raise ToolNotFoundError(f"The requested function `{function}` is not available.")
        return "", f"ToolNotFoundError: The requested function `{function}` is not available."
    f = self.functions[function]

    # Execute nested function calls
    try:
        resolved_kwargs = self._execute_nested_calls(env, kwargs)
    except Exception as e:
        if raise_on_error:
            raise e
        return "", f"{type(e).__name__}: {e}"

    # Validate the arguments
    try:
        args = f.parameters.model_validate(resolved_kwargs).model_dump()
    except ValidationError as e:
        if raise_on_error:
            raise e
        return "", f"ValidationError: {e}"

    # Extract dependencies from the environment
    if env is None and len(f.dependencies) > 0:
        raise ValueError(f"Function {function} has dependencies but no environment was provided.")
    else:
        env_args = {
            arg_name: dependency.extract_dep_from_env(env)  # type: ignore -- If there are no dependencies, this line will not be executed
            for arg_name, dependency in f.dependencies.items()
        }
    kwargs_with_deps = args | env_args

    # Run the function
    try:
        return f(**kwargs_with_deps), None
    except Exception as e:
        if raise_on_error:
            raise e
        return "", f"{type(e).__name__}: {e}"

Function

Bases: BaseModel, Generic[P, T]

A function that can be called by an agent and run by a FunctionsRuntime.

name instance-attribute

name: str

The name of the function.

description instance-attribute

description: str

A short description of the function.

parameters instance-attribute

parameters: type[BaseModel]

The input schema for the function. It is defined as a Pydantic model.

dependencies instance-attribute

dependencies: dict[str, Depends]

A dictionary of dependencies for the function. See Depends for more information.

run instance-attribute

run: Callable[P, T]

The function implementation.

full_docstring instance-attribute

full_docstring: str

The full docstring of the functions.

return_type instance-attribute

return_type: Any | None

The return type of the function.

make_function

make_function(function: Callable[P, T]) -> Function

Creates a Function instance from a function.

It does so by extracting the docstrings and type hints from the function. It then creates a Pydantic model for the input schema of the function.

Note

ReStructuredText is the recommended docstring format.

Parameters:

  • function (Callable[P, T]) –

    The function to create a Function instance from. The function should have docstrings with a short description of the function and descriptions for each argument. Depends arguments should not be documented in the docstring.

Returns:

Raises:

  • ValueError

    If the function has no docstring or short description, or if the arguments docstrings are invalid.

Source code in src/agentdojo/functions_runtime.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
def make_function(function: Callable[P, T]) -> Function:
    """Creates a [`Function`][agentdojo.functions_runtime.Function] instance from a function.

    It does so by extracting the docstrings and type hints from the function. It then creates
    a Pydantic model for the input schema of the function.

    Note:
        ReStructuredText is the recommended docstring format.

    Args:
        function: The function to create a [`Function`][agentdojo.functions_runtime.Function] instance from.
            The function should have docstrings with a short description of the function and descriptions
            for each argument. [`Depends`][agentdojo.functions_runtime.Depends] arguments should not be
            documented in the docstring.

    Returns:
        A [`Function`][agentdojo.functions_runtime.Function] instance.

    Raises:
        ValueError: If the function has no docstring or short description, or if the arguments docstrings are
            invalid.
    """
    dependencies = _get_dependencies(function)

    if function.__doc__ is None or function.__doc__ == "":
        raise ValueError(f"Function {function.__name__} has no docstring")
    function_docs = parse(function.__doc__)
    if function_docs.short_description is None:
        raise ValueError(f"Function {function.__name__} has no short description")
    return Function[P, T](
        name=function.__name__,
        description=function_docs.short_description.replace("None", "null"),
        parameters=_parse_args(function.__name__, function_docs.params, inspect.signature(function)),
        run=function,
        dependencies=dependencies,
        full_docstring=function.__doc__,
        return_type=get_type_hints(function).get("return"),
    )

Depends dataclass

Depends(
    env_dependency: str | Callable[[BaseModel], BaseModel]
)

A dependency for a function. It is used to extract information from the environment to pass to the function.

env_dependency instance-attribute

env_dependency: str | Callable[[BaseModel], BaseModel]

The name of the attribute to extract from the environment or a function that returns the attribute from the environment.

extract_dep_from_env

extract_dep_from_env(env: BaseModel) -> BaseModel

Extracts the dependency from the environment.

Source code in src/agentdojo/functions_runtime.py
31
32
33
34
35
def extract_dep_from_env(self, env: BaseModel) -> BaseModel:
    """Extracts the dependency from the environment."""
    if callable(self.env_dependency):
        return self.env_dependency(env)
    return getattr(env, self.env_dependency)

FunctionCall

Bases: BaseModel

An object containing information about a function call requested by an agent.

function instance-attribute

function: str

The name of the function to call.

args instance-attribute

The arguments to pass to the function.

id class-attribute instance-attribute

id: str | None = None

An optional ID for the function call. E.g., used by OpenAI and Anthropic.

placeholder_args class-attribute instance-attribute

placeholder_args: (
    Mapping[str, FunctionCallArgTypes] | None
) = None

An optional dictionary of placeholder arguments to use in by ground truth agent in injection tasks.

FunctionCallArgTypes module-attribute

FunctionCallArgTypes = (
    str
    | int
    | float
    | bool
    | None
    | dict
    | list
    | FunctionCall
)

Valid types for function call arguments.

FunctionReturnType module-attribute

FunctionReturnType: TypeAlias = (
    BaseModel
    | Sequence["FunctionReturnType"]
    | dict
    | str
    | int
    | float
    | bool
    | None
)

Union of valid return types for functions. The default FunctionsRuntime is not guaranteed to work with other types.

TaskEnvironment

Bases: BaseModel

Base class for the environment in which the agent is running.

EmptyEnv

Bases: TaskEnvironment

An empty environment for when a state is not needed.