Goal
Compose small skills into a booking-change journey with authentication and confirmation.
Teach
When a skill needs another skill’s logic mid-conversation, reference it with @skill.<name>. The parent stays on the stack; the sub-skill runs and exports public memory; the parent resumes.
First verify identity: @skill.authenticate
Then find the booking: @skill.find_booking
Parent skills can also gate their own activation, using the same expression syntax at the top level of the frontmatter:
requires: session.project.authenticated
Mantle will not activate change_booking until that field is true — the only contract is the memory field.
Where shared fields live
This is the part that trips people up, so it is worth slowing down for. When a tool writes a memory field, the write lands in the namespace of the skill that is active at that moment. find_booking is the skill running when a booking gets selected, so if selected_booking_ref were declared inside find_booking/memory.yml, the value would land in session.find_booking.selected_booking_ref and change_booking could never gate on it.
Fields that travel between skills therefore belong in the project-wide memory.yml at the repo root, where they resolve to session.project.* no matter which skill is active:
# memory.yml (project root)
selected_booking_ref:
type: text
description: Booking reference the traveler has settled on for this request.
selected_trip_name:
type: text
description: Trip name for the selected booking.
A good rule of thumb: a field used by exactly one skill belongs to that skill, and a field that is a handoff between skills belongs to the project.
Confirming an irreversible tool
tool_constraints:
- cancel_booking:
requires: session.project.selected_booking_ref
requires_confirmation:
enabled: true
utter_for_confirmation: utter_confirm_cancel_booking
utter_on_user_denial: utter_cancel_aborted
on_success: utter_booking_cancelled
Note the division of labour between the two gates. requires is a readiness check — it hides the tool until the data it needs exists. requires_confirmation is the human check — the tool is available, but the engine pauses and asks before running it. You rarely need a separate “did they confirm?” memory field, because the confirmation gate already is that check.
Composition rules:
- Prefer small, focused skills that export shared state through project memory
- The parent must have meaningful business logic of its own
@skillis coordinated; user interrupts are not guaranteed to resume the same way
Paste
Paste set: tutorial/snippets/step-06-composition/
Copy skills/authenticate, skills/find_booking, and skills/change_booking, plus the updated project memory.yml that adds the two shared booking fields.
Optional fast-forward for remaining skills: tutorial/snippets/step-07-remaining/ (human_handoff, goodbye, intro).
Demo PIN: four two four two (4242).
Train and try
make train
make inspect
Try: “I need to cancel a booking.”
Verify: Atlas authenticates, finds a booking, asks for confirmation, then cancels only after approval.
Talking point
Authentication is reusable across every sensitive skill. Transaction or booking lookup is reusable across changes, baggage, and status. Parents own the business outcome.
