TYPO3 Documentation
TYPO3 LLM extension
Options
Give feedback View source View as Markdown How to edit Edit on GitHub

TYPO3 LLM extension

  • Introduction
  • Installation
  • Administration
    • Managing providers
    • Managing models
    • Managing configurations
    • Managing tasks
    • Managing prompt snippets
    • Managing translation glossaries
    • Get Started: use-case packs
    • Managing skills
    • Running tools
    • MCP servers
    • AI-powered wizards
    • Per-user AI budgets
    • Backend user permissions
    • Verifying the specialized services
    • Usage analytics
    • Agent runs
    • Data retention & purge
    • Effective policy
  • Configuration reference
    • Provider fields
    • Model fields
    • Configuration field reference
    • Task fields
    • Settings
  • Developer guide
    • Streaming support
    • Tool/function calling
    • Creating custom providers
    • Registering a provider
    • Fallback chain
    • Configuration presets
    • Quality evaluation
    • Build your extension on nr-llm
    • Protecting anonymous LLM-cost-bearing endpoints
    • Rendering LLM Markdown server-side safely
    • Feature services
  • API reference
    • API stability
    • Deprecation and removal policy
    • Support matrix
    • LlmServiceManager
    • CompletionService
    • EmbeddingService
    • VisionService
    • DocumentAnalysisService
    • TranslationService
    • ToolCallingService
    • KeywordSearch
    • ReciprocalRankFusion
    • Reranker
    • Response objects
    • Option classes
    • Provider interface
    • Events
    • Exceptions
  • Architecture
  • Testing guide
    • Unit testing
    • Functional testing
    • E2E testing
    • CI configuration
  • Architecture Decision Records
    • ADR-001: Provider Abstraction Layer
    • ADR-002: Feature Services Architecture
    • ADR-003: Typed Response Objects
    • ADR-004: PSR-14 Event System
    • ADR-005: TYPO3 Caching Framework Integration
    • ADR-006: Option Objects vs Arrays
    • ADR-007: Multi-Provider Strategy
    • ADR-008: Error Handling Strategy
    • ADR-009: Streaming Implementation
    • ADR-010: Tool/Function Calling Design
    • ADR-011: Object-Only Options API
    • ADR-012: API key encryption at application level
    • ADR-013: Three-level configuration architecture (Provider-Model-Configuration)
    • ADR-014: AI-Powered Wizard System
    • ADR-015: Type-Safe Domain Models via PHP 8.1+ Enums & Value Objects
    • ADR-016: Thinking/Reasoning Block Extraction
    • ADR-017: Safe Type Casting via SafeCastTrait
    • ADR-018: Multi-Provider Model Discovery
    • ADR-019: Internationalization Strategy
    • ADR-020: Backend Output Format Rendering
    • ADR-021: Provider Fallback Chain
    • ADR-022: Attribute-Based Provider Registration
    • ADR-023: Native Backend Capability Permissions
    • ADR-024: Dashboard Widgets
    • ADR-025: Per-User AI Budgets
    • ADR-026: Provider Middleware Pipeline
    • ADR-027: Split TaskController
    • ADR-028: Public services policy in Configuration/Services.yaml
    • ADR-029: Usage Analytics Dashboard
    • ADR-030: Specialized Services Authenticate Through nr-vault
    • ADR-031: Tagged Prompt Snippet Library
    • ADR-032: Specialized Usage Tracking and Pricing Catalog
    • ADR-033: Specialized Models in the Model Registry
    • ADR-034: Remove the ExtensionConfiguration default-provider fallback
    • ADR-035: Skill ingest (GitHub-hosted SKILL.md sources)
    • ADR-036: Skill injection (attach + compose into prompts)
    • ADR-037: Backend AJAX admin guard
    • ADR-038: Tool runtime (function-calling agent loop)
    • ADR-039: Global per-tool availability state
    • ADR-040: Playground run trace and tool-path prompt augmentation
    • ADR-041: Playground live run streaming
    • ADR-042: Content and configuration read tools for the agent
    • ADR-043: Tool groups with a fail-closed enable cascade
    • ADR-044: Error-analysis tools with fail-closed guards
    • ADR-045: Schema and resolution tools
    • ADR-046: History, URL and validation tools
    • ADR-047: FAL tools
    • ADR-048: Diagnostics tools
    • ADR-049: RAG site-search tools over installed search indexes
    • ADR-050: Retrieval and embedding scope — the boundary with nr_ai_search
    • ADR-051: Tool-calling feature service — narrow consumer interface
    • ADR-052: Usage attribution honours the caller-supplied beUserUid
    • ADR-053: One marker interface for all thrown exceptions
    • ADR-054: Typed tool turns on ChatMessage instead of wire arrays
    • ADR-055: Embeddings join the configuration path; dimensions metadata
    • ADR-056: Configuration presets — consumer-declared, admin-imported records
    • ADR-057: Speech and image services carry attribution in options
    • ADR-058: Telemetry Middleware
    • ADR-059: Decompose LlmServiceManager into focused collaborators
    • ADR-060: Quality evaluation — golden sets, grading and regression detection
    • ADR-061: Skill trust levels, signed manifests, injection scanning
    • ADR-062: Streaming Request Lifecycle
    • ADR-063: Provider Resilience — Circuit Breaker, Health, Idempotency
    • ADR-064: Central Privacy Model
    • ADR-065: Reduce the public service surface (ADR-028 follow-up)
    • ADR-066: Criteria-mode configurations resolve in the service layer
    • ADR-067: Solr per-language core — no language filter query
    • ADR-069: Remove the unusable PromptTemplate stack
    • ADR-070: User-less configuration resolution by identifier
    • ADR-071: Public keyword-search facade over the retrieval cascade
    • ADR-072: Retrieval-quality evaluation — golden questions and top-k hit rates
    • ADR-073: First-party test doubles for consumer-facing interfaces
    • ADR-074: Reciprocal Rank Fusion as a hosted utility
    • ADR-075: Neutral cross-encoder reranker protocol
    • ADR-076: Document understanding — native-first, rasterize fallback
    • ADR-077: Plain completion joins the named-configuration path
    • ADR-078: Budget pre-flight for the specialized image/speech services
    • ADR-079: First-party fakes for Completion, Vision and Budget services
    • ADR-080: Typed provider HTTP exceptions (authentication 401, rate-limit 429)
    • ADR-081: Agent run persistence and a durable event stream
    • ADR-082: Schema-validated structured outputs with one repair round-trip
    • ADR-083: Conversation sessions and memory
    • ADR-084: Human-in-the-loop tool approval with suspend and resume
    • ADR-085: Guardrail pipeline for provider responses
    • ADR-086: Guardrail enforcement gaps — playground verdicts and streamed output
    • ADR-087: Input-side guardrails — screening and redacting the outgoing prompt
    • ADR-088: Live streaming redaction with a holdback buffer
    • ADR-089: Guardrail boundary completeness — reasoning, system prompt, vision
    • ADR-090: One extension until 1.0, with documented split seams
    • ADR-091: Sessions are owned — an explicit actor context on every turn
    • ADR-092: A run records why it ended, and cannot be settled twice
    • ADR-093: One tool gate, in the loop — not in the controller
    • ADR-094: Tool data classes and provider trust zones
    • ADR-095: One failure taxonomy for retry and circuit-breaker decisions
    • ADR-096: The pipeline configuration lives on the call context
    • ADR-097: Specialized services dispatch through the shared pipeline
    • ADR-098: Input-guardrail screening for specialized prompts
    • ADR-099: Fail-closed HTTP egress for the specialized services
    • ADR-100: Specialized usage recorded by tagged extractors in the pipeline
    • ADR-101: AgentRuntime — the agent-run lifecycle as a public service
    • ADR-102: Queued agent runs over the TYPO3 message bus
    • ADR-103: Cooperative cancellation at step boundaries
    • ADR-104: Worker heartbeat, stale-run reaper, retry and dead-letter
    • ADR-105: Typed user-input suspension (WAITING_FOR_INPUT)
    • ADR-106: Per-configuration guardrail policies
    • ADR-107: Agent-loop context-window management
    • ADR-108: Typed ToolResult with run-only artifacts
    • ADR-109: Agent Runs approvals inbox (backend module)
    • ADR-110: Service account scopes
    • ADR-111: Tool side effects and fail-closed audit for writes
    • ADR-112: Lease-before-op fence — no retry for an interrupted write
    • ADR-113: Fail-closed tool data-class enforcement switch
    • ADR-114: Encrypt queued and suspended agent-run state at rest
    • ADR-115: Tool data-class enforcement is the default for new installs
    • ADR-116: Central tooling authority — nr_llm owns builtin + MCP tools
    • ADR-117: Withdraw the backend capability permissions
    • ADR-118: Verify the specialized services from the backend
    • ADR-119: Where the backend modules live — Administration, for now
    • ADR-120: The agent loop's tool gate is a required collaborator
    • ADR-121: Conversations are bounded where they are assembled
    • ADR-122: The side-effecting tool contract waits for a side-effecting tool
    • ADR-123: One catalogue of secret shapes for every masking path
    • ADR-124: A provider key can be set from the command line
    • ADR-125: Per-adapter collaborator classes
    • ADR-126: A named JSON-Schema subset, enforced strict
    • ADR-127: A marked, versioned API surface
    • ADR-128: Provider-native structured output
    • ADR-129: In-repo consumers of structured output
    • ADR-130: Capability grants for backend users
    • ADR-131: The editor-facing module
    • ADR-132: Fail-closed approval audit and turn binding
    • ADR-133: An approver may only release a write they could run
    • ADR-134: A builtin's declared write effect implies human approval
    • ADR-135: The first writing tool, and the contract it actually needed
    • ADR-136: The write preview is produced when the run suspends
    • ADR-137: One candidate resolution for the primary's chain
    • ADR-138: Criteria-mode selection matches the operation, not only the criteria
    • ADR-139: Context assembly is a seam, not a provider registry
    • ADR-140: The effective-policy readout has no apply path
    • ADR-141: Every executing segment holds a lease, or writes stop
    • ADR-142: One routing decision, with a reason per candidate
    • ADR-143: Bound every send against the model that actually serves it
    • ADR-144: Injected context carries a declared data class
    • ADR-145: Governance profiles describe a posture, they never apply it
    • ADR-146: Three more editorial writers, and what the third one reviewed
    • ADR-147: No Symfony AI bridge while it is below 1.0
    • ADR-148: The routing readout is a second gate on the Governance tab
    • ADR-149: A criteria-mode trust zone comes from the resolved model
    • ADR-150: A submitter may only feed a tool they could run, on the turn they saw
    • ADR-151: The context budget is a breakdown, not a number
    • ADR-152: An editor action is a declaration, not a second executor
    • ADR-153: A run's uuid is the correlation id of everything it does
    • ADR-154: An MCP server's liveness is observed, not inferred
    • ADR-155: The system prompt carries a declared data class
    • ADR-156: Persist the routing decision, and observe complexity without routing
    • ADR-157: The simulation covers the run, and answers for an actor
    • ADR-158: The Editor Action Center adds a catalogue, not a runtime
    • ADR-159: One extension, confirmed at the 1.0 API freeze
    • ADR-160: One adapter contract, and honest capability provenance
    • ADR-161: One conformance suite for every MCP connection we support
    • ADR-162: Bulk editor actions are N ordinary runs, not a bulk runtime
    • ADR-163: A use-case pack is data plus a small installer
    • ADR-164: A run's forced sources bind against the trust ceiling
    • ADR-165: A resumed run re-gates its forced sources
    • ADR-166: Deactivating a source does not lower a ceiling
    • ADR-167: Configuration access is a simulated axis
    • ADR-168: A use-case pack declares editor actions, and only declares them
    • ADR-169: Record management belongs to TYPO3's permission model
    • ADR-170: One deadline per MCP operation, spent across its legs
    • ADR-171: The personas nr_llm's code already assumes
    • ADR-172: Four-eyes approval is a per-configuration switch, default off
    • ADR-173: A self-approved run says so, wherever the approval is shown
    • ADR-174: Per-call cost, and request facts measured before the model is chosen
    • ADR-175: A forced skill binds by the same rule as a forced snippet
    • ADR-176: A per-call outcome, kept apart from the approval gate
    • ADR-177: Caller-source attribution on the options path
    • ADR-178: Caller source on the cost path
    • ADR-179: A forced source that is dropped is recorded on the run
    • ADR-180: The sixth writer creates a page, and the one-record rule holds
    • ADR-181: The client reads an event-stream framed answer, and holds no stream
    • ADR-182: A write tool names the record it wrote
    • ADR-183: The AI section exists, and editor surfaces live in it
    • ADR-184: An approval binds to the state the preview showed
    • ADR-185: An observed outcome is derived from history, inside a window
    • ADR-186: A pack may ship snippets its own extension reads
    • ADR-187: AI-write provenance is announced, not implemented
    • ADR-188: Every conversation has a configuration from the moment it opens
    • ADR-189: A model capability is vocabulary, and only sometimes data
    • ADR-190: Cancellation crosses the transport boundary as a signal
    • ADR-191: A cancelled tool call is not a failed one
    • ADR-192: The eighth writer describes an asset, and stays out of the seventh's field
    • ADR-193: A draft element does not turn a connected page into a mixed one
    • ADR-194: Two more metadata fields, one of them a select
    • ADR-195: The ninth writer sets a page's social image, and stays out of the first's allow-list
    • ADR-196: The element draft offers the TCA's content types
    • ADR-197: A generic record creator, only where no narrow writer exists
    • ADR-198: The assistant acts on existing pages and content elements
    • ADR-199: A copy is a hidden draft, and a page is copied without its branch
    • ADR-200: A denied approval tells the model who declined it
    • ADR-201: A consumer can ask which tools a run will not be offered
    • ADR-202: Reading a public web page through an address guard
    • ADR-203: Tool calling on an OpenAI reasoning model goes through Responses
    • ADR-204: Reasoning effort is a request option, and the thinking switch sets it
    • ADR-205: A column every content type carries excludes no type
    • ADR-206: A hook that fails does not fail the write it ran after
    • ADR-207: The DeepL character quota is shown on the test page
    • ADR-208: A site glossary reaches both translators
    • ADR-209: The translation draft translates its text
  • Changelog
  • Sitemap

