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

1"""@tool decorator — converts async functions into agent tools.""" 

2 

3from __future__ import annotations 

4 

5import inspect 

6from typing import Any, Callable 

7 

8from lexigram.ai.agents.tools.schema import generate_json_schema 

9 

10 

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. 

18 

19 Automatically generates JSON schema from type hints for LLM 

20 function calling. 

21 

22 Usage:: 

23 

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) 

28 

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 """ 

37 

38 def decorator(fn: Callable) -> FunctionTool: 

39 tool_name = name or fn.__name__ 

40 tool_description = description or inspect.getdoc(fn) or "" 

41 

42 # Extract first line of docstring as description 

43 if "\n" in tool_description: 

44 tool_description = tool_description.split("\n")[0].strip() 

45 

46 # Generate JSON schema from type hints + Google-style docstring 

47 schema = generate_json_schema(fn) 

48 

49 return FunctionTool( 

50 fn=fn, 

51 tool_name=tool_name, 

52 tool_description=tool_description, 

53 schema=schema, 

54 ) 

55 

56 if func is not None: 

57 return decorator(func) 

58 return decorator 

59 

60 

61class FunctionTool: 

62 """Tool wrapping an async function with auto-generated schema.""" 

63 

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 

75 

76 @property 

77 def name(self) -> str: 

78 return self._name 

79 

80 @property 

81 def description(self) -> str: 

82 return self._description 

83 

84 @property 

85 def parameters_schema(self) -> dict[str, Any]: 

86 return self._schema 

87 

88 async def execute(self, **kwargs: Any) -> Any: 

89 return await self._fn(**kwargs) 

90 

91 def __repr__(self) -> str: 

92 return f"FunctionTool({self._name})"