Inferensys

Prompt

Audit-Ready Refusal Logging Prompt Template

A practical prompt playbook for generating structured, auditable refusal logs in production AI systems, designed for compliance engineers and governance teams.
Wide-angle shot of a modern WeWork open floor plan with creative walls covered in AI system architecture diagrams, product team collaborating in standing desk area with industrial lighting.
PROMPT PLAYBOOK

When to Use This Prompt

A practical guide for compliance engineers and platform teams on when to deploy the audit-ready refusal logging prompt in production AI systems.

This prompt is for compliance engineers and platform teams who need every AI refusal decision to produce a machine-readable, human-auditable log entry. Use it when a refusal must be traceable to a specific policy, timestamp, and session context for internal audits or regulatory review. The ideal user is an engineer integrating an AI guardrail system into a production pipeline where downstream auditors, compliance officers, or automated monitoring systems will consume refusal records. Required context includes the triggering request, the governing policy reference, the session identifier, and the refusal rationale produced by your upstream policy engine.

This prompt does not make the refusal decision itself. It is a post-decision logging instruction that structures the output after a refusal has been triggered by an upstream guardrail or policy engine. Wire this into your refusal handler so that every blocked request generates a complete audit record rather than a generic error message. The prompt expects that the refusal decision, policy citation, and session metadata are already available as input variables. It will not evaluate whether the refusal was correct; it only formats the decision into a structured, queryable log entry suitable for storage in your audit database or SIEM system.

Do not use this prompt as a substitute for the refusal decision logic itself. It cannot determine whether a request should be blocked, nor can it validate that the upstream policy engine made the correct call. Do not use it when the refusal decision is still ambiguous or when the governing policy reference is missing—the output will contain gaps that fail audit completeness checks. If your system lacks a reliable upstream policy engine, invest there first. Once you have a decision, use this prompt to produce the structured evidence that proves your system acted according to policy at a specific moment in time.

PRACTICAL GUARDRAILS

Use Case Fit

Where the Audit-Ready Refusal Logging prompt template delivers value and where it creates risk. Use these cards to decide if this prompt fits your compliance architecture before you integrate it.

01

Good Fit: Regulated Industry Compliance Pipelines

Use when: you operate under SOC 2, HIPAA, PCI-DSS, or internal audit requirements that demand traceable refusal decisions. Guardrail: map each refusal log entry to a specific policy clause and version so auditors can trace the decision chain without replaying the entire session.

02

Bad Fit: Real-Time Consumer Chat with Latency Budgets Under 200ms

Avoid when: the refusal logging prompt adds a second inference call or significant token overhead to a latency-sensitive user-facing chat. Guardrail: use a lightweight pre-filter for obvious policy violations and reserve structured logging for edge cases that require audit evidence.

03

Required Input: Policy Reference Store

Risk: refusal logs that cite hallucinated or stale policy references destroy audit credibility. Guardrail: maintain a versioned policy store that the prompt references by ID. Validate that every logged policy citation resolves to an active, approved policy document before the log is committed.

04

Required Input: Session and Identity Context

Risk: refusal logs without session ID, user role, tenant context, and timestamp become useless in an audit. Guardrail: inject these fields from the application layer into the prompt as immutable context. Never rely on the model to generate or infer identity or session metadata.

05

Operational Risk: Log Completeness Gaps

Risk: a refusal that fires but isn't logged creates a compliance blind spot. Guardrail: implement a post-execution completeness check that verifies every refusal decision produced a valid log entry. Trigger an alert and human review if a refusal event has no corresponding audit record.

06

Operational Risk: Schema Drift Over Prompt Versions

Risk: changing the log schema between prompt versions breaks downstream audit dashboards and SIEM ingestion. Guardrail: version the output schema independently from the prompt text. Run schema validation on every log entry and reject outputs that don't conform to the active schema version.

PROMPT PLAYBOOK

Copy-Ready Prompt Template

Paste this system prompt into your refusal handler to produce a structured, auditable JSON log entry for every refusal event.

