Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ dist/
skills-lock.json
.agents/
.pnpm-store
*.dev.ts
81 changes: 65 additions & 16 deletions bin/deploy-runner.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

96 changes: 48 additions & 48 deletions servers/genesys-cloud-architect-mcp.js

Large diffs are not rendered by default.

38 changes: 34 additions & 4 deletions skills/write-flow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ trigger:
- build a flow
- architect flow
- inbound call flow
- inbound chat flow
- inbound email flow
- inbound message flow
- IVR flow
- chat flow
- email flow
- test a bot flow
- test bot flow
- SMS flow
- workflow flow
- bot flow
- digital bot flow
- deploy a flow
---
Expand All @@ -40,7 +41,7 @@ If the user already has a flow file and just wants to deploy it, skip straight t
### 1. Understand the requirement

Ask the user:
- **Flow type**: inbound call, inbound chat, inbound email, inbound message (SMS), or workflow
- **Flow type**: inbound call, bot flow, digital bot flow, inbound email, inbound message (SMS), or workflow
- **What it should do**: routing, menus, greetings, queue transfers, data lookups, etc.
- **Flow name**: what to name the flow in Architect

Expand All @@ -55,8 +56,9 @@ Before writing any flow code, read these reference files from this skill:
3. **Always read**: `references/action-reference.md` — available action types
4. **Read when the flow uses expressions**: `references/expression-reference.md` — expression language syntax, functions, operators, data types, and common patterns. Read this whenever the flow involves conditional logic, dynamic text, variable manipulation, date/time calculations, or any `setExpression()` / expression property usage.
5. **Read the matching example** from `references/examples/`:
- `bot-flow.md` — bot flow with NLU intent detection, slot filling, and testing
- `digital-bot-flow.md` — digital bot with menu, free-text fallback, and exit
- `inbound-call.md` — IVR with menus and queue transfers
- `inbound-chat.md` — chat greeting and queue transfer
- `inbound-email.md` — auto-reply and queue transfer
- `inbound-message.md` — SMS auto-reply and queue transfer
- `workflow.md` — callback workflow
Expand Down Expand Up @@ -115,3 +117,31 @@ The tool spawns an isolated process that:
3. Returns success/failure with SDK logs

If deployment fails, read the error logs carefully — the SDK has three error channels (logging callback, TRACE lines, HTTP errors) and the deploy runner captures all of them.

**Bot flows — publish before testing:** The `deploy_flow` tool checks in the flow but does not publish it. To test a bot flow or digital bot flow with the `test_bot_flow` tool (step 6), the flow must be published first. Replace `flow.checkInAsync()` with `flow.publishAsync()` in the `buildFlow` function — do not call both, because `checkInAsync` releases the lock and `publishAsync` will fail with a 409:

```typescript
return await flow.publishAsync();
```

### 6. Test (bot flows and digital bot flows)

After deploying and publishing a bot flow or digital bot flow, test it using the `test_bot_flow` MCP tool. The deploy result includes the flow ID.

**Start a session:**
```
Tool: test_bot_flow
Input: { "flowId": "<flow-id-from-deploy>" }
```

The tool returns the bot's opening messages and a `sessionId`. Each turn includes `nextActionType`:
- `WaitForInput` — the bot is waiting for a user message
- `Disconnect` / `Exit` — the conversation has ended

**Send a message:**
```
Tool: test_bot_flow
Input: { "sessionId": "<session-id>", "message": "Billing" }
```

Walk through the flow's conversation paths to verify the bot responds correctly. If the bot behaves unexpectedly, update the flow file, re-deploy, re-publish, and test again.
2 changes: 1 addition & 1 deletion skills/write-flow/references/action-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ reply.setBodyByLiteralString("Thank you for your email.");
### Communicate
```typescript
const comm = actionFactory.addActionCommunicate(container, "Greeting");
comm.communicationExpression.setExpression('"Hello! How can I help?"');
comm.communication.setExpression('"Hello! How can I help?"');
```
Note: use quoted strings inside the expression, NOT `ToAudioTTS()`.

Expand Down
144 changes: 144 additions & 0 deletions skills/write-flow/references/examples/bot-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Example: Bot Flow

Bot flow with NLU intent detection, slot filling, and confirmation. Bot flows use `AskForIntent` and `AskForSlot` for natural language conversations — the Genesys Dialog Engine handles intent matching and entity extraction at runtime. After deploying and publishing, use the `test_bot_flow` MCP tool to simulate a text conversation and verify the NLU behaves as expected.

