Skip to content

AI tools

github-actions[bot] edited this page Sep 15, 2026 · 9 revisions

The AI tool runs a fixed set of one-tap writing actions against whatever text is in the field you're typing in: rewrite, summarize, translate, and more. Where they run is up to you. Pick a cloud provider with your own API key, a self-hosted Ollama or LM Studio server on your network, or a model that downloads once and answers entirely on the device.

Using it

Open AI from the toolbar or the toolbox. It isn't pinned by default, so the first time you'll probably reach it through the toolbox. Typing its ai keyword on the suggestion strip works too. On a hardware keyboard, use the leader key: double-tap Ctrl, then press A.

The panel opens on a row of action chips. Eleven ship with the keyboard, and the list is yours to change: rename them, rewrite their prompts, turn off the ones you never use, reorder them, or add your own. See Your own actions below.

  • Rewrite, Summarize, Translate, Improve, Formal, Shorter, Friendly, Fix grammar, Explain, Continue: each needs text to work on and is greyed out on an empty field.
  • Custom: the one chip that stays live on an empty field. Tapping it opens an instruction box on the keyboard itself. Whatever you type there is the prompt for that run, so Custom can write brand-new text from nothing instead of transforming what's already in the field.

If nothing is configured yet, the panel shows a short explanation in place of the chip row. You get an Open settings shortcut when no provider is set up, which is where a fresh install starts, or a Download a model shortcut when On-device is selected and nothing has come down yet. A model that's downloading right now takes over that empty state with its progress. Once you're past the empty state, a one-line progress strip sits above the chips, so a download you started in Settings stays visible while you carry on typing.

The AI panel's empty state, before any provider or local model is set up.

What gets sent: selected text wins if you've selected any, and otherwise the whole field goes. Continue is the exception. It always reads back from the cursor, since continuing needs to know what came before rather than what comes after, and How much the AI reads back sets how far: 500 to 32,000 characters, default 4,000. That limit only applies with nothing selected. A selection is always sent as it is. Tap a chip on a truly empty field with no selection and you get "There is nothing to work on. Type some text first." instead of a request.

While a request runs, the panel names the step it's on instead of showing a bare spinner: Preparing, Connecting, Waiting for the model, and Reasoning for a model that thinks before it answers. A request can spend most of its time waiting on a slow connection or a long field, so the step is worth seeing. Waiting for the model is the one you'll meet most. It starts the moment your text is on its way and lasts until the first words come back, which for a cloud provider is nearly the whole run.

Once a result streams in, two buttons commit it. Replace swaps the field's text for the result. Insert drops it in at the cursor instead. Continue is the one exception to Replace: deleting the text you just asked it to continue would defeat the point, so Replace appends there. A Delete markdown checkbox, shown only when the result contains any and checked to start with, removes headings, bullets, quotes, code fences, inline code, links, and bold/italic syntax from what gets committed. Uncheck it to keep the raw markdown. Reasoning output between <think> tags is filtered out of both Replace and Insert either way, so only the answer itself lands in your field.

If a model stops mid-answer because it hit the length ceiling, the panel says so and points at the setting to raise. That's worth knowing about: a truncated answer otherwise looks exactly like a finished one, and you'd only find out by reading your own half-rewritten text.

Seeing what changed

A finished result gets a Result / Changes pair of chips. Changes compares the answer against the text the action ran on and marks what the model added and what it took out, the way git diff does. It's the one thing the plain result can't show you: after a Fix grammar run, the spelling it corrected is simply gone from the screen.

Deleted text is struck through, added text is underlined and slightly bolder. Shape rather than colour alone is deliberate, so the view stays readable on a photo-background theme, in a high-contrast theme, and if you're colour-blind. A changed space or paragraph break is drawn with a visible mark, since an empty highlight tells you nothing. Under the text sits a count of how many parts changed. "Parts" because they're words in prose and single characters in a language that doesn't put spaces between words.

Two cases can't be compared, so they don't offer the chips: Continue, which only ever read the text before your cursor, and any run that wrote from an empty field, where there's no original to compare against. Very long pairs of texts aren't compared either. The panel shows the plain result and says why. The comparison also waits until the answer has finished streaming, since half an answer reads as "everything after this was deleted".

The chips are on by default. Open a result on the changes (off by default) makes the panel start there instead.

Reporting a result

