thunder_ai
A Drupal recipe for Thunder that installs and configures AI providers.
What this recipe installs
Module Description drupal/ai Core AI integration layer drupal/ai_provider_azure Azure OpenAI provider integration drupal/ai_provider_openai OpenAI provider integration drupal/gemini_provider Google Gemini provider integration drupal/ai_provider_anthropic Anthropic provider integrationRequirements
- Thunder distribution
- Composer
Installation
Apply the recipe using Drupal's recipe system:
drush recipe ../recipes/thunder_aiThe recipe asks the following questions:
- Default AI provider —
azure,openai,gemini, oranthropic - Key storage method —
config(value stored in Drupal config) orenv(value read from an environment variable) - Azure API key value or env var name — press Enter to skip if not using Azure
- Azure endpoint URL — the full deployment endpoint from Azure AI Studio
- OpenAI: API key value or env var name — press Enter to skip if not using OpenAI
- Google Gemini: API key value or env var name — press Enter to skip if not using Gemini
- Anthropic: API key value or env var name — press Enter to skip if not using Anthropic
- Default model ID — model to use for chat; defaults to
thunder_ai_azure(the Azure model registered by this recipe). Override when using a different provider (e.g.gpt-4o,claude-opus-4-5,gemini-2.0-flash)
For questions 3, 5, 6, and 7: enter the raw API key when using config storage, or the environment variable name (e.g. OPENAI_API_KEY) when using env storage.
Note: Drupal recipe inputs cannot be made conditional, so all questions are always shown. Only fill in credentials and a model for the provider you selected; press Enter to skip the rest.
To skip the prompts entirely, pass all values as flags:
drush recipe ../recipes/thunder_ai \ --input="thunder_ai.default_provider=azure" \ --input="thunder_ai.default_model=thunder_ai_azure" \ --input="thunder_ai.key_provider=env" \ --input="thunder_ai.azure_api_key=AZURE_API_KEY" \ --input="thunder_ai.azure_endpoint=https://my-resource.openai.azure.com/openai/deployments/my-deployment/chat" \ --input="thunder_ai.openai_api_key=" \ --input="thunder_ai.gemini_api_key=" \ --input="thunder_ai.anthropic_api_key="All four provider modules are installed regardless of the selection. The chosen provider is set as the site default for chat operations.
What the recipe configures
For each provider whose credentials are supplied, the recipe:
- Creates a Key module entity (
thunder_ai_{provider}_key) using the chosen key provider (configorenv) - Wires the Key entity to the provider's settings
- For Azure: registers a chat model in
ai.settings.modelswith the given endpoint - Sets the chosen provider and its model as the site default for chat in
ai.settings
Post-installation
Non-Azure model — ai.settings.default_providers.chat.model_id is set from the default_model input. If you selected OpenAI, Gemini, or Anthropic, visit Administration > Configuration > AI to update the default model.
Production key storage — credentials are stored in Drupal config via the Key module's config provider. For production environments, switch to an environment-variable-based key provider at Administration > Configuration > System > Keys.
FAQ
Why are all four AI providers installed when I only selected one?
Drupal recipes have no conditional logic — it is not possible to install a module only when a specific input value is chosen. All four provider modules are always installed regardless of the selection. The chosen provider is set as the site default; the others are installed but unconfigured. See Removing unneeded providers below for how to clean them up.
Why does the default model default to thunder_ai_azure when I selected a different provider?
Azure OpenAI requires an explicit model registration in ai.settings.models that includes the deployment endpoint URL. The recipe registers one such model (thunder_ai_azure) using the endpoint supplied as input. Other providers discover available models dynamically and need no registration entry. Because the recipe always creates the Azure model entry, the default_model input defaults to thunder_ai_azure. When using a different provider, override the default_model input during recipe application or update the default model afterwards at Administration > Configuration > AI.
Why is setupAiProvider not used to configure the providers?
The drupal/ai module provides a setupAiProvider config action that creates a Key entity and wires it to a provider in one step. It was not used for two reasons:
- The Azure provider does not implement
getSetupData()— it returns an empty array — which causes the action to fail for Azure. setupAiProviderhardcodes the Key module'sconfigstorage backend. There is no way to have it create a Key entity that reads from an environment variable instead.
The recipe uses createIfNotExists and simpleConfigUpdate directly, which avoids both limitations and works uniformly for all four providers.
Removing unneeded providers
The recipe installs all four AI provider modules. Once you have decided which provider to use, you can unpack the recipe and remove the providers you do not need.
Unpacking inlines the recipe's Composer dependencies into your project's composer.json and removes the recipe package itself, giving you full control over each dependency.
1. Install the unpack plugin
composer require drupal/core-recipe-unpack2. Unpack the recipe
composer drupal:recipe-unpack drupal/thunder_aiThis moves all packages from drupal/thunder_ai's require into your root composer.json and removes the recipe package.
3. Uninstall the unused Drupal modules
Drupal modules must be uninstalled before their packages are removed from Composer. Removing the package first leaves Drupal with a reference to a missing module, which causes pm:uninstall to fail.
drush pm:uninstall ai_provider_azure # not using Azure OpenAI drush pm:uninstall ai_provider_openai # not using OpenAI drush pm:uninstall gemini_provider # not using Google Gemini drush pm:uninstall ai_provider_anthropic # not using Anthropic4. Delete the unused Key config entries
drush config:delete key.key.thunder_ai_azure_key drush config:delete key.key.thunder_ai_openai_key drush config:delete key.key.thunder_ai_gemini_key drush config:delete key.key.thunder_ai_anthropic_key5. Export the updated configuration
drush config:export6. Remove the unused provider packages
Now that the modules are uninstalled, remove their Composer packages:
composer remove drupal/ai_provider_azure composer remove drupal/ai_provider_openai composer remove drupal/gemini_provider composer remove drupal/ai_provider_anthropic