Skip to main content
Some moments need specific wording: a recording notice at the start of a call, a fraud warning when a card is reported stolen, a legal disclaimer after a transaction. Responses let you declare that text once in responses.yml and have the framework deliver it exactly as written. The LLM never rewrites it.

Defining responses

Response text lives in the skill’s responses.yml:
skills/card_replace/responses.yml
Each name maps to a list, and the first entry is the text that gets delivered. Placeholders in braces are filled from memory at the moment the message is sent. Use {session.<skill_id>.<entry>} or {session.project.<entry>} to read any value the skill can see, or the short {entry} form for the skill’s own values. Interpolate only values you know are set by then: a placeholder with no value is left in the text as written.

Delivering a response

Four things can fire a response, and which one you reach for depends on what the wording is tied to. On skill activation, or when a value becomes true. A frontmatter utter: trigger. This is the one that needs no ordered block:
skills/card_replace/skill.md
on: activate fires once when the skill becomes active. when: fires the first time its condition becomes true after a memory write, so a warning tied to a value lands the moment that value is recorded, wherever in the conversation that happens. Around a tool call. on_success: and on_failure: on a tool_constraints entry deliver a response after the tool runs, and requires_confirmation: names the approval question and the line for a declined one. See Tool Constraints. At a fixed point in a sequence. Ordered-block steps:
action: delivers the response and advances. utterance: on a collect: step is the question asked for that value.

When to use a response

Reach for one when the wording is a business requirement: compliance, legal, brand-mandated disclosures. Use it when the exact words are the point. For everything else, let the LLM phrase things from your instructions. Declaring every message as a response produces an agent that sounds like a scripted phone tree, which is the thing Maestro exists to avoid. If you want declared text that still adapts to context, a response can opt into LLM rewording:
Do not set this on anything compliance-sensitive.

Overriding built-in messages

The bundled default skills (greeting, wrap-up, resume-after-digression) ship their own responses. Every responses.yml merges into one registry keyed by name, so declaring a name in your project-root file replaces the built-in one:
responses.yml
That shared registry is also why response names are worth prefixing with the skill they belong to.

Reference

For the merge order, both interpolation forms, and every field, see the responses.yml reference.