> This page is for Agent Studio.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.moveworks.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.moveworks.com/_mcp/server.

# PurpleSuite Build Reference

PurpleSuite provides mock enterprise SaaS APIs and seeded data for Agent Studio development. This reference assembles the feature-request capability you built throughout the masterclass.

> **Use This as a Checkpoint**
>
> If you followed each Build Along section, the connector, actions, mappings, slots, compound action, conversation process, and plugin already exist. Compare those assets with the reference below and complete only the missing or failing checkpoints.

The completed build contains:

```text
PurpleSuite connector
  ├── List feature requests HTTP action
  ├── Get feature request HTTP action
  ├── Update feature request HTTP action
  ├── Feature request dynamic resolver
  ├── Status static resolver
  ├── Update feature request compound action
  ├── Conversation process
  └── Conversational plugin
```

> **Safe Explorer**
>
> The explorer below fetches only public PurpleSuite catalog and OpenAPI metadata. It does not request, store, or transmit your PAT or instance ID, and it does not execute API operations.

## Explore the Live API Contract

Select **Community**, then inspect the instance-based `GET /feature_requests`, `GET /feature_requests/{id}`, and `PATCH /feature_requests/{id}` operations.

The catalog and operation schemas come from the current PurpleSuite codebase, so new systems and fields can appear without rewriting this page.

## Phase 0: Create a PurpleSuite Instance

Complete [PurpleSuite Setup](/agent-studio/quickstart-guide/purple-suite-setup) to:

1. Create an instance with sample data.
2. Copy the temporary PAT and instance ID.
3. Create an API-key connector.
4. Verify the connection with a read-only request.

You can use either connector boundary:

#### Reusable Across PurpleSuite

Connector base URL:

```text
https://marketplace.moveworks.com
```

HTTP action endpoint:

```text
/api/purple-suite/community/feature_requests
```

#### Limited to the Community API

Connector base URL:

```text
https://marketplace.moveworks.com/api/purple-suite/community
```

HTTP action endpoint:

```text
/feature_requests
```

The narrower base URL reduces the destinations compatible actions can reach. The broader connector is convenient when one build intentionally uses several PurpleSuite systems.

## Phase 1: Build the Read Actions

Create an HTTP action named `List PurpleSuite feature requests`.

| Field                             | Value                                          |
| --------------------------------- | ---------------------------------------------- |
| Method                            | `GET`                                          |
| Endpoint with host-only connector | `/api/purple-suite/community/feature_requests` |
| Header                            | `X-Instance-ID: <your instance ID>`            |
| Optional query                    | `$top=25`                                      |

PurpleSuite list operations return a structured envelope:

```json
{
  "data": [
    {
      "id": "FR-1042",
      "name": "Bulk edit requests",
      "currentStatus": "New",
      "productArea": "Admin"
    }
  ],
  "nextCursor": null,
  "total": 1
}
```

Keep the list envelope in the HTTP action's response schema. The dynamic resolver will transform `response.data` into candidate values in the next phase.

Create another HTTP action named `Get PurpleSuite feature request`:

| Field                             | Value                                                                   |
| --------------------------------- | ----------------------------------------------------------------------- |
| Input argument                    | `feature_request_id` as `string`                                        |
| Method                            | `GET`                                                                   |
| Endpoint with host-only connector | `/api/purple-suite/community/feature_requests/{{{feature_request_id}}}` |
| Header                            | `X-Instance-ID: <your instance ID>`                                     |

### Checkpoint

The list action returns the documented `{ data, nextCursor, total }` envelope. The get action returns one requested record.

## Phase 2: Build the Resolvers

### Dynamic Feature Request Resolver

Create an object slot named `selected_feature_request`.

Configure a dynamic resolver that:

1. Calls `List PurpleSuite feature requests`.

2. Maps the resolver output directly to a candidate list:

   ```yaml
   MAP():
     items: response.data
     converter:
       id: item.id
       display_name: item.name
       current_status: item.currentStatus
       product_area: item.productArea
   ```

3. Configures cardinality to interpret the output as a list of candidate values.

