skill.md is the only required file in a skill folder. It is YAML frontmatter
followed by a markdown body.
skills/card_replace/skill.md
--- on the first line and close the frontmatter
with a second ---. A missing delimiter fails with
skill.markdown.invalid_frontmatter_delimiter.
The skill id is the folder name
The skill id — used for routing, memory namespacing, and@skill. references — is always the parent directory name, never the name: field.
A skill in skills/card_replace/ with name: Card Replace is:
- referenced in prose as
@skill.card_replace - namespaced in memory as
session.card_replace.<entry>
Frontmatter properties
Write
description as a routing summary, including the phrasings a customer
would actually use. It is the only thing the orchestrator matches against.
requires
A condition string checked before the orchestrator
offers the skill:
complete_when
A condition that, once true, marks the skill’s prose flow complete:
import_tools
Declares tools defined in the agent-root tools/ folder, so this skill may use
them:
tools.py or tools/*.py are auto-discovered and must
not be listed. A shared tool that is not declared here is not attached to the
skill.
To use the same tool from more than one skill, define it once in the agent-root
tools/ folder and declare it in each skill’s import_tools.
tool_constraints
A list of single-key mappings, tool name to options:
See Tool Constraints for worked examples.
An entry that is not a single-key mapping, or whose options are not a mapping,
fails with
skill.markdown.invalid_tool_constraints.
utter
Fires a verbatim response from responses.yml on a skill lifecycle event or
when a memory condition first becomes true:
An entry may set both. These are distinct from a tool’s
on_success: /
on_failure:, which attach to a gated tool in tool_constraints.
disabled
Body format
The body is markdown. It supports:Prose paragraphs
Always visible to the LLM. Blank lines separate paragraphs; each paragraph is a scoping unit.if: markers
A paragraph whose first line is if: <condition> is included only when the
condition holds:
if: paragraph per case; for exclusive either/or branching, use
an ordered block’s next: branches.
Jumps to blocks and skills
Both take the id:
@block. names a block declared in the same file, and
@skill. names the target skill’s directory name.
Tools are named in plain prose rather than with a token, since they are already
in the model’s schema while the skill is active.
How the parent is parked
The engine parks the current skill differently depending on what put the new one on top:
A
@skill. target is offered only while its own requires: condition holds.
Public memory is readable across skills in every case, so the difference is
control rather than data: the first two are part of the skill’s design, the
third is the customer steering the conversation.
Ordered blocks
routable: inside the block. See
Ordered Blocks for step types.
Steps inside ordered blocks use the same YAML schema as top-level flow steps.
Unknown step properties are rejected at skill load and during
rasa data validate — misspelled or obsolete keys fail with a clear error
instead of being silently ignored.
Two removed collect-step keys have dedicated migration messages:
Any other unrecognized step property produces a generic validation error naming
the unknown key.
A skill needs prose or a block
Askill.md with neither prose instructions nor an ordered block fails with
skill.markdown.missing_instructions.
The combination determines routability:
Companion files
Each of the first three is scoped to the skill.
memory.yml declares entries
under this skill’s namespace, tools.py is attached to this skill, and
responses.yml merges into the shared registry under the names it declares.
references/ is project-wide
skills/<id>/references/**/*.md is indexed into the same index as the
agent-root references/ folder, and search_knowledge queries that whole index
on every call whatever skill is active. The folder location decides where the
files sit in your project, and the index a search reads is the same either way.
Two consequences worth designing around:
- Whether
search_knowledgeis offered at all depends on the project having an index, not on the active skill having areferences/folder. - Each retrieved snippet reaches the model with its
sourcefile path and ascopeof eitherglobalor the owning skill id. The model can tell where a chunk came from, so write each document to stand on its own rather than relying on the skill it sits under to supply the context.
See also
- Conditions: the expression grammar
- Ordered Blocks: step types and branching
- References: how knowledge is indexed and searched