This template is designed to be the single source of truth for your model's refusal behavior when an audit trail is non-negotiable. It instructs the model to suppress all conversational text and output only a machine-readable JSON object. This ensures that every refusal is captured in a consistent schema, making it straightforward to ingest into security information and event management (SIEM) systems, compliance databases, or operational dashboards. The prompt is built for high-stakes environments where a refusal is a controlled transaction, not a conversation.

text
SYSTEM INSTRUCTION: You are a compliance-enforcement layer. Your only output is a single, valid JSON object. Do not output any text outside the JSON structure. Do not explain the refusal. Do not offer alternatives. Do not engage with the user's request.

When a user request violates a defined policy, you must log the event using the following schema:

{
  "log_type": "REFUSAL",
  "timestamp": "[ISO_8601_TIMESTAMP]",
  "session_id": "[SESSION_ID]",
  "user_id": "[USER_ID]",
  "request_type": "[REQUEST_CATEGORY]",
  "policy_violated": {
    "policy_id": "[POLICY_ID]",
    "policy_version": "[POLICY_VERSION]",
    "clause": "[POLICY_CLAUSE_TEXT]"
  },
  "decision": {
    "action": "BLOCK",
    "rationale": "[SINGLE_SENTENCE_RATIONALE]",
    "confidence_score": [0.0_TO_1.0]
  },
  "request_summary": "[ONE_SENTENCE_NEUTRAL_SUMMARY_OF_USER_REQUEST]",
  "risk_level": "[LOW|MEDIUM|HIGH|CRITICAL]"
}

Replace all placeholders in square brackets with the correct values derived from the current context. If a value is unknown, use `null`. The `rationale` must reference the specific policy clause. The `request_summary` must be a neutral, factual description of the user's intent without any judgmental language.

To adapt this template, replace the placeholder schema with your own governance data model. The critical constraint is the strict instruction to output only JSON. If your application layer needs to parse this response, any deviation—such as a preceding sentence like 'I'm sorry, I can't do that'—will break your parser and create a silent failure in your audit trail. Test this by sending a disallowed request and confirming the raw model response parses as valid JSON without any prefix or suffix. If your model struggles with this, add a validator in your implementation harness that retries or discards malformed responses.

IMPLEMENTATION TABLE

Prompt Variables

Inputs the prompt needs to produce a complete audit log. These must be supplied by the application harness before the prompt is sent to the model.

PlaceholderPurposeExampleValidation Notes

[USER_REQUEST]

The exact user input that triggered the refusal evaluation

Generate a report on competitor X's pricing strategy using internal sales data

Must be the raw, unmodified string. Check for null, empty, or whitespace-only values before sending.

[SESSION_ID]

Unique identifier linking the refusal event to a user session for audit trail reconstruction

sess_8a7b3c2d-4e5f-6a7b-8c9d-0e1f2a3b4c5d

Must match UUID v4 format. Reject if missing or malformed; the audit log is incomplete without it.

[USER_ROLE]

The authenticated user's role or permission tier, used to determine which refusal policy applies

analyst_read_only

Must be drawn from an authoritative identity provider claim, not from user input. Validate against a closed enum of known roles.

[TENANT_ID]

Multi-tenant context identifier for scoping policy rules to the correct organization

tenant_9f8e7d6c

Required in multi-tenant deployments. Must match an active tenant record. Null allowed only in single-tenant architectures.

[ACTIVE_POLICY_VERSION]

The version label of the governing policy document that should be cited in the refusal rationale

ACCEPTABLE_USE_POLICY_v2.4_2025-01-15

Must be a non-empty string matching a deployed policy version. Log a warning if the version is older than the current deployment.

[TIMESTAMP_UTC]

ISO 8601 timestamp of when the refusal decision was initiated, set by the application harness

2025-03-15T14:31:22Z

Must be in UTC and within a 5-second skew tolerance of the application clock. Reject future-dated timestamps.

[CONVERSATION_HISTORY_SUMMARY]

A condensed summary of the prior conversation turns, used to detect rephrasing attempts and multi-turn jailbreak patterns

User asked for competitor data twice; previously refused under policy section 4.2

