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".
Quality benchmark for routing
Measured quality uses one explicitly selected completion benchmark (Completion benchmark revision). These extension settings are read on every score lookup, including in long-running workers.
-
- Type
- string
- Default
- empty
Exact golden prompt set identifier to use for measured quality. Choose a benchmark relevant to the application and evaluate its candidates.
-
- Type
- string
- Default
- empty
Copy the
Benchmarkvalue printed bynrllm:for that set. Only results for this exact revision with a verified serving generator and deterministic grading can supply a score. Empty or invalid settings, or no matching measurement, mean unknown quality. A measured zero remains zero. Other routing signals remain available.eval: run
After upgrading from an unversioned benchmark, re-evaluate and configure both values. Changing prompts or grading rules produces a new fingerprint; switch the selected revision deliberately after reviewing the measurements.
Model discovery
-
- Type
- boolean
- Default
- 0
When on, Confirm capabilities on a model of an OpenAI provider also reads OpenRouter's public model list (
https://) and stores whether it callsopenrouter. ai/ api/ v1/ models openai/<model id>a reasoning model, marked as a third-party source (ADR-275). It is one anonymousGETper confirmation: no key, no request content. It never runs while a request is being sent. The effort scale is not taken from it, and a failed lookup stores nothing.
Model rounds of an agent run
An agent run sends the model a request, runs the tools it asks for and sends
the result back; each such exchange is a round. The settings are in the extension
configuration of nr_, section agent (ADR-101). The
Governance tab of the LLM overview module shows the values
that apply.
-
- Type
- integer
- Default
- 5
The rounds a run gets when its caller asks for no number, for example an ordinary backend chat turn or an editor feature's tool call. A value above
agent.is that maximum. An empty, non-numeric, zero or negative value falls back to 5.max Iterations
-
- Type
- integer
- Default
- 20
The most rounds any run may take, whatever its caller asks for. Every round is a model request, so this bounds the cost of one run. A run that resumes after an approval or an answered question is limited by the value in force when it resumes, and its count starts again for that part. An empty, non-numeric, zero or negative value falls back to 20.
A run that reaches its number ends with one more request without tools, which writes the answer. The values are read for every run, so a change applies to the next one. A worker that started before the change applies it from its next start.
The Agent Runs module and the playground continue a run after an approval or an answer inside the web request. Each round can take several seconds, so with a high maximum such a request can outlast a timeout of the web server or a proxy in front of it. If PHP keeps running, completion may later appear in Agent Runs. A PHP-worker timeout, process termination or host failure can instead leave an executing segment unfinished. Inspect the run status and worker lease; use the reaper procedure rather than assuming completion. See Command-line operation.
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.
EXT:autotranslate
Used only when autotranslate's own setting translator names nr-llm's
translator (Page trees and records in the background). The setting is in the
extension configuration of nr_, section autotranslate.
-
- Type
- string
- Default
- (empty)
The identifier of the nr-llm translator autotranslate's texts go to, for example
deeplorllm. Empty uses the language model. An identifier no translator is registered under fails each translation, and autotranslate logs it.
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.
A save in a draft workspace is filled in that workspace: the run reads the record and its page as the workspace shows them and stores the text as a draft there, which waits for the workspace to be published. Live stays unchanged, wherever the editor works when the worker runs. A table without workspace versions is not filled from a draft (ADR-265).
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,
Update file metadata and Set categories from the image
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,title,descriptionandcategories. 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
For
alternative,titleanddescription;categorieshas no length. The longest value in characters. It applies to every writer of the field, the assistant included, and it cannot lift a narrower TCAmax. 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. For
categoriesthe list of categories it may choose from is always added.
-
- Type
- integer
- Default
- 0
The
sys_uid below which categories may be set on a file from its image (ADR-268). The model chooses only from the live, visible, default-language categories below it, and only from those inside the editor's category mounts where the editor has any; it never creates one, and the root itself is not offered.category 0switches thecategoriesfield off: Set categories from the image is not offered, and the toolset_refuses every call. At most ten levels and 200 categories are read, because the list goes into every prompt. There is no TSconfig form of this setting: a file has no page to read it from.file_ categories
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
Validate the input your application accepts. Removing markup is optional
text normalization, not authorization or a prompt-injection defence.
trim does not remove embedded control characters.
if (preg_match('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', $userInput)) {
throw new \InvalidArgumentException('Unsupported control character.');
}
$text = trim(strip_tags($userInput));
$response = $llmManager->completeForConfiguration($text, $configuration);
Resolve $configuration with the guarded service in
Step 5: Select a database configuration. Apply length and format limits appropriate to
the application, keep input data separate from trusted instructions, and
check permissions before any record read or write.
Output handling
Treat LLM responses as untrusted content:
$response = $llmManager->completeForConfiguration($prompt, $configuration);
$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
The backend's default (3600 seconds) does not enable every cache
path. Each producer decides whether to store content and with which TTL:
| Path | Activation and TTL | Stored content and removal |
|---|---|---|
| Embeddings | 86400 seconds by default; Embedding disables it. | Vectors; expire by TTL or the nrllm cache-group flush. |
| Plain configuration chat/completion | answer_ defaults to 0 (off), up to 86400 seconds. | Verbatim complete answer; requires effective full privacy. Flush
nrllm_ or the cache group. without opts out. |
| Specialized translation cache | Translation opts in; off by default. | Translator result; glossary/configuration/skill changes flush its tag. |
| Agent/tool/schema/streaming answer paths | Excluded from configuration answer caching. | No cached answer through that path. |
A cache hit avoids the corresponding provider request and its budget charge. Idempotency is a separate retry contract; it is not this response-cache TTL. The privacy purge removes governed database rows; it does not replace cache expiry or an explicit cache flush. See Configuration parameters and policies.
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