Plugins › AI
Docs/Plugins/AI

AI

What you'll learn

Connect Claude, GPT, Gemini or a server of your own for the admin's AI features, and keep their cost and privacy in hand.

Before this page: Integrations.

@easy-cms/plugin-ai adds AI providers to the AI category of Settings → Integrations: Anthropic (Claude), OpenAI (GPT), Google Gemini, and any OpenAI-compatible server (Ollama, OpenRouter). Easy CMS calls them over HTTP, from the server: keys never reach the browser.

npm
npm install @easy-cms/plugin-ai
pnpm
pnpm add @easy-cms/plugin-ai
yarn
yarn add @easy-cms/plugin-ai
bun
bun add @easy-cms/plugin-ai
import { aiPlugin } from '@easy-cms/plugin-ai'
 
export default defineConfig({
  // …
  plugins: [aiPlugin()],
})

The plugin adds an ai-usage collection (usage, kept out of the admin): create a migration for it (easy-cms migrate:create ai, see Migrations).

Connecting a provider

  1. Settings → Integrations → AI, then Connect an account on a provider.
  2. Read and accept what the provider is sent (once per provider; who accepted goes to the audit log).
  3. Paste the API key, press Find Model to choose a model (empty: a sensible default), and Save. Connecting asks the model for one word: the card shows the model and its tokens.
ProviderKey in the environment (wins)Default model
AnthropicANTHROPIC_API_KEYclaude-sonnet-5-5
OpenAIOPENAI_API_KEYgpt-5-mini
Google GeminiGEMINI_API_KEYgemini-flash-latest
OpenAI-compatible— (a Base URL up to /v1, a key if it needs one)—

With a key in the environment, the provider has an "Environment" connection on its default model. Each connection's card shows this month's requests and tokens.

Features

Features that use AI are listed in the AI features box at the top of the AI category. Each can be turned off, or use another connection than the main connection (the first one connected, until an admin chooses). Plugins add theirs to aiFeatures in the config:

aiFeatures: [{ id: 'summary', label: 'Summaries', description: 'Writes the excerpt of a post', default: true }]

Limits

Each user makes at most 100 requests a day (in timeZone); the 101st is refused. Admins change the number in the AI features box, and a role can have its own in Settings → Roles (0: the role can't use AI). In code:

aiPlugin({ limits: { perUserPerDay: 50, roles: { editor: 20 } } })

The box shows this month's requests and tokens by user and by feature. Prompts and answers are not stored: only who asked, which feature and connection, the tokens and when, for 90 days.

In your code

cms.ai is null without the plugin. On the server:

const result = await cms.ai?.generate(
  {
    feature: 'summary', // one of aiFeatures, turned on
    system: 'You write short, plain excerpts.',
    prompt: `Summarize in one sentence:\n\n${post.text}`,
    images: [{ media: post.cover }], // or { data: base64, mediaType }
    json: { type: 'object', properties: { excerpt: { type: 'string' } } }, // the answer's shape
    maxTokens: 300, // default 1024
  },
  { user, about: { collection: 'posts', id: post.id } }, // counts toward the user's limit
)
result.json // { excerpt: '…' }; result.text, result.usage, result.connection

A provider that is busy (429, 5xx) is asked once more; a request takes at most 60 seconds. A key it refuses (401, 403) marks the connection, which shows on the dashboard and sends integration.failed, e.g. to a notification. There is no REST endpoint for prompts: each feature has its own, with its prompt on the server.

Options

OptionDefault
providersall four'anthropic', 'openai', 'gemini', 'openai-compatible'
limits.perUserPerDay100Requests a user makes a day.
limits.roles—Per role, e.g. { editor: 20 }.

Next steps