@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
@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 precondition below).
Write @skill.<name> when the parent needs another skill’s result to carry on,
including when that request is still part of this skill’s task. The referenced
skill has its own task. That is a delegation: the orchestrator runs the named
skill and resumes the parent when it finishes. A task this skill does not
handle is not a delegation, so leave the reference out. The orchestrator parks
this skill and offers a resume. When to write the reference
is in
Writing prose.
How each case parks and resumes the parent is in
Jumps to blocks and skills.
Composition rules
- 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.
- Compose when you need context continuity. A dispute skill calls transaction-lookup as a sub-skill. The parent owns the conversation.
- 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
Use a precondition when a skill must not start until session memory says it may — for example, card replacement should wait until the customer is authenticated.skills/card_replace/skill.md
agent.yml
precondition: customer_authenticated. In
agent.yml, that name means: start Card
Replace only when satisfied_when is true; until then, call the resolve_with
skill (authentication).
Unlike hidden: true, Card Replace stays in routing — the customer can still
ask for it. When they do and they are not authenticated yet, the engine parks
Card Replace as pending, runs authentication, then either promotes Card Replace
or abandons the turn. If authentication is already the active skill (for example
it doubles as the session opener), the engine parks Card Replace under that run
instead of starting authentication again.
Card Replace depends on the memory key authenticated, never on hiding itself
from routing. 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 precondition when a skill must not start before another has done its
job; use @skill.<name> when a parent needs another skill’s result
mid-conversation (see above).
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.