Every finished result also carries a Report button, at the bottom right of the panel next to the Delete markdown checkbox. Tap it if a model produced something offensive, dangerous, or plainly wrong, and it opens a pre-filled email to the developer with a blank line at the top for what went wrong.

Nothing is uploaded when you tap it. The report is a draft in your own mail app, and you can read every line, edit it, or throw it away before sending. What it fills in for you:

  • Your complaint, once you type it in the space at the top.
  • Which action ran, which provider and model answered, and (for Custom) the instruction you gave.
  • The app version, Android version, and device model.
  • The text that went in and the text that came out, each trimmed to the first 4,000 characters.

That last one is worth a second look before you hit send, since it quotes whatever was in the field. The button only appears once a result has finished streaming. Half an answer isn't the thing you'd be reporting anyway.

For bugs in the keyboard itself rather than something a model wrote, use the Feedback rows in About instead.

Choosing where it runs

A row of provider chips sits at the top of the tool's settings: Claude, OpenAI, Gemini, Grok, DeepSeek, Ollama, LM Studio, Other service, and On-device. The pick isn't for life. Switching providers is another tap.

The AI settings screen's provider list.

Cloud providers

Claude (Anthropic), OpenAI, Gemini, Grok, and DeepSeek are bring-your-own-key only. Unlike some of the other network tools, WM Keyboard ships no built-in or proxied key for any of them. Paste your own key into the provider's field:

  • Claude: from console.anthropic.com → API keys
  • OpenAI: from platform.openai.com → API keys
  • Gemini: has a free tier at aistudio.google.com
  • Grok: from console.x.ai → API keys
  • DeepSeek: from platform.deepseek.com → API keys

Each provider also has a Model field. Leave it blank and the app falls back to a built-in default, shown right in the field's hint: claude-sonnet-5 for Claude, gpt-5.6-luna for OpenAI, gemini-3.5-flash for Gemini, grok-4.5 for Grok, deepseek-v4-flash for DeepSeek. Type a model name here to use something else.

DeepSeek's reasoning models stream their thinking on a separate field. The app folds that into the same <think> handling everything else uses, so Show model reasoning and the reasoning progress readout behave there exactly as they do elsewhere.

Any other OpenAI-compatible service

Other service is the escape hatch, and it reaches far more than the named chips do. Anything that speaks OpenAI's chat-completions shape works: OpenRouter, Groq, Together, Mistral, Cerebras, self-hosted vLLM. Three fields:

  • Service address: the address up to and including the version segment, for example https://openrouter.ai/api/v1. The app adds /chat/completions itself. That split exists because services genuinely disagree about the prefix (/v1, /openai/v1, /api/v1), so guessing it would break half of them.
  • Model: required here, unlike the named providers. There's no sensible default to guess for a service the app knows nothing about.
  • API key: optional. A gateway on your own network often wants none.
Note

An http:// address works, for a service on your own network, and that traffic is plain HTTP. Keep the server on a network you trust.

Self-hosted servers

Ollama and LM Studio point at a server on your own network instead of a cloud API. No key is needed, only an address like http://192.168.0.10:11434 (Ollama) or http://192.168.0.10:1234 (LM Studio). Set OLLAMA_HOST=0.0.0.0 so Ollama listens beyond localhost. Turn on LM Studio's local-server option. Both address fields are blank by default. Ollama defaults its model field to qwen3 when you leave it blank. LM Studio has no default model to fall back to, so it uses whatever the server currently has loaded.

Note

Traffic to a self-hosted server is plain HTTP, and the app allows cleartext traffic app-wide to support it. Keep the server on a network you trust.

Local models

The On-device provider runs a model entirely on the phone, no network involved. It's the only provider option that needs a download first, and it's the one provider chip that doesn't appear at all in a Lite build.

The on-device model catalog, with tier badges and a size/RAM subtitle per model.

The catalog is eight models, ordered best-first rather than smallest-first:

Model Params Size Tier Gated
Gemma 4 E2B 2B 2.59 GB Recommended
Gemma 4 E4B 4B 3.66 GB Recommended
Gemma 3 1B 1B 584 MB Untested Yes
Qwen 2.5 1.5B 1.5B 1.6 GB Standard
Qwen 3 0.6B 0.6B 347 MB Experimental
Qwen 2.5 0.5B 0.5B 546 MB Experimental
Gemma 3 270M 270M 304 MB Untested Yes
SmolLM2 135M 135M 143 MB Experimental

