# How to Leverage Skills for Structured Instructions in Agno Agents

> Learn how to leverage Agno Skills for structured instructions in Agno agents. Discover token-efficient access to domain knowledge and enhance your agent's capabilities with tool functions.

- Repository: [Agno/agno](https://github.com/agno-agi/agno)
- Tags: how-to-guide
- Published: 2026-02-23

---

**Agno Skills are self-contained instruction packages that agents discover via a catalog snippet and consume through three specialized tool functions, enabling safe, token-efficient access to domain knowledge without bloating the system prompt.**

The **Agno** framework (repository: `agno-agi/agno) provides a **Skills** system that lets you inject structured, domain-specific instructions into agents without hardcoding them into the system prompt. This architecture separates reusable knowledge bundles from agent configuration, allowing LLMs to dynamically load instructions, reference materials, and executable scripts only when needed.

## What Are Skills?

A **Skill** is a self-contained package that bundles domain expertise into a portable folder structure. According to the source code in [`libs/agno/agno/skills/skill.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/skill.py), the core data model is the `Skill` dataclass:

```python

# libs/agno/agno/skills/skill.py

@dataclass
class Skill:
    name: str                     # unique identifier (folder name or front-matter)

    description: str              # short one-liner

    instructions: str             # full SKILL.md content

    source_path: str              # absolute path to the skill folder

    scripts: List[str] = field(default_factory=list)
    references: List[str] = field(default_factory=list)
    metadata: Optional[Dict[str, Any]] = None
    license: Optional[str] = None
    compatibility: Optional[str] = None
    allowed_tools: Optional[List[str]] = None

```

Each skill lives on disk as a folder containing:

- **SKILL.md** – The instruction source containing detailed, human-readable guidance on *when* and *how* to apply the skill
- **scripts/** – Executable code templates that can be read or run on demand
- **references/** – Supplemental documentation, cheatsheets, and examples
- **Metadata** – Optional front-matter such as version, author, tags, license, and compatibility

## The Skills Orchestrator

The `Skills` class in [`libs/agno/agno/skills/agent_skills.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/agent_skills.py) serves as the runtime orchestrator that manages skill discovery and access. It performs four critical functions:

1. **Loads** skill objects from `SkillLoader` implementations (local folders, remote repos, etc.)
2. **Indexes** them by name for O(1) lookup
3. **Exposes** three low-level tool functions (`get_skill_instructions`, `get_skill_reference`, `get_skill_script`) that agents can call
4. **Generates** a concise XML-style system-prompt snippet describing available skills without dumping full instructions

```python

# libs/agno/agno/skills/agent_skills.py

class Skills:
    def __init__(self, loaders: List[SkillLoader]):
        self.loaders = loaders
        self._skills: Dict[str, Skill] = {}
        self._load_skills()
    
    def get_tools(self) -> List[Function]:
        # Returns Function objects wrapping the three low-level helpers

        ...

```

The orchestrator registers these tools as `Function` objects (defined in [`libs/agno/agno/tools/function.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/tools/function.py)) that the LLM can invoke through Agno's tool-execution layer.

## How Agents Consume Skills

Agents interact with skills through a **progressive discovery workflow** designed to minimize token usage and prevent accidental script execution.

### System Prompt Injection

When initializing an agent, you inject `skills.get_system_prompt_snippet()` into the system prompt. This provides the LLM with a lightweight catalog of available skills:

```python
system_prompt = f"""You are a helpful assistant.

{skills.get_system_prompt_snippet()}
"""

```

The snippet (generated in [`libs/agno/agno/skills/agent_skills.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/agent_skills.py) lines 88-127) lists skill names, descriptions, and availability of scripts/references, but omits the full instruction text.

### Tool-Based Access

The agent's toolset includes the three functions returned by `skills.get_tools()`. When the LLM decides a skill is relevant, it calls these functions:

- **`get_skill_instructions(skill_name)`** – Returns the full SKILL.md content
- **`get_skill_reference(skill_name, reference_name)`** – Retrieves specific reference documents
- **`get_skill_script(skill_name, script_name, execute=False)`** – Reads or executes scripts (with safety validation via `is_safe_path` in [`libs/agno/agno/skills/utils.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/utils.py))

### Progressive Discovery Stages

As implemented in the Agno source, agents follow this staged approach:

1. **Browse** – Scan the skill catalog in the system prompt
2. **Load** – Call `get_skill_instructions` for the selected skill
3. **Reference** – If deeper docs are needed, call `get_skill_reference`
4. **Scripts** – Use `get_skill_script` only when the `scripts` list is non-empty (check for `"none"` to confirm unavailability)

This staged approach keeps token usage low by loading full instructions only when necessary.

## Implementation Example

Below is a complete implementation showing how to leverage Skills for structured instructions within an Agno agent:

```python
from agno.skills.agent_skills import Skills
from agno.skills.loaders.local import LocalSkills
from agno.agent import Agent
from agno.tools.function import Function

# 1. Create a loader pointing at a directory with skill folders

loader = LocalSkills(root_path="/path/to/your/skills")

# 2. Build the Skills orchestrator (can pass multiple loaders)

skills = Skills(loaders=[loader])

# 3. Gather the tool objects the agent can call

tool_functions: List[Function] = skills.get_tools()

# 4. Assemble the system prompt with the skill catalog

system_prompt = f"""
You are an AI assistant equipped with domain-specific Skills.

{skills.get_system_prompt_snippet()}
"""

# 5. Instantiate the agent with skill tools

assistant = Agent(
    name="SkillfulBot",
    system_prompt=system_prompt,
    tools=tool_functions,        # expose the three skill-access tools

)

# 6. Run a conversation

response = assistant.chat("How do I clean my CSV data?")
print(response)

```

### Under the Hood

When the agent runs, this execution flow occurs:

- **`LocalSkills.load()`** (in [`libs/agno/agno/skills/loaders/local.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/loaders/local.py)) reads each skill folder, parses [`SKILL.md`](https://github.com/agno-agi/agno/blob/main/SKILL.md), and collects scripts and references
- **`get_system_prompt_snippet()`** returns an XML block describing the skill inventory
- **LLM tool invocation** routes to `Skills._get_skill_instructions`, which returns a JSON payload containing the full instructions
- **Script execution** (if requested) validates paths using `is_safe_path` and runs via the safe wrapper in [`libs/agno/agno/tools/script.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/tools/script.py)

## Summary

- **Skills** are self-contained instruction packages defined by the `Skill` dataclass in [`libs/agno/agno/skills/skill.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/skill.py), living as folders with [`SKILL.md`](https://github.com/agno-agi/agno/blob/main/SKILL.md), scripts, and references.
- The **Skills orchestrator** ([`libs/agno/agno/skills/agent_skills.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/agent_skills.py)) loads, indexes, and exposes skills through three tool functions while generating lightweight system-prompt catalogs.
- Agents consume skills via **progressive discovery**: browsing the catalog, loading instructions on demand, accessing references, and executing scripts only when explicitly allowed.
- Always use **`LocalSkills`** or other `SkillLoader` implementations to hydrate the orchestrator, and validate that `scripts` lists are non-empty before attempting execution.
- Call **`skills.reload()`** to refresh the skill catalog without restarting the process when skill definitions change.

## Frequently Asked Questions

### How do I prevent an agent from executing arbitrary scripts in a Skill?

The Agno framework implements path validation through `is_safe_path` in [`libs/agno/agno/skills/utils.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/utils.py) and checks the `scripts` list for the `"none"` value before execution. Always ensure `get_skill_script` is called with `execute=False` for read-only access, and verify that the skill's `scripts` field contains valid entries before allowing execution.

### What is the difference between Skills and regular Tools in Agno?

**Tools** are individual functions exposed to the LLM, while **Skills** are comprehensive instruction packages containing multiple resources (instructions, references, scripts) accessed through specialized tools (`get_skill_instructions`, `get_skill_reference`, `get_skill_script`). Skills enable structured, multi-stage knowledge retrieval without bloating the system prompt, whereas standard Tools typically perform atomic actions.

### Can I load Skills from remote repositories rather than local folders?

Yes. While the example uses `LocalSkills` from [`libs/agno/agno/skills/loaders/local.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/loaders/local.py), the architecture supports multiple `SkillLoader` implementations. You can extend the abstract `SkillLoader` interface defined in [`libs/agno/agno/skills/loaders/base.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/loaders/base.py) to fetch skills from Git repositories, databases, or API endpoints, then pass these loaders to the `Skills` orchestrator.

### Why does the system prompt only show a catalog instead of full instructions?

The `get_system_prompt_snippet()` method intentionally generates a concise XML-style catalog to minimize token usage and prevent context window overflow. Full instructions are loaded on-demand via `get_skill_instructions` when the LLM explicitly requests them, following the progressive discovery workflow documented in [`libs/agno/agno/skills/agent_skills.py`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/skills/agent_skills.py) lines 88-127.