Global Configuration
Provider
Kirby Copilot supports multiple AI providers. You must configure at least one provider with valid credentials to generate content in the Panel or from PHP.
google as the provider.provider sits at the root of johannschopplich.copilot. Every other option in this section is set per provider, under providers.<name> – providers.google, for example.
provider String
The provider Copilot sends its requests to. The Panel falls back to google, while the PHP Client throws without one, so set it whenever PHP code generates content.
Default: google (Panel only)
Options: openai, google, anthropic, mistral
return [
'johannschopplich.copilot' => [
'provider' => 'openai',
'providers' => [
'openai' => [
'apiKey' => 'your-openai-api-key',
'model' => 'gpt-5.6-terra'
]
]
]
];
return [
'johannschopplich.copilot' => [
'provider' => 'google',
'providers' => [
'google' => [
'apiKey' => 'your-google-api-key',
'model' => 'gemini-3.8-flash'
]
]
]
];
return [
'johannschopplich.copilot' => [
'provider' => 'anthropic',
'providers' => [
'anthropic' => [
'apiKey' => 'your-anthropic-api-key',
'model' => 'claude-sonnet-5'
]
]
]
];
return [
'johannschopplich.copilot' => [
'provider' => 'mistral',
'providers' => [
'mistral' => [
'apiKey' => 'your-mistral-api-key',
'model' => 'mistral-medium-latest',
// Optional: custom base URL
'baseUrl' => 'https://api.mistral.ai/v1'
]
]
]
];
apiKey String | Closure
The provider's API key. All AI provider requests are routed through a server-side proxy, so API keys are never exposed in browser network requests and stay hidden from Panel users. No additional configuration required – the proxy is enabled automatically.
Default: none
For advanced use cases, pass a closure that resolves the key at runtime. It receives the Kirby instance as its first argument, allowing user-specific or context-dependent API keys:
return [
'johannschopplich.copilot' => [
'providers' => [
'openai' => [
'apiKey' => function (\Kirby\Cms\App $kirby) {
// Example: Return different keys based on user role
$user = $kirby->user();
if ($user?->role()->name() === 'admin') {
return 'your-admin-api-key';
}
return 'your-user-api-key';
}
]
]
]
];
This is useful for scenarios like:
- Different API keys or rate limits per user role.
- Fetching keys from external services or databases.
- Multi-tenant setups with client-specific credentials.
model String
The model for content generation – text, blocks, and layouts.
Default: per provider, see Default Models
return [
'johannschopplich.copilot' => [
'provider' => 'google',
'providers' => [
'google' => [
'apiKey' => 'your-google-api-key',
'model' => 'gemini-3.8-flash'
]
]
]
];
completionModel String
The model for inline suggestions in writer fields. Pick a fast, lightweight one.
Default: per provider, see Default Models
return [
'johannschopplich.copilot' => [
'provider' => 'google',
'providers' => [
'google' => [
'apiKey' => 'your-google-api-key',
// Suggestions from the generation model instead of the lighter default
'completionModel' => 'gemini-3.8-flash'
]
]
]
];
completionModel yourself whenever your model carries a prefix from another provider – google-ai-studio/gemini-3.8-flash under provider: 'openai', for example. Copilot won't guess one across gateways, so inline suggestions fail until you set it. See Routing Multiple Providers Through One Gateway.Default Models
If you do not specify a model or completionModel, Kirby Copilot uses sensible defaults for each provider:
| Provider | Generation Model (model) | Completion Model (completionModel) |
|---|---|---|
| OpenAI | gpt-5.6-terra | gpt-5.6-luna |
gemini-3.8-flash | gemini-3.5-flash-lite | |
| Anthropic | claude-sonnet-5 | claude-sonnet-5 |
| Mistral | mistral-medium-latest | mistral-small-latest |
baseUrl String
Custom base URL for the AI provider API. Useful when using proxy services, custom API endpoints, or self-hosted AI services like llama.cpp.
Default: Provider-specific default URL
return [
'johannschopplich.copilot' => [
'provider' => 'openai',
'providers' => [
'openai' => [
'apiKey' => 'your-openai-api-key',
'model' => 'llama-3.2-3b-instruct',
'baseUrl' => 'https://llama.example.com/v1'
]
]
]
];
api String
Selects the OpenAI API variant the Panel calls. Defaults to the Responses API (/v1/responses). Set to chat when your endpoint only exposes /v1/chat/completions – see AI Gateways for which endpoints need it. PHP runs through OpenAIProvider always use Chat Completions and ignore this option.
Default: responses
Options: chat, responses
return [
'johannschopplich.copilot' => [
'provider' => 'openai',
'providers' => [
'openai' => [
'apiKey' => 'your-openai-api-key',
'baseUrl' => 'https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/compat',
'model' => 'openai/gpt-5.6-terra',
'api' => 'chat'
]
]
]
];
timeout Integer since v3.12.0
Seconds a single request to the provider may take before it counts as failed. Applies to PHP runs through Client; Panel requests go through the proxy, which bounds them on its own. Anything but a positive integer falls back to the default.
Default: 120
Raise it for long structured-output runs against a slow endpoint, lower it for batch scripts that should fail fast:
return [
'johannschopplich.copilot' => [
'provider' => 'google',
'providers' => [
'google' => [
'apiKey' => 'your-google-api-key',
'model' => 'gemini-3.8-flash',
'timeout' => 30
]
]
]
];
options Array
A map the Panel passes to the AI SDK as this provider's options with every request, keyed by the option names the SDK defines for that provider. The PHP Client ignores it; request parameters for PHP runs sit beside it as provider-specific options.
Default: none
Shorter output from every generation, without touching a prompt:
return [
'johannschopplich.copilot' => [
'provider' => 'openai',
'providers' => [
'openai' => [
'apiKey' => 'your-openai-api-key',
'model' => 'gpt-5.6-terra',
'options' => [
'textVerbosity' => 'low'
]
]
]
]
];
AI Gateways
An OpenAI-compatible gateway runs under provider: 'openai', with the gateway's URL as baseUrl.
Compatibility
| Endpoint | Responses API | api flag |
|---|---|---|
Direct OpenAI (api.openai.com/v1) | Yes | — |
Vercel AI Gateway (ai-gateway.vercel.sh/v1) | Yes | — |
Cloudflare AI Gateway – …/openai (OpenAI only) | Yes | — |
Cloudflare AI Gateway – …/compat (many providers) | No | chat |
OpenRouter (openrouter.ai/api/v1) | Yes | — |
| Self-hosted (llama.cpp, vLLM, LiteLLM default) | Typically no | chat |
Not listed? Check your gateway's docs for /v1/responses support – if absent, set api: 'chat'.
reasoningEffort continues to work with both API variants.Routing Multiple Providers Through One Gateway
Cloudflare AI Gateway's Unified API (…/compat) routes many providers through the OpenAI SDK shape using {provider}/{model} model IDs. This lets you access Google, Anthropic, OpenAI, and more through a single endpoint – handy for unified observability, caching, and rate limiting across providers.
Because /compat is Chat Completions only, api: 'chat' is required.
return [
'johannschopplich.copilot' => [
'provider' => 'openai',
'providers' => [
'openai' => [
'apiKey' => 'your-google-ai-studio-api-key',
'baseUrl' => 'https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/compat',
'model' => 'google-ai-studio/gemini-3.8-flash',
// Required when the gateway prefix doesn't match the provider
'completionModel' => 'google-ai-studio/gemini-3.5-flash-lite',
'api' => 'chat'
]
]
]
];
Limitations
- Structured output (blocks, layouts, field schemas) through OpenAI-compatible gateways depends on the gateway's
json_schematranslation. Test before relying on blocks or layout generation through this path. reasoningEffortmay not apply across cross-provider gateway prefixes. The OpenAI-compatible path cannot reliably map reasoning settings onto other vendors' models. For full reasoning control on Anthropic or Google models, useprovider: "anthropic"orprovider: "google"directly.
Panel Generation
These options sit at the root of johannschopplich.copilot and apply across every Panel view and section. A view button or section can override systemPrompt and logLevel in its blueprint – see View Button Properties.
systemPrompt String
Global system prompt that defines how the AI model should structure and approach content generation.
The default prompt formats the response per field type and preserves formatting in a selection – override it only when your project needs different rules.
excludedBlocks Array
Specify block types to exclude from structured data generation in blocks and layout fields. This is useful for custom block types for which AI generation is not desired.
Default: [] (no blocks excluded)
return [
'johannschopplich.copilot' => [
'excludedBlocks' => ['custom-form', 'widget', 'advertisement'],
]
];
reasoningEffort String
Controls the depth of reasoning applied during content generation. Configure the effort once – it is translated to each provider's native reasoning controls automatically. Models without reasoning support simply ignore the setting.
Default: low
Options: provider-default, none, minimal, low, medium, high, xhigh
return [
'johannschopplich.copilot' => [
'reasoningEffort' => 'medium'
]
];
Use provider-default to let the provider pick its own reasoning depth – equivalent to not sending a reasoning setting at all. Not every model supports every level; providers clamp unsupported values to the nearest supported one.
completion Array | Boolean
Controls inline suggestions in writer fields: false stops ghost text from appearing on its own, and debounce sets the pause in milliseconds before a suggestion.
Default: ['debounce' => 1000]
return [
'johannschopplich.copilot' => [
'completion' => [
'debounce' => 1500 // Wait 1.5 seconds after typing stops
]
]
];
promptTemplates Array
Define prompt templates that appear for all Panel users. Config-defined templates are read-only and displayed alongside user-created templates.
Default: [] (uses built-in defaults)
return [
'johannschopplich.copilot' => [
'promptTemplates' => [
[
'label' => 'Apply House Style',
'prompt' => 'Format the text according to our editorial style: artist names in bold, album titles in italics, use curly quotation marks.'
],
[
'label' => 'Add Spotify Links',
'prompt' => 'Find all album titles in the text and wrap them in Markdown links to their Spotify pages.'
]
]
]
];
skills Array
Define reusable prompt instructions – tone, style, or house rules – that editors invoke via @skill:// references in the prompt editor.
Default: []
return [
'johannschopplich.copilot' => [
'skills' => [
[
'id' => 'brand-voice',
'label' => 'Brand Voice',
'instructions' => 'Write in a warm, conversational tone. Avoid corporate jargon. Prefer short sentences.'
]
]
]
];
logLevel String
Logging level for debugging AI generation. Inspect the browser console to see logs. At info and debug, each generation logs its system and user prompt.
Default: warn
Options: error, warn, info, debug
return [
'johannschopplich.copilot' => [
'logLevel' => 'info'
]
];
Agents
agents Boolean
Lets users connect agents like Claude or ChatGPT to the site through its MCP URL, and adds the Agents view to the Panel menu.
Default: false
return [
'johannschopplich.copilot' => [
'agents' => true
]
];