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,237 @@
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
+ """
11
+ API Ninjas Trivia Skill
12
+
13
+ A configurable skill for getting trivia questions from API Ninjas with customizable
14
+ categories and multiple tool instances.
15
+ """
16
+
17
+ from typing import Dict, Any, List
18
+ from signalwire_agents.core import SwaigFunctionResult
19
+ from signalwire_agents.core.skill_base import SkillBase
20
+
21
+
22
+ class ApiNinjasTriviaSkill(SkillBase):
23
+ """
24
+ Skill for getting trivia questions from API Ninjas with configurable categories.
25
+
26
+ Supports multiple instances with different tool names and category combinations.
27
+ Uses DataMap for serverless execution with dynamic enum generation.
28
+
29
+ Configuration:
30
+ - tool_name: Custom name for the generated SWAIG function
31
+ - api_key: API Ninjas API key
32
+ - categories: Array of category strings to enable
33
+
34
+ Available categories:
35
+ - artliterature: Art and Literature
36
+ - language: Language
37
+ - sciencenature: Science and Nature
38
+ - general: General Knowledge
39
+ - fooddrink: Food and Drink
40
+ - peopleplaces: People and Places
41
+ - geography: Geography
42
+ - historyholidays: History and Holidays
43
+ - entertainment: Entertainment
44
+ - toysgames: Toys and Games
45
+ - music: Music
46
+ - mathematics: Mathematics
47
+ - religionmythology: Religion and Mythology
48
+ - sportsleisure: Sports and Leisure
49
+
50
+ Example:
51
+ agent.add_skill("api_ninjas_trivia", {
52
+ "tool_name": "get_science_trivia",
53
+ "api_key": "your_api_key",
54
+ "categories": ["sciencenature", "mathematics", "general"]
55
+ })
56
+ """
57
+
58
+ SKILL_NAME = "api_ninjas_trivia"
59
+ SKILL_DESCRIPTION = "Get trivia questions from API Ninjas"
60
+ SUPPORTS_MULTIPLE_INSTANCES = True
61
+ REQUIRED_ENV_VARS = [] # API key can be passed via params
62
+
63
+ # Valid API Ninjas trivia categories with human-readable descriptions
64
+ VALID_CATEGORIES = {
65
+ "artliterature": "Art and Literature",
66
+ "language": "Language",
67
+ "sciencenature": "Science and Nature",
68
+ "general": "General Knowledge",
69
+ "fooddrink": "Food and Drink",
70
+ "peopleplaces": "People and Places",
71
+ "geography": "Geography",
72
+ "historyholidays": "History and Holidays",
73
+ "entertainment": "Entertainment",
74
+ "toysgames": "Toys and Games",
75
+ "music": "Music",
76
+ "mathematics": "Mathematics",
77
+ "religionmythology": "Religion and Mythology",
78
+ "sportsleisure": "Sports and Leisure"
79
+ }
80
+
81
+ def __init__(self, agent, params: Dict[str, Any] = None):
82
+ """
83
+ Initialize the skill with configuration parameters.
84
+
85
+ Args:
86
+ agent: The agent instance this skill belongs to
87
+ params: Configuration dictionary containing:
88
+ - tool_name: Custom tool name (default: "get_trivia")
89
+ - api_key: API Ninjas API key (required)
90
+ - categories: Array of category strings (default: all categories)
91
+ """
92
+ super().__init__(agent, params)
93
+
94
+ # Extract configuration
95
+ self.tool_name = self.params.get('tool_name', 'get_trivia')
96
+ self.api_key = self.params.get('api_key')
97
+ self.categories = self.params.get('categories', list(self.VALID_CATEGORIES.keys()))
98
+
99
+ # Validate configuration
100
+ self._validate_config()
101
+
102
+ def _validate_config(self):
103
+ """Validate the skill configuration."""
104
+ # Validate API key
105
+ if not self.api_key or not isinstance(self.api_key, str):
106
+ raise ValueError("api_key parameter is required and must be a non-empty string")
107
+
108
+ # Validate categories
109
+ if not isinstance(self.categories, list) or len(self.categories) == 0:
110
+ raise ValueError("categories parameter must be a non-empty list")
111
+
112
+ # Validate each category
113
+ for i, category in enumerate(self.categories):
114
+ if not isinstance(category, str):
115
+ raise ValueError(f"Category {i} must be a string")
116
+ if category not in self.VALID_CATEGORIES:
117
+ valid_cats = ', '.join(self.VALID_CATEGORIES.keys())
118
+ raise ValueError(f"Category '{category}' is not valid. Valid categories: {valid_cats}")
119
+
120
+ def setup(self) -> bool:
121
+ """
122
+ Setup the skill - validates API key is available.
123
+
124
+ Returns:
125
+ True if setup successful
126
+ """
127
+ # API key validation already done in _validate_config
128
+ return True
129
+
130
+ def register_tools(self) -> None:
131
+ """Register SWAIG tools with the agent"""
132
+ tools = self.get_tools()
133
+ for tool in tools:
134
+ # Merge any swaig_fields from params into the tool
135
+ if self.swaig_fields:
136
+ tool.update(self.swaig_fields)
137
+ self.agent.register_swaig_function(tool)
138
+
139
+ def get_instance_key(self) -> str:
140
+ """
141
+ Generate a unique instance key for this skill configuration.
142
+
143
+ Returns:
144
+ Unique key combining skill name and tool name
145
+ """
146
+ return f"{self.SKILL_NAME}_{self.tool_name}"
147
+
148
+ def get_tools(self) -> List[Dict[str, Any]]:
149
+ """
150
+ Generate the SWAIG tool with DataMap webhook.
151
+
152
+ Returns:
153
+ List containing the generated tool configuration
154
+ """
155
+ # Build enum values and descriptions
156
+ enum_values = []
157
+ descriptions = []
158
+
159
+ for category in self.categories:
160
+ enum_values.append(category)
161
+ descriptions.append(f"{category}: {self.VALID_CATEGORIES[category]}")
162
+
163
+ # Build parameter description
164
+ description = "Category for trivia question. Options: " + "; ".join(descriptions)
165
+
166
+ # Create the tool configuration with DataMap webhook
167
+ tool = {
168
+ "function": self.tool_name,
169
+ "description": f"Get trivia questions for {self.tool_name.replace('_', ' ')}",
170
+ "parameters": {
171
+ "type": "object",
172
+ "properties": {
173
+ "category": {
174
+ "type": "string",
175
+ "description": description,
176
+ "enum": enum_values
177
+ }
178
+ },
179
+ "required": ["category"]
180
+ },
181
+ "data_map": {
182
+ "webhooks": [
183
+ {
184
+ "url": "https://api.api-ninjas.com/v1/trivia?category=%{args.category}",
185
+ "method": "GET",
186
+ "headers": {
187
+ "X-Api-Key": self.api_key
188
+ },
189
+ "output": SwaigFunctionResult(
190
+ "Category %{array[0].category} question: %{array[0].question} Answer: %{array[0].answer}, be sure to give the user time to answer before saying the answer."
191
+ ).to_dict()
192
+ }
193
+ ],
194
+ "error_keys": ["error"],
195
+ "output": SwaigFunctionResult(
196
+ "Sorry, I cannot get trivia questions right now. Please try again later."
197
+ ).to_dict()
198
+ }
199
+ }
200
+
201
+ return [tool]
202
+
203
+ @classmethod
204
+ def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]:
205
+ """
206
+ Get the parameter schema for the API Ninjas Trivia skill.
207
+
208
+ Returns parameter definitions for GUI configuration.
209
+ """
210
+ schema = super().get_parameter_schema()
211
+
212
+ # Build categories enum description
213
+ category_options = []
214
+ for key, desc in cls.VALID_CATEGORIES.items():
215
+ category_options.append(f"{key} ({desc})")
216
+
217
+ schema.update({
218
+ "api_key": {
219
+ "type": "string",
220
+ "description": "API Ninjas API key",
221
+ "required": True,
222
+ "hidden": True,
223
+ "env_var": "API_NINJAS_KEY"
224
+ },
225
+ "categories": {
226
+ "type": "array",
227
+ "description": "List of trivia categories to enable. Available: " + ", ".join(category_options),
228
+ "default": list(cls.VALID_CATEGORIES.keys()),
229
+ "required": False,
230
+ "items": {
231
+ "type": "string",
232
+ "enum": list(cls.VALID_CATEGORIES.keys())
233
+ }
234
+ }
235
+ })
236
+
237
+ return schema
@@ -0,0 +1,210 @@
1
+ # DataSphere Skill
2
+
3
+ The datasphere skill provides knowledge search capabilities using SignalWire DataSphere's RAG (Retrieval-Augmented Generation) stack. It allows agents to search through uploaded documents and knowledge bases to find relevant information.
4
+
5
+ ## Features
6
+
7
+ - SignalWire DataSphere integration for knowledge search
8
+ - Vector-based similarity search with configurable distance thresholds
9
+ - Multi-language support and synonym expansion
10
+ - Tag-based filtering for targeted searches
11
+ - Custom no-results messages with query placeholders
12
+ - **Multiple instance support** - search different knowledge bases with different configurations
13
+
14
+ ## Requirements
15
+
16
+ - **Packages**: `requests`
17
+ - **SignalWire Account**: DataSphere-enabled space with uploaded documents
18
+
19
+ ## Parameters
20
+
21
+ ### Required Parameters
22
+
23
+ - `space_name` (string): SignalWire space name
24
+ - `project_id` (string): SignalWire project ID
25
+ - `token` (string): SignalWire authentication token
26
+ - `document_id` (string): DataSphere document ID to search
27
+
28
+ ### Optional Parameters
29
+
30
+ - `count` (integer, default: 1): Number of search results to return
31
+ - `distance` (float, default: 3.0): Distance threshold for search matching (lower = more similar)
32
+ - `tags` (list): List of tags to filter search results
33
+ - `language` (string): Language code to limit search (e.g., "en", "es")
34
+ - `pos_to_expand` (list): Parts of speech for synonym expansion (e.g., ["NOUN", "VERB"])
35
+ - `max_synonyms` (integer): Maximum number of synonyms to use for each word
36
+ - `tool_name` (string, default: "search_knowledge"): Custom name for the search tool (enables multiple instances)
37
+ - `no_results_message` (string): Custom message when no results are found
38
+ - Default: "I couldn't find any relevant information for '{query}' in the knowledge base. Try rephrasing your question or asking about a different topic."
39
+ - Use `{query}` as placeholder for the search query
40
+
41
+ ### Advanced Parameters
42
+
43
+ - `swaig_fields` (dict): Additional SWAIG function configuration
44
+ - `secure` (boolean): Override security settings
45
+ - `fillers` (dict): Language-specific filler phrases during search
46
+ - Any other SWAIG function parameters
47
+
48
+ ## Tools Created
49
+
50
+ - **Default**: `search_knowledge` - Search the knowledge base for information
51
+ - **Custom**: Uses the `tool_name` parameter value
52
+
53
+ ## Usage Examples
54
+
55
+ ### Basic Usage
56
+
57
+ ```python
58
+ # Minimal configuration
59
+ agent.add_skill("datasphere", {
60
+ "space_name": "my-space",
61
+ "project_id": "my-project-id",
62
+ "token": "my-token",
63
+ "document_id": "my-document-id"
64
+ })
65
+ ```
66
+
67
+ ### Advanced Configuration
68
+
69
+ ```python
70
+ # Comprehensive search with filtering
71
+ agent.add_skill("datasphere", {
72
+ "space_name": "my-space",
73
+ "project_id": "my-project-id",
74
+ "token": "my-token",
75
+ "document_id": "my-document-id",
76
+ "count": 3,
77
+ "distance": 5.0,
78
+ "tags": ["FAQ", "Support"],
79
+ "language": "en",
80
+ "pos_to_expand": ["NOUN", "VERB"],
81
+ "max_synonyms": 3,
82
+ "no_results_message": "I couldn't find information about '{query}' in our support documentation."
83
+ })
84
+ ```
85
+
86
+ ### Multiple Instances
87
+
88
+ ```python
89
+ # Product documentation search
90
+ agent.add_skill("datasphere", {
91
+ "space_name": "my-space",
92
+ "project_id": "my-project-id",
93
+ "token": "my-token",
94
+ "document_id": "product-docs-id",
95
+ "tool_name": "search_product_docs",
96
+ "tags": ["Products", "Features"],
97
+ "count": 2
98
+ })
99
+
100
+ # Support knowledge base search
101
+ agent.add_skill("datasphere", {
102
+ "space_name": "my-space",
103
+ "project_id": "my-project-id",
104
+ "token": "my-token",
105
+ "document_id": "support-kb-id",
106
+ "tool_name": "search_support",
107
+ "tags": ["Support", "Troubleshooting"],
108
+ "count": 3,
109
+ "distance": 4.0
110
+ })
111
+
112
+ # Policy and procedure search
113
+ agent.add_skill("datasphere", {
114
+ "space_name": "my-space",
115
+ "project_id": "my-project-id",
116
+ "token": "my-token",
117
+ "document_id": "policies-id",
118
+ "tool_name": "search_policies",
119
+ "tags": ["Policy", "Compliance"],
120
+ "count": 1,
121
+ "distance": 2.0
122
+ })
123
+ ```
124
+
125
+ ### With Custom Fillers
126
+
127
+ ```python
128
+ agent.add_skill("datasphere", {
129
+ "space_name": "my-space",
130
+ "project_id": "my-project-id",
131
+ "token": "my-token",
132
+ "document_id": "my-document-id",
133
+ "swaig_fields": {
134
+ "fillers": {
135
+ "en-US": [
136
+ "Searching our knowledge base...",
137
+ "Looking through our documentation...",
138
+ "Checking our information database..."
139
+ ],
140
+ "es-ES": [
141
+ "Buscando en nuestra base de conocimientos...",
142
+ "Revisando nuestra documentación..."
143
+ ]
144
+ }
145
+ }
146
+ })
147
+ ```
148
+
149
+ ## How It Works
150
+
151
+ 1. **Vector Search**: Uses semantic similarity to find relevant content chunks
152
+ 2. **Distance Filtering**: Only returns results within the specified distance threshold
153
+ 3. **Tag Filtering**: Optionally filters results by document tags
154
+ 4. **Language Processing**: Supports synonym expansion and language-specific search
155
+ 5. **Format Results**: Presents found content with metadata and relevance scores
156
+
157
+ ## Multiple Instance Support
158
+
159
+ The datasphere skill supports multiple instances, allowing you to:
160
+
161
+ - Search different knowledge bases/documents with one agent
162
+ - Use different search parameters per knowledge domain
163
+ - Create specialized search tools (`search_products`, `search_support`, etc.)
164
+ - Apply different tag filtering per instance
165
+ - Customize distance thresholds based on content type
166
+
167
+ Each instance is uniquely identified by its `search_engine_id` (derived from space/project/document) and `tool_name` combination.
168
+
169
+ ## Parameters Explained
170
+
171
+ ### Distance Threshold
172
+ - **Lower values** (1.0-2.0): Very strict matching, only highly similar content
173
+ - **Medium values** (3.0-4.0): Balanced matching, good for most use cases
174
+ - **Higher values** (5.0+): More permissive matching, broader results
175
+
176
+ ### Count vs Distance
177
+ - Use higher `count` with lower `distance` for precise, multiple results
178
+ - Use lower `count` with higher `distance` for broader, fewer results
179
+
180
+ ### Tags Usage
181
+ - Pre-tag your documents in DataSphere with categories
182
+ - Use tags to create domain-specific searches (e.g., ["FAQ"], ["Legal"], ["Technical"])
183
+
184
+ ### Language Support
185
+ - Specify language codes for multilingual knowledge bases
186
+ - Helps improve search accuracy for non-English content
187
+
188
+ ## Error Handling
189
+
190
+ - **No Results**: Returns custom `no_results_message` with query placeholder
191
+ - **API Issues**: Returns friendly error message for authentication/connectivity issues
192
+ - **Invalid Documents**: Gracefully handles missing or inaccessible documents
193
+ - **Timeout Protection**: Built-in 30-second timeout for API requests
194
+
195
+ ## Best Practices
196
+
197
+ 1. **Document Organization**: Use meaningful tags when uploading to DataSphere
198
+ 2. **Distance Tuning**: Start with default 3.0, adjust based on result quality
199
+ 3. **Multiple Instances**: Separate different knowledge domains for better results
200
+ 4. **Language Consistency**: Specify language when dealing with multilingual content
201
+ 5. **Result Count**: Balance between comprehensive answers (higher count) and response speed (lower count)
202
+
203
+ ## Setting Up DataSphere
204
+
205
+ 1. Access your SignalWire space
206
+ 2. Enable DataSphere in your space settings
207
+ 3. Upload documents through the DataSphere interface
208
+ 4. Note the document IDs for use in skill configuration
209
+ 5. Apply appropriate tags during document upload
210
+ 6. Get your project ID and token from SignalWire console
@@ -26,6 +26,88 @@ class DataSphereSkill(SkillBase):
26
26
  # Enable multiple instances support
