Tool Registry¶
A capability-tagged registry that downstream packages use to publish their @geo_tool-decorated tools. The factory pulls a filtered subset (by category, by package availability) when assembling the agent's tool list.
geoagent.core.registry
¶
GeoAgent tool metadata registry.
GeoToolMeta
dataclass
¶
Metadata for a registered Strands tool.
Source code in geoagent/core/registry.py
@dataclass
class GeoToolMeta:
"""Metadata for a registered Strands tool."""
name: str
description: str = ""
category: str = "general"
requires_confirmation: bool = False
destructive: bool = False
long_running: bool = False
available_in: tuple[str, ...] = ("full",)
requires_packages: tuple[str, ...] = ()
extra: dict[str, Any] = field(default_factory=dict)
GeoToolRegistry
¶
Maps tool names to :class:GeoToolMeta.
Source code in geoagent/core/registry.py
class GeoToolRegistry:
"""Maps tool names to :class:`GeoToolMeta`."""
def __init__(self) -> None:
self._by_name: dict[str, GeoToolMeta] = {}
def register_tool(self, tool_obj: Any, meta: GeoToolMeta) -> None:
"""Register metadata for a Strands decorated tool."""
name = getattr(tool_obj, "tool_name", None) or meta.name
self._by_name[str(name)] = meta
def register(self, meta: GeoToolMeta) -> None:
"""Register metadata by explicit name."""
self._by_name[meta.name] = meta
def get(self, tool_name: str) -> GeoToolMeta | None:
"""Return metadata for a registered tool name."""
return self._by_name.get(tool_name)
def list_names(self) -> list[str]:
"""Return registered tool names."""
return sorted(self._by_name.keys())
def get_all_tools_config(self) -> list[dict[str, Any]]:
"""Return tool metadata as serializable config records.
Mirrors the type of inspection users expect from Strands-facing
registries while preserving GeoAgent-specific metadata.
"""
out: list[dict[str, Any]] = []
for name in self.list_names():
meta = self._by_name[name]
out.append(
{
"name": meta.name,
"description": meta.description,
"category": meta.category,
"requires_confirmation": meta.requires_confirmation,
"destructive": meta.destructive,
"long_running": meta.long_running,
"available_in": list(meta.available_in),
"requires_packages": list(meta.requires_packages),
"extra": dict(meta.extra),
}
)
return out
def needs_user_confirmation(self, meta: GeoToolMeta) -> bool:
"""Return True if the tool should go through the confirm callback."""
return bool(meta.requires_confirmation or meta.destructive or meta.long_running)
get(self, tool_name)
¶
Return metadata for a registered tool name.
Source code in geoagent/core/registry.py
def get(self, tool_name: str) -> GeoToolMeta | None:
"""Return metadata for a registered tool name."""
return self._by_name.get(tool_name)
get_all_tools_config(self)
¶
Return tool metadata as serializable config records.
Mirrors the type of inspection users expect from Strands-facing registries while preserving GeoAgent-specific metadata.
Source code in geoagent/core/registry.py
def get_all_tools_config(self) -> list[dict[str, Any]]:
"""Return tool metadata as serializable config records.
Mirrors the type of inspection users expect from Strands-facing
registries while preserving GeoAgent-specific metadata.
"""
out: list[dict[str, Any]] = []
for name in self.list_names():
meta = self._by_name[name]
out.append(
{
"name": meta.name,
"description": meta.description,
"category": meta.category,
"requires_confirmation": meta.requires_confirmation,
"destructive": meta.destructive,
"long_running": meta.long_running,
"available_in": list(meta.available_in),
"requires_packages": list(meta.requires_packages),
"extra": dict(meta.extra),
}
)
return out
list_names(self)
¶
Return registered tool names.
Source code in geoagent/core/registry.py
def list_names(self) -> list[str]:
"""Return registered tool names."""
return sorted(self._by_name.keys())
needs_user_confirmation(self, meta)
¶
Return True if the tool should go through the confirm callback.
Source code in geoagent/core/registry.py
def needs_user_confirmation(self, meta: GeoToolMeta) -> bool:
"""Return True if the tool should go through the confirm callback."""
return bool(meta.requires_confirmation or meta.destructive or meta.long_running)
register(self, meta)
¶
Register metadata by explicit name.
Source code in geoagent/core/registry.py
def register(self, meta: GeoToolMeta) -> None:
"""Register metadata by explicit name."""
self._by_name[meta.name] = meta
register_tool(self, tool_obj, meta)
¶
Register metadata for a Strands decorated tool.
Source code in geoagent/core/registry.py
def register_tool(self, tool_obj: Any, meta: GeoToolMeta) -> None:
"""Register metadata for a Strands decorated tool."""
name = getattr(tool_obj, "tool_name", None) or meta.name
self._by_name[str(name)] = meta
collect_tools_for_context(tool_objects, *, fast, registry)
¶
Filter tools for fast mode using metadata or :data:FAST_TOOL_FALLBACK.
Source code in geoagent/core/registry.py
def collect_tools_for_context(
tool_objects: Sequence[Any],
*,
fast: bool,
registry: GeoToolRegistry,
) -> list[Any]:
"""Filter tools for fast mode using metadata or :data:`FAST_TOOL_FALLBACK`."""
if not fast:
return list(tool_objects)
out: list[Any] = []
for t in tool_objects:
name = getattr(t, "tool_name", None)
if name is None:
continue
meta = registry.get(str(name))
if meta is not None and "fast" in meta.available_in:
out.append(t)
continue
if str(name) in FAST_TOOL_FALLBACK:
out.append(t)
return out
packages_available(requires)
¶
Return True if every named package is importable.
Source code in geoagent/core/registry.py
def packages_available(requires: Iterable[str]) -> bool:
"""Return True if every named package is importable."""
for pkg in requires:
try:
__import__(pkg)
except ImportError:
return False
return True