Skip to content

Tool Registry

Registry

agora_workbench.code_execution.tool_registry.tool_registry.ToolRegistry(package=None)

Registry that stores and indexes :class:~code_execution.tool_registry.ToolDefinition objects.

Each registered tool receives a unique integer ID (assigned sequentially starting from 0). Tools can be retrieved by ID or by name in O(1) time via internal dictionaries.

By default, tool X is imported as from {package}.{X} import {X}. Override with ToolDefinition.module or ToolDefinition.module_override to use a custom import path.

Parameters:

Name Type Description Default
package str | None

Default Python package for tool imports. When set, the kernel proxy generates from {package}.{tool_name} import {tool_name} for each registered tool that does not set module_override or an explicit module.

None
Source code in src/agora_workbench/code_execution/tool_registry/tool_registry.py
def __init__(self, package: str | None = None):
    self.package = package
    self.tools: list[ToolDefinition] = []
    self.next_id = 0
    self._name_index: dict[str, ToolDefinition] = {}
    self._id_index: dict[int, ToolDefinition] = {}

register_tool(tool)

Register a tool in the registry.

A copy of tool is stored so that the registry's internal state cannot be mutated through the caller's reference. The copy is assigned a unique integer id before being stored.

Module resolution order
  1. tool.module_override (explicit full module path on the tool)
  2. tool.module (already resolved, e.g. from catalog deserialization)
  3. {registry.package}.{tool.name} (default convention)

If none of these yield a module path, a :class:ValueError is raised.

Parameters:

Name Type Description Default
tool ToolDefinition

The :class:~code_execution.tool_registry.ToolDefinition to register.

required

Raises:

Type Description
ValueError

If the tool's module cannot be resolved.

Source code in src/agora_workbench/code_execution/tool_registry/tool_registry.py
def register_tool(self, tool: ToolDefinition) -> None:
    """Register a tool in the registry.

    A copy of *tool* is stored so that the registry's internal state
    cannot be mutated through the caller's reference.  The copy is
    assigned a unique integer ``id`` before being stored.

    Module resolution order:
        1. ``tool.module_override`` (explicit full module path on the tool)
        2. ``tool.module`` (already resolved, e.g. from catalog deserialization)
        3. ``{registry.package}.{tool.name}`` (default convention)

    If none of these yield a module path, a :class:`ValueError` is raised.

    Args:
        tool: The :class:`~code_execution.tool_registry.ToolDefinition` to register.

    Raises:
        ValueError: If the tool's module cannot be resolved.
    """
    _tool = copy(tool)
    _tool.id = self.next_id

    # Resolve the kernel import module path
    if _tool.module_override:
        _tool.module = _tool.module_override
    elif not _tool.module:
        if self.package:
            _tool.module = f"{self.package}.{_tool.name}"
        else:
            raise ValueError(
                f"Tool '{_tool.name}' has no module_override and no explicit module set, "
                f"and the registry has no default package. Either set "
                f"ToolRegistry(package='my_package'), or set module_override on the tool."
            )

    self.tools.append(_tool)
    self._name_index[_tool.name] = _tool
    self._id_index[self.next_id] = _tool
    self.next_id += 1

get_tool_by_name(name)

Return the tool registered under name.

Parameters:

Name Type Description Default
name str

The tool's string name as supplied when it was registered.

required

Returns:

Name Type Description
The ToolDefinition

class:~code_execution.tool_registry.ToolDefinition registered under name.

Raises:

Type Description
ValueError

If no tool with that name is registered.

Source code in src/agora_workbench/code_execution/tool_registry/tool_registry.py
def get_tool_by_name(self, name: str) -> ToolDefinition:
    """Return the tool registered under *name*.

    Args:
        name: The tool's string name as supplied when it was registered.

    Returns:
        The :class:`~code_execution.tool_registry.ToolDefinition` registered under *name*.

    Raises:
        ValueError: If no tool with that name is registered.
    """
    if tool := self._name_index.get(name):
        return tool
    else:
        raise ValueError(f"The tool {name} is not registered.")

get_tool_by_server_and_name(server_name, name)

Return the tool registered under server_name and name.

Parameters:

Name Type Description Default
server_name str