Two of the eight are gated and need a Hugging Face account. Paste a token into the Access token field under Hugging Face account, above the catalog. Then accept the model's license on its Hugging Face page, once per model.

Every model carries an advisory minimum-RAM figure behind the scenes. When your phone's total RAM falls under it, the app appends "May be too large for this device" to that model's subtitle. It never blocks the download and never shows you the raw number. That warning is the only per-device signal the catalog gives you up front. There's no published speed benchmark, because how fast a model answers depends on the phone as much as on the model. What you get instead is a progress readout with elapsed seconds, once a request is actually running.

Tapping Download starts a resumable download. Cancel it, lose signal, or background the app, and the next attempt picks the transfer up where it left off rather than restarting. Only one download runs at a time. On a metered connection, a model of 500 MB or more asks for confirmation first.

Don't need the catalog? Import your own takes any .litertlm or .task file, the two container formats the on-device engine loads. That covers one you converted yourself or downloaded elsewhere in a browser. There's no GGUF support. A file with any other extension is rejected on import.

A Compute row picks CPU or GPU for inference, and CPU is the default. GPU is best-effort. If it fails to initialize, or crashes partway through an answer, the engine falls back to CPU on its own and remembers not to retry GPU for that model file again this session.

A Context size row sets how much text the model is loaded with, prompt and answer together, in tokens. It defaults to the model's own value. This is the only length lever on-device. Unlike a cloud API there's no per-response ceiling to set, so the window is what bounds an answer. A larger window costs memory, and changing it reloads the model.

Your own actions

Tools / AI writing tools / Actions on the panel

The eleven chips on the panel are a list you own. The screen lists them in panel order, with a checkbox to turn one off, an edit button, and a New action row at the bottom. Drag the handles in Order of the actions to rearrange them. The panel follows that order exactly.

Any of these can also be a button on the selection actions bar: pick them under Advanced, Selection actions, AI buttons, and one tap runs the action on whatever is selected, with the result landing here ready to apply. Formal, Shorter and Friendly were added with that in mind.

An action that ships with the keyboard is never deleted, only changed. Editing one saves your version under the same identity, so Reset in its editor drops your version and the original comes straight back. Turning one off leaves it on this screen, greyed on the panel and one checkbox away from returning. Only actions you wrote yourself get a Delete.

The editor holds a name, the prompt, and a handful of behaviour switches:

  • Type the prompt at every run: the keyboard asks you for the prompt instead of using a saved one. This is what makes Custom work the way it does.
  • Start from the saved prompt: only shown under the switch above, and it brings the prompt field back. The instruction box then opens with that text already in it, so you adjust a template rather than retype it. Useful for something you run often with a small variation each time: "reply to this politely, and mention that…". The saved text wins every time the box opens, not only the first, since a template you see once isn't a template. Leave it off and the box reopens on whatever you typed last.
  • Works with an empty field: with nothing in the field, the action writes new text instead of changing text.
  • Read the text before the cursor: the action reads only what's in front of the cursor rather than the whole field. A selection always wins over this.
  • Add the result to the end: Replace appends rather than overwriting. Pair it with the switch above and you have Continue. Keeping them separate is what makes "append but read the whole field" something you can build.
  • Answer with the text only: on for everything except Explain, whose answer is prose about your text rather than a replacement for it. Hidden once Write the whole prompt is on, since a raw prompt has nothing left for the switch to act on.

About the prompt field

You write the task, not the whole prompt. The app wraps what you write in a fixed frame. That frame says who the model is, and it says your field's text is material to work on and never instructions to obey. Unless you turn it off, it also says to answer with the result and nothing else.

That's on purpose. The middle part is what stops a model from treating text in your field as commands aimed at it, and that text is often an email you're replying to or a message someone sent you. A text box shouldn't be able to delete that rule by accident. The prompt that the app sends below the editor shows you the assembled result, so it's visible without being editable.

Write {target} anywhere in a prompt and it becomes the translate target language, which is how the shipped Translate action works. Because the token is stored rather than the language, changing the target language updates every prompt that mentions it.

Write the whole prompt is the deliberate way out for anyone who wants to write the safety wording themselves. The app then sends your text exactly as you typed it.

Note

Prompts you'd already customised carry over automatically, and the app checks its own work. A prompt it recognises is unpicked back into a task. Anything it doesn't recognise is kept verbatim under this switch rather than guessed at.

Chatting instead of transforming

Tools / AI writing tools / Chat with the model

