Prompt Engineering for ChatGPT Apps: Best Practices
Effective prompt engineering is the foundation of every successful ChatGPT app. Whether you're building a customer service chatbot or a fitness studio booking assistant, the quality of your prompts directly determines user experience, accuracy, and conversion rates.
This guide covers advanced prompt engineering techniques specifically optimized for ChatGPT apps built with the OpenAI Apps SDK, including system prompts, few-shot learning, chain-of-thought reasoning, role prompting, output formatting, and constraint enforcement.
Table of Contents
- System Prompts: The Foundation of Your ChatGPT App
- Few-Shot Learning: Teaching by Example
- Chain-of-Thought Prompting: Structured Reasoning
- Role Prompting: Personality and Context
- Output Formatting: Structured Responses
- Constraint Enforcement: Preventing Hallucinations
- Practical Implementation Examples
System Prompts: The Foundation of Your ChatGPT App {#system-prompts}
System prompts define the core behavior, capabilities, and boundaries of your ChatGPT app. When building apps for the ChatGPT App Store, system prompts must be clear, concise, and aligned with your app's primary use case.
Key Components of Effective System Prompts
- Role Definition: Who is the AI assistant?
- Capability Scope: What can it do (and what can't it do)?
- Response Style: Tone, formality, verbosity
- Safety Guardrails: What topics to avoid
- Tool Usage Instructions: When to call MCP tools
Example: Fitness Studio Booking Assistant
// Prompt Template Engine (120 lines)
// /home/ashish/gbp/temp-scripts/prompt-template-engine.js
class PromptTemplateEngine {
constructor(config) {
this.config = config;
this.templates = new Map();
}
/**
* Register a system prompt template with variable interpolation
*/
registerTemplate(name, template) {
this.templates.set(name, template);
}
/**
* Generate system prompt with dynamic variables
*/
generateSystemPrompt(templateName, variables = {}) {
const template = this.templates.get(templateName);
if (!template) {
throw new Error(`Template "${templateName}" not found`);
}
// Replace {{variable}} placeholders
let prompt = template;
for (const [key, value] of Object.entries(variables)) {
const regex = new RegExp(`{{${key}}}`, 'g');
prompt = prompt.replace(regex, value);
}
return prompt;
}
/**
* Create a fitness studio booking assistant system prompt
*/
createFitnessBookingPrompt(studioName, services, policies) {
const template = `You are a professional booking assistant for {{studioName}}, a fitness studio.
**Your Role:**
- Help users book classes, view schedules, and manage reservations
- Provide information about class types, instructors, and pricing
- Answer questions about studio policies and membership options
**Available Services:**
{{serviceList}}
**Studio Policies:**
{{policyList}}
**Tool Usage:**
- Use getClassSchedule() to retrieve real-time class availability
- Use bookClass() ONLY after confirming user details (name, email, class time)
- Use cancelReservation() when users request cancellations
- NEVER make bookings without explicit user confirmation
**Response Guidelines:**
- Be friendly, professional, and concise
- Always confirm booking details before finalizing
- If a class is full, suggest alternative times
- Never hallucinate class availability - always use getClassSchedule()
**Constraints:**
- Do NOT discuss pricing for services not listed above
- Do NOT make medical or fitness recommendations
- Do NOT process refunds (direct users to studio manager)
- Stay focused on booking and scheduling tasks`;
this.registerTemplate('fitness-booking', template);
return this.generateSystemPrompt('fitness-booking', {
studioName,
serviceList: services.map((s, i) => `${i + 1}. ${s.name} - ${s.description}`).join('\n'),
policyList: policies.map((p, i) => `${i + 1}. ${p}`).join('\n')
});
}
/**
* Create a restaurant reservation assistant system prompt
*/
createRestaurantPrompt(restaurantName, menuHighlights, hours) {
const template = `You are the reservation assistant for {{restaurantName}}.
**Your Capabilities:**
- Take reservations for parties of 1-10 people
- Provide menu information and answer dietary questions
- Share operating hours and location details
**Menu Highlights:**
{{menuList}}
**Operating Hours:**
{{hoursList}}
**Booking Rules:**
- Parties of 6+ require 48-hour advance notice
- Maximum reservation is 10 people (larger groups contact manager)
- Cancellations must be made 24 hours in advance
**Tool Usage:**
- checkAvailability() before confirming reservations
- createReservation() only after collecting: name, phone, party size, date/time
- Never promise availability without checking tools
**Tone:**
Warm, welcoming, and professional - represent our restaurant's hospitality.`;
this.registerTemplate('restaurant-booking', template);
return this.generateSystemPrompt('restaurant-booking', {
restaurantName,
menuList: menuHighlights.map((m, i) => `${i + 1}. ${m}`).join('\n'),
hoursList: Object.entries(hours).map(([day, time]) => `${day}: ${time}`).join('\n')
});
}
/**
* Validate system prompt length (OpenAI best practices: <1500 tokens)
*/
validatePromptLength(prompt) {
// Rough token estimation: 1 token ≈ 4 characters
const estimatedTokens = Math.ceil(prompt.length / 4);
if (estimatedTokens > 1500) {
console.warn(`⚠️ System prompt is ${estimatedTokens} tokens (recommended: <1500)`);
return { valid: false, tokens: estimatedTokens };
}
return { valid: true, tokens: estimatedTokens };
}
}
// Usage Example
const engine = new PromptTemplateEngine();
const fitnessPrompt = engine.createFitnessBookingPrompt(
'FlexFit Studio',
[
{ name: 'Yoga', description: '60-min vinyasa flow' },
{ name: 'HIIT', description: '45-min high-intensity interval training' },
{ name: 'Pilates', description: '55-min core strengthening' }
],
[
'Cancel up to 2 hours before class for full credit',
'Late arrivals (>10 min) may forfeit spot',
'First class free for new members'
]
);
console.log(fitnessPrompt);
console.log(engine.validatePromptLength(fitnessPrompt));
module.exports = { PromptTemplateEngine };
Key Takeaways:
- System prompts should be 500-1,500 tokens (OpenAI recommendation)
- Use clear section headers (Role, Capabilities, Constraints)
- Include explicit tool usage instructions for MCP servers
- Add safety guardrails to prevent off-topic responses
Few-Shot Learning: Teaching by Example {#few-shot-learning}
Few-shot learning provides example interactions that demonstrate desired behavior. This is especially powerful for ChatGPT apps built with no-code tools where you need consistent, high-quality responses without fine-tuning.
When to Use Few-Shot Prompts
- Complex output formatting (JSON, Markdown tables, structured data)
- Nuanced tone requirements (empathetic customer service, technical precision)
- Multi-turn conversations (booking flows, troubleshooting sequences)
- Domain-specific language (medical terminology, legal phrasing)
Example: Few-Shot Generator for Booking Confirmations
// Few-Shot Learning Generator (130 lines)
// /home/ashish/gbp/temp-scripts/few-shot-generator.js
class FewShotGenerator {
constructor() {
this.examples = [];
}
/**
* Add a training example (input-output pair)
*/
addExample(userInput, assistantOutput, explanation = '') {
this.examples.push({ userInput, assistantOutput, explanation });
}
/**
* Generate few-shot prompt section
*/
generateFewShotPrompt() {
if (this.examples.length === 0) {
return '';
}
let prompt = '\n**Example Interactions:**\n\n';
this.examples.forEach((example, index) => {
prompt += `Example ${index + 1}:\n`;
prompt += `User: "${example.userInput}"\n`;
prompt += `Assistant: "${example.assistantOutput}"\n`;
if (example.explanation) {
prompt += `(Note: ${example.explanation})\n`;
}
prompt += '\n';
});
return prompt;
}
/**
* Create few-shot examples for booking confirmations
*/
createBookingExamples() {
// Example 1: Successful booking
this.addExample(
"I'd like to book the 6pm yoga class tomorrow",
`I'll check availability for tomorrow's 6pm yoga class.
*[Calling getClassSchedule()]*
Great news! The 6pm Vinyasa Flow class on December 26th has 3 spots available.
To complete your booking, I'll need:
1. Your full name
2. Email address
3. Phone number (for class reminders)
Could you provide those details?`,
'Always check availability before collecting user details'
);
// Example 2: Class is full
this.addExample(
"Book me into the 9am HIIT class on Saturday",
`Let me check Saturday's 9am HIIT class availability.
*[Calling getClassSchedule()]*
Unfortunately, the 9am HIIT class on December 28th is fully booked (12/12 spots filled).
**Alternative Options:**
- 7am HIIT (5 spots available)
- 11am HIIT (8 spots available)
- 6pm HIIT (10 spots available)
Would any of these times work for you?`,
'When full, proactively suggest alternatives'
);
// Example 3: Incomplete information
this.addExample(
"I want to cancel my class",
`I can help you cancel your reservation. To locate your booking, could you provide:
1. Your full name or email address
2. The class date and time
(Our cancellation policy allows cancellations up to 2 hours before class start time for full credit.)`,
'Request missing information politely, include relevant policy'
);
// Example 4: Outside scope
this.addExample(
"What's the best workout for weight loss?",
`While I'd love to help with fitness advice, I'm specifically designed to assist with class bookings and studio information.
For personalized workout recommendations, I suggest speaking with one of our certified instructors during your next class - they offer free 15-minute consultations!
Can I help you book a class today?`,
'Redirect out-of-scope questions, offer relevant alternative'
);
return this.generateFewShotPrompt();
}
/**
* Create few-shot examples for JSON output formatting
*/
createJSONFormattingExamples() {
this.addExample(
"Show me yoga classes this week",
`*[Calling getClassSchedule(classType: 'yoga', startDate: '2026-12-25', endDate: '2026-12-31')]*
Here are this week's yoga classes:
\`\`\`json
{
"classes": [
{
"id": "cls_001",
"name": "Vinyasa Flow",
"instructor": "Sarah Chen",
"date": "2026-12-26",
"time": "18:00",
"duration": 60,
"spotsAvailable": 3,
"totalSpots": 15
},
{
"id": "cls_002",
"name": "Yin Yoga",
"instructor": "Marcus Johnson",
"date": "2026-12-27",
"time": "19:30",
"duration": 75,
"spotsAvailable": 8,
"totalSpots": 12
}
]
}
\`\`\`
Both classes have availability! Would you like to book one?`,
'Use JSON code blocks for structured data responses'
);
return this.generateFewShotPrompt();
}
/**
* Combine system prompt with few-shot examples
*/
buildCompletePrompt(systemPrompt) {
return systemPrompt + '\n' + this.generateFewShotPrompt();
}
}
// Usage Example
const generator = new FewShotGenerator();
const bookingExamples = generator.createBookingExamples();
console.log('=== FEW-SHOT BOOKING EXAMPLES ===');
console.log(bookingExamples);
module.exports = { FewShotGenerator };
Best Practices:
- Use 3-5 examples (more doesn't always improve performance)
- Cover edge cases (errors, missing data, out-of-scope queries)
- Include tool call demonstrations in examples
- Add explanation notes to clarify intent
For more on building robust ChatGPT apps, see our complete guide to ChatGPT app development.
Chain-of-Thought Prompting: Structured Reasoning {#chain-of-thought}
Chain-of-Thought (CoT) prompting encourages the model to show its reasoning process before generating final answers. This technique dramatically improves accuracy for complex tasks like multi-step booking flows or troubleshooting sequences.
When to Use Chain-of-Thought
- Multi-step calculations (pricing, availability checks)
- Decision trees (eligibility checks, routing logic)
- Complex business rules (cancellation policies, membership tiers)
- Error diagnosis (why a booking failed)
Example: Chain-of-Thought Formatter
// Chain-of-Thought Formatter (110 lines)
// /home/ashish/gbp/temp-scripts/cot-formatter.js
class ChainOfThoughtFormatter {
/**
* Format a reasoning chain for class booking validation
*/
static formatBookingValidation(userRequest, classData, userProfile) {
return `**Reasoning Process:**
Step 1: Parse user request
- Requested class: ${userRequest.className}
- Requested date: ${userRequest.date}
- Requested time: ${userRequest.time}
- Party size: ${userRequest.partySize || 1}
Step 2: Check class availability
- Total spots: ${classData.totalSpots}
- Booked spots: ${classData.bookedSpots}
- Available spots: ${classData.totalSpots - classData.bookedSpots}
- User requested: ${userRequest.partySize || 1} spot(s)
- ✓ Availability check: ${classData.totalSpots - classData.bookedSpots >= (userRequest.partySize || 1) ? 'PASS' : 'FAIL'}
Step 3: Validate user eligibility
- User membership: ${userProfile.membershipTier}
- Class requires: ${classData.minimumTier}
- ✓ Membership check: ${this.tierComparison(userProfile.membershipTier, classData.minimumTier) ? 'PASS' : 'FAIL'}
Step 4: Check booking constraints
- User's existing bookings today: ${userProfile.bookingsToday}
- Maximum bookings per day: ${userProfile.maxBookingsPerDay}
- ✓ Constraint check: ${userProfile.bookingsToday < userProfile.maxBookingsPerDay ? 'PASS' : 'FAIL'}
Step 5: Calculate pricing
- Base price: $${classData.basePrice}
- Member discount: ${userProfile.discountRate * 100}%
- Final price: $${this.calculatePrice(classData.basePrice, userProfile.discountRate)}
**Decision:** ${this.generateDecision(userRequest, classData, userProfile)}`;
}
/**
* Compare membership tiers
*/
static tierComparison(userTier, requiredTier) {
const tiers = { 'free': 0, 'starter': 1, 'professional': 2, 'business': 3 };
return tiers[userTier.toLowerCase()] >= tiers[requiredTier.toLowerCase()];
}
/**
* Calculate discounted price
*/
static calculatePrice(basePrice, discountRate) {
return (basePrice * (1 - discountRate)).toFixed(2);
}
/**
* Generate final decision with reasoning
*/
static generateDecision(userRequest, classData, userProfile) {
const available = classData.totalSpots - classData.bookedSpots >= (userRequest.partySize || 1);
const eligible = this.tierComparison(userProfile.membershipTier, classData.minimumTier);
const withinConstraints = userProfile.bookingsToday < userProfile.maxBookingsPerDay;
if (available && eligible && withinConstraints) {
return `✅ APPROVED - All checks passed. Proceeding with booking confirmation.`;
}
const failures = [];
if (!available) failures.push('Class is fully booked');
if (!eligible) failures.push(`Requires ${classData.minimumTier} membership or higher`);
if (!withinConstraints) failures.push('Maximum daily bookings reached');
return `❌ REJECTED - ${failures.join(', ')}`;
}
/**
* Format multi-turn conversation reasoning
*/
static formatConversationContext(conversationHistory) {
let reasoning = '**Conversation Context Analysis:**\n\n';
// Extract user intent from history
const intents = conversationHistory.map((turn, idx) => {
return `Turn ${idx + 1}: ${this.extractIntent(turn.userMessage)}`;
});
reasoning += 'User Intent Progression:\n';
reasoning += intents.map(i => `- ${i}`).join('\n');
// Identify missing information
const requiredFields = ['name', 'email', 'phone', 'classSelection', 'dateTime'];
const collectedFields = this.extractCollectedFields(conversationHistory);
const missingFields = requiredFields.filter(f => !collectedFields.includes(f));
reasoning += '\n\nInformation Collected:\n';
reasoning += collectedFields.map(f => `✓ ${f}`).join('\n');
if (missingFields.length > 0) {
reasoning += '\n\nStill Needed:\n';
reasoning += missingFields.map(f => `○ ${f}`).join('\n');
}
reasoning += '\n\n**Next Action:** ';
reasoning += missingFields.length > 0
? `Request ${missingFields[0]}`
: 'Proceed with booking confirmation';
return reasoning;
}
/**
* Extract user intent from message
*/
static extractIntent(message) {
const lowercaseMsg = message.toLowerCase();
if (lowercaseMsg.includes('book') || lowercaseMsg.includes('reserve')) {
return 'Booking request';
}
if (lowercaseMsg.includes('cancel')) {
return 'Cancellation request';
}
if (lowercaseMsg.includes('reschedule') || lowercaseMsg.includes('change')) {
return 'Modification request';
}
if (lowercaseMsg.includes('?')) {
return 'Information inquiry';
}
return 'General conversation';
}
/**
* Extract collected information from conversation
*/
static extractCollectedFields(conversationHistory) {
const collected = [];
const fullText = conversationHistory.map(t => t.userMessage).join(' ');
if (/@/.test(fullText)) collected.push('email');
if (/\d{3}[-.\s]?\d{3}[-.\s]?\d{4}/.test(fullText)) collected.push('phone');
if (/\b[A-Z][a-z]+ [A-Z][a-z]+\b/.test(fullText)) collected.push('name');
// Add more field detection logic as needed
return collected;
}
}
// Usage Example
const userRequest = {
className: 'Vinyasa Flow',
date: '2026-12-26',
time: '18:00',
partySize: 1
};
const classData = {
totalSpots: 15,
bookedSpots: 12,
minimumTier: 'starter',
basePrice: 25
};
const userProfile = {
membershipTier: 'professional',
discountRate: 0.15,
bookingsToday: 1,
maxBookingsPerDay: 3
};
const reasoning = ChainOfThoughtFormatter.formatBookingValidation(
userRequest,
classData,
userProfile
);
console.log(reasoning);
module.exports = { ChainOfThoughtFormatter };
Chain-of-Thought Benefits:
- Improved accuracy for complex logic (15-30% improvement)
- Easier debugging (see exactly where logic fails)
- User transparency (builds trust by showing reasoning)
- Better error messages (explain why something failed)
Role Prompting: Personality and Context {#role-prompting}
Role prompting assigns a specific persona to your ChatGPT app, improving response quality and user engagement. This is critical for industry-specific ChatGPT apps where domain expertise matters.
Effective Role Definitions
❌ Weak: "You are a helpful assistant."
✅ Strong: "You are Maria, a certified yoga instructor with 10 years of experience and a specialty in therapeutic yoga for injury recovery."
❌ Weak: "You help with bookings."
✅ Strong: "You are the front desk manager at a luxury spa, known for your warm hospitality and attention to detail."
Role Prompt Template:
You are [Name], a [Professional Title] with [X years] of experience in [Domain].
Your expertise includes:
- [Skill 1]
- [Skill 2]
- [Skill 3]
Your personality:
- [Trait 1] (e.g., "Empathetic and patient")
- [Trait 2] (e.g., "Detail-oriented")
- [Trait 3] (e.g., "Solutions-focused")
When interacting with users:
- [Behavioral guideline 1]
- [Behavioral guideline 2]
- [Behavioral guideline 3]
For more on creating engaging ChatGPT apps, explore our AI conversational editor that automates prompt creation.
Output Formatting: Structured Responses {#output-formatting}
Structured output formatting ensures consistent, parseable responses that integrate seamlessly with your MCP server tools.
Common Output Formats
- JSON - Machine-readable structured data
- Markdown Tables - Human-readable comparisons
- Numbered Lists - Step-by-step instructions
- Code Blocks - Technical examples
Example: Output Parser with Format Enforcement
// Output Format Parser (100 lines)
// /home/ashish/gbp/temp-scripts/output-parser.js
class OutputParser {
/**
* Parse and validate JSON responses
*/
static parseJSON(response) {
try {
// Extract JSON from markdown code blocks
const jsonMatch = response.match(/```json\n([\s\S]*?)\n```/);
if (jsonMatch) {
return JSON.parse(jsonMatch[1]);
}
// Try parsing the entire response
return JSON.parse(response);
} catch (error) {
throw new Error(`Invalid JSON response: ${error.message}`);
}
}
/**
* Validate booking response structure
*/
static validateBookingResponse(response) {
const required = ['bookingId', 'className', 'dateTime', 'status', 'userDetails'];
const parsed = this.parseJSON(response);
const missing = required.filter(field => !(field in parsed));
if (missing.length > 0) {
throw new Error(`Missing required fields: ${missing.join(', ')}`);
}
// Validate field types
if (typeof parsed.bookingId !== 'string') {
throw new Error('bookingId must be a string');
}
if (typeof parsed.status !== 'string') {
throw new Error('status must be a string');
}
if (!['confirmed', 'pending', 'cancelled'].includes(parsed.status)) {
throw new Error(`Invalid status: ${parsed.status}`);
}
return parsed;
}
/**
* Format booking confirmation response
*/
static formatBookingConfirmation(booking) {
return `✅ **Booking Confirmed!**
**Booking Details:**
\`\`\`json
{
"bookingId": "${booking.bookingId}",
"className": "${booking.className}",
"instructor": "${booking.instructor}",
"dateTime": "${booking.dateTime}",
"duration": ${booking.duration},
"location": "${booking.location}",
"status": "confirmed"
}
\`\`\`
**What to Expect:**
1. You'll receive a confirmation email at ${booking.userDetails.email}
2. Please arrive 10 minutes early to check in
3. Bring a water bottle and yoga mat (or rent one for $5)
**Cancellation Policy:**
Cancel up to 2 hours before class start time for full credit.
**Questions?**
Reply to your confirmation email or call us at (555) 123-4567.`;
}
/**
* Create a format enforcement prompt
*/
static createFormatPrompt(formatType) {
const prompts = {
json: `**Output Format Requirement:**
Always return booking responses in this exact JSON structure:
\`\`\`json
{
"bookingId": "string (format: bkg_XXXXXXXXXX)",
"className": "string",
"instructor": "string",
"dateTime": "string (ISO 8601 format)",
"duration": number (minutes),
"location": "string",
"status": "confirmed" | "pending" | "cancelled",
"userDetails": {
"name": "string",
"email": "string",
"phone": "string"
},
"pricing": {
"basePrice": number,
"discount": number,
"finalPrice": number
}
}
\`\`\`
CRITICAL: Wrap JSON in markdown code blocks.`,
markdown: `**Output Format Requirement:**
Use clean Markdown formatting:
- **Bold** for section headers
- Numbered lists for steps/instructions
- Bullet points for options/features
- Code blocks for technical data
- Emojis for visual emphasis (✅ ❌ ⚠️)
Example:
**Class Schedule:**
1. Vinyasa Flow - 6:00 PM (3 spots)
2. HIIT - 7:00 PM (8 spots)
**Pricing:**
- Members: $20
- Non-members: $30`,
conversational: `**Output Format Requirement:**
Use natural, conversational language:
✅ Good: "Great! I've booked you into the 6pm yoga class. You'll receive a confirmation email shortly."
❌ Bad: "Booking confirmed. Class: Yoga. Time: 18:00. Status: Confirmed."
Guidelines:
- Write like you're talking to a friend
- Use contractions (I'll, you've, we're)
- Add transitional phrases (Great!, Perfect!, I see...)
- End with a helpful next step or question`
};
return prompts[formatType] || prompts.conversational;
}
}
// Usage Example
const bookingData = {
bookingId: 'bkg_1234567890',
className: 'Vinyasa Flow',
instructor: 'Sarah Chen',
dateTime: '2026-12-26T18:00:00Z',
duration: 60,
location: 'Studio A',
userDetails: {
name: 'John Doe',
email: 'john@example.com',
phone: '555-123-4567'
},
pricing: {
basePrice: 25,
discount: 3.75,
finalPrice: 21.25
}
};
console.log(OutputParser.formatBookingConfirmation(bookingData));
console.log('\n' + OutputParser.createFormatPrompt('json'));
module.exports = { OutputParser };
Format Best Practices:
- Specify format explicitly in system prompts
- Provide examples in few-shot prompts
- Validate outputs programmatically (don't trust LLMs blindly)
- Use schemas (JSON Schema, TypeScript interfaces)
Constraint Enforcement: Preventing Hallucinations {#constraint-enforcement}
Constraint enforcement prevents your ChatGPT app from generating inaccurate, dangerous, or off-brand responses. This is critical for production ChatGPT apps.
Types of Constraints
- Factual Constraints - "Only use data from MCP tools, never hallucinate"
- Scope Constraints - "Only discuss booking-related topics"
- Safety Constraints - "Never provide medical advice"
- Brand Constraints - "Always maintain professional tone"
Example: Constraint Validator
// Constraint Validator (80 lines)
// /home/ashish/gbp/temp-scripts/constraint-validator.js
class ConstraintValidator {
constructor(config) {
this.constraints = config.constraints || [];
this.violations = [];
}
/**
* Add a constraint rule
*/
addConstraint(name, validatorFn, errorMessage) {
this.constraints.push({ name, validatorFn, errorMessage });
}
/**
* Validate a response against all constraints
*/
validate(response) {
this.violations = [];
for (const constraint of this.constraints) {
const isValid = constraint.validatorFn(response);
if (!isValid) {
this.violations.push({
constraint: constraint.name,
message: constraint.errorMessage
});
}
}
return this.violations.length === 0;
}
/**
* Get validation report
*/
getReport() {
if (this.violations.length === 0) {
return { valid: true, message: 'All constraints satisfied' };
}
return {
valid: false,
violations: this.violations,
summary: `${this.violations.length} constraint(s) violated`
};
}
/**
* Create fitness studio booking constraints
*/
static createFitnessConstraints() {
const validator = new ConstraintValidator({});
// Constraint 1: No hallucinated availability
validator.addConstraint(
'no-hallucination',
(response) => {
// If response mentions availability, must include tool call evidence
if (/\d+ spots? (available|remaining)/i.test(response)) {
return /getClassSchedule\(\)/i.test(response);
}
return true;
},
'Availability claims must be backed by getClassSchedule() tool calls'
);
// Constraint 2: No medical advice
validator.addConstraint(
'no-medical-advice',
(response) => {
const medicalTerms = ['diagnose', 'cure', 'treatment', 'prescription', 'injury recovery'];
return !medicalTerms.some(term => response.toLowerCase().includes(term));
},
'Responses must not provide medical advice'
);
// Constraint 3: No pricing hallucination
validator.addConstraint(
'verified-pricing',
(response) => {
// If response mentions specific prices, must be from approved list
const priceMatch = response.match(/\$(\d+)/);
if (priceMatch) {
const approvedPrices = [20, 25, 30, 150, 250]; // Monthly/class prices
const mentionedPrice = parseInt(priceMatch[1]);
return approvedPrices.includes(mentionedPrice);
}
return true;
},
'Pricing must match approved studio rates'
);
// Constraint 4: Always confirm before booking
validator.addConstraint(
'require-confirmation',
(response) => {
// If response calls bookClass(), must include user confirmation
if (/bookClass\(/i.test(response)) {
return /confirm|approved|verified/i.test(response);
}
return true;
},
'Must obtain user confirmation before calling bookClass()'
);
return validator;
}
}
// Usage Example
const validator = ConstraintValidator.createFitnessConstraints();
// Test Case 1: Valid response
const validResponse = `Let me check availability.
*[Calling getClassSchedule()]*
The 6pm Vinyasa Flow class has 3 spots available. Would you like me to confirm your booking?`;
console.log('Test 1 (Valid):', validator.validate(validResponse));
console.log(validator.getReport());
// Test Case 2: Hallucinated availability (VIOLATION)
const invalidResponse = `The 6pm Vinyasa Flow class has 3 spots available. I'll book you in now!`;
console.log('\nTest 2 (Invalid - Hallucination):', validator.validate(invalidResponse));
console.log(validator.getReport());
// Test Case 3: Medical advice (VIOLATION)
const medicalResponse = `Yoga is great for your back injury. I recommend trying our therapeutic yoga class to help with your recovery.`;
console.log('\nTest 3 (Invalid - Medical Advice):', validator.validate(medicalResponse));
console.log(validator.getReport());
module.exports = { ConstraintValidator };
Constraint Enforcement Techniques:
- Pre-response validation (reject responses before sending to users)
- Tool call verification (ensure claims are backed by MCP tool data)
- Keyword blacklists (prevent discussing forbidden topics)
- Output sanitization (remove sensitive information)
Learn more about building compliant ChatGPT apps in our OpenAI Apps SDK compliance guide.
Practical Implementation Examples {#implementation-examples}
Complete Example: Fitness Studio Booking App Prompts
// Combining all techniques for production ChatGPT app
const { PromptTemplateEngine } = require('./prompt-template-engine');
const { FewShotGenerator } = require('./few-shot-generator');
const { ChainOfThoughtFormatter } = require('./cot-formatter');
const { OutputParser } = require('./output-parser');
const { ConstraintValidator } = require('./constraint-validator');
class FitnessAppPromptEngine {
constructor(studioConfig) {
this.config = studioConfig;
this.templateEngine = new PromptTemplateEngine();
this.fewShotGen = new FewShotGenerator();
this.validator = ConstraintValidator.createFitnessConstraints();
}
/**
* Generate complete system prompt with all optimizations
*/
generateSystemPrompt() {
// Step 1: Base system prompt
const basePrompt = this.templateEngine.createFitnessBookingPrompt(
this.config.studioName,
this.config.services,
this.config.policies
);
// Step 2: Add few-shot examples
const fewShotExamples = this.fewShotGen.createBookingExamples();
// Step 3: Add output formatting requirements
const formatRequirements = OutputParser.createFormatPrompt('json');
// Step 4: Add chain-of-thought instruction
const cotInstruction = `\n**Reasoning Process:**
For complex requests (bookings, cancellations), show your reasoning:
1. Parse user request
2. Check availability/eligibility
3. Validate constraints
4. Calculate pricing
5. Generate decision
Use the format: "Let me verify... *[reasoning steps]* ... Based on this, I recommend..."`;
// Step 5: Combine all components
return `${basePrompt}\n\n${fewShotExamples}\n\n${formatRequirements}\n\n${cotInstruction}`;
}
/**
* Validate response before sending to user
*/
validateResponse(response) {
const isValid = this.validator.validate(response);
const report = this.validator.getReport();
if (!isValid) {
console.error('❌ Response validation failed:', report);
return {
approved: false,
violations: report.violations,
fallback: 'I apologize, but I need to verify some information before proceeding. Let me check with my tools and get back to you.'
};
}
return { approved: true, response };
}
}
// Production Usage
const studioConfig = {
studioName: 'FlexFit Studio',
services: [
{ name: 'Yoga', description: '60-min vinyasa flow' },
{ name: 'HIIT', description: '45-min high-intensity' },
{ name: 'Pilates', description: '55-min core work' }
],
policies: [
'Cancel up to 2 hours before class',
'Late arrivals may forfeit spot',
'First class free for new members'
]
};
const promptEngine = new FitnessAppPromptEngine(studioConfig);
const systemPrompt = promptEngine.generateSystemPrompt();
console.log('=== PRODUCTION SYSTEM PROMPT ===');
console.log(systemPrompt);
console.log('\n=== TOKEN COUNT ===');
console.log(`Estimated: ${Math.ceil(systemPrompt.length / 4)} tokens`);
Key Takeaways
- System Prompts - Define role, capabilities, and constraints (500-1,500 tokens)
- Few-Shot Learning - Provide 3-5 examples of desired behavior
- Chain-of-Thought - Show reasoning for complex decisions (improves accuracy 15-30%)
- Role Prompting - Assign specific persona for domain expertise
- Output Formatting - Enforce structured responses (JSON, Markdown)
- Constraint Validation - Prevent hallucinations and off-topic responses
Internal Links
- Complete Guide to Building ChatGPT Apps (Pillar Page)
- OpenAI Apps SDK Complete Guide
- MCP Server Development Guide
- ChatGPT App Booking Systems
- ChatGPT App Deployment Best Practices
- ChatGPT App Store Submission Guide
- AI Conversational Editor
- Fitness Studio Booking Template
- Customer Service Chatbot Template
- MakeAIHQ Features
External Links
- OpenAI Apps SDK Documentation
- Model Context Protocol (MCP) Specification
- Chain-of-Thought Prompting Research Paper
HowTo Schema (JSON-LD)
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "Prompt Engineering for ChatGPT Apps: Best Practices",
"description": "Master prompt engineering for ChatGPT apps: system prompts, few-shot learning, chain-of-thought reasoning, output formatting, and constraint validation.",
"image": "https://makeaihq.com/images/prompt-engineering-guide.png",
"totalTime": "PT30M",
"step": [
{
"@type": "HowToStep",
"name": "Create System Prompts",
"text": "Define role, capabilities, and constraints for your ChatGPT app in 500-1,500 tokens. Include tool usage instructions and safety guardrails.",
"url": "https://makeaihq.com/guides/cluster/prompt-engineering-chatgpt-apps-best-practices#system-prompts"
},
{
"@type": "HowToStep",
"name": "Implement Few-Shot Learning",
"text": "Provide 3-5 example interactions demonstrating desired behavior, covering edge cases and tool call demonstrations.",
"url": "https://makeaihq.com/guides/cluster/prompt-engineering-chatgpt-apps-best-practices#few-shot-learning"
},
{
"@type": "HowToStep",
"name": "Apply Chain-of-Thought Prompting",
"text": "Encourage the model to show reasoning process for complex tasks like multi-step bookings or decision trees.",
"url": "https://makeaihq.com/guides/cluster/prompt-engineering-chatgpt-apps-best-practices#chain-of-thought"
},
{
"@type": "HowToStep",
"name": "Define Role Prompting",
"text": "Assign a specific persona with domain expertise, personality traits, and behavioral guidelines.",
"url": "https://makeaihq.com/guides/cluster/prompt-engineering-chatgpt-apps-best-practices#role-prompting"
},
{
"@type": "HowToStep",
"name": "Enforce Output Formatting",
"text": "Specify exact output structure (JSON, Markdown, etc.) and validate programmatically.",
"url": "https://makeaihq.com/guides/cluster/prompt-engineering-chatgpt-apps-best-practices#output-formatting"
},
{
"@type": "HowToStep",
"name": "Implement Constraint Validation",
"text": "Add factual, scope, safety, and brand constraints to prevent hallucinations and off-topic responses.",
"url": "https://makeaihq.com/guides/cluster/prompt-engineering-chatgpt-apps-best-practices#constraint-enforcement"
}
],
"tool": [
{
"@type": "HowToTool",
"name": "MakeAIHQ No-Code Builder"
},
{
"@type": "HowToTool",
"name": "OpenAI Apps SDK"
}
]
}
Ready to build production-grade ChatGPT apps with optimized prompts?
Start Your Free Trial | Explore Templates | View Pricing
Questions? Contact our team or read our Complete ChatGPT App Building Guide.