Jido.Discovery (Jido v1.1.0-rc.2)
View SourceThe Discovery module is Jido's component registry system, providing efficient caching and lookup of system components like Actions, Sensors, Agents, and Skills. Think of it as a "service registry" that helps different parts of your system find and interact with each other.
Core Concepts
Component Discovery
Discovery works by scanning all loaded applications for components that implement Jido's metadata protocols. It automatically finds and indexes:
- Actions - Discrete units of work
- Sensors - Event monitoring components
- Agents - Autonomous workers
- Skills - Reusable capability packs
- Demos - Example implementations - used in the Jido Workbench (https://github.com/agentjido/jido_workbench)
The module uses Erlang's :persistent_term
for optimal lookup performance
Component Metadata
Each discovered component includes the following metadata:
%{
module: MyApp.CoolAction, # The actual module
name: "cool_action", # Human-readable name
description: "Does cool stuff", # What it does
slug: "abc123de", # Unique identifier
category: :utility, # Broad classification
tags: [:cool, :stuff] # Searchable tags
}
Usage Examples
Basic Component Lookup
Find components by their unique slugs:
# Find a specific action
case Discovery.get_action_by_slug("abc123de") do
%{module: module} ->
# Use the action module
{:ok, result} = module.run()
nil ->
# Handle missing action
end
# Find a sensor
sensor = Discovery.get_sensor_by_slug("def456gh")
Filtered Component Lists
Get filtered lists of components:
# List all monitoring sensors
sensors = Discovery.list_sensors(
category: :monitoring,
tag: :metrics
)
# Get the first 10 utility actions
actions = Discovery.list_actions(
category: :utility,
limit: 10
)
# Search agents by name
agents = Discovery.list_agents(
name: "processor",
offset: 5,
limit: 5
)
Cache Management
Control the discovery cache lifecycle:
# Initialize cache (usually done at startup)
:ok = Discovery.init()
# Force cache refresh if needed
:ok = Discovery.refresh()
# Check last update time
{:ok, last_updated} = Discovery.last_updated()
Component Registration
Components are automatically discovered when they:
- Are loaded in any application in the system
- Implement the appropriate metadata callback
- Include required metadata fields
Example component:
defmodule MyApp.CoolAction do
use Jido.Action,
name: "cool_action",
description: "Does cool stuff",
category: :utility,
tags: [:cool, :stuff]
# Metadata is automatically generated from use params
# def __action_metadata__ do
# %{
# name: "cool_action",
# description: "Does cool stuff",
# category: :utility,
# tags: [:cool, :stuff]
# }
# end
end
Cache Structure
The discovery cache maintains separate collections for each component type:
%{
version: "1.0", # Cache format version
last_updated: ~U[...], # Last refresh timestamp
actions: [...], # List of actions
sensors: [...], # List of sensors
agents: [...], # List of agents
skills: [...], # List of skills
demos: [...] # List of demos
}
Filtering Options
All list functions support these filters:
:limit
- Maximum results to return:offset
- Results to skip (pagination):name
- Filter by name (partial match):description
- Filter by description (partial match):category
- Filter by category (exact match):tag
- Filter by tag (must have exact tag)
Important Notes
- Cache is shared across all processes
- Components must be loaded before discovery
- Metadata changes require cache refresh
- Slug generation is deterministic
- Filter options are additive (AND logic)
See Also
Jido.Action
- Action component behaviorJido.Sensor
- Sensor component behaviorJido.Agent
- Agent component behaviorJido.Skill
- Skill component behavior
Summary
Functions
Retrieves an Action by its slug.
Retrieves an Agent by its slug.
Retrieves a Demo by its slug.
Retrieves a Sensor by its slug.
Retrieves a Skill by its slug.
Initializes the discovery cache. Should be called during application startup.
Gets the last time the cache was updated.
Lists all Actions with optional filtering and pagination.
Lists all Agents with optional filtering and pagination.
Lists all Demos with optional filtering and pagination.
Lists all Sensors with optional filtering and pagination.
Lists all Skills with optional filtering and pagination.
Forces a refresh of the discovery cache.
Types
@type cache_entry() :: %{ version: String.t(), last_updated: DateTime.t(), actions: [component_metadata()], sensors: [component_metadata()], agents: [component_metadata()], skills: [component_metadata()], demos: [component_metadata()] }
@type component_type() :: :action | :sensor | :agent | :skill | :demo
Functions
@spec get_action_by_slug(String.t()) :: component_metadata() | nil
Retrieves an Action by its slug.
Parameters
slug
: A string representing the unique identifier of the Action.
Returns
The Action metadata if found, otherwise nil
.
Examples
iex> Jido.get_action_by_slug("abc123de")
%{module: MyApp.SomeAction, name: "some_action", description: "Does something", slug: "abc123de"}
iex> Jido.get_action_by_slug("nonexistent")
nil
@spec get_agent_by_slug(String.t()) :: component_metadata() | nil
Retrieves an Agent by its slug.
Parameters
slug
: A string representing the unique identifier of the Agent.
Returns
The Agent metadata if found, otherwise nil
.
Examples
iex> Jido.get_agent_by_slug("ghi789jk")
%{module: MyApp.SomeAgent, name: "some_agent", description: "Represents an agent", slug: "ghi789jk"}
iex> Jido.get_agent_by_slug("nonexistent")
nil
@spec get_demo_by_slug(String.t()) :: component_metadata() | nil
Retrieves a Demo by its slug.
Parameters
slug
: A string representing the unique identifier of the Demo.
Returns
The Demo metadata if found, otherwise nil
.
Examples
iex> Jido.get_demo_by_slug("mno345pq")
%{module: MyApp.SomeDemo, name: "some_demo", description: "Demonstrates something", slug: "mno345pq"}
iex> Jido.get_demo_by_slug("nonexistent")
nil
@spec get_sensor_by_slug(String.t()) :: component_metadata() | nil
Retrieves a Sensor by its slug.
Parameters
slug
: A string representing the unique identifier of the Sensor.
Returns
The Sensor metadata if found, otherwise nil
.
Examples
iex> Jido.get_sensor_by_slug("def456gh")
%{module: MyApp.SomeSensor, name: "some_sensor", description: "Monitors something", slug: "def456gh"}
iex> Jido.get_sensor_by_slug("nonexistent")
nil
@spec get_skill_by_slug(String.t()) :: component_metadata() | nil
Retrieves a Skill by its slug.
Parameters
slug
: A string representing the unique identifier of the Skill.
Returns
The Skill metadata if found, otherwise nil
.
Examples
iex> Jido.get_skill_by_slug("jkl012mn")
%{module: MyApp.SomeSkill, name: "some_skill", description: "Provides some capability", slug: "jkl012mn"}
iex> Jido.get_skill_by_slug("nonexistent")
nil
@spec init() :: :ok | {:error, term()}
Initializes the discovery cache. Should be called during application startup.
Returns
:ok
if cache was initialized successfully{:error, reason}
if initialization failed
@spec last_updated() :: {:ok, DateTime.t()} | {:error, :not_initialized}
Gets the last time the cache was updated.
Returns
{:ok, datetime}
with the last update time{:error, :not_initialized}
if cache hasn't been initialized
@spec list_actions(keyword()) :: [component_metadata()]
Lists all Actions with optional filtering and pagination.
Parameters
opts
: A keyword list of options for filtering and pagination. Available options::limit
: Maximum number of results to return.:offset
: Number of results to skip before starting to return.:name
: Filter Actions by name (partial match).:description
: Filter Actions by description (partial match).:category
: Filter Actions by category (exact match).:tag
: Filter Actions by tag (must have the exact tag).
Returns
A list of Action metadata.
Examples
iex> Jido.list_actions(limit: 10, offset: 5, category: :utility)
[%{module: MyApp.SomeAction, name: "some_action", description: "Does something", slug: "abc123de", category: :utility}]
@spec list_agents(keyword()) :: [component_metadata()]
Lists all Agents with optional filtering and pagination.
Parameters
opts
: A keyword list of options for filtering and pagination. Available options::limit
: Maximum number of results to return.:offset
: Number of results to skip before starting to return.:name
: Filter Agents by name (partial match).:description
: Filter Agents by description (partial match).:category
: Filter Agents by category (exact match).:tag
: Filter Agents by tag (must have the exact tag).
Returns
A list of Agent metadata.
Examples
iex> Jido.list_agents(limit: 10, offset: 5, category: :business)
[%{module: MyApp.SomeAgent, name: "some_agent", description: "Represents an agent", slug: "ghi789jk", category: :business}]
@spec list_demos(keyword()) :: [component_metadata()]
Lists all Demos with optional filtering and pagination.
Parameters
opts
: A keyword list of options for filtering and pagination. Available options::limit
: Maximum number of results to return.:offset
: Number of results to skip before starting to return.:name
: Filter Demos by name (partial match).:description
: Filter Demos by description (partial match).:category
: Filter Demos by category (exact match).:tag
: Filter Demos by tag (must have the exact tag).
Returns
A list of Demo metadata.
Examples
iex> Jido.list_demos(limit: 10, offset: 5, category: :example)
[%{module: MyApp.SomeDemo, name: "some_demo", description: "Demonstrates something", slug: "mno345pq", category: :example}]
@spec list_sensors(keyword()) :: [component_metadata()]
Lists all Sensors with optional filtering and pagination.
Parameters
opts
: A keyword list of options for filtering and pagination. Available options::limit
: Maximum number of results to return.:offset
: Number of results to skip before starting to return.:name
: Filter Sensors by name (partial match).:description
: Filter Sensors by description (partial match).:category
: Filter Sensors by category (exact match).:tag
: Filter Sensors by tag (must have the exact tag).
Returns
A list of Sensor metadata.
Examples
iex> Jido.list_sensors(limit: 10, offset: 5, category: :monitoring)
[%{module: MyApp.SomeSensor, name: "some_sensor", description: "Monitors something", slug: "def456gh", category: :monitoring}]
@spec list_skills(keyword()) :: [component_metadata()]
Lists all Skills with optional filtering and pagination.
Parameters
opts
: A keyword list of options for filtering and pagination. Available options::limit
: Maximum number of results to return.:offset
: Number of results to skip before starting to return.:name
: Filter Skills by name (partial match).:description
: Filter Skills by description (partial match).:category
: Filter Skills by category (exact match).:tag
: Filter Skills by tag (must have the exact tag).
Returns
A list of Skill metadata.
Examples
iex> Jido.list_skills(limit: 10, offset: 5, category: :capability)
[%{module: MyApp.SomeSkill, name: "some_skill", description: "Provides some capability", slug: "jkl012mn", category: :capability}]
@spec refresh() :: :ok | {:error, term()}
Forces a refresh of the discovery cache.
Returns
:ok
if cache was refreshed successfully{:error, reason}
if refresh failed