Skills Overview
View SourceIntroduction
Skills are a module to group a set of Routing rules, Sensors and Actions into a Plugin of functionality for a Jido Agent. As your agents grow and get more sophisticated, the intent is to support just adding a "Chat Skill" or "Database Skill" to an Agent that accepts a few customization parameters - empowering your agent with a useful set of functionality very easily.
A Skill encapsulates:
- Signal routing and handling patterns
- State management and isolation
- Process supervision
- Configuration management
- Runtime adaptation
Core Concepts
1. Skill Structure
A Skill is defined by creating a module that uses the use Jido.Skill
macro.
defmodule MyApp.WeatherMonitorSkill do
use Jido.Skill,
name: "weather_monitor",
description: "Monitors weather conditions and generates alerts",
category: "monitoring",
tags: ["weather", "alerts"],
vsn: "1.0.0",
# An optional schema key to namespace the skill's state
opts_key: :weather,
# An optional list of signals the skill will handle
signals: [
input: ["weather.data.received", "weather.alert.*"],
output: ["weather.alert.generated"]
],
# An optional configuration schema for the skill
config: [
weather_api: [
type: :map,
required: true,
doc: "Weather API configuration"
]
]
end
Let's break down each component:
name
: Unique identifier for the skill (required)description
: Human-readable explanation of the skill's purposecategory
: Broad classification for organizationtags
: List of searchable tagsvsn
: Version string for compatibility checkingopts_key
: Atom key for state namespace isolationsignals
: Input/output signal patterns the skill handlesconfig
: Configuration schema for validation
2. State Management
Skills use opts_key
for state namespace isolation. This prevents different skills from accidentally interfering with each other's state:
def initial_state do
%{
current_conditions: nil,
alert_history: [],
last_update: nil
}
end
This state will be stored under the skill's opts_key
in the agent's state map:
%{
weather: %{ # Matches opts_key
current_conditions: nil,
alert_history: [],
last_update: nil
}
}
3. Signal Routing
Skills define signal routing patterns using a combination of exact matches, wildcards, and pattern matching functions:
def router do
[
# High priority alerts
%{
path: "weather.alert.**",
instruction: %{
action: Actions.GenerateWeatherAlert
},
priority: 100
},
# Process incoming data
%{
path: "weather.data.received",
instruction: %{
action: Actions.ProcessWeatherData
}
},
# Match severe conditions
%{
path: "weather.condition.*",
match: fn signal ->
get_in(signal.data, [:severity]) >= 3
end,
instruction: %{
action: Actions.GenerateWeatherAlert
},
priority: 75
}
]
end
Building Skills
Step 1: Define the Skill Module
defmodule MyApp.DataProcessingSkill do
use Jido.Skill,
name: "data_processor",
description: "Processes and transforms data streams",
opts_key: :processor,
signals: [
input: ["data.received.*", "data.transform.*"],
output: ["data.processed.*"]
],
config: [
batch_size: [
type: :pos_integer,
default: 100,
doc: "Number of items to process in each batch"
]
]
end
Step 2: Implement Required Callbacks
# Initial state for the skill's namespace
def initial_state do
%{
processed_count: 0,
last_batch: nil,
error_count: 0
}
end
# Child processes to supervise, such as custom Sensors
def child_spec(config) do
[
{DataProcessor.BatchWorker,
[
name: "batch_worker",
batch_size: config.batch_size
]}
]
end
# Signal routing rules
def router do
[
%{
path: "data.received.*",
instruction: %{
action: Actions.ProcessData
}
}
]
end
Step 3: Define Actions
defmodule MyApp.DataProcessingSkill.Actions do
defmodule ProcessData do
use Jido.Action,
name: "process_data",
description: "Processes incoming data batch",
schema: [
data: [type: {:list, :map}, required: true]
]
def run(%{data: data}, context) do
# Access skill config from context
batch_size = get_in(context, [:config, :batch_size])
# Process data...
{:ok, %{
processed: transformed_data,
count: length(transformed_data)
}}
end
end
end
Best Practices
State Isolation
- Use meaningful
opts_key
names - Keep state focused and minimal
- Document state structure
- Consider persistence needs
- Use meaningful
Signal Design
- Use consistent naming patterns
- Document signal formats
- Include necessary context
- Consider routing efficiency
Configuration
- Validate thoroughly
- Provide good defaults
- Document all options
- Consider runtime changes
Process Management
- Supervise child processes
- Handle crashes gracefully
- Monitor resource usage
- Consider distribution
Sharing and Distribution
Skills are designed to be shared and reused across different Jido applications. They act as plugins that can extend agent capabilities:
Package as Library
- Create dedicated package
- Document dependencies
- Version appropriately
- Include examples
Distribution
- Publish to Hex.pm
- Document installation
- Provide configuration guide
- Include integration examples
Example Shared Skills
Some common types of shared skills:
Integration Skills
- Database connectors
- API clients
- Message queue adapters
- File system monitors
Processing Skills
- Data transformation
- Content analysis
- Format conversion
- Batch processing
Monitoring Skills
- System metrics
- Performance tracking
- Error detection
- Health checks