The panel's actions all do the same shape of thing: take the text in a field, hand it back changed. When you want an actual conversation instead, Chat opens one in the settings app, against any model you've already set up here. It's a separate screen with its own saved conversations, its own model picker, and a launcher shortcut of its own. See AI chat.

History

Tools / AI writing tools / History

Off by default. Turn it on and the keyboard keeps a record of each run: what you sent, what came back, which action and model, how long it took, how much of that was reasoning, and whether you used the answer. The screen searches across the input, the answer and the model name. It filters by action, and expands a row so you can copy either side or delete it.

Failed runs are recorded too, with the error the panel showed, since "it keeps failing" is the most likely reason to open the screen at all.

Four things have to be true before anything is written down, and any one of them being false is the end of it:

  1. You turned the history on.
  2. The device has been unlocked at least once since it restarted.
  3. The field isn't a password box.
  4. Incognito isn't in force, from either the setting or a field that asked for it, like a private browser tab.

API keys are never part of a record. It carries the model's name and nothing about the connection.

Number of records to keep defaults to 100 and tops out at 500. The oldest falls off once it's full, and each side of a record is capped at 4,000 characters. Delete all history clears the lot, and so does turning the setting off. An off switch that quietly leaves the log on disk isn't an off switch.

Options

Tools / AI writing tools

Like every tool, AI has an Enabled toggle (on by default) and, if colorful tool icons are on, a per-tool icon color override. Below that:

  • Keyword: the word that offers this tool on the suggestion strip when you type it alone. Defaults to ai.
  • Provider: which of the nine providers above is active. Defaults to Claude, though with no key entered yet a fresh install lands on the empty-state screen until you add one.
  • Max response length: a token ceiling, roughly ¾ of a word each, picked from steps rather than a slider: 1k through 128k, plus Provider maximum. Default 8,192. A model the app takes for a reasoning model gets 4× this ceiling on its own, capped at 131,072, because reasoning tokens come out of the same budget before the answer starts. That guess is a substring match on the model ID, for strings like "thinking", "qwen3", "grok-4" or "deepseek-v4". The On-device provider swaps this row for Context size.
  • Translate action's target language: free text, defaults to English.
  • Show model reasoning: off by default. Turning it on streams a reasoning model's raw <think> passages instead of the step-by-step progress readout.
  • Model picker on the panel: on by default. Adds a horizontally-scrolling row to the panel itself for switching between every configured provider and downloaded local model in one tap. It's hidden automatically whenever there are fewer than two to choose from.
  • Show a changes view: on by default, see Seeing what changed. Open a result on the changes below it is off.
  • Chat with the model: opens the conversation screen, see AI chat.
  • Actions on the panel: the whole action list, see Your own actions.
  • History: off by default, see History.

On the History screen

Tools / AI writing tools / History

One more row lives on the History screen, under a Downloading models heading. Model downloads on a metered connection are set in Data saver now, on the Downloads row, which starts at Ask each time: the size-keyed prompt (500 MB for a language model, 150 MB for a Whisper one) still fires on top, so a smaller model asks too rather than coming down without a word. Set the row to Turn off and no model downloads on mobile data at all.

  • How much the AI reads back: 4,000 characters by default, anywhere from 500 to 32,000. This is how far back from the cursor a carry-on action such as Continue reads. More characters give the model more of your writing to follow, and cost more tokens and more time on every run. It has no effect when you've selected something, because a selection is always sent as it is.

What the On-device provider adds

Picking On-device draws the whole model manager onto the same screen, under the provider row. Local models covers the catalog, Compute and Context size. Three more things sit on that screen and nowhere else:

  • Hugging Face account, holding an Access token field. Blank by default, stored the same way an API key is, and only the gated models need it. Under the field, Get a token opens huggingface.co/settings/tokens in your browser.
  • Import your own, an Import model file button that opens the system file picker. It takes .litertlm and .task files only, and anything else is rejected with a message under the button.
  • Free up, labelled with a size (like "Free up 584 MB"). It only appears when there are orphaned files, meaning model directories left behind by an app update that dropped a model from the catalog. No row can reach those files any more, so the button is the only way to delete them. They're reported rather than deleted for you, on the grounds that it's a multi-gigabyte download you already paid for.

Above that sits a line reporting how much storage your models take in total, partial downloads included. That figure is usually bigger than the one beside Your models, which only sums the finished ones you can see.

About "Provider maximum"

