---
title: "Provider interface"
manual: "LLM Foundation"
version: "0.43"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-llm:api-providers@0.43"
source: "Api/ProviderInterface.rst"
rendered: "2026-11-04T13:45:29+00:00"
---

# Provider interface {#api-providers}

-   **interface ProviderInterface**

    -   *Fully qualified name:* `\Netresearch\NrLlm\Provider\Contract\ProviderInterface`

    Contract for LLM providers.

    -   **getName() : string**

        Get human-readable provider name.

    -   **getIdentifier() : string**

        Get provider identifier for configuration.

    -   **configure(array $config) : void**

        Configure the provider with its Vault credential identifier and settings.

        -   *param array $config:* Configuration key-value pairs

    -   **isAvailable() : bool**

        Check if provider is available and configured.

    -   **supportsFeature(string|ModelCapability $feature) : bool**

        Check if provider supports a specific feature.

    -   **chatCompletion(array $messages, array $options = \[\]) : CompletionResponse**

        Execute chat completion.

        -   *param array $messages:*

            A list of typed `ChatMessage` values or legacy
            arrays with `role` and `content`. Rich provider-specific arrays
            retain their additional fields, including tool results and multimodal
            content. Implementations normalize typed messages with `toArray()`.

    -   **complete(string $prompt, array $options = \[\]) : CompletionResponse**

        Execute simple completion from a prompt.

    -   **embeddings(string|array $input, array $options = \[\]) : EmbeddingResponse**

        Generate embeddings for text.

    -   **getAvailableModels() : array**

        Get list of available models.

    -   **getDefaultModel() : string**

        Get the default model identifier.

    -   **testConnection() : array**

        Test the connection to the provider.

        -   *throws:* ProviderConnectionException

        *Returns:* array{success, message, models?}

<a id="api-provider-tools"></a>
## Synchronous Gemini text and thinking {#api-provider-streaming}

For Gemini `chatCompletion()` and `chatCompletionWithTools()`, all string
text parts of the first candidate contribute in their original order. Native
parts with `thought: true` populate `CompletionResponse::$thinking`;
other text parts populate `$content`. Neither sequence gains an invented
separator, and native text keeps its whitespace.

The joined visible text then uses the existing `<think>...</think>` extraction
once, including a delimiter split across parts. Inline blocks keep their
existing trimming and whitespace normalization. If native and inline thinking
both contribute, `$thinking` contains native text, one newline and inline
thinking. With neither contribution, it is `null`. Native-only responses
have empty visible content. This does not change streaming or vision parsing,
and preserves tool calls, response fields and the unmodified native parts used
by the existing response capture or replay behavior. See [ADR-223: Gemini separates native thoughts from text](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-223@0.43).

-   **interface VisionCapableInterface**

    -   *Fully qualified name:* `\Netresearch\NrLlm\Provider\Contract\VisionCapableInterface`

    Contract for providers supporting vision/image
    analysis.

    -   **analyzeImage(array $content, array $options = \[\]) : VisionResponse**

        Analyze an image.

        -   *param array $content:*

            A list of typed `VisionContent` values.
            `LlmServiceManager::vision()` normalizes legacy content-part arrays
            before calling the provider; direct adapter calls use typed values.

        -   *param array $options:* Optional configuration

        *Returns:* VisionResponse

    -   **supportsVision() : bool**

        Check if vision is supported.

    -   **getSupportedImageFormats() : array**

        Get supported image formats.

    -   **getMaxImageSize() : int**

        Get maximum image size in bytes.

-   **interface StreamingCapableInterface**

    -   *Fully qualified name:* `\Netresearch\NrLlm\Provider\Contract\StreamingCapableInterface`

    Contract for providers supporting streaming.

    -   **streamChatCompletion(array $messages, array $options = \[\]) : Generator**

        Stream chat completion.

    -   **supportsStreaming() : bool**

        Check if streaming is supported.

-   **interface ToolCapableInterface**

    -   *Fully qualified name:* `\Netresearch\NrLlm\Provider\Contract\ToolCapableInterface`

    Contract for providers supporting tool/function
    calling.

    -   **chatCompletionWithTools(array $messages, array $tools, array $options = \[\]) : CompletionResponse**

        Chat with tool calling. Messages support multimodal content
        (string or array of content blocks).

        -   *param array $messages:*

            Typed `ChatMessage` values or provider-specific
            legacy message arrays

        -   *param array $tools:*

            A list of typed `ToolSpec` values.
            `LlmServiceManager::chatWithTools()` normalizes legacy tool arrays
            before calling the provider.

    -   **supportsTools() : bool**

        Check if tool calling is supported.

-   **interface DocumentCapableInterface**

    -   *Fully qualified name:* `\Netresearch\NrLlm\Provider\Contract\DocumentCapableInterface`

    Optional capability for Base64 inline document content in chat messages.
    It adds capability discovery, not a separate completion method.

    -   **supportsDocuments() : bool**

        Check if inline document input is supported.

    -   **getSupportedDocumentFormats() : array**

        Return supported document formats, for example `['pdf']`.

-   **interface DecisionCapableInterface**

    -   *Fully qualified name:* `\Netresearch\NrLlm\Provider\Contract\DecisionCapableInterface`

    Optional capability for providers that natively answer typed questions
    about a screened subject (ADR-211).

    -   **decide(DecisionSubject $subject, array $questions, array $options = \[\]) : DecisionResponse**

        -   *param DecisionSubject $subject:* Typed subject to evaluate
        -   *param array $questions:* A list of `DecisionQuestion` values
        -   *param array $options:* Configuration call options, including `model`
        -   *throws:*

            InvalidDecisionResponseException for malformed answers;
            ProviderException for other provider failures

        *Returns:* Typed answers with one valid answer per question

## Gemini known JSON-object slots {#gemini-known-json-object-slots}

Gemini requests encode `FunctionCall.args` and
`FunctionResponse.response` as JSON objects, including empty and numeric-key
maps. This applies to plain chat, tool chat and streaming requests that carry
existing assistant turns, including Gemini-owned replay parts restored after
an approval resume. The public `ToolCall.arguments` PHP array and the saved
replay carrier remain unchanged; conversion occurs in the final request copy.

Decoded list results retain their values under numeric object keys. Scalar or
invalid JSON tool results retain the existing `result` string fallback.
Only these two known object slots are restored. Arbitrary nested object/list
kinds already lost by associative decoding remain an open limitation; nested
lists retain their current shape. See [ADR-224](https://docs.typo3.org/permalink/netresearch/nr-llm:adr-224@0.43).
