> 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.

# Compose the Workflow

Composition is where modular assets become one capability. Use two orchestration layers for different jobs:

* A **compound action** coordinates uninterrupted backend execution.
* A **conversation process** coordinates interaction with a user.

## The Golden Rule

> Never place consecutive action activities in a conversation process without collecting a new required slot between them.

If no new required user input is needed, keep the backend sequence in one compound action. An Activity Confirmation Policy can protect that compound-action activity, but confirmation by itself does not justify exposing each backend step. Every action activity exposed in a conversation process can add output to the reasoning engine's context; a compound action keeps its internal outputs behind one boundary and returns one shaped result.

## Build the Compound Action

A compound action behaves like a typed backend function:

```text
input arguments
      ↓
ordered steps and control flow
      ↓
named internal outputs
      ↓
return.output_mapper
```

### Define Input Arguments

Declare only the values the workflow needs:

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

The caller maps values into these inputs. Inside the compound action, reference them as `data.feature_request_id` and `data.new_status`.

### Add Focused Steps

Use supported action blocks and control flow to:

* Look up the current record.
* Validate a deterministic precondition.
* Execute the write.
* Handle provider errors.
* Retrieve the final state.
* Notify a user when the ambient workflow requires a conversational handoff.

Give every useful internal result a descriptive output key.

### Return One Public Result

Use `return.output_mapper` to cross the boundary:

```yaml
- return:
    output_mapper:
      feature_request:
        id: data.updated_feature_request.id
        name: data.updated_feature_request.name
        status: data.updated_feature_request.currentStatus
```

Do not return lookup payloads, raw headers, debug data, or redundant intermediate responses unless the caller needs them.

> **System Triggers Do Not Supply User Context**
>
> A compound action invoked by a webhook or schedule has mapped trigger inputs and earlier step outputs, but no automatic `meta_info.user`. A conversational caller can provide user context.

## Build the Conversation Process

A conversation process contains:

| Component                 | Responsibility                                                                  |
| ------------------------- | ------------------------------------------------------------------------------- |
| Slots                     | Collect or infer typed user inputs                                              |
| Policies and control flow | Decide what must happen before the next activity                                |
| Action activities         | Invoke HTTP, script, built-in, LLM, or compound actions available in the editor |
| Content activities        | Display explicit text, knowledge articles, or forms                             |
| Data Bank                 | Store collected slots and completed activity outputs                            |

### Use Action Activities for Operations

An action activity supplies:

* **Input Mapping**: parent data → typed action arguments.
* **Output Mapping**: action response → exposed process output.
* Confirmation or execution behavior supported by the activity.

For a compound action:

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

Then expose only the compound return:

```yaml
updated_request:
  id: response.feature_request.id
  name: response.feature_request.name
  status: response.feature_request.status
display_instructions_for_model: >-
  Confirm the request name and its new status.
```

### Use Content Activities Deliberately

Use a Content Activity when you must display something explicitly inside the flow:

* Instructions the user must read before continuing.
* A knowledge article.
* A form.
* An intermediate result that must appear before the next step.

Do not add a final Content Activity merely to restate an action output that the reasoning engine can already present. A form is a special case: it must end its branch.

### Add Another Conversational Step Only When Needed

Add another action activity only after the assistant collects a new required slot. If the flow needs confirmation, branching, or explicit display but no new required input between backend calls, keep those calls in one compound action and configure the policy or content around that compound-action boundary.

## Understand Synchronous and Asynchronous Work

A compound-action activity configured to wait for completion makes its returned output available to later steps.

A compound-action activity configured as fire-and-forget starts backend work without making its output available downstream. Use it only when the conversation does not need the result.

## Shape the Model Boundary

The reasoning engine can present a clean result well when keys carry meaning:

```json
{
  "updated_feature_request": {
    "name": "Bulk edit requests",
    "status": "Planned"
  }
}
```

Avoid sending several implementation-shaped objects:

```json
{
  "get_response": {},
  "patch_response": {},
  "verify_response": {}
}
```

Use `display_instructions_for_model` for presentation preferences. Use mappings and deterministic checks for business correctness.

## Build Along: Compose the PurpleSuite Workflow

Create a compound action named `Update PurpleSuite feature request workflow` with this public contract:

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

Inside the compound action:

1. Call `Update PurpleSuite feature request`, which runs `PATCH /api/purple-suite/community/feature_requests/{id}`.
2. Call `Get PurpleSuite feature request`, which runs `GET /api/purple-suite/community/feature_requests/{id}` for the same ID.
3. Handle provider errors without exposing credentials or raw headers.
4. Return one `feature_request` object containing `id`, `name`, and `status`.

Then create a conversation process that:

1. Collects `selected_feature_request`.
2. Collects `target_status`.
3. Applies confirmation to the compound-action activity.
4. Maps both slot values into the compound action.
5. Exposes the shaped return for the assistant to present.

Your checkpoint is one conversational action boundary. The PATCH and verification operations remain inside the compound action.

The list `GET` is not part of this compound action. It already ran in the dynamic resolver before confirmation. A successful conversational run therefore produces the call order shown in the trace: list `GET`, update `PATCH`, then verification `GET`.

## Composition Decision Table

| Requirement                               | Put it in                                            |
| ----------------------------------------- | ---------------------------------------------------- |
| User must provide a value                 | Slot in conversation process                         |
| User chooses from live API records        | Dynamic resolver                                     |
| User must confirm a write                 | Activity Confirmation Policy (`confirmation_policy`) |
| Several API calls run without interaction | Compound action                                      |
| Loop, parallel branch, or error handling  | Compound action                                      |
| Explicit knowledge article or form        | Content Activity                                     |
| Final structured backend result           | Compound `return.output_mapper`                      |
| Result exposed to conversation            | Action Activity Output Mapping                       |

## Deep Dives

* [Compound Actions](/agent-studio/actions/compound-actions)
* [Compound Action Input Arguments](/agent-studio/actions/compound-actions/compound-action-input-arguments)
* [Compound Action Return](/agent-studio/actions/compound-actions/return)
* [Conversation Process](/agent-studio/conversation-process)
* [Activities](/agent-studio/conversation-process/activities)
* [Content Activities](/agent-studio/conversation-process/activities/content-activities)
* [The Golden Rule](/agent-studio/guides/best-practices/the-golden-rule)

Next, [publish and trigger the plugin](/agent-studio/guides/plugin-building-masterclass/publish-and-trigger-the-plugin).