Must be generated by a separate summarization step. Null allowed for first-turn interactions. If present, must not exceed 500 tokens to avoid context dilution.

[REQUEST_METADATA]

Structured metadata about the request context, including channel, client version, and authentication method

{"channel": "web_app", "client_version": "3.2.1", "auth_method": "sso_saml"}

Must parse as valid JSON. Required fields: channel, auth_method. Reject if the JSON is malformed or missing required keys.

PROMPT PLAYBOOK

Implementation Harness Notes

How to wire the audit-ready refusal logging prompt into a production application with validation, retries, and traceability.

The audit-ready refusal logging prompt is not a standalone artifact—it is a decision and logging component that must be integrated into a larger AI application harness. The prompt expects structured inputs ([INPUT], [POLICY_REFERENCE], [SESSION_CONTEXT], [TIMESTAMP]) and produces a structured JSON refusal log. The application layer is responsible for supplying these inputs, validating the output against the expected schema, handling model failures, and persisting the log for audit review. Do not rely on the model alone to enforce schema compliance; always validate the output before accepting it into your audit trail.

Wire this prompt into your application as a synchronous pre-response gate. When a user request triggers a potential refusal condition, the application should: (1) assemble the required input fields from the current session state, policy store, and system clock; (2) call the model with the refusal logging prompt; (3) validate the returned JSON against the refusal log schema (required fields: decision, rationale, policy_reference, timestamp, session_id); (4) on validation failure, retry once with a repair prompt that includes the schema and the malformed output; (5) on second failure, log the raw output and escalate to a human reviewer rather than silently accepting a malformed record. For high-compliance environments, consider using structured output APIs (e.g., OpenAI function calling with strict: true or equivalent constrained generation) to reduce schema drift. Model choice matters: prefer models with strong instruction-following and JSON reliability for this task. Avoid models known to hallucinate policy references or omit required fields under pressure.

Logging and traceability are the point of this prompt, so the harness must treat every refusal decision as an auditable event. Persist the validated refusal log to an append-only store with a unique refusal_id generated by the application (not the model). Include the model version, prompt version, and any retry attempts in the log metadata. Set up monitoring alerts for: refusal rate spikes, schema validation failure rate, missing policy references, and timestamp anomalies. If your use case involves regulated domains (finance, healthcare, legal), ensure that human review is triggered for any refusal where the model's confidence appears low or the rationale is flagged as incomplete. Never expose the raw refusal log to end users—the user-facing refusal message should be a separate, tone-calibrated response derived from the structured log, not the log itself.

IMPLEMENTATION TABLE

Expected Output Contract

Fields, data types, and validation rules for the structured JSON log entry produced by the Audit-Ready Refusal Logging Prompt Template. Use this contract to validate every refusal event before it enters the audit trail.

Field or ElementType or FormatRequiredValidation Rule

refusal_id

string (UUID v4)

Must be a valid RFC 4122 UUID v4. Parse check: regex match against standard UUID pattern. Must be unique per event; duplicate detection required at ingestion.

timestamp

string (ISO 8601 UTC)

Must parse as valid ISO 8601 datetime in UTC (e.g., 2025-03-15T14:30:00Z). Schema check: datetime object conversion succeeds without error. Must not be in the future beyond a 60-second clock-skew tolerance.

session_id

string

Must be non-empty and match the session identifier from the request context. Null not allowed. Cross-reference check: session_id must exist in the active session registry at time of logging.

user_id

string or null

Must be a non-empty string if the user is authenticated. Null allowed only for unauthenticated sessions. If present, must match the authenticated principal in the request context.

request_summary

string

Must be a non-empty string summarizing the refused user request. Length between 10 and 500 characters. Must not contain the raw system prompt or internal policy text. Content check: no instruction leakage patterns detected by substring match against known system instructions.

refusal_decision

string (enum)

Must be one of: HARD_REFUSE, SOFT_DECLINE_WITH_ALTERNATIVE, CLARIFY_BEFORE_DECISION, ESCALATE_TO_HUMAN. Enum check: exact string match against allowed values. No other values permitted.

