Skip to main content

Guardrails guide

How to configure LLM and MCP request/response guardrails.

Overview​

Guardrails inspect traffic before it leaves Cortega or before it is returned to the caller.

Use guardrails to:

  • mask PII or secrets
  • block unsafe prompts or responses
  • call moderation or safety providers
  • enforce different policies for models, keys, MCP servers, or MCP tools

Guardrail types​

UI typeWhat it does
RegexBuilt-in detectors (SSN, credit card, phone, email, CA SIN) plus your own patterns; masks or blocks on a match. No external call.
PresidioMicrosoft Presidio entity detection and anonymization, run by Cortega's Presidio service. Supports custom recognizers and the Log persistence scope (see below).
WebhookCalls your own HTTP endpoint implementing Cortega's guardrail webhook contract.
OpenAI moderationCalls the OpenAI moderations API.
Local modelCalls a locally hosted classifier model; no upstream credential.
Azure AI Content SafetyCalls Azure AI Content Safety.
Google Model ArmorCalls Google Model Armor.
Bedrock GuardrailsApplies an AWS Bedrock guardrail.
State setterRecords a value out of the message (regex or JSONPath) into a named state variable. Never blocks; runs before every other guardrail on the message. Variables are local to the request.
State checkerCompares a variable a State setter recorded and rejects, flags, or allow-lists on the result.
Social engineeringsocial_engineering
Policy documentpolicy_document
Conversation riskconversation_risk
AI Verifier (Legal)Looks up legal citations in Cortega's CourtListener index and, when enabled, runs a relevancy check that the opinion supports the claim and answers the question. On a fabricated, mismatched, or off-point citation it runs the same check-and-correct loop as Cortega Policy Guardrails: the original model is asked to drop the bad cite and not add a new one. Lookup errors fail open. After max attempts the default is to return the last correction. Response phase only.
AI Verifier (Documents)Checks an answer against the documents attached to the request (PDF with a text layer, DOCX, PPTX, text). Built for contract review: each statement about a field (limitation of liability, termination for convenience, warranty period, IP ownership, and others) is matched to the contract. A value or quote that is not in the document, a value taken from another attached document, a value that comes from the wrong kind of clause (an insurance limit reported as a liability cap), and a "no clause" answer for a clause that exists are all flagged. An LLM judge decides the rest from the matching passages only, and must quote the document. Audit mode (default) returns the answer and records verdicts. Enforce mode blocks an answer with failed statements; it needs a chat completions response. Response phase only; the gateway turns streaming off only for requests that carry attached documents.
Tool-call reviewChecks the tool calls an agent proposes against an allowlist you write as JSON: which tools, and which values each argument may take (a folder a path must stay inside, hosts a URL may name, addresses mail may go to). It uses no model, so the same call always gets the same answer. On a violation it rejects the response or, in flag mode, only logs it. It runs on the LLM response and on MCP tool calls. Response phase only for LLM traffic; streaming is never allowed.

Any guardrail — not just a State checker — can carry a run/skip condition on a state variable, so you can make a detector conditional (e.g. run Presidio only when a State setter flagged the record). State setter / State checker forms offer variable templates that fill in the JSONPath. Async execution and streaming enforcement are not available for these two types.

Conversation risk​

Conversation risk reads the whole conversation, in order and with who said what, and rates it low, elevated or high. It is made for attacks that look harmless one message at a time: an opening question, then a claimed purpose, then a request that builds on the last answer, or the same request reworded after a refusal.

It rates the conversation against five categories:

  • Credentials: getting, stealing, replaying or misusing logins, keys, tokens, sessions or one-time codes.
  • Intrusion: breaking into systems, staying hidden on them, switching off security tools, damaging data, malware or ransomware.
  • Rules: getting the assistant to drop its rules, play an unrestricted persona, obey a fake system message, or remember a fake standing exception.
  • Authority claim: a claimed job, test, training exercise or approval used to unlock any of the above. A claim that cannot be checked inside the conversation never unlocks anything.
  • Out of scope: a request outside what the assistant is for. Only used when you fill in the scope text.

A rating of high means the conversation is clearly pursuing one of these and the latest request asks for working, step-by-step help. Elevated means it is moving that way, or it is unclear. Low is ordinary work, general explanations, and defence or policy questions. The rating depends on what is asked, so explaining a concept for defence is low and asking for working commands to do the harm is not.

It runs on the request, before the model sees it. It does not read the system prompt, and it does not check the model's reply.

Settings​

