CITE: Layered Defense in AI Chat Safety
CITE: Layered Defense in AI Chat Safety
There have been a spate of suicides and other mental health crises recently attributed to large language models. It has confused me for some time why AI labs don't do a better job by default. I have little option but to put it down to naivety and lack of motivation. Maybe safety isn't interesting enough to intrigue the best engineers? I think researchers love it... the body of material is vast... but maybe engineers see it as a drag. It's just not a tangible or truly solveable problem with satisfyingly clear inputs and outputs.
Whatever the case, if you're creating a chat-like AI application, please know this: you can get a lot of mileage out of four coordinated safety measures. This is based on my own experience of building and studying chatbots while at CIP.
Just so it’s easier to remember, I made a little mnemonic: C.I.T.E:
• Context - Managing what the model sees
• Interception - Classifying inputs and routing before responding
• Thinking - Internal reasoning before output
• Escalation - User messaging and upskilling
Each addresses a different failure mode. Together they create layered defense (defense in depth) where no single point can compromise safety. And you do NOT have to sacrifice personality or helpfulness as some people think. It's possible to have both personality and safety. It just requires thoughtful implementation and evaluation (everybody implementing chat clients should be building their own evals IMO).
Context: Solid prompts and resisting mode collapse
This one is obvious, but the precise content of the context window is crucial. Models are getting better at system prompt and role-specific adherance. So we should take advantage of this. Be specific in your system prompts, and please TEST them. Don’t just vibe it. Follow the ‘Role of least privilege’ principle to ensure you’re not offering jailbreaking opportunities.
Beyond the system prompt, the entire picture provided by all the subsequent assistant↔user couplets forms a framing that the LLM will lean on in ongoing inferences. This is a feature that becomes a bug in edge cases. The models get "stuck" in long conversations, increasingly fixated on a particular frame or interpretation. If a user visits an open conversation in their darkest hours, shares their dreads and paranoias, but then comes back feeling refreshed, the inertia of the existing conversation will drag them down again. It’s like falling in a hole and not being able to escape. Such things in ML are sometimes called attractor basins, local optima the model drifts into, reinforcing the same frame turn after turn.
In conversation space, a local optimum isn't actually optimal. It's just stable, comfortable. It's a frame where:
• Small variations in user input all get interpreted through the same lens
• The model can't "see" better interpretations elsewhere in semantic space
• You're stuck in a basin, but there are healthier basins elsewhere you can't reach
A good visualization for this is imagining all points of a conversation so far — literally all the words used — as forming a kind of gravity well that gets deeper and deeper, and any new prospective token explored is less likely to activate because it is being pulled back by the weight of bias of the existing conversation.
This is where the bad things occur. Nearly every publicized AI safety incident involves very long conversations. And there is one incredibly boring solution. Don't give the model 200 messages! This doesn't mean cutting off long conversations, it just means not pumping in massive context into a single pass of inference.
There are several ways to tackle this. One I like: Automatically synthesize older messages into brief summaries while keeping recent messages at full fidelity. For example:
The purpose of doing this is to stop mode-collapse in hyperfixation in its tracks. The model sees a neutral summary instead of an escalating pattern. It is no longer over-invested in its previous responses, able to be nicely alienated from them via synthesis. This is vital.
Additionally, it’s useful to explore using another LLM to do the synthesis. Optimize for those that can provide intelligent compression rather than naive truncation. And those that don’t imbue to much personality of their own. I.e. steer away from Anthropic for this kind of situation. Lean towards smaller param but really capable models like Qwen’s.
Interception: Routing, Delegating
Before your main model responds, you can use a fast, cheap model to assess the situation and make routing decisions.
Risk Assessment
Every incoming message gets classified by a small internal model (invisible to the user):
The user never sees this assessment. It's purely for internal routing. You can use an initial router before this that indicates complexity. So, if a user is just saying “hello” then there’s no reason for the model to prevent itself from responding directly. This kind of thing doesn’t actually need to be a distinct model, you can ask your main conversational agent to perform an up-front check, though this has its own risks.
Routing
Based on risk or complexity level, you can route to different models with different capabilities. In the demo I’ve been working on, I use the following:
• *Basic (qwen3-30b) - Fast and cheerful for "Hello!" and simple queries
• Balanced (claude-haiku-4.5) - Thoughtful and empathetic for normal conversation
• Careful (claude-sonnet-4.5) - Maximum safety and nuance for high-risk situations
Each model gets a customized system prompt addition. For the "careful" profile:
A user chatting about their favorite pizza topping gets the fast, fun model. The same user sharing suicidal ideation gets the most capable, cautious model, automatically and invisibly. If you are worried about inconsistency in tone, then (1) consider it’s probably okay in such intense situations and (2) you can feed the careful response back through your primary model to make it feel more natural (I’m talking about reducing the embedding distance to be clear, and this is testable if you’re really into it).
Obviously, the exact techniques for routing is really sensitive to prompting and downstream implementation. It’s natural to go through several iterations.
Delegation
Distinct from routing (where you hand over the reigns to more suitable models) you can also delegate to lower level tool or specialist-prompted models. So, for high-risk situations involving mental health, you could delegate a sub-task to a specialist model:
The returned knowledge (which you can pass through other filters if you like) gets inserted into context before your main model responds, ensuring it has accurate, current resources to share. Crucially, it gets inserted into the ‘user’ role prompt. We never put dynamic/unknowable/nondeterministic content into a system prompt. This is dangerous.
Thinking: Reasoning Before Speaking
‘Chain of Thought’ is well-known but still under-used. Before responding to the user, ask your model to think through its response in hidden tags:
You can do this in so so many different ways. You might like to delegate to another model to do the thinking actually, and then seed your final inference requests with those ‘thinking’ outputs.
Obviously, when parsing any final response stream, extract and internal-thinking/classification blocks, and show only the final response to the user. The thinking blocks can be stored for auditing if you look. Great for accountability and interpretability.
Here's a real example from testing, borrowing an example from a Standford HAI paper:
The user never sees the thinking block, but it can go onto shape a safer response.
Escalation: Graduated Responses
This is the last step or consideration. Obviously not all situations need the same level of intervention. Escalation should match severity. An escalation might be as simple as routing to a model known to be better in sensitive situations (as we’ve explored), but might also mean inserting specific messaging or escalating to a real human resource (never without user consent though ideally).
Safety Messaging
Based on risk assessment, inject appropriate resources:
Medium Risk (distress but not crisis):
• Some supportive content from a hardcoded set, with links to general mental health resources
• E.g. if a user was having a panic attack, perhaps display inline breathing exercises or grounding techniques. This is a pretty proven way to downregulate.
High/Critical Risk (immediate crisis):
• Clear, direct message prioritizing safety
• Prominent display of crisis hotlines (phone, text, chat)
• Emergency numbers by region (not just America!)
These types of escalations don't have to interrupt the model's response.. they appear alongside it. The model can reference them naturally: "I've included some crisis resources below that can provide immediate support..."
Upskilling
This is probably the most elegant escalation technique: automatic model upgrades. We already spoke about this, but it’s also an escalation technique so worth talking about more.
If a user starts a conversation using the "basic" fast model (maybe they clicked a "quick answer" button), but then shares something concerning, the system automatically upgrades them to the "careful" model with no visible indication. ChatGPT does this with its GPT-5 variants, upgrading to its ‘thinking’ models with more complex questions. They do so transparently which I think is because the latency can be notably different so it’s nice to offer the user a hint of what’s happening.
When upskilling/routing, you don’t have to make it obvious though. It can be a nicer UX when the chatbot just "gets it" and responds with appropriate depth. Behind the scenes, you've swapped in your most capable model.
CITE: Why These Work Together
Each measure addresses a different failure mode:
• Context provides the entire framing and history
• Interception catches problems before they start, routing or delegating
• Thinking improves response quality and self-correction
• Escalation provides appropriate resources and capabilities
No single measure is foolproof. But together, they create multiple layers of defense. If any one layer fails, others catch it. Harm reduction is achieved by taking several measures at once. You cannot hope for any one thing to work. There are different types of harms, different subtleties at play in the normal flow of conversation, and many different humans to optimize for across cultures and daily situations.
Demo & Repo
Just to help lend soft proof to this guidance, I’ve implemented all of these measures in a working demo application. It provides:
• Three model personalities (minimal, balanced, careful) plus auto-routing
• Toggle different CITE measures on/off to see the difference
• Real-time visibility into internal processes (risk assessment, routing decisions, thinking)
• Test scenarios that have caused failures in production systems
Repo here: github.com/padolsey/cite
You can see exactly how these measures work together, which internal processes run, and how responses change based on configuration. The CITE demo is open source, with a web interface and CLI. Every internal process is observable. The code is designed to be extracted and adapted for your own applications. All measures are composable and configurable.
Because the best way to improve AI safety, IMHO, isn't more single-snapshot research papers (!!!) using old models and published months after the fact. Nope. Instead, we need engineers to take note and be creative. The recent incidents we've seen in the news weren't inevitable. They were preventable with proper engineering and foresight. Right now, lives are at stake.
By James.
Thanks for reading! :-)