Artificial IntelligenceAnthropicProjects

Project: Build a Customer Support Chatbot with Claude API

TT
TopicTrick
Project: Build a Customer Support Chatbot with Claude API

Customer support chatbots have a well-earned poor reputation. They fail to understand questions, give irrelevant answers from a FAQ list, and ultimately frustrate customers into demanding a human agent. The difference between a bad support bot and a useful one is not the technology — it is the design of the knowledge base, the system prompt, and the escalation logic.

Claude's conversational ability, combined with a well-structured knowledge base and clear behavioural instructions, produces a support bot that genuinely helps. This project builds a complete customer support chatbot with a static knowledge base, multi-turn conversation management, prompt caching for cost efficiency, and a clear escalation path to human support.


What We Are Building

The chatbot handles these core responsibilities:

  1. Answers questions from a company knowledge base — products, policies, account management, troubleshooting
  2. Maintains conversation context across multiple turns — no need for users to repeat themselves
  3. Recognises when to escalate — complex complaints, billing disputes, and repeated-failure scenarios get handed to a human
  4. Handles out-of-scope questions gracefully — redirects rather than guessing or confabulating

Prerequisites

  • Python 3.9 or later
  • pip install anthropic
  • An Anthropic API key set as ANTHROPIC_API_KEY

The Knowledge Base

The knowledge base is the most important component of a support bot. Claude should answer only from this content — not from its general training knowledge about your industry. Define it clearly in your system prompt.

python
1KNOWLEDGE_BASE = """ 2=== MERIDIAN CLOUD SERVICES — SUPPORT KNOWLEDGE BASE === 3 4PRODUCTS AND PLANS: 5- Starter Plan: £29/month. 5 users. 100 GB storage. Email support only. 6- Professional Plan: £99/month. 25 users. 1 TB storage. Priority email and chat support. 7- Enterprise Plan: Custom pricing. Unlimited users. Custom storage. Dedicated support manager. 8 9BILLING AND PAYMENTS: 10- Billing cycle is monthly, charged on the 1st of each month. 11- Payment methods accepted: Visa, Mastercard, American Express, BACS transfer. 12- Invoices are emailed to the account billing email within 24 hours of charge. 13- Refunds are available within 14 days of charge for annual plans. Monthly plans are non-refundable. 14- To update payment details, go to Account Settings → Billing → Payment Methods. 15 16ACCOUNT MANAGEMENT: 17- Password reset: Account Settings → Security → Reset Password, or use the login page "Forgot Password" link. 18- Adding users: Account Settings → Team → Invite Users. Admin role required. 19- Changing plan: Account Settings → Subscription → Change Plan. Takes effect at next billing date. 20- Cancellation: Account Settings → Subscription → Cancel. Data retained for 30 days after cancellation. 21 22TECHNICAL SUPPORT: 23- Service status: status.meridiancloud.com 24- Supported browsers: Chrome 108+, Firefox 108+, Safari 16+, Edge 108+. 25- Mobile app available for iOS 15+ and Android 10+. 26- API documentation: docs.meridiancloud.com 27- For persistent technical issues, collect: browser console errors, network tab HAR file, account ID. 28 29KNOWN ISSUES (as of this knowledge base update): 30- Export to Excel feature may show a loading spinner for up to 2 minutes on large datasets — this is expected behaviour. 31- Safari users may experience intermittent login issues — recommended workaround: clear browser cache and cookies. 32"""

The System Prompt

python
1def build_system_prompt(knowledge_base: str) -> str: 2 return f"""You are a helpful customer support agent for Meridian Cloud Services. 3Your name is Alex. You are helpful, professional, and concise. 4 5KNOWLEDGE BASE: 6{knowledge_base} 7 8BEHAVIOUR RULES: 91. Answer questions using ONLY information in the knowledge base above. 102. If the answer is not in the knowledge base, say: "I don't have information on that in my support resources. I can connect you with our team for more help." 113. Do not make up policies, prices, or features that are not stated above. 124. Keep answers focused — 2-4 sentences for most queries. 135. For billing disputes, account security concerns, or complex complaints: say "This is something I want to make sure gets handled perfectly — let me connect you with a specialist." 146. If the user expresses frustration or has repeated the same problem more than once: acknowledge their frustration first, then respond. 157. Never ask for passwords, payment card numbers, or full account credentials. 16 17ESCALATION TRIGGER PHRASES — if the user says any of these, offer to escalate: 18- "I want to speak to a human" 19- "This is unacceptable" / "I want to make a complaint" 20- "My account has been charged incorrectly" / "My card was charged without permission" 21- "I've been trying to fix this for days" 22"""

The Complete Chatbot

