Jidoka: Subagents
Subagents are specialist agents exposed to a parent as tool-like capabilities. The parent stays in control of the turn; the specialist handles a bounded task.
Setup
Mix.install(
[
{:jidoka, git: "https://github.com/mikehostetler/jidoka.git", ref: "924a486f3c1b7e7a943cb3d5ceee0de65f158467"},
{:kino, "~> 0.19.0"}
],
config: [
jidoka: [
model_aliases: %{fast: "anthropic:claude-haiku-4-5"}
]
]
)
Jidoka.Kino.setup()
Define A Specialist
defmodule LivebookDemo.Subagents.ResearchSpecialist do
defmodule Runtime do
use Jido.Agent,
name: "livebook_research_specialist_runtime",
schema: Zoi.object(%{})
end
def name, do: "research_agent"
def runtime_module, do: Runtime
def start_link(opts \\ []), do: Jidoka.start_agent(Runtime, opts)
def chat(_pid, message, opts \\ []) do
context = Keyword.get(opts, :context, %{})
if notify_pid = Map.get(context, :notify_pid, Map.get(context, "notify_pid")) do
send(notify_pid, {:research_context, context})
end
tenant = Map.get(context, :tenant, Map.get(context, "tenant", "none"))
depth = Map.get(context, Jidoka.Subagent.depth_key(), 0)
{:ok, "research: #{message}; tenant=#{tenant}; depth=#{depth}"}
end
end
defmodule LivebookDemo.Subagents.ManagerAgent do
use Jidoka.Agent
agent do
id :livebook_subagent_manager
end
defaults do
model :fast
instructions "Delegate research tasks to the research specialist."
end
capabilities do
subagent LivebookDemo.Subagents.ResearchSpecialist,
as: "research_agent",
description: "Ask the research specialist for a bounded research task.",
result: :structured
end
end
Inspect the generated subagent capability.
%{
subagent_names: LivebookDemo.Subagents.ManagerAgent.subagent_names(),
tool_names: LivebookDemo.Subagents.ManagerAgent.tool_names(),
subagents: LivebookDemo.Subagents.ManagerAgent.subagents()
}
Call The Generated Tool Directly
This is the same model-visible surface the parent agent receives.
research_tool =
Enum.find(LivebookDemo.Subagents.ManagerAgent.tools(), fn tool ->
tool.name() == "research_agent"
end)
{:ok, result} =
research_tool.run(
%{task: "Summarize the onboarding risk."},
%{tenant: "acme", notify_pid: self(), secret: "not forwarded"}
)
forwarded_context =
receive do
{:research_context, context} -> context
after
100 -> :no_context_message
end
%{
result: result,
forwarded_context: forwarded_context
}
The subagent metadata is available when result: :structured is configured.
Map.take(result.subagent, [:name, :mode, :outcome, :context_keys, :result_preview])
Optional Provider Turn
{:ok, pid} =
Jidoka.Kino.start_or_reuse("livebook-subagent-manager", fn ->
LivebookDemo.Subagents.ManagerAgent.start_link(id: "livebook-subagent-manager")
end)
Jidoka.Kino.chat("Subagent manager chat", fn ->
LivebookDemo.Subagents.ManagerAgent.chat(
pid,
"Ask the research_agent to summarize why focused onboarding notebooks help.",
context: %{tenant: "acme"}
)
end)