ADK.Skill (ADK v0.0.1-alpha.1)

Copy Markdown View Source

A Skill is a reusable bundle of instructions (and optionally tools) that can be loaded from a directory and mixed into an LlmAgent.

A skill directory contains:

  • SKILL.md — required; provides the skill's instruction text
  • Additional files as needed (tool modules, reference docs, etc.)

SKILL.md format

The first # Heading becomes the skill name (fallback: directory basename). The first > blockquote line becomes the description. The full file content is used as the instruction.

# My Skill

> Short description of what this skill does.

## Instructions

Detailed instruction text here...

Usage

# Load a single skill from a directory
{:ok, skill} = ADK.Skill.from_dir("path/to/skills/my_skill")

# Load all skills from a root skills directory
{:ok, skills} = ADK.Skill.load_from_dir("path/to/skills/")

# Use with LlmAgent
agent = ADK.Agent.LlmAgent.new(
  name: "bot",
  model: "gemini-flash-latest",
  instruction: "You are helpful.",
  skills: [skill]
)

Summary

Functions

Merge a list of skills into an agent opts keyword list.

Load a single skill from a directory.

Load a single skill from a directory, raising on error.

Scan a root directory and load all skills from subdirectories containing SKILL.md.

Returns the instruction string for this skill.

Types

t()

@type t() :: %ADK.Skill{
  description: String.t() | nil,
  dir: Path.t(),
  instruction: String.t(),
  name: String.t(),
  tools: [map()] | nil
}

Functions

apply_to_opts(opts, skills)

@spec apply_to_opts(
  keyword(),
  [t()]
) :: keyword()

Merge a list of skills into an agent opts keyword list.

Appends skill instructions to the :instruction field and merges skill tools into the :tools list. Safe to call with an empty list.

Examples

iex> skill = %ADK.Skill{
...>   name: "Helper",
...>   instruction: "Be extra helpful.",
...>   dir: "/tmp/helper"
...> }
iex> opts = [name: "bot", model: "test", instruction: "You assist users.", tools: []]
iex> merged = ADK.Skill.apply_to_opts(opts, [skill])
iex> String.contains?(merged[:instruction], "Be extra helpful.")
true

from_dir(dir)

@spec from_dir(Path.t()) :: {:ok, t()} | {:error, String.t()}

Load a single skill from a directory.

The directory must contain a SKILL.md file.

Returns {:ok, skill} or {:error, reason}.

Examples

iex> dir = Path.join(System.tmp_dir!(), "test_skill_from_dir")
iex> File.mkdir_p!(dir)
iex> File.write!(Path.join(dir, "SKILL.md"), "# Test Skill\n\n> A test.\n\nDo stuff.")
iex> {:ok, skill} = ADK.Skill.from_dir(dir)
iex> skill.name
"Test Skill"
iex> skill.description
"A test."

from_dir!(dir)

@spec from_dir!(Path.t()) :: t()

Load a single skill from a directory, raising on error.

Examples

iex> dir = Path.join(System.tmp_dir!(), "test_skill_bang")
iex> File.mkdir_p!(dir)
iex> File.write!(Path.join(dir, "SKILL.md"), "# Bang Skill\n\nInstruction.")
iex> skill = ADK.Skill.from_dir!(dir)
iex> skill.name
"Bang Skill"

load_from_dir(root)

@spec load_from_dir(Path.t()) :: {:ok, [t()]} | {:error, String.t()}

Scan a root directory and load all skills from subdirectories containing SKILL.md.

Returns {:ok, [skill]} with all successfully loaded skills. Subdirectories without SKILL.md are silently skipped.

Examples

iex> root = Path.join(System.tmp_dir!(), "test_skill_root")
iex> skill_dir = Path.join(root, "my_skill")
iex> File.mkdir_p!(skill_dir)
iex> File.write!(Path.join(skill_dir, "SKILL.md"), "# My Skill\n\nDo things.")
iex> {:ok, skills} = ADK.Skill.load_from_dir(root)
iex> length(skills)
1
iex> hd(skills).name
"My Skill"

to_instruction(skill)

@spec to_instruction(t()) :: String.t()

Returns the instruction string for this skill.

Useful when composing multiple skill instructions.