$npx -y skills add microsoft/skills-for-copilot-studio --skill clone-agentClone a Copilot Studio agent from the cloud. Guides through environment selection, agent selection, and downloads agent YAML files.
| 1 | # Clone Agent |
| 2 | |
| 3 | Guided flow to clone a Copilot Studio agent from the cloud to a local workspace. Walks the user through environment selection, agent selection, and downloads the agent's YAML files. |
| 4 | |
| 5 | ## IMPORTANT: Do Not Modify Scripts |
| 6 | |
| 7 | This is a new capability under active development. If the manage-agent script fails, **do not attempt to fix, patch, or work around it**. Instead: |
| 8 | 1. Show the user the full error output |
| 9 | 2. Direct them to https://github.com/microsoft/skills-for-copilot-studio/issues |
| 10 | 3. Suggest using the Copilot Studio VS Code extension directly as a fallback for push/pull/clone |
| 11 | |
| 12 | ## Phase 0: Resolve Configuration |
| 13 | |
| 14 | Look for existing connection details in this order. Stop at the first source that provides a `tenantId`: |
| 15 | |
| 16 | ### 0a. Scan for existing `.mcs/conn.json` files |
| 17 | |
| 18 | Search the filesystem for previously cloned agents — these already have all the connection details: |
| 19 | |
| 20 | ``` |
| 21 | Glob: **/.mcs/conn.json |
| 22 | ``` |
| 23 | |
| 24 | Also search common project locations: |
| 25 | |
| 26 | ``` |
| 27 | Glob: /Users/**/projects/**/.mcs/conn.json |
| 28 | ``` |
| 29 | |
| 30 | Each `conn.json` contains `TenantId`, `EnvironmentId`, `DataverseEndpoint`, `AgentManagementEndpoint`, and `AccountInfo`. Parse any found files and collect unique tenant/environment pairs. If matches are found, present them to the user: |
| 31 | |
| 32 | > **Found existing agent connections:** |
| 33 | > 1. Employee Assistant — Elad's Env (tenant: 8a235459...) |
| 34 | > 2. IT Agent — Contoso Dev (tenant: efb073bb...) |
| 35 | > |
| 36 | > Use one of these, or enter a different tenant ID? |
| 37 | |
| 38 | If the user picks one → extract `tenantId`, `environmentId`, `environmentUrl`, `agentMgmtUrl` and **skip to Phase 2** (or Phase 1 if they want a different environment). |
| 39 | |
| 40 | ### 0b. Check for a Copilot Studio URL |
| 41 | |
| 42 | If the user pastes a Copilot Studio URL (e.g. from their browser while viewing the agent), extract environment and agent IDs directly — no need for `list-envs` or `list-agents`. |
| 43 | |
| 44 | Recognised URL formats: |
| 45 | ``` |
| 46 | https://copilotstudio.microsoft.com/environments/<envId>/bots/<agentId>/overview |
| 47 | https://copilotstudio.preview.microsoft.com/environments/<envId>/bots/<agentId> |
| 48 | ``` |
| 49 | |
| 50 | If the user provides a URL like this, you still need a `tenantId` (from a `conn.json` or by asking the user). Then **skip to Phase 3**, passing `--url` instead of `--agent-id` / `--environment-id` / `--environment-url` / `--agent-mgmt-url`: |
| 51 | |
| 52 | ```bash |
| 53 | node ${CLAUDE_SKILL_DIR}/../../scripts/manage-agent.bundle.js clone \ |
| 54 | --workspace "." \ |
| 55 | --tenant-id "<tenantId>" \ |
| 56 | --url "<copilotStudioUrl>" |
| 57 | ``` |
| 58 | |
| 59 | The script will parse the URL to extract the environment ID and agent ID, then resolve the remaining environment details (Dataverse URL, agent management URL) automatically via the BAP API. |
| 60 | |
| 61 | ### 0c. Ask the user |
| 62 | |
| 63 | If no `conn.json` found (or user wants a different tenant) → ask for their **tenant ID** (required). |
| 64 | |
| 65 | No `--client-id` is needed — the script uses VS Code's first-party client ID with interactive browser login automatically. |
| 66 | |
| 67 | ## Phase 1: Select Environment |
| 68 | |
| 69 | Tell the user: **"A browser window may open for Microsoft sign-in (tokens are cached after first login)."** |
| 70 | |
| 71 | Run the list-envs command: |
| 72 | |
| 73 | ```bash |
| 74 | node ${CLAUDE_SKILL_DIR}/../../scripts/manage-agent.bundle.js list-envs \ |
| 75 | --tenant-id "<tenantId>" |
| 76 | ``` |
| 77 | |
| 78 | **Timeout: 300000ms (5 minutes)** — set this on the Bash tool call to allow time for browser auth. |
| 79 | |
| 80 | Parse the JSON output. On success (`status: "ok"`), present the environments as a numbered list to the user: |
| 81 | |
| 82 | ``` |
| 83 | 1. Contoso Dev (abc123-...) |
| 84 | 2. Contoso Prod (def456-...) |
| 85 | ``` |
| 86 | |
| 87 | Ask the user to pick an environment. Extract: |
| 88 | - `environmentId` |
| 89 | - `environmentUrl` (the `url` or `dataverseUrl` field) |
| 90 | - `agentMgmtUrl` (the `agentManagementUrl` field) |
| 91 | |
| 92 | ## Phase 2: Select Agent |
| 93 | |
| 94 | First, ask the user: **"Do you want to list only agents you own, or all agents in the environment?"** |
| 95 | |
| 96 | - If **only mine** → run without `--no-owner` (default, filters by current user) |
| 97 | - If **all agents** → add `--no-owner` flag |
| 98 | |
| 99 | ```bash |
| 100 | node ${CLAUDE_SKILL_DIR}/../../scripts/manage-agent.bundle.js list-agents \ |
| 101 | --tenant-id "<tenantId>" \ |
| 102 | --environment-url "<environmentUrl>" \ |
| 103 | [--no-owner] |
| 104 | ``` |
| 105 | |
| 106 | **Timeout: 300000ms (5 minutes)** |
| 107 | |
| 108 | Parse the JSON output. Each agent has `agentId`, `displayName`, and `ownedByCurrentUser`. Present agents as a numbered list: |
| 109 | |
| 110 | ``` |
| 111 | 1. My Support Bot (yours) |
| 112 | 2. HR Assistant |
| 113 | 3. IT Helpdesk (yours) |
| 114 | ``` |
| 115 | |
| 116 | Ask the user to pick an agent. Extract the `agentId`. |
| 117 | |
| 118 | ## Phase 3: Clone |
| 119 | |
| 120 | Run the clone command. The workspace should be the current directory (`.`). The `--agent-id` is required (from Phase 2): |
| 121 | |
| 122 | ```bash |
| 123 | node ${CLAUDE_SKILL_DIR}/../../scripts/manage-agent.bundle.js clone \ |
| 124 | --workspace "." \ |
| 125 | --tenant-id "<tenantId>" \ |
| 126 | --agent-id "<agentId>" \ |
| 127 | --environment-id "<environmentId>" \ |