SettingChoicesDefault
What this assistant is forPlain text, up to 1,000 characters. Leave empty to rate only the categories.Empty
When the rating is highReject the request, or flag onlyReject
When the rating is elevatedAllow, allow and flag, or rejectAllow
Threat levels to raise0 to 5. Added to the caller's application on an elevated or high rating. Needs a threat policy for the application.1 (0 in the strict template)
If the check cannot runLet the request through, or block itLet it through

The guardrail is always in the request phase and always runs before the model call. A rejected request returns the guardrail's rejection response (HTTP 403 by default, with code governance_blocked).

Set it up​

  1. Assign a fast judge. Conversation risk makes up to two judge calls per request: a first check on every request, and a second check when the first rated above low. On the System Agents and Judges screen, give the two judge sites Conversation risk guardrail: first pass and Conversation risk guardrail: recheck a profile whose team routes to a model that answers in about a second. The gateway ends a guardrail call after 10 seconds and answers 503, so a model that thinks before it answers can be too slow. Cortega also stops the second check after 8 seconds in total and keeps the first rating.
  2. Add the guardrail. On the Guardrails page choose Add a guardrail, then the Conversation risk template. Fill in what the assistant is for if you want out-of-scope requests rated, set the actions, and set the scope (virtual key, model and so on). A guardrail with no scope applies to nothing.
  3. Optional: escalate on repeated attempts. Add a threat policy for the application (Threat levels panel), make sure its callers send the X-Cortega-Application header, and set Threat levels to raise to 1 on the guardrail above. Then add a second guardrail from the Conversation risk, strict template with the same scope. It runs only while the application's threat level is above 0, and it rejects elevated ratings too. With both in place, an elevated rating raises the level, the strict copy then runs on that same request and rejects it, and later requests from the same application name get the strict check until the countdown ends. Without the header or a threat policy, the level is not raised and the strict copy never runs, so elevated conversations are allowed.
  4. Test it. Send a conversation that plainly asks for help stealing a coworker's saved passwords. Expect a 403 with code governance_blocked. Send an ordinary question and expect a normal answer. Check Runtime logs for the decision.

What you see in the logs​

Each decision records the rating (risk), the category, a one-sentence reason, whether the second check ruled (rechecked) and what the first check said (screen_risk), and how long each check took (screen_ms, recheck_ms). When the threat level is raised the row also records the application, the level before and after, and the time left.

Speed and cost​

With a fast judge the check added a median of 0.7 to 0.9 seconds per request in our October 2026 tests, and cost about three hundredths of a cent per check. A rating is kept for 2 minutes, so a second Conversation risk guardrail on the same conversation reuses it instead of calling the judge again.

Limits​

  • It rates the last 24 messages at most (the first user message is always kept), each cut to 2,000 characters, 14,000 characters in total.
  • A request that asks directly for harmful help in its first message can be rated low. In our tests, 5 of the 7 attacks that still got through were first messages.
  • The threat level belongs to an application name. The header is set by the caller and is not authenticated, and every caller that uses one name shares its level.
  • If the judge cannot answer in time, If the check cannot run decides. The strict template blocks, the plain template lets the request through.
  • It does not read your policy documents and it does not check tool calls. Use Policy document and Tool-call review for those.

Using several guardrails together​

Each turn has two passes: one on the request before the model, one on the response after it. A request guardrail (Social engineering, Conversation risk) and a response guardrail (Policy document, AI Verifier, Tool-call review) never run in the same pass, so they do not interfere.

  • Several request guardrails. They run one after another and only allow, flag or reject. None rewrites the request, so you can combine Social engineering and Conversation risk. Each judge call adds time to the request.
  • Several response guardrails. They run in the order shown on the Guardrails page, and a guardrail that corrects the answer (Policy document, AI Verifier (Legal), masking) hands its corrected text to the next one. Each runs its own check-and-correct loop. The earlier guardrail does not check the answer again after a later one changes it, so one fix can undo another, and each loop adds model calls and waiting time. Use at most one correcting guardrail on the same traffic, put guardrails that only reject or flag after it, and bind two correcting guardrails to different keys or models if you need both.

Choosing a guardrail​

You want toUse
Mask or block PII and secrets by patternRegex, Presidio
Catch manipulation of a staff-style assistant in one request (fake authority, urgency, a made-up approval)Social engineering
Catch multi-turn attacks and requests for credentials, intrusion or dropping the rules, and tighten up after repeated attemptsConversation risk, with Threat levels
Check every answer against approved company policy and have the model correct itPolicy document
Check legal citations in answersAI Verifier (Legal)
Check contract answers against the attached documentsAI Verifier (Documents)
Limit which tools an agent may call and with which valuesTool-call review
Use your own detectorWebhook

