- Choosing. Your skill’s
descriptionsits in a list next to the description of every other skill, with one customer message to go on. The model picks one skill. - Working. Your skill is now running, and the model reads the body to decide what to say and what to do next.
The description decides which skill gets picked
The routing list the model reads is built from two things per skill: the skill id, which is the folder name, and thedescription. The name field is a
display label and takes no part in choosing, so the description is where the
work happens.
Name the thing first, then the action
Lead with the subject the skill covers, then say what it does with it:How do I replace my PIN?The model opens the card replacement skill. Nothing about PINs lives in that skill, but the question and the front of the description both lead with “replace”, so that is what matches. With the subject in front, the same question falls through to the knowledge base, which is where the answer is.
The same ordering helps a tool description, which the model reads the same way
when it is choosing which tool to call:
Use the words your customers use
Fill the description with the phrasings a real customer would type or say:Leave out what the skill id already says
The routing list already shows the skill id, so words that repeat it buy nothing. For a skill inskills/travel_notice/:
The body tells the model how to do the job
Once a skill is running, the body is what the model follows.Brief it like a new teammate
Write the body the way you would explain the job to someone competent who is new: what to find out, what to offer, and in what order.skills/card_replace/skill.md
Number the steps that have to happen in order
Use a numbered list when each step depends on the one before it:Give a long body headings
A short body reads fine as a few paragraphs. Once it covers several stages, put each one under its own## heading:
Put a rule where its cost matches its reach
A rule can sit in three places, and they differ in how often the model is carrying it:
Put a rule in
agent.yml when it holds everywhere, such as the language to
answer in. Put it at the top of a skill body when it holds for that job only:
Say what to achieve, not which words to use
Describe the outcome and let the model find the wording. It adapts to how the customer is talking, which is most of the value of writing prose at all. When the wording has to be exact, for legal or compliance reasons, put it inresponses.yml and it is delivered verbatim.
Say what you want to happen
Write the behaviour you want. Naming a behaviour to avoid puts that very thing in front of the model, and the “never” is a weak word wrapped around a strong one, so the ban half-reads as an instruction to do it. Most prohibitions have a positive form that is also more useful, because it tells the model what to do instead:
A prohibition earns its place only as a hard guardrail you cannot phrase
positively. Pair it with the positive target when you write one, so the model
still has something to aim at.
Point at things with @
Four kinds of thing can be named in the body, and they share one shape. Each
takes an id, never a display name.
Tools. While a skill is running, its tools are already available to the
model, so naming one is enough:
Ask for their account number, then call @tool.check_balance.Memory. The namespace is either a skill id or
project, and there are
always exactly two parts after @memory.:
Confirm the card ending in @memory.card_replace.selected_card_last_four is the right one.This is the form for the body. Paths like
session.card_replace.… belong in
conditions such as requires: and if:.
Another skill. Use the folder name under skills/, which is the skill id,
rather than the name: label:
Once the card is chosen, run @skill.card_disambiguation to settle which account it belongs to.The other skill runs, and this one carries on where it left off when that finishes. That return is guaranteed. Write the reference when this skill still handles the request, and leave it out when the user changes the subject. See Delegate a part of a skill to another skill with
@skill.
An ordered block. Use the id you gave the fence in
:::ordered_block id=<block_id>:
Once the reason is recorded, work through @block.pick_card.The block runs its steps in order, then hands back to the prose that called it.
rasa train resolves @memory references against the memory this skill can
read, and @block ids against the blocks this skill declares, so a typo in
either surfaces at build time.
Delegate a part of a skill to another skill with @skill
The referenced skill has its own task. Write @skill.<skill_id> when the
skill you are writing still handles the request, including the part the other
skill does. That is a delegation: Mantle runs the other skill and brings this
one back when it finishes. When the user asks for a task this skill does not
handle, leave the reference out. Mantle parks this skill and offers them a
resume.
For example, a complaint about the replacement fee is still the replacement:
skills/card_replace/skill.md
@skill.account_balance out of the
card-replacement body. Mantle treats the question as a topic change, parks the
replacement, and offers the user a resume once the balance is answered.
How a delegation and a topic change park and resume the parent is in
skill.md.
Let the tool result carry what happens next
The model sees what a tool returned, so write what to do with the result:Once you have their cards, show the last four digits of each and ask which one needs replacing.Describing the shape of the result, such as which fields it contains, repeats something the model already has in front of it. When an instruction only applies after a particular tool has run, the result itself is a good place for it. Return it as a field alongside the data:
Reference
skill.mdfor the full frontmatter and body syntax- Instructions for how prose fits with control levers
- When prose is not enough for memory, tool constraints, responses, and blocks a sentence cannot cover