The smallest possible rung. Four skills and no infrastructure: each SKILL.md is copied verbatim into an InlineAgentSkill behavior and the instructions route to it. This is the agent whose solution you can export from Copilot Studio unchanged.
| Input | Becomes |
|---|---|
agent-author/SKILL.md, brainstem-doctor/SKILL.md | two InlineAgentSkill behaviors carrying the SKILL.md text verbatim |
hello_world_agent.py, skill_advisor_agent.py | two reasoning-only skills that carry the agent's contract and code (no live tool; the agent says so) |
| a one-paragraph description | settings.mcs.yml: display name, schema name, CLICopilotRecognizer, Sonnet 4.6, instructions with one routing line per skill |
The workspace is generated by a RAPP brainstem's MakeCopilotStudioAgent tool (any brainstem that carries agents/copilot_studio_agent.py) and deployed through this repo's deploy script. Without a brainstem, write the same workspace by hand: one behaviors/<prefix>_<skill>.mcs.yml per skill, then deploy.
# through a brainstem's /chat (the tool takes the same arguments):
# "Make a Copilot Studio agent named 'RAPP Brainstem Skills Demo' with the
# brainstem-doctor and agent-author skills and the HelloWorldAgent and
# SkillAdvisor agents; deploy it to https://<org>.crm.dynamics.com/"
#
# or directly from a built workspace:
node scripts/deploy-harness-agent.mjs --name "RAPP Brainstem Skills Demo" --publisher-prefix rapp \
--schema-name rapp_RAPPBrainstemSkillsDemo --environment https://<org>.crm.dynamics.com/ \
--workspace-dir ./workspace --work-dir ./.deploy/demo \
--token-command "az account get-access-token --resource https://<org>.crm.dynamics.com/ --tenant <tenant> --query accessToken -o tsv"
A behavior file looks like this (the SKILL.md is indented under content, nothing rewritten):
mcs.metadata:
componentName: "brainstem-doctor"
description: "Check a RAPP brainstem's health: capabilities, quarantine, execution profile."
kind: InlineAgentSkill
content: |
---
name: brainstem-doctor
description: Check a RAPP brainstem's health ...
---
# Brainstem doctor
...
This agent has no tools, so anonymous Direct Line is enough: the prover flips the bot to no-auth, publishes, sends the turns through the SDK's agentic-directline mode, and restores the auth mode.
node tools/prove-copilot.mjs --environment-url https://<org>.crm.dynamics.com/ --environment-id <env-id> \
--bot-id <bot-id> --schema rapp_RAPPBrainstemSkillsDemo --turns turns.json --no-auth --restore
| Prompt | Expected | Answer (15 Sep 2026) |
|---|---|---|
| What skills do you have? List their names. | agent-author, brainstem-doctor | a table of the installed skills, both named |
| Greet Ada using your hello world capability and quote what it would say. | Hello, Ada | "Hello, Ada! Welcome to the RAPP Agent ecosystem." with the note that the helloworldagent skill was used |
| Is my brainstem healthy? Use the brainstem-doctor skill. | a report naming skills | reports that the skill's scripts/check.py is not shipped in this deployment and gives a manual inspection instead |
The third answer is the honest one: a SKILL.md that expects a script beside it cannot run that script in Copilot Studio unless the script ships too. That is rung 3.
rappRAPPBrainstemSkillsDemoHarness.exported.zip is the unmanaged solution exported from Copilot Studio with pac solution export, unmodified: one bot, four bot components. It contains no environment-specific values. Import it into any environment with the harness enabled and publish; nothing from RAPP is needed. See the manual way.