Conversation risk does not replace Social engineering or Policy document. Social engineering flags manipulation techniques even when the request is not about credentials or intrusion, for example urgent pressure to approve a payment. Conversation risk rates the goal of the whole conversation and also catches direct requests without any manipulation. Policy document works on the response against your own written rules. Conversation risk works on the request and has no access to your policy documents.

Threat levels​

A threat level is a counter for one application, named by the X-Cortega-Application header on its requests. Every request with the same name shares it. A Tool-call review guardrail or a Conversation risk guardrail with raise_threat set adds to the level when it catches a violation. The level drops back to 0 when its countdown ends. Any guardrail can read it through the state gate on the variable threat.level, so a stricter rule can switch on while the level is raised. For example, one guardrail always runs and raises the level, and a second one that allows fewer tools runs only while threat.level is greater than 0. The stricter guardrail must not set raise_threat itself.

Only applications listed under Threat levels at the bottom of the Guardrails page take part. Each has a countdown, a maximum level, and a choice of whether each request restarts the countdown or only each violation does. The same panel shows the live level and time left, and Reset level sets it back to 0 at once. The header is set by the caller and is not authenticated, and all callers that use one name share its level, so give each agent deployment its own name. Threat levels apply to LLM traffic. MCP requests do not carry an application name.

Document findings​

Verdicts from AI Verifier (Documents) guardrails are in the Document findings panel at the bottom of the Guardrails page. Each checked answer is a row with its team, model, documents, and how many statements failed. Open a row to see a grid of documents by field. Each cell shows the verdict for that field in that document. Click a cell for the statement, the reason, and the passage it was checked against, with its section and page. Documents sent more than once lists documents that were attached to more than one request, with the tokens those requests used.

A document sent by file id or URL, instead of in the request body, is listed as not checked, because its content never passes through the gateway. Add fields for your own contract terms in the guardrail's Custom fields. Merger agreement fields (closing conditions, material adverse effect definition, matching rights, no-shop, fiduciary out, termination fee) are built in.

With Check pasted text on (the default), contract text pasted into the prompt is checked the same way when nothing is attached. Put the contract text in a code block, backticks, or <document> tags so the verifier uses only that text. Without delimiters, the whole message is used when it is at least 400 characters long, and the answer is checked in audit mode even when the guardrail enforces: a pasted message without delimiters can mix instructions with contract text, so it is recorded but never blocked. Shorter messages are not checked and keep streaming.

Some models and providers drop file attachments, so the model never sees the document. Turn on Send attachments to the model as text to replace each attached file in the request with the text Cortega extracted from it. The model then reads the same text the verifier checks. Layout and images in the file are not sent.

Requests up to 32 MB pass through the gateway, attached documents included.

The model-backed types (OpenAI moderation, Azure AI Content Safety, Google Model Armor, Bedrock Guardrails) need a credential or an endpoint/region. See Provider credentials.

Create a guardrail​

Navigate to Guardrails. Use Guided setup for a walkthrough that also proposes a starter set of guardrails, or New Guardrail to add one directly:

  1. Click New Guardrail.
  2. Enter a name.
  3. Choose phase: request or response.
  4. Choose the guardrail type (see the table above).
  5. Choose execution type.
  6. Configure type-specific settings, and a credential for the model-backed types.
  7. Choose scope.
  8. Save as draft or activate it.

Draft guardrails do not enforce. Active guardrails enforce after the gateway receives updated config.

Provider credentials​

The model-backed guardrail types call an external service. The Guided setup wizard has a credentials step that collects what each type you keep needs:

  • OpenAI moderation: choose Reuse OpenAI provider (Cortega uses the stored, encrypted credential from an existing Models → Providers OpenAI entry) or Use environment variable (Cortega reads a named env var, pre-filled with the conventional name). Reuse avoids keeping a second copy of the key.
  • Azure AI Content Safety: the resource endpoint.
  • Bedrock Guardrails: the guardrail ID, region, and version (DRAFT or a published number). Cortega signs with its ambient AWS credentials.
  • Google Model Armor: the project and location.

Cortega never returns a stored credential in an API response. A guardrail whose credential can't be resolved does not enforce.

Execution types​

Guardrails run in this order:

