# Add Sample Data

> >-

- **Type:** Skill
- **Install:** `agentstack add skill-microsoft-power-platform-skills-add-sample-data`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [microsoft](https://agentstack.voostack.com/s/microsoft)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [microsoft](https://github.com/microsoft)
- **Source:** https://github.com/microsoft/power-platform-skills/tree/main/plugins/power-pages/skills/add-sample-data
- **Website:** https://aka.ms/ppskills

## Install

```sh
agentstack add skill-microsoft-power-platform-skills-add-sample-data
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

> **Plugin check**: Run `node "${PLUGIN_ROOT}/scripts/check-version.js"` — if it outputs a message, show it to the user before proceeding.

# Add Sample Data

Populate Dataverse tables with sample records via OData API so users can test and demo their Power Pages sites.

## Core Principles

- **Respect insertion order**: Always insert parent/referenced tables before child/referencing tables so lookup IDs are available when needed.
- **Use TaskCreate/TaskUpdate**: Track all progress throughout all phases -- create the todo list upfront with all phases before starting any work.
- **Fail gracefully**: On insertion failure, log the error and continue with remaining records -- never attempt automated rollback.

**Initial request:** $ARGUMENTS

---

## Phase 1: Verify Prerequisites

**Goal**: Confirm PAC CLI auth, acquire an Azure CLI token, and verify API access

**Actions**:

1. Create todo list with all 6 phases (see [Progress Tracking](#progress-tracking) table)
2. Follow the prerequisite steps in `${PLUGIN_ROOT}/references/dataverse-prerequisites.md` to verify PAC CLI auth, acquire an Azure CLI token, and confirm API access. Note the environment URL as `` for subsequent script calls.

**Output**: Authenticated session with valid token and confirmed API access

---

## Phase 2: Discover Tables

**Goal**: Find the custom tables available in the user's Dataverse environment

**Actions**:

### Path A: Read `.datamodel-manifest.json` (Preferred)

Check if `.datamodel-manifest.json` exists in the project root (written by the `setup-datamodel` skill). If it exists, read it -- it already contains table logical names, display names, and column info.

See `${PLUGIN_ROOT}/references/datamodel-manifest-schema.md` for the full manifest schema.

### Path B: Query OData API (Fallback)

If no manifest exists, discover custom tables via OData:

```
node "${PLUGIN_ROOT}/scripts/dataverse-request.js"  GET "EntityDefinitions?\$select=LogicalName,DisplayName,EntitySetName&\$filter=IsCustomEntity eq true"
```

For each discovered table, fetch its custom columns:

```
node "${PLUGIN_ROOT}/scripts/dataverse-request.js"  GET "EntityDefinitions(LogicalName='')/Attributes?\$select=LogicalName,DisplayName,AttributeType,RequiredLevel&\$filter=IsCustomAttribute eq true"
```

### 2.1 Present Available Tables

Show the user the list of discovered tables with their columns so they can choose which to populate.

**Output**: List of discovered tables with their columns presented to the user

---

## Phase 3: Select Tables & Configure

**Goal**: Gather user preferences on which tables to populate and how many records to create

**Actions**:

### 3.1 Select Tables

> 🚦 **Gate (plan · add-sample-data:3.1.tables):** Multi-select over discovered tables — decides which tables get populated with sample data.
>
> **Trigger:** Phase 2 discovery completed.
> **Why we ask:** Auto-selecting all tables can pollute production-shape tables (e.g. `contact`) with throwaway records.
> **Cancel leaves:** Nothing — no record inserts yet.

Use `AskUserQuestion` to ask which tables they want to populate (use `multiSelect: true`). List all discovered tables as options.

### 3.2 Select Record Count

> 🚦 **Gate (plan · add-sample-data:3.2.count):** Pick records-per-table (5 / 10 / 25 / Custom). Custom branch is a follow-up free-text prompt under the same gate.
>
> **Trigger:** Tables selected in 3.1.
> **Why we ask:** Inserting hundreds of records can blow past Dataverse storage / API throttling budgets.
> **Cancel leaves:** Nothing — no record inserts yet.

Use `AskUserQuestion` to ask how many sample records per table:

| Option | Description |
|--------|-------------|
| **5 records** | Quick test -- just enough to verify the setup |
| **10 records** | Light demo data for basic testing |
| **25 records** | Fuller dataset for realistic demos |
| **Custom** | Let the user specify a number |

### 3.3 Determine Insertion Order

Analyze relationships between selected tables. Parent/referenced tables must be inserted first so their IDs are available for child/referencing table lookups.

Build the insertion order:

1. Tables with no lookup dependencies (parent tables) -- insert first
2. Tables that reference already-inserted tables -- insert next
3. Continue until all tables are ordered

**Output**: Confirmed table selection, record count, and insertion order

---

## Phase 4: Generate & Review Sample Data

**Goal**: Generate contextually appropriate sample records and get user approval before inserting

**Actions**:

### 4.1 Generate Contextual Sample Data

For each selected table, generate sample records with contextually appropriate values based on column names and types:

- **String columns**: Generate realistic values matching the column name (e.g., "Email" -> `jane.doe@example.com`, "Phone" -> `(555) 123-4567`, "Name" -> realistic names)
- **Memo columns**: Generate short descriptive text relevant to the column name
- **Integer/Decimal/Currency columns**: Generate reasonable numeric values
- **DateTime columns**: Generate dates within a sensible range (past year to next month)
- **Boolean columns**: Mix of `true` and `false` values
- **Picklist/Choice columns**: Query valid options first (see references/odata-record-patterns.md), then use actual option values
- **Lookup columns**: Reference records from parent tables that will be/were already inserted

### 4.2 Present Sample Data Preview

For each table, show a markdown table previewing the sample records directly in the conversation:

```markdown
### Project (cr123_project) -- 5 records

| Name | Description | Status | Start Date |
|------|-------------|--------|------------|
| Website Redesign | Modernize the corporate website | 100000000 (Active) | 2025-03-15 |
| Mobile App | Build iOS and Android app | 100000001 (Planning) | 2025-04-01 |
| ... | ... | ... | ... |
```

Show relationship handling: which lookup fields reference which parent table records.

**Output**: Sample data plan ready for insertion. Proceed directly to Phase 5.

---

## Phase 5: Insert Sample Data

**Goal**: Execute OData POST calls to create all approved sample records with correct relationship handling

**Actions**:

Refer to `references/odata-record-patterns.md` for full patterns.

### 5.1 Get Entity Set Names

For each table, get the entity set name (needed for the API URL):

```
node "${PLUGIN_ROOT}/scripts/dataverse-request.js"  GET "EntityDefinitions(LogicalName='')?\$select=EntitySetName"
```

### 5.2 Get Picklist Options

For any picklist/choice columns, query valid option values before insertion:

```
node "${PLUGIN_ROOT}/scripts/dataverse-request.js"  GET "EntityDefinitions(LogicalName='')/Attributes(LogicalName='')/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?\$expand=OptionSet"
```

Use the actual `Value` integers from the option set in your sample data.

### 5.3 Insert Parent Tables First

Insert records into parent/referenced tables first to capture their IDs:

```
node "${PLUGIN_ROOT}/scripts/dataverse-request.js"  POST "" --body '{"cr123_name":"Sample Record","cr123_description":"A sample record for testing"}' --include-headers
```

The `--include-headers` flag includes the `OData-EntityId` response header, which contains the created record ID. Parse the GUID from the response to use in child table lookups.

Store parent record IDs for use in child table lookups.

### 5.4 Insert Child Tables with Lookups

For child/referencing tables, use `@odata.bind` syntax to set lookup fields:

```
node "${PLUGIN_ROOT}/scripts/dataverse-request.js"  POST "" --body '{"cr123_name":"Child Record","cr123_ParentId@odata.bind":"/()"}' --include-headers
```

### 5.5 Track Progress

Track each insertion attempt:

- Record table name, record number, success/failure
- On failure, log the error message but continue with remaining records
- Do NOT attempt automated rollback on failure

### 5.6 Refresh Token Periodically

The `dataverse-request.js` script handles 401 token refresh internally. For long-running operations (many records), periodically re-run `verify-dataverse-access.js` to confirm the session is still valid:

```
node "${PLUGIN_ROOT}/scripts/verify-dataverse-access.js" 
```

**Output**: All approved records inserted with parent-child relationships established

---

## Phase 6: Verify & Summarize

**Goal**: Confirm record counts and present a final summary to the user

**Actions**:

### 6.1 Verify Record Counts

For each table that was populated, query the record count:

```
node "${PLUGIN_ROOT}/scripts/dataverse-request.js"  GET "?\$count=true&\$top=0"
```

The `@odata.count` field in the response gives the total record count.

### 6.2 Record Skill Usage

> Reference: `${PLUGIN_ROOT}/references/skill-tracking-reference.md`

Follow the skill tracking instructions in the reference to record this skill's usage. Use `--skillName "AddSampleData"`.

### 6.3 Present Summary

Present a summary table:

| Table | Records Requested | Records Created | Failures |
|-------|-------------------|-----------------|----------|
| `cr123_project` (Project) | 10 | 10 | 0 |
| `cr123_task` (Task) | 10 | 9 | 1 |

Include:

- Total records created across all tables
- Any failures with error details
- Lookup relationships that were established

### 6.4 Suggest Next Steps

After the summary, suggest:

- Review the data in the Power Pages maker portal or model-driven app
- If the site is not yet built: `/create-site`
- If the site is ready to deploy: `/deploy-site`

**Output**: Verified record counts and summary presented to the user

---

## Important Notes

### Throughout All Phases

- **Use TaskCreate/TaskUpdate** to track progress at every phase
- **Ask for user confirmation** at key decision points (see list below)
- **Respect insertion order** -- always insert parent tables before child tables
- **Fail gracefully** -- log errors and continue, never rollback automatically
- **Refresh tokens** every 20 records to avoid expiration

### Key Decision Points (Wait for User)

1. After Phase 2: Confirm which tables to populate
2. After Phase 3: Confirm record count and insertion order
3. After Phase 6: Review summary and decide next steps

### Progress Tracking

Before starting Phase 1, create a task list with all phases using `TaskCreate`:

| Task subject | activeForm | Description |
|-------------|------------|-------------|
| Verify prerequisites | Verifying prerequisites | Confirm PAC CLI auth, acquire Azure CLI token, verify API access |
| Discover tables | Discovering tables | Read .datamodel-manifest.json or query OData API for custom tables |
| Select tables and configure | Configuring tables | User picks tables, record count, and determine insertion order |
| Generate and review sample data | Generating sample data | Generate contextual sample records, present preview, get user approval |
| Insert sample data | Inserting records | Execute OData POST calls with relationship handling and token refresh |
| Verify and summarize | Verifying results | Confirm record counts, present summary, suggest next steps |

Mark each task `in_progress` when starting it and `completed` when done via `TaskUpdate`. This gives the user visibility into progress and keeps the workflow deterministic.

---

**Begin with Phase 1: Verify Prerequisites**

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [microsoft](https://github.com/microsoft)
- **Source:** [microsoft/power-platform-skills](https://github.com/microsoft/power-platform-skills)
- **License:** MIT
- **Homepage:** https://aka.ms/ppskills

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-microsoft-power-platform-skills-add-sample-data
- Seller: https://agentstack.voostack.com/s/microsoft
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
