Jido.Skill behaviour (Jido v1.1.0-rc)
View SourceDefines the core behavior and structure for Jido Skills, the fundamental building blocks of agent capabilities in the Jido framework.
Overview
Skills encapsulate discrete sets of functionality that agents can use to accomplish tasks. Think of them as feature packs that give agents new abilities - similar to how a person might learn skills like "cooking" or "programming". Each Skill provides:
- Signal routing and handling patterns
- Isolated state management
- Process supervision
- Configuration validation
- Runtime adaptation
Core Concepts
State Isolation
Skills use schema-based state isolation to prevent different capabilities from interfering with each other. Each skill defines:
- A unique
schema_key
for namespace isolation - An
initial_state/0
callback for state setup - Validation rules for configuration
Signal Patterns
Skills define what signals they can handle through pattern matching:
use Jido.Skill,
name: "weather_monitor",
signals: [
input: ["weather.data.*", "weather.alert.**"],
output: ["weather.alert.generated"]
]
Pattern rules:
- Exact matches: "user.created"
- Single wildcards: "user.*.updated"
- Multi-wildcards: "audit.**"
Configuration Management
Skills provide schema-based config validation:
config: [
api_key: [
type: :string,
required: true,
doc: "API key for weather service"
],
update_interval: [
type: :pos_integer,
default: 60_000,
doc: "Update interval in milliseconds"
]
]
Process Supervision
Skills can define child processes through the child_spec/1
callback:
def child_spec(config) do
[
{WeatherAPI.Client, config.api_key},
{MetricsCollector, name: config.metrics_name}
]
end
Usage Example
Here's a complete skill example:
defmodule MyApp.WeatherSkill do
use Jido.Skill,
name: "weather_monitor",
description: "Monitors weather conditions and generates alerts",
category: "monitoring",
tags: ["weather", "alerts"],
vsn: "1.0.0",
schema_key: :weather,
signals: [
input: ["weather.data.*", "weather.alert.**"],
output: ["weather.alert.generated"]
],
config: [
api_key: [type: :string, required: true]
]
def initial_state do
%{
current_conditions: nil,
alert_history: [],
last_update: nil
}
end
def child_spec(config) do
[
{WeatherAPI.Client, config.api_key}
]
end
def handle_signal(%Signal{type: "weather.data.updated"} = signal) do
# Handle weather updates
{:ok, signal}
end
end
Callbacks
Skills implement these callbacks:
initial_state/0
- Returns the skill's initial state mapchild_spec/1
- Returns child process specificationsroutes/0
- Returns signal routing ruleshandle_signal/1
- Processes incoming signalsprocess_result/2
- Post-processes signal handling results
Behavior
The Skill behavior enforces a consistent interface:
@callback initial_state() :: map()
@callback child_spec(config :: map()) :: Supervisor.child_spec() | [Supervisor.child_spec()]
@callback routes() :: [map()]
@callback handle_signal(signal :: Signal.t()) :: {:ok, Signal.t()} | {:error, term()}
@callback process_result(signal :: Signal.t(), result :: term()) ::
{:ok, term()} | {:error, term()}
Configuration
Skills validate their configuration at compile time using these fields:
name
- Unique identifier (required)description
- Human-readable explanationcategory
- Broad classificationtags
- List of searchable tagsvsn
- Version stringschema_key
- State namespace keysignals
- Input/output patternsconfig
- Configuration schema
Best Practices
State Isolation
- Use meaningful schema_key names
- Keep state focused and minimal
- Document state structure
Signal Design
- Use consistent naming patterns
- Document signal formats
- Consider routing efficiency
Configuration
- Validate thoroughly
- Provide good defaults
- Document all options
Process Management
- Supervise child processes
- Handle crashes gracefully
- Monitor resource usage
See Also
Jido.Signal
- Signal structure and validationJido.Error
- Error handlingJido.Agent
- Agent integration
Summary
Functions
Implements the skill behavior and configuration validation.
Gets a skill's configuration schema.
Skills must be defined at compile time, not runtime.
Validates a skill's configuration against its schema.
Validates a signal against a skill's defined patterns.
Types
@type t() :: %Jido.Skill{ category: String.t() | nil, config: map() | nil, description: String.t() | nil, name: String.t(), schema_key: atom() | nil, signals: map() | nil, tags: [String.t()], vsn: String.t() | nil }
Represents a skill's core structure and metadata.
Fields:
name
: Unique identifier for the skilldescription
: Human-readable explanation of purposecategory
: Broad classification for organizationtags
: List of searchable tagsvsn
: Version string for compatibilityschema_key
: Atom key for state namespacesignals
: Input/output signal patternsconfig
: Configuration schema
Callbacks
@callback child_spec(config :: map()) :: Supervisor.child_spec() | [Supervisor.child_spec()]
@callback handle_signal(signal :: Jido.Signal.t()) :: {:ok, Jido.Signal.t()} | {:error, term()}
@callback initial_state() :: map()
@callback process_result(signal :: Jido.Signal.t(), result :: term()) :: {:ok, term()} | {:error, any()}
@callback routes() :: [map()]
Functions
Implements the skill behavior and configuration validation.
This macro:
- Validates configuration at compile time
- Defines metadata accessors
- Provides JSON serialization
- Sets up default implementations
Example
defmodule MySkill do
use Jido.Skill,
name: "my_skill",
schema_key: :my_skill,
signals: [
input: ["my.event.*"],
output: ["my.result.*"]
]
end
@spec get_config_schema(module()) :: {:ok, map()} | {:error, Jido.Error.t()}
Gets a skill's configuration schema.
Parameters
skill_module
: The skill module to inspect
Returns
{:ok, schema}
: The skill's config schema{:error, reason}
: Schema not found
Example
Skill.get_config_schema(WeatherSkill)
@spec new() :: {:error, Jido.Error.t()}
Skills must be defined at compile time, not runtime.
This function always returns an error to enforce compile-time definition.
@spec validate_config(module(), map()) :: {:ok, map()} | {:error, Jido.Error.t()}
Validates a skill's configuration against its schema.
Parameters
skill_module
: The skill module to validateconfig
: Configuration map to validate
Returns
{:ok, validated_config}
: Successfully validated config{:error, reason}
: Validation failed
Example
Skill.validate_config(WeatherSkill, %{
api_key: "abc123",
interval: 1000
})
@spec validate_signal(Jido.Signal.t(), map()) :: :ok | {:error, Jido.Error.t()}
Validates a signal against a skill's defined patterns.
Parameters
signal
: The signal to validatepatterns
: Map of input/output patterns
Returns
:ok
: Signal matches patterns{:error, reason}
: No matching patterns
Example
Skill.validate_signal(
%Signal{type: "weather.data.updated"},
%{input: ["weather.data.*"], output: []}
)