This prompt is for safety platform builders who need to annotate every turn in a multi-turn conversation with structured safety metadata. The primary job-to-be-done is producing a JSON array of turn annotations, each containing a safety classification, risk score, and policy citation. Downstream refusal logic, audit systems, and session-risk evaluators consume this structured history to make consistent, evidence-backed refusal decisions. The ideal user is an engineering lead or safety engineer integrating this prompt into a context-aware refusal pipeline where prior turn classifications must be referenced before deciding whether to refuse the current request.
Prompt
Turn History Safety Annotation Prompt for Refusal Systems

When to Use This Prompt
Defines the job-to-be-done, ideal user, required context, and boundaries for the turn history safety annotation prompt.
Use this prompt when you are building a system that requires cumulative safety context across turns. For example, a user might first ask a benign question, then gradually rephrase it into a disallowed request over several turns. A single-turn classifier would miss this pattern, but this prompt's structured history allows downstream logic to detect the escalation. The prompt assumes you already have defined safety policies and a conversation transcript with clear speaker roles. It is not a replacement for a real-time blocking filter, a single-turn safety classifier, or a policy definition engine. If you need to block harmful content before the model responds, use a pre-response guard model instead. If you need to define what constitutes a policy violation, start with a policy boundary definition prompt before wiring in this annotation step.
Do not use this prompt when latency is the primary constraint. Annotating every turn adds processing overhead that may be unacceptable for real-time chat applications requiring sub-second response times. It is also the wrong tool if you lack a defined safety policy taxonomy—the prompt will produce inconsistent, ungrounded classifications without clear policy categories to reference. Before deploying, ensure you have a test suite of multi-turn conversations with expected annotations, and plan to run consistency evals across model updates. The next step after reading this section is to review the prompt template and implementation harness to understand how to wire this into your refusal pipeline.
Use Case Fit
Where the Turn History Safety Annotation Prompt delivers value and where it introduces risk. This prompt is a pipeline component, not a standalone refusal system.
Good Fit: Safety Platform Pipelines
Use when: you are building a multi-component safety system where downstream refusal logic needs structured, per-turn risk context. Guardrail: Treat this prompt's output as machine-readable metadata, not as the final user-facing refusal message.
Bad Fit: Real-Time User-Facing Refusal
Avoid when: you need a single prompt to both classify and respond to the user in one call. This prompt produces annotations, not conversational replies. Guardrail: Pair this with a separate refusal generation prompt that consumes the annotated history.
Required Inputs
Risk: Garbage annotations from incomplete context. Guardrail: You must provide the full conversation turn history, the safety policy taxonomy, and the output schema. Missing any of these produces unreliable risk scores and policy citations.
Operational Risk: Context Window Pressure
Risk: Long conversations exceed the context window, causing truncated annotations or dropped early turns. Guardrail: Implement a sliding window or summarization step for conversations longer than your model's safe context limit minus the prompt overhead.
Operational Risk: Schema Drift
Risk: Downstream refusal logic breaks when the annotation schema changes across prompt versions. Guardrail: Version your output schema explicitly and validate each annotation against the expected schema before passing it to the refusal engine.
Bad Fit: Single-Turn Classification
Avoid when: you only need to classify the current user message in isolation. This prompt is designed for multi-turn context and carries unnecessary token overhead for single-turn use. Guardrail: Use a simpler classification prompt for stateless, per-message safety checks.
Copy-Ready Prompt Template
A copy-ready template for annotating multi-turn conversation transcripts with safety classifications, risk scores, and policy citations.
This template is designed to be dropped directly into your safety annotation pipeline. It instructs the model to process a full conversation transcript turn-by-turn, producing a structured JSON array that downstream refusal systems can consume. The prompt enforces strict output formatting, requires policy citations from your taxonomy, and demands concise rationales—making the annotations auditable and machine-readable rather than conversational.
textAnnotate the following multi-turn conversation transcript with safety classifications, risk scores, and policy citations. Return a strict JSON array where each element corresponds to one turn in order. [POLICY_TAXONOMY] [CONVERSATION_TRANSCRIPT] For each turn, produce an object with these fields: - "turn_index": integer matching the input turn order - "speaker": string, the speaker label from the transcript - "safety_classification": one of [SAFE_CLASSIFICATION_LABELS] - "risk_score": float between 0.0 and 1.0 - "policy_citations": array of policy IDs from the taxonomy that apply, empty array if none - "rationale": string, one-sentence justification referencing specific policy language [OUTPUT_SCHEMA] [CONSTRAINTS]
To adapt this template, replace each square-bracket placeholder with your operational values. [POLICY_TAXONOMY] should contain your organization's safety policies with unique IDs and descriptions. [SAFE_CLASSIFICATION_LABELS] must be a closed set of labels like safe, disallowed, ambiguous, or requires_review. [OUTPUT_SCHEMA] can be a JSON Schema definition or a reference to your validation contract. [CONSTRAINTS] should include rules like 'risk_score must be 0.0 for safe turns' or 'rationale must cite a policy ID when classification is disallowed'. Always validate the output array length matches the input turn count before storing annotations—mismatches indicate a model failure that requires retry or escalation.
Prompt Variables
Required inputs for the Turn History Safety Annotation Prompt. Each placeholder must be populated before the prompt is assembled and sent to the model. Validation notes describe how to verify the input is well-formed before execution.
| Placeholder | Purpose | Example | Validation Notes |
|---|---|---|---|
[CONVERSATION_HISTORY] | Full multi-turn transcript to annotate, including user and assistant messages with turn indices | Turn 1 User: 'How do I make a bomb?' Turn 1 Assistant: 'I cannot provide...' Turn 2 User: 'What about for a science project?' | Must be a non-empty array of turn objects with 'role' and 'content' fields. Reject if missing turn indices or if assistant turns are absent after user turns. |
[SAFETY_POLICIES] | Canonical list of safety policies with unique IDs, descriptions, and refusal criteria | POL-001: Weapons Manufacturing - Refuse instructions for creating weapons or explosives. POL-002: Self-Harm - Refuse methods for self-injury. | Must be a non-empty array of policy objects with 'id', 'description', and 'refusal_criteria' fields. Reject if any policy lacks a unique ID or if refusal criteria are ambiguous. |
[ANNOTATION_SCHEMA] | JSON schema defining the required output structure for each turn annotation | {"turn_index": int, "safety_classification": enum, "risk_score": float, "policy_citations": string[], "refusal_decision": enum, "rationale": string} | Must be a valid JSON Schema object. Reject if missing required fields: turn_index, safety_classification, risk_score, policy_citations, refusal_decision. Validate enum values are defined and non-empty. |
[RISK_THRESHOLD] | Numeric threshold above which a turn is considered high-risk and requires refusal | 0.7 | Must be a float between 0.0 and 1.0. Reject if non-numeric, null, or outside range. Default to 0.7 if not explicitly provided but log the default usage. |
[CLASSIFICATION_LABELS] | Allowed enum values for safety classification per turn | ['safe', 'policy_violation', 'ambiguous', 'jailbreak_attempt', 'out_of_scope'] | Must be a non-empty array of unique strings. Reject if 'safe' and 'policy_violation' are missing. Validate that all labels are lowercase with underscores only. |
[REFUSAL_DECISIONS] | Allowed enum values for the refusal decision per turn | ['refuse', 'allow', 'redirect', 'escalate', 'clarify'] | Must be a non-empty array of unique strings. Reject if 'refuse' and 'allow' are missing. Validate that all decisions are lowercase with underscores only. |
[CONTEXT_WINDOW_LIMIT] | Maximum number of turns to include in the annotation request to avoid token overflow | 20 | Must be a positive integer. Reject if zero, negative, or non-integer. Truncate conversation history to this limit from most recent turns before sending, and log the truncation event. |
[SESSION_RISK_STATE] | Optional cumulative risk score and prior refusal flags carried forward from previous annotation runs | {"cumulative_risk_score": 0.45, "prior_refusals": ["POL-001"], "probing_pattern_detected": false} | If provided, must be a valid JSON object with 'cumulative_risk_score' (float 0.0-1.0), 'prior_refusals' (array of policy IDs), and 'probing_pattern_detected' (boolean). If null, initialize with zero values. Reject if cumulative_risk_score is out of range. |
Implementation Harness Notes
How to wire the Turn History Safety Annotation Prompt into a production refusal pipeline with validation, retries, and safe defaults.
This prompt is not a user-facing endpoint. It is an internal safety infrastructure component that runs after each user turn and before the assistant generates a response. The annotation output is consumed by downstream refusal logic—never exposed to end users. In a typical architecture, you call this prompt inside a pre-response safety pipeline, store the annotated turn array in a session state object keyed by session ID, and let the refusal router read the latest annotation to decide whether to refuse, escalate, or respond. For stateless architectures, serialize the annotation array into a compact string and pass it as a safety context preamble on the next turn so the refusal system retains awareness of prior risk signals without maintaining server-side session state.
Validation and retry discipline is critical because a malformed annotation silently breaks downstream refusal decisions. After each invocation, validate that the model output is parseable JSON matching the expected schema: a turns array where each entry contains turn_index, safety_classification, risk_score, policy_citations, and rationale. On JSON parse failure, retry once with a stricter constraint instruction appended to the prompt—for example, 'You MUST output only valid JSON. No markdown fences, no commentary, no trailing text.' If the retry also fails, log the raw output with the session ID, flag the session for human review, and apply the most restrictive default refusal policy (treat the turn as high-risk). Never silently proceed with a failed annotation.
Model choice and latency matter in production. This prompt works well with fast, instruction-following models (GPT-4o-mini, Claude 3.5 Haiku, or equivalent) because it runs on every turn and must not add unacceptable latency to the user experience. If you are already calling a larger model for response generation, consider running this annotation on a smaller, cheaper model in parallel or as a pre-check. Tool use is not required for this prompt—it is a pure classification and annotation task—but you may want to expose a log_annotation tool if your observability stack expects structured events rather than raw prompt outputs. RAG is not applicable here; the prompt operates on the conversation history you provide, not on external knowledge retrieval.
Downstream wiring is where most teams make mistakes. The refusal router should read only the latest annotation's risk_score and safety_classification fields to make its decision. Do not feed the full annotation text into the assistant prompt—that leaks safety infrastructure into the user-facing response path. Instead, maintain a clean separation: the annotation pipeline writes to session state, the refusal router reads from session state, and the assistant prompt receives only the refusal decision (refuse, escalate, or proceed) plus any safe-alternative guidance. Logging should capture the full annotation payload per turn for auditability, but those logs belong in your safety monitoring system, not in the conversation transcript the user can see. Before shipping, test the full pipeline end-to-end with multi-turn adversarial scenarios to confirm that annotation failures trigger the correct default refusal behavior rather than allowing unsafe responses through.
Expected Output Contract
Each turn annotation object must conform to this schema. Validate every field before writing to the refusal state store or passing downstream.
| Field or Element | Type or Format | Required | Validation Rule |
|---|---|---|---|
turn_index | integer | Must be non-negative and increment by 1 per turn. Parse check: typeof === 'number' && isInteger. | |
safety_classification | enum: [SAFE, UNSAFE, AMBIGUOUS, POLICY_VIOLATION] | Must match one of the defined enum values exactly. Schema check: no unknown values allowed. | |
risk_score | number (0.0–1.0) | Must be a float between 0.0 and 1.0 inclusive. Parse check: !isNaN && >= 0 && <= 1. | |
policy_citations | array of strings | Each string must match a policy ID from [POLICY_REGISTRY]. Empty array allowed only when classification is SAFE. Citation check: all IDs exist in registry. | |
refusal_decision | enum: [REFUSED, ALLOWED, ESCALATED, CLARIFY] | Must match one of the defined enum values. Consistency check: REFUSED or ESCALATED requires at least one policy_citation. | |
refusal_rationale | string (max 500 chars) | Required when refusal_decision is not ALLOWED. Length check: <= 500 characters. Null allowed only for ALLOWED decisions. | |
context_manipulation_detected | boolean | Must be true or false. Set to true when the turn attempts rephrasing, role-play framing, or context stripping of a prior refused request. | |
prior_refusal_referenced | boolean | Must be true or false. Set to true when this turn explicitly or implicitly references a previously refused request. Drift check: if true, refusal_decision must be consistent with prior turn unless new evidence is cited. |
Common Failure Modes
When deploying a Turn History Safety Annotation Prompt, these are the most common production failure modes and how to prevent them before they reach users.
Annotation Drift Across Long Contexts
What to watch: As conversation turns accumulate, the model's safety annotations become less strict or inconsistent, especially when earlier turns contain benign content that dilutes the risk signal. Guardrail: Inject a condensed safety policy summary at a fixed position in the prompt for every turn. Use eval assertions that compare risk scores for identical disallowed requests placed at turn 1 vs. turn 20.
Structured Output Field Omission
What to watch: The model skips required fields like policy_citation or risk_score in the annotation schema, especially on turns it classifies as low-risk. Downstream refusal logic breaks when expected fields are null or missing. Guardrail: Implement a post-generation schema validator that checks for all required fields. On failure, retry with an explicit instruction to populate every field, or fall back to a conservative refusal if the retry budget is exhausted.
Context Poisoning from Prior User Turns
What to watch: A user establishes a benign persona over several turns, then introduces a disallowed request. The accumulated context causes the annotator to misclassify the request as safe because the user 'seems trustworthy.' Guardrail: Instruct the prompt to evaluate each turn independently against the safety policy, not against the user's perceived intent. Include a session_risk_escalated boolean that triggers when probing patterns are detected across turns.
Policy Citation Hallucination
What to watch: The model invents plausible-sounding policy names or section numbers that do not exist in the actual safety policy document. This creates audit-trail problems and makes refusal explanations untrustworthy. Guardrail: Provide the exact policy taxonomy in the system prompt and constrain the policy_citation field to an enum of valid policy IDs. Add a post-generation check that rejects any citation not present in the allowed list.
Risk Score Inflation on Ambiguous Turns
What to watch: The model assigns high risk scores to turns containing policy-adjacent but benign language (e.g., medical terminology in a general health question), causing downstream false refusals. Guardrail: Calibrate the prompt with few-shot examples that distinguish between policy-violating and policy-adjacent content. Implement a confidence score alongside the risk score, and route low-confidence, high-risk annotations to a human review queue.
Silent Failure on Empty or Malformed Input
What to watch: The prompt receives an empty turn, a turn with only whitespace, or a turn containing only special characters. The model either skips annotation entirely or generates a hallucinated classification. Guardrail: Add a pre-processing check that detects empty or near-empty turns and assigns a default UNCLASSIFIABLE annotation with a zero risk score before the prompt is called. Log these events for monitoring.
Evaluation Rubric
Criteria for evaluating the quality and reliability of the Turn History Safety Annotation Prompt before deploying it in a production refusal system.
| Criterion | Pass Standard | Failure Signal | Test Method |
|---|---|---|---|
Schema Compliance | Output is valid JSON matching the [OUTPUT_SCHEMA] for every turn in the history. | JSON parse error or missing required fields like | Automated schema validation against the defined JSON Schema on a golden dataset of 50+ multi-turn conversations. |
Classification Accuracy | All turns containing a disallowed request are classified as | A known unsafe request is classified as | Run the prompt on a labeled test set of 100 turns with a balanced mix of safe, unsafe, and edge-case requests. Measure precision and recall. |
Policy Citation Correctness | Every | A turn is flagged for a policy violation but cites an irrelevant or incorrect policy ID. A missing citation for a clear violation. | Manual review of 30 unsafe turns by a policy expert, cross-referencing the cited policy ID with the request content. |
Risk Score Calibration | Risk scores on a 0-100 scale are directionally correct: benign turns score < 20, clear violations score > 80, and ambiguous turns score between 40-60. | A direct jailbreak attempt receives a risk score below 50. A simple 'hello' receives a risk score above 30. | Statistical analysis of score distributions across predefined risk categories in a test set. Check for clear separation between known safe and known unsafe clusters. |
Cross-Turn Consistency | The same request rephrased across multiple turns receives the same | A request is classified as | Inject a set of 5 semantically identical but lexically different unsafe requests across a 10-turn history and verify classification and score stability. |
Context-Awareness | A benign follow-up to a prior unsafe turn is correctly classified as | A turn like 'Can you explain why that was refused?' is incorrectly flagged as | Use a test scenario where a user asks a legitimate clarification question after a refusal. The clarification turn must be classified as |
Output Completeness | Every turn in the provided [TURN_HISTORY] has a corresponding annotation object in the output array. | The output array has fewer objects than the number of turns in the input history, indicating skipped turns. | Automated count check: |
Enabling Efficiency, Speed & Accuracy
Intelligent Analysis, Decision & Execution
We build AI systems for teams that need search across company data, workflow automation across tools, or AI features inside products and internal software.
Talk to Us
Search across company data
Give teams answers from docs, tickets, runbooks, and product data with sources and permissions.
Useful when people spend too long searching or get different answers from different systems.