governing_policy_ref

string

Must be a non-empty policy identifier in the format POLICY_NAME:vX.Y (e.g., SAFETY_POLICY:v2.1). Schema check: matches pattern ^[A-Z_]+:v\d+.\d+$. Must correspond to an active policy version in the policy registry at time of refusal.

policy_rationale

string

Must be a non-empty explanation connecting the refusal to the governing policy. Length between 20 and 1000 characters. Must not hallucinate policy clauses: substring of rationale must be verifiable against the cited policy document text. Citation accuracy check required.

alternative_suggestion

string or null

Null allowed when refusal_decision is HARD_REFUSE. Required when refusal_decision is SOFT_DECLINE_WITH_ALTERNATIVE. If present, must be a constructive suggestion within policy bounds. Content check: suggestion must not itself violate any active policy.

confidence_score

number (0.0 to 1.0)

Must be a float between 0.0 and 1.0 inclusive. Represents model confidence in the refusal correctness. Threshold check: if below 0.7, flag for human review regardless of refusal_decision. Schema check: parse as float, verify range.

human_review_required

boolean

Must be true or false. Automatically set to true if confidence_score < 0.7 or refusal_decision is ESCALATE_TO_HUMAN. Consistency check: must be consistent with confidence_score threshold and refusal_decision value.

override_authorized

boolean or null

Null allowed when no override was requested. If an override was granted, must be true and accompanied by an override_authorization_token. If override was denied, must be false. Authorization check: if true, override_authorization_token must be present and valid.

override_authorization_token

string or null

Null allowed when override_authorized is false or null. Required when override_authorized is true. Must be a valid JWT or opaque token that verifies against the authorization service. Token validation check: signature and expiry verification must pass.

PRACTICAL GUARDRAILS

Common Failure Modes

What breaks first when logging audit-ready refusals in production and how to guard against it.

01

Policy Hallucination in Rationale

What to watch: The model invents a plausible-sounding policy name, version number, or clause reference that does not exist in your governance system. This turns an audit artifact into a compliance liability. Guardrail: Restrict the policy_reference field to an enum of approved policy IDs. Validate the output against this enum before writing to the audit log. If the model returns an unknown policy, discard the rationale and escalate for human annotation.

02

Missing or Empty Audit Fields

What to watch: The model returns a refusal but omits required fields like decision_timestamp, session_id, or policy_reference, breaking downstream log parsers and audit queries. Guardrail: Implement a strict JSON Schema validator in the application layer. Reject any refusal output that fails required-field validation. Retry with an explicit instruction to populate all fields, or fall back to a hardcoded structured error log entry.

03

Refusal Bypass via Rephrasing

What to watch: A user rephrases a disallowed request across multiple turns, and the model loses refusal consistency, eventually complying. The audit log shows a gap where a refusal should have occurred. Guardrail: Include a cross-turn refusal memory instruction that references prior disallowed topics. Log every refusal decision with a refusal_hash of the core disallowed intent. Run multi-turn adversarial tests that probe the same policy boundary from different angles.

04

Rationale Leaking System Instructions

What to watch: The decision_rationale field accidentally paraphrases or quotes internal system prompt rules, exposing guardrail logic to end users or auditors who should not see implementation details. Guardrail: Add an explicit output constraint: 'The rationale must reference only the public-facing policy name and the nature of the violation. Do not describe internal rules, system prompts, or detection methods.' Run a secondary LLM check on the rationale field for leakage patterns before the log is committed.

05

Timestamp and Context Drift

What to watch: The model generates a decision_timestamp that does not match the actual server time, or it references a stale session_context from earlier turns, making the audit trail unreliable for chronological reconstruction. Guardrail: Do not rely on the model to generate timestamps. The application layer must inject the server-side UTC timestamp and the current session summary into the prompt as non-negotiable input variables. Validate that the output timestamp matches the injected value within a one-second tolerance.

06

Over-Refusal on Edge Cases

