# How to Handle Parent-Child Agent Hierarchies in Jido: A Complete Guide

> Master parent child agent hierarchies in Jido using data directives like SpawnAgent and StopChild. Discover efficient agent management without OTP supervision trees.

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

---

**Jido manages parent-child agent hierarchies through pure data directives like `SpawnAgent` and `StopChild`, with the `AgentServer` handling runtime side-effects such as process monitoring and signal routing without requiring OTP supervision trees.**

Jido is an Elixir framework for building agent-based systems where pure functional logic meets runtime orchestration. Unlike traditional OTP applications that rely on nested supervision trees, Jido implements **parent-child agent hierarchies** entirely through directives and internal state management. This approach enables flexible, dynamic topologies that remain testable and deterministic while maintaining explicit parent-child relationships at runtime.

## Spawning Child Agents with SpawnAgent

To create a child agent, emit the `Jido.Agent.Directive.SpawnAgent` directive from any agent action. This is a pure data structure that describes the intent to spawn; the `AgentServer` executes the actual side-effects.

When executed, the server:

- Generates a unique child instance ID by concatenating the parent ID and tag: `state.id <> "/" <> tag`
- Starts a new `AgentServer` for the child, passing a `parent` map containing the parent PID, instance ID, child tag, and optional metadata
- Stores a `ChildInfo` struct in the parent's runtime state under `State.children`, keyed by the child tag

The child receives its parent reference via `State.from_options/3`, which injects the parent map into the child's state as `agent.state.__parent__`.

```elixir
defmodule MyParentAgent do
  use Jido.Agent, name: "parent"

  @impl true
  def cmd(_agent, _msg) do
    # Spawn a worker with tag :worker_1

    child = %Jido.Agent.Directive.SpawnAgent{
      agent: MyWorkerAgent,
      tag: :worker_1,
      meta: %{role: :producer}
    }

    {:ok, %{}, [child]}
  end
end

```

*Directive definition*: [`lib/jido/agent/directive.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent/directive.ex) (lines 30-52).  
*Execution logic*: [`lib/jido/agent_server/directive_executors.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent_server/directive_executors.ex) (lines 85-124).

## Communicating from Child to Parent

Child agents communicate upward using `Directive.emit_to_parent/3`. This utility inspects the child's `__parent__` field—automatically injected during spawning—and generates an `Emit` directive targeting the parent's PID. If the child has no parent (for example, if spawned outside the hierarchy), the function returns `nil`.

```elixir
defmodule MyWorkerAgent do
  use Jido.Agent, name: "worker"

  @impl true
  def cmd(_agent, _msg) do
    # Create a signal with the result

    result = Jido.Signal.new!("worker.result", %{value: 42})

    # Emit the signal to the parent (if any)

    parent_emit = Directive.emit_to_parent(context.agent, result)

    {:ok, %{}, List.wrap(parent_emit)}
  end
end

```

*Utility function*: [`lib/jido/agent/directive.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent/directive.ex) (lines 79-91).

## Managing Child Lifecycle and Shutdown

Parents initiate graceful shutdown of tracked children using the `Jido.Agent.Directive.StopChild` directive. The executor looks up the child by tag in `State.children`, constructs a `jido.agent.stop` signal, and casts it to the child's PID.

For lifecycle monitoring, the parent tracks each child via `Process.monitor/1`. When a child terminates, the `AgentServer` handles the monitor message by removing the entry from the `children` map and optionally emitting a `jido.agent.child.exit` signal (defined in [`lib/jido/signal/child_exit.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/signal/child_exit.ex)) to notify the parent of the exit.

```elixir
defmodule MyParentAgent do
  use Jido.Agent, name: "parent"

  @impl true
  def cmd(_agent, :shutdown_worker) do
    stop = %Jido.Agent.Directive.StopChild{tag: :worker_1, reason: :shutdown}
    {:ok, %{}, [stop]}
  end
end

```

*Directive definition*: [`lib/jido/agent/directive.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent/directive.ex) (lines 93-108).  
*Executor implementation*: [`lib/jido/agent_server/directive_executors.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent_server/directive_executors.ex) (lines 41-78).

## Accessing Child Information at Runtime

The parent maintains a complete registry of its children in the `State.children` map (defined in [`lib/jido/agent_server/state.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent_server/state.ex)). Each entry is a `ChildInfo` struct (defined in [`lib/jido/agent_server/child_info.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent_server/child_info.ex)) containing the child's PID, monitor reference, tag, and metadata. You can inspect this map within agent actions to enumerate or validate active children.

```elixir
defmodule MyParentAgent do
  use Jido.Agent, name: "parent"

  @impl true
  def cmd(state, :list_children) do
    child_tags = Map.keys(state.children)   # state is the internal AgentServer.State

    {:ok, %{children: child_tags}, []}
  end
end

```

*State definition*: [`lib/jido/agent_server/state.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent_server/state.ex) (lines 45-48).  
*Child tracking*: [`lib/jido/agent_server/child_info.ex`](https://github.com/agentjido/jido/blob/main/lib/jido/agent_server/child_info.ex).

## Summary

- Jido uses **pure data directives** (`SpawnAgent`, `StopChild`) rather than OTP supervision for hierarchy management.
- The **`AgentServer`** handles all side-effects including process spawning, monitoring, and signal routing.
- Child agents store parent references in **`__parent__`** and use **`emit_to_parent/3`** for upward communication.
- Parents track children in a **`State.children`** map and receive automatic exit notifications via process monitors.

## Frequently Asked Questions

### Does Jido use OTP supervision trees for parent-child relationships?

No. Jido deliberately avoids OTP supervision nesting for agent hierarchies. Instead, it uses the `SpawnAgent` directive and `AgentServer` state management to track parent-child relationships, making the hierarchy explicit and queryable at runtime according to the `agentjido/jido` source code.

### How does a child agent know who its parent is?

When spawned, the child receives a parent map via `State.from_options/3` which injects it into `agent.state.__parent__`. This field contains the parent PID, instance ID, child tag, and metadata, enabling the child to target the parent with signals.

### What happens when a child agent crashes?

The parent monitors each child with `Process.monitor/1`. When the child exits, the `AgentServer` handles the monitor message, removes the child from the `State.children` map, and optionally emits a `jido.agent.child.exit` signal to notify the parent of the termination.

### Can a child agent emit signals to its parent?

Yes. Child agents use `Directive.emit_to_parent/3` to create an `Emit` directive targeting the parent PID. This function checks for the `__parent__` field in the agent state; if present, it returns the directive, otherwise it returns `nil`.