---
title: "AI assistant"
description: "The AI surfaces in the Admin, what the model knows, and enabling it."
requested_language: fr
language: en
translation_notice: "This page isn't translated yet"
url: https://docs.systhema.app/fr/payload/ai
version: unreleased (main)
docs_index: https://docs.systhema.app/fr/llms.txt
---
> This page isn't translated yet. Showing English.


The Admin assistant can open beside an individual field.

![The field assistant prompt panel](./images/field-panel.light.webp)

The Lexical toolbar also opens the assistant.

![The assistant in the Lexical toolbar](./images/editor-toolbar.light.webp)

`@systhemaui/payload` ships a native AI assistant for the admin panel — no extra plugin to install. It covers seven surfaces:

1. **Field-level generation** — a four-pointed AI star riding inside eligible text and textarea fields on the right, positioned like a select's caret and always visible (the star becomes a hexagon when hovered, and holds it while its panel is open). It opens one combined panel: a highlighted free-text prompt first (Enter generates), then the pre-made actions underneath — **Check grammar** / **Rephrase** as prominent paired buttons, then Expand, Summarize, Simplify, Translate and a **Personalize** link (which opens its own sub-page). While generating, the mark morphs between hexagon and a smaller rotating, pulsing circle (click it to stop), the field locks read-only, and a skeleton shimmer sweeps over it while the text streams in — back to the star when done. The whole UI is built from Payload's own admin primitives, so it matches the panel's look in both themes.
2. **Rich text editing** — a single AI button (the same star mark, always last) in the lexical editor toolbars opens the same combined panel as a floating popover anchored at the button (works in fixed and inline toolbars): prompt first, then the transform actions — **Check grammar**, **Rephrase**, **Expand**, **Summarize**, **Simplify**, **Translate**. Each acts on the current selection, or — with nothing selected — on the **whole editor**: grammar, rephrase and translate map every text 1:1 so blocks, formatting and structure are preserved, while Expand/Summarize/Simplify regenerate the content and replace it. Results splice into a selection so native undo/redo keeps working. There is **no separate "generate layout" control** — the prompt itself drives everything (see Layout generation). While generating, the toolbar hexagon runs the same morph animation, the editor locks read-only under a skeleton shimmer, and the panel shows the result streaming in live; the final content is applied in a single update so undo stays one step.
3. **Layout generation** — generation is driven entirely by the **prompt's intent** — there's no explicit layout button to toggle. The model is aware of the editor's design blocks but **strongly prefers plain rich text** and reaches for blocks only when the brief genuinely asks for a designed page. "Write a 500-word blog post about …" produces flowing editorial text — a scannable heading outline, paragraphs, lists, links and an occasional inline **call-to-action button** (the real Systhema button block, with the project's own token-driven variants), with no unnecessary block wrappers. "A beautifully designed landing page about …" — or a brief that names structures ("add an FAQ accordion", "a 3-column feature grid", "a contact form") — gets the full designer treatment with token-driven defaults. With text **selected**, the selected content becomes the source material and is replaced; without a selection the result is inserted at the cursor (and a pure write reveals progressively in its final formatted shape). Layout blocks are only available in editors that register them; elsewhere the prompt composes plain rich text. See [What the model knows](#what-the-model-knows) for the vocabulary.
4. **Page-level assistant** — on content collections only (those with a top-level rich text editor — pages, components, posts; never uploads/taxonomy), an AI button next to the document controls (styled like the live-preview toggler) generates the **whole page from one brief**: a value for every fillable text field plus a layout for every top-level rich text editor, all telling one coherent story. It also offers **full-page translation**: every text/textarea value plus every rich text editor (including content nested inside blocks) translated at once, schema-driven so slugs, URLs, selects, uploads and relationships are structurally untouchable. Results land in the form as draft edits — review and save yourself. Because a whole-page run rewrites every field and editor at once, a full-document loading veil (the AI mark + a shimmer sweep, like an "Uploading…" state) covers and shields the form until the changes land.
5. **Image generation and refinement** — upload fields get the same AI mark, opening the same combined panel: an auto-growing prompt first; with an image already selected, a pre-checked **"Refine the selected image"** toggle plus quick actions (**Boost resolution**, **Remove background**); and a **Settings** sub-page for aspect ratio and **target resolution** (1K/2K/4K — providers price by resolution; mapped best-effort per provider/model, e.g. Gemini's `imageSize`, OpenAI's quality tiers). Generation **defaults to 1K** — cheap and fast to iterate; Boost resolution is the upscale path once a result is worth keeping. Style direction belongs in the prompt itself. Both flows always create a **new** uploads document — and after a result lands, a **Revert** affordance restores the previous image with a choice to delete the generated upload and revert, keep it and revert, or cancel. Refining pulls the source image bytes from the upload's URL, forwarding the admin session cookie only when the URL is same-origin as `serverURL` (guarding against SSRF/cookie leakage); a missing or unreachable source returns HTTP 400. The status message cycles through friendlier updates while the longer image runs work.
6. **SEO auto-generation** — with AI enabled, the SEO tab's native auto-generate buttons (meta title and meta description) are powered by the AI module: the page's whole content is digested into the prompt, so the description actually describes the page (≤155 characters, content language). Quota-gated and usage-logged like every other generation; without AI they fall back to naive field copies. The `/seo` and `/alt` endpoints return a bare `{ error }` on failure (quota → 429 with `quotaExceeded`, other generation errors → 500), distinct from the `{ success: false, error, quotaExceeded }` envelope used by `/generate` and `/generate-image`.

7. **Image alt text** — an upload collection's `alt` field gets a one-click **Auto-generate alt text** button (below the field description — never the full compose panel). The model **sees the image** (vision) and writes a concise descriptive alt tag (≤125 characters, no "image of…" preamble); for local/non-public files the image is sent as bytes, and on a text-only provider it falls back to context-only. Counts as one text generation and bills its tokens (vision input included) like any other. The uploads **list view** also gets a **Generate missing alt text** bulk action: it finds image uploads with no alt, confirms the count (one generation each), then generates + saves them one by one, stopping cleanly if the plan limit is hit.

Each quick-generate trigger (SEO title/description, single + bulk alt text) has a **caret** opening a small popup to customize the result: a **target language** (overrides the content's language) and free-text **custom instructions**. The choices persist per-surface in localStorage and are sent with the request (instructions are length-clamped server-side).

Every generation is **page-aware**: the request carries the current form data, and the server digests the whole document (every text and rich text value, path-labelled, schema-driven) into prompt context — so a generated label, paragraph or layout fits the page it lands on instead of just the field it was asked from.

## What the model knows

The layout vocabulary is built per request from two inputs: what the requesting editor registers (its tier decides the blocks, its inline blocks decide `button` / `chip`), and the project's own facts, read server-side with the requesting user's access:

| Item                                    | Where it may appear                          | What the model chooses                                                       | What it needs                     |
| --------------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------- |
| `text`                                  | everywhere                                   | headings, paragraphs, lists, links, an occasional `button`, a `chip` tag row | —                                 |
| `section`                               | root                                         | `background` and `theme` from the project's colour system, region content    | —                                 |
| `feature`                               | root                                         | an image beside copy, `float` left/right, `background` / `theme`             | an image in the uploads catalogue |
| `columns`, `card`, `quote`, `accordion` | root, region (columns/card where registered) | the same shapes an editor inserts by hand                                    | —                                 |
| `image`                                 | root, region, fragment                       | a content-width picture                                                      | an image in the uploads catalogue |
| `form`                                  | root, region, fragment                       | an existing form                                                             | a form in the forms catalogue     |
| `component`                             | root                                         | a reusable band authored once in the Components collection                   | a component in the catalogue      |
| `posts`                                 | root                                         | `limit`, `view`, `background` / `theme`                                      | the Posts module                  |

The catalogues are short lists of existing documents: published pages (title and path — the **only** paths an internal link or button may use; they hydrate as real document references, and an invented internal path is dropped while its words stay), forms, components, and the most recent image uploads by alt text. A kind whose catalogue is empty is withheld from the schema entirely, so the model can never invent an id. Every generated block is hydrated from the real block definition, so untouched fields carry the same defaults an editor gets.

Three design rules from Systhema's own layout model are part of every layout prompt, because they are what a fresh author most often gets wrong: adjacent sections with the same theme and background **merge into one band** (so a designed page alternates backgrounds, and gives at most one band an accent theme); a `feature` is one image beside copy and is never faked with columns plus an image; and prose needs **no wrappers or spacing of its own** — the rich-text rules already space it. The page's own title (its hero or title field) is the only `h1`: composed content starts at `h2`, and a generated `h1` is demoted on hydration. Whole-page generation additionally treats the hero group as the masthead, so the editors continue the page after it instead of opening with a second title.

The feature is **disabled by default** and activates through the `ai` plugin option.

## Installation

There is nothing to install. The Vercel AI SDK is **bundled inside `@systhemaui/payload`** — enabling `ai` requires no extra dependencies in your project, and the provider code loads lazily so projects with AI disabled never pay for it.

> [!NOTE]
> The SDK is vendored (bundled at build time) rather than declared as a dependency deliberately: a package-level dependency on `ai` would inject `@opentelemetry/api` into `@systhemaui/payload`'s subtree only, changing `next`'s peer-resolution hash under pnpm and splitting `@payloadcms/ui` into two instances — which breaks every React context in the admin.

## Enabling

On an existing project, the recommended path is the global CLI: `systhema setup ai` walks the same questionnaire as `create` (None / single provider / custom model list), writes `src/payload/ai.ts`, and wires the `.env` variables for you — see [`systhema setup`](https://docs.systhema.app/fr/cli/setup.md). The rest of this section covers what that config looks like and how to author it by hand.

Configuration is forwarded through the `ai` plugin option from your own environment — exactly like the captcha site/secret keys. The package never reads environment variables itself:

```ts title="payload.config.ts"
withSysthema({
  ai: {
    text: {
      provider: 'anthropic',
      apiKey: process.env.ANTHROPIC_API_KEY,
      model: 'claude-opus-4-8',
    },
    image: {
      provider: 'openai', // gpt-image-1 — supports refinement (so do Gemini/Nano Banana models)
      apiKey: process.env.OPENAI_API_KEY,
    },
  },
})
```

`model` is optional — each provider has a built-in default (`openai` → `gpt-5-mini`, `anthropic` → `claude-opus-4-8`, `google` → `gemini-flash-latest`, `groq` → `openai/gpt-oss-120b`).

To make the feature conditional on the environment (the same pattern the Payload template uses for captcha), gate it on the variable:

```ts
ai: process.env.ANTHROPIC_API_KEY
  ? { text: { provider: 'anthropic', apiKey: process.env.ANTHROPIC_API_KEY } }
  : false,
```

### New projects: `systhema create`

The Payload template ships pre-wired. `systhema create` asks about the AI assistant in its setup questionnaire, offering:

- **None** — AI disabled.
- **Single provider** (`--ai <provider>` / `--ai-key` / `--ai-model` / `--ai-base-url`) — one model, driven by `SYSTHEMA_AI_*` env vars.
- **Custom** — an interactive loop to add your own text/image models (and locked upgrade teasers), plus an optional credit budget and plan label — all your own values.

The wizard configures the AI assistant technically and prescribes **no plan or pricing structure** — that's the licensee's own business logic. Author a plan (`packageName` + `models[]` + `quota`) directly in `src/payload/ai.ts` if you want one.

The AI config lives in its own module, `src/payload/ai.ts` (`export const ai`), which `payload.config.ts` imports — the same pattern as the database/email adapters. Single-provider scaffolds keep the env-gated module below; a custom model list emits an explicit `models[]` config whose keys are referenced from per-provider env vars (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, …). The env-gated single-model module activates whenever `SYSTHEMA_AI_PROVIDER` is set:

| Env var                | Meaning                                                              |
| ---------------------- | -------------------------------------------------------------------- |
| `SYSTHEMA_AI_PROVIDER` | `openai` \| `anthropic` \| `google` \| `groq` \| `openai-compatible` |
| `SYSTHEMA_AI_API_KEY`  | The provider API key (optional for self-hosted endpoints)            |
| `SYSTHEMA_AI_MODEL`    | Model id (blank = package default; required for `openai-compatible`) |
| `SYSTHEMA_AI_BASE_URL` | Endpoint base URL — `openai-compatible` only                         |

`systhema doctor` validates this convention (the `ai-config` check) and flags an unknown provider, a missing key, or a self-hosted endpoint without its base URL/model.
