---
title: "Option classes"
manual: "LLM Foundation"
version: "0.44"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-llm:api-options@0.44"
source: "Api/OptionClasses.rst"
rendered: "2026-11-12T17:35:48+00:00"
---

# Option classes {#api-options}

Option objects are immutable: each `with…()` method returns a copy. Keep
that return value. Message arrays are still supported on relevant paths;
option arrays are not a substitute for a typed options object.

**Keep the returned options**

```php
$options = (new ChatOptions())->withMaxTokens(2000);
$options = $options->withCallerSource('my_extension', 'summarize');
```

## Shared call controls {#shared-call-controls}

| Method | Default and effect |
| --- | --- |
| `withIdempotencyKey($key)` | Unset by default; identifies a retry, separate from response-cache TTL. |
| `withCorrelationId($id)` | Unset; a non-empty caller ID links the call to telemetry/outcomes. |
| `withCallerSource($extension, $operation = '')` | Unset; attribution metadata, not authorization or a provider field. |
| `withSite($site)` | Unset; supplies site context to supported routing/translation paths. |
| `withBeUserUid($uid)` | Unset; attributes/checks a budget on budget-aware options. It does not authenticate a worker or grant group/record access. |
| `withPlannedCost($cost)` | Unset; non-negative estimated cost for the preflight check, not an atomic reservation or provider invoice. |

Provider-specific option support still depends on the adapter and operation.
The service forwards call metadata separately; `toArray()` is not a complete
serialization of all policy and actor context.

## ChatOptions {#chatoptions}

-   **class ChatOptions**

    -   *Fully qualified name:* `\Netresearch\NrLlm\Service\Option\ChatOptions`

    Typed options for chat operations.

    -   **static factual()**

        Create options optimized for factual responses (temperature: 0.1).

        -   *returns:* ChatOptions

    -   **static creative()**

        Create options for creative content (temperature: 1.2).

        -   *returns:* ChatOptions

    -   **static balanced()**

        Create balanced options (temperature: 0.7).

        -   *returns:* ChatOptions

    -   **static json()**

        Create options for JSON output format.

        -   *returns:* ChatOptions

    -   **static code()**

        Create options optimized for code generation.

        -   *returns:* ChatOptions

    -   **withTemperature(float $temperature) : self**

        Set temperature (0.0 - 2.0).

    -   **withMaxTokens(int $maxTokens) : self**

        Request a maximum output-token budget. For recognized OpenAI reasoning
        models, the adapter raises values below 16,000 to 16,000 unless the
        applied reasoning effort is `None`. Thinking consumes that budget
        too. This option is therefore not a universal hard output or cost cap.

    -   **withTopP(float $topP) : self**

        Set nucleus sampling parameter.

    -   **withFrequencyPenalty(float $penalty) : self**

        Set frequency penalty (-2.0 to 2.0).

    -   **withPresencePenalty(float $penalty) : self**

        Set presence penalty (-2.0 to 2.0).

    -   **withSystemPrompt(string $prompt) : self**

        Set system prompt.

    -   **withResponseFormat(string $format) : self**

        Request an output format: `text`, `json` or `markdown`.
        Adapter support differs. The current Claude adapter does not implement
        bare `response_format=json`. Its object-schema path uses a forced
        tool instead. For validated structured output, use
        `completeStructured()`; local schema validation remains authoritative
        ([ADR-128](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-128@0.44)).

    -   **withResponseSchema(array $schema) : self**

        Attach a strict-subset JSON schema ([ADR-126](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-126@0.44)) the
        provider should enforce natively where it can. Set automatically
        by `completeStructured()`; the local strict validation remains
        authoritative either way.

    -   **withStopSequences(array $sequences) : self**

        Set stop sequences the model must not generate past. The OpenAI
        provider does not send them to a reasoning model (GPT-6, GPT-5,
        o-series), because OpenAI refuses the parameter there; the answer is
        then not cut at the sequence.

    -   **withProvider(string $provider) : self**

        Set an explicit registered provider key on the unbound call path. This is
        not a substitute for a database configuration identifier.

    -   **withModel(string $model) : self**

        Set specific model.

    -   **withReasoningEffort(ReasoningEffort $effort) : self**

        Ask a reasoning model for an amount of thinking: one of the
        `ReasoningEffort` cases `None`, `Minimal`, `Low`,
        `Medium`, `High`, `XHigh` and `Max`
        ([ADR-204](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-204@0.44)). It wins over the coarse `think`
        switch. The adapter maps it to a bundled model profile, not a live
        provider capability query. Profiles cover the declared family rules.
        GPT-6.1 Sol, GPT-6 Astra and their dated snapshots accept
        low/medium/high/xhigh and map `None` and `think=false` to
        `Low`. GPT-6 Sol, GPT-6 Luna and GPT-6.1 Terra accept none to
        xhigh. No GPT-6 model accepts `Max`; for these five models a
        request for it is clamped to `XHigh` (measured against the OpenAI
        API on 2026-11-09). Any other `gpt-6` identifier has no effort
        scale, so it receives no effort at all, `Max` included, and
        unknown gateway identifiers receive no guessed effort scale.

        `nrllm_reasoning_effort` records an applied effort when available.
        Its absence does not prove the provider has no effort setting: the
        model may have no local profile or may use the provider default.

    -   **toArray() : array**

        Convert to array format.

## ToolOptions {#tooloptions}

Extends `ChatOptions`. `toolChoice` and `parallelToolCalls` default to
`null` (no explicit override); `captureRaw` defaults to false.
`ToolOptions::auto()` selects automatic tool choice, but does not choose a
default provider. Use the configuration-bound service or set an explicit
registered provider key. `withTaskUid()` supplies task attribution;
`withTextSink()` attaches a live text callback on supported paths.

## EmbeddingOptions {#embeddingoptions}

`model`, `provider` and `dimensions` default to `null`. `cacheTtl`
defaults to 86400 seconds. Use `withCacheTtl()` or `noCache()` to change
caching, `withDimensions()` to request a supported vector size, and the
`compact()` / `highPrecision()` factories for the offered presets.
Model limits and adapter support still apply; see [EmbeddingService](https://docs.typo3.org/permalink/netresearch/nr-llm:api-embedding-service@0.44).

## VisionOptions {#visionoptions}

`detailLevel`, `maxTokens`, `temperature`, `provider` and `model`
default to `null`. `withDetailLevel()` asks for the supported image-detail
mode; it does not make unsupported image input available on another adapter.
Budget attribution uses the shared controls. See [VisionService](https://docs.typo3.org/permalink/netresearch/nr-llm:api-vision-service@0.44).

## TranslationOptions {#translationoptions}

`preserveFormatting` defaults to true. Provider/model/configuration,
languages' glossary/context controls, `tagHandling` and `cacheTtl` are
unset by default; polishing is opt-in. `withConfiguration()` selects the
translator configuration on the specialized path, not automatically the
polisher's configuration. See [Translation options](https://docs.typo3.org/permalink/netresearch/nr-llm:api-translation-options@0.44) for the full
method-specific options and [LLM and specialized translator paths](https://docs.typo3.org/permalink/netresearch/nr-llm:api-translation-paths@0.44) for result types.
