signalwire-agents 0.1.23__py3-none-any.whl → 0.1.25__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 +1 -1
- signalwire_agents/agent_server.py +2 -1
- signalwire_agents/cli/config.py +61 -0
- signalwire_agents/cli/core/__init__.py +1 -0
- signalwire_agents/cli/core/agent_loader.py +254 -0
- signalwire_agents/cli/core/argparse_helpers.py +164 -0
- signalwire_agents/cli/core/dynamic_config.py +62 -0
- signalwire_agents/cli/execution/__init__.py +1 -0
- signalwire_agents/cli/execution/datamap_exec.py +437 -0
- signalwire_agents/cli/execution/webhook_exec.py +125 -0
- signalwire_agents/cli/output/__init__.py +1 -0
- signalwire_agents/cli/output/output_formatter.py +132 -0
- signalwire_agents/cli/output/swml_dump.py +177 -0
- signalwire_agents/cli/simulation/__init__.py +1 -0
- signalwire_agents/cli/simulation/data_generation.py +365 -0
- signalwire_agents/cli/simulation/data_overrides.py +187 -0
- signalwire_agents/cli/simulation/mock_env.py +271 -0
- signalwire_agents/cli/test_swaig.py +522 -2539
- signalwire_agents/cli/types.py +72 -0
- signalwire_agents/core/agent/__init__.py +1 -3
- signalwire_agents/core/agent/config/__init__.py +1 -3
- signalwire_agents/core/agent/prompt/manager.py +25 -7
- signalwire_agents/core/agent/tools/decorator.py +2 -0
- signalwire_agents/core/agent/tools/registry.py +8 -0
- signalwire_agents/core/agent_base.py +492 -3053
- signalwire_agents/core/function_result.py +31 -42
- signalwire_agents/core/mixins/__init__.py +28 -0
- signalwire_agents/core/mixins/ai_config_mixin.py +373 -0
- signalwire_agents/core/mixins/auth_mixin.py +287 -0
- signalwire_agents/core/mixins/prompt_mixin.py +345 -0
- signalwire_agents/core/mixins/serverless_mixin.py +368 -0
- signalwire_agents/core/mixins/skill_mixin.py +55 -0
- signalwire_agents/core/mixins/state_mixin.py +219 -0
- signalwire_agents/core/mixins/tool_mixin.py +295 -0
- signalwire_agents/core/mixins/web_mixin.py +1130 -0
- signalwire_agents/core/skill_manager.py +3 -1
- signalwire_agents/core/swaig_function.py +10 -1
- signalwire_agents/core/swml_service.py +140 -58
- signalwire_agents/skills/README.md +452 -0
- signalwire_agents/skills/api_ninjas_trivia/README.md +215 -0
- signalwire_agents/skills/datasphere/README.md +210 -0
- signalwire_agents/skills/datasphere_serverless/README.md +258 -0
- signalwire_agents/skills/datetime/README.md +132 -0
- signalwire_agents/skills/joke/README.md +149 -0
- signalwire_agents/skills/math/README.md +161 -0
- signalwire_agents/skills/native_vector_search/skill.py +33 -13
- signalwire_agents/skills/play_background_file/README.md +218 -0
- signalwire_agents/skills/spider/README.md +236 -0
- signalwire_agents/skills/spider/__init__.py +4 -0
- signalwire_agents/skills/spider/skill.py +479 -0
- signalwire_agents/skills/swml_transfer/README.md +395 -0
- signalwire_agents/skills/swml_transfer/__init__.py +1 -0
- signalwire_agents/skills/swml_transfer/skill.py +257 -0
- signalwire_agents/skills/weather_api/README.md +178 -0
- signalwire_agents/skills/web_search/README.md +163 -0
- signalwire_agents/skills/wikipedia_search/README.md +228 -0
- {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/METADATA +47 -2
- {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/RECORD +62 -22
- {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/entry_points.txt +1 -1
- signalwire_agents/core/agent/config/ephemeral.py +0 -176
- signalwire_agents-0.1.23.data/data/schema.json +0 -5611
- {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/WHEEL +0 -0
- {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/licenses/LICENSE +0 -0
- {signalwire_agents-0.1.23.dist-info → signalwire_agents-0.1.25.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,452 @@
|
|
1
|
+
# SignalWire Agents Skills System
|
2
|
+
|
3
|
+
This directory contains the modular skills system for SignalWire AI Agents. Skills provide reusable, configurable capabilities that can be easily added to any agent.
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
|
7
|
+
- [Overview](#overview)
|
8
|
+
- [Creating a New Skill](#creating-a-new-skill)
|
9
|
+
- [Skill Structure](#skill-structure)
|
10
|
+
- [Required Files](#required-files)
|
11
|
+
- [Skill Class Implementation](#skill-class-implementation)
|
12
|
+
- [DataMap Integration](#datamap-integration)
|
13
|
+
- [Package Configuration](#package-configuration)
|
14
|
+
- [Testing Your Skill](#testing-your-skill)
|
15
|
+
- [Documentation](#documentation)
|
16
|
+
- [Examples](#examples)
|
17
|
+
- [Best Practices](#best-practices)
|
18
|
+
|
19
|
+
## Overview
|
20
|
+
|
21
|
+
The skills system provides:
|
22
|
+
- **Modular capabilities**: Reusable functionality across agents
|
23
|
+
- **Automatic discovery**: Skills are automatically found and registered
|
24
|
+
- **Configuration validation**: Parameter checking and error handling
|
25
|
+
- **DataMap integration**: Serverless API execution without custom webhooks
|
26
|
+
- **Documentation**: Built-in help and usage information
|
27
|
+
|
28
|
+
## Creating a New Skill
|
29
|
+
|
30
|
+
### Step 1: Create Skill Directory
|
31
|
+
|
32
|
+
Create a new directory under `signalwire_agents/skills/` with your skill name:
|
33
|
+
|
34
|
+
```bash
|
35
|
+
mkdir signalwire_agents/skills/your_skill_name
|
36
|
+
```
|
37
|
+
|
38
|
+
### Step 2: Required Files
|
39
|
+
|
40
|
+
Every skill needs these files:
|
41
|
+
|
42
|
+
```
|
43
|
+
signalwire_agents/skills/your_skill_name/
|
44
|
+
├── __init__.py # Package initialization
|
45
|
+
├── skill.py # Main skill implementation
|
46
|
+
└── README.md # Skill documentation
|
47
|
+
```
|
48
|
+
|
49
|
+
### Step 3: Update Package Configuration
|
50
|
+
|
51
|
+
Add your skill to `pyproject.toml`:
|
52
|
+
|
53
|
+
```toml
|
54
|
+
[tool.setuptools]
|
55
|
+
packages = [
|
56
|
+
# ... existing packages ...
|
57
|
+
"signalwire_agents.skills.your_skill_name"
|
58
|
+
]
|
59
|
+
```
|
60
|
+
|
61
|
+
## Skill Structure
|
62
|
+
|
63
|
+
### `__init__.py`
|
64
|
+
|
65
|
+
Simple package initialization:
|
66
|
+
|
67
|
+
```python
|
68
|
+
"""Your Skill Name for SignalWire Agents"""
|
69
|
+
```
|
70
|
+
|
71
|
+
### `skill.py`
|
72
|
+
|
73
|
+
Main skill implementation inheriting from `SkillBase`:
|
74
|
+
|
75
|
+
```python
|
76
|
+
"""
|
77
|
+
Copyright (c) 2025 SignalWire
|
78
|
+
|
79
|
+
This file is part of the SignalWire AI Agents SDK.
|
80
|
+
|
81
|
+
Licensed under the MIT License.
|
82
|
+
See LICENSE file in the project root for full license information.
|
83
|
+
"""
|
84
|
+
|
85
|
+
from typing import List, Dict, Any
|
86
|
+
|
87
|
+
from signalwire_agents.core.skill_base import SkillBase
|
88
|
+
from signalwire_agents.core.data_map import DataMap
|
89
|
+
from signalwire_agents.core.function_result import SwaigFunctionResult
|
90
|
+
|
91
|
+
|
92
|
+
class YourSkillClass(SkillBase):
|
93
|
+
"""Your skill description"""
|
94
|
+
|
95
|
+
SKILL_NAME = "your_skill_name"
|
96
|
+
SKILL_DESCRIPTION = "Brief description of what your skill does"
|
97
|
+
SKILL_VERSION = "1.0.0"
|
98
|
+
REQUIRED_PACKAGES = [] # List of required Python packages
|
99
|
+
REQUIRED_ENV_VARS = [] # List of required environment variables
|
100
|
+
|
101
|
+
def setup(self) -> bool:
|
102
|
+
"""Setup and validate skill configuration"""
|
103
|
+
# Validate required parameters
|
104
|
+
required_params = ['param1', 'param2']
|
105
|
+
missing_params = [param for param in required_params if not self.params.get(param)]
|
106
|
+
if missing_params:
|
107
|
+
self.logger.error(f"Missing required parameters: {missing_params}")
|
108
|
+
return False
|
109
|
+
|
110
|
+
# Store configuration
|
111
|
+
self.param1 = self.params['param1']
|
112
|
+
self.param2 = self.params.get('param2', 'default_value')
|
113
|
+
|
114
|
+
return True
|
115
|
+
|
116
|
+
def register_tools(self) -> None:
|
117
|
+
"""Register skill tools/functions"""
|
118
|
+
# Implement your tool registration here
|
119
|
+
pass
|
120
|
+
|
121
|
+
def get_hints(self) -> List[str]:
|
122
|
+
"""Return speech recognition hints"""
|
123
|
+
# Currently no hints provided, but you could add them like:
|
124
|
+
# return ["hint1", "hint2", "phrase users might say"]
|
125
|
+
return []
|
126
|
+
|
127
|
+
def get_global_data(self) -> Dict[str, Any]:
|
128
|
+
"""Return global data for DataMap variables"""
|
129
|
+
return {
|
130
|
+
"skill_param": self.param1
|
131
|
+
}
|
132
|
+
|
133
|
+
def get_prompt_sections(self) -> List[Dict[str, Any]]:
|
134
|
+
"""Return prompt sections to add to agent"""
|
135
|
+
return [
|
136
|
+
{
|
137
|
+
"title": "Your Skill Capability",
|
138
|
+
"body": "Description of what the agent can do with this skill.",
|
139
|
+
"bullets": [
|
140
|
+
"Specific capability 1",
|
141
|
+
"Specific capability 2"
|
142
|
+
]
|
143
|
+
}
|
144
|
+
]
|
145
|
+
```
|
146
|
+
|
147
|
+
## Skill Class Implementation
|
148
|
+
|
149
|
+
### Required Class Attributes
|
150
|
+
|
151
|
+
- `SKILL_NAME`: Unique identifier for the skill
|
152
|
+
- `SKILL_DESCRIPTION`: Brief description shown in skill listings
|
153
|
+
- `SKILL_VERSION`: Version string for the skill
|
154
|
+
- `REQUIRED_PACKAGES`: List of Python packages needed
|
155
|
+
- `REQUIRED_ENV_VARS`: List of environment variables needed
|
156
|
+
|
157
|
+
### Required Methods
|
158
|
+
|
159
|
+
#### `setup(self) -> bool`
|
160
|
+
- Validate and store configuration parameters
|
161
|
+
- Return `True` if setup successful, `False` otherwise
|
162
|
+
- Access parameters via `self.params`
|
163
|
+
|
164
|
+
#### `register_tools(self) -> None`
|
165
|
+
- Register SWAIG functions/tools with the agent
|
166
|
+
- Use `self.agent.register_swaig_function()` for custom functions
|
167
|
+
- Use DataMap for external API integration
|
168
|
+
|
169
|
+
#### `get_hints(self) -> List[str]`
|
170
|
+
- Return phrases for speech recognition hints (optional)
|
171
|
+
- Help the ASR system recognize skill-related requests
|
172
|
+
- Can return empty list if no hints are needed
|
173
|
+
|
174
|
+
#### `get_global_data(self) -> Dict[str, Any]`
|
175
|
+
- Return data available to DataMap expressions
|
176
|
+
- Access via `${global.key}` in DataMap configurations
|
177
|
+
|
178
|
+
#### `get_prompt_sections(self) -> List[Dict[str, Any]]`
|
179
|
+
- Return prompt sections to add to the agent
|
180
|
+
- Structure: `{"title": str, "body": str, "bullets": List[str]}`
|
181
|
+
|
182
|
+
## DataMap Integration
|
183
|
+
|
184
|
+
For skills that need to call external APIs, use DataMap for serverless execution:
|
185
|
+
|
186
|
+
```python
|
187
|
+
def register_tools(self) -> None:
|
188
|
+
"""Register DataMap-based tool"""
|
189
|
+
|
190
|
+
tool = (DataMap("tool_name")
|
191
|
+
.description("What this tool does")
|
192
|
+
.parameter("param1", "string", "Parameter description", required=True)
|
193
|
+
.parameter("param2", "string", "Optional parameter", required=False)
|
194
|
+
.webhook("GET", "https://api.example.com/endpoint/${args.param1}",
|
195
|
+
headers={"Authorization": f"Bearer {self.api_key}"})
|
196
|
+
.output(SwaigFunctionResult("Result: ${response.data}"))
|
197
|
+
.error_keys(["error", "message"])
|
198
|
+
)
|
199
|
+
|
200
|
+
self.agent.register_swaig_function(tool.to_swaig_function())
|
201
|
+
```
|
202
|
+
|
203
|
+
### DataMap Features
|
204
|
+
|
205
|
+
- **Dynamic URLs**: Use `${args.param}` for user inputs
|
206
|
+
- **Headers**: Add authentication and other headers
|
207
|
+
- **Response Processing**: Extract data with `${response.field}`
|
208
|
+
- **Error Handling**: Specify error keys to watch for
|
209
|
+
- **Defaults**: Use `${args.param || "default"}` for fallbacks
|
210
|
+
|
211
|
+
## Package Configuration
|
212
|
+
|
213
|
+
After creating your skill, update `pyproject.toml` to include it in the package:
|
214
|
+
|
215
|
+
```toml
|
216
|
+
[tool.setuptools]
|
217
|
+
packages = [
|
218
|
+
"signalwire_agents",
|
219
|
+
"signalwire_agents.prefabs",
|
220
|
+
"signalwire_agents.utils",
|
221
|
+
"signalwire_agents.core",
|
222
|
+
"signalwire_agents.core.state",
|
223
|
+
"signalwire_agents.core.security",
|
224
|
+
"signalwire_agents.skills",
|
225
|
+
"signalwire_agents.skills.web_search",
|
226
|
+
"signalwire_agents.skills.datetime",
|
227
|
+
"signalwire_agents.skills.math",
|
228
|
+
"signalwire_agents.skills.joke",
|
229
|
+
"signalwire_agents.skills.datasphere",
|
230
|
+
"signalwire_agents.skills.wikipedia_search",
|
231
|
+
"signalwire_agents.skills.your_skill_name" # Add your skill here
|
232
|
+
]
|
233
|
+
```
|
234
|
+
|
235
|
+
## Testing Your Skill
|
236
|
+
|
237
|
+
### 1. Install the Package
|
238
|
+
|
239
|
+
```bash
|
240
|
+
pip install . --force-reinstall
|
241
|
+
```
|
242
|
+
|
243
|
+
### 2. Test Skill Discovery
|
244
|
+
|
245
|
+
```python
|
246
|
+
from signalwire_agents.skills.registry import skill_registry
|
247
|
+
|
248
|
+
skill_registry.discover_skills()
|
249
|
+
skills = skill_registry.list_skills()
|
250
|
+
print(f"Found {len(skills)} skills:")
|
251
|
+
for skill in skills:
|
252
|
+
print(f" • {skill['name']}: {skill['description']}")
|
253
|
+
```
|
254
|
+
|
255
|
+
### 3. Test Skill Usage
|
256
|
+
|
257
|
+
```python
|
258
|
+
from signalwire_agents import AgentBase
|
259
|
+
|
260
|
+
class TestAgent(AgentBase):
|
261
|
+
def __init__(self):
|
262
|
+
super().__init__(name="Test Agent", route="/test")
|
263
|
+
|
264
|
+
# Add your skill
|
265
|
+
self.add_skill("your_skill_name", {
|
266
|
+
"param1": "value1",
|
267
|
+
"param2": "value2"
|
268
|
+
})
|
269
|
+
|
270
|
+
agent = TestAgent()
|
271
|
+
# Test that skill loads without errors
|
272
|
+
```
|
273
|
+
|
274
|
+
## Documentation
|
275
|
+
|
276
|
+
### `README.md` Template
|
277
|
+
|
278
|
+
Create a comprehensive README for your skill:
|
279
|
+
|
280
|
+
```markdown
|
281
|
+
# Your Skill Name
|
282
|
+
|
283
|
+
Brief description of what the skill does.
|
284
|
+
|
285
|
+
## Description
|
286
|
+
|
287
|
+
Detailed explanation of the skill's purpose and capabilities.
|
288
|
+
|
289
|
+
## Features
|
290
|
+
|
291
|
+
- Feature 1
|
292
|
+
- Feature 2
|
293
|
+
- Feature 3
|
294
|
+
|
295
|
+
## Requirements
|
296
|
+
|
297
|
+
- Required service accounts or API keys
|
298
|
+
- Any external dependencies
|
299
|
+
|
300
|
+
## Configuration
|
301
|
+
|
302
|
+
### Required Parameters
|
303
|
+
|
304
|
+
- `param1`: Description of required parameter
|
305
|
+
- `param2`: Description of another required parameter
|
306
|
+
|
307
|
+
### Optional Parameters
|
308
|
+
|
309
|
+
- `optional_param`: Description with default value
|
310
|
+
|
311
|
+
## Usage
|
312
|
+
|
313
|
+
### Basic Usage
|
314
|
+
|
315
|
+
```python
|
316
|
+
from signalwire_agents import AgentBase
|
317
|
+
|
318
|
+
class MyAgent(AgentBase):
|
319
|
+
def __init__(self):
|
320
|
+
super().__init__(name="My Agent", route="/agent")
|
321
|
+
|
322
|
+
self.add_skill("your_skill_name", {
|
323
|
+
"param1": "value1",
|
324
|
+
"param2": "value2"
|
325
|
+
})
|
326
|
+
|
327
|
+
agent = MyAgent()
|
328
|
+
agent.serve()
|
329
|
+
```
|
330
|
+
|
331
|
+
### Advanced Configuration
|
332
|
+
|
333
|
+
Examples of advanced usage patterns.
|
334
|
+
|
335
|
+
## Generated Functions
|
336
|
+
|
337
|
+
List the SWAIG functions your skill creates and their parameters.
|
338
|
+
|
339
|
+
## Example Conversations
|
340
|
+
|
341
|
+
Show example interactions between users and agents using your skill.
|
342
|
+
|
343
|
+
## Troubleshooting
|
344
|
+
|
345
|
+
Common issues and solutions.
|
346
|
+
```
|
347
|
+
|
348
|
+
## Examples
|
349
|
+
|
350
|
+
Create example scripts in the `examples/` directory:
|
351
|
+
|
352
|
+
```python
|
353
|
+
#!/usr/bin/env python3
|
354
|
+
"""
|
355
|
+
Your Skill Demo - Description
|
356
|
+
|
357
|
+
This demo shows how to use your skill with the SignalWire Agents SDK.
|
358
|
+
|
359
|
+
Run with: python examples/your_skill_demo.py
|
360
|
+
"""
|
361
|
+
|
362
|
+
from signalwire_agents import AgentBase
|
363
|
+
|
364
|
+
class YourSkillAgent(AgentBase):
|
365
|
+
def __init__(self):
|
366
|
+
super().__init__(
|
367
|
+
name="Your Skill Demo Agent",
|
368
|
+
route="/your-skill-demo"
|
369
|
+
)
|
370
|
+
|
371
|
+
# Configure the agent
|
372
|
+
self.prompt_add_section("Goal", body="What this demo agent does")
|
373
|
+
|
374
|
+
# Add your skill
|
375
|
+
self.add_skill("your_skill_name", {
|
376
|
+
"param1": "demo-value"
|
377
|
+
})
|
378
|
+
|
379
|
+
def main():
|
380
|
+
print("=" * 60)
|
381
|
+
print("YOUR SKILL DEMO")
|
382
|
+
print("=" * 60)
|
383
|
+
|
384
|
+
agent = YourSkillAgent()
|
385
|
+
agent.serve(host="0.0.0.0", port=3000)
|
386
|
+
|
387
|
+
if __name__ == "__main__":
|
388
|
+
main()
|
389
|
+
```
|
390
|
+
|
391
|
+
## Best Practices
|
392
|
+
|
393
|
+
### Configuration
|
394
|
+
- Always validate required parameters in `setup()`
|
395
|
+
- Provide sensible defaults for optional parameters
|
396
|
+
- Use descriptive parameter names
|
397
|
+
- Log errors clearly when configuration fails
|
398
|
+
|
399
|
+
### Error Handling
|
400
|
+
- Return `False` from `setup()` if configuration is invalid
|
401
|
+
- Handle API errors gracefully in DataMap configurations
|
402
|
+
- Use `self.logger` for consistent logging
|
403
|
+
- Provide helpful error messages
|
404
|
+
|
405
|
+
### Documentation
|
406
|
+
- Write clear, comprehensive README files
|
407
|
+
- Include working code examples
|
408
|
+
- Document all parameters and their purposes
|
409
|
+
- Show example conversations
|
410
|
+
|
411
|
+
### Security
|
412
|
+
- Never hard-code API keys or secrets
|
413
|
+
- Validate all user inputs
|
414
|
+
- Use HTTPS for all external API calls
|
415
|
+
- Be careful with user data in logs
|
416
|
+
|
417
|
+
### Performance
|
418
|
+
- Cache expensive operations when possible
|
419
|
+
- Use appropriate timeouts for external calls
|
420
|
+
- Consider rate limiting for API calls
|
421
|
+
- Keep skill setup fast
|
422
|
+
|
423
|
+
### Compatibility
|
424
|
+
- Avoid breaking changes in minor versions
|
425
|
+
- Test with different Python versions
|
426
|
+
- Document any external dependencies
|
427
|
+
- Use standard library when possible
|
428
|
+
|
429
|
+
## Troubleshooting
|
430
|
+
|
431
|
+
### Skill Not Found
|
432
|
+
- Check that the skill directory is in `signalwire_agents/skills/`
|
433
|
+
- Verify `pyproject.toml` includes your skill package
|
434
|
+
- Reinstall the package after changes: `pip install . --force-reinstall`
|
435
|
+
|
436
|
+
### Import Errors
|
437
|
+
- Ensure all required packages are installed
|
438
|
+
- Check import statements in your skill.py
|
439
|
+
- Verify Python path and virtual environment
|
440
|
+
|
441
|
+
### Configuration Errors
|
442
|
+
- Check parameter validation logic in `setup()`
|
443
|
+
- Ensure required parameters are being passed
|
444
|
+
- Look for typos in parameter names
|
445
|
+
|
446
|
+
### DataMap Issues
|
447
|
+
- Validate API endpoints and authentication
|
448
|
+
- Check response format matches your expectations
|
449
|
+
- Test API calls independently first
|
450
|
+
- Use `.error_keys()` to handle API errors
|
451
|
+
|
452
|
+
Remember to always test your skill thoroughly and provide clear documentation for other developers!
|
@@ -0,0 +1,215 @@
|
|
1
|
+
# API Ninjas Trivia Skill
|
2
|
+
|
3
|
+
A configurable skill for getting trivia questions from API Ninjas with customizable categories and multiple tool instances. Supports serverless DataMap webhook execution.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- **Multiple Instances**: Create different tools with unique names and category sets
|
8
|
+
- **Configurable Categories**: Choose from 14 trivia categories
|
9
|
+
- **Dynamic Enum Generation**: Function parameters built from selected categories
|
10
|
+
- **DataMap Efficiency**: Serverless webhook execution, no agent processing load
|
11
|
+
- **API Integration**: Direct webhook to API Ninjas trivia endpoint
|
12
|
+
- **Error Handling**: Graceful fallback for API failures
|
13
|
+
|
14
|
+
## Configuration
|
15
|
+
|
16
|
+
### Basic Structure
|
17
|
+
|
18
|
+
```python
|
19
|
+
agent.add_skill("api_ninjas_trivia", {
|
20
|
+
"tool_name": "your_custom_tool_name",
|
21
|
+
"api_key": "your_api_ninjas_key",
|
22
|
+
"categories": ["category1", "category2", ...] # Optional, defaults to all
|
23
|
+
})
|
24
|
+
```
|
25
|
+
|
26
|
+
### Parameters
|
27
|
+
|
28
|
+
- **tool_name** (string): Custom name for the generated SWAIG function (default: "get_trivia")
|
29
|
+
- **api_key** (string, required): Your API Ninjas API key
|
30
|
+
- **categories** (array, optional): List of category strings to enable (default: all categories)
|
31
|
+
|
32
|
+
### Available Categories
|
33
|
+
|
34
|
+
| Category | Description |
|
35
|
+
|----------|-------------|
|
36
|
+
| `artliterature` | Art and Literature |
|
37
|
+
| `language` | Language |
|
38
|
+
| `sciencenature` | Science and Nature |
|
39
|
+
| `general` | General Knowledge |
|
40
|
+
| `fooddrink` | Food and Drink |
|
41
|
+
| `peopleplaces` | People and Places |
|
42
|
+
| `geography` | Geography |
|
43
|
+
| `historyholidays` | History and Holidays |
|
44
|
+
| `entertainment` | Entertainment |
|
45
|
+
| `toysgames` | Toys and Games |
|
46
|
+
| `music` | Music |
|
47
|
+
| `mathematics` | Mathematics |
|
48
|
+
| `religionmythology` | Religion and Mythology |
|
49
|
+
| `sportsleisure` | Sports and Leisure |
|
50
|
+
|
51
|
+
## Usage Examples
|
52
|
+
|
53
|
+
### All Categories (Default)
|
54
|
+
|
55
|
+
```python
|
56
|
+
agent.add_skill("api_ninjas_trivia", {
|
57
|
+
"tool_name": "get_trivia",
|
58
|
+
"api_key": "your_api_key"
|
59
|
+
})
|
60
|
+
```
|
61
|
+
|
62
|
+
**Generated Tool**: `get_trivia(category)`
|
63
|
+
**Actions**: All 14 categories available
|
64
|
+
|
65
|
+
### Science & Math Only
|
66
|
+
|
67
|
+
```python
|
68
|
+
agent.add_skill("api_ninjas_trivia", {
|
69
|
+
"tool_name": "get_science_trivia",
|
70
|
+
"api_key": "your_api_key",
|
71
|
+
"categories": ["sciencenature", "mathematics"]
|
72
|
+
})
|
73
|
+
```
|
74
|
+
|
75
|
+
**Generated Tool**: `get_science_trivia(category)`
|
76
|
+
**Actions**: `["sciencenature", "mathematics"]`
|
77
|
+
|
78
|
+
### Entertainment Trivia
|
79
|
+
|
80
|
+
```python
|
81
|
+
agent.add_skill("api_ninjas_trivia", {
|
82
|
+
"tool_name": "get_entertainment_trivia",
|
83
|
+
"api_key": "your_api_key",
|
84
|
+
"categories": ["entertainment", "music", "toysgames"]
|
85
|
+
})
|
86
|
+
```
|
87
|
+
|
88
|
+
**Generated Tool**: `get_entertainment_trivia(category)`
|
89
|
+
**Actions**: `["entertainment", "music", "toysgames"]`
|
90
|
+
|
91
|
+
### Geography & History
|
92
|
+
|
93
|
+
```python
|
94
|
+
agent.add_skill("api_ninjas_trivia", {
|
95
|
+
"tool_name": "get_geography_trivia",
|
96
|
+
"api_key": "your_api_key",
|
97
|
+
"categories": ["geography", "historyholidays", "peopleplaces"]
|
98
|
+
})
|
99
|
+
```
|
100
|
+
|
101
|
+
**Generated Tool**: `get_geography_trivia(category)`
|
102
|
+
**Actions**: `["geography", "historyholidays", "peopleplaces"]`
|
103
|
+
|
104
|
+
## Generated SWAIG Function
|
105
|
+
|
106
|
+
For the science & math example above, the skill generates:
|
107
|
+
|
108
|
+
```json
|
109
|
+
{
|
110
|
+
"function": "get_science_trivia",
|
111
|
+
"description": "Get trivia questions for get science trivia",
|
112
|
+
"parameters": {
|
113
|
+
"type": "object",
|
114
|
+
"properties": {
|
115
|
+
"category": {
|
116
|
+
"type": "string",
|
117
|
+
"description": "Category for trivia question. Options: sciencenature: Science and Nature; mathematics: Mathematics",
|
118
|
+
"enum": ["sciencenature", "mathematics"]
|
119
|
+
}
|
120
|
+
},
|
121
|
+
"required": ["category"]
|
122
|
+
},
|
123
|
+
"data_map": {
|
124
|
+
"webhook": {
|
125
|
+
"url": "https://api.api-ninjas.com/v1/trivia?category=%{args.category}",
|
126
|
+
"method": "GET",
|
127
|
+
"headers": {
|
128
|
+
"X-Api-Key": "your_api_key"
|
129
|
+
}
|
130
|
+
},
|
131
|
+
"output": {
|
132
|
+
"response": "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."
|
133
|
+
},
|
134
|
+
"error_keys": ["error"],
|
135
|
+
"fallback_output": {
|
136
|
+
"response": "Sorry, I cannot get trivia questions right now. Please try again later."
|
137
|
+
}
|
138
|
+
}
|
139
|
+
}
|
140
|
+
```
|
141
|
+
|
142
|
+
## Execution Flow
|
143
|
+
|
144
|
+
1. **AI calls function**: `get_science_trivia(category: "mathematics")`
|
145
|
+
2. **DataMap webhook**: `GET https://api.api-ninjas.com/v1/trivia?category=mathematics`
|
146
|
+
3. **API response**: `[{"category": "Mathematics", "question": "What is 2+2?", "answer": "4"}]`
|
147
|
+
4. **AI responds**: "Category Mathematics question: What is 2+2? Answer: 4, be sure to give the user time to answer before saying the answer."
|
148
|
+
|
149
|
+
## Multiple Instances
|
150
|
+
|
151
|
+
You can add multiple instances for different use cases:
|
152
|
+
|
153
|
+
```python
|
154
|
+
# General trivia with all categories
|
155
|
+
agent.add_skill("api_ninjas_trivia", {
|
156
|
+
"tool_name": "get_trivia",
|
157
|
+
"api_key": "your_api_key"
|
158
|
+
})
|
159
|
+
|
160
|
+
# Science-focused trivia
|
161
|
+
agent.add_skill("api_ninjas_trivia", {
|
162
|
+
"tool_name": "get_science_trivia",
|
163
|
+
"api_key": "your_api_key",
|
164
|
+
"categories": ["sciencenature", "mathematics"]
|
165
|
+
})
|
166
|
+
|
167
|
+
# Entertainment trivia
|
168
|
+
agent.add_skill("api_ninjas_trivia", {
|
169
|
+
"tool_name": "get_fun_trivia",
|
170
|
+
"api_key": "your_api_key",
|
171
|
+
"categories": ["entertainment", "music", "toysgames", "sportsleisure"]
|
172
|
+
})
|
173
|
+
|
174
|
+
# Educational trivia
|
175
|
+
agent.add_skill("api_ninjas_trivia", {
|
176
|
+
"tool_name": "get_educational_trivia",
|
177
|
+
"api_key": "your_api_key",
|
178
|
+
"categories": ["geography", "historyholidays", "artliterature", "language"]
|
179
|
+
})
|
180
|
+
```
|
181
|
+
|
182
|
+
This creates four separate tools: `get_trivia`, `get_science_trivia`, `get_fun_trivia`, and `get_educational_trivia`.
|
183
|
+
|
184
|
+
## API Integration
|
185
|
+
|
186
|
+
The skill integrates directly with API Ninjas trivia endpoint:
|
187
|
+
|
188
|
+
- **Endpoint**: `https://api.api-ninjas.com/v1/trivia`
|
189
|
+
- **Method**: GET
|
190
|
+
- **Parameters**: `category` (from enum)
|
191
|
+
- **Headers**: `X-Api-Key` with your API key
|
192
|
+
- **Response**: Array with question, answer, and category
|
193
|
+
|
194
|
+
## Benefits
|
195
|
+
|
196
|
+
- **Reusable**: Same skill supports different category combinations
|
197
|
+
- **Configurable**: Easy to add/remove categories without code changes
|
198
|
+
- **Efficient**: DataMap webhook execution, no agent load
|
199
|
+
- **Type Safe**: Enum parameters prevent invalid categories
|
200
|
+
- **Error Handling**: Graceful fallback for API failures
|
201
|
+
- **Maintainable**: Centralized trivia logic
|
202
|
+
|
203
|
+
## Error Handling
|
204
|
+
|
205
|
+
- **Invalid Categories**: Validation at skill initialization
|
206
|
+
- **API Failures**: Fallback response for network/API issues
|
207
|
+
- **Missing API Key**: Clear error message during setup
|
208
|
+
|
209
|
+
## Implementation Notes
|
210
|
+
|
211
|
+
- Categories are validated against the official API Ninjas list
|
212
|
+
- Enum values use exact API category names
|
213
|
+
- Human-readable descriptions are auto-generated
|
214
|
+
- Instance keys combine skill name and tool name for uniqueness
|
215
|
+
- API key is stored securely in DataMap headers
|