```typescript
import type { ArchitectScripting } from "purecloud-flow-scripting-api-sdk-javascript";

const nluCreationData = {
nluDomainVersion: {
language: "en-us",
intents: [
{
name: "CheckBalance",
utterances: [
{ segments: [{ text: "I want to check my balance" }] },
{ segments: [{ text: "What is my account balance" }] },
{ segments: [{ text: "How much do I owe" }] },
],
},
{
name: "MakePayment",
utterances: [
{ segments: [{ text: "I want to make a payment" }] },
{ segments: [{ text: "Pay my bill" }] },
{ segments: [{ text: "I need to pay" }] },
],
},
],
},
};

export async function buildFlow(scripting: ArchitectScripting) {
const { archFactoryFlows, archFactoryActions, archFactoryTasks } =
scripting.factories;

const flow = await archFactoryFlows.createFlowBotAsync(
"Example Bot Flow",
"Bot flow with NLU intent detection, slot filling, and task routing",
undefined,
undefined,
undefined,
nluCreationData,
);

const initialState = flow.startUpObject;

// Greet the user — bot flows use Communicate with plain string expressions
const greeting = archFactoryActions.addActionCommunicate(
initialState,
"Greeting",
);
greeting.communication.setExpression(
'"Hello! How can I help you today?"',
);

// AskForIntent — the Dialog Engine matches user input to configured intents
const askIntent = archFactoryActions.addActionAskForIntent(
initialState,
"Detect Intent",
);

// Create tasks for each intent — then associate them in botFlowSettings
const balanceTask = archFactoryTasks.addTask(flow, "Check Balance");
const balanceReply = archFactoryActions.addActionCommunicate(
balanceTask,
"Balance Response",
);
balanceReply.communication.setExpression(
'"Let me look up your balance. One moment please."',
);
archFactoryActions.addActionExitBotFlow(balanceTask, "Done");

const paymentTask = archFactoryTasks.addTask(flow, "Make Payment");
const paymentReply = archFactoryActions.addActionCommunicate(
paymentTask,
"Payment Response",
);
paymentReply.communication.setExpression(
'"I can help you make a payment. Let me transfer you to an agent."',
);
archFactoryActions.addActionExitBotFlow(paymentTask, "Done");

// Associate intents with tasks via botFlowSettings
const balanceIntent =
flow.botFlowSettings.getIntentSettingsByIntentName("CheckBalance");
if (balanceIntent) {
balanceIntent.confirmation.setExpression(
'"I think you want to check your balance, is that correct?"',
);
balanceIntent.associateWithTask(balanceTask);
}

const paymentIntent =
flow.botFlowSettings.getIntentSettingsByIntentName("MakePayment");
if (paymentIntent) {
paymentIntent.confirmation.setExpression(
'"You want to make a payment, is that correct?"',
);
paymentIntent.associateWithTask(paymentTask);
}

// Handle no intent detected
const noIntentPath = askIntent.outputNoIntent;
const fallback = archFactoryActions.addActionCommunicate(
noIntentPath,
"No Intent",
);
fallback.communication.setExpression(
'"I\'m sorry, I didn\'t understand that. Could you try rephrasing?"',
);

return await flow.publishAsync();
}
```

## Testing with `test_bot_flow`

Bot flows must be **published** before testing. The example above uses `publishAsync()` which validates, saves, and publishes in one call.

**Start a test session** with the flow ID returned by `deploy_flow`:
```
Tool: test_bot_flow
Input: { "flowId": "<flow-id>" }
```

The bot responds with its greeting and waits for input. Send a message to trigger intent detection:
```
Tool: test_bot_flow
Input: { "sessionId": "<session-id>", "message": "I want to check my balance" }
```

The response includes:
- **Text segments** — the bot's reply (greeting, confirmation, slot prompts)
- **RichMedia segments** — quick reply buttons (e.g. Yes/No for intent confirmation)
- **`nextActionType`** — `WaitForInput` (send another message), `Disconnect`/`Exit` (conversation ended)

Walk through each conversation path to verify intent detection, slot filling, and task routing work correctly. The Genesys Cloud UI does not expose this testing capability for Bot Flows.

Key differences from Digital Bot Flows:
- **`createFlowBotAsync`** — creates a bot flow with NLU support via Genesys Dialog Engine
- **`AskForIntent`** — lets the Dialog Engine match user input to configured intents (vs `DigitalMenu` with explicit choices)
- **`AskForSlot`** — prompts for and extracts slot values using NLU entity recognition
- **`botFlowSettings.getIntentSettingsByIntentName()`** — configures confirmation prompts and associates intents with reusable tasks
- **`settingsPrompts`** — bot flows have prompt settings (not available on digital bot flows)
Loading