How to Integrate Jido Agents with OTP Supervision Trees
Jido provides a built-in OTP supervisor that embeds directly into your application supervision tree, combining a Task.Supervisor, Registry, and DynamicSupervisor to manage agent lifecycles with standard OTP primitives.
The agentjido/jido library implements autonomous agents as pure Elixir functions while delegating all process management to battle-tested OTP supervisors. When you integrate Jido agents with OTP supervision trees, you gain automatic restarts, graceful shutdowns, and full supervision-tree introspection without sacrificing the isolation of your agent logic.
Understanding Jido's OTP Architecture
The core Jido module in lib/jido.ex implements the Supervisor behaviour and wires together three OTP components that handle every aspect of agent runtime management.
The Three Core Components
Each Jido instance creates its own isolated supervision infrastructure:
-
Task.Supervisor – Runs asynchronous work such as scheduled actions and background tasks without blocking the agent's main process.
-
Registry – Stores a mapping from an agent's id (a string) to its PID, enabling fast lookups via
Jido.whereis/2. According to the source code inlib/jido.ex(lines 38-44), this usesRegistry.lookup/2under the hood. -
DynamicSupervisor – The AgentSupervisor that hosts each running agent as a child process using the
Jido.AgentServerchild spec. This is the component that enables dynamic agent spawning with full OTP supervision semantics.
When you define a Jido instance (e.g., MyApp.Jido), the system automatically creates MyApp.Jido.Registry, MyApp.Jido.TaskSupervisor, and MyApp.Jido.AgentSupervisor under your application's supervisor.
Adding Jido to Your Application Supervision Tree
Integration requires two steps: defining a Jido instance module and adding it to your application's supervision tree.
First, define the Jido instance module using the use Jido macro with your OTP application name:
# lib/my_app/jido.ex
defmodule MyApp.Jido do
use Jido, otp_app: :my_app
end
This single declaration creates the Registry, TaskSupervisor, and DynamicSupervisor under the instance's namespace.
Next, add this module to your Application.start/2 callback:
# lib/my_app/application.ex
defmodule MyApp.Application do
use Application
def start(_type, _args) do
children = [
MyApp.Repo,
# Insert the Jido instance here
MyApp.Jido
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
end
Because MyApp.Jido implements the Supervisor behaviour, you can nest it under any other supervisor (e.g., OneForOne or RestForOne) and combine it with your own workers.
Starting and Managing Agents
Once integrated, starting an agent requires a single call to your instance's start_agent/2 function, which delegates to the underlying OTP primitives.
Starting Agents via DynamicSupervisor
The Jido.start_agent/3 function (implemented in lib/jido.ex, lines 94-106) builds a child specification for Jido.AgentServer and hands it to the instance's DynamicSupervisor:
# Start a Counter agent with a custom identifier
{:ok, pid} = MyApp.Jido.start_agent(MyApp.CounterAgent, id: "counter-1")
Internally, this uses DynamicSupervisor.start_child/2 to spawn the agent process under MyApp.Jido.AgentSupervisor, ensuring it inherits the supervision tree's restart policies.
Agent Lifecycle Operations
All lifecycle operations delegate to standard OTP primitives, as implemented in lib/jido.ex:
-
Stop an agent: Uses
DynamicSupervisor.terminate_child/2(lines 16-25) viaMyApp.Jido.stop_agent/1. -
Find an agent: Uses
Registry.lookup/2(lines 38-44) viaMyApp.Jido.whereis/2. -
List agents: Uses
Registry.select/2(lines 55-60) viaMyApp.Jido.list_agents/0, returning tuples of{"agent-id", #PID<...>}. -
Count agents: Uses
DynamicSupervisor.count_children/1(lines 66-71) viaMyApp.Jido.count_agents/0.
# Find the PID by its ID
pid = MyApp.Jido.whereis("counter-1")
# List all agents registered under this Jido instance
agents = MyApp.Jido.list_agents()
# Stop a specific agent
:ok = MyApp.Jido.stop_agent("counter-1")
Advanced Supervision Patterns
You can create dedicated supervisors that manage isolated agent pools, for example separating "payment" agents from general workers.
Creating Dedicated Agent Pools
Define a separate Jido instance with the agent_pools option:
# lib/my_app/payment_jido.ex
defmodule MyApp.PaymentJido do
use Jido,
otp_app: :my_app,
agent_pools: [{:payment_pool, max_concurrency: 10}]
end
Add this to your application supervisor alongside the default instance:
children = [
MyApp.Jido,
MyApp.PaymentJido # separate pool, separate registry
]
Now MyApp.PaymentJido.start_agent/2 places agents under MyApp.PaymentJido.AgentSupervisor, completely isolated from the default pool's registry and supervisor.
Summary
- Jido implements the OTP Supervisor behaviour in
lib/jido.ex, embedding Task.Supervisor, Registry, and DynamicSupervisor components for each instance. - Add a Jido instance to your supervision tree by defining a module with
use Jido, otp_app: :my_app, then including it in yourApplication.start/2children list. - Start agents via
Jido.start_agent/3(or your instance wrapper), which delegates toDynamicSupervisorto spawnJido.AgentServerprocesses as supervised children. - Manage lifecycles through standard OTP primitives:
Registry.lookup/2for discovery,DynamicSupervisor.terminate_child/2for shutdown, andRegistry.select/2for enumeration. - Create isolated pools by defining multiple Jido instances with custom
agent_poolsconfiguration, each with separate registries and supervisors.
Frequently Asked Questions
How do I start a Jido agent under a custom supervisor?
Define a dedicated Jido instance module using use Jido with the agent_pools option, then add this instance to your application supervisor's children list alongside or instead of the default instance. Each instance creates its own named Registry and DynamicSupervisor.
What OTP primitives does Jido use for agent discovery?
Jido uses Registry.lookup/2 (exposed via Jido.whereis/2) to map string agent IDs to PIDs, and Registry.select/2 (exposed via Jido.list_agents/0) for listing all registered agents. These operations run in constant time against the ETS tables managed by the instance's Registry.
Can I nest multiple Jido instances in the same supervision tree?
Yes. Because each Jido instance creates its own uniquely named Registry and DynamicSupervisor (e.g., MyApp.Jido.Registry vs. MyApp.PaymentJido.Registry), you can run multiple isolated pools under a single OTP supervisor without name collisions.
How does Jido handle agent crashes and restarts?
Agents run as Jido.AgentServer children under a DynamicSupervisor, which provides OTP-compliant process supervision. The DynamicSupervisor handles restart semantics according to the child specifications, while metadata about each child (including id, tag, and parent relationships) is tracked in lib/jido/agent_server/child_info.ex for supervision logic.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →