On this page
ToolRegistry builds an agent's tool set from data-driven ToolEntry records and advisory Edges between tools; create_builtin_registry seeds it and validate_allow_lists checks allow-list references.
#scheduler.src.orxtra.scheduler._tool_registry
#scheduler.src.orxtra.scheduler._tool_registry
Data-driven tool registry for building agent tool sets.
#ToolEntry
Registry entry for a single tool.
#Edge
Advisory edge between two tools in the tool graph.
Edges are purely advisory -- they inform suggestions but never enforce ordering or auto-loading.
#ToolRegistry
Registry of tool entries for data-driven tool construction.
Built-in tools are registered at construction time. Custom tools can be added via register_custom. The registry provides metadata for allow-list resolution and builds concrete Tool instances from a set of resolved names.
#register
def register(self, entry: ToolEntry) -> NoneRegister a tool entry.
Raises ValueError on duplicate name.
#register_custom
def register_custom(self, name: str, namespace: str, tags: frozenset[str], factory: Callable[[ToolDeps], Tool], description: str='', deferred: bool=False, location: ToolLocation=ToolLocation.ANYWHERE, capabilities: frozenset[ToolCapability]=frozenset()) -> NoneRegister a custom tool with full metadata.
The factory receives ToolDeps like built-in factories. Namespace and tags are required -- no implicit defaults.
#get_metadata
def get_metadata(self) -> dict[str, tuple[str, frozenset[str]]]Return name -> (namespace, tags) for all registered tools.
Used by resolve_allow_list to match wildcards and tag filters.
#get_entry
def get_entry(self, name: str) -> ToolEntry | NoneReturn the ToolEntry for a given name, or None.
#add_edge
def add_edge(self, source: str, target: str, edge_type: str) -> NoneRegister an advisory edge between two tools.
Both source and target must be registered tool names (or synthetic entries). Duplicate edges are silently ignored.
#edges_from
def edges_from(self, tool_name: str) -> list[Edge]Return all edges originating from a tool.
#edges_to
def edges_to(self, tool_name: str) -> list[Edge]Return all edges pointing to a tool.
#edges_by_type
def edges_by_type(self, edge_type: str) -> list[Edge]Return all edges of a given type.
#build_tools
def build_tools(self, names: set[str], deps: ToolDeps) -> list[Tool]Build Tool instances for the given names.
Unknown names are silently skipped (the allow-list resolver may have included names not in the registry, e.g. custom tools that were not registered).
Each built Tool inherits location and capabilities from its ToolEntry via dataclasses.replace, so factories do not need to know about routing metadata.
#_make_builtin_entries
def _make_builtin_entries() -> list[ToolEntry]Create ToolEntry objects for all 18 built-in tools.
Import the make_* constructors lazily to avoid circular imports at module load time.
#_seed_builtin_edges
def _seed_builtin_edges(registry: ToolRegistry) -> NoneSeed the registry with advisory edges for obvious relationships.
These are a small starter set. Edges are purely advisory -- they drive result-appendix suggestions, never enforcement.
#create_builtin_registry
def create_builtin_registry() -> ToolRegistryCreate a ToolRegistry populated with all built-in tools.
Does NOT include: git (needs resolved_names context), consult (needs already-built tools), or lifecycle tools (always added unconditionally).
Git and consult are handled separately in the build phase because they depend on the resolved tool set.
#validate_allow_lists
def validate_allow_lists(agents: dict[str, Any], registry: ToolRegistry) -> NoneValidate every agent's allow list and deferred declarations.
Called at Scheduler construction after all custom tools are registered, before any execution starts.
Allow-list rules:
*(universal wildcard): always valid.#tag: the tag must exist in the known tag vocabulary
(union of all tags across registry entries and synthetic entries). Unknown tag = hard error.
ns.*(namespace wildcard): zero matches is fine --
wildcards are the flexible mechanism for optional tool sets.
- Explicit name: must exist in registry entries, synthetic
entries, or lifecycle tool names. Unknown = hard error.
Deferred-list rules:
- Every name in an agent's deferred list must exist in the
registry (not synthetic entries or lifecycle tools -- deferred tools must have a factory to build later). Unknown = hard error.
- Deferred names must also be in the agent's allow list
(deferred is a subset of allowed).
Raises:
ValueError: naming the agent and the offending entry.