Prompt template · LLM apps and evals
Text classification prompt template
Sort text into fixed labels with definitions, examples and an “unclear” option, returning JSON. Free to copy, or open it in the prompt builder to fill the variables and get the exact API request.
281 tokens unfilled · 356 with the example below · o200k_base (GPT-4o and later)
Template
The prompt
Paste this into a chat window and replace each {{variable}}, or open it in the prompt builder to fill them in a form. Sections are marked with XML tags, which every major model reads well.
You classify {{item_type}} into exactly one category. You are consistent: the same text always gets the same label.
<examples>
<example>
<input>
I was charged twice for March and only have one account.
</input>
<output>
{"label": "billing", "reason": "Asks about a duplicate charge."}
</output>
</example>
<example>
<input>
The export button does nothing when I click it in Firefox.
</input>
<output>
{"label": "bug", "reason": "Reports a feature that doesn’t work."}
</output>
</example>
<example>
<input>
Hi
</input>
<output>
{"label": "unclear", "reason": "Too short to tell what the customer needs."}
</output>
</example>
</examples>
<constraints>
Categories:
{{labels}}
- unclear: the text doesn’t fit any category, fits several equally, or is too short to judge.
Rules:
- Choose by the main intent of the text, not by keywords that appear in it.
- Use “unclear” rather than forcing a weak match.
</constraints>
<output_format>
JSON only: {"label": "<one category>", "reason": "<one short sentence>"}
</output_format>
<task>
Classify this {{item_type}}:
<text>
{{text}}
</text>
</task>For an API call: system prompt and user message
With a system prompt, the role, constraints and output format stay fixed across calls (and can be cached), while the context and task go in the user message.
You classify {{item_type}} into exactly one category. You are consistent: the same text always gets the same label.
<constraints>
Categories:
{{labels}}
- unclear: the text doesn’t fit any category, fits several equally, or is too short to judge.
Rules:
- Choose by the main intent of the text, not by keywords that appear in it.
- Use “unclear” rather than forcing a weak match.
</constraints>
<output_format>
JSON only: {"label": "<one category>", "reason": "<one short sentence>"}
</output_format>
<examples>
<example>
<input>
I was charged twice for March and only have one account.
</input>
<output>
{"label": "billing", "reason": "Asks about a duplicate charge."}
</output>
</example>
<example>
<input>
The export button does nothing when I click it in Firefox.
</input>
<output>
{"label": "bug", "reason": "Reports a feature that doesn’t work."}
</output>
</example>
<example>
<input>
Hi
</input>
<output>
{"label": "unclear", "reason": "Too short to tell what the customer needs."}
</output>
</example>
</examples><task>
Classify this {{item_type}}:
<text>
{{text}}
</text>
</task>Variables
What to put in each variable
- {{item_type}}
- What is being classified, such as “support ticket”, “app review” or “commit message”.
- {{text}}
- The text to classify.
- {{labels}}
- One line per category with a definition, such as “- billing: charges, invoices, refunds, plan changes”. Definitions matter more than names.
Use
When to use it
Use it for routing and tagging at scale: support tickets to teams, reviews to themes, feedback by product area, log lines by type. It suits label sets of up to roughly a dozen categories with clear definitions.
Measure it before trusting it. Label a hundred real examples by hand, run the prompt over them and count agreements per label. The labels where it disagrees with you usually need a sharper definition or a better example, not a different model.
Structure
Why it’s structured this way
Each label has a definition because names alone are ambiguous: is “my card was declined” billing or a bug? The definitions are your policy, and the “main intent, not keywords” rule tells the model how to apply it.
The “unclear” option is a release valve. Without it, every input is forced into a category and the errors look like confident classifications. With it, ambiguous texts can go to a person or a default queue, and the rate of “unclear” becomes a useful metric.
The examples show the exact output shape and one of each kind of decision, including an “unclear” case. Anthropic recommends three to five varied examples, and Google recommends always including some for Gemini. They sit in the prompt rather than the conversation by default; the builder can move them into turns.
Example
A filled-in example
- {{item_type}}
support ticket
- {{text}}
Since yesterday I can’t sign in with Google, it just loops back to the login page. Other people on my team are fine.
- {{labels}}
- billing: charges, invoices, refunds, plan or seat changes - bug: something in the product doesn’t work as documented - how-to: the customer wants to know how to do something that works - account: login, password, SSO, deleting or merging accounts
What to look for. This one sits between “bug” and “account”. Under “main intent” it is most likely account (a login problem for one user), and the reason sentence should say so. If your team would route it to engineering instead, sharpen the definitions; that’s the policy decision the template makes visible.
The complete filled-in prompt (356 tokens)
You classify support ticket into exactly one category. You are consistent: the same text always gets the same label.
<examples>
<example>
<input>
I was charged twice for March and only have one account.
</input>
<output>
{"label": "billing", "reason": "Asks about a duplicate charge."}
</output>
</example>
<example>
<input>
The export button does nothing when I click it in Firefox.
</input>
<output>
{"label": "bug", "reason": "Reports a feature that doesn’t work."}
</output>
</example>
<example>
<input>
Hi
</input>
<output>
{"label": "unclear", "reason": "Too short to tell what the customer needs."}
</output>
</example>
</examples>
<constraints>
Categories:
- billing: charges, invoices, refunds, plan or seat changes
- bug: something in the product doesn’t work as documented
- how-to: the customer wants to know how to do something that works
- account: login, password, SSO, deleting or merging accounts
- unclear: the text doesn’t fit any category, fits several equally, or is too short to judge.
Rules:
- Choose by the main intent of the text, not by keywords that appear in it.
- Use “unclear” rather than forcing a weak match.
</constraints>
<output_format>
JSON only: {"label": "<one category>", "reason": "<one short sentence>"}
</output_format>
<task>
Classify this support ticket:
<text>
Since yesterday I can’t sign in with Google, it just loops back to the login page. Other people on my team are fine.
</text>
</task>Models
Tips by model family
- All models
Set the model’s output to a schema with an
enumof your labels using the provider’s structured outputs. The model can then only return a label you defined. - Claude
Anthropic notes that structured outputs don’t guarantee the capitalisation of
enumvalues. Compare labels case-insensitively in your code, or keep them all lower-case as here. - OpenAI GPT
For high-volume classification, a small, fast model is often enough once the examples are good. Price your volume with the cost calculator before choosing.
Related
Related templates and tools
- Extract structured JSONPull fields from emails, documents or pages into a fixed JSON shape, with null instead of guesses.
- LLM-as-judge with a rubricGrade one answer against a written rubric and a reference answer, pass or fail per criterion, with evidence.
- Generate eval test casesDraft realistic, edge-case and adversarial inputs for your prompt, each with the expected behaviour.
Building this into an app that sends the same instructions with every request? Start from a system prompt instead; each comes with design notes, failure modes and a monthly cost. In the system prompt library: Support ticket triage and routing or Content moderation classifier.
Edited the template? Compare your version with this one in the prompt diff, and count it for your model with the token counter. In the glossary: few-shot prompting, structured outputs. Browse all 29 prompt templates.