Skip to main content
Skip to main content

Release notes

Drupal AI 1.5.0 is out

A ChatProcessor layer between chatbots and the backends that answer them, guardrails that work on a stream, a reranker for Search API and a smaller core. 51 issues, 52 contributors, 31 organizations.

Drupal AI 1.5.0 came out on 25 September 2026. It is a minor release, so it is backwards compatible: update, run the database updates, and everything keeps working.

51 issues went into it, from 52 contributors and 31 organizations. And the module keeps growing: it has passed 20,000 installs, and it is growing faster than ever.

More and more of the work now goes into making the AI module a lean core engine, instead of a module filled with feature submodules, and that continues until 2.0.0 is out. The framework, developer and logging submodules will still be there. So in these release posts we will talk as much about what moves out as about what is added. In 1.5, five submodules became their own projects, and AI Search and AI CKEditor are on their way out: if you use either of them, read the warning further down before you update to 1.6.0.

Watch the walkthrough (or scroll down to read)

0:00

Chat

ChatProcessor: a layer between chatbot and backend

Until now the DeepChat chatbot talked straight to an AI Assistant. In 1.5 it talks to a ChatProcessor plugin instead: a middle layer between the chat window and whatever does the thinking. The plugin type was already in 1.4, but 1.5 is the first release where the chatbot uses it.

1.5 ships one processor, the AI Assistant API processor, so your existing assistants keep working. A post-update moves your chatbot blocks over, and old block configuration still works.

The interesting part is what can plug in next. The chat window does not need to know if the answer comes from an assistant, an agent, a workflow engine or your own service. Scroll through three chatbots with three different backends:

  • Full screen admin assistant: "Make the title of the About page shorter" goes through ChatProcessor to Drupal CMS assistant (AI Assistants API), which answers "Done. The title is now "About us", and I updated the menu link as well.".
  • Support center bot: "I want a refund for order #1042" goes through ChatProcessor to Refund workflow (FlowDrop), which answers "I checked the order, the return policy and the payment. Your refund of €49 is approved and will be back on your card in 3 to 5 days.".
  • Bot with widgets: "Will it rain at the Vienna office tomorrow?" goes through ChatProcessor to Weather agent (AI Agents), which answers "Yes, light rain after lunch. Bring an umbrella." with a card: Vienna, tomorrow, 14°C, Light rain, Rain from 13:00 to 17:00, Hourly forecast, Next 7 days.

ChatMemory: chat history, stored one way

Chatbots used to forget. 1.5 adds a ChatMemory plugin type that normalizes how chat history is stored. The history lives on the server and survives a page reload, and every thread belongs to its user or session, so nobody sees someone else's conversation.

Two plugins ship:

  • private_tempstore keeps one ongoing thread per user or session.
  • private_tempstore_pool keeps several threads, so a new conversation can start fresh.

You pick the memory on the AI Assistant form. A post-update converts the old "allow history" setting for you, and the new /api/deepchat/reset endpoint resets a thread. Because it is a plugin type, keeping history in your own table or an external service means writing one plugin, and the developer docs have a guide for it.

ChatMemory follows the work in Symfony AI, which the AI module will update to in AI 2.0.

Batch embeddings

Embedding content for search used to mean one request per text. 1.5 adds EmbeddingsCollectionInput and EmbeddingsCollectionOutput, so you can send many texts in one call. Providers that cannot batch get a fallback, so the same code works everywhere.

For short texts, most of the time in an embeddings call is the round trip, not the model. So 30 texts sent as three batches of ten finish long before 30 single requests:

30 texts embedded one request at a time take 9.00 s; the same texts in 3 batch requests of 10 take 1.35 s.

An illustration with a 300 ms round trip per single request and 450 ms per batch of ten. Real numbers depend on the provider, the model and your network.

Guardrails

Sensitive Content Stream Filter

