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.
- signalwire_agents/__init__.py +99 -15
- signalwire_agents/agent_server.py +248 -60
- signalwire_agents/agents/bedrock.py +296 -0
- signalwire_agents/cli/__init__.py +9 -0
- signalwire_agents/cli/build_search.py +951 -41
- signalwire_agents/cli/config.py +80 -0
- signalwire_agents/cli/core/__init__.py +10 -0
- signalwire_agents/cli/core/agent_loader.py +470 -0
- signalwire_agents/cli/core/argparse_helpers.py +179 -0
- signalwire_agents/cli/core/dynamic_config.py +71 -0
- signalwire_agents/cli/core/service_loader.py +303 -0
- signalwire_agents/cli/dokku.py +2320 -0
- signalwire_agents/cli/execution/__init__.py +10 -0
- signalwire_agents/cli/execution/datamap_exec.py +446 -0
- signalwire_agents/cli/execution/webhook_exec.py +134 -0
- signalwire_agents/cli/init_project.py +2636 -0
- signalwire_agents/cli/output/__init__.py +10 -0
- signalwire_agents/cli/output/output_formatter.py +255 -0
- signalwire_agents/cli/output/swml_dump.py +186 -0
- signalwire_agents/cli/simulation/__init__.py +10 -0
- signalwire_agents/cli/simulation/data_generation.py +374 -0
- signalwire_agents/cli/simulation/data_overrides.py +200 -0
- signalwire_agents/cli/simulation/mock_env.py +282 -0
- signalwire_agents/cli/swaig_test_wrapper.py +52 -0
- signalwire_agents/cli/test_swaig.py +566 -2366
- signalwire_agents/cli/types.py +81 -0
- signalwire_agents/core/__init__.py +2 -2
- signalwire_agents/core/agent/__init__.py +12 -0
- signalwire_agents/core/agent/config/__init__.py +12 -0
- signalwire_agents/core/agent/deployment/__init__.py +9 -0
- signalwire_agents/core/agent/deployment/handlers/__init__.py +9 -0
- signalwire_agents/core/agent/prompt/__init__.py +14 -0
- signalwire_agents/core/agent/prompt/manager.py +306 -0
- signalwire_agents/core/agent/routing/__init__.py +9 -0
- signalwire_agents/core/agent/security/__init__.py +9 -0
- signalwire_agents/core/agent/swml/__init__.py +9 -0
- signalwire_agents/core/agent/tools/__init__.py +15 -0
- signalwire_agents/core/agent/tools/decorator.py +97 -0
- signalwire_agents/core/agent/tools/registry.py +210 -0
- signalwire_agents/core/agent_base.py +845 -2916
- signalwire_agents/core/auth_handler.py +233 -0
- signalwire_agents/core/config_loader.py +259 -0
- signalwire_agents/core/contexts.py +418 -0
- signalwire_agents/core/data_map.py +3 -15
- signalwire_agents/core/function_result.py +116 -44
- signalwire_agents/core/logging_config.py +162 -18
- signalwire_agents/core/mixins/__init__.py +28 -0
- signalwire_agents/core/mixins/ai_config_mixin.py +442 -0
- signalwire_agents/core/mixins/auth_mixin.py +280 -0
- signalwire_agents/core/mixins/prompt_mixin.py +358 -0
- signalwire_agents/core/mixins/serverless_mixin.py +460 -0
- signalwire_agents/core/mixins/skill_mixin.py +55 -0
- signalwire_agents/core/mixins/state_mixin.py +153 -0
- signalwire_agents/core/mixins/tool_mixin.py +230 -0
- signalwire_agents/core/mixins/web_mixin.py +1142 -0
- signalwire_agents/core/security_config.py +333 -0
- signalwire_agents/core/skill_base.py +84 -1
- signalwire_agents/core/skill_manager.py +62 -20
- signalwire_agents/core/swaig_function.py +18 -5
- signalwire_agents/core/swml_builder.py +207 -11
- signalwire_agents/core/swml_handler.py +27 -21
- signalwire_agents/core/swml_renderer.py +123 -312
- signalwire_agents/core/swml_service.py +171 -203
- signalwire_agents/mcp_gateway/__init__.py +29 -0
- signalwire_agents/mcp_gateway/gateway_service.py +564 -0
- signalwire_agents/mcp_gateway/mcp_manager.py +513 -0
- signalwire_agents/mcp_gateway/session_manager.py +218 -0
- signalwire_agents/prefabs/concierge.py +0 -3
- signalwire_agents/prefabs/faq_bot.py +0 -3
- signalwire_agents/prefabs/info_gatherer.py +0 -3
- signalwire_agents/prefabs/receptionist.py +0 -3
- signalwire_agents/prefabs/survey.py +0 -3
- signalwire_agents/schema.json +9218 -5489
- signalwire_agents/search/__init__.py +7 -1
- signalwire_agents/search/document_processor.py +490 -31
- signalwire_agents/search/index_builder.py +307 -37
- signalwire_agents/search/migration.py +418 -0
- signalwire_agents/search/models.py +30 -0
- signalwire_agents/search/pgvector_backend.py +748 -0
- signalwire_agents/search/query_processor.py +162 -31
- signalwire_agents/search/search_engine.py +916 -35
- signalwire_agents/search/search_service.py +376 -53
- signalwire_agents/skills/README.md +452 -0
- signalwire_agents/skills/__init__.py +14 -2
- signalwire_agents/skills/api_ninjas_trivia/README.md +215 -0
- signalwire_agents/skills/api_ninjas_trivia/__init__.py +12 -0
- signalwire_agents/skills/api_ninjas_trivia/skill.py +237 -0
- signalwire_agents/skills/datasphere/README.md +210 -0
- signalwire_agents/skills/datasphere/skill.py +84 -3
- signalwire_agents/skills/datasphere_serverless/README.md +258 -0
- signalwire_agents/skills/datasphere_serverless/__init__.py +9 -0
- signalwire_agents/skills/datasphere_serverless/skill.py +82 -1
- signalwire_agents/skills/datetime/README.md +132 -0
- signalwire_agents/skills/datetime/__init__.py +9 -0
- signalwire_agents/skills/datetime/skill.py +20 -7
- signalwire_agents/skills/joke/README.md +149 -0
- signalwire_agents/skills/joke/__init__.py +9 -0
- signalwire_agents/skills/joke/skill.py +21 -0
- signalwire_agents/skills/math/README.md +161 -0
- signalwire_agents/skills/math/__init__.py +9 -0
- signalwire_agents/skills/math/skill.py +18 -4
- signalwire_agents/skills/mcp_gateway/README.md +230 -0
- signalwire_agents/skills/mcp_gateway/__init__.py +10 -0
- signalwire_agents/skills/mcp_gateway/skill.py +421 -0
- signalwire_agents/skills/native_vector_search/README.md +210 -0
- signalwire_agents/skills/native_vector_search/__init__.py +9 -0
- signalwire_agents/skills/native_vector_search/skill.py +569 -101
- signalwire_agents/skills/play_background_file/README.md +218 -0
- signalwire_agents/skills/play_background_file/__init__.py +12 -0
- signalwire_agents/skills/play_background_file/skill.py +242 -0
- signalwire_agents/skills/registry.py +395 -40
- signalwire_agents/skills/spider/README.md +236 -0
- signalwire_agents/skills/spider/__init__.py +13 -0
- signalwire_agents/skills/spider/skill.py +598 -0
- signalwire_agents/skills/swml_transfer/README.md +395 -0
- signalwire_agents/skills/swml_transfer/__init__.py +10 -0
- signalwire_agents/skills/swml_transfer/skill.py +359 -0
- signalwire_agents/skills/weather_api/README.md +178 -0
- signalwire_agents/skills/weather_api/__init__.py +12 -0
- signalwire_agents/skills/weather_api/skill.py +191 -0
- signalwire_agents/skills/web_search/README.md +163 -0
- signalwire_agents/skills/web_search/__init__.py +9 -0
- signalwire_agents/skills/web_search/skill.py +586 -112
- signalwire_agents/skills/wikipedia_search/README.md +228 -0
- signalwire_agents/{core/state → skills/wikipedia_search}/__init__.py +5 -4
- signalwire_agents/skills/{wikipedia → wikipedia_search}/skill.py +33 -3
- signalwire_agents/web/__init__.py +17 -0
- signalwire_agents/web/web_service.py +559 -0
- signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-agent-init.1 +400 -0
- signalwire_agents-1.0.17.dev4.data/data/share/man/man1/sw-search.1 +483 -0
- signalwire_agents-1.0.17.dev4.data/data/share/man/man1/swaig-test.1 +308 -0
- {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/METADATA +347 -215
- signalwire_agents-1.0.17.dev4.dist-info/RECORD +147 -0
- signalwire_agents-1.0.17.dev4.dist-info/entry_points.txt +6 -0
- signalwire_agents/core/state/file_state_manager.py +0 -219
- signalwire_agents/core/state/state_manager.py +0 -101
- signalwire_agents/skills/wikipedia/__init__.py +0 -9
- signalwire_agents-0.1.13.data/data/schema.json +0 -5611
- signalwire_agents-0.1.13.dist-info/RECORD +0 -67
- signalwire_agents-0.1.13.dist-info/entry_points.txt +0 -3
- {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/WHEEL +0 -0
- {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/licenses/LICENSE +0 -0
- {signalwire_agents-0.1.13.dist-info → signalwire_agents-1.0.17.dev4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
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
|
+
Weather API Skill
|
|
12
|
+
|
|
13
|
+
A configurable skill for getting weather information from WeatherAPI.com with customizable
|
|
14
|
+
temperature units and TTS-friendly responses.
|
|
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 WeatherApiSkill(SkillBase):
|
|
23
|
+
"""
|
|
24
|
+
Skill for getting weather information from WeatherAPI.com.
|
|
25
|
+
|
|
26
|
+
Provides current weather data with configurable temperature units and
|
|
27
|
+
TTS-optimized natural language responses.
|
|
28
|
+
|
|
29
|
+
Configuration:
|
|
30
|
+
- tool_name: Custom name for the generated SWAIG function
|
|
31
|
+
- api_key: WeatherAPI.com API key
|
|
32
|
+
- temperature_unit: "fahrenheit" or "celsius" for temperature display
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
agent.add_skill("weather_api", {
|
|
36
|
+
"tool_name": "get_weather",
|
|
37
|
+
"api_key": "your_weatherapi_key",
|
|
38
|
+
"temperature_unit": "fahrenheit"
|
|
39
|
+
})
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
SKILL_NAME = "weather_api"
|
|
43
|
+
SKILL_DESCRIPTION = "Get current weather information from WeatherAPI.com"
|
|
44
|
+
SUPPORTS_MULTIPLE_INSTANCES = False
|
|
45
|
+
REQUIRED_ENV_VARS = [] # API key can be passed via params
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]:
|
|
49
|
+
"""Get parameter schema for weather API skill"""
|
|
50
|
+
schema = super().get_parameter_schema()
|
|
51
|
+
schema.update({
|
|
52
|
+
"api_key": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"description": "WeatherAPI.com API key",
|
|
55
|
+
"required": True,
|
|
56
|
+
"hidden": True,
|
|
57
|
+
"env_var": "WEATHER_API_KEY"
|
|
58
|
+
},
|
|
59
|
+
"tool_name": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "Custom name for the weather tool",
|
|
62
|
+
"default": "get_weather",
|
|
63
|
+
"required": False
|
|
64
|
+
},
|
|
65
|
+
"temperature_unit": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"description": "Temperature unit to display",
|
|
68
|
+
"default": "fahrenheit",
|
|
69
|
+
"required": False,
|
|
70
|
+
"enum": ["fahrenheit", "celsius"]
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
return schema
|
|
74
|
+
|
|
75
|
+
def __init__(self, agent, params: Dict[str, Any] = None):
|
|
76
|
+
"""
|
|
77
|
+
Initialize the skill with configuration parameters.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
agent: The agent instance this skill belongs to
|
|
81
|
+
params: Configuration dictionary containing:
|
|
82
|
+
- tool_name: Custom tool name (default: "get_weather")
|
|
83
|
+
- api_key: WeatherAPI.com API key (required)
|
|
84
|
+
- temperature_unit: "fahrenheit" or "celsius" (default: "fahrenheit")
|
|
85
|
+
"""
|
|
86
|
+
super().__init__(agent, params)
|
|
87
|
+
|
|
88
|
+
# Extract configuration
|
|
89
|
+
self.tool_name = self.params.get('tool_name', 'get_weather')
|
|
90
|
+
self.api_key = self.params.get('api_key')
|
|
91
|
+
self.temperature_unit = self.params.get('temperature_unit', 'fahrenheit')
|
|
92
|
+
|
|
93
|
+
# Validate configuration
|
|
94
|
+
self._validate_config()
|
|
95
|
+
|
|
96
|
+
def _validate_config(self):
|
|
97
|
+
"""Validate the skill configuration."""
|
|
98
|
+
# Validate API key
|
|
99
|
+
if not self.api_key or not isinstance(self.api_key, str):
|
|
100
|
+
raise ValueError("api_key parameter is required and must be a non-empty string")
|
|
101
|
+
|
|
102
|
+
# Validate temperature unit
|
|
103
|
+
if self.temperature_unit not in ['fahrenheit', 'celsius']:
|
|
104
|
+
raise ValueError("temperature_unit must be either 'fahrenheit' or 'celsius'")
|
|
105
|
+
|
|
106
|
+
def setup(self) -> bool:
|
|
107
|
+
"""
|
|
108
|
+
Setup the skill - validates API key is available.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
True if setup successful
|
|
112
|
+
"""
|
|
113
|
+
# API key validation already done in _validate_config
|
|
114
|
+
return True
|
|
115
|
+
|
|
116
|
+
def register_tools(self) -> None:
|
|
117
|
+
"""Register SWAIG tools with the agent"""
|
|
118
|
+
tools = self.get_tools()
|
|
119
|
+
for tool in tools:
|
|
120
|
+
# Merge any swaig_fields from params into the tool
|
|
121
|
+
if self.swaig_fields:
|
|
122
|
+
tool.update(self.swaig_fields)
|
|
123
|
+
self.agent.register_swaig_function(tool)
|
|
124
|
+
|
|
125
|
+
def get_tools(self) -> List[Dict[str, Any]]:
|
|
126
|
+
"""
|
|
127
|
+
Generate the SWAIG tool with DataMap webhook.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
List containing the generated tool configuration
|
|
131
|
+
"""
|
|
132
|
+
# Determine temperature fields based on unit
|
|
133
|
+
if self.temperature_unit == 'fahrenheit':
|
|
134
|
+
temp_field = 'temp_f'
|
|
135
|
+
feels_like_field = 'feelslike_f'
|
|
136
|
+
unit_name = 'Fahrenheit'
|
|
137
|
+
else:
|
|
138
|
+
temp_field = 'temp_c'
|
|
139
|
+
feels_like_field = 'feelslike_c'
|
|
140
|
+
unit_name = 'Celsius'
|
|
141
|
+
|
|
142
|
+
# Create TTS-friendly response instruction
|
|
143
|
+
response_instruction = (
|
|
144
|
+
f"Tell the user the current weather conditions. "
|
|
145
|
+
f"Express all temperatures in {unit_name} using natural language numbers "
|
|
146
|
+
f"without abbreviations or symbols for clear text-to-speech pronunciation. "
|
|
147
|
+
f"For example, say 'seventy two degrees {unit_name}' instead of '72F' or '72°F'. "
|
|
148
|
+
f"Include the condition, current temperature, wind direction and speed, "
|
|
149
|
+
f"cloud coverage percentage, and what the temperature feels like."
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Build the weather data template
|
|
153
|
+
weather_template = (
|
|
154
|
+
f"{response_instruction} "
|
|
155
|
+
f"Current conditions: ${{current.condition.text}}. "
|
|
156
|
+
f"Temperature: ${{current.{temp_field}}} degrees {unit_name}. "
|
|
157
|
+
f"Wind: ${{current.wind_dir}} at ${{current.wind_mph}} miles per hour. "
|
|
158
|
+
f"Cloud coverage: ${{current.cloud}} percent. "
|
|
159
|
+
f"Feels like: ${{current.{feels_like_field}}} degrees {unit_name}."
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# Create the tool configuration with DataMap webhook
|
|
163
|
+
tool = {
|
|
164
|
+
"function": self.tool_name,
|
|
165
|
+
"description": f"Get current weather information for any location",
|
|
166
|
+
"parameters": {
|
|
167
|
+
"type": "object",
|
|
168
|
+
"properties": {
|
|
169
|
+
"location": {
|
|
170
|
+
"type": "string",
|
|
171
|
+
"description": "The city, state, country, or location to get weather for"
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"required": ["location"]
|
|
175
|
+
},
|
|
176
|
+
"data_map": {
|
|
177
|
+
"webhooks": [
|
|
178
|
+
{
|
|
179
|
+
"url": f"https://api.weatherapi.com/v1/current.json?key={self.api_key}&q=${{lc:enc:args.location}}&aqi=no",
|
|
180
|
+
"method": "GET",
|
|
181
|
+
"output": SwaigFunctionResult(weather_template).to_dict()
|
|
182
|
+
}
|
|
183
|
+
],
|
|
184
|
+
"error_keys": ["error"],
|
|
185
|
+
"output": SwaigFunctionResult(
|
|
186
|
+
"Sorry, I cannot get weather information right now. Please try again later or check if the location name is correct."
|
|
187
|
+
).to_dict()
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return [tool]
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Web Search Skill
|
|
2
|
+
|
|
3
|
+
The web_search skill provides web search capabilities using Google Custom Search API with web scraping functionality. It allows agents to search the internet for current information and extract content from the resulting web pages.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Google Custom Search API integration
|
|
8
|
+
- Web page content scraping and extraction
|
|
9
|
+
- Configurable number of search results
|
|
10
|
+
- Configurable delay between requests
|
|
11
|
+
- Custom no-results messages with query placeholders
|
|
12
|
+
- **Multiple instance support** - run multiple search engines with different configurations
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- **Packages**: `beautifulsoup4`, `requests`
|
|
17
|
+
- **API Access**: Google Custom Search API key and Search Engine ID
|
|
18
|
+
|
|
19
|
+
## Parameters
|
|
20
|
+
|
|
21
|
+
### Required Parameters
|
|
22
|
+
|
|
23
|
+
- `api_key` (string): Google Custom Search API key
|
|
24
|
+
- `search_engine_id` (string): Google Custom Search Engine ID
|
|
25
|
+
|
|
26
|
+
### Optional Parameters
|
|
27
|
+
|
|
28
|
+
- `num_results` (integer, default: 1): Number of search results to return (max: 10)
|
|
29
|
+
- `delay` (float, default: 0): Delay in seconds between web page requests
|
|
30
|
+
- `tool_name` (string, default: "web_search"): Custom name for the search tool (enables multiple instances)
|
|
31
|
+
- `no_results_message` (string): Custom message when no results are found
|
|
32
|
+
- Default: "I couldn't find any results for '{query}'. This might be due to a very specific query or temporary issues. Try rephrasing your search or asking about a different topic."
|
|
33
|
+
- Use `{query}` as placeholder for the search query
|
|
34
|
+
|
|
35
|
+
### Advanced Parameters
|
|
36
|
+
|
|
37
|
+
- `swaig_fields` (dict): Additional SWAIG function configuration
|
|
38
|
+
- `secure` (boolean): Override security settings
|
|
39
|
+
- `fillers` (dict): Language-specific filler phrases during search
|
|
40
|
+
- Any other SWAIG function parameters
|
|
41
|
+
|
|
42
|
+
## Tools Created
|
|
43
|
+
|
|
44
|
+
- **Default**: `web_search` - Search the web for information
|
|
45
|
+
- **Custom**: Uses the `tool_name` parameter value
|
|
46
|
+
|
|
47
|
+
## Usage Examples
|
|
48
|
+
|
|
49
|
+
### Basic Usage
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
# Minimal configuration
|
|
53
|
+
agent.add_skill("web_search", {
|
|
54
|
+
"api_key": "your-google-api-key",
|
|
55
|
+
"search_engine_id": "your-search-engine-id"
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Advanced Configuration
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
# Comprehensive results with delay
|
|
63
|
+
agent.add_skill("web_search", {
|
|
64
|
+
"api_key": "your-google-api-key",
|
|
65
|
+
"search_engine_id": "your-search-engine-id",
|
|
66
|
+
"num_results": 5,
|
|
67
|
+
"delay": 1.0,
|
|
68
|
+
"no_results_message": "Sorry, I couldn't find information about '{query}'. Try a different search term."
|
|
69
|
+
})
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Multiple Instances
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
# General web search
|
|
76
|
+
agent.add_skill("web_search", {
|
|
77
|
+
"api_key": "your-api-key",
|
|
78
|
+
"search_engine_id": "general-search-engine-id",
|
|
79
|
+
"tool_name": "search_general",
|
|
80
|
+
"num_results": 1
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
# News-specific search
|
|
84
|
+
agent.add_skill("web_search", {
|
|
85
|
+
"api_key": "your-api-key",
|
|
86
|
+
"search_engine_id": "news-search-engine-id",
|
|
87
|
+
"tool_name": "search_news",
|
|
88
|
+
"num_results": 3,
|
|
89
|
+
"delay": 0.5
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
# Quick search for fast answers
|
|
93
|
+
agent.add_skill("web_search", {
|
|
94
|
+
"api_key": "your-api-key",
|
|
95
|
+
"search_engine_id": "quick-search-engine-id",
|
|
96
|
+
"tool_name": "quick_search",
|
|
97
|
+
"num_results": 1,
|
|
98
|
+
"delay": 0
|
|
99
|
+
})
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### With Custom Fillers
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
agent.add_skill("web_search", {
|
|
106
|
+
"api_key": "your-api-key",
|
|
107
|
+
"search_engine_id": "your-search-engine-id",
|
|
108
|
+
"swaig_fields": {
|
|
109
|
+
"fillers": {
|
|
110
|
+
"en-US": [
|
|
111
|
+
"Let me search the web for that...",
|
|
112
|
+
"Looking that up online...",
|
|
113
|
+
"Searching the internet now..."
|
|
114
|
+
],
|
|
115
|
+
"es-ES": [
|
|
116
|
+
"Déjame buscar eso en internet...",
|
|
117
|
+
"Buscando en línea..."
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## How It Works
|
|
125
|
+
|
|
126
|
+
1. **Search**: Uses Google Custom Search API to find relevant web pages
|
|
127
|
+
2. **Scrape**: Downloads and extracts readable content from each result page
|
|
128
|
+
3. **Format**: Presents results with titles, URLs, snippets, and extracted content
|
|
129
|
+
4. **Filter**: Removes unwanted elements (scripts, styles, navigation) for clean text
|
|
130
|
+
|
|
131
|
+
## Multiple Instance Support
|
|
132
|
+
|
|
133
|
+
The web_search skill supports multiple instances, allowing you to:
|
|
134
|
+
|
|
135
|
+
- Use different Google search engines for different types of content
|
|
136
|
+
- Have different configurations (number of results, delays) per instance
|
|
137
|
+
- Create specialized search tools (news, products, support, etc.)
|
|
138
|
+
- Customize tool names for clarity (`search_news`, `search_products`, etc.)
|
|
139
|
+
|
|
140
|
+
Each instance is uniquely identified by its `search_engine_id` and `tool_name` combination.
|
|
141
|
+
|
|
142
|
+
## Error Handling
|
|
143
|
+
|
|
144
|
+
- **No Results**: Returns custom `no_results_message` with query placeholder
|
|
145
|
+
- **Network Issues**: Returns friendly error message for timeouts/connectivity issues
|
|
146
|
+
- **Invalid Pages**: Gracefully handles pages that can't be scraped
|
|
147
|
+
- **Rate Limiting**: Built-in delay support to respect API limits
|
|
148
|
+
|
|
149
|
+
## Best Practices
|
|
150
|
+
|
|
151
|
+
1. **For Speed**: Use `num_results: 1` and `delay: 0` for customer service
|
|
152
|
+
2. **For Research**: Use `num_results: 3-5` and `delay: 0.5-1.0` for comprehensive results
|
|
153
|
+
3. **For News**: Use a news-specific search engine ID with higher result count
|
|
154
|
+
4. **Rate Limiting**: Add delays when making frequent searches to respect API quotas
|
|
155
|
+
5. **Custom Messages**: Tailor `no_results_message` to your agent's personality and use case
|
|
156
|
+
|
|
157
|
+
## Getting Google Custom Search Setup
|
|
158
|
+
|
|
159
|
+
1. Create a Google Cloud Project
|
|
160
|
+
2. Enable the Custom Search JSON API
|
|
161
|
+
3. Create a Custom Search Engine at https://cse.google.com/
|
|
162
|
+
4. Get your API key from Google Cloud Console
|
|
163
|
+
5. Get your Search Engine ID from the Custom Search Engine settings
|