Options

Give feedback View source View as Markdown How to edit Edit on GitHub
  1. TYPO3 LLM extension
  2. API reference
  3. KeywordSearch
Give feedback Markdown Edit on GitHub

KeywordSearch 

interface KeywordSearchInterface
Fully qualified name
\Netresearch\NrLlm\Service\Retrieval\KeywordSearchInterface

Public keyword-search facade over the site-search retrieval cascade (ADR-071: Public keyword-search facade over the retrieval cascade). Searches the first available backend (Solr, ke_search, indexed_search, database fallback), always filtered public-only — hits are what the anonymous visitor could read.

Input is clamped, never rejected, and any backend failure degrades to an empty result: the facade never throws.

search(string $query, int $limit, ?int $languageId = null): array

Run a public-only keyword search. The query is trimmed and truncated to 200 characters; a query shorter than 2 characters returns an empty list. The limit is clamped to 1–20; a negative language id is clamped to 0. Hits are deduplicated by URL and capped at the limit.

param string $query

Free-text query

param int $limit

Maximum number of hits (clamped to 1–20)

param ?int $languageId

sys_language uid; null means default (0)

Returns

list<KeywordHit> — empty when nothing matched, the query is too short, or no backend is available

isAvailable(): bool

Whether at least one search backend of this variant can answer right now. Never throws.

