Settings
Provider configuration
Providers, models and configurations are database-backed and managed
in the LLM backend module — not via TypoScript. nr-llm does not read
plugin. TypoScript settings; any such constants/setup have no
effect (this is true for both classic TypoScript templates and site sets).
To make the generic chat / complete entry points work without
pinning a provider per call, set up a default configuration:
- Open the LLM backend module.
- Create a Provider (e.g. OpenAI) and store its API key as an nr-vault identifier — see API key protection.
- Create a Model for that provider.
- Create a Configuration bundling the model, then mark it active and default.
The Setup Wizard in the module walks through these steps.
Without an active default configuration, generic calls throw "No provider specified and no default provider configured".
Background worker
A queued run reads its provider key in a process without a logged-in backend
user (ADR-234). The setting is in the extension configuration of
nr_, section worker.
-
- Type
- integer
- Default
- 0
The uid of the backend user whose grants on a vault secret count when a queued run reads a provider key on the command line.
nrllm:, a Messenger consumer and the reaper all do. The user needs read access to the secret, by ownership or through a group, and nothing else.agent: work 0applies the nr_vault CLI rule, which refuses unlessallowis on. Every run then fails on its first model call. A user who is disabled, deleted or unknown fails the run. A web request keeps its logged-in user.Cli Access Everything else a run does in nr_vault happens as this user too. A delegated MCP tool stores a credential for the run's actor, which this user cannot do without the rights of that actor, so a queued run with such a tool fails.
Filling empty fields on save
An installation can have empty fields written by AI after a save
(ADR-237). The settings are in the extension configuration of
nr_, section fieldFill. Nothing happens until field is set.
-
- Type
- string
- Default
- (empty)
Comma-separated
table.entries, for examplefield pages.. Only plain text fields count: a rich text field, a code editor, a slug or a relation stays out, and so do accounts anddescription,pages. abstract sys_tables.
-
- Type
- integer
- Default
- 300
The longest text written, in characters. The TCA
maxof the field applies when it is lower. The model is asked for a tenth less, and a longer answer is not written.
When an editor changes and saves a record with such a field empty, a background run is queued and the save ends. A save that changes nothing queues nothing. A worker has to run (Background tasks from the command line and the scheduler). It writes the text as the user who saved, and only while the field is still empty. A failed run writes nothing, and Agent Runs shows what became of each answer.
Nothing is queued for a field the save itself emptied, for a page with hardly any
text, for _cli_ or an import, for a copy or a translation made by TYPO3, or
for a user who may not use the default configuration. The record's text is sent
to the provider of the default configuration.
Vision editor actions
The editor actions Set alternative text and
Update file metadata send the image of the file to the model
(ADR-235). The settings are in the extension configuration of
nr_, section vision.
-
- Type
- integer
- Default
- 1024
The longest edge in pixels of the image sent to the model. TYPO3's file processing scales it and keeps the result in the processed folder. An image that cannot be brought to this size is not sent, and the action is not available for it. Core remembers a failed attempt: an image tried while the image processor was broken stays unavailable until the processed files are cleared in Admin Tools > Maintenance.
-
- Type
- string
- Default
- (empty)
Comma-separated combined folder identifiers, for example
1:/. No image from these folders or their subfolders reaches a model.private/, 1:/ hr/
-
- Type
- boolean
- Default
- 1
For
alternative,titleanddescription. Whether the editor action fills this field. An action with no field left is not offered. This does not switch off the tool: the assistant may still use it, which the Tools module governs.
-
- Type
- integer
- Default
- 0
The longest value in characters. It applies to every writer of the field, the assistant included, and it cannot lift a narrower TCA
max. The model is asked for a tenth less, and a longer value is refused on the approval card.0sets no limit of its own.
-
- Type
- string
- Default
- (empty)
What the model is told to write for this field. Empty uses the shipped text.
The action is not offered when the default configuration's model declares
capabilities without vision. A model with an empty capability field passes. A
configuration that selects its model by criteria has to require vision in its
criteria.
The prompt asks for the language of the backend user.
Environment variables
# TYPO3 encryption key (used for API key encryption)
TYPO3_CONF_VARS__SYS__encryptionKey=your-key
Security
API key protection
- Encrypted storage — API keys are stored as vault identifiers (UUIDs) via the nr-vault extension, which uses envelope encryption. nr-llm never stores raw API keys.
- Database security — the database only contains vault UUIDs, not secrets. Ensure backups are encrypted regardless.
- Backend access — restrict the LLM module to authorized administrators.
- Key rotation — re-encrypt via nr-vault's key rotation mechanism.
Input sanitization
Sanitize user input before sending to providers:
// Strip markup and control characters from free-text input before it is
// sent to a provider. (GeneralUtility::removeXSS() was removed from the
// TYPO3 core and must not be used.)
$sanitizedInput = trim(strip_tags($userInput));
$response = $adapter->chatCompletion([
['role' => 'user', 'content' => $sanitizedInput],
]);
Output handling
Treat LLM responses as untrusted content:
$response = $adapter->chatCompletion([
['role' => 'user', 'content' => $prompt],
]);
$safeOutput = htmlspecialchars(
$response->content, ENT_QUOTES, 'UTF-8'
);
Logging
use Psr\Log\LogLevel;
use TYPO3\CMS\Core\Log\Writer\FileWriter;
$GLOBALS['TYPO3_CONF_VARS']['LOG']
['Netresearch']['NrLlm'] = [
'writerConfiguration' => [
LogLevel::DEBUG => [
FileWriter::class => [
'logFileInfix' => 'nr_llm',
],
],
],
];
Log files: var/
Caching
The extension uses TYPO3's caching framework with
cache identifier nrllm_.
No cache backend is specified — TYPO3 automatically uses the instance's default cache backend. If your instance has Redis, Valkey, or Memcached configured, nr-llm uses it transparently with zero configuration.
- Cache identifier:
nrllm_responses - Cache group:
nrllm - Default TTL: 3600 seconds (1 hour)
- Embeddings TTL: 86400 seconds (24 hours)
To override the backend for this cache specifically:
use TYPO3\CMS\Core\Cache\Backend\RedisBackend;
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']
['cacheConfigurations']['nrllm_responses']
['backend'] = RedisBackend::class;
Clear cache:
vendor/bin/typo3 cache:flush --group=nrllm