| Duration | 60 minutes |
| Prerequisites | Module 2.4 completed |
Objectives
- Create a custom skill using SkillBase
- Package reusable functionality
- Share skills between agents
Setup
Create two files:
weather_skill.py- The custom skilllab2_4_agent.py- The agent using the skill
Part 1: Create Basic Skill (20 min)
Task
Create a weather lookup skill (simulated data).
weather_skill.py
#!/usr/bin/env python3
"""Custom weather skill."""
from signalwire_agents.skills import SkillBase
class WeatherSkill(SkillBase):
"""Skill for weather lookups."""
SKILL_NAME = "weather_lookup"
SKILL_DESCRIPTION = "Look up weather information for cities"
# Simulated weather data
WEATHER_DATA = {
"new york": {"temp": 45, "condition": "cloudy", "humidity": 65},
"los angeles": {"temp": 72, "condition": "sunny", "humidity": 40},
"chicago": {"temp": 38, "condition": "windy", "humidity": 55},
"miami": {"temp": 82, "condition": "sunny", "humidity": 75},
"seattle": {"temp": 52, "condition": "rainy", "humidity": 80},
}
def setup(self):
"""Configure the skill's tools."""
@self.tool(
description="Get current weather for a city",
parameters={
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name"
}
},
"required": ["city"]
}
)
def get_weather(city: str):
city_lower = city.lower()
weather = self.WEATHER_DATA.get(city_lower)
if weather:
return (
f"Weather in {city}: {weather['temp']}°F, "
f"{weather['condition']}, {weather['humidity']}% humidity"
)
return f"Weather data not available for {city}"
@self.tool(
description="Get list of cities with weather data"
)
def list_weather_cities():
cities = list(self.WEATHER_DATA.keys())
return f"Available cities: {', '.join(c.title() for c in cities)}"
Part 2: Use Skill in Agent (15 min)
Task
Create an agent that uses the weather skill.
lab2_4_agent.py
#!/usr/bin/env python3
"""Lab 2.4: Agent using custom skill."""
from signalwire_agents import AgentBase
from weather_skill import WeatherSkill
class WeatherAgent(AgentBase):
def __init__(self):
super().__init__(name="weather-agent")
self.prompt_add_section(
"Role",
"You are a weather information assistant. "
"Help users check weather conditions in various cities."
)
self.prompt_add_section(
"Instructions",
bullets=[
"Use the weather skill to look up conditions",
"If city not found, suggest available cities",
"Provide helpful weather-related advice"
]
)
self.add_language("English", "en-US", "rime.spore")
# Add custom weather skill
self.add_skill(WeatherSkill)
if __name__ == "__main__":
agent = WeatherAgent()
agent.run()
Part 3: Add Configurable Skill (25 min)
Task
Enhance the weather skill to accept configuration options.
Updated weather_skill.py
#!/usr/bin/env python3
"""Custom weather skill with configuration."""
from signalwire_agents.skills import SkillBase
class WeatherSkill(SkillBase):
"""Configurable weather skill."""
SKILL_NAME = "weather_lookup"
SKILL_DESCRIPTION = "Look up weather information for cities"
# Default configuration
DEFAULT_CONFIG = {
"units": "fahrenheit", # or "celsius"
"include_humidity": True,
"include_forecast": False
}
WEATHER_DATA = {
"new york": {"temp_f": 45, "temp_c": 7, "condition": "cloudy", "humidity": 65},
"los angeles": {"temp_f": 72, "temp_c": 22, "condition": "sunny", "humidity": 40},
"chicago": {"temp_f": 38, "temp_c": 3, "condition": "windy", "humidity": 55},
"miami": {"temp_f": 82, "temp_c": 28, "condition": "sunny", "humidity": 75},
"seattle": {"temp_f": 52, "temp_c": 11, "condition": "rainy", "humidity": 80},
}
def setup(self):
"""Configure the skill with options."""
# Merge default config with provided config
config = {**self.DEFAULT_CONFIG, **self.config}
units = config.get("units", "fahrenheit")
include_humidity = config.get("include_humidity", True)
@self.tool(
description="Get current weather for a city",
parameters={
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name"
}
},
"required": ["city"]
}
)
def get_weather(city: str):
city_lower = city.lower()
weather = self.WEATHER_DATA.get(city_lower)
if not weather:
return f"Weather data not available for {city}"
# Format based on configuration
if units == "celsius":
temp = f"{weather['temp_c']}°C"
else:
temp = f"{weather['temp_f']}°F"
result = f"Weather in {city}: {temp}, {weather['condition']}"
if include_humidity:
result += f", {weather['humidity']}% humidity"
return result
@self.tool(description="List available cities")
def list_weather_cities():
cities = list(self.WEATHER_DATA.keys())
return f"Available cities: {', '.join(c.title() for c in cities)}"
Using with Configuration
# In your agent
self.add_skill(
WeatherSkill,
{
"units": "celsius",
"include_humidity": True
}
)
Testing
# Test the agent with skill
swaig-test lab2_4_agent.py --dump-swml
# List tools (should show skill functions)
swaig-test lab2_4_agent.py --list-tools
# Test get_weather
swaig-test lab2_4_agent.py --exec get_weather --city "New York"
# Test list_weather_cities
swaig-test lab2_4_agent.py --exec list_weather_cities
Validation Checklist
- WeatherSkill class inherits from SkillBase
- SKILL_NAME and SKILL_DESCRIPTION are defined
- setup() method registers tools
- Agent successfully loads custom skill
- Configuration options work correctly
- Both tools appear in SWML output
Challenge Extension
Create a “translation” skill that:
- Translates simple phrases (simulated)
- Supports configurable source/target languages
- Has a tool to list supported languages
Submission
Upload both files:
weather_skill.pylab2_4_agent.py