The MCP server name the tool belongs to.

required
name str

The tool's string name.

required

Returns:

Type Description
ToolDefinition

The matching :class:~code_execution.tool_registry.ToolDefinition.

Raises:

Type Description
ValueError

If no matching tool can be found.

Source code in src/agora_workbench/code_execution/tool_registry/tool_registry.py
def get_tool_by_server_and_name(self, server_name: str, name: str) -> ToolDefinition:
    """Return the tool registered under *server_name* and *name*.

    Args:
        server_name: The MCP server name the tool belongs to.
        name: The tool's string name.

    Returns:
        The matching :class:`~code_execution.tool_registry.ToolDefinition`.

    Raises:
        ValueError: If no matching tool can be found.
    """
    for tool in self.tools:
        if tool.name == name and (tool.server_name or "") == (server_name or ""):
            return tool
    raise ValueError(f"The tool '{name}' on server '{server_name}' is not registered.")

get_tool_by_id(tool_id)

Return the tool with the given integer registry ID.

Parameters:

Name Type Description Default
tool_id int

The integer ID assigned to the tool at registration time.

required

Returns:

Name Type Description
The ToolDefinition

class:~code_execution.tool_registry.ToolDefinition with that ID.

Raises:

Type Description
ValueError

If no tool with that ID is registered.

Source code in src/agora_workbench/code_execution/tool_registry/tool_registry.py
def get_tool_by_id(self, tool_id: int) -> ToolDefinition:
    """Return the tool with the given integer registry ID.

    Args:
        tool_id: The integer ID assigned to the tool at registration time.

    Returns:
        The :class:`~code_execution.tool_registry.ToolDefinition` with that ID.

    Raises:
        ValueError: If no tool with that ID is registered.
    """
    if tool := self._id_index.get(tool_id):
        return tool
    else:
        raise ValueError(f"The tool with id {tool_id} is not registered.")

get_id_by_name(name)

Return the integer registry ID for the tool registered under name.

Parameters:

Name Type Description Default
name str

The tool's string name.

required

Returns:

Type Description
int

The integer ID assigned to the tool at registration time.

Raises:

Type Description
ValueError

If no tool with that name is registered.

Source code in src/agora_workbench/code_execution/tool_registry/tool_registry.py
def get_id_by_name(self, name: str) -> int:
    """Return the integer registry ID for the tool registered under *name*.

    Args:
        name: The tool's string name.

    Returns:
        The integer ID assigned to the tool at registration time.

    Raises:
        ValueError: If no tool with that name is registered.
    """
    if tool := self._name_index.get(name):
        assert tool.id is not None
        return tool.id
    else:
        raise ValueError(f"The tool {name} is not registered.")

get_name_by_id(tool_id)

Return the name of the tool with the given integer registry ID.

Parameters:

Name Type Description Default
tool_id int

The integer ID assigned to the tool at registration time.

required

Returns:

Type Description
str

The string name of the registered tool.

Raises:

Type Description
ValueError

If no tool with that ID is registered.

Source code in src/agora_workbench/code_execution/tool_registry/tool_registry.py
def get_name_by_id(self, tool_id: int) -> str:
    """Return the name of the tool with the given integer registry ID.

    Args:
        tool_id: The integer ID assigned to the tool at registration time.

    Returns:
        The string name of the registered tool.

    Raises:
        ValueError: If no tool with that ID is registered.
    """
    if tool := self._id_index.get(tool_id):
        return tool.name
    else:
        raise ValueError(f"The tool with id {tool_id} is not registered.")

remove_tool_by_id(tool_id)

Remove the tool with the given ID and update indexes.

Parameters:

Name Type Description Default
tool_id int

The integer ID of the tool to remove.

required

Returns:

Type Description
bool

True if the tool was successfully removed.

Raises:

Type Description
ValueError

If no tool with that ID is registered.

Source code in src/agora_workbench/code_execution/tool_registry/tool_registry.py
def remove_tool_by_id(self, tool_id: int) -> bool:
    """Remove the tool with the given ID and update indexes.

    Args:
        tool_id: The integer ID of the tool to remove.

    Returns:
        ``True`` if the tool was successfully removed.

    Raises:
        ValueError: If no tool with that ID is registered.
    """
    tool = self.get_tool_by_id(tool_id)
    self.tools = [t for t in self.tools if t.id != tool_id]
    del self._id_index[tool_id]
    if tool.name in self._name_index:
        del self._name_index[tool.name]
    return True

