drupal / ai_recipe_validations
Adds AI-powered validation to Drupal CMS: Basic page content is checked against an editorial policy and Image media uploads are checked for unsafe imagery, using AI Validations and any chat- and vision-capable AI provider.
Package info
git.drupalcode.org/project/ai_recipe_validations.git
Type:drupal-recipe
pkg:composer/drupal/ai_recipe_validations
Requires
- drupal/ai: ^1.4
- drupal/ai_recipe_validations_image_safety: ^1.0
- drupal/ai_validations: ^1.3
- drupal/core: ^10.4 || ^11
- drupal/field_validation: ^3.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-13 17:18:29 UTC
README
Adds AI-powered validation to the editorial workflow of a Drupal CMS site, so AI enforces content quality before content is saved instead of after it is published:
Basic page text. A chat-capable AI provider checks the page text against an editorial content policy. The save is rejected, with a clear message to the editor, when the text contains:
- personal data about a private individual (personal email address or phone number, home address, date of birth, ID / passport / social security number, bank or card number, health information, …),
- offensive language (profanity, slurs, threats, harassment, or content that demeans people based on a protected characteristic), or
- unfinished placeholder text ("lorem ipsum", "TODO", "TBD", "insert text here", …).
Everything else passes, including critical or controversial content that is expressed respectfully. Published contact details of an organization (a departmental email address, a public office phone number) are allowed.
- Image media uploads. A vision-capable AI provider checks every image uploaded to the Image media type, and blocks nudity, sexually suggestive content, gore, graphic violence and graphic medical imagery. This part is provided by the AI image safety validation recipe, which this recipe applies.
Uses AI Validations on top of Field Validation, and works with any AI provider (OpenAI, Anthropic, Google Gemini, Mistral, Ollama, …).
Requirements
- Drupal 10.4+ or 11
- AI module 1.4 or newer (provides the
verifySetupAiconfig action used for the preflight checks) - AI Validations (standalone) 1.3 or newer. The shipped rules store an empty provider, which this version resolves to the site default for the operation type.
- Field Validation 3.0 or newer
- A Basic page content type (
page). Drupal CMS 1.x and 2.x provide it with a Content field (field_content); a site installed from the Standard profile provides it with a Body field (body). The recipe validates whichever of the two exists. It does not create the content type itself: the Drupal CMS recipes that do (drupal_cms_page) are abandoned and cannot be installed next to Drupal CMS 2.x. - Default models at
/admin/config/ai/settings→ Default Providers for- the
chatoperation type (page text), and - the
chat_with_image_visionoperation type (image uploads).
- the
Note: the AI module still bundles a deprecated copy of ai_validations.
When the standalone package is installed, Drupal's extension discovery
automatically prefers it (shallower path wins); no uninstall/reinstall is
needed on existing sites, just a cache rebuild. Without the standalone
package, the deprecated copy treats the recipe's empty provider as an error
and blocks every save with "No AI provider specified to do validation".
Apply
Set up a provider before applying. On a site where the AI module is not yet configured, the recipe's preflight checks abort the apply (see "Recovering from a failed apply" below).
composer require drupal/ai_provider_openai drupal/ai_recipe_validations
drush en ai ai_provider_openai key -y
(Substitute ai_provider_openai with the provider module of your choice:
ai_provider_anthropic, ai_provider_google_gemini, etc. On a Drupal CMS
site where the AI recipe is applied, a provider is already configured;
check that both operation types below have a default model.)
Then, in the admin UI:
- Add your API key at
/admin/config/system/keys. - Configure the provider at
/admin/config/ai/providers. - Set default models for the
chatandchat_with_image_visionoperation types at/admin/config/ai/settings→ Default Providers.
Finally, apply the recipe from the Drupal root (the web directory in a
Composer project):
php core/scripts/drupal recipe ../recipes/ai_recipe_validations
drush cache:rebuild
Recovering from a failed apply
If the apply aborts with "The operation type 'chat_with_image_vision' does not have a default model" or "The operation type 'chat' does not have a default model", this recipe created no validation rule: its rule set is only created after the preflight succeeds, so a failed apply cannot leave Basic pages impossible to save. Configure the missing default model, then re-run the apply.
Core's drupal recipe command normally also rolls the whole apply back to
a checkpoint. When that rollback does not happen (another runner, or a
rollback that fails quietly), a failed vision preflight can leave the
media_image rule set of the image safety recipe behind, enabled and
without a provider, so that saving Image media fails with "No AI provider
specified to do validation". Configure the vision model and re-apply, or
delete that rule set at Structure → Field validation meanwhile.
What it does
- Applies
ai_recipe_validations_image_safety, which applies core's Image media type recipe, installsai,ai_validationsandfield_validation, and creates themedia_imagefield validation rule set with one AI image constraint rule onfield_media_image. - Checks that the
chatoperation type has a default model, then creates thenode_pagefield validation rule set with two AI text prompt constraint rules that share the same policy prompt: one onfield_content(Drupal CMS) and one onbody(Standard profile). A rule whose field does not exist on the site is skipped, so a page save costs one AI call. The rule set is created by a config action that runs after the check, not shipped as config, so a failed check leaves nothing behind. - Rules run in entity validation mode, so they cover the node and media forms, JSON:API posts and programmatic saves alike.
- Re-applying the recipe is safe: a rule set that already exists is left alone, including one an administrator has disabled.
Field Validation keys rule sets by entity type and bundle (node_page,
media_image): there is one rule set per bundle. If a node_page rule set
already exists on the site (another recipe or a site builder created it),
the recipe's one is skipped. Add the rule by hand in that case:
Structure → Field validation → (Basic page rule set) → Add rule → AI text
prompt constraint, and copy the prompt and message from the
field_validation.rule_set.node_page action in recipe.yml.
Adjusting the policy
The policies live entirely in the rules' prompts, so they can be changed in the UI without code:
- Go to Structure → Field validation → AI validations (Basic page).
- Edit the Enforce the editorial content policy rule for your field.
- Change the numbered items under
=== POLICY ===(for example, drop item 3 to allow drafts with placeholder text, or add a tone-of-voice rule), and update the Message so editors know what to fix.
Keep the === DECISION === and === OUTPUT FORMAT === sections: a
constraint passes only when the model answers with the token XTRUE.
To validate another text field or content type, add a rule to that bundle's rule set with the same plugin and prompt. The prompt is written for text with HTML markup, so it works for both plain and formatted text fields. The image policy is documented in the image safety recipe.
Cost note
Every save of a Basic page triggers one chat API call with the full page text, also when the text is empty (AI Validations 1.3 does not skip empty values; the policy accepts empty content). Every image upload to the Image media type triggers one vision API call. Bulk migrations, imports, or large editorial teams will incur proportional cost. Long pages also need a model with a sufficient context window.
Tests
The functional tests in tests/src/Functional apply the recipe with a
scripted AI provider (tests/modules/ai_recipe_validations_test) whose
XTRUE/XFALSE answer each test sets:
CoreBasicPageTestuses core's Basic page (body). It covers both preflight failures (no models at all, and a vision model without a chat model) and that they leave no rule set behind, the editor-facing message in the node form, image uploads, and re-applying the recipe.DrupalCmsCompatibilityTestuses Drupal CMS (field_content). It runs in the GitLab CI "Drupal CMS" job, which.gitlab-ci.ymlturns on.
The test module also declares the config schema that AI Validations 1.3 is missing for its rule plugins, so the tests keep strict schema checking on.
Issue queue
Bugs and feature requests: https://www.drupal.org/project/issues/ai_recipe_validations