Skip to main content
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
The file must open with --- 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 in the skill’s own 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

The skill loads but is excluded from routing. Useful for parking a work-in-progress skill without deleting it.

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:
The marker scopes only the paragraph directly beneath it, up to the next blank line. Write one 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

The id is a fence attribute. Duplicate ids in one file are an error, as is setting 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

A skill.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_knowledge is offered at all depends on the project having an index, not on the active skill having a references/ folder.
  • Each retrieved snippet reaches the model with its source file path and a scope of either global or 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 References for the retrieval flow and the embedding model.

See also