Skip to content

Decorators

The @geo_tool decorator wraps LangChain's @tool to stamp GeoAgent metadata (category, confirmation requirement, required Python packages, context keys) onto each tool. The metadata is read by the registry and the safety / confirmation bridge.

geoagent.core.decorators

@geo_tool — Strands :func:strands.tool plus GeoAgent metadata.

geo_tool(*, category='general', name=None, description=None, requires_confirmation=False, destructive=False, long_running=False, available_in=('full',), requires_packages=())

Decorate a function as a Strands tool with GeoAgent metadata.

The returned object is a Strands DecoratedFunctionTool. Metadata is stored on tool._geoagent_meta as :class:GeoToolMeta.

Parameters:

Name Type Description Default
category str

Logical group (map, qgis, data, ...).

'general'
name str | None

Optional override for tool name (forwarded via @tool(name=...)).

None
description str | None

Optional override; otherwise the docstring is used.

None
requires_confirmation bool

If True, host must approve via callback.

False
destructive bool

Implies confirmation when True.

False
long_running bool

Marks expensive jobs (typically confirmation-required).

False
available_in Iterable[str]

Include "fast" for tools exposed in fast mode.

('full',)
requires_packages Iterable[str]

Skip registering tools when imports fail upstream.

()
Source code in geoagent/core/decorators.py
def geo_tool(
    *,
    category: str = "general",
    name: str | None = None,
    description: str | None = None,
    requires_confirmation: bool = False,
    destructive: bool = False,
    long_running: bool = False,
    available_in: Iterable[str] = ("full",),
    requires_packages: Iterable[str] = (),
) -> Callable[[F], Any]:
    """Decorate a function as a Strands tool with GeoAgent metadata.

    The returned object is a Strands ``DecoratedFunctionTool``. Metadata is
    stored on ``tool._geoagent_meta`` as :class:`GeoToolMeta`.

    Args:
        category: Logical group (``map``, ``qgis``, ``data``, ...).
        name: Optional override for tool name (forwarded via ``@tool(name=...)``).
        description: Optional override; otherwise the docstring is used.
        requires_confirmation: If True, host must approve via callback.
        destructive: Implies confirmation when True.
        long_running: Marks expensive jobs (typically confirmation-required).
        available_in: Include ``\"fast\"`` for tools exposed in fast mode.
        requires_packages: Skip registering tools when imports fail upstream.
    """

    def deco(fn: F) -> Any:
        """Attach GeoAgent metadata to the decorated function."""
        kwargs: dict[str, Any] = {}
        if name is not None:
            kwargs["name"] = name
        if description is not None:
            kwargs["description"] = description

        base = strands_tool(**kwargs)(fn)

        meta = GeoToolMeta(
            name=str(base.tool_name),
            description=description or (fn.__doc__ or "").strip(),
            category=category,
            requires_confirmation=requires_confirmation or destructive,
            destructive=destructive,
            long_running=long_running,
            available_in=tuple(available_in),
            requires_packages=tuple(requires_packages),
        )
        setattr(base, "_geoagent_meta", meta)
        return base

    return deco

get_geo_meta(tool_obj)

Return GeoAgent metadata as a plain dict for callbacks / UIs.

Source code in geoagent/core/decorators.py
def get_geo_meta(tool_obj: Any) -> dict[str, Any]:
    """Return GeoAgent metadata as a plain dict for callbacks / UIs."""
    meta: GeoToolMeta | None = getattr(tool_obj, "_geoagent_meta", None)
    if meta is None:
        return {}
    return {
        "category": meta.category,
        "requires_confirmation": meta.requires_confirmation,
        "destructive": meta.destructive,
        "long_running": meta.long_running,
        "available_in": meta.available_in,
        "requires_packages": meta.requires_packages,
        **meta.extra,
    }

needs_confirmation(tool_obj)

Return True if tool should use the confirmation callback.

Source code in geoagent/core/decorators.py
def needs_confirmation(tool_obj: Any) -> bool:
    """Return True if tool should use the confirmation callback."""
    meta: GeoToolMeta | None = getattr(tool_obj, "_geoagent_meta", None)
    if meta is None:
        return False
    return bool(meta.requires_confirmation or meta.destructive or meta.long_running)

stamp_geo_meta(tool_obj, **fields)

Attach or merge :class:GeoToolMeta fields on a Strands tool.

Source code in geoagent/core/decorators.py
def stamp_geo_meta(tool_obj: Any, **fields: Any) -> Any:
    """Attach or merge :class:`GeoToolMeta` fields on a Strands tool."""
    meta: GeoToolMeta | None = getattr(tool_obj, "_geoagent_meta", None)
    if meta is None:
        name = getattr(tool_obj, "tool_name", "unknown")
        meta = GeoToolMeta(name=str(name))
    for k, v in fields.items():
        if hasattr(meta, k):
            setattr(meta, k, v)
    setattr(tool_obj, "_geoagent_meta", meta)
    return tool_obj