python
1import anthropic 2import json 3 4client = anthropic.Anthropic() 5 6KNOWLEDGE_BASE = """[Your knowledge base content here]""" 7 8ESCALATION_KEYWORDS = [ 9 "speak to a human", "real person", "manager", "complaint", 10 "unacceptable", "charged incorrectly", "days trying", "this is ridiculous" 11] 12 13class SupportChatbot: 14 def __init__(self): 15 self.conversation_history = [] 16 self.escalation_triggered = False 17 self.system_prompt = build_system_prompt(KNOWLEDGE_BASE) 18 19 def should_escalate(self, user_message: str) -> bool: 20 """Check if the user's message triggers escalation.""" 21 message_lower = user_message.lower() 22 return any(keyword in message_lower for keyword in ESCALATION_KEYWORDS) 23 24 def chat(self, user_message: str) -> str: 25 """Process one turn of the conversation.""" 26 27 # Check for escalation triggers 28 if self.should_escalate(user_message): 29 self.escalation_triggered = True 30 31 # Add user message to history 32 self.conversation_history.append({ 33 "role": "user", 34 "content": user_message 35 }) 36 37 # Build system with cached knowledge base for cost efficiency 38 system_messages = [ 39 { 40 "type": "text", 41 "text": self.system_prompt, 42 "cache_control": {"type": "ephemeral"} # Cache the large system prompt 43 } 44 ] 45 46 # Add escalation note if triggered 47 if self.escalation_triggered: 48 system_messages.append({ 49 "type": "text", 50 "text": "\n\n[SYSTEM NOTE: Escalation triggered. Offer to connect the user with a human specialist in your response.]" 51 }) 52 53 response = client.messages.create( 54 model="claude-sonnet-4-6", 55 max_tokens=1024, 56 system=system_messages, 57 messages=self.conversation_history 58 ) 59 60 assistant_message = response.content[0].text 61 62 # Add assistant response to history 63 self.conversation_history.append({ 64 "role": "assistant", 65 "content": assistant_message 66 }) 67 68 return assistant_message 69 70 def get_conversation_summary(self) -> str: 71 """Produce a summary for handoff to a human agent.""" 72 if len(self.conversation_history) < 2: 73 return "No conversation to summarise." 74 75 # Format conversation for summary 76 conv_text = "\n".join([ 77 f"{msg['role'].upper()}: {msg['content']}" 78 for msg in self.conversation_history 79 ]) 80 81 response = client.messages.create( 82 model="claude-haiku-4-5", # Use cheaper model for internal summaries 83 max_tokens=512, 84 messages=[ 85 { 86 "role": "user", 87 "content": f"""Summarise this customer support conversation for handoff to a human agent. 88Include: the customer's issue, what was tried, and why escalation is needed. 89Keep it under 100 words. 90 91CONVERSATION: 92{conv_text}""" 93 } 94 ] 95 ) 96 97 return response.content[0].text 98 99 def reset(self): 100 """Reset conversation for a new user session.""" 101 self.conversation_history = [] 102 self.escalation_triggered = False 103 104 105# ─── Interactive Demo ───────────────────────────────────────────────────────── 106 107def run_demo(): 108 bot = SupportChatbot() 109 110 print("Meridian Cloud Support — Alex is here to help.") 111 print("Type 'quit' to exit, 'summary' to see the handoff summary.\n") 112 113 while True: 114 user_input = input("You: ").strip() 115 116 if not user_input: 117 continue 118 119 if user_input.lower() == "quit": 120 print("\nSession ended.") 121 break 122 123 if user_input.lower() == "summary": 124 print("\n--- HANDOFF SUMMARY ---") 125 print(bot.get_conversation_summary()) 126 print("--- END SUMMARY ---\n") 127 continue 128 129 response = bot.chat(user_input) 130 print(f"\nAlex: {response}\n") 131 132 if bot.escalation_triggered: 133 print("[SYSTEM: Escalation flag active — prepare for human handoff if user accepts]\n") 134 135 136if __name__ == "__main__": 137 run_demo()

Extending the Project

  • FastAPI endpoint: Wrap in an API server so any frontend (React, Vue, or a third-party chat widget) can connect to it
  • Session storage: Store conversation history in Redis or PostgreSQL keyed by session ID to support concurrent users and persistent sessions
  • Dynamic knowledge base: Load the knowledge base from a database or CMS so it can be updated without redeploying the application
  • WebSocket streaming: Use the Claude streaming API to start showing the response character by character, reducing perceived latency for users
  • Analytics: Log every conversation with metadata (escalation rate, topic classification, resolution status) to identify knowledge gaps

Prompt Caching Makes Support Bots Much Cheaper

The knowledge base system prompt in this project is large — potentially 10,000+ tokens for a comprehensive product. By adding cache_control to the system prompt, you pay full input token cost only on the first request of each cache period (5 minutes minimum). All subsequent requests reuse the cached version at 10% of the cost. For a high-volume support bot handling thousands of conversations per day, this is a significant cost difference.


    Summary

    A well-designed support chatbot has three success factors: a high-quality knowledge base, clear behavioural boundaries, and a reliable escalation path. Claude handles the conversational intelligence — you provide the domain knowledge and the rules.

    • Use cache_control on the system prompt to reduce costs at scale
    • Maintain full conversation history so Claude has context for follow-up questions
    • Define explicit escalation triggers rather than relying on Claude to judge when to escalate
    • Use a cheaper model (Haiku) for internal tasks like summary generation

    Next project: Project: Build an Automated Meeting Notes Summariser.


    This post is part of the Anthropic AI Tutorial Series. Previous post: Project: Build a Smart CV / Resume Analyser with Claude.