defmodule Jido.Runic.ChildWorker do
@moduledoc """
Default child agent for delegated Runic workflow execution.
A minimal Jido agent that receives Runnables from a parent orchestrator,
executes them, and returns results. Use this as the default `child_modules`
entry when child agents don't need custom domain logic.
## Usage
use Jido.Agent,
strategy: {Jido.Runic.Strategy,
child_modules: %{
drafter: Jido.Runic.ChildWorker,
editor: Jido.Runic.ChildWorker
}}
For custom child agents that need domain-specific behavior, create your
own agent module and use `Jido.Runic.RunnableExecution` as a building
block for execution logic.
"""
use Jido.Agent,
name: "runic_child_worker",
schema: [
status: [type: :atom, default: :idle]
]
@doc false
@spec plugin_specs() :: [Jido.Plugin.Spec.t()]
def plugin_specs, do: []
@doc false
def signal_routes(_ctx) do
[
{"runic.child.execute", __MODULE__.ExecuteAction}
]
end
end
defmodule Jido.Runic.ChildWorker.ExecuteAction do
@moduledoc """
Jido Action that executes a Runic Runnable and returns the result to the parent.
Used by `Jido.Runic.ChildWorker` and available as a building block for custom
child agents. Handles execution, error wrapping, and parent signaling.
"""
use Jido.Action,
name: "execute_runnable",
description: "Execute a Runic Runnable and emit result to parent",
schema: [
runnable: [type: :any, required: true],
runnable_id: [type: :any, required: true],
tag: [type: :any, required: true]
]
alias Jido.Agent.Directive
alias Jido.Runic.RunnableExecution
@impl true
def run(%{runnable: runnable, runnable_id: runnable_id, tag: _tag}, context) do
if runnable.id != runnable_id do
{:error, "Runnable ID mismatch: expected #{inspect(runnable_id)}, got #{inspect(runnable.id)}"}
else
executed = RunnableExecution.execute(runnable)
result_signal = RunnableExecution.completion_signal(executed, source: "/runic/child")
emit_directive = Directive.emit_to_parent(%Jido.Agent{state: context.state}, result_signal)
{:ok, %{}, List.wrap(emit_directive)}
end
end
end