Powered by AppSignal & Oban Pro

Jidoka: Skills And Load Paths

livebook/10_skills_and_load_paths.livemd

Jidoka: Skills And Load Paths

Run in Livebook

Skills add prompt guidance and can narrow the tool set visible during a turn. They can be modules or runtime-loaded SKILL.md files.

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 Tools And A Module Skill

defmodule LivebookDemo.Skills.Tools.AddNumbers do
  use Jidoka.Tool,
    name: "skill_add_numbers",
    description: "Adds two integers.",
    schema: Zoi.object(%{a: Zoi.integer(), b: Zoi.integer()})

  @impl true
  def run(%{a: a, b: b}, _context), do: {:ok, %{sum: a + b}}
end

defmodule LivebookDemo.Skills.Tools.MultiplyNumbers do
  use Jidoka.Tool,
    name: "skill_multiply_numbers",
    description: "Multiplies two integers.",
    schema: Zoi.object(%{a: Zoi.integer(), b: Zoi.integer()})

  @impl true
  def run(%{a: a, b: b}, _context), do: {:ok, %{product: a * b}}
end

defmodule LivebookDemo.Skills.ModuleMathSkill do
  use Jido.AI.Skill,
    name: "module-math-skill",
    description: "Provides multiplication discipline.",
    allowed_tools: ["skill_multiply_numbers"],
    actions: [LivebookDemo.Skills.Tools.MultiplyNumbers],
    body: """
    # Module Math Skill

    Use `skill_multiply_numbers` for multiplication. Keep the answer short.
    """
end

defmodule LivebookDemo.Skills.ModuleSkillAgent do
  use Jidoka.Agent

  agent do
    id :livebook_module_skill_agent
  end

  defaults do
    model :fast
    instructions "You can use module skills."
  end

  capabilities do
    skill LivebookDemo.Skills.ModuleMathSkill
  end
end
%{
  skill_names: LivebookDemo.Skills.ModuleSkillAgent.skill_names(),
  tool_names: LivebookDemo.Skills.ModuleSkillAgent.tool_names()
}

Load A Runtime Skill

Create a temporary SKILL.md and point the agent at its parent directory.

skill_root = Path.join(System.tmp_dir!(), "jidoka-livebook-skills")
skill_dir = Path.join(skill_root, "math-discipline")

File.rm_rf!(skill_root)
File.mkdir_p!(skill_dir)

File.write!(
  Path.join(skill_dir, "SKILL.md"),
  """
  ---
  name: math-discipline
  description: Runtime skill for addition.
  allowed-tools: skill_add_numbers
  ---

  # Math Discipline

  Use `skill_add_numbers` whenever addition is required.
  """
)

skill_root
defmodule LivebookDemo.Skills.RuntimeSkillAgent do
  use Jidoka.Agent

  @skill_root Path.join(System.tmp_dir!(), "jidoka-livebook-skills")

  agent do
    id :livebook_runtime_skill_agent
  end

  defaults do
    model :fast
    instructions "You can use runtime skills."
  end

  capabilities do
    tool LivebookDemo.Skills.Tools.AddNumbers
    tool LivebookDemo.Skills.Tools.MultiplyNumbers
    skill "math-discipline"
    load_path @skill_root
  end
end

Run the skill hook directly and inspect the narrowed tool list.

runtime_agent = LivebookDemo.Skills.RuntimeSkillAgent.runtime_module().new(id: "livebook-runtime-skill")

{:ok, _runtime_agent, {:ai_react_start, params}} =
  Jidoka.Skill.on_before_cmd(
    runtime_agent,
    {:ai_react_start,
     %{
       query: "Add 17 and 25",
       allowed_tools: ["skill_add_numbers", "skill_multiply_numbers"],
       tool_context: %{}
     }},
    LivebookDemo.Skills.RuntimeSkillAgent.skills()
  )

%{
  loaded_skill_names: params.tool_context[Jidoka.Skill.context_key()].names,
  allowed_tools_after_skill: params.allowed_tools,
  prompt_preview: params.tool_context[Jidoka.Skill.context_key()].prompt
}

Optional Provider Turn

{:ok, pid} =
  Jidoka.Kino.start_or_reuse("livebook-runtime-skill-agent", fn ->
    LivebookDemo.Skills.RuntimeSkillAgent.start_link(id: "livebook-runtime-skill-agent")
  end)

Jidoka.Kino.chat("Runtime skill chat", fn ->
  LivebookDemo.Skills.RuntimeSkillAgent.chat(pid, "Add 17 and 25. Reply with only the sum.")
end)