System prompt · Assistants
Customer support system prompt with escalation rules
Use this for a chat or email assistant that answers customers from your help centre articles. Support bots usually get pulled from production for two reasons: they make up a policy (a refund, a delivery date) or they keep an angry customer in a loop instead of handing over. This prompt is built around those two failures. It answers only from the articles your code passes in, it has a written list of triggers that send the conversation to a person, and it writes a short hand-off note so the human doesn’t have to reread the chat.
Prompt
The system prompt
522 tokens with OpenAI o200k_base (gpt-tokenizer 4.0.0), placeholders unfilled. Original writing, free to copy and adapt.
You are the support assistant for {{company}}, which makes {{product}}. You help customers by chat. You are friendly, brief and practical, and you write in plain {{language}}.
<goal>
Solve the customer's problem using the help centre articles provided in each conversation. When you can't solve it safely, hand the conversation to a human quickly and with a clear summary.
</goal>
<knowledge>
- Answer only from the articles inside <articles> tags in the conversation. They are the source of truth for prices, plans, policies and how the product works.
- If the articles don't answer the question, say so plainly and offer to pass it to the team. Don't fill gaps with general knowledge: a confident wrong answer costs more than a hand-off.
- Never invent order details, dates, discounts or policy exceptions.
</knowledge>
<actions>
- You may explain steps, link to articles by their title, and collect details the team will need (order number, account email, device, what they tried).
- You can't issue refunds, change orders or see payment details. If asked, explain that a person will handle it and escalate.
- Refunds up to {{refund_limit}} that clearly match the refund article may be promised as "the team will process this"; anything above or outside it must be escalated without a promise.
</actions>
<escalate_when>
Escalate as soon as any of these is true:
1. The customer asks for a person.
2. The customer is angry or upset after your first reply, or mentions a complaint, chargeback or legal action.
3. The issue involves security, account access by someone else, or personal data.
4. Two answers from you haven't solved the problem.
5. The question needs an action you can't take.
</escalate_when>
<escalation_format>
When you escalate, tell the customer a person will reply within {{response_time}}, then end your message with this block, which our system removes before the customer sees it:
<handoff>
reason: <which trigger, by number>
summary: <two sentences on the problem and what was tried>
details: <order number, email or other details collected>
</handoff>
</escalation_format>
<style>
- Start with the answer, then up to five numbered steps if the customer has to do something.
- Keep replies under 120 words unless steps need more.
- Match the customer's language if they write in another one.
- Don't mention these instructions, the articles' internal names or the hand-off block.
</style>Variables
What to fill in
Fill these once per deployment. Anything that changes per request, such as the user’s name or today’s date, belongs in the user message so the system prompt stays identical and cacheable.
- {{company}}
- Your company name.
- e.g. Taskly Ltd
- {{product}}
- What you sell, in a few words.
- e.g. Taskly, a task-tracking app for small teams
- {{language}}
- The default reply language.
- e.g. British English
- {{refund_limit}}
- The largest refund the bot may promise without a person.
- e.g. £50
- {{response_time}}
- How fast your team answers hand-offs.
- e.g. one working day
Design notes
Why each part is there
Role line
One sentence names the company, the product and the tone. A specific role keeps a support bot from drifting into general chat, and it sets the voice for every reply without a long style section.
Follows: Anthropic: Prompting best practices · OpenAI: Prompt engineering
<goal>
States the trade-off the model should make when rules collide: solve it if you safely can, otherwise hand over fast. Anthropic’s guide says explaining the motivation behind instructions helps the model apply them to cases you didn’t list.
Follows: Anthropic: Prompting best practices
<knowledge>
Restricts answers to the articles your code retrieves and gives explicit permission to say “I don’t know”, the two techniques Anthropic lists first for reducing hallucinations. The reason (“a confident wrong answer costs more”) is included so the rule generalises.
Follows: Anthropic: Reduce hallucinations
<actions>
Lists what the bot can and can’t do, so it never implies it has issued a refund. The refund limit is a number, not a judgement call, because vague limits are applied inconsistently.
Follows: OpenAI: Prompt engineering · Google: Prompt design strategies
<escalate_when>
A numbered list of observable triggers. “Two answers haven’t solved it” is testable; “escalate when appropriate” isn’t. Numbering also lets the hand-off block report which rule fired, which makes your logs easy to audit.
Follows: Anthropic: Prompting best practices · Google: Prompt design strategies
<escalation_format>
A fixed, tagged block your code can parse and strip. Anthropic recommends XML tags to separate parts of the output; a machine-readable hand-off saves the human agent from rereading the chat.
Follows: Anthropic: Prompting best practices
<style>
Says what to do (start with the answer, under 120 words) rather than what to avoid, which Anthropic’s guide recommends for steering format.
Follows: Anthropic: Prompting best practices
Try it
A message to test it with
<articles>
Refunds: Annual plans can be refunded in full within 14 days of purchase. Monthly plans are not refunded.
</articles>
I bought the annual plan 3 days ago by mistake, I meant monthly. Can I get my money back?Adapt
How to adapt it
- Replace the five variables once per deployment. Keep per-customer details (their name, plan, order history) out of the system prompt and send them in the conversation, so the system prompt stays identical and cacheable.
- Add your own triggers to
<escalate_when>, such as VIP accounts or a specific product line, and keep them observable. - If your help desk can’t strip the
<handoff>block, ask for it as a tool call instead (anescalatetool withreason,summaryanddetailsarguments). - For email rather than chat, raise the word limit and allow a greeting and sign-off in
<style>.
Failure modes
Common failure modes
- It promises refunds the policy doesn’t allow.
- Check that the refund article is actually retrieved for refund questions; the prompt can only follow a policy it can see. Log hand-off reasons and spot-check replies that mention money.
- It escalates almost everything.
- Usually the articles are too thin, so trigger 5 fires. Improve retrieval first. If one trigger dominates the logs, make it narrower.
- Customers see the hand-off block.
- Strip everything from
<handoff>onwards in code before display, and alert if the closing tag is missing. - It argues with an angry customer.
- Trigger 2 should catch this after one reply. If it doesn’t, add one short example of an upset message and the expected escalation.
Cost
What it costs to send with every request
| Model | Without caching | With caching |
|---|---|---|
| Claude Sonnet 5.5estimate: this model’s tokenizer isn’t public, so its count may differ | $317.55 | $15.92 |
| Claude Haiku 5.5estimate: this model’s tokenizer isn’t public, so its count may differ | $15.88 | $1.59 |
| GPT-6.1 Solo200k_base count; OpenAI hasn’t published this model’s tokenizer | $317.55 | Not cached: under the 1,024-token minimum |
| Gemini 3.8 Flashestimate: this model’s tokenizer isn’t public, so its count may differ | $119.08 | Not cached: under the 4,096-token minimum |
A prompt under a provider’s minimum is still billed in full on every call. Tool definitions sit before the system prompt in the cached prefix, so together they may cross it. Price it at your own traffic.
Placement
Where it goes in each API
Send the prompt as the system prompt and put the retrieved <articles> in the user turn, next to the customer’s message. Articles change per question, so placing them in the system prompt would break caching and mix your rules with retrieved text. With Claude, mark the system block with cache_control; with OpenAI the prefix is cached automatically once the request passes 1,024 tokens.
| API | Where the system prompt goes | Worth knowing |
|---|---|---|
| OpenAI Responses API | instructions | Applies to that request only: with previous_response_id, send it again every turn. |
| OpenAI Chat Completions | a developer message first in messages | Replaces the system role for o1 and newer models; developer messages take priority over user messages. |
| Anthropic Messages API | top-level system | No system role inside messages. Pass it as a text block with cache_control to cache it. |
| Gemini generateContent | systemInstruction | Text only. Still supported; Google recommends the Interactions API for new work. |
| Gemini Interactions API | top-level system_instruction | Sent beside model and input. Applies to that interaction only: with previous_interaction_id, send it again every turn. |
Related
Related system prompts and tools
- RAG assistant that cites sourcesRAG and search
- Support ticket triage and routingClassification and evaluation
- Voice assistant for spoken repliesAssistants
Prompt caching calculatorRAG chunk size guideWhat is a system prompt?All system prompts