agentleFS
MicrosoftKnown publishermicrosoft/Copilot-Managed-Runtime/plugins/copilot-managed-runtime/skills/add-data-source/SKILL.md

add-data-source

Skill4 starsChanged 9 days agoMITView on GitHub

Canonical add flow for Copilot Managed Runtime. Use when adding any data source through `ms app add data-source` (with `--as table` or `--as action`), or when the user wants help discovering which connector / api-id to use.

4 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

29 rules. 0 are common, 8 are distinctive, and 21 are very specific to this project.

  • 0

    Common

    Most of the 4 edited versions we read keep these.

  • 8

    Distinctive

    This author's own choices. Worth a look.

  • 21

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    If this skill is called from a wrapper, do not delegate back

    line 19
  2. Distinctive:

    If this skill is called directly, complete the workflow without delegation

    line 20
  3. Distinctive:

    If invoked via a specialized skill → Refer to that specialized skill's documentation for usage patterns (it was already provided)

    line 23
  4. Distinctive:

    If invoked directly → Identify which specialized skill matches your use case and refer to its documentation for:

    line 24
  5. Very specific:

    Run the matching ms app add ...

    line 36
  6. Very specific:

    Check for a shared connection and declare allowedActions if so.

    line 37
  7. Very specific:

    Wrapper preset: If invoked by a specialized /add-* skill (see "Common Presets" below), use the preset api-id and skip discovery.

    line 73
  8. Very specific:

    Caller-supplied: If $ARGUMENTS includes an api-id (e.g., api-id=shared_office365), use it verbatim.

    line 74
  9. Very specific:

    User-supplied verbatim string: If the user already typed an api-id (anything matching the shared_* / microsoftcopilotstudio shape, or a …

    line 75
  10. Very specific:

    Treat dataverse and "Microsoft Dataverse" as ambiguous service names, not exact connector IDs.

    line 95
  11. Distinctive:

    Use the older connector only when the user explicitly requests it.

    line 97
  12. Very specific:

    Use table mode for a fixed, existing table.

    line 99
  13. Very specific:

    Use action mode when users choose the organization URL or entity-set name inside the app.

    line 100
  14. Distinctive:

    When user intent is about knowledge retrieval / grounded Microsoft 365 search summaries (for example: "analyze M365 content", "search my …

    line 105
  15. Very specific:

    If they insist on /add-data-source, proceed but after adding the connector, refer them to the /add-workiq skill documentation so they …

    line 120
  16. Distinctive:

    If the caller is a wrapper skill, use wrapper presets as defaults and only ask for missing fields.

    line 132
  17. Very specific:

    All modes use the single ms app add data-source command.

    line 136
  18. Very specific:

    Do not pass --dataset. Run once per table.

    line 160
  19. Very specific:

    Add --dataverse-environment-id <environment-guid> only when targeting a specific environment.

    line 161
  20. Very specific:

    If omitted, the CLI uses the app environment.

    line 162
  21. Very specific:

    After a Dataverse add, check the new reference in ms.config.json.

    line 169
  22. Very specific:

    Check that the generated service uses that reference.

    line 171
  23. Very specific:

    If the binding is wrong, stop and report the mismatch.

    line 172
  24. Very specific:

    Check required operations with ms connector list-actions --connector shared_commondataserviceforapps --json.

    line 175
  25. Distinctive:

    If policy blocks a required operation, report the restriction.

    line 177
  26. Very specific:

    If it prints OK, skip to Step 5 — the connection isn't shared, or is already covered.

    line 214
  27. Very specific:

    Deferral — when there is no app code yet: If src/ has no calls into this service because the app hasn't been written yet (the usual case …

    line 233
  28. Very specific:

    Leave allowedActions unset for now.

    line 237
  29. Very specific:

    If memory-bank.md exists, record api-id, mode, parameters used, and — when the reference is shared — the allowedActions that were agreed, …

    line 257

“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

📋 Shared Instructions: shared-instructions.md — Cross-cutting concerns.

Reference: connector-reference.md — Inline connection creation, Grep-first for large generated files.

Reference: allowed-actions.md — Shared connections must declare allowedActions before deploy (Step 4).

Add Data Source (Canonical)

This is the single implementation for all connector-binding skills.

Delegation model:

  • Specialized /add-* skills (e.g., /add-office365, /add-workiq) delegate to this skill with presets
  • If this skill is called from a wrapper, do not delegate back
  • If this skill is called directly, complete the workflow without delegation

After the connector is added:

  • If invoked via a specialized skill → Refer to that specialized skill's documentation for usage patterns (it was already provided)
  • If invoked directly → Identify which specialized skill matches your use case and refer to its documentation for:
    • Correct import paths for generated services
    • Best practices for using the connector
    • Common patterns and implementation examples
    • Error handling guidance

This ensures developers have complete context for implementing features, not just adding the connector.

Workflow

  1. Verify workspace + auth.
  2. Resolve api-id (discover via ms connector list if the user didn't supply one), mode, and required arguments.
  3. Run the matching ms app add ... command.
  4. Check for a shared connection and declare allowedActions if so.
  5. Run npm run build.
  6. Record the binding in memory-bank.md if present.

Step 1: Verify Project + Env

test -f ms.config.json || { echo "Not in a Microsoft App workspace."; exit 1; }
BIN=ms
$BIN auth status

Step 2: Resolve Inputs

Collect:

  • api-id (required — see resolution order below). Passed to the CLI via --connector <api-id>.
  • mode = action | table (controls the --as flag). There is no procedure mode — binding a specific SQL stored procedure is not exposed by the current CLI (see note below).
  • connection-id (optional interactive, required for non-interactive where applicable)

Additional by mode:

  • table: dataset, table. Dataverse uses a table logical name without dataset, plus an optional dataverse-environment-id.

SQL stored procedures: the CLI has no ms app add procedure command and ms app add data-source does not accept --sql-stored-procedure. You can still add the SQL data source as a table (--connector shared_sql --as table --dataset <db> --table <tbl>), but binding a specific stored procedure is not currently supported.

2a. Resolve api-id

Try sources in this order; stop at the first one that yields a value:

  1. Wrapper preset. If invoked by a specialized /add-* skill (see "Common Presets" below), use the preset api-id and skip discovery.
  2. Caller-supplied. If $ARGUMENTS includes an api-id (e.g., api-id=shared_office365), use it verbatim.
  3. User-supplied verbatim string. If the user already typed an api-id (anything matching the shared_* / microsoftcopilotstudio shape, or a string they explicitly call an api-id), use it. Apply the Dataverse rule below to ambiguous service names.
  4. Discovery via ms connector list. Do not ask the user to type an api-id from memory. Instead:

    a. Ask one question: "Which connector do you need? (a short keyword like 'teams', 'sql', 'sharepoint', 'salesforce' is fine — I'll search the catalog.)" Capture the keyword as {term}.

    b. Search the catalog:

    $BIN connector list --search "<term>"

    Parse the output into a short table (display name + api-id). If the result set is large (more than ~10 rows), narrow with a more specific term and re-run rather than dumping everything.

    c. Present the candidates to the user via AskUserQuestion with the display names as choices (and api-ids in parentheses for transparency). Map their selection back to the api-id; never ask them to retype it.

    d. If ms connector list --search "<term>" returns no results, fall back to ms connector list with no filter, surface a representative slice, and ask the user to refine the term. Do not proceed with a guessed api-id.

  5. Validation. Once an api-id is chosen, confirm it's real before spending a build cycle on it: $BIN connector list-actions --connector <api-id> --search "" should succeed. If the CLI replies that the api-id is unknown, drop back to step 4 — don't keep retrying with the same value.

Dataverse intent hint

For Dataverse requests, use shared_commondataserviceforapps. Treat dataverse and "Microsoft Dataverse" as ambiguous service names, not exact connector IDs. Both the current connector and the older shared_commondataservice connector use that display name. Use the older connector only when the user explicitly requests it.

Use table mode for a fixed, existing table. Use action mode when users choose the organization URL or entity-set name inside the app. Preserve the caller's selected mode. Do not ask for a fixed table in action mode.

Work IQ intent hint

When user intent is about knowledge retrieval / grounded Microsoft 365 search summaries (for example: "analyze M365 content", "search my email and Teams", "knowledge-grounded query"), default to:

  • api-id: shared_a365copilotchatmcp
  • mode: action

⚠️ IMPORTANT: If the user is adding Work IQ via /add-data-source, ask them to use /add-workiq instead.

Why: Work IQ uses MCP (Model Context Protocol), a stateful protocol that requires special handling. The /add-workiq skill provides:

  • Complete McpSession wrapper class (handles session initialization, auto-retry, response parsing)
  • Best practices for structuring prompts
  • Error handling patterns
  • Multi-turn conversation support

Guidance: "I can add the connector, but for Work IQ I recommend using /add-workiq — it provides a production-ready McpSession class and comprehensive patterns to avoid common errors. Would you like to use /add-workiq instead?"

If they insist on /add-data-source, proceed but after adding the connector, refer them to the /add-workiq skill documentation so they understand the McpSession requirement.

2b. Resolve mode

For Dataverse, use the intent rule above. For other api-ids in the "Common Presets" table, use that table's mode. Otherwise ask the user one question, framed by what they want to do:

  • "Read or write rows in a tabular store?" → table
  • "Trigger an operation (send a message, post a file, list events)?" → action

mode selects the --as flag. Tabular connectors (e.g. SharePoint, SQL) support both; in non-interactive runs --as is required for them. Action-only connectors ignore --as.

If the caller is a wrapper skill, use wrapper presets as defaults and only ask for missing fields.

Step 3: Execute Add Command

All modes use the single ms app add data-source command; --as chooses table vs action. The connector is passed via --connector (there is no --api-id flag).

Deprecated alias: ms app add connector still works but is deprecated — prefer ms app add data-source. Both share the same handler and flags.

Action mode

$BIN app add data-source --connector <api-id> --as action

Table mode (other connectors)

$BIN app add data-source --connector <api-id> --as table --dataset "<dataset>" --table "<table>"

Dataverse table mode

$BIN app add data-source --connector shared_commondataserviceforapps --as table --table "<logical-name>"

Do not pass --dataset. Run once per table. Add --dataverse-environment-id <environment-guid> only when targeting a specific environment. If omitted, the CLI uses the app environment. For runtime-selected organizations and tables, use the action command without --table or --dataverse-environment-id. In interactive action mode, decline the optional prompt to bind a specific Dataverse table.

The CLI resolves connections inline. Pass --connection-id <id> or -c <id> when a specific connection is required. See connector-reference.md for connection selection.

After a Dataverse add, check the new reference in ms.config.json. Its id must be /providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps, unless the user explicitly requested the older connector. Check that the generated service uses that reference. If the binding is wrong, stop and report the mismatch. Do not change only the ID in the config. Regenerate services and update app calls and shared allowedActions when replacing an older binding.

Check required operations with ms connector list-actions --connector shared_commondataserviceforapps --json. For a runtime-selected organization, inspect the *WithOrganization operations and their generated signatures. If policy blocks a required operation, report the restriction. Do not substitute the older connector or bypass policy.

SQL stored procedures have no ms app add procedure command and --sql-stored-procedure is not accepted by ms app add data-source; binding a specific stored procedure is not currently supported.

Step 4: Shared Connection Policy (allowedActions)

Do this before the build, on every add. The CLI writes sharedConnectionId automatically when the connection's auth type is shareable, so this can trigger without the user asking for it — and it doesn't surface as a build error, it surfaces later as a deploy failure.

4a. Read the config back and check the reference that was just written. Node 22+ is a project prerequisite, so this works in bash and PowerShell alike:

node -e '
const fs = require("fs");
const refs = JSON.parse(fs.readFileSync("ms.config.json", "utf8")).connectionReferences || {};
const ok = (a) => Array.isArray(a) && a.length > 0 &&
  a.every((x) => typeof x === "string" && /\S/.test(x));
let bad = 0;
for (const [name, r] of Object.entries(refs)) {
  if (!String(r.sharedConnectionId || "").trim()) continue;
  const t = Object.entries(r.dataSets || {}).flatMap(([d, s]) =>
    Object.entries(s.dataSources || {}).map(([k, v]) => [d + "/" + k, v]));
  if (r.allowedActions !== undefined && !ok(r.allowedActions)) {
    bad++;
    console.log("INVALID connector-level allowedActions: " + name);
  }
  if (t.length) {
    for (const [p, v] of t) if (!ok(v.allowedActions)) { bad++; console.log("MISSING per-table allowedActions: " + name + " -> " + p); }
  } else if (r.allowedActions === undefined) { bad++; console.log("MISSING connector-level allowedActions: " + name); }
}
if (bad) { console.log(bad + " issue(s): fix before deploy"); process.exitCode = 1; } else console.log("OK: all shared references declare allowedActions");
'

If it prints OK, skip to Step 5 — the connection isn't shared, or is already covered.

4b. If it is shared, determine the shape:

Reference has…Declare
dataset tables (dataSets)per-table allowedActions — every table, from "get" / "post" / "patch" / "delete"
no dataset tablesconnector-level allowedActions — Action IDs from ms connector list-actions --connector <api-id> --json (id, behavior: Allow only)

4c. Infer least privilege, then confirm. Grep src/ for calls into the generated service. For dataset tables, map read/list to get, create to post, update to patch, and delete to delete. For action references, use the exact invoked operation IDs from ms connector list-actions. Present the inferred list and ask the user to confirm or adjust:

"<reference> is a shared connection, so it needs an action policy before deploy. From the code, I'd declare <inferred>. Anything else it should be allowed to do?"

Never grant the full set just to pass validation.

Deferral — when there is no app code yet. If src/ has no calls into this service because the app hasn't been written yet (the usual case when /create-app invokes this skill before generating the UI), do not guess and do not prompt. Instead:

  • Leave allowedActions unset for now. ms app dev does not validate it, so local iteration is unaffected — only ms app pack / ms app deploy do.
  • Record the reference as shared, policy pending in memory-bank.md.
  • Note it in your summary so the decision happens once the app code exists.

/deploy re-runs this same check as a preflight gate, so a deferred policy is caught before it can reach a failing deploy — not silently forgotten.

4d. Write the confirmed values into ms.config.json (skip when deferring).

Full rules, worked examples, and failure recovery: allowed-actions.md.

Step 5: Build

npm run build

Step 6: Memory Update

If memory-bank.md exists, record api-id, mode, parameters used, and — when the reference is shared — the allowedActions that were agreed, so the next session doesn't re-litigate them.


Common Presets

Wrapper skillapi-idmode
/add-dataverseshared_commondataserviceforappstable or action by intent
/add-sharepointshared_sharepointonlinetable
/add-excelshared_excelonlinebusinesstable
/add-office365shared_office365action
/add-office365-usersshared_office365usersaction
/add-teamsshared_teamsaction
/add-onedriveshared_onedriveforbusinessaction
/add-azuredevopsshared_visualstudioteamservicesaction
/add-mcscopilotmicrosoftcopilotstudioaction
/add-workiqshared_a365copilotchatmcpaction

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.