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)

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)

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)

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)

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)

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)

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, operation_id=None, durable_execution=False)

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.

operation_id is an optional stable logical-call identifier supplied by the LLM executor. It is transport metadata only: gateway-pinned delegation forwards it as rpc_call_id and local handlers never see it. Direct callers that omit it retain the legacy behaviour.

durable_execution forces the handler to remain inline until it has a terminal result. A checkpointed caller must never complete its tool slot while TaskManager still owns a detached child effect.

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()

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()

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)

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()

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()

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()

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__()

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