# How to Integrate Jido Agents with OTP Supervision Trees

> Learn to integrate Jido agents with OTP supervision trees using Jido's built-in supervisor for robust agent lifecycle management with standard OTP primitives.

- Repository: [agentjido/jido](https://github.com/agentjido/jido)
- Tags: how-to-guide
- Published: 2026-03-09

---

**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`](https://github.com/agentjido/jido/blob/main/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 in [`lib/jido.ex`](https://github.com/agentjido/jido/blob/main/lib/jido.ex) (lines 38-44), this uses `Registry.lookup/2` under the hood.

- **DynamicSupervisor** – The *AgentSupervisor* that hosts each running agent as a child process using the `Jido.AgentServer` child 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:

```elixir

# 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:

```elixir

# 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`](https://github.com/agentjido/jido/blob/main/lib/jido.ex), lines 94-106) builds a child specification for `Jido.AgentServer` and hands it to the instance's `DynamicSupervisor`:

```elixir

# 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`](https://github.com/agentjido/jido/blob/main/lib/jido.ex):

- **Stop an agent**: Uses `DynamicSupervisor.terminate_child/2` (lines 16-25) via `MyApp.Jido.stop_agent/1`.

- **Find an agent**: Uses `Registry.lookup/2` (lines 38-44) via `MyApp.Jido.whereis/2`.

- **List agents**: Uses `Registry.select/2` (lines 55-60) via `MyApp.Jido.list_agents/0`, returning tuples of `{"agent-id", #PID<...>}`.

- **Count agents**: Uses `DynamicSupervisor.count_children/1` (lines 66-71) via `MyApp.Jido.count_agents/0`.

```elixir

# 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:

```elixir

# 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:

```elixir
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`](https://github.com/agentjido/jido/blob/main/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 your `Application.start/2` children list.
- **Start agents** via `Jido.start_agent/3` (or your instance wrapper), which delegates to `DynamicSupervisor` to spawn `Jido.AgentServer` processes as supervised children.
- **Manage lifecycles** through standard OTP primitives: `Registry.lookup/2` for discovery, `DynamicSupervisor.terminate_child/2` for shutdown, and `Registry.select/2` for enumeration.
- **Create isolated pools** by defining multiple Jido instances with custom `agent_pools` configuration, 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`](https://github.com/agentjido/jido/blob/main/lib/jido/agent_server/child_info.ex) for supervision logic.