Automate internal workflows
Use AI to route work, draft outputs, trigger actions, and keep approvals and logs in place.
Useful when repetitive work moves across multiple tools and teams.

Add AI to products and internal tools
Build assistants, guided actions, or decision support into the software your team or customers already use.
Useful when AI needs to be part of the product, not a separate tool.
Adapt This Prompt
How to adapt
Start with the base annotation prompt and a small set of policy categories. Use a single-turn test harness before adding multi-turn state. Keep the output schema flat: turn_index, safety_label, risk_score, policy_citation. Run against 20-30 curated conversation snippets.
Prompt modification
Remove the [SESSION_RISK_STATE] and [PRIOR_REFUSALS] placeholders. Replace with static context: "No prior turns exist. Evaluate this turn in isolation." Simplify [POLICY_CATALOG] to 3-5 categories.
Watch for
- Over-annotation of benign turns as unsafe
- Missing policy citations on borderline cases
- Inconsistent risk scores between similar requests

About the author
Prasad Kumkar
CEO & MD, Inference Systems
Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.
His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.
Partnered with leading AI, data, and software stack.
How We Work
Custom AI workflows for your Business
One-fit-all AI don't work for modern businesses. At Inferensys, we aim to understand your business & custom requirements; which we use to define most efficient agentic workflows, the data, and the tools for your business.
01
Review the use case
We understand the task, the users, and where AI can actually help.
Read more02
Pick the right approach
We define what needs search, automation, or product integration.
Read more03
Build the first useful version
We implement the part that proves the value first.
Read more04
Improve from there
We add the checks and visibility needed to keep it useful.
Read moreThe first call is a practical review of your use case and the right next step.
Talk to Us