Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-agents/src/lexigram/ai/agents/tools/decorator.py: 44%
34 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""@tool decorator — converts async functions into agent tools."""
3from __future__ import annotations
5import inspect
6from typing import Any, Callable
8from lexigram.ai.agents.tools.schema import generate_json_schema
11def tool(
12 func: Callable | None = None,
13 *,
14 name: str | None = None,
15 description: str | None = None,
16) -> Any:
17 """Decorator that converts an async function into an agent tool.
19 Automatically generates JSON schema from type hints for LLM
20 function calling.
22 Usage::
24 @tool
25 async def lookup_order(order_id: str) -> dict:
26 \"\"\"Look up an order by its ID.\"\"\"
27 return await order_service.find(order_id)
29 @tool(name="search", description="Search local services")
30 async def search_services(
31 query: str,
32 category: str | None = None,
33 radius_km: float = 5.0,
34 ) -> list[dict]:
35 return await search.find(query, category, radius_km)
36 """
38 def decorator(fn: Callable) -> FunctionTool:
39 tool_name = name or fn.__name__
40 tool_description = description or inspect.getdoc(fn) or ""
42 # Extract first line of docstring as description
43 if "\n" in tool_description:
44 tool_description = tool_description.split("\n")[0].strip()
46 # Generate JSON schema from type hints + Google-style docstring
47 schema = generate_json_schema(fn)
49 return FunctionTool(
50 fn=fn,
51 tool_name=tool_name,
52 tool_description=tool_description,
53 schema=schema,
54 )
56 if func is not None:
57 return decorator(func)
58 return decorator
61class FunctionTool:
62 """Tool wrapping an async function with auto-generated schema."""
64 def __init__(
65 self,
66 fn: Callable,
67 tool_name: str,
68 tool_description: str,
69 schema: dict[str, Any],
70 ) -> None:
71 self._fn = fn
72 self._name = tool_name
73 self._description = tool_description
74 self._schema = schema
76 @property
77 def name(self) -> str:
78 return self._name
80 @property
81 def description(self) -> str:
82 return self._description
84 @property
85 def parameters_schema(self) -> dict[str, Any]:
86 return self._schema
88 async def execute(self, **kwargs: Any) -> Any:
89 return await self._fn(**kwargs)
91 def __repr__(self) -> str:
92 return f"FunctionTool({self._name})"