4. Uses `display_name` as the useful display field.

5. Preserves `id`, `current_status`, and `product_area`.

The user can refer to a request naturally while the selected slot retains the exact record ID.

### Static Status Resolver

Create an object slot named `target_status`.

Use a static resolver based on the current `currentStatus` enum shown in the live OpenAPI schema. Do not copy an older list from another quickstart without checking the spec.

Add a DSL validator when your business flow allows only a subset of transitions.

### Checkpoint

Test:

* One exact request name.
* An ambiguous phrase that matches several requests.
* A phrase with no matching request.
* Each allowed target status.
* A status excluded by your business rule.

## Phase 3: Build the Write Action

Create an HTTP action named `Update PurpleSuite feature request`.

| Input argument       | Type     |
| -------------------- | -------- |
| `feature_request_id` | `string` |
| `new_status`         | `string` |

Configure the request from the live `PATCH /feature_requests/{id}` schema.

Endpoint:

```text
/api/purple-suite/community/feature_requests/{{{feature_request_id}}}
```

Example body shape:

```json
{
  "currentStatus": "{{{new_status}}}"
}
```

Keep the exact property name and enum values defined by the current OpenAPI schema.

### Checkpoint

Test the action against non-production sample data. Confirm that the selected record changes and the action returns a useful updated object.

## Phase 4: Compose the Backend Workflow

Create a compound action named `Update and verify feature request`.

Declare:

```yaml
feature_request_id:
  type: string
new_status:
  type: string
```

Add steps:

#### Update the record

Call the update HTTP action with the compound input arguments.

#### Retrieve the final state

Call `GET /feature_requests/{id}` with the same record ID.

#### Return the public result

Map only the stable ID, name, current status, and product area.

Example return:

```yaml
- return:
    output_mapper:
      feature_request:
        id: data.verified_feature_request.id
        name: data.verified_feature_request.name
        status: data.verified_feature_request.currentStatus
        product_area: data.verified_feature_request.productArea
```

### Checkpoint

The compound action exposes one result. The internal write and verification responses do not leak into the caller's contract.

## Phase 5: Build the Conversation Process

Add:

1. `selected_feature_request` object slot with the dynamic resolver.
2. `target_status` object slot with the static resolver and validation.
3. Confirmation before the write.
4. An action activity that calls the compound action.

Input mapping:

```yaml
feature_request_id: data.selected_feature_request.id
new_status: data.target_status.value
```

Output mapping:

```yaml
updated_feature_request:
  id: response.feature_request.id
  name: response.feature_request.name
  status: response.feature_request.status
  product_area: response.feature_request.product_area
display_instructions_for_model: >-
  Confirm the feature request name and new status.
  Include the product area. Do not mention internal implementation steps.
```

### Checkpoint

The process collects both values, confirms once, performs the backend sequence, and returns one concise result.

## Phase 6: Publish the Conversational Plugin

Use:

| Field       | Example                                                           |
| ----------- | ----------------------------------------------------------------- |
| Title       | `Manage Product Feature Requests`                                 |
| Description | `Find a product feature request and update its supported status.` |
| Process     | Your tested conversation process                                  |

Add at least five varied positive triggering examples and negative examples for nearby project-management or ticketing capabilities.

Launch to a test group and try:

```text
Move <a request returned by your resolver> to Planned.
```

## Optional Phase 7: Reuse the Backend as an Ambient Agent

Create a separate plugin with a webhook or scheduled trigger. Map an event body containing `feature_request_id` and `new_status` directly into the same compound action.

This variant demonstrates reuse:

* Same connector.
* Same HTTP actions.
* Same compound action.
* Different trigger and no conversational slots.
* No automatic `meta_info.user`.

Add notify only when the result must reach a resolved user.

## Lab Review

You have built one capability from modular contracts:

```text
API schema
  → connector trust boundary
  → focused HTTP operations
  → resolvers and typed slots
  → deterministic compound workflow
  → user-facing conversation process
  → plugin retrieval and launch
```

Continue to [Test and Operate](/agent-studio/guides/plugin-building-masterclass/test-and-operate).