Input Controls
Language Validator
language-validator detects the language of a request and blocks it, or records a warning, when the language is not allowed. For example, an assistant for English and French users can block Japanese input.
Text that the detector is unsure about passes, so this is not a strict language boundary. It checks requests only, never model responses.
Configuration
Save this as policy-config.yaml. It allows English and French and blocks the other supported languages when the detection confidence is at least 0.5.
pack:
name: language-validator
version: "1.0.0"
enabled: true
policies:
chain:
- language-validator
policy:
language-validator:
allowed_languages:
- en
- fr
min_confidence: 0.5
action: block
apply_to: inputVerify with text from your application
Test a full English sentence, a Japanese one, and a short word:
testing:
suites:
- name: language-validator
cases:
- name: allows-english
input: {messages: [{role: user, content: "Please summarize the quarterly report and list the three main risks for the team."}]}
expected: {verdict: allow, reason_code: ok}
- name: blocks-japanese
input: {messages: [{role: user, content: "四半期報告書を要約して、チームの主なリスクを三つ挙げてください。"}]}
expected: {verdict: block, reason_code: language-validator.blocked.ja}
- name: allows-short-text
input: {messages: [{role: user, content: "OK"}]}
expected: {verdict: allow, reason_code: ok}All three pass. The nested results show the detected code and confidence: OK is detected as English with a confidence of only 0.2, so it passes whatever the list says. Then test real paragraphs from your users, and start with action: warn to measure false matches before you block.
Fields
| Field | Type | Default | Description |
|---|---|---|---|
allowed_languages | string[] | [] | Allowed codes. When not empty, every other detected code is a violation. |
denied_languages | string[] | [] | Rejected codes. Used only when allowed_languages is empty. |
min_confidence | number | 0.5 | Minimum confidence, from 0.0 to 1.0. A less confident detection passes. |
action | block or warn | block | warn allows the request and records a warning reason code. |
apply_to | input, output, or both | input | Set input. both checks input only, and output skips the check. |
Lint rejects allowed_languages together with denied_languages, a code outside the supported set, and a min_confidence outside 0.0 to 1.0.
Supported language codes
| Code | Language |
|---|---|
en | English |
es | Spanish |
fr | French |
de | German |
zh | Chinese |
ja | Japanese |
ko | Korean |
ar | Arabic |
pt | Portuguese |
ru | Russian |
How it works
- With
apply_to: output, the control allows withlanguage-validator.skipped_output_onlyand stops. - The gateway joins the
userandsystemmessages. - Local Unicode block and trigram rules detect the language and a confidence.
- A confidence below
min_confidencepasses. - With
allowed_languages, a code outside the list is a violation. Otherwise, a code indenied_languagesis a violation. - No violation:
allowwithlanguage-validator.ok. - A violation blocks with
action: block, or is allowed with a warning code withaction: warn. - The details record the detected language, the confidence, both lists, and
min_confidence.
Phase and verdicts
| Item | Value |
|---|---|
| Input phase | The joined user and system messages |
| Output phase | Not enforced |
| Verdicts | allow, block |
| No violation | language-validator.ok |
| Block | language-validator.blocked.<code>, such as language-validator.blocked.ja |
| Warning | language-validator.warned.<code> |
apply_to: output | language-validator.skipped_output_only |
Examples
English-only input gate
pack:
name: english-only
version: "1.0.0"
enabled: true
policies:
chain:
- language-validator
policy:
language-validator:
allowed_languages:
- en
min_confidence: 0.6
action: block
apply_to: inputRecord a warning for denied languages
pack:
name: routing-observability
version: "1.0.0"
enabled: true
policies:
chain:
- language-validator
policy:
language-validator:
denied_languages:
- ja
- ar
min_confidence: 0.4
action: warn
apply_to: inputLimits and failure behavior
- Response text is never checked.
outputskips the check andbothchecks input only. - The schema gives
bothas the default ofapply_to, but the runtime usesinput. Setapply_to: input. - For a streaming request,
outputandbothstop the stream at startup withstreaming.policy_cannot_enforce. - Only the ten codes are recognized. Other languages get the closest code or a low confidence.
- Mixed or short text often scores below
min_confidenceand passes. assistantandtoolmessages are ignored.
Next steps
- Prompt Injection Detection: the other main input check.
- PII Detector: redact personal data in the same phase.