pygeai-orchestration 0.1.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. pygeai_orchestration/__init__.py +99 -0
  2. pygeai_orchestration/cli/__init__.py +7 -0
  3. pygeai_orchestration/cli/__main__.py +11 -0
  4. pygeai_orchestration/cli/commands/__init__.py +13 -0
  5. pygeai_orchestration/cli/commands/base.py +192 -0
  6. pygeai_orchestration/cli/error_handler.py +123 -0
  7. pygeai_orchestration/cli/formatters.py +419 -0
  8. pygeai_orchestration/cli/geai_orch.py +270 -0
  9. pygeai_orchestration/cli/interactive.py +265 -0
  10. pygeai_orchestration/cli/texts/help.py +169 -0
  11. pygeai_orchestration/core/__init__.py +130 -0
  12. pygeai_orchestration/core/base/__init__.py +23 -0
  13. pygeai_orchestration/core/base/agent.py +121 -0
  14. pygeai_orchestration/core/base/geai_agent.py +144 -0
  15. pygeai_orchestration/core/base/geai_orchestrator.py +77 -0
  16. pygeai_orchestration/core/base/orchestrator.py +142 -0
  17. pygeai_orchestration/core/base/pattern.py +161 -0
  18. pygeai_orchestration/core/base/tool.py +149 -0
  19. pygeai_orchestration/core/common/__init__.py +18 -0
  20. pygeai_orchestration/core/common/context.py +140 -0
  21. pygeai_orchestration/core/common/memory.py +176 -0
  22. pygeai_orchestration/core/common/message.py +50 -0
  23. pygeai_orchestration/core/common/state.py +181 -0
  24. pygeai_orchestration/core/composition.py +190 -0
  25. pygeai_orchestration/core/config.py +356 -0
  26. pygeai_orchestration/core/exceptions.py +400 -0
  27. pygeai_orchestration/core/handlers.py +380 -0
  28. pygeai_orchestration/core/utils/__init__.py +37 -0
  29. pygeai_orchestration/core/utils/cache.py +138 -0
  30. pygeai_orchestration/core/utils/config.py +94 -0
  31. pygeai_orchestration/core/utils/logging.py +57 -0
  32. pygeai_orchestration/core/utils/metrics.py +184 -0
  33. pygeai_orchestration/core/utils/validators.py +140 -0
  34. pygeai_orchestration/dev/__init__.py +15 -0
  35. pygeai_orchestration/dev/debug.py +288 -0
  36. pygeai_orchestration/dev/templates.py +321 -0
  37. pygeai_orchestration/dev/testing.py +301 -0
  38. pygeai_orchestration/patterns/__init__.py +15 -0
  39. pygeai_orchestration/patterns/multi_agent.py +237 -0
  40. pygeai_orchestration/patterns/planning.py +219 -0
  41. pygeai_orchestration/patterns/react.py +221 -0
  42. pygeai_orchestration/patterns/reflection.py +134 -0
  43. pygeai_orchestration/patterns/tool_use.py +170 -0
  44. pygeai_orchestration/tests/__init__.py +1 -0
  45. pygeai_orchestration/tests/test_base_classes.py +187 -0
  46. pygeai_orchestration/tests/test_cache.py +184 -0
  47. pygeai_orchestration/tests/test_cli_formatters.py +232 -0
  48. pygeai_orchestration/tests/test_common.py +214 -0
  49. pygeai_orchestration/tests/test_composition.py +265 -0
  50. pygeai_orchestration/tests/test_config.py +301 -0
  51. pygeai_orchestration/tests/test_dev_utils.py +337 -0
  52. pygeai_orchestration/tests/test_exceptions.py +327 -0
  53. pygeai_orchestration/tests/test_handlers.py +307 -0
  54. pygeai_orchestration/tests/test_metrics.py +171 -0
  55. pygeai_orchestration/tests/test_patterns.py +165 -0
  56. pygeai_orchestration-0.1.0b2.dist-info/METADATA +290 -0
  57. pygeai_orchestration-0.1.0b2.dist-info/RECORD +61 -0
  58. pygeai_orchestration-0.1.0b2.dist-info/WHEEL +5 -0
  59. pygeai_orchestration-0.1.0b2.dist-info/entry_points.txt +2 -0
  60. pygeai_orchestration-0.1.0b2.dist-info/licenses/LICENSE +8 -0
  61. pygeai_orchestration-0.1.0b2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,144 @@
