> ## Documentation Index
> Fetch the complete documentation index at: https://maestro.rasa.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Skills

> Build AI agents that scale reliably

<div id="skills-scrolly">
  <div className="sk-wrap">
    <div className="sk-steps">
      <div className="sk-header" data-sk-focus>
        <h1>Skills</h1>
        <p className="sk-lede">Voice and chat agents in Rasa are built from composable skills, coordinated at runtime by an orchestrator called <a href="/docs/maestro/maestro">Maestro</a>. Reliability at scale comes from progressive control: each skill starts as plain instructions, and you add deterministic guarantees only where the business needs them.</p>
        <p className="sk-lede">This page builds one skill, <code>card\_replace</code>, from a single file to a constrained procedure. Scroll to follow along.</p>
        <div className="sk-hint" aria-hidden="true"><svg width="12" height="12" viewBox="0 0 16 16" fill="none"><path d="M8 3v10m0 0l-4-4m4 4l4-4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" /></svg><span>Scroll</span></div>
      </div>

      <section className="sk-step" data-sk-step="1" data-sk-focus>
        <h2>Start with <code>skill.md</code></h2>
        <p>A skill is a folder: instructions for the LLM, plus optional tools and references. At its simplest, the folder holds one file. Frontmatter with a name and description, then instructions in plain language. The folder name is the skill id; see <a href="/docs/maestro/reference/project-structure">Project structure</a> for the full layout.</p>
        <p>No flowcharts, no state machine. The LLM interprets the instructions in conversation.</p>
      </section>

      <section className="sk-step" data-sk-step="2" data-sk-focus>
        <h2>Add <code>tools/</code></h2>
        <p>Define tools in a <code>tools/</code> subfolder and they are automatically available while the skill is active. No registration. A tool returns structured data to the LLM and can store results in <a href="/docs/maestro/reference/memory-yml">memory</a> for later steps.</p>
      </section>

      <section className="sk-step" data-sk-step="3" data-sk-focus>
        <h2>Add <code>references/</code></h2>
        <p>FAQs, policies, and other reference material live in a <code>references/</code> subfolder. They are indexed at training time and retrieved on demand, so the agent can answer from them without carrying them in every prompt.</p>
      </section>

      <div className="sk-inter" data-sk-focus>
        <h2>Progressive control</h2>
        <p>Everything so far is instructions an LLM interprets. Where a mistake is expensive, you constrain it, with tool constraints, skill prerequisites, or ordered blocks.</p>
        <p>These are framework guarantees enforced by the runtime, not suggestions to the model. A tool whose constraint isn't met is not available for the LLM to call; a jailbreak can't change that.</p>
      </div>

      <section className="sk-step" data-sk-step="4" data-sk-focus>
        <h2>Tool constraints</h2>
        <p>A <code>requires</code> condition in the frontmatter gates when a tool becomes available. Until <code>selected\_card\_id</code> exists in memory, <code>lock\_card</code> is removed from the tool schema entirely. The model can't call a tool it never sees.</p>
        <div className="sk-badge">Enforced before the tool call executes</div>
      </section>

      <section className="sk-step" data-sk-step="5" data-sk-focus>
        <h2>Scoped instructions</h2>
        <p>Different situations need different instructions. <code>if:</code> markers scope a paragraph to a memory value: when <code>replacement\_reason</code> is <code>stolen</code>, only the stolen paragraph is visible to the LLM. Non-matching branches are stripped from the prompt entirely.</p>
        <div className="sk-badge">Non-matching branches removed from prompt</div>
      </section>

      <section className="sk-step" data-sk-step="6" data-sk-focus>
        <h2>Skill prerequisites</h2>
        <p>A <code>requires</code> block at the root of the frontmatter gates the whole skill: Maestro won't activate <code>card\_replace</code> until <code>authenticated</code> is true. The only contract with the authentication skill is the memory key.</p>
        <div className="sk-badge">Checked before the skill activates</div>
      </section>

      <section className="sk-step" data-sk-step="7" data-sk-focus>
        <h2>Ordered blocks</h2>
        <p>For steps that must run in exact order, add an <code>ordered\_block</code> to the instructions. The LLM decides when to invoke <code>@block.pick\_card</code>; the runtime executes the steps inside it in order.</p>
        <div className="sk-badge">Step order enforced by the runtime</div>
      </section>
    </div>

    <div className="sk-panel-col">
      <div className="sk-panel">
        <div className="sk-panel-head"><svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M1.5 4.5A1.5 1.5 0 013 3h3l1.5 2H13a1.5 1.5 0 011.5 1.5V12A1.5 1.5 0 0113 13.5H3A1.5 1.5 0 011.5 12V4.5z" stroke="currentColor" strokeWidth="1.3" /></svg><span>card\_replace/</span></div>

        <div className="sk-tree">
          <div className="sk-row" data-sk-from="1" data-sk-on="1,4,5,6,7" data-sk-mod="4,5,6,7"><svg width="12" height="12" viewBox="0 0 16 16" fill="none"><path d="M4 1.5h5.5L13 5v9.5H4V1.5z" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" /><path d="M9.5 1.5V5H13" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" /></svg><span>skill.md</span><i className="sk-dot" /></div>
          <div className="sk-row" data-sk-from="2" data-sk-on="2"><svg width="12" height="12" viewBox="0 0 16 16" fill="none"><path d="M10.4 5.6a2.8 2.8 0 01-3.6 3.6L3.6 12.4a1.13 1.13 0 01-1.6-1.6l3.2-3.2a2.8 2.8 0 013.6-3.6L7 5.8l1.6 1.6 1.8-1.8z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" /></svg><span>tools/tools.py</span><em>Optional</em></div>
          <div className="sk-row" data-sk-from="3" data-sk-on="3"><svg width="12" height="12" viewBox="0 0 16 16" fill="none"><path d="M8 3.5C6.8 2.6 5.2 2.5 3.5 2.5v10c1.7 0 3.3.1 4.5 1 1.2-.9 2.8-1 4.5-1v-10c-1.7 0-3.3.1-4.5 1z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" /><path d="M8 3.5v10" stroke="currentColor" strokeWidth="1.2" /></svg><span>references/faqs.md</span><em>Optional</em></div>
        </div>

        <div className="sk-view">
          <div className="sk-slide" data-sk-slide="1">
            <div className="sk-file">card\_replace/skill.md</div>

            <div className="sk-code">
              <span className="ln">
                <span className="c">
                  {"---"}
                </span>
              </span>

              <span className="ln"><span className="y">name</span>: Card Replace</span>
              <span className="ln"><span className="y">description</span>{": Replace a credit card -- lost,"}</span>
              <span className="ln">  stolen, damaged, or not received</span>

              <span className="ln">
                <span className="c">
                  {"---"}
                </span>
              </span>

              <span className="ln" />

              <span className="ln"><span className="t">Help the customer replace a credit card.</span></span>

              <span className="ln" />

              <span className="ln"><span className="t">Check whether their account is eligible for</span></span>
              <span className="ln"><span className="t">replacement. If they have multiple cards, ask</span></span>

              <span className="ln">
                <span className="t">
                  {"which one. Ask why they need a replacement --"}
                </span>
              </span>

              <span className="ln"><span className="t">the valid reasons are lost, stolen, damaged,</span></span>
              <span className="ln"><span className="t">or not received.</span></span>

              <span className="ln" />

              <span className="ln"><span className="t">For stolen or not-received cards, offer to lock</span></span>
              <span className="ln"><span className="t">the card while a new one ships. Once everything</span></span>
              <span className="ln"><span className="t">is gathered, ask their shipping preference,</span></span>
              <span className="ln"><span className="t">confirm the order, and process the replacement.</span></span>
            </div>
          </div>

          <div className="sk-slide" data-sk-slide="2">
            <div className="sk-file">card\_replace/tools/tools.py</div>

            <div className="sk-code">
              <span className="ln"><span className="k">from</span> rasa.calm\_v2.tools.decorator <span className="k">import</span> ToolContext, tool</span>
              <span className="ln"><span className="k">from</span> rasa.calm\_v2.tools.result <span className="k">import</span> ToolResult</span>

              <span className="ln" />

              <span className="ln"><span className="f">@tool</span>(description=<span className="s">{"\"List the active bank cards"}</span></span>
              <span className="ln"><span className="s">{"      associated with the customer's account\""}</span>)</span>
              <span className="ln"><span className="k">async def</span> <span className="f">list\_cards</span>(</span>
              <span className="ln">    account\_id: <span className="y">str</span>,</span>
              <span className="ln">    context: <span className="y">ToolContext</span> = <span className="k">None</span>,</span>
              <span className="ln">) -> <span className="y">ToolResult</span>:</span>
              <span className="ln">    cards = <span className="k">await</span> call\_cards\_api(account\_id)</span>

              <span className="ln" />

              <span className="ln">    <span className="c"># Store in memory for later steps</span></span>
              <span className="ln">    context.memory.set(<span className="s">{"\"user_cards\""}</span>, cards)</span>

              <span className="ln" />

              <span className="ln">    <span className="c"># Structured data goes back to the LLM</span></span>
              <span className="ln">    <span className="k">return</span> ToolResult(</span>
              <span className="ln">        llm\_response=\{</span>
              <span className="ln">            <span className="s">{"\"cards\""}</span>: cards,</span>
              <span className="ln">            <span className="s">{"\"total_cards\""}</span>: len(cards)</span>
              <span className="ln">        },</span>
              <span className="ln">    )</span>
            </div>
          </div>

          <div className="sk-slide" data-sk-slide="3">
            <div className="sk-file">card\_replace/references/faqs.md</div>

            <div className="sk-code">
              <span className="ln"><span className="y">Q:</span> <span className="t">What if my dog ate my card?</span></span>
              <span className="ln"><span className="y">A:</span> <span className="t">That counts as damaged.</span></span>

              <span className="ln" />

              <span className="ln"><span className="y">Q:</span> <span className="t">Will my replacement card keep the same</span></span>
              <span className="ln"><span className="t">   number and PIN?</span></span>
              <span className="ln"><span className="y">A:</span> <span className="t">The number may change; your PIN stays</span></span>
              <span className="ln"><span className="t">   the same.</span></span>

              <span className="ln" />

              <span className="ln"><span className="y">Q:</span> <span className="t">How long does delivery take?</span></span>
              <span className="ln"><span className="y">A:</span> <span className="t">5-7 business days, or 2 with express</span></span>
              <span className="ln"><span className="t">   shipping.</span></span>

              <span className="ln" />

              <span className="ln">
                <span className="c">
                  {"..."}
                </span>
              </span>
            </div>
          </div>

          <div className="sk-slide" data-sk-slide="4">
            <div className="sk-file">card\_replace/skill.md<span className="sk-tag">hard guarantee</span></div>

            <div className="sk-code">
              <span className="ln">
                <span className="c">
                  {"---"}
                </span>
              </span>

              <span className="ln"><span className="y">name</span>: Card Replace</span>
              <span className="ln"><span className="y">description</span>{": Replace a credit card -- lost,"}</span>
              <span className="ln">  stolen, damaged, or not received</span>
              <span className="ln add"><span className="y">tool\_constraints</span>:</span>
              <span className="ln add">  - <span className="y">lock\_card</span>:</span>
              <span className="ln add">      <span className="y">requires</span>: <span className="s">{"\"session.project.selected_card_id\""}</span></span>

              <span className="ln">
                <span className="c">
                  {"---"}
                </span>
              </span>

              <span className="ln" />

              <span className="ln dm"><span className="t">Help the customer replace a credit card.</span></span>

              <span className="ln dm" />

              <span className="ln dm"><span className="c">Until selected\_card\_id is set, lock\_card is</span></span>
              <span className="ln dm"><span className="c">not in the tool schema at all.</span></span>
            </div>
          </div>

          <div className="sk-slide" data-sk-slide="5">
            <div className="sk-file">card\_replace/skill.md<span className="sk-tag">scoped</span></div>

            <div className="sk-code">
              <span className="ln">
                <span className="t">
                  {"Ask why they need a replacement -- lost, stolen,"}
                </span>
              </span>

              <span className="ln"><span className="t">damaged, or not received.</span></span>

              <span className="ln" />

              <span className="ln add"><span className="k">if:</span> {"session.card_replace.replacement_reason == 'damaged'"}</span>
              <span className="ln add"><span className="t">Ask who needs a replacement: just the</span></span>

              <span className="ln add">
                <span className="t">
                  {"customer's card, an authorized user's, or both."}
                </span>
              </span>

              <span className="ln" />

              <span className="ln add"><span className="k">if:</span> {"session.card_replace.replacement_reason == 'stolen'"}</span>
              <span className="ln add"><span className="t">Tell the customer the card will be locked.</span></span>
              <span className="ln add"><span className="t">Confirm, then lock the card.</span></span>

              <span className="ln" />

              <span className="ln add"><span className="k">if:</span> {"session.card_replace.replacement_reason == 'lost'"}</span>
              <span className="ln add"><span className="t">Present recent transactions and ask if they</span></span>
              <span className="ln add"><span className="t">look familiar. Then handle locking.</span></span>
            </div>
          </div>

          <div className="sk-slide" data-sk-slide="6">
            <div className="sk-file">card\_replace/skill.md<span className="sk-tag">hard guarantee</span></div>

            <div className="sk-code">
              <span className="ln">
                <span className="c">
                  {"---"}
                </span>
              </span>

              <span className="ln"><span className="y">name</span>: Card Replace</span>
              <span className="ln"><span className="y">description</span>{": Replace a credit card -- lost,"}</span>
              <span className="ln">  stolen, damaged, or not received</span>
              <span className="ln add"><span className="y">requires</span>: <span className="s">{"\"session.project.authenticated\""}</span></span>
              <span className="ln"><span className="y">tool\_constraints</span>:</span>
              <span className="ln">  - <span className="y">lock\_card</span>:</span>
              <span className="ln">      <span className="y">requires</span>: <span className="s">{"\"session.project.selected_card_id\""}</span></span>

              <span className="ln">
                <span className="c">
                  {"---"}
                </span>
              </span>

              <span className="ln" />

              <span className="ln dm"><span className="c">Checked by the runtime before the skill</span></span>
              <span className="ln dm"><span className="c">activates.</span></span>
            </div>
          </div>

          <div className="sk-slide" data-sk-slide="7">
            <div className="sk-file">card\_replace/skill.md<span className="sk-tag">exact order</span></div>

            <div className="sk-code">
              <span className="ln"><span className="y">## Identify the reason</span></span>

              <span className="ln" />

              <span className="ln">
                <span className="t">
                  {"Ask why they need a replacement -- lost, stolen,"}
                </span>
              </span>

              <span className="ln"><span className="t">damaged, or not received. Once the reason is</span></span>
              <span className="ln"><span className="t">collected, invoke</span> <span className="f">@block.pick\_card</span></span>

              <span className="ln" />

              <span className="ln add"><span className="k">:::ordered\_block</span> <span className="y">id</span>=pick\_card</span>
              <span className="ln add"><span className="y">steps</span>:</span>
              <span className="ln add">  - <span className="y">id</span>: check\_eligibility</span>
              <span className="ln add">    <span className="y">execute\_tool</span>: card\_replace\_eligibility</span>
              <span className="ln add">  - <span className="y">id</span>: fetch\_cards</span>
              <span className="ln add">    <span className="y">execute\_tool</span>: get\_customer\_info</span>
              <span className="ln add">  - <span className="y">id</span>: select\_card</span>
              <span className="ln add">    <span className="y">instructions</span>{": show user's cards and let"}</span>
              <span className="ln add">      them pick one</span>
              <span className="ln add">    <span className="y">complete\_when</span>: <span className="s">{"\"session.project.selected_card_id\""}</span></span>
              <span className="ln add">  - <span className="y">id</span>: END</span>
              <span className="ln add"><span className="k">:::</span></span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div className="sk-close">
    <p>If a whole skill must follow a strict procedure, replace the entire body with an ordered block. Start simple, add control incrementally, and build fully deterministic skills where you need them.</p>
  </div>
</div>

<div className="sk-cards">
  <CardGroup cols={2}>
    <Card title="Local Quickstart" icon="rocket" href="/docs/maestro/getting-started">
      Build a skill and run it. 2 minutes.
    </Card>

    <Card title="Build Guide" icon="wrench" href="/docs/maestro/build-guide/tool-constraints">
      The progressive control spectrum, one lever at a time.
    </Card>

    <Card title="Orchestration" icon="diagram-project" href="/docs/maestro/maestro/runtime-loop">
      How Maestro runs a turn and what it guarantees.
    </Card>

    <Card title="Reference" icon="book" href="/docs/maestro/reference/skill-md">
      File formats, tools contract, runtime internals.
    </Card>
  </CardGroup>
</div>