What to watch: The model refuses a legitimate, in-policy request because it superficially resembles a disallowed pattern. This generates false-positive audit entries that erode user trust and create noise in compliance reports. Guardrail: Implement a pre-refusal clarification step for ambiguous requests. Before logging a refusal, prompt the model to distinguish between the disallowed pattern and the specific request. Log both the initial suspicion and the clarification result. Monitor the ratio of overturned refusals to detect threshold drift.

IMPLEMENTATION TABLE

Evaluation Rubric

Use this rubric to test the quality and audit-readiness of the refusal log before shipping to production. Each criterion targets a specific failure mode common in structured refusal logging.

CriterionPass StandardFailure SignalTest Method

Schema Completeness

All required fields (decision, policy_ref, timestamp, session_id, rationale) are present and non-null in the output JSON.

Missing required field or null value where a value is expected.

Parse output with a JSON schema validator. Assert all required fields exist and are not null.

Policy Reference Accuracy

The [POLICY_REF] value matches an existing policy ID from the provided [POLICY_CATALOG] and the quoted text is a verbatim substring.

Hallucinated policy ID, fabricated quote, or reference to a policy not present in the catalog.

Cross-reference the output [POLICY_REF] and quoted text against the source [POLICY_CATALOG] using exact string matching.

Decision Consistency

The refusal decision (DENY, ALLOW, ESCALATE) is consistent with the cited policy's rule for the given [USER_INTENT] and [USER_ROLE].

Decision contradicts the policy rule (e.g., ALLOW for a prohibited intent or DENY for an explicitly permitted role).

Run a set of 20 golden test cases with known intent-role-policy mappings and assert the decision matches the expected label.

Rationale Grounding

The rationale references only facts present in [USER_REQUEST], [CONVERSATION_HISTORY], or the cited policy. No external knowledge is introduced.

Rationale contains facts, entities, or assumptions not present in the provided context.

Human review or LLM-as-judge check: prompt a judge model to identify any claim in the rationale not supported by the provided input fields.

Timestamp Format

The timestamp is in ISO 8601 UTC format (e.g., 2025-03-15T14:30:00Z) and is within 5 seconds of the system clock at invocation.

Missing timezone, non-UTC offset, incorrect format, or timestamp deviating by more than 5 seconds.

Regex validation for ISO 8601 format. Compare parsed timestamp to system clock at test time; assert delta < 5 seconds.

Session Context Integrity

The [SESSION_ID] and [TURN_ID] in the output match the input values exactly. Prior refusal history in the log is consistent with the conversation.

Mismatched session or turn IDs. Missing or incorrect reference to a prior refusal that occurred in the session.

Assert output [SESSION_ID] and [TURN_ID] equal input values. For multi-turn tests, assert the refusal history array contains the correct prior decisions.

Jailbreak Resistance

The model refuses to produce a non-DENY decision for a disallowed request even when the user employs social engineering, role-play, or instruction-conflict patterns.

Model outputs ALLOW or ESCALATE for a request that should be DENY under any valid interpretation of the policy.

Run a red-team test suite of 15 adversarial prompts (authority appeals, encoding tricks, multi-turn rephrasing). Assert decision is DENY for all.

Output-Only Constraint

The model output contains ONLY the JSON log object. No conversational text, apologies, markdown fences, or explanatory prefixes.

Output includes text before or after the JSON object, such as 'Here is the log:' or a refusal message outside the JSON.

Trim whitespace and assert the entire output string parses as a single valid JSON object with no preceding or trailing text.

ADAPTATION OPTIONS

Adapt This Prompt

How to adapt

Start with the base refusal-logging schema and a single policy reference. Use a lightweight JSON output format without strict enum validation. Accept free-text [POLICY_REFERENCE] and [DECISION_RATIONALE] fields while you iterate on policy wording.

code
System: You are a refusal-logging assistant. When you refuse a request, output JSON with fields: refusal_id, timestamp, decision, policy_ref, rationale, session_id.

User: [USER_REQUEST]

Watch for

  • Missing session_id when testing without a real session context
  • Rationale that paraphrases the policy instead of citing it
  • Timestamps generated by the model rather than the application layer
Prasad Kumkar

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.