remove_tool_by_name(name)

Remove the tool with the given name and update indexes.

Parameters:

Name Type Description Default
name str

The string name of the tool to remove.

required

Returns:

Type Description
bool

True if the tool was successfully removed.

Raises:

Type Description
ValueError

If no tool with that name is registered.

Source code in src/agora_workbench/code_execution/tool_registry/tool_registry.py
def remove_tool_by_name(self, name: str) -> bool:
    """Remove the tool with the given name and update indexes.

    Args:
        name: The string name of the tool to remove.

    Returns:
        ``True`` if the tool was successfully removed.

    Raises:
        ValueError: If no tool with that name is registered.
    """
    tool = self.get_tool_by_name(name)
    self.tools = [t for t in self.tools if t.name != name]
    del self._name_index[name]
    if tool.id in self._id_index:
        del self._id_index[tool.id]
    return True

Tool Schema

agora_workbench.code_execution.tool_registry.tool_schema

Pydantic models for tool definitions used by code execution servers.

This module provides strongly-typed schemas for tool registry entries, ensuring consistent structure and validation for tools registered on MCP code execution servers.

ToolParameter

Bases: BaseModel

Schema for a tool parameter (required or optional).

ReturnSpec

Bases: BaseModel

Specification for a single return value from a tool.

Tool implementation returns a dict mapping names to values

return {"builder": builder_obj, "model": model_obj, "summary": {...}}

State(token, description='', affordances=None)

A named state in a domain's tool workflow graph.

States represent meaningful intermediate artifacts that tools produce and consume. They form the nodes in the state-transition graph that powers workflow planning and skill discovery.

Can be used directly in StateTransition.requires and StateTransition.produces alongside plain strings::

MOLECULE_PARSED = State(
    token="chemistry.molecule_parsed",
    description="A SMILES string has been validated and canonicalized",
    affordances=["validate a SMILES string", "identify a molecule from SMILES"],
)

parse_molecule = ToolDefinition(
    ...,
    state_transition=StateTransition(produces=frozenset({MOLECULE_PARSED})),
)

Attributes:

Name Type Description
token

Canonical string identifier (e.g. "chemistry.molecule_parsed").

description

Human-readable explanation of what this state represents.

affordances

Search phrases describing what achieving this state enables.

Source code in src/agora_workbench/code_execution/tool_registry/tool_schema.py
def __init__(self, token: str, description: str = "", affordances: list[str] | None = None):
    object.__setattr__(self, "token", token)
    object.__setattr__(self, "description", description)
    object.__setattr__(self, "affordances", affordances or [])

StateTransition

Bases: BaseModel

Preconditions and postconditions for a tool expressed as state tokens.

State tokens can be plain strings or :class:State objects. When State objects are used, the token string is extracted for storage and serialization. The requires set lists states that must hold before the tool can run; produces lists states that will hold after a successful invocation.

normalize_state_tokens(v) classmethod

Accept State objects, strings, or Enums and normalize to a frozenset of token strings.

Source code in src/agora_workbench/code_execution/tool_registry/tool_schema.py
@field_validator("requires", "produces", mode="before")
@classmethod
def normalize_state_tokens(cls, v: Any) -> frozenset[str]:
    """Accept State objects, strings, or Enums and normalize to a frozenset of token strings."""

    def _to_token(item: Any) -> str:
        if isinstance(item, State):
            return item.token
        # Support str-Enums (e.g. class MyState(str, Enum)) — use .value
        if isinstance(item, Enum):
            return str(item.value)
        return str(item)

    if isinstance(v, (frozenset, set, list, tuple)):
        return frozenset(_to_token(item) for item in v)
    return v

ToolDefinition

Bases: BaseModel

Schema for a complete tool definition in the registry.

By default, tool X is imported as from {package}.{X} import {X} when registered in ToolRegistry(package=...). Override with module or module_override for custom import paths.