class KeywordHit
Fully qualified name
\Netresearch\NrLlm\Service\Retrieval\KeywordHit

One keyword-search hit. Final readonly DTO.

sourceId

string — Stable source id; format is backend-internal.

title

string — Result title.

url

string — Public URL of the hit (may be empty when the backend cannot resolve one).

excerpt

string — Short indexed-content excerpt.

languageId

int — sys_language uid the hit belongs to.

score

?float — Backend-native relevance score; not comparable across backends; null when the backend reports none.

pageUid

?int — Page uid when the answering backend can resolve the hit to a page, null otherwise.

Service variants 

Two container registrations exist (ADR-071: Public keyword-search facade over the retrieval cascade):

  • KeywordSearchInterface — the full cascade including the database LIKE fallback. Wire it via constructor type hint or resolve it from the container.
  • nr_llm.keyword_search.index_backed — a named variant that excludes the fallback tier. Use it when "index unavailable" must yield an empty result instead of LIKE hits (e.g. hybrid dense+sparse fusion). Its isAvailable() answers for index-backed engines only.

Usage 

use Netresearch\NrLlm\Service\Retrieval\KeywordSearchInterface;

final class PageFinder
{
    public function __construct(
        private readonly KeywordSearchInterface $keywordSearch,
    ) {}

    public function findCandidates(string $topic): array
    {
        if (!$this->keywordSearch->isAvailable()) {
            return [];
        }

        return $this->keywordSearch->search($topic, 10);
    }
}
Copied!

Wiring the index-backed-only variant:

Vendor\Ext\Search\SparseArm:
  arguments:
    $keywordSearch: '@nr_llm.keyword_search.index_backed'
Copied!
  • Previous
  • Next
Reference to the headline

Copy and freely share the link

This link target has no permanent anchor assigned. You can make a pull request on GitHub to suggest an anchor. The link below can be used, but is prone to change if the page gets moved.

Copy this link into your TYPO3 manual.

  • Home
  • Contact
  • Issues
  • Repository

Last rendered: Sep 26, 2026 18:37

© since 2025 by Netresearch DTT GmbH
  • Legal Notice
  • Privacy Policy