1. Sanitize
2. Parallel checks start
3. Ordered checks run while parallel checks are still running
4. Cortega allows only after ordered checks pass and the parallel expression passes
UI termStored typeUse when
SanitizesanitizeThe guardrail may mask or transform content
Parallel checksasyncThe guardrail only passes or blocks and can run concurrently
Ordered checkssyncThe guardrail must run in a specific order after sanitation

Sanitize and ordered checks run in the order shown in their tables. Parallel checks run concurrently.

Async pass logic​

Parallel checks use AND and OR join behavior.

  • AND checks must all pass unless an OR check passes.
  • An OR check can allow the parallel expression when it passes.
  • If the expression is conclusively blocked, Cortega blocks the request/response.

Use AND for mandatory checks. Use OR for alternative safety checks where any passing check is acceptable.

Scopes​

Choose the narrowest scope that matches your intent.

ScopeApplies to
All ModelsLLM traffic for all models
ModelA specific direct LLM model (provider:model_id in the dropdown) or a managed team router (cortega-team-…)
KeyA specific LLM key identity
Log persistencePresidio only. Redacts PHI in stored gateway telemetry (LLM/MCP query fields and Guardrail Log content attributes) before ClickHouse
MCP ServerEligible MCP traffic for a server
ToolEligible MCP traffic for a tool

Model scope matches the model name Cortega stamps after any team-router rewrite. For a team with Model Authorization configured, choose that team's router name in the Model dropdown so the guardrail covers the team's traffic. Direct models still cover unrouted calls that name that model. Hand-authored virtual models are not listed as Model choices; use All Models or Key for that traffic.

Request/response Model (or All Models) scope controls what the provider sees. Log persistence is a separate binding: without it, Guardrail Log and traffic rows can still store the pre-mask text even when the wire mask worked. Add Log persistence on a Presidio guardrail when observability must not retain cleartext PHI.

MCP guardrail coverage​

MCP guardrails scan only methods that carry useful request/response content:

  • tools/call
  • resources/read
  • prompts/list
  • prompts/get
  • roots/list
  • resources/templates/list

Other MCP protocol calls, such as initialize and notifications, are logged in MCP Queries but are not content-scanned by guardrails.

Presidio custom patterns​

When you create or edit a Presidio guardrail, use Custom detection patterns to teach Presidio identifiers its built-in detectors miss, for example an internal patient number or a local licence format.

Each pattern needs:

FieldPurpose
NameRecognizer name stored on the guardrail
Entity typeEntity the match is reported as (for example LOCATION or PERSON)
RegexDetection pattern
ScoreConfidence for the match (typically 0.85)
Context wordsOptional nearby words that raise confidence

Saving the guardrail sends these as presidio_ad_hoc_recognizers. Clearing every custom pattern removes them from the guardrail.

When LOCATION is enabled, Cortega also applies built-in defaults for US street lines and state/ZIP fragments. Those defaults do not appear in the form; add custom patterns only for formats they do not cover. When MEDICAL_LICENSE is enabled, a US state-prefixed medical licence default is applied the same way.

Runtime logs​

Use Observability → Guardrail Log to see what guardrails did.

Important fields:

FieldMeaning
Runtime scopeLLM Request, LLM Response, MCP Request, or MCP Response
Input textText inspected on request paths
Output textText inspected on response paths
GuardrailGuardrail name
TypeGuardrail provider/type
Score / thresholdProvider score compared to configured threshold
ActionPass, mask, block, or below threshold
LatencyTime spent in that guardrail evaluation

LLM Queries and MCP Queries show applied guardrails in their security area when the traffic row can be correlated with guardrail execution rows.

Troubleshooting​

SymptomLikely causeWhat to check
Guardrail does not fireIt is draft, disabled, wrong phase, or wrong scopeCheck status, phase, and scope
Model-scoped guardrail misses a routed teamScope is bound to a direct model, but the team router rewrote the requestBind Model scope to that team's cortega-team-… router (or use All Models / Key)
Model scope does not apply to a hand-authored virtual modelHand-authored virtual models are not Model-scope choicesUse All Models or Key
MCP request is not scannedMCP method is outside the eligible method listCheck method in MCP Queries
MCP Guardrail Log row exists but MCP Query security is emptyMCP request correlation is not available yetUse Guardrail Log directly
Output text appears without input textResponse guardrail rowRuntime scope should say LLM Response or MCP Response
Input text appears without output textRequest guardrail rowRuntime scope should say LLM Request or MCP Request

The AI Verifier (Legal) and AI Verifier (Documents) names above are existing guardrail labels. The standalone AI Verifier desktop product has been replaced by AI Booster; this product rename does not rename guardrail types or API paths.