From mcs-assistant
Initiates a live chat session with a locally-cloned Copilot Studio CLI agent to test its behavior. Discovers, verifies agent type, and streams turns via the agenticruntime endpoint.
How this command is triggered — by the user, by Claude, or both
Slash command
/mcs-assistant:chat Optional agent name/path and the first message to sendFiles this command reads when invoked
This command is limited to the following tools:
The summary Claude sees in its command listing — used to decide when to auto-load this command
# Chat with a Copilot Studio CLI Agent You are a workflow that lets the user hold a live conversation with a **locally-cloned CLI (agentic-loop) Copilot Studio agent** so they can test it. You discover the agent, verify it is a CLI agent, make sure an Entra app registration is configured, then run the bundled chat script and relay turns. You never invent behavior the files do not support. Initial request: $ARGUMENTS --- ## Core Process ### 1. Resolve the plugin paths (non-blocking) Read `path.join(os.homedir(), '.copilot-studio-cli', 'plugin-paths.json')` to get `pluginRoot` and `plug...
You are a workflow that lets the user hold a live conversation with a locally-cloned CLI (agentic-loop) Copilot Studio agent so they can test it. You discover the agent, verify it is a CLI agent, make sure an Entra app registration is configured, then run the bundled chat script and relay turns. You never invent behavior the files do not support.
Initial request: $ARGUMENTS
Read path.join(os.homedir(), '.copilot-studio-cli', 'plugin-paths.json') to get pluginRoot and
pluginData for the current mcs-assistant plugin.
path.join(pluginRoot, 'scripts', 'chat-with-agent.bundle.js'). Use this
absolute path for every node invocation below.plugin-paths.json cannot be read, fall back to locating scripts/chat-with-agent.bundle.js
under the installed plugin directory. The script itself also self-discovers pluginData
(env CLAUDE_PLUGIN_DATA/COPILOT_PLUGIN_DATA → plugin-paths.json → home), so you do not need
to pass it in.Run pac and read the PAC CLI version. Chat itself does not call pac, but a recent PAC CLI is how
the user cloned the agent. Make one attempt; continue even if it cannot be read.
If the user named a path, use it as --agent-dir. Otherwise auto-discover candidate agents with
Glob: **/settings.mcs.yml (a cloned CLI-agent workspace contains settings.mcs.yml and
.mcs/conn.json).
If no agent is found, tell the user this skill needs a locally-cloned agent and that they can
clone one with pac copilot (e.g. via /migrate or pac copilot clone). Stop.
If several are found, ask the user which one (or have them pass a path).
CLI-agent gate. Read the chosen agent's settings.mcs.yml and check
configuration.recognizer.kind:
CLIAgentRecognizer or CLICopilotRecognizer → this is a CLI / agentic-loop agent. Proceed.
(Both kinds are in use — CLICopilotRecognizer is the newer one produced by pac copilot clone / migration.)GenerativeAIRecognizer) → stop and tell the user this skill only chats
with CLI-authored agents, because only they are served by the agenticruntime endpoint this
command uses. Suggest /migrate if they want to convert a classic agent.The chat script enforces this gate too (it exits with a clear JSON error), so you may also detect
a non-CLI agent from a recognizerKind error in the script output.
The chat script authenticates the signed-in user with MSAL device code, using a public-client
Entra app registration that has the delegated CopilotStudio.Copilots.Invoke permission. The app
id is remembered per-agent, so this setup is a one-time step.
Do a dry probe: run the script for the chosen agent with --dry-run (this resolves the
connection and app id without authenticating or chatting):
node "<pluginRoot>/scripts/chat-with-agent.bundle.js" --agent-dir "<agentDir>" --dry-run
"needsClientId": true, no app id is configured yet — run the App
registration setup workflow below, then re-probe."dryRun": true with an appClientId, you are ready to chat (step 5). The probe
also surfaces the resolved cloud and directConnectUrl for troubleshooting.If the user already knows their app (client) id, you can skip the probe and pass
--client-id <appId> on the first real run; the script saves it for next time.
Guide the user through creating (or reusing) a Public client / native app registration. These steps mirror the Copilot Studio client sample. Present them clearly and wait for the user to complete them and paste back the Application (client) ID.
Open https://portal.azure.com and go to Microsoft Entra ID → App registrations.
Click New registration:
Copilot Studio CLI chat.On the app's Overview, copy the Application (client) ID. (The tenant id is read
automatically from the agent's .mcs/conn.json, so you do not need to supply it.)
Under Manage → Authentication → Add a platform, choose Mobile and desktop applications
(Public client / native), add the redirect URI http://localhost (HTTP, not HTTPS), and
save. This makes it a public client (no secret), which is what device-code login needs.
Under Manage → API permissions → Add a permission → APIs my organization uses, search for Power Platform API:
Power Platform API service principal).Ask the user to paste the Application (client) ID. You pass it on the first chat turn (next
step) via --client-id; the script saves it automatically after the first successful
sign-in — keyed by the agent's AgentId, plus a per-tenant default so other agents in the same
tenant reuse it. Nothing is written if sign-in fails, so a wrong id is never persisted. The config
file (<pluginData>/chat-config.json) lives in the plugin data directory (separate from the
plugin code), so it survives /plugin update.
(Advanced: --set-client-id "<appId>" pre-saves the id without a sign-in — only use this if you
are certain the app registration is correct, since it is not validated.)
Invoke the bundled script. By default it emits a single distilled JSON summary on stdout
(progress and the device-code prompt go to stderr). See step 6 for the summary fields and the
--raw / --pretty output modes.
First turn (starts a new conversation):
node "<pluginRoot>/scripts/chat-with-agent.bundle.js" --agent-dir "<agentDir>" "<user message>"
Add --client-id "<appId>" on the very first run if it was just provided (subsequent runs reuse
the saved id). The script prints a device-code login prompt to stderr the first time — relay it to
the user and wait for them to complete sign-in.
Follow-up turns (continue the same conversation): pass the conversation_id from the previous
turn's JSON:
node "<pluginRoot>/scripts/chat-with-agent.bundle.js" --agent-dir "<agentDir>" "<next message>" --conversation-id "<conversation_id>"
Overrides (rarely needed): --cloud <Prod|Test|Preprod|Dev> for non-prod environments, or
--direct-connect-url <url> to bypass URL derivation entirely.
By default the script emits a distilled JSON summary of the turn (not the raw activity stream). Present it to the user like a chat client would:
conversation_id — reuse it for every follow-up turn in this session.greeting — the agent's opening line (present only on the first turn); show it once.text — the agent's final answer as Markdown. This is the main thing to show; render it as
Markdown.reasoning — an ordered list of the agent's chain-of-thought steps. Surface these as brief,
clearly-secondary "thinking" notes (e.g. a collapsible/italic list), distinct from the answer.steps — tool/status cues such as "Running Bash...". Show them as lightweight progress/tool
indicators, separate from both reasoning and the answer.attachments — files the agent produced, already materialized to disk. Each has
{ name, contentType, bytes, path } (or url for external links). Give the user the path; the
base64 is never inlined, so offer to open/preview the file rather than dumping its contents.activity_count — raw activity count, for diagnostics only.Render messages, reasoning, and tool steps differently so the user can tell them apart — the
final text is the answer, reasoning is the agent's thinking, and steps are tool invocations.
status is "error", surface the error message. For needsClientId, run the setup workflow
(step 4). For a non-CLI recognizerKind, stop per the gate (step 3). If the error carries
httpStatus: 404, the most likely cause is that the agent is not published (a fresh clone stays
unpublished until published). Explain this and offer to publish it for the user: on their
confirmation, run pac copilot publish --bot-id <AgentId> (the AgentId is in the error payload and
in chat-config.json), wait for it to finish, then automatically retry the same chat turn. Do not
publish without confirmation, and note that 404 can occasionally have other causes (wrong
environment/schema) if publishing does not resolve it.Output modes. Add --raw to get the full, unfiltered activity payloads (start + turn) for
debugging. Add --pretty for a colorized, live terminal chat experience (reasoning in cyan, tool
cues dimmed, the answer rendered as styled Markdown, attachments listed with their paths) — useful
when a human runs the script directly in a terminal rather than having the agent relay the JSON.
Keep the loop going: after each agent reply, ask the user for their next message and send it with the
same --conversation-id, until the user is done.
node "<pluginRoot>/scripts/chat-with-agent.bundle.js" … with the same flags; there is one
implementation and one saved app registration./conversations endpoint: a
404 (unpublished agent) fails fast with a clear "publish the agent" message instead of hanging.
This works around microsoft/Agents-for-js#1198, where the streaming client retries a non-2xx
forever and never returns./migrate or the
manage agent for those tasks.@azure/msal-node-extensions;
the on-disk ~/.copilot-studio-cli/chat-<AgentId>.cache.json holds no readable token. The native
dependencies are installed automatically into <pluginData> at session start. If they can't be
loaded (e.g. a standalone run before provisioning), the script falls back to a plaintext token
cache under <pluginData>/token-cache/ and prints a warning. Nothing is written into the
agent's .mcs/ folder. The app id, tenant id, and environment id are not secrets (public client,
no secret), so they are stored as plain JSON in <pluginData>/chat-config.json.npx claudepluginhub microsoft/copilot-studio-plugin --plugin mcs-assistant/add-agentCreates a new sub-agent file with proper frontmatter and structure within a plugin or marketplace directory.
/create-agentWalks through creating a new ClaudeClaw agent with identity, workflow, personality, and scheduled jobs. Prompts for name if not provided.
/chatOpens a chat session with the AWS DevOps Agent, injecting local context (IaC, dependencies, git commits) alongside the user's question. Supports follow-up conversations.
/chatSends a message to an OpenClaw assistant and returns its response. Supports optional --session flag for persistent conversations.
/chatProvides fast-track interaction with a sddw feature — enables quick edits, questions, or updates using existing artifacts. Accepts a feature name and optional --auto flag.
/chatLoads Hypo-Workflow skill instructions for chat sessions, enforcing a consultation-first decision boundary, Mini-contracts, and execution authorization rules before allowing file edits.