Guardrails could already check the input and the finished answer. Now they can also work on a response while it streams. The first streaming guardrail is the Sensitive Content Stream Filter: tell the model to wrap anything sensitive in [SENSITIVE] and [/SENSITIVE], and the guardrail drops everything between the markers before it reaches the browser. The markers and the replacement text are configurable.

In this case a model writes a patient summary. The sensitive part never leaves the server, and the rest streams out as normal:

The model streams: "Here is the summary you asked for. [SENSITIVE]Patient: Marcus Johansson. Diagnosis: chronic funny bone. Current medicine: Bitter Drops, three times a day.[/SENSITIVE] The next check-up is on Thursday at 10:00 at the main clinic. Please bring your insurance card and arrive ten minutes early.". The browser receives: "Here is the summary you asked for. [Content removed.] The next check-up is on Thursday at 10:00 at the main clinic. Please bring your insurance card and arrive ten minutes early."

Made-up data. No funny bones were harmed.

Moderation guardrail

The new Moderation guardrail sends user input to a provider's moderation endpoint, instead of asking an LLM to judge it with a classification prompt. That is cheaper and faster. You choose the provider and model per guardrail, and you can have it scan all user messages, not only the last one. If no provider is usable, it fails closed: it blocks, instead of letting everything through.

Restrict to Topic: semantic mode

Restrict to Topic has a new Semantic matching mode. It hardens the prompt and fuzzy-matches the topic the model reports back to your configured list, with a similarity threshold (0.75 by default). So "bananas", "Banane" and "banana fruit" all count as "banana". Topics that do not match are recorded in the metadata, so you can see what people actually ask about.

AI Automators

Interactive refinement in Field Widget Actions

Automator buttons in Field Widget Actions used to be one shot: click, get a value, take it or leave it. Now a text automator can open a refine dialog. You look at the result, ask for a change ("shorter", "more formal"), and it tries again. The field's original automator prompt goes along with every refinement, so the result stays on track. When you are happy, you accept it.

  1. Suggest a name: The Golden Fork Bistro
  2. Make it sound Swedish: Den Gyllene Gaffeln
  3. Shorter, one word: Gaffeln
  4. Accepted: Gaffeln

Rich text image descriptions

Text automators can now see the images inside a formatted text field. When a body field has embedded images, the automator describes them with your default vision model and puts the descriptions into {{ context }}, next to the text. So a summary or a meta description can mention what is in the pictures, not only what is in the words. If you use content moderation, you can require a human review when the image analysis could not be completed.

AI Reranker for Search API

Keyword search and vector search are good at finding candidates. They are less good at putting the best one first. The new AI Reranker processor for Search API takes the results your index found and re-orders them by how well they answer the query, with any rerank-capable provider. It works on any backend: the database, Solr or a vector database. You set the provider and model, how many results to rerank (Top N) and which fields to send.

In this case the answer is in the index, but the search only puts it at #8. Keep scrolling to turn the reranker on:

⌕ Why does my chatbot forget what I said? After the AI reranker

  1. Keeping chat history between messages ChatMemory stores the thread, so the bot remembers what you said. was #8
  2. Your first chatbot in five minutes Install, configure a provider, place the block. was #6
  3. Chatbot block settings Place the chatbot block and choose who can see it. was #1
  4. Debugging chatbot errors Read the logs when the chatbot does not answer. was #5
  5. Chatbot API endpoints The DeepChat API and what each endpoint does. was #7
  6. Chatbot permissions Which roles can use the chatbot and its API. was #4
  7. What is a chatbot? An introduction to chatbots on a Drupal site. was #2
  8. Styling the chatbot Change the colours, the avatar and the greeting. was #3
  9. Translating the chatbot Use the chatbot on a multilingual site.
  10. Chatbot accessibility Keyboard use and screen reader support.
An illustration with made-up documentation pages.

Extractive question answering

A new operation type: extractive question answering. Instead of writing a new answer, the model points at the part of your text that answers the question, and returns that span, its position in the text and a score. That makes it easy to check, because the answer is always a quote. You can try it on its own page in the API Explorer.

AI CKEditor uses the Prompt Library

