tools package

Extensible tool-calling framework.

Register tools with the @registry.tool decorator. Each tool is an async callable that receives keyword arguments and returns a string result.

Example usage:

from tools import ToolRegistry

registry = ToolRegistry()

@registry.tool(
    name="get_weather",
    description="Get the current weather for a location.",
    parameters={
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "City and state, e.g. 'San Francisco, CA'",
            },
        },
        "required": ["location"],
    },
)
async def get_weather(location: str) -> str:
    return f"The weather in {location} is sunny and 72°F."
class tools.ToolDefinition(name, description, parameters, handler, no_background=False, allow_repeat=False)[source]

Bases: object

Immutable record describing one tool registered with the framework.

Holds everything ToolRegistry needs to expose a tool to the LLM and dispatch a call to it: the LLM-visible name and description, the JSON-Schema parameters block, the async handler coroutine, and two behavioural flags. no_background keeps the call inline (the result is awaited directly instead of being handed to TaskManager for background execution), and allow_repeat exempts the tool from the executor’s repetition-loop guard. Instances are created by ToolRegistry.tool() when a handler is decorated and are read back out by the schema-export and dispatch paths (ToolRegistry.call(), ToolRegistry.list_tools(), ToolRegistry.repeat_allowed_tools()).

Parameters:
  • name (str) – Tool name as advertised to the model.

  • description (str) – Human-readable summary of what the tool does.

  • parameters (dict[str, Any]) – JSON Schema object describing the accepted arguments.

  • handler (Callable[..., Awaitable[str]]) – The async callable invoked to run the tool.

  • no_background (bool) – If true, never offload the call to TaskManager.

  • allow_repeat (bool) – If true, the tool is exempt from repetition detection.

name: str
description: str
parameters: dict[str, Any]
handler: Callable[[...], Awaitable[str]]
no_background: bool = False
allow_repeat: bool = False
class tools.ToolRegistry(task_manager=None)[source]

Bases: object

Registry that stores tool definitions and executes tool calls.

A threading.RLock serializes access to _tools and tool caches so run() and concurrent call() / OpenAI schema reads cannot race.

Parameters:

task_manager (TaskManager | None)

__init__(task_manager=None)[source]

Initialize an empty registry, optionally bound to a TaskManager.

Sets up the internal tool table, the per-tool permission map, the threading.RLock that serializes every read and write, and the two lazily-populated caches of OpenAI-format schemas. The optional task_manager is stored so that non-nested call() invocations of background-eligible tools can be offloaded to it; when it is None every call runs inline. A registry is constructed once per microservice worker (the inference and web services build one during startup) and then populated by the tool loader.

Parameters:

task_manager (TaskManager | None) – The TaskManager used to run long tools in the background, or None to always run inline.

Return type:

None

task_manager: TaskManager | None
set_permissions(permissions)[source]

Set per-tool user whitelists.

permissions maps tool names to lists of allowed user IDs. A special value "*" in the list means everyone. Tools not present in the dict are allowed for all users.

Return type:

None

Parameters:

permissions (dict[str, list[str]])

is_allowed(tool_name, user_id)[source]

Return True if user_id may execute tool_name.

Rules: 1. Tool not in the permissions dict -> allow (backward compatible). 2. "*" in the tool’s allowed list -> allow. 3. user_id in the tool’s allowed list -> allow. 4. Otherwise -> deny.

Return type:

bool

Parameters:
  • tool_name (str)

  • user_id (str)

tool(name, description, parameters)[source]

Decorator to register an async function as a tool.

Parameters:
  • name (str) – The tool name exposed to the LLM.

  • description (str) – Human-readable description of what the tool does.

  • parameters (dict[str, Any]) – JSON Schema object describing the tool’s parameters.

Return type:

Callable

async call(name, arguments, user_id='', ctx=None, *, nested=False)[source]

Execute a registered tool by name and return the result string.

If user_id is provided, the tool’s permission whitelist is checked first. If ctx is provided and the handler declares a ctx parameter, the context is injected automatically.

If nested is true, the coroutine is awaited directly (TaskManager is skipped) so compound tools receive concrete results instead of background task_id envelopes when inner calls exceed the timeout.

If the tool raises an exception the error message is returned so the LLM can see what went wrong and recover.

Return type:

str

Parameters:
invalidate_cache()[source]

Clear the cached OpenAI tool representations.

Called automatically when tools are registered via the tool decorator. Must also be called explicitly after bulk mutations such as _tools.clear() (e.g. in reload_tools).

Return type:

None

get_openai_tools()[source]

Return tool definitions in the OpenAI function-calling JSON format.

Returns an empty list when no tools are registered, which means the tools parameter can be omitted from the API call.

Return type:

list[dict[str, Any]]

get_openai_tools_by_names(names)[source]

Return only the OpenAI tool dicts whose names are in names.

Uses a cached dict for O(1) per-name lookup instead of rebuilding and filtering the full list each time.

Return type:

list[dict[str, Any]]

Parameters:

names (set[str])

list_tools()[source]

Return a snapshot list of every registered ToolDefinition.

Takes the lock and copies the current values of _tools so callers can iterate the full set of tools (name, description, parameters and flags) without holding the lock or racing a reload. It backs a wide range of consumers across the repo – the tool-embedding indexer in classifiers.update_tool_embeddings and classifiers.build_tool_index, the web tools_tasks_api listing endpoint, the subagent tool filter in tools/subagent_tools.py, tools/search_tools.py and the write/import-tool flows – each of which then reads fields off the returned definitions.

Return type:

list[ToolDefinition]

Returns:

A new list of the registered tool definitions.

tool_names()[source]

Return the set of all registered tool names as an immutable snapshot.

Reads the keys of _tools under the lock and freezes them, giving a thread-safe, cheaply-comparable view of which tools currently exist. Used by message_processor.generate_and_send to validate and gate tool selection (for example checking that activate_skill is present) and by the per-service tool-loading tests to assert a service finished registering its tools.

Return type:

frozenset[str]

Returns:

A frozenset of the registered tool names.

repeat_allowed_tools()[source]

Return the names of tools exempt from repetition-loop detection.

Collects the names of every definition whose allow_repeat flag is set, snapshotting them under the lock. The executor (openrouter_client.executor) reads this set so it can suppress its “the model keeps calling the same tool” guard for tools that are legitimately meant to be invoked repeatedly.

Return type:

frozenset[str]

Returns:

A frozenset of repeat-exempt tool names.

property has_tools: bool

Return whether any tool is currently registered.

A cheap, lock-guarded predicate used to decide whether tool-calling is even possible. The transport layer (openrouter_client.transport) checks it before attaching a tools block to an outbound request, and the per-service loading tests use it to confirm that the inference service registered tools while the web service did not.

Returns:

True if at least one tool is registered, else False.

__len__()[source]

Return the number of registered tools.

Lets the registry be used directly in len(registry) and boolean contexts. Reads the size of _tools under the lock.

Return type:

int

Returns:

The count of registered tool definitions.

Subpackages

Submodules