27
27
  SUPPORTS_MULTIPLE_INSTANCES = True
28
28
 
29
+ @classmethod
30
+ def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]:
31
+ """Get parameter schema for DataSphere skill"""
32
+ schema = super().get_parameter_schema()
33
+ schema.update({
34
+ "space_name": {
35
+ "type": "string",
36
+ "description": "SignalWire space name (e.g., 'mycompany' from mycompany.signalwire.com)",
37
+ "required": True
38
+ },
39
+ "project_id": {
40
+ "type": "string",
41
+ "description": "SignalWire project ID",
42
+ "required": True,
43
+ "env_var": "SIGNALWIRE_PROJECT_ID"
44
+ },
45
+ "token": {
46
+ "type": "string",
47
+ "description": "SignalWire API token",
48
+ "required": True,
49
+ "hidden": True,
50
+ "env_var": "SIGNALWIRE_TOKEN"
51
+ },
52
+ "document_id": {
53
+ "type": "string",
54
+ "description": "DataSphere document ID to search within",
55
+ "required": True
56
+ },
57
+ "count": {
58
+ "type": "integer",
59
+ "description": "Number of search results to return",
60
+ "default": 1,
61
+ "required": False,
62
+ "minimum": 1,
63
+ "maximum": 10
64
+ },
65
+ "distance": {
66
+ "type": "number",
67
+ "description": "Maximum distance threshold for results (lower is more relevant)",
68
+ "default": 3.0,
69
+ "required": False,
70
+ "minimum": 0.0,
71
+ "maximum": 10.0
72
+ },
73
+ "tags": {
74
+ "type": "array",
75
+ "description": "Tags to filter search results",
76
+ "required": False,
77
+ "items": {
78
+ "type": "string"
79
+ }
80
+ },
81
+ "language": {
82
+ "type": "string",
83
+ "description": "Language code for query expansion (e.g., 'en', 'es')",
84
+ "required": False
85
+ },
86
+ "pos_to_expand": {
87
+ "type": "array",
88
+ "description": "Parts of speech to expand with synonyms",
89
+ "required": False,
90
+ "items": {
91
+ "type": "string",
92
+ "enum": ["NOUN", "VERB", "ADJ", "ADV"]
93
+ }
94
+ },
95
+ "max_synonyms": {
96
+ "type": "integer",
97
+ "description": "Maximum number of synonyms to use for query expansion",
98
+ "required": False,
99
+ "minimum": 1,
100
+ "maximum": 10
101
+ },
102
+ "no_results_message": {
103
+ "type": "string",
104
+ "description": "Message to return when no results are found",
105
+ "default": "I couldn't find any relevant information for '{query}' in the knowledge base. Try rephrasing your question or asking about a different topic.",
106
+ "required": False
107
+ }
108
+ })
109
+ return schema
110
+
29
111
  def get_instance_key(self) -> str:
30
112
  """
31
113
  Get the key used to track this skill instance
@@ -77,7 +159,7 @@ class DataSphereSkill(SkillBase):
77
159
 
78
160
  def register_tools(self) -> None:
79
161
  """Register knowledge search tool with the agent"""
80
- self.agent.define_tool(
162
+ self.define_tool(
81
163
  name=self.tool_name,
82
164
  description="Search the knowledge base for information on any topic and return relevant results",
83
165
  parameters={
@@ -86,8 +168,7 @@ class DataSphereSkill(SkillBase):
86
168
  "description": "The search query - what information you're looking for in the knowledge base"
87
169
  }
88
170
  },
89
- handler=self._search_knowledge_handler,
90
- **self.swaig_fields
171
+ handler=self._search_knowledge_handler
91
172
  )
92
173
 
93
174
  def _search_knowledge_handler(self, args, raw_data):