This one is worth understanding, because the old default was the reason a long Improve used to come back with only the first part rewritten. Provider maximum leaves the ceiling out of the request entirely and lets the service apply its own, which for a modern model is far more than any number you'd pick by hand. It's the right choice for long text.

Anthropic is the one exception: its API requires the field, so the app asks for a large number there instead. If the model you picked allows less, Anthropic rejects the request and names its real limit in the error. The app retries once at that number. Nothing has streamed at that point, so all you see is the answer.

Ollama had never been sent a limit at all before this. It gets one now, and Provider maximum there means what it always did.

What leaves your phone

The panel itself sends nothing until you actually tap an action chip: opening the tool, or typing in the field behind it, sends nothing anywhere on its own.

  • On-device: the text you run an action on never leaves the phone. Response length is bounded by the local model's own context window instead of a server-side limit.
  • Any other provider (cloud or self-hosted): the text you run an action on is sent to that provider, only at the moment you tap the action. API keys and server addresses are stored on the device, not in any WM Keyboard service. See Privacy at a glance for how this fits the keyboard's broader per-tool approach to anything that leaves the device.
  • Report: builds a draft in your mail app and hands it over. The app has no reporting server and sends nothing itself, so a report only exists if you send the mail. API keys are never part of it.
  • History: goes nowhere. It's a file in the app's private storage, off unless you turn it on, never written from a password field or in incognito, and deleted when you turn it off. It's deliberately left out of the backup file too, so it can't ride along in something you export and mail to yourself. There's no section for it to travel in, unlike the learned dictionary, which is a section of its own that you tick or leave alone. See Your data.
  • The changes view: is computed on your phone. Comparing two pieces of text is arithmetic, not a request, so nothing is sent to build it.

Details & edge cases

  • Not every row here can be reset. The Enabled switch and four of the AI switches (Show model reasoning, Model picker on the panel, Show a changes view, Open a result on the changes) grow a restore button once you move them off the default listed above, and so does the Translate target-language field. See Putting one setting back. Keyword does it differently: change the word and a Reset to defaults row appears under the field, naming the word it would put back. The provider row, Max response length and Context size are drawn as chip rows rather than settings rows, so none of them has a button. The shipped value of an API key or address field is an empty box, which you clear yourself.
  • AI isn't pinned to the toolbar or the onboarding wizard's starter set by default. You add it yourself from the toolbox once you want it, the same as most non-essential tools.
  • Not available on the lock screen. AI needs credentials the direct-boot-safe mirror of your data deliberately doesn't carry, so it's one of the tools that only works after you've unlocked the device once since restart.
  • The Writing keyboard mode pins AI first on its toolbar for apps it recognizes as writing-heavy (see Keyboard modes). The pin shows in both editions, same as the tool itself. Only the On-device provider is Full-only.
  • A reasoning model's guess is a substring match against the model ID, on strings like "thinking", "-r1", "qwen3", "gpt-5", "grok-4", "deepseek-v4". It can be wrong in either direction. A false positive only costs a larger token ceiling. A false negative risks a response cut off mid-thought.
  • Custom has no stored default prompt. Every other action's prompt can be edited and still has a built-in fallback. Custom's instruction only ever exists for the run you type it for.
  • On-device answers never claim to have been cut off. The local engine reports no stop reason, so there's nothing to read, and the app says nothing rather than guessing. Every other provider does report it.
  • The changes view can't spot moved text. A paragraph the model relocated reads as a deletion where it was and an insertion where it went. Detecting moves properly needs a second pass that git only does on request. The actions that move text, Summarize and Rewrite, reword it at the same time, so that pass would fire rarely and mislead when it did.
  • Comparisons drop to whole characters for scripts without spaces (Chinese, Japanese, Thai, and others). Word-sized pieces would make an entire sentence a single highlight there. Mixed text uses characters throughout, which is noisier but never wrong.
  • Local models are advisory about RAM, never a hard gate. A phone under a model's stated minimum can still download and run it. You get a warning in the catalog first.
  • No shared or built-in key for any cloud provider. Claude, OpenAI, Gemini, Grok, and DeepSeek each need your own API key. There's no free built-in quota here, the way some of the other network tools offer one.
  • A model download dies with the app's process. It resumes rather than restarting, but it isn't a foreground service, so backgrounding the app for long enough can stop it. That hasn't changed. The panel just shows you it's happening now.

Clone this wiki locally