Skip to main content
When a skill needs another skill’s logic mid-conversation, it references it with @skill.<name>. The parent stays on the stack, the sub-skill runs, and the parent resumes with the sub-skill’s public memory available to it. That public memory stays after the sub-skill completes, so the parent can read it on later turns. It is cleared only when that same skill starts again in the session. If a result must last the whole conversation, write it to project memory instead.

The @skill.<name> reference

When the orchestrator reaches @skill.authentication, it parks Card Replace on the stack, runs Authentication to completion, then resumes Card Replace, which can now read Authentication’s public fields such as authenticated and party_id. Those leftover public values stay after complete so the parent can read them; they are cleared only if Authentication starts again. Session-long facts such as authenticated belong in project memory so they survive that next run (see requires: below). Write @skill.<name> when the parent needs another skill’s result to carry on. A customer who changes topic mid-conversation is handled by the engine on its own, with no authoring needed. For how each case parks and resumes the parent, see Jumps to blocks and skills.

Composition rules

  1. Default to small, focused skills. Each skill does one thing and exports results as public memory. Transaction lookup is its own skill, not embedded in disputes, refunds, and fraud review.
  2. Compose when you need context continuity. A dispute skill calls transaction-lookup as a sub-skill. The parent owns the conversation.
  3. The parent must have meaningful business logic of its own. If you strip out all the @skill.<name> references and the skill is empty, it’s not a skill. That’s the orchestrator’s job.

Depending on another skill’s outcome

A skill can declare its own requires:, and the orchestrator offers it only once that condition holds:
skills/card_replace/skill.md
This is the loosest way to compose. Card Replace depends on whatever skill sets authenticated, never on the authentication skill itself. The memory key is the whole contract, which is why it lives in the project-level memory.yml rather than inside either skill. Reach for this when one skill must not start before another has done its job, and for @skill.<name> when the parent needs the result mid-conversation.

Which one to use

Both take the id, not the display name: @skill.card_disambiguation for a skill in skills/card_disambiguation/, and @block.pick_card for a block declared as :::ordered_block id=pick_card. Tools need no token. They are already in the model’s schema while their skill is active, so name them in plain prose.