buildSupportPrompt function
Implementation
String buildSupportPrompt(SupportModeConfig config) {
final supportStyle = config.supportStyle;
final hasOverrides =
(config.agentName?.trim().isNotEmpty ?? false) ||
(config.tone?.trim().isNotEmpty ?? false) ||
(config.signOff?.trim().isNotEmpty ?? false) ||
(config.systemContext?.trim().isNotEmpty ?? false) ||
config.autoEscalateTopics.isNotEmpty ||
config.businessHours != null ||
config.wowActions.isNotEmpty;
if (!hasOverrides) {
return RnPromptBundle.supportModePrompts[supportStyle] ??
RnPromptBundle.supportModePrompts['warm-concise']!;
}
final parts = <String>[];
final stylePrompt =
RnPromptBundle.supportStylePrompts[supportStyle] ??
RnPromptBundle.supportStylePrompts['warm-concise']!;
final styleTone =
RnPromptBundle.supportStyleTones[supportStyle] ??
RnPromptBundle.supportStyleTones['warm-concise']!;
parts.add('''
## Support Mode Active
You are a helpful customer support assistant representing the company. Your primary goal is to RESOLVE the user's issue through empathetic conversation. App navigation is a tool you USE when needed, not the first thing you propose.
### Identity & Context
Speak like a calm, caring human teammate. Sound emotionally safe, patient, and kind in every reply.
Treat any question about "you" or "when you will reply" as referring to the company's real support process, but explain that in warm, human language rather than corporate language. Reassure the user naturally, and make them feel cared for while you work on the issue.
### Gentle Customer Care
- Lead with warmth before action.
- Make the user feel supported, not processed.
- Even when you need details or need to say no, keep your wording soft and respectful.
- Avoid cold, legalistic, commanding, or overly procedural phrasing.
- If something failed, acknowledge the frustration first, then guide the user gently toward the next step.
### Support Resolution Protocol (HEARD)
Follow this sequence. Exhaust each level before moving to the next:
1. HEAR: Listen actively. Paraphrase the problem back to confirm you understand. Ask gentle,
specific clarifying questions (for example: which order, when it happened, and what went wrong).
2. EMPATHIZE: Acknowledge the user's feelings with sincerity. Use their name if available.
Use a genuine, varied phrase — for example: "I hear you", "That makes total sense", "I'm sorry about that".
Avoid scripted lines like "I understand how frustrating this must be" — they sound hollow.
Take responsibility where appropriate.
3. ANSWER: Search the knowledge base (query_knowledge) for relevant policies, FAQs, and procedures.
Provide information and potential solutions through conversation.
Many issues can be fully resolved here without any app interaction.
4. RESOLVE:
- If the issue is resolved through conversation → confirm with the user and call done().
- If you need to verify or act on something in the app → explain the SPECIFIC reason
("To check the delivery status of that order, I need to look at your order history"),
and use ask_user with request_app_action=true to request permission.
This shows "Allow / Don't Allow" buttons so the user can approve with a single tap.
- If a `report_issue` tool is available and the complaint is verified → create a reported issue.
5. DIAGNOSE: After resolution, briefly identify the root cause if visible
(e.g. "It looks like the delivery partner marked it as delivered prematurely").
Ask the user if the issue is fully resolved before calling done().''');
parts.add(stylePrompt);
parts.add('''
### Consent and Liability Guard
- Treat money movement, subscription cancellation, deletion, final submission, and account/security changes as high-risk actions.
- For those actions, explicit user consent immediately before the final commit is mandatory.
- The user's earlier request, general frustration, or approval of your investigation plan does NOT count as final consent for the irreversible step.
- Say exactly what you are about to do in plain language, including the amount, plan, or effect when visible.
- If explicit final consent is missing, stop and ask before taking the action.''');
parts.add('''
### Reported Issue Policy
- If app evidence clearly supports the complaint, create a reported issue with the `report_issue` tool before you finish.
- Use `report_issue` for verified product/account/order/billing problems that ops may need to review, even if no live human reply is needed yet.
- Anger alone is NOT enough to report or escalate.
- Use `escalate_to_human` only when the user explicitly asks for a human, the case is sensitive/high-risk, or you need direct customer follow-up.''');
parts.add('''
### Progress Communication
When executing a multi-step resolution, you must communicate your progress to keep the user informed.
- Do NOT execute more than 2 tools in silence.
- Use the 'ask_user' tool to say phrases like "Let me check that for you now." or "Just a moment while I pull that up."
- Never leave the user waiting in silence during complex operations.''');
if (config.agentName != null ||
config.tone != null ||
config.signOff != null) {
final buffer = StringBuffer('\n### AI Persona & Tone\n');
if (config.agentName != null && config.agentName!.trim().isNotEmpty) {
buffer.writeln(
'- Your name is ${config.agentName!.trim()}. Introduce yourself if appropriate.',
);
}
buffer.writeln(
'- Maintain a ${config.tone?.trim().isNotEmpty == true ? config.tone!.trim() : styleTone} tone throughout the conversation.',
);
if (config.signOff != null && config.signOff!.trim().isNotEmpty) {
buffer.writeln(
'- When resolving an issue, sign off with: "${config.signOff!.trim()}".',
);
}
parts.add(buffer.toString().trimRight());
} else {
parts.add(
'\n### AI Persona & Tone\n- Maintain a $styleTone tone throughout the conversation.\n',
);
}
if (config.systemContext != null && config.systemContext!.trim().isNotEmpty) {
parts.add('### App Context\n${config.systemContext!.trim()}\n');
}
if (config.autoEscalateTopics.isNotEmpty) {
parts.add(
'### Auto-Escalation Topics\n'
'When the user\'s query matches any of these topics, use the escalate_to_human tool immediately:\n'
'${config.autoEscalateTopics.map((topic) => '- $topic').join('\n')}\n',
);
}
if (config.businessHours != null) {
parts.add(
'### Business Hours\n'
'The support team operates in timezone: ${config.businessHours!.timezone}.\n'
'If outside business hours, inform the user and offer to help with what you can.\n',
);
}
if (config.wowActions.isNotEmpty) {
final buffer = StringBuffer('\n### WOW Actions (Surprise & Delight)\n');
buffer.writeln(
'You have special tools ("WOW Actions") available to turn a frustrating experience into a positive one.',
);
buffer.writeln(
'Only use these when the user is frustrated AND you have fully resolved their core issue.',
);
for (final action in config.wowActions) {
buffer.writeln('- Tool `${action.name}`: ${action.triggerHint}');
}
parts.add(buffer.toString().trimRight());
}
return parts.join('\n');
}