signalwire-agents 0.1.13__py3-none-any.whl → 1.0.17.dev4__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 (143) hide show
  1. signalwire_agents/__init__.py +99 -15
  2. signalwire_agents/agent_server.py +248 -60
  3. signalwire_agents/agents/bedrock.py +296 -0
  4. signalwire_agents/cli/__init__.py +9 -0
  5. signalwire_agents/cli/build_search.py +951 -41
  6. signalwire_agents/cli/config.py +80 -0
  7. signalwire_agents/cli/core/__init__.py +10 -0
  8. signalwire_agents/cli/core/agent_loader.py +470 -0
  9. signalwire_agents/cli/core/argparse_helpers.py +179 -0
  10. signalwire_agents/cli/core/dynamic_config.py +71 -0
  11. signalwire_agents/cli/core/service_loader.py +303 -0
  12. signalwire_agents/cli/dokku.py +2320 -0
  13. signalwire_agents/cli/execution/__init__.py +10 -0
  14. signalwire_agents/cli/execution/datamap_exec.py +446 -0
  15. signalwire_agents/cli/execution/webhook_exec.py +134 -0
  16. signalwire_agents/cli/init_project.py +2636 -0
  17. signalwire_agents/cli/output/__init__.py +10 -0
  18. signalwire_agents/cli/output/output_formatter.py +255 -0
  19. signalwire_agents/cli/output/swml_dump.py +186 -0
  20. signalwire_agents/cli/simulation/__init__.py +10 -0
  21. signalwire_agents/cli/simulation/data_generation.py +374 -0
  22. signalwire_agents/cli/simulation/data_overrides.py +200 -0
  23. signalwire_agents/cli/simulation/mock_env.py +282 -0
  24. signalwire_agents/cli/swaig_test_wrapper.py +52 -0
  25. signalwire_agents/cli/test_swaig.py +566 -2366
  26. signalwire_agents/cli/types.py +81 -0
  27. signalwire_agents/core/__init__.py +2 -2
  28. signalwire_agents/core/agent/__init__.py +12 -0
  29. signalwire_agents/core/agent/config/__init__.py +12 -0
  30. signalwire_agents/core/agent/deployment/__init__.py +9 -0
  31. signalwire_agents/core/agent/deployment/handlers/__init__.py +9 -0
  32. signalwire_agents/core/agent/prompt/__init__.py +14 -0
  33. signalwire_agents/core/agent/prompt/manager.py +306 -0
  34. signalwire_agents/core/agent/routing/__init__.py +9 -0
  35. signalwire_agents/core/agent/security/__init__.py +9 -0
  36. signalwire_agents/core/agent/swml/__init__.py +9 -0
  37. signalwire_agents/core/agent/tools/__init__.py +15 -0
  38. signalwire_agents/core/agent/tools/decorator.py +97 -0
  39. signalwire_agents/core/agent/tools/registry.py +210 -0
  40. signalwire_agents/core/agent_base.py +845 -2916
  41. signalwire_agents/core/auth_handler.py +233 -0
  42. signalwire_agents/core/config_loader.py +259 -0
  43. signalwire_agents/core/contexts.py +418 -0
  44. signalwire_agents/core/data_map.py +3 -15
  45. signalwire_agents/core/function_result.py +116 -44
  46. signalwire_agents/core/logging_config.py +162 -18
  47. signalwire_agents/core/mixins/__init__.py +28 -0
  48. signalwire_agents/core/mixins/ai_config_mixin.py +442 -0
  49. signalwire_agents/core/mixins/auth_mixin.py +280 -0
  50. signalwire_agents/core/mixins/prompt_mixin.py +358 -0
  51. signalwire_agents/core/mixins/serverless_mixin.py +460 -0
  52. signalwire_agents/core/mixins/skill_mixin.py +55 -0
  53. signalwire_agents/core/mixins/state_mixin.py +153 -0
  54. signalwire_agents/core/mixins/tool_mixin.py +230 -0
  55. signalwire_agents/core/mixins/web_mixin.py +1142 -0
  56. signalwire_agents/core/security_config.py +333 -0
  57. signalwire_agents/core/skill_base.py +84 -1
  58. signalwire_agents/core/skill_manager.py +62 -20
  59. signalwire_agents/core/swaig_function.py +18 -5
  60. signalwire_agents/core/swml_builder.py +207 -11
  61. signalwire_agents/core/swml_handler.py +27 -21
  62. signalwire_agents/core/swml_renderer.py +123 -312
  63. signalwire_agents/core/swml_service.py +171 -203
  64. signalwire_agents/mcp_gateway/__init__.py +29 -0
  65. signalwire_agents/mcp_gateway/gateway_service.py +564 -0
  66. signalwire_agents/mcp_gateway/mcp_manager.py +513 -0
  67. signalwire_agents/mcp_gateway/session_manager.py +218 -0
  68. signalwire_agents/prefabs/concierge.py +0 -3
  69. signalwire_agents/prefabs/faq_bot.py +0 -3
  70. signalwire_agents/prefabs/info_gatherer.py +0 -3
  71. signalwire_agents/prefabs/receptionist.py +0 -3
  72. signalwire_agents/prefabs/survey.py +0 -3
  73. signalwire_agents/schema.json +9218 -5489
  74. signalwire_agents/search/__init__.py +7 -1
  75. signalwire_agents/search/document_processor.py +490 -31
  76. signalwire_agents/search/index_builder.py +307 -37
  77. signalwire_agents/search/migration.py +418 -0
  78. signalwire_agents/search/models.py +30 -0
  79. signalwire_agents/search/pgvector_backend.py +748 -0
  80. signalwire_agents/search/query_processor.py +162 -31
  81. signalwire_agents/search/search_engine.py +916 -35
  82. signalwire_agents/search/search_service.py +376 -53
  83. signalwire_agents/skills/README.md +452 -0
  84. signalwire_agents/skills/__init__.py +14 -2
  85. signalwire_agents/skills/api_ninjas_trivia/README.md +215 -0
  86. signalwire_agents/skills/api_ninjas_trivia/__init__.py +12 -0
  87. signalwire_agents/skills/api_ninjas_trivia/skill.py +237 -0
  88. signalwire_agents/skills/datasphere/README.md +210 -0
  89. signalwire_agents/skills/datasphere/skill.py +84 -3
  90. signalwire_agents/skills/datasphere_serverless/README.md +258 -0
  91. signalwire_agents/skills/datasphere_serverless/__init__.py +9 -0
  92. signalwire_agents/skills/datasphere_serverless/skill.py +82 -1
  93. signalwire_agents/skills/datetime/README.md +132 -0
  94. signalwire_agents/skills/datetime/__init__.py +9 -0
  95. signalwire_agents/skills/datetime/skill.py +20 -7
  96. signalwire_agents/skills/joke/README.md +149 -0
  97. signalwire_agents/skills/joke/__init__.py +9 -0
  98. signalwire_agents/skills/joke/skill.py +21 -0
  99. signalwire_agents/skills/math/README.md +161 -0
  100. signalwire_agents/skills/math/__init__.py +9 -0
  101. signalwire_agents/skills/math/skill.py +18 -4
  102. signalwire_agents/skills/mcp_gateway/README.md +230 -0
  103. signalwire_agents/skills/mcp_gateway/__init__.py +10 -0
  104. signalwire_agents/skills/mcp_gateway/skill.py +421 -0
  105. signalwire_agents/skills/native_vector_search/README.md +210 -0
  106. signalwire_agents/skills/native_vector_search/__init__.py +9 -0
  107. signalwire_agents/skills/native_vector_search/skill.py +569 -101
  108. signalwire_agents/skills/play_background_file/README.md +218 -0
  109. signalwire_agents/skills/play_background_file/__init__.py +12 -0
  110. signalwire_agents/skills/play_background_file/skill.py +242 -0
  111. signalwire_agents/skills/registry.py +395 -40
  112. signalwire_agents/skills/spider/README.md +236 -0
  113. signalwire_agents/skills/spider/__init__.py +13 -0
  114. signalwire_agents/skills/spider/skill.py +598 -0
  115. signalwire_agents/skills/swml_transfer/README.md +395 -0
  116. signalwire_agents/skills/swml_transfer/__init__.py +10 -0
  117. signalwire_agents/skills/swml_transfer/skill.py +359 -0
  118. signalwire_agents/skills/weather_api/README.md +178 -0
  119. signalwire_agents/skills/weather_api/__init__.py +12 -0
  120. signalwire_agents/skills/weather_api/skill.py +191 -0
  121. signalwire_agents/skills/web_search/README.md +163 -0
  122. signalwire_agents/skills/web_search/__init__.py +9 -0
  123. signalwire_agents/skills/web_search/skill.py +586 -112
  124. signalwire_agents/skills/wikipedia_search/README.md +228 -0
  125. signalwire_agents/{core/state → skills/wikipedia_search}/__init__.py +5 -4
  126. signalwire_agents/skills/{wikipedia → wikipedia_search}/skill.py +33 -3
  127. signalwire_agents/web/__init__.py +17 -0
  128. signalwire_agents/web/web_service.py +559 -0
  129. signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-agent-init.1 +400 -0
  130. signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-search.1 +483 -0
  131. signalwire_agents-1.0.17.dev4.data/data/share/man/man1/swaig-test.1 +308 -0
  132. {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/METADATA +347 -215
  133. signalwire_agents-1.0.17.dev4.dist-info/RECORD +147 -0
  134. signalwire_agents-1.0.17.dev4.dist-info/entry_points.txt +6 -0
  135. signalwire_agents/core/state/file_state_manager.py +0 -219
  136. signalwire_agents/core/state/state_manager.py +0 -101
  137. signalwire_agents/skills/wikipedia/__init__.py +0 -9
  138. signalwire_agents-0.1.13.data/data/schema.json +0 -5611
  139. signalwire_agents-0.1.13.dist-info/RECORD +0 -67
  140. signalwire_agents-0.1.13.dist-info/entry_points.txt +0 -3
  141. {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/WHEEL +0 -0
  142. {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/licenses/LICENSE +0 -0
  143. {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Copyright (c) 2025 SignalWire
4
+
5
+ This file is part of the SignalWire AI Agents SDK.
6
+
7
+ Licensed under the MIT License.
8
+ See LICENSE file in the project root for full license information.
9
+ """
10
+
11
+ """
12
+ Type definitions for the CLI tools
13
+ """
14
+
15
+ from typing import TypedDict, Dict, Any, Optional, List, Union
16
+
17
+
18
+ class CallData(TypedDict, total=False):
19
+ """Call data structure for SWML post_data"""
20
+ id: str
21
+ node_id: str
22
+ state: str
23
+ type: str
24
+ direction: str
25
+ project_id: str
26
+ space_id: str
27
+ from_number: str
28
+ to_number: str
29
+ from_: str
30
+ to: str
31
+ from_name: str
32
+ headers: Dict[str, str]
33
+ timeout: int
34
+ tag: str
35
+
36
+
37
+ class VarsData(TypedDict, total=False):
38
+ """Variables data structure for SWML post_data"""
39
+ userVariables: Dict[str, Any]
40
+ environment: str
41
+ call_data: Dict[str, Any]
42
+
43
+
44
+ class PostData(TypedDict, total=False):
45
+ """Complete post_data structure for SWML requests"""
46
+ call_id: str
47
+ call: CallData
48
+ vars: VarsData
49
+ params: Dict[str, Any]
50
+ project_id: str
51
+ space_id: str
52
+ meta_data: Dict[str, Any]
53
+ post_prompt_data: Dict[str, Any]
54
+ error: Optional[str]
55
+ protocol_error: Optional[bool]
56
+ parse_error: Optional[bool]
57
+
58
+
59
+ class DataMapConfig(TypedDict, total=False):
60
+ """DataMap function configuration"""
61
+ function: str
62
+ data_map: Dict[str, Any]
63
+ description: str
64
+ parameters: Dict[str, Any]
65
+
66
+
67
+ class AgentInfo(TypedDict):
68
+ """Information about a discovered agent"""
69
+ class_name: str
70
+ file_path: str
71
+ is_instance: bool
72
+ instance_name: Optional[str]
73
+
74
+
75
+ class FunctionInfo(TypedDict):
76
+ """Information about a SWAIG function"""
77
+ name: str
78
+ description: str
79
+ parameters: Dict[str, Any]
80
+ type: str # 'local', 'external', 'datamap'
81
+ webhook_url: Optional[str]
@@ -13,7 +13,7 @@ Core components for SignalWire AI Agents
13
13
 
14
14
  from signalwire_agents.core.agent_base import AgentBase
15
15
  from signalwire_agents.core.function_result import SwaigFunctionResult
16
- from signalwire_agents.core.swaig_function import SwaigFunction
16
+ from signalwire_agents.core.swaig_function import SWAIGFunction
17
17
  from signalwire_agents.core.swml_service import SWMLService
18
18
  from signalwire_agents.core.swml_handler import SWMLVerbHandler, VerbHandlerRegistry
19
19
  from signalwire_agents.core.swml_builder import SWMLBuilder
@@ -21,7 +21,7 @@ from signalwire_agents.core.swml_builder import SWMLBuilder
21
21
  __all__ = [
22
22
  'AgentBase',
23
23
  'SwaigFunctionResult',
24
- 'SwaigFunction',
24
+ 'SWAIGFunction',
25
25
  'SWMLService',
26
26
  'SWMLVerbHandler',
27
27
  'VerbHandlerRegistry',
@@ -0,0 +1,12 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ """Agent refactored components."""
11
+
12
+ __all__ = []
@@ -0,0 +1,12 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ """Configuration management modules."""
11
+
12
+ __all__ = []
@@ -0,0 +1,9 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
@@ -0,0 +1,9 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
@@ -0,0 +1,14 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ """Prompt management modules."""
11
+
12
+ from .manager import PromptManager
13
+
14
+ __all__ = ['PromptManager']
@@ -0,0 +1,306 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ """Prompt management functionality for AgentBase."""
11
+
12
+ from typing import Dict, Any, Optional, List, Union
13
+ import inspect
14
+ import logging
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class PromptManager:
20
+ """Manages prompt building and configuration."""
21
+
22
+ def __init__(self, agent):
23
+ """
24
+ Initialize PromptManager with reference to parent agent.
25
+
26
+ Args:
27
+ agent: Parent AgentBase instance
28
+ """
29
+ self.agent = agent
30
+ self._prompt_text = None
31
+ self._post_prompt_text = None
32
+ self._contexts = None
33
+
34
+ def _validate_prompt_mode_exclusivity(self):
35
+ """
36
+ Check that only one prompt mode is in use.
37
+
38
+ Raises:
39
+ ValueError: If both prompt modes are in use
40
+ """
41
+ if self._prompt_text and self.agent._use_pom and self.agent.pom:
42
+ pom_sections = self.agent.pom.to_dict() if hasattr(self.agent.pom, 'to_dict') else []
43
+ if pom_sections:
44
+ raise ValueError(
45
+ "Cannot use both prompt_text and POM sections. "
46
+ "Please use either set_prompt_text() OR the prompt_add_* methods, not both."
47
+ )
48
+
49
+ def _process_prompt_sections(self) -> Optional[Union[str, List[Dict[str, Any]]]]:
50
+ """
51
+ Process prompt sections from POM or raw prompt text.
52
+
53
+ Returns:
54
+ String, List of section dictionaries, or None
55
+ """
56
+ # First check if we have contexts - they take precedence
57
+ if self._contexts:
58
+ return None # Contexts handle their own prompt sections
59
+
60
+ # Check if we have a raw prompt text - return it directly
61
+ if self._prompt_text:
62
+ return self._prompt_text
63
+
64
+ # Otherwise use POM sections if available
65
+ if self.agent._use_pom and self.agent.pom:
66
+ sections = self.agent.pom.to_dict()
67
+ if sections:
68
+ return sections
69
+
70
+ return None
71
+
72
+ def define_contexts(self, contexts: Union[Dict[str, Any], Any]) -> None:
73
+ """
74
+ Define contexts for the agent.
75
+
76
+ Args:
77
+ contexts: Context configuration (dict or ContextBuilder)
78
+ """
79
+ if hasattr(contexts, 'to_dict'):
80
+ # It's a ContextBuilder
81
+ self._contexts = contexts.to_dict()
82
+ elif isinstance(contexts, dict):
83
+ # It's already a dictionary
84
+ self._contexts = contexts
85
+ else:
86
+ raise ValueError("contexts must be a dictionary or a ContextBuilder object")
87
+
88
+ logger.debug(f"Defined contexts: {self._contexts}")
89
+
90
+ def set_prompt_text(self, text: str) -> None:
91
+ """
92
+ Set the agent's prompt as raw text.
93
+
94
+ Args:
95
+ text: Prompt text
96
+ """
97
+ self._validate_prompt_mode_exclusivity()
98
+ self._prompt_text = text
99
+ logger.debug(f"Set prompt text: {text[:100]}...")
100
+
101
+ def set_post_prompt(self, text: str) -> None:
102
+ """
103
+ Set the post-prompt text.
104
+
105
+ Args:
106
+ text: Post-prompt text
107
+ """
108
+ self._post_prompt_text = text
109
+ logger.debug(f"Set post-prompt text: {text[:100]}...")
110
+
111
+ def set_prompt_pom(self, pom: List[Dict[str, Any]]) -> None:
112
+ """
113
+ Set the prompt as a POM dictionary.
114
+
115
+ Args:
116
+ pom: POM dictionary structure
117
+
118
+ Raises:
119
+ ValueError: If use_pom is False
120
+ """
121
+ if self.agent._use_pom:
122
+ self.agent.pom = pom
123
+ else:
124
+ raise ValueError("use_pom must be True to use set_prompt_pom")
125
+
126
+ def prompt_add_section(
127
+ self,
128
+ title: str,
129
+ body: str = "",
130
+ bullets: Optional[List[str]] = None,
131
+ numbered: bool = False,
132
+ numbered_bullets: bool = False,
133
+ subsections: Optional[List[Dict[str, Any]]] = None
134
+ ) -> None:
135
+ """
136
+ Add a section to the prompt.
137
+
138
+ Args:
139
+ title: Section title
140
+ body: Optional section body text
141
+ bullets: Optional list of bullet points
142
+ numbered: Whether this section should be numbered
143
+ numbered_bullets: Whether bullets should be numbered
144
+ subsections: Optional list of subsection objects
145
+ """
146
+ self._validate_prompt_mode_exclusivity()
147
+ if self.agent._use_pom and self.agent.pom:
148
+ # Create parameters for add_section based on what's supported
149
+ kwargs = {}
150
+
151
+ # Start with basic parameters
152
+ kwargs['title'] = title
153
+ kwargs['body'] = body
154
+ if bullets:
155
+ kwargs['bullets'] = bullets
156
+
157
+ # Add optional parameters if they look supported
158
+ if hasattr(self.agent.pom, 'add_section'):
159
+ sig = inspect.signature(self.agent.pom.add_section)
160
+ if 'numbered' in sig.parameters:
161
+ kwargs['numbered'] = numbered
162
+ if 'numberedBullets' in sig.parameters:
163
+ kwargs['numberedBullets'] = numbered_bullets
164
+
165
+ # Create the section
166
+ section = self.agent.pom.add_section(**kwargs)
167
+
168
+ # Now add subsections if provided, by calling add_subsection on the section
169
+ if subsections:
170
+ for subsection in subsections:
171
+ if 'title' in subsection:
172
+ section.add_subsection(
173
+ title=subsection.get('title'),
174
+ body=subsection.get('body', ''),
175
+ bullets=subsection.get('bullets', [])
176
+ )
177
+
178
+ def prompt_add_to_section(
179
+ self,
180
+ title: str,
181
+ body: Optional[str] = None,
182
+ bullet: Optional[str] = None,
183
+ bullets: Optional[List[str]] = None
184
+ ) -> None:
185
+ """
186
+ Add content to an existing section (creating it if needed).
187
+
188
+ Args:
189
+ title: Section title
190
+ body: Optional text to append to section body
191
+ bullet: Optional single bullet point to add
192
+ bullets: Optional list of bullet points to add
193
+ """
194
+ if self.agent._use_pom and self.agent.pom:
195
+ # Find the section first
196
+ section = self.agent.pom.find_section(title)
197
+
198
+ if section is None:
199
+ # Section doesn't exist, create it
200
+ section = self.agent.pom.add_section(title=title)
201
+
202
+ # Add content to the section
203
+ if body:
204
+ if section.body:
205
+ section.body = f"{section.body}\n\n{body}"
206
+ else:
207
+ section.body = body
208
+
209
+ # Process bullets
210
+ bullets_to_add = []
211
+ if bullet:
212
+ bullets_to_add.append(bullet)
213
+ if bullets:
214
+ bullets_to_add.extend(bullets)
215
+
216
+ if bullets_to_add:
217
+ section.add_bullets(bullets_to_add)
218
+
219
+ def prompt_add_subsection(
220
+ self,
221
+ parent_title: str,
222
+ title: str,
223
+ body: str = "",
224
+ bullets: Optional[List[str]] = None
225
+ ) -> None:
226
+ """
227
+ Add a subsection to an existing section (creating parent if needed).
228
+
229
+ Args:
230
+ parent_title: Parent section title
231
+ title: Subsection title
232
+ body: Optional subsection body text
233
+ bullets: Optional list of bullet points
234
+ """
235
+ if self.agent._use_pom and self.agent.pom:
236
+ # First find or create the parent section
237
+ parent_section = None
238
+
239
+ # Try to find the parent section by title
240
+ if hasattr(self.agent.pom, 'sections'):
241
+ for section in self.agent.pom.sections:
242
+ if hasattr(section, 'title') and section.title == parent_title:
243
+ parent_section = section
244
+ break
245
+
246
+ # If parent section not found, create it
247
+ if not parent_section:
248
+ parent_section = self.agent.pom.add_section(title=parent_title)
249
+
250
+ # Now call add_subsection on the parent section object, not on POM
251
+ parent_section.add_subsection(
252
+ title=title,
253
+ body=body,
254
+ bullets=bullets or []
255
+ )
256
+
257
+ def prompt_has_section(self, title: str) -> bool:
258
+ """
259
+ Check if a section exists in the prompt.
260
+
261
+ Args:
262
+ title: Section title to check
263
+
264
+ Returns:
265
+ True if section exists, False otherwise
266
+ """
267
+ if self.agent._use_pom and self.agent.pom:
268
+ # Use find_section method from POM
269
+ return self.agent.pom.find_section(title) is not None
270
+ return False
271
+
272
+ def get_prompt(self) -> Optional[Union[str, List[Dict[str, Any]]]]:
273
+ """
274
+ Get the prompt configuration.
275
+
276
+ Returns:
277
+ Prompt text or sections or None
278
+ """
279
+ return self._process_prompt_sections()
280
+
281
+ def get_raw_prompt(self) -> Optional[str]:
282
+ """
283
+ Get the raw prompt text if set.
284
+
285
+ Returns:
286
+ Raw prompt text or None
287
+ """
288
+ return self._prompt_text
289
+
290
+ def get_post_prompt(self) -> Optional[str]:
291
+ """
292
+ Get the post-prompt text.
293
+
294
+ Returns:
295
+ Post-prompt text or None
296
+ """
297
+ return self._post_prompt_text
298
+
299
+ def get_contexts(self) -> Optional[Dict[str, Any]]:
300
+ """
301
+ Get the contexts configuration.
302
+
303
+ Returns:
304
+ Contexts dict or None
305
+ """
306
+ return self._contexts
@@ -0,0 +1,9 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
@@ -0,0 +1,9 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
@@ -0,0 +1,9 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
@@ -0,0 +1,15 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ """Tool management modules."""
11
+
12
+ from .registry import ToolRegistry
13
+ from .decorator import ToolDecorator
14
+
15
+ __all__ = ['ToolRegistry', 'ToolDecorator']
@@ -0,0 +1,97 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ """Tool decorator functionality."""
11
+
12
+ from functools import wraps
13
+ from typing import Callable, Optional, Dict, Any
14
+ import logging
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class ToolDecorator:
20
+ """Handles tool decoration logic."""
21
+
22
+ @staticmethod
23
+ def create_instance_decorator(registry):
24
+ """
25
+ Create instance tool decorator.
26
+
27
+ Args:
28
+ registry: ToolRegistry instance to register with
29
+
30
+ Returns:
31
+ Decorator function
32
+ """
33
+ def decorator(name=None, **kwargs):
34
+ """
35
+ Decorator for defining SWAIG tools in a class.
36
+
37
+ Used as:
38
+
39
+ @agent.tool(name="example_function", parameters={...})
40
+ def example_function(self, param1):
41
+ # ...
42
+ """
43
+ def inner_decorator(func):
44
+ nonlocal name
45
+ if name is None:
46
+ name = func.__name__
47
+
48
+ parameters = kwargs.pop("parameters", {})
49
+ description = kwargs.pop("description", func.__doc__ or f"Function {name}")
50
+ secure = kwargs.pop("secure", True)
51
+ fillers = kwargs.pop("fillers", None)
52
+ webhook_url = kwargs.pop("webhook_url", None)
53
+ required = kwargs.pop("required", None)
54
+
55
+ registry.define_tool(
56
+ name=name,
57
+ description=description,
58
+ parameters=parameters,
59
+ handler=func,
60
+ secure=secure,
61
+ fillers=fillers,
62
+ webhook_url=webhook_url,
63
+ required=required,
64
+ **kwargs # Pass through any additional swaig_fields
65
+ )
66
+ return func
67
+ return inner_decorator
68
+ return decorator
69
+
70
+ @classmethod
71
+ def create_class_decorator(cls):
72
+ """
73
+ Create class tool decorator.
74
+
75
+ Returns:
76
+ Decorator function
77
+ """
78
+ def tool(name=None, **kwargs):
79
+ """
80
+ Class method decorator for defining SWAIG tools.
81
+
82
+ Used as:
83
+
84
+ @AgentBase.tool(name="example_function", parameters={...})
85
+ def example_function(self, param1):
86
+ # ...
87
+ """
88
+ def decorator(func):
89
+ # Mark the function as a tool
90
+ func._is_tool = True
91
+ func._tool_name = name if name else func.__name__
92
+ func._tool_params = kwargs
93
+
94
+ # Return the original function
95
+ return func
96
+ return decorator
97
+ return tool