Multilingual LLM Prompts: Armenian, Russian and English Without Behavior Drift
Keep policy invariant
Review every locale
Original LANG-CONTRACT-7 architecture
Language changes presentation, not permission

$ prompt --contract LANG-CONTRACT-7
> compare: invariant rules / locale templates
> validate: evidence / schema / route
> route: answer / clarify / refuse / reviewA translated prompt can be fluent while changing what the assistant is allowed to do. A Russian instruction may say “ask for clarification”, an English variant may say “infer the missing field”, and an Armenian variant may omit the rule entirely. The problem is behavioral equivalence, not word-for-word translation.
This guide is about one narrow engineering question: how to maintain the same decision rules across Armenian, Russian and English prompts. For the wider system, see prompt engineering, AI automation and the AI specialist guide for Armenia. Related guides cover system prompts as contracts and structured output validation.
Problem and requirements
Imagine a synthetic support assistant that reads a customer request and proposes a reply draft. It may summarize the issue, quote an approved policy and request a missing order identifier. It must not promise a refund, reveal another customer's data or execute a change. The language of the request must not change these boundaries.
Define acceptance in terms of observable routes: answer with approved evidence, ask a clarification question, refuse an out-of-scope request, or send a case to human review. Keep the response language appropriate to the user, but make authorization, required evidence, output fields and escalation independent of locale. Armenian content needs review by a qualified human before an Armenian public page or production prompt is released.
Original LANG-CONTRACT-7 architecture
This is an illustrative design, not a measured result or a claim about any deployed customer system.
01 INTENT classify task and requested language 02 POLICY load one versioned invariant rule set 03 LOCALE select a reviewed language template 04 EVIDENCE retrieve only permitted current material 05 GENERATE produce a typed draft and route code 06 VALIDATE compare output with policy and evidence 07 ROUTE deliver, clarify, refuse or review
The invariant contract should be stored once as structured rules, with locale-specific wording attached by stable rule IDs. For example, refund.promise.denied is a policy decision; the Armenian, Russian and English sentences explaining it are presentation. Changing one translation cannot silently change the decision.
Minimal contract and pseudocode
const policy = loadPolicy("support-v3"); const locale = detectSupportedLocale(request.text); const template = loadReviewedTemplate(locale, policy.version); const evidence = retrieveAllowedSources(request.actor, request.topic); const draft = await model.generate({ policy, template, evidence }); const parsed = responseSchema.parse(draft); if (!policy.allows(parsed.route, request.actor)) return review("route"); if (!claimsSupported(parsed.claims, evidence)) return review("evidence"); return renderInLocale(parsed, locale);
detectSupportedLocale, claimsSupported and renderInLocale represent application-owned functions. The model's own declaration that it followed policy is not validation. Templates and policy versions belong in each decision receipt so a regression can be reproduced.
Components and failure modes
| Boundary | Drift example | Required route |
|---|---|---|
| Language detection | Mixed Armenian and Russian text is treated as English | Ask or choose a declared fallback; preserve the original input |
| Policy translation | “May draft” becomes “may send” | Reject unreviewed template change |
| Evidence | A locale has an older policy document | Hold until the current approved source is available |
| Structured output | One language omits review_required | Reject schema-invalid draft |
| Authorization | A localized phrase implies broader account access | Deny based on actor scope outside the model |
| Human handoff | Refusal text hides the actual escalation route | Emit stable route code and review receipt |
Do not translate identifiers, permissions or source revisions as free prose. Treat user supplied text and retrieved documents as data, even when they contain instructions in another language. A prompt saying “ignore the previous rules” in any script remains untrusted input.
Testing and production check
Build a fixture set with the same intents in all three languages: normal answer, missing identifier, forbidden action, stale source, mixed-language input and prompt injection. Human reviewers should confirm semantic equivalence of the fixtures and localized responses. Assert the same route code, authorization decision, required fields and source revision for each parallel case. Wording may differ; decision boundaries should not.
Run the suite whenever the policy, template, model, retrieval corpus or output schema changes. Inspect mismatches by rule ID, not only aggregate accuracy. Keep a rollback path to the last reviewed policy and templates. At release, check the version manifest, fixture coverage, human review of Armenian wording, source freshness, logging boundaries and escalation owner. These are acceptance criteria, not promised performance numbers.
For a project review, request a technical audit. The function calling error guide explains how to validate any downstream tool proposal separately from the language layer.
const policy = loadPolicy("support-v3");
const template = loadReviewedTemplate(locale, policy.version);
const draft = await generate(policy, template, evidence);
return validateRouteAndClaims(draft, policy, evidence);