# How to Use the Jido Registry for Agent Naming and Lookup

> Learn how to use the Jido Registry for agent naming and lookup in Elixir. Discover helper functions to resolve agent names across your supervision tree.

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

---

**Jido uses Elixir's built-in `Registry` to provide every agent with a stable, unique name that can be resolved across the entire supervision tree, exposing helper functions like `Jido.whereis/2` and `Jido.AgentServer.via_tuple/2` to abstract the low-level Registry API.**

The Jido Registry is a core component of the [agentjido/jido](https://github.com/agentjido/jido) framework that separates agent identity from process state. By leveraging Elixir’s `Registry` with `keys: :unique`, Jido ensures that every agent ID maps to exactly one PID, enabling reliable distributed lookups without tight coupling to process lifecycle.

## How the Jido Registry Works

### Registry Naming Convention

Each Jido instance automatically derives its registry name from the module name. If your Jido module is `MyApp.Jido`, the registry is named `MyApp.Jido.Registry`. This convention is enforced by `Jido.registry_name/1` in [`lib/jido.ex`](https://github.com/agentjido/jido/blob/main/lib/jido.ex), which uses `Module.concat/2` to build the atom:

```elixir

# lib/jido.ex (line 371)

def registry_name(name) do
  Module.concat(name, Registry)
end

```

### Automatic Startup in the Supervision Tree

The registry starts automatically when the Jido supervisor initializes. In [`lib/jido.ex`](https://github.com/agentjido/jido/blob/main/lib/jido.ex) (lines 443-452), the `child_spec/1` function includes the `Registry` process in the supervision tree with `keys: :unique`, ensuring no duplicate agent IDs can exist:

```elixir

# lib/jido.ex (lines 443-452)

def child_spec(opts) do
  %{
    id: __MODULE__,
    start: {__MODULE__, :start_link, [opts]},
    type: :supervisor
  }
end

# Within start_link, the registry is started as:

Registry.start_link(keys: :unique, name: registry_name(module))

```

## Naming Agents with Via Tuples

### Creating Via Tuples for Agent Servers

To register an agent process under the Jido Registry, use the `via_tuple/2` helper in `Jido.AgentServer`. Located in [`lib/jido/agent_server.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent_server.ex) (lines 49-52), this function constructs the standard `{:via, Registry, {registry, id}}` tuple required by `GenServer.start_link/3`:

```elixir

# lib/jido/agent_server.ex (lines 49-52)

def via_tuple(registry, id) do
  {:via, Registry, {registry, id}}
end

```

When starting an agent, pass this tuple as the `name` option:

```elixir
opts = [
  agent: MyAgent,
  id: "agent-123",
  registry: MyApp.Jido.Registry
]

{:ok, pid} = Jido.AgentServer.start_link(opts)

```

### Using the Utility Helpers for Generic Processes

For non-agent processes that still need Jido-compatible naming, [`lib/jido/util.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/util.ex) provides generic `via_tuple/2` and `whereis/2` functions. These work with any `Registry` instance:

```elixir
defmodule MyWorker do
  use GenServer

  def start_link(id) do
    name = Jido.Util.via_tuple(id, registry: MyApp.Jido.Registry)
    GenServer.start_link(__MODULE__, %{}, name: name)
  end
end

```

## Looking Up Agents by Name

### Instance-Level Lookup with Jido.whereis/2

The high-level `Jido.whereis/2` function (defined in [`lib/jido.ex`](https://github.com/agentjido/jido/blob/main/lib/jido.ex), lines 37-44) resolves an agent ID to its PID without requiring knowledge of the underlying registry name. It automatically derives the registry from the Jido module:

```elixir

# lib/jido.ex (lines 37-44)

def whereis(jido, id) do
  registry = registry_name(jido)
  AgentServer.whereis(registry, id)
end

```

Usage:

```elixir
pid = MyApp.Jido.whereis("agent-123")

# => #PID<0.123.0> | nil

```

### Registry-Specific Lookup with AgentServer.whereis/2

For scenarios where you have direct access to the registry module, `Jido.AgentServer.whereis/2` in [`lib/jido/agent_server.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent_server.ex) (lines 33-38) performs the lookup using `Registry.lookup/2`:

```elixir

# lib/jido/agent_server.ex (lines 33-38)

def whereis(registry, id) do
  case Registry.lookup(registry, id) do
    [{pid, _}] -> pid
    [] -> nil
  end
end

```

This is useful when working with multiple Jido instances or custom registries:

```elixir
pid = Jido.AgentServer.whereis(MyApp.Jido.Registry, "agent-123")

```

### Listing All Registered Agents

To enumerate every registered agent in a Jido instance, use `Jido.list_agents/1`. This function uses `Registry.select/2` to return a list of `{id, pid}` tuples:

```elixir
agents = MyApp.Jido.list_agents()

# => [{"agent-123", #PID<0.123.0>}, {"other-agent", #PID<0.124.0>}]

```

## Practical Code Examples

### Starting an Agent with the Default Registry

When you start a Jido instance, the registry starts automatically. Agents started via `start_agent/2` are automatically registered:

```elixir
defmodule MyApp.Jido do
  use Jido, otp_app: :my_app
end

# Start the supervisor (usually in application.ex)

{:ok, _pid} = MyApp.Jido.start_link([])

# Start an agent - automatically registered under MyApp.Jido.Registry

{:ok, _agent_pid} = MyApp.Jido.start_agent(MyAgent, id: "agent-123")

```

### Using a Custom Registry for Testing

Isolate tests by creating a temporary registry:

```elixir
defmodule MyApp.AgentTest do
  use ExUnit.Case

  setup do
    # Create a temporary registry for this test

    {:ok, _registry} = Registry.start_link(keys: :unique, name: __MODULE__.Registry)
    
    # Start agent with custom registry

    opts = [
      agent: MyAgent,
      id: "test-agent",
      registry: __MODULE__.Registry
    ]
    
    {:ok, pid} = Jido.AgentServer.start_link(opts)
    %{agent_pid: pid, registry: __MODULE__.Registry}
  end

  test "can lookup agent in custom registry", %{registry: registry} do
    pid = Jido.AgentServer.whereis(registry, "test-agent")
    assert is_pid(pid)
  end
end

```

### Registering Generic GenServer Processes

Any GenServer can use the Jido registry for naming:

```elixir
defmodule MyWorker do
  use GenServer

  def start_link(id) do
    # Create via tuple using Jido utility

    name = Jido.Util.via_tuple(id, registry: MyApp.Jido.Registry)
    GenServer.start_link(__MODULE__, %{}, name: name)
  end

  def get_state(pid_or_id) do
    GenServer.call(pid_or_id, :get_state)
  end
end

# Usage

{:ok, _pid} = MyWorker.start_link("worker-1")
state = MyWorker.get_state("worker-1")  # Lookup by name works automatically

```

## Summary

- **Automatic Registry Creation**: Every Jido instance creates a dedicated Registry (e.g., `MyApp.Jido.Registry`) via `Jido.registry_name/1` and starts it in the supervision tree via `Jido.child_spec/1`.
- **Via Tuple Naming**: Agents are named using `{:via, Registry, {registry, id}}` tuples generated by `Jido.AgentServer.via_tuple/2` or `Jido.Util.via_tuple/2`.
- **Safe Lookup**: Resolve agent IDs to PIDs using `Jido.whereis/2` (instance-level) or `Jido.AgentServer.whereis/2` (registry-specific), both returning `nil` for missing agents rather than raising.
- **Process Isolation**: The registry stores only identity mappings, not agent state, ensuring state mutations remain contained within the AgentServer process.

## Frequently Asked Questions

### How is the Jido Registry name generated?

The registry name is automatically derived from your Jido module name using `Jido.registry_name/1` in [`lib/jido.ex`](https://github.com/agentjido/jido/blob/main/lib/jido.ex). If your module is `MyApp.Jido`, the registry becomes `MyApp.Jido.Registry` via `Module.concat(name, Registry)`. This convention ensures each Jido instance has an isolated namespace for its agents.

### Can I use a custom Registry for testing?

Yes. While production code typically relies on the auto-generated registry, you can pass a custom `:registry` option to `Jido.AgentServer.start_link/1`, `Jido.AgentServer.via_tuple/2`, and `Jido.AgentServer.whereis/2`. This allows you to start a temporary `Registry` process in your test setup (e.g., `Registry.start_link(keys: :unique, name: MyTest.Registry)`) for complete test isolation.

### What is the difference between Jido.whereis/2 and AgentServer.whereis/2?

`Jido.whereis/2` is the high-level instance method that automatically resolves the registry name from your Jido module (e.g., `MyApp.Jido.whereis("agent-123")`), making it ideal for application code. `Jido.AgentServer.whereis/2` requires you to explicitly pass the registry module as the first argument (e.g., `Jido.AgentServer.whereis(MyApp.Jido.Registry, "agent-123")`), which is useful when working with multiple registries or in library code where the Jido instance isn't available.

### Is the Jido Registry suitable for high-frequency lookups?

Yes. The Jido Registry is a thin wrapper around Elixir's built-in `Registry`, which is implemented in ETS (Erlang Term Storage) and provides O(1) lookup times. Since `Jido.whereis/2` and `Jido.AgentServer.whereis/2` delegate to `Registry.lookup/2`, you can safely use them in hot paths, such as routing messages in Phoenix channels or dispatching work to specific agents in high-throughput pipelines.