The AI CKEditor actions Modify, Reformat, Spellfix, Summarize, Tone and Translate now get their prompts from the Prompt Library, as ai_prompt config entities. So you can change how "Summarize" behaves on your site without touching code. A post-update converts your existing editor configuration, and Tone and Translate got the language and tone improvements from the 2.0.x branch.

A smaller AI module

Submodules that moved out

AI Content Suggestions, AI Logging, AI Translate, AI Validations and Field Widget Actions are now their own projects. You do not need to do anything: the AI module's composer.json pulls them in, so composer update drupal/ai gets them, and drush updb does the rest.

Why move them? When the AI module first came out, it was a different era. We needed to make sure everyone understood what is possible with AI in Drupal, so a lot went into one module. That is not needed anymore. Some of these modules are not necessarily the number one solution for what they do, and as their own projects they can move at their own speed, while the AI module stays focused.

Deprecated: AI Search and AI CKEditor

For developers

Observability

AI calls now follow the OpenTelemetry gen_ai.* semantic conventions: the operation, the provider, the model and the token usage are standard span attributes. Streaming spans are closed when the stream ends, so their timing is right, and sending the prompt and response payloads is now opt-in.

Because it is plain OpenTelemetry, the traces are not tied to one tool. Point the exporter somewhere else and the same spans show up there:

Drupal AI sends spans with gen_ai.operation.name: chat, gen_ai.provider.name: openai, gen_ai.request.model: gpt-4.1-mini, gen_ai.usage.input_tokens: 412, gen_ai.usage.output_tokens: 128 through OpenTelemetry (OTLP) to Datadog (LLM calls next to the rest of your APM traces.), Grafana (Traces in Tempo, with latency and token panels on your dashboards.), Honeycomb (Slice slow calls by model, operation and token count.).

Token usage in the API Explorer

The chat generator in the API Explorer now shows the token usage of every call: input, output, reasoning and cached tokens. It also shows the provider's rate limits: how many requests you have left and when they reset.

HTML to Markdown

The ai.html_to_markdown_converter service turns HTML into Markdown, which is handy when you send content to a model. It has a settings page at /admin/config/ai/html-to-markdown, and when the Markdownify module is installed it uses Markdownify's converter and settings. The other direction, Markdown to HTML, goes through CommonMarkConverterFactory.

Thank you

A huge thank you to everyone who worked on this release: 52 contributors from 31 organizations. The full list is on the 1.5.0 release page.

Contributors: breidert, robloach, joshua1234511, b_sharpe, ahmad khader, marcus_johansson, a.dmitriiev, manandearth, sgavilan, jorgik, ajv009, harivansh, abhisekmazumdar, adhariwal, jucs7, jessehs, kristen pol, akhil babu, ahmad-khalil-imagex, paulsheldrake, scott_euser, abarrio, nikro, scott falconer, fago, lbesenyei, merilainen, gxleano, farse, csakiistvan, violaniko, annmarysruthy, prabha1997, ezeedub, fizcs3, cobadger, mandclu, kotekirkitadze, ajabhinavjha30, aivazashvilit, cadence96, d34dman, ultimike, ishani patel, shivamsen_12579, rduterte, tbalog, loopduplicate, m4olivei, murz, tazo_vekua and ro-no-lo.

Organizations: 1xINTERNET, Kalamuna, Axelerant, ImageX, Vardot, FreelyGive, OpenSense Labs, Dropsolid, DrupalFit, esinergia., Itty Bitty Byte, Salsa Digital, QED42, Soapbox, Acquia, drunomics, Brainsum, Mearra (formerly known as Wunder), Factorial.io, Integral Vision Ltd, Phase2, Conference Catalysts, Pare & Co, Omedia, Pantheon, SeeD EM, Digitwings, DrupalEasy, Cambridge University Press & Assessment, Lullabot and EPAM.

Chapters

Updated 11 min read

Other ways to consume this

Listen to this article

13:21
Articles read out (podcast feed)