How to Handle Parent-Child Agent Hierarchies in Jido: A Complete Guide
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
AgentServerfor the child, passing aparentmap containing the parent PID, instance ID, child tag, and optional metadata - Stores a
ChildInfostruct in the parent's runtime state underState.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__.
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 (lines 30-52).
Execution logic: 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.
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 (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) to notify the parent of the exit.
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 (lines 93-108).
Executor implementation: 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). Each entry is a ChildInfo struct (defined in 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.
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 (lines 45-48).
Child tracking: lib/jido/agent_server/child_info.ex.
Summary
- Jido uses pure data directives (
SpawnAgent,StopChild) rather than OTP supervision for hierarchy management. - The
AgentServerhandles all side-effects including process spawning, monitoring, and signal routing. - Child agents store parent references in
__parent__and useemit_to_parent/3for upward communication. - Parents track children in a
State.childrenmap 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.
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 →