Skip to main content

Skills

When to use this

Use skills to inject context documents into an agent's system prompt dynamically based on what the user asks. Skills are Markdown files with YAML frontmatter that describe a capability, its triggers, and the resources needed to execute it.

Import path

from agentflow.core.skills.models import SkillConfig, SkillMeta

How skills work

  1. You create a directory of SKILL.md files. Each file has YAML frontmatter with name, description, triggers, tags, and optional resources.
  2. You attach a SkillConfig to an Agent pointing at that directory.
  3. When the agent processes a message, it evaluates trigger phrases against the user input. If a trigger matches, the full SKILL.md content is injected into the system prompt for that turn.
  4. With hot_reload=True (default), skill files are re-read on every call — no restart needed during development.

SkillConfig

Configuration passed to the Agent constructor via the skills= parameter.

from agentflow.core.skills.models import SkillConfig

agent = Agent(
model="gpt-4o",
skills=SkillConfig(
skills_dir="./skills",
inject_trigger_table=True,
hot_reload=True,
),
)

Fields

FieldTypeDefaultDescription
skills_dirstr | NoneNonePath to the directory containing SKILL.md files. Relative paths are resolved from the working directory. Set to None to disable skills entirely.
inject_trigger_tableboolTrueWhen True, the agent's system prompt includes a summary table of all available skills and their triggers. This helps the LLM discover skills before they are triggered.
hot_reloadboolTrueRe-read skill files on every agent call. Set to False in production for better performance once skills are stable.

Validation: skills_dir must not be an empty string. Pass None to disable.


SkillMeta

Parsed metadata for a single skill file. Returned when you inspect loaded skills programmatically.

Fields

FieldTypeConstraintsDescription
namestrLowercase alphanumeric, hyphens, underscores. Max 128 chars.Slug identifier for the skill.
descriptionstrNon-empty, max 2000 chars.Human-readable description of what this skill does.
triggerslist[str]Max 50 triggers, each max 500 chars.Phrases that activate this skill. The agent checks if any trigger appears in the user message.
resourceslist[str]Max 100 items. Relative paths only. No .. or absolute paths.Additional files the skill may reference.
tagsset[str]Max 50 tags.Tags for filtering and discovery.
priorityint0 to 1000.Order in which skills are injected when multiple trigger simultaneously. Higher = earlier.
skill_dirstrDirectory containing the skill file. Set automatically by the loader.
skill_filestrPath to the SKILL.md file. Set automatically by the loader.

Writing a SKILL.md file

---
name: sql-query-helper
description: Help the user write and debug SQL queries.
triggers:
- "sql"
- "query"
- "database"
- "join"
- "SELECT"
tags:
- database
- sql
priority: 10
resources:
- schemas/users.sql
- schemas/orders.sql
---

# SQL Query Helper

You are an expert SQL assistant. Always produce:
- Fully qualified column references (table.column)
- Use CTEs for readability
- Explain each JOIN type chosen

Available schema files are provided in context.

Skills directory layout

my_agent/
├── graph/
│ └── react.py
└── skills/
├── sql-query-helper/
│ └── SKILL.md
├── code-reviewer/
│ └── SKILL.md
└── summariser/
└── SKILL.md

Each skill lives in its own subdirectory. The directory name is ignored — the name field in frontmatter determines the skill identifier.


Filtering skills by tag

Pass tools_tags to Agent to restrict which tools are available. Similarly, you can filter skills at load time by tags (future feature). For now, all skills in skills_dir are loaded.


Example: coding assistant with multiple skills

from agentflow.core.graph import Agent, ToolNode, StateGraph
from agentflow.core.skills.models import SkillConfig
from agentflow.utils import START, END

agent = Agent(
model="gpt-4o",
system_prompt=[{"role": "system", "content": "You are a software engineering assistant."}],
skills=SkillConfig(
skills_dir="./skills",
inject_trigger_table=True,
hot_reload=False, # disabled in production
),
)

graph = StateGraph()
graph.add_node("MAIN", agent)
graph.set_entry_point("MAIN")
graph.add_edge("MAIN", END)

app = graph.compile()

When a user says "Help me write a SQL join", the sql-query-helper skill is triggered and its full SKILL.md content is prepended to the system prompt for that turn.


Common errors

ErrorCauseFix
ValueError: skills_dir must not be an empty stringskills_dir="" passed to SkillConfig.Use skills_dir=None to disable or provide a valid directory path.
ValueError: Invalid skill nameSkill name contains uppercase or special characters.Use lowercase alphanumeric with hyphens/underscores only.
ValueError: Invalid resource pathresources entry contains .. or starts with /.Use only relative paths within the skill directory.
Skill not triggeringTrigger phrase not present in the user message.Check that the trigger appears (case-insensitive substring match) in the input.