$npx -y skills add microsoft/skills-for-copilot-studio --skill new-topicCreate a new Copilot Studio topic YAML file. Use when the user asks to create a new topic, conversation flow, or dialog for their agent.
| 1 | # Create New Topic |
| 2 | |
| 3 | Generate a new Copilot Studio topic YAML file based on user requirements. |
| 4 | |
| 5 | ## Instructions |
| 6 | |
| 7 | 1. **Auto-discover the agent directory**: |
| 8 | ``` |
| 9 | Glob: **/agent.mcs.yml |
| 10 | ``` |
| 11 | If multiple agents found, ask which one. NEVER hardcode an agent name. |
| 12 | |
| 13 | 2. **Check for matching templates** in `${CLAUDE_SKILL_DIR}/../../templates/topics/` first: |
| 14 | - `greeting.topic.mcs.yml` — OnConversationStart greeting |
| 15 | - `fallback.topic.mcs.yml` — OnUnknownIntent fallback with escalation |
| 16 | - `arithmeticsum.topic.mcs.yml` — Topic with inputs/outputs and computation |
| 17 | - `question-topic.topic.mcs.yml` — Question with branching logic |
| 18 | - `search-topic.topic.mcs.yml` — Generative answers from knowledge |
| 19 | - `auth-topic.topic.mcs.yml` — Authentication flow |
| 20 | - `error-handler.topic.mcs.yml` — Error handling |
| 21 | - `disambiguation.topic.mcs.yml` — Multiple topics matched |
| 22 | If a template matches, use it as the starting point. |
| 23 | |
| 24 | 3. **MANDATORY: Verify ALL `kind:` values against the schema** before writing them: |
| 25 | ```bash |
| 26 | node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js kinds # List all valid kind values |
| 27 | node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js resolve AdaptiveDialog # Resolve trigger structure |
| 28 | node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js resolve <TriggerType> # Resolve specific trigger |
| 29 | node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js search <ActionKind> # Verify an action kind exists |
| 30 | ``` |
| 31 | **NEVER write a `kind:` value you haven't verified exists in the schema.** This is the #1 source of hallucination errors. If `schema-lookup.bundle.js search <kind>` returns no results, the kind does NOT exist — do not use it. |
| 32 | |
| 33 | 4. **Determine the trigger type** from the user's description: |
| 34 | - `OnRecognizedIntent` — For topics triggered by user phrases (most common) |
| 35 | - `OnConversationStart` — For welcome/greeting topics |
| 36 | - `OnUnknownIntent` — For fallback topics |
| 37 | - `OnEscalate` — For escalation to human agent |
| 38 | - `OnError` — For error handling |
| 39 | |
| 40 | 5. **Generate the topic YAML** with: |
| 41 | - A `# Name:` comment at the top |
| 42 | - `kind: AdaptiveDialog` |
| 43 | - Appropriate `beginDialog` with correct trigger |
| 44 | - **Unique IDs** for ALL nodes (format: `<nodeType>_<6-8 random alphanumeric>`) |
| 45 | - If using a template, replace ALL `_REPLACE` placeholders with unique IDs |
| 46 | |
| 47 | 6. **Check settings.mcs.yml** for `GenerativeActionsEnabled`. Read the agent's `settings.mcs.yml` to check. |
| 48 | |
| 49 | 7. **Save** to the agent's `topics/<topic-name>.topic.mcs.yml` directory |
| 50 | |
| 51 | 8. **MANDATORY: Validate the generated file** after saving: |
| 52 | |
| 53 | **Step A: Schema validation** — always run this first: |
| 54 | ```bash |
| 55 | node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js validate <saved-file.yml> |
| 56 | ``` |
| 57 | |
| 58 | **Step B: LSP-based validation** — also run this if the agent has `.mcs/conn.json`: |
| 59 | Read `.mcs/conn.json` to get connection details, then: |
| 60 | ```bash |
| 61 | node ${CLAUDE_SKILL_DIR}/../../scripts/manage-agent.bundle.js validate \ |
| 62 | --workspace "<path-to-agent-folder>" \ |
| 63 | --tenant-id "<tenantId>" \ |
| 64 | --environment-id "<envId>" \ |
| 65 | --environment-url "<envUrl>" \ |
| 66 | --agent-mgmt-url "<mgmtUrl>" |
| 67 | ``` |
| 68 | |
| 69 | Both validations are complementary: schema validation checks structural correctness (action kinds, property placement), while LSP validation checks Power Fx expressions, cross-file references, and environment-specific rules. If either fails, fix the issues before reporting success to the user. |
| 70 | |
| 71 | ## Generative Orchestration Guidelines |
| 72 | |
| 73 | When the agent has `GenerativeActionsEnabled: true` in settings: |
| 74 | |
| 75 | **Use Topic Inputs** (AutomaticTaskInput) instead of Question nodes to auto-collect user info. |
| 76 | Place `inputs` at the **AdaptiveDialog root level** (NOT inside `beginDialog`): |
| 77 | ```yaml |
| 78 | kind: AdaptiveDialog |
| 79 | inputs: # <-- at AdaptiveDialog root, NOT inside beginDialog |
| 80 | - kind: AutomaticTaskInput |
| 81 | propertyName: userName |
| 82 | description: "The user's name" |
| 83 | entity: StringPrebuiltEntity |
| 84 | shouldPromptUser: true |
| 85 | beginDialog: |
| 86 | kind: OnRecognizedIntent |
| 87 | id: main |
| 88 | actions: |
| 89 | - ... |
| 90 | ``` |
| 91 | - The orchestrator auto-collects inputs based on the description — no explicit Question node needed. |
| 92 | - Still use Question nodes when: conditional asks (ask X only if Y), or end-of-flow confirmations. |
| 93 | |
| 94 | **Use Topic Outputs** instead of SendActivity for final results. |
| 95 | Use `outputType` at the root level and `SetVariable` to set output values — do NOT use `TaskOutput` (which is only valid in `TaskDialog` connector actions): |
| 96 | ```yaml |
| 97 | kind: AdaptiveDialog |
| 98 | inputs: |
| 99 | - ... |
| 100 | beginDialog: |
| 101 | kind: |