# `ADK.Skill`
[🔗](https://github.com/zeroasterisk/adk-elixir/blob/main/lib/adk/skill.ex#L1)

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.

```markdown
# 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]
    )

# `t`

```elixir
@type t() :: %ADK.Skill{
  auth_requirements: [map()] | nil,
  description: String.t() | nil,
  dir: Path.t(),
  instruction: String.t(),
  mcp_toolsets: [pid()] | nil,
  missing_deps: [String.t()],
  name: String.t(),
  supervisor: pid() | nil,
  tools: [map()] | nil
}
```

# `apply_to_opts`

```elixir
@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`

```elixir
@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!`

```elixir
@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`

```elixir
@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"

# `stop`

```elixir
@spec stop(t()) :: :ok
```

Stop all supervised processes for this skill (MCP servers, etc).

# `to_instruction`

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

Returns the instruction string for this skill.

Useful when composing multiple skill instructions.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
