Skip to main content
This is the first hard guarantee you can add. tool_constraints in the frontmatter make a tool invisible until its condition holds. The instructions body stays untouched.

Tool gating with requires:

Add a tool_constraints entry for the tool. The framework removes it from the LLM’s schema until the condition is true. The model can’t call what it can’t see.
skills/card_replace/skill.md
Before selected_card_id is set, the LLM sees:
After a card is selected:

Explicit confirmations

For a tool with irreversible side effects, add requires_confirmation: with enabled: true. The runtime holds the call, asks the customer to approve it, and runs the tool only if they say yes.
The two utter_* names are optional. Set enabled: true on its own and the LLM phrases both the ask and the denial:
The pause and the resume are handled for you. The engine holds the pending call while the customer answers, then runs the tool on a yes or cancels it on a no. There is nothing further to wire up.

How memory drives gating

Every requires: condition evaluates against current memory. Memory is where tools write results and where the framework checks conditions. Memory must be declared. A key a tool writes with context.memory.set() has to exist in the skill’s memory.yml or the project one, or rasa train fails with undeclared_memory_write:
skills/card_replace/memory.yml
memory.yml
tool_constraints are enforced regardless of who triggers the tool. Whether the LLM calls it or an ordered-block step runs it via execute_tool:, the same requires: and confirmation checks run, and gating fails closed, so an unevaluatable condition keeps the tool hidden.

Checking a gate

The Inspector’s tools panel shows every declared tool with its current gate result, so you can watch a condition flip as memory fills in. That is the quickest way to confirm a requires: expression behaves the way you intended. Two things to confirm when a tool is not appearing:
  • The condition uses the full namespaced form, session.<skill_id>.<entry> or session.project.<entry>.
  • The entry is one this skill can read: its own fields, another skill’s public fields, or project memory.
Local tools in tools.py are auto-discovered. They only need a tool_constraints entry when you are gating them.