---
title: "ADR-051: Tool-calling feature service — narrow consumer interface"
manual: "TYPO3 LLM Extension"
version: "0.35"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-llm:adr-051@0.35"
source: "Adr/Adr051ToolCallingFeatureService.rst"
modified: "2026-09-16T22:09:16+00:00"
---

# ADR-051: Tool-calling feature service — narrow consumer interface

-   *Status:* Accepted
-   *Date:* 2026-07-12
-   *Authors:* Netresearch DTT GmbH

## Context

Every capability except tool calling has a narrow feature-service
interface (`CompletionServiceInterface`, `EmbeddingServiceInterface`,
`VisionServiceInterface`, `TranslationServiceInterface`) whose
docblocks tell consumers to depend on the interface, not the concrete
class. Tool calling is the exception: `chatWithTools()` and
`chatWithToolsForConfiguration()` exist only on
`LlmServiceManagerInterface` — a nineteen-method surface.

A consumer that needs exactly tool calling therefore binds to the whole
manager interface. That coupling is not theoretical: `nr_ai_search`
needs a single method, keeps a hand-written fake of the manager
interface for its unit tests, and that fake fatals every time the
manager interface grows a method — its 0.13 → 0.16 update was blocked in
CI by the two methods 0.14 added, none of which it calls.

## Decision

Add the missing feature-service pair, mirroring the existing pattern:

-   `Netresearch\NrLlm\Service\Feature\ToolCallingServiceInterface`
    with exactly the two tool-calling entry points,
    `chatWithTools()` and `chatWithToolsForConfiguration()`,
    signature-identical to the manager's.
-   `Netresearch\NrLlm\Service\Feature\ToolCallingService` delegating to
    `LlmServiceManagerInterface`, adding only the feature-service
    standard beUserUid auto-population
    (`AutoPopulatesBeUserUidTrait`, REC #4) so per-user budget
    enforcement works without caller wiring.
-   Registered in `Configuration/Services.yaml` like the other feature
    services (public service + public interface alias).

The manager keeps its methods unchanged — this is additive; the feature
service is the documented consumer entry point going forward.

## Consequences

-   A tool-calling consumer's test double is two methods, and additions to
    `LlmServiceManagerInterface` no longer break consumers that do not
    call them.
-   The feature-service catalogue now covers every capability, so the
    integration guide's "depend on the feature interface" rule holds
    without exception.
-   Consumers pinning a provider or configuration keep doing so through
    `ToolOptions` / the `LlmConfiguration` parameter — the service adds
    no second way to select one.
