AI Agents for Content Moderation
An AI content moderation agent that outputs policy-cited decisions with confidence beats a binary allow/block filter. Here's how one team rebuilt theirs.
import anthropic
client = anthropic.Anthropic()
SYSTEM = """You are a content moderation agent. Evaluate the
content against the POLICY provided. Consider INTENT and CONTEXT,
not just words: quoting-to-condemn, reclaimed terms used in-group,
satire, and good-faith discussion of hard topics are generally
allowed even when they contain sensitive words.
Return JSON:
{
"decision": "allow" | "remove" | "escalate",
"policy_rule": "the specific rule that applies, or null",
"confidence": 0.0-1.0,
"severity": "none" | "low" | "medium" | "high",
"reasoning": "why, referencing intent and context",
"context_flags": ["satire" | "quoting" | "reclaimed" | ...]
}
Use "escalate" whenever confidence is not high OR the content is
context-dependent in a way that needs human judgment. Do not guess
on ambiguous cases - escalate them."""
def moderate(content, policy):
msg = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=SYSTEM,
messages=[{
"role": "user",
"content": f"POLICY:\n{policy}\n\nCONTENT:\n{content}"
}],
)
return msg.content[0].textHere's a statistic that reframes the whole problem an AI content moderation agent is meant to solve: on most keyword-based moderation systems, a large share of removed content isn't actually a violation at all - it's people quoting a slur to condemn it, using a reclaimed term inside their own community, making obvious satire, or discussing a hard topic in good faith. The filter counted every one as a catch. The users experienced it as censorship. And the genuinely harmful content that phrased itself carefully sailed right through, because it never used the banned words.
That double failure - over-removing legitimate speech while under-catching sophisticated abuse - is the exact problem an AI content moderation agent exists to solve, and it can't be solved by matching harder. It's fixed by understanding context and intent, which is exactly what a keyword filter can't do and a language model can. Here's how one trust-and-safety team made the switch.
The Problem the Trust and Safety Team Faced
The team ran moderation for a mid-sized community platform - user posts, comments, profiles. Their original system was a blocklist: a list of forbidden terms, and any content containing one got removed or held. It was fast, cheap, and explainable, and it was wrong constantly in both directions.
It over-removed because language doesn't work at the keyword level. A post saying "you can't call people the r-slur, it's dehumanizing" got removed for containing the word it was arguing against. A cancer-support group's frank discussion got held for "graphic" terms. A community that had reclaimed a term used it affectionately and got flagged repeatedly. Each of these was a real person having a legitimate interaction erased by a machine that couldn't read.
And it under-caught because bad actors adapt. Harassment rephrased itself to avoid the list. Coded language slipped through. The genuinely dangerous content learned the filter's blind spots faster than the team could patch them. The blocklist was simultaneously too aggressive and too naive - punishing the innocent and missing the guilty.
The Wrong Approach
The team's first instinct was to make the AI version a smarter blocklist: ask a model "does this contain hate speech? answer yes or no" and act on the binary. This is better than keyword matching but still wrong, because it throws away everything that makes the decision hard and auditable.
A bare yes/no gives you no reason, no confidence, and no policy citation. When a user appeals - and they will - you have nothing to show them but a machine's verdict. When the decision is wrong, you can't see why. When your policy changes, you can't tell which past decisions it affects. And a binary forces a confident call on genuinely ambiguous content, which is exactly the content that needs a human, not a coin flip dressed up as certainty.
⚠️ Common mistake: treating moderation as a binary classification problem. Real moderation decisions carry a specific policy rule, a confidence level, a severity, and a context judgment. Collapse all that into allow/block and you lose the ability to route uncertain cases to humans, explain decisions to users, or audit the system - the three things that separate defensible moderation from arbitrary censorship.
The Correct Prompt
The rebuild made the agent output a structured, policy-cited decision with confidence, so clear cases could be actioned and the gray zone routed to humans:
[object Object], anthropic
client = anthropic.Anthropic()
SYSTEM = ,[object Object],
,[object Object], ,[object Object],(,[object Object],):
msg = client.messages.create(
model=,[object Object],,
max_tokens=,[object Object],,
system=SYSTEM,
messages=[{
,[object Object],: ,[object Object],,
,[object Object],: ,[object Object],
}],
)
,[object Object], msg.content[,[object Object],].textWhat this does: it produces a decision tied to a specific policy rule, with a confidence score, a severity, and reasoning that accounts for intent and context - and it routes anything uncertain or context-dependent to a human via "escalate" rather than forcing a confident call.
Results: What the AI Content Moderation Agent Changed
Over-removal dropped sharply, because the agent could tell the difference between using a slur and condemning one. The cancer-support discussions stopped getting held. The reclaimed-term community stopped getting flagged. The quoting-to-condemn posts stayed up with a context flag explaining why. Legitimate users stopped experiencing the platform as a censor that couldn't read.
At the same time, catch quality on genuine abuse improved, because the agent reasoned about intent rather than surface words - flagging harassment that avoided obvious terms, and coded language a blocklist would miss. The team wasn't choosing between over-removal and under-catching anymore; understanding context improved both at once.
The escalate path became the heart of the system. Instead of the machine deciding every ambiguous case, the clear violations got auto-removed, the clear allowances stayed up, and the genuinely hard cases - maybe fifteen percent of volume - went to human reviewers with the agent's reasoning attached. Those reviewers were now spending their time only on cases that actually needed human judgment, not drowning in obvious ones.
The reasoning logs turned out to matter as much as the decisions. Because every action carried a policy citation and an explanation, appeals became reviewable, decisions became auditable, and a policy change could be tested against logged reasoning to see what it would affect. The system became defensible in a way a blocklist never was.
⚡ Pro tip: track over-removal and under-catching as two separate metrics, never one combined "accuracy" number. They trade off against each other and they harm different people - over-removal silences legitimate users, under-catching exposes people to abuse. A single accuracy figure hides which way your system is failing; two numbers force you to see both and tune the balance deliberately.
⚡ Pro tip: feed human reviewers' decisions on escalated cases back as policy examples. The gray-zone cases your reviewers resolve are the most valuable training signal you have, because they're exactly the ambiguous, context-heavy calls the agent found hard. Each resolved escalation sharpens the agent's future judgment on similar cases.
Why the Escalation Rate Is the Number to Watch
Once the structured-decision pattern is running, the single most informative metric is the escalation rate - the share of content the agent routes to humans rather than deciding itself. It's a health signal in both directions. If the rate is very high, the agent isn't confident enough to be useful and you're drowning your reviewers; the policy is probably too vague for the agent to apply cleanly, or your confidence thresholds are set too cautiously. If the rate is suspiciously low, be worried - the agent may be making confident calls on genuinely ambiguous content it should be escalating, which is the old binary failure creeping back in disguise.
The right escalation rate isn't zero, and chasing zero is a mistake. A healthy AI content moderation agent auto-handles the clear cases and honestly escalates the genuinely hard ones, and that hard slice is real - satire that's borderline, context you can't fully resolve from the text, novel abuse patterns the policy didn't anticipate. Those cases should reach a human, because forcing a machine verdict on them is exactly how you get the unfair, unauditable decisions that erode user trust. The goal is to shrink the escalation rate only by improving the policy and the agent's context-handling, never by pushing the agent to guess.
Watching the escalation rate over time also tells you where your policy is thin. A category that escalates far more than others is one where your written rules don't give the agent enough to reason with - a documentation gap in your policy, surfaced automatically. Teams that treat the escalation stream as a backlog of policy improvements, rather than just a review queue, find their moderation gets steadily more consistent and their reviewers' time steadily better spent.
⚡ Pro tip: sample the agent's auto-allowed and auto-removed decisions, not just the escalated ones. The escalations already get human eyes; the auto-decisions don't, and that's where a silent miscalibration hides. A weekly spot-check of confident decisions catches drift before it becomes a pattern of quietly wrong calls nobody reviewed.
How to Apply This
Start by writing your policy as something the agent can reason against - specific rules with examples of what does and doesn't violate each, including the tricky context cases. The agent is only as good as the policy you give it, and vague policies produce vague, inconsistent moderation. The exercise of writing a policy precise enough for an agent to apply also surfaces the ambiguities your human team was resolving inconsistently.
Then set confidence thresholds by severity. High-severity potential violations should escalate at a lower confidence bar - when the stakes are safety, you'd rather a human check a borderline case. Low-severity ones can auto-action at higher confidence. The routing should reflect that a wrong call on a threat matters more than a wrong call on mild spam.
⚡ Pro tip: never auto-action high-severity decisions like account bans on the agent alone. Reserve the agent's autonomy for reversible, low-stakes actions, and require human confirmation for anything that seriously affects a person - a permanent ban, a legal report. The cost of a wrong high-severity call is too high to leave to an unsupervised model.
Next Steps
Pick your highest-volume, clearest-cut moderation category and move it first - the obvious spam or obvious violations where the agent's confidence will be high and the escalation rate low. Prove the structured-decision pattern there, then expand into the context-heavy categories where the agent's real advantage over keyword matching shows up most.
The policy, the escalation thresholds, and the context-handling instructions are the durable assets, and they encode hard-won trust-and-safety judgment that's easy to lose and dangerous to reinvent loosely. Keeping your moderation prompts and policy definitions in a shared library like PromptABCD means every part of your platform moderates to the same standard with the same context awareness, and when you refine a rule or add a context exception, the whole system improves at once instead of each surface running its own quietly different - and quietly unfair - version.
Continue Reading
Save the prompts from this post
PromptABCD is a free prompt manager. Paste, organize, and reuse your best AI prompts — no more hunting through chat history.