1
+ """
2
+ PyGEAI-based agent implementation.
3
+
4
+ This module provides a concrete agent implementation using the PyGEAI SDK,
5
+ enabling AI-powered task execution with GeneXus Enterprise AI.
6
+ """
7
+
8
+ from typing import Any, Dict, Optional
9
+ from .agent import BaseAgent, AgentConfig
10
+ from ..utils import get_logger
11
+
12
+ logger = get_logger()
13
+
14
+ try:
15
+ from pygeai import Session
16
+
17
+ PYGEAI_AVAILABLE = True
18
+ except ImportError:
19
+ PYGEAI_AVAILABLE = False
20
+ logger.warning("PyGEAI not available. GEAIAgent will have limited functionality.")
21
+
22
+
23
+ class GEAIAgent(BaseAgent):
24
+ """
25
+ Agent implementation using PyGEAI SDK.
26
+
27
+ This agent leverages the PyGEAI SDK to execute tasks using GeneXus
28
+ Enterprise AI models, providing AI-powered reasoning and generation.
29
+
30
+ The agent:
31
+ - Integrates with PyGEAI Session and Agent resources
32
+ - Supports custom system prompts and model configuration
33
+ - Automatically manages agent resource creation
34
+ - Maintains execution history
35
+ """
36
+
37
+ def __init__(self, config: AgentConfig, session=None, alias: Optional[str] = None):
38
+ """
39
+ Initialize the GEAI agent with PyGEAI session.
40
+
41
+ :param config: AgentConfig - Agent configuration.
42
+ :param session: Optional PyGEAI Session - Existing session to use.
43
+ :param alias: Optional[str] - Session alias if creating new session.
44
+ :raises ImportError: If PyGEAI is not installed.
45
+ """
46
+ super().__init__(config)
47
+ if not PYGEAI_AVAILABLE:
48
+ raise ImportError("PyGEAI is required for GEAIAgent but is not installed")
49
+ self._session = session or Session(alias=alias)
50
+ self._agent_resource = None
51
+
52
+ async def execute(self, task: str, context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
53
+ """
54
+ Execute a task using PyGEAI generation.
55
+
56
+ :param task: str - Task description or instruction.
57
+ :param context: Optional[Dict[str, Any]] - Execution context.
58
+ :return: Dict[str, Any] - Execution result with success status and output.
59
+ """
60
+ logger.debug(f"GEAIAgent '{self.name}' executing task")
61
+
62
+ try:
63
+ result = await self.generate(task, context=context)
64
+
65
+ execution_result = {
66
+ "success": True,
67
+ "result": result,
68
+ "agent": self.name,
69
+ "metadata": context or {},
70
+ }
71
+
72
+ self.add_to_history(execution_result)
73
+ return execution_result
74
+
75
+ except Exception as e:
76
+ logger.error(f"GEAIAgent execution failed: {str(e)}")
77
+ error_result = {"success": False, "result": None, "error": str(e), "agent": self.name}
78
+ self.add_to_history(error_result)
79
+ return error_result
80
+
81
+ async def generate(self, prompt: str, **kwargs) -> str:
82
+ """
83
+ Generate a response using PyGEAI chat completion.
84
+
85
+ :param prompt: str - Input prompt for generation.
86
+ :param kwargs: Additional generation parameters (messages, etc.).
87
+ :return: str - Generated text response.
88
+ :raises Exception: If generation fails.
89
+ """
90
+ try:
91
+ self._get_or_create_agent()
92
+
93
+ messages = kwargs.get("messages", [])
94
+ if not messages:
95
+ messages = [{"role": "user", "content": prompt}]
96
+
97
+ if self.config.system_prompt:
98
+ messages.insert(0, {"role": "system", "content": self.config.system_prompt})
99
+
100
+ chat = self._session.chats.create(
101
+ messages=messages,
102
+ model=self.config.model,
103
+ temperature=self.config.temperature,
104
+ max_tokens=self.config.max_tokens,
105
+ )
106
+
107
+ response = chat.choices[0].message.content
108
+
109
+ self.add_to_history({"type": "generation", "prompt": prompt, "response": response})
110
+
111
+ return response
112
+
113
+ except Exception as e:
114
+ logger.error(f"Generation failed: {str(e)}")
115
+ raise
116
+
117
+ def _get_or_create_agent(self):
118
+ """
119
+ Get or create PyGEAI agent resource.
120
+
121
+ Lazily creates an agent resource in PyGEAI if not already created,
122
+ or reuses existing agent with matching name.
123
+
124
+ :return: PyGEAI Agent resource.
125
+ """
126
+ if self._agent_resource is None:
127
+ try:
128
+ agents = self._session.agents.list()
129
+ for agent in agents.data:
130
+ if agent.name == self.name:
131
+ self._agent_resource = agent
132
+ break
133
+
134
+ if self._agent_resource is None:
135
+ logger.debug(f"Creating new agent resource: {self.name}")
136
+ self._agent_resource = self._session.agents.create(
137
+ name=self.name,
138
+ model=self.config.model,
139
+ description=self.config.description or f"Orchestration agent: {self.name}",
140
+ )
141
+ except Exception as e:
142
+ logger.warning(f"Could not create agent resource: {str(e)}")
143
+
144
+ return self._agent_resource
@@ -0,0 +1,77 @@
1
+ from typing import Any, Dict, List, Optional
2
+ from .orchestrator import BaseOrchestrator, OrchestratorConfig
3
+ from .pattern import PatternResult
4
+ from ..utils import get_logger
5
+
6
+ logger = get_logger()
7
+
8
+
9
+ class GEAIOrchestrator(BaseOrchestrator):
10
+ def __init__(self, config: OrchestratorConfig):
11
+ super().__init__(config)
12
+ self._execution_history: List[Dict[str, Any]] = []
13
+
14
+ async def orchestrate(
15
+ self, task: str, pattern: str, context: Optional[Dict[str, Any]] = None
16
+ ) -> PatternResult:
17
+ logger.info(f"Orchestrating task with pattern '{pattern}': {task[:50]}...")
18
+
19
+ pattern_instance = self.get_pattern(pattern)
20
+ if pattern_instance is None:
21
+ error_msg = f"Pattern '{pattern}' not found. Available: {self.list_patterns()}"
22
+ logger.error(error_msg)
23
+ return PatternResult(success=False, result=None, iterations=0, error=error_msg)
24
+
25
+ try:
26
+ result = await pattern_instance.execute(task, context)
27
+
28
+ self._execution_history.append(
29
+ {
30
+ "task": task,
31
+ "pattern": pattern,
32
+ "success": result.success,
33
+ "iterations": result.iterations,
34
+ "result": result.result,
35
+ }
36
+ )
37
+
38
+ logger.info(
39
+ f"Orchestration {'succeeded' if result.success else 'failed'} "
40
+ f"after {result.iterations} iterations"
41
+ )
42
+
43
+ return result
44
+
45
+ except Exception as e:
46
+ logger.error(f"Orchestration error: {str(e)}")
47
+ return PatternResult(success=False, result=None, iterations=0, error=str(e))
48
+
49
+ async def coordinate_agents(self, agents: List[str], task: str) -> Dict[str, Any]:
50
+ logger.info(f"Coordinating {len(agents)} agents for task: {task[:50]}...")
51
+
52
+ results = {}
53
+
54
+ for agent_name in agents:
55
+ agent = self.get_agent(agent_name)
56
+ if agent is None:
57
+ logger.warning(f"Agent '{agent_name}' not found, skipping")
58
+ continue
59
+
60
+ try:
61
+ result = await agent.execute(task)
62
+ results[agent_name] = result
63
+ except Exception as e:
64
+ logger.error(f"Agent '{agent_name}' failed: {str(e)}")
65
+ results[agent_name] = {"success": False, "error": str(e)}
66
+
67
+ return {
68
+ "success": len(results) > 0,
69
+ "results": results,
70
+ "agents_executed": list(results.keys()),
71
+ }
72
+
73
+ def get_execution_history(self) -> List[Dict[str, Any]]:
74
+ return self._execution_history.copy()
75
+
76
+ def clear_history(self) -> None:
77
+ self._execution_history.clear()
@@ -0,0 +1,142 @@
1
+ """
2
+ Orchestrator base classes for managing agents and patterns.
3
+
4
+ This module provides the foundation for orchestrating multiple agents
5
+ and patterns, including registration, coordination, and task delegation.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import Any, Dict, List, Optional
10
+ from pydantic import BaseModel, Field
11
+
12
+ from .agent import BaseAgent
13
+ from .pattern import BasePattern, PatternResult
14
+
15
+
16
+ class OrchestratorConfig(BaseModel):
17
+ """
18
+ Configuration model for orchestrators.
19
+
20
+ This Pydantic model defines orchestrator behavior including
21
+ concurrency limits, timeouts, and retry policies.
22
+
23
+ :param name: str - Unique identifier for the orchestrator.
24
+ :param max_concurrent_tasks: int - Maximum number of tasks to run concurrently.
25
+ :param timeout: Optional[float] - Global timeout in seconds. None means no timeout.
26
+ :param retry_attempts: int - Number of retry attempts on task failure.
27
+ :param metadata: Dict[str, Any] - Custom metadata for orchestrator configuration.
28
+ """
29
+
30
+ name: str = Field(..., description="Orchestrator name")
31
+ max_concurrent_tasks: int = Field(5, ge=1, description="Max concurrent tasks")
32
+ timeout: Optional[float] = Field(None, ge=0.0, description="Global timeout in seconds")
33
+ retry_attempts: int = Field(3, ge=0, description="Number of retry attempts on failure")
34
+ metadata: Dict[str, Any] = Field(default_factory=dict)
35
+
36
+
37
+ class BaseOrchestrator(ABC):
38
+ """
39
+ Abstract base class for orchestrator implementations.
40
+
41
+ This class defines the interface for orchestrating multiple agents
42
+ and patterns, enabling complex multi-agent workflows and pattern chaining.
43
+
44
+ Orchestrators manage:
45
+ - Agent registration and retrieval
46
+ - Pattern registration and selection
47
+ - Task delegation and coordination
48
+ - Multi-agent collaboration
49
+
50
+ Subclasses must implement:
51
+ - orchestrate(): Execute a task using a specific pattern
52
+ - coordinate_agents(): Coordinate multiple agents on a task
53
+ """
54
+
55
+ def __init__(self, config: OrchestratorConfig):
56
+ """
57
+ Initialize the orchestrator with configuration.
58
+
59
+ :param config: OrchestratorConfig - Configuration for this orchestrator.
60
+ """
61
+ self.config = config
62
+ self.name = config.name
63
+ self._agents: Dict[str, BaseAgent] = {}
64
+ self._patterns: Dict[str, BasePattern] = {}
65
+
66
+ def register_agent(self, agent: BaseAgent) -> None:
67
+ """
68
+ Register an agent with this orchestrator.
69
+
70
+ :param agent: BaseAgent - Agent to register.
71
+ """
72
+ self._agents[agent.name] = agent
73
+
74
+ def register_pattern(self, pattern: BasePattern) -> None:
75
+ """
76
+ Register a pattern with this orchestrator.
77
+
78
+ :param pattern: BasePattern - Pattern to register.
79
+ """
80
+ self._patterns[pattern.name] = pattern
81
+
82
+ def get_agent(self, name: str) -> Optional[BaseAgent]:
83
+ """
84
+ Retrieve a registered agent by name.
85
+
86
+ :param name: str - Agent name.
87
+ :return: Optional[BaseAgent] - The agent if found, None otherwise.
88
+ """
89
+ return self._agents.get(name)
90
+
91
+ def get_pattern(self, name: str) -> Optional[BasePattern]:
92
+ """
93
+ Retrieve a registered pattern by name.
94
+
95
+ :param name: str - Pattern name.
96
+ :return: Optional[BasePattern] - The pattern if found, None otherwise.
97
+ """
98
+ return self._patterns.get(name)
99
+
100
+ def list_agents(self) -> List[str]:
101
+ """
102
+ List all registered agent names.
103
+
104
+ :return: List[str] - Agent names.
105
+ """
106
+ return list(self._agents.keys())
107
+
108
+ def list_patterns(self) -> List[str]:
109
+ """
110
+ List all registered pattern names.
111
+
112
+ :return: List[str] - Pattern names.
113
+ """
114
+ return list(self._patterns.keys())
115
+
116
+ @abstractmethod
117
+ async def orchestrate(
118
+ self, task: str, pattern: str, context: Optional[Dict[str, Any]] = None
119
+ ) -> PatternResult:
120
+ """
121
+ Execute a task using a specified pattern.
122
+
123
+ :param task: str - Task description or instruction.
124
+ :param pattern: str - Name of the pattern to use.
125
+ :param context: Optional[Dict[str, Any]] - Execution context.
126
+ :return: PatternResult - Execution result.
127
+ """
128
+ pass
129
+
130
+ @abstractmethod
131
+ async def coordinate_agents(self, agents: List[str], task: str) -> Dict[str, Any]:
132
+ """
133
+ Coordinate multiple agents to complete a task.
134
+
135
+ :param agents: List[str] - Names of agents to coordinate.
136
+ :param task: str - Task description or instruction.
137
+ :return: Dict[str, Any] - Coordination results.
138
+ """
139
+ pass
140
+
141
+ def __repr__(self) -> str:
142
+ return f"<{self.__class__.__name__}(name='{self.name}', agents={len(self._agents)}, patterns={len(self._patterns)})>"
@@ -0,0 +1,161 @@
1
+ """
2
+ Base pattern definitions for orchestration patterns.
3
+
4
+ This module provides the foundation classes for all orchestration patterns,
5
+ including configuration, results, and the abstract base pattern interface.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import Any, Dict, Optional
10
+ from pydantic import BaseModel, Field
11
+ from enum import Enum
12
+
13
+
14
+ class PatternType(str, Enum):
15
+ """
16
+ Enumeration of available orchestration pattern types.
17
+
18
+ Each pattern type represents a distinct approach to agentic AI orchestration:
19
+ - REFLECTION: Iterative self-critique and refinement
20
+ - TOOL_USE: External tool integration and execution
21
+ - REACT: Reasoning and acting with thought traces
22
+ - PLANNING: Task decomposition and sequential execution
23
+ - MULTI_AGENT: Collaborative multi-agent problem solving
24
+ """
25
+
26
+ REFLECTION = "reflection"
27
+ TOOL_USE = "tool_use"
28
+ REACT = "react"
29
+ PLANNING = "planning"
30
+ MULTI_AGENT = "multi_agent"
31
+
32
+
33
+ class PatternConfig(BaseModel):
34
+ """
35
+ Configuration model for orchestration patterns.
36
+
37
+ This Pydantic model defines the configuration parameters that control
38
+ pattern execution behavior, including iteration limits, timeouts, and
39
+ custom metadata.
40
+
41
+ :param name: str - Unique identifier for the pattern instance.
42
+ :param pattern_type: PatternType - The type of orchestration pattern.
43
+ :param max_iterations: int - Maximum number of iterations allowed (minimum 1).
44
+ :param timeout: Optional[float] - Execution timeout in seconds. None means no timeout.
45
+ :param verbose: bool - Enable detailed logging output. Defaults to False.
46
+ :param metadata: Dict[str, Any] - Custom metadata for pattern-specific configuration.
47
+ """
48
+
49
+ name: str = Field(..., description="Pattern name")
50
+ pattern_type: PatternType = Field(..., description="Type of orchestration pattern")
51
+ max_iterations: int = Field(10, ge=1, description="Maximum iterations")
52
+ timeout: Optional[float] = Field(None, ge=0.0, description="Timeout in seconds")
53
+ verbose: bool = Field(False, description="Enable verbose output")
54
+ metadata: Dict[str, Any] = Field(default_factory=dict)
55
+
56
+
57
+ class PatternResult(BaseModel):
58
+ """
59
+ Result model for pattern execution outcomes.
60
+
61
+ This Pydantic model encapsulates the results of pattern execution,
62
+ including success status, output data, iteration count, errors, and
63
+ execution metadata.
64
+
65
+ :param success: bool - Whether the pattern execution succeeded.
66
+ :param result: Any - The final output or answer from pattern execution.
67
+ :param iterations: int - Number of iterations executed (minimum 0).
68
+ :param error: Optional[str] - Error message if execution failed. None on success.
69
+ :param metadata: Dict[str, Any] - Additional execution metadata (e.g., intermediate results, timing).
70
+ """
71
+
72
+ success: bool = Field(..., description="Whether pattern execution succeeded")
73
+ result: Any = Field(None, description="Pattern execution result")
74
+ iterations: int = Field(0, ge=0, description="Number of iterations executed")
75
+ error: Optional[str] = Field(None, description="Error message if failed")
76
+ metadata: Dict[str, Any] = Field(default_factory=dict)
77
+
78
+
79
+ class BasePattern(ABC):
80
+ """
81
+ Abstract base class for all orchestration patterns.
82
+
83
+ This class defines the interface that all orchestration patterns must implement,
84
+ including the core execute() and step() methods. It provides common functionality
85
+ for iteration tracking and state management.
86
+
87
+ Subclasses must implement:
88
+ - execute(): Main entry point for pattern execution
89
+ - step(): Single iteration/step logic
90
+
91
+ The base class handles iteration counting and provides lifecycle hooks for
92
+ pattern initialization and reset.
93
+ """
94
+
95
+ def __init__(self, config: PatternConfig):
96
+ """
97
+ Initialize the base pattern with configuration.
98
+
99
+ :param config: PatternConfig - Configuration for this pattern instance.
100
+ """
101
+ self.config = config
102
+ self.name = config.name
103
+ self.pattern_type = config.pattern_type
104
+ self._iteration_count = 0
105
+
106
+ @abstractmethod
107
+ async def execute(self, task: str, context: Optional[Dict[str, Any]] = None) -> PatternResult:
108
+ """
109
+ Execute the orchestration pattern on the given task.
110
+
111
+ This is the main entry point for pattern execution. Subclasses must
112
+ implement this method to define their specific orchestration logic.
113
+
114
+ :param task: str - The task or question to execute.
115
+ :param context: Optional[Dict[str, Any]] - Additional context for execution.
116
+ :return: PatternResult - Execution results including success status and output.
117
+ """
118
+ pass
119
+
120
+ @abstractmethod
121
+ async def step(self, state: Dict[str, Any]) -> Dict[str, Any]:
122
+ """
123
+ Execute a single iteration step of the pattern.
124
+
125
+ This method defines the logic for one iteration of the pattern's execution
126
+ loop. Subclasses implement this to define step-level behavior.
127
+
128
+ :param state: Dict[str, Any] - Current state including iteration count, history, etc.
129
+ :return: Dict[str, Any] - Step results and updated state information.
130
+ """
131
+ pass
132
+
133
+ def reset(self) -> None:
134
+ """
135
+ Reset the pattern state for a new execution.
136
+
137
+ Clears iteration count and any other stateful information to prepare
138
+ for a fresh pattern execution.
139
+ """
140
+ self._iteration_count = 0
141
+
142
+ def increment_iteration(self) -> int:
143
+ """
144
+ Increment the iteration counter and return the new count.
145
+
146
+ :return: int - The new iteration count after incrementing.
147
+ """
148
+ self._iteration_count += 1
149
+ return self._iteration_count
150
+
151
+ @property
152
+ def current_iteration(self) -> int:
153
+ """
154
+ Get the current iteration count.
155
+
156
+ :return: int - Current iteration number (0-indexed).
157
+ """
158
+ return self._iteration_count
159
+
160
+ def __repr__(self) -> str:
161
+ return f"<{self.__class__.__name__}(name='{self.name}', type='{self.pattern_type.value}')>"
@@ -0,0 +1,149 @@
1
+ """
2
+ Base tool definitions for orchestration tools.
3
+
4
+ This module provides the foundation classes for all tool implementations,
5
+ including configuration, results, and the abstract base tool interface.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import Any, Dict, Optional
10
+ from pydantic import BaseModel, Field
11
+ from enum import Enum
12
+
13
+
14
+ class ToolCategory(str, Enum):
15
+ """
16
+ Enumeration of tool categories.
17
+
18
+ Categories help organize and classify tools by their primary function:
19
+ - SEARCH: Web search, knowledge retrieval
20
+ - COMPUTATION: Calculators, data processing, algorithms
21
+ - DATA_ACCESS: Database queries, file access, API calls
22
+ - COMMUNICATION: Email, messaging, notifications
23
+ - CUSTOM: User-defined or specialized tools
24
+ """
25
+
26
+ SEARCH = "search"
27
+ COMPUTATION = "computation"
28
+ DATA_ACCESS = "data_access"
29
+ COMMUNICATION = "communication"
30
+ CUSTOM = "custom"
31
+
32
+
33
+ class ToolConfig(BaseModel):
34
+ """
35
+ Configuration model for tools.
36
+
37
+ This Pydantic model defines the configuration parameters for tool behavior,
38
+ including metadata, parameter schemas, and execution limits.
39
+
40
+ :param name: str - Unique identifier for the tool.
41
+ :param description: str - Human-readable description of tool functionality.
42
+ :param category: ToolCategory - Category classification for the tool.
43
+ :param parameters_schema: Dict[str, Any] - JSON schema for tool parameters.
44
+ :param timeout: Optional[float] - Execution timeout in seconds. None means no timeout.
45
+ :param metadata: Dict[str, Any] - Custom metadata for tool-specific configuration.
46
+ """
47
+
48
+ name: str = Field(..., description="Tool name")
49
+ description: str = Field(..., description="Tool description")
50
+ category: ToolCategory = Field(ToolCategory.CUSTOM, description="Tool category")
51
+ parameters_schema: Dict[str, Any] = Field(default_factory=dict)
52
+ timeout: Optional[float] = Field(None, ge=0.0, description="Tool execution timeout")
53
+ metadata: Dict[str, Any] = Field(default_factory=dict)
54
+
55
+
56
+ class ToolResult(BaseModel):
57
+ """
58
+ Result model for tool execution outcomes.
59
+
60
+ This Pydantic model encapsulates the results of tool execution,
61
+ including success status, output data, errors, and execution metrics.
62
+
63
+ :param success: bool - Whether the tool execution succeeded.
64
+ :param result: Any - The output data from tool execution.
65
+ :param error: Optional[str] - Error message if execution failed. None on success.
66
+ :param execution_time: Optional[float] - Time taken to execute in seconds.
67
+ :param metadata: Dict[str, Any] - Additional execution metadata.
68
+ """
69
+
70
+ success: bool = Field(..., description="Whether tool execution succeeded")
71
+ result: Any = Field(None, description="Tool execution result")
72
+ error: Optional[str] = Field(None, description="Error message if failed")
73
+ execution_time: Optional[float] = Field(None, description="Execution time in seconds")
74
+ metadata: Dict[str, Any] = Field(default_factory=dict)
75
+
76
+
77
+ class BaseTool(ABC):
78
+ """
79
+ Abstract base class for all tool implementations.
80
+
81
+ This class defines the interface that all tool implementations must provide,
82
+ including execution, parameter validation, and schema retrieval.
83
+
84
+ Tools extend agent capabilities by providing access to:
85
+ - External APIs and services
86
+ - Computational operations
87
+ - Data retrieval and manipulation
88
+ - Communication channels
89
+
90
+ Subclasses must implement:
91
+ - execute(): Perform the tool's primary function
92
+ - validate_parameters(): Validate input parameters before execution
93
+ """
94
+
95
+ def __init__(self, config: ToolConfig):
96
+ """
97
+ Initialize the base tool with configuration.
98
+
99
+ :param config: ToolConfig - Configuration for this tool instance.
100
+ """
101
+ self.config = config
102
+ self.name = config.name
103
+ self.description = config.description
104
+ self.category = config.category
105
+
106
+ @abstractmethod
107
+ async def execute(self, **kwargs) -> ToolResult:
108
+ """
109
+ Execute the tool with the given parameters.
110
+
111
+ This is the main entry point for tool execution. Subclasses implement
112
+ this method to define their specific functionality.
113
+
114
+ :param kwargs: Tool-specific parameters.
115
+ :return: ToolResult - Execution results including success status and output.
116
+ """
117
+ pass
118
+
119
+ @abstractmethod
120
+ def validate_parameters(self, parameters: Dict[str, Any]) -> bool:
121
+ """
122
+ Validate parameters before execution.
123
+
124
+ Subclasses implement this to check parameter correctness, types,
125
+ and required fields before attempting execution.
126
+
127
+ :param parameters: Dict[str, Any] - Parameters to validate.
128
+ :return: bool - True if valid, False otherwise.
129
+ """
130
+ pass
131
+
132
+ def get_schema(self) -> Dict[str, Any]:
133
+ """
134
+ Get the tool's schema definition.
135
+
136
+ Returns a structured representation of the tool including name,
137
+ description, category, and parameter schema for agent introspection.
138
+
139
+ :return: Dict[str, Any] - Tool schema with metadata and parameter definitions.
140
+ """
141
+ return {
142
+ "name": self.name,
143
+ "description": self.description,
144
+ "category": self.category.value,
145
+ "parameters": self.config.parameters_schema,
146
+ }
147
+
148
+ def __repr__(self) -> str:
149
+ return f"<{self.__class__.__name__}(name='{self.name}', category='{self.category.value}')>"
@@ -0,0 +1,18 @@
1
+ from .message import Message, MessageRole, Conversation
2
+ from .context import Context, ContextManager
3
+ from .state import State, StateStatus, StateManager
4
+ from .memory import Memory, MemoryEntry, MemoryStore
5
+
6
+ __all__ = [
7
+ "Message",
8
+ "MessageRole",
9
+ "Conversation",
10
+ "Context",
11
+ "ContextManager",
12
+ "State",
13
+ "StateStatus",
14
+ "StateManager",
15
+ "Memory",
16
+ "MemoryEntry",
17
+ "MemoryStore",
18
+ ]