Spring AI
Plug GoodMem's RAG memory into Spring AI as a DocumentRetriever for RAG pipelines, plus agent tools for search, administration, and file uploads.
Overview
GoodMem is a retrieval-augmented generation (RAG) memory layer that chunks, embeds, and indexes
documents server-side so an agent can pull back the most relevant passages on any question. The
Spring AI connector plugs that in three ways: GoodMemDocumentRetriever, a Spring AI
DocumentRetriever for RetrievalAugmentationAdvisor and any RAG pipeline that takes one;
GoodMemSearchTool, a single @Tool an agent can call with a query; and GoodMemAdminTools
plus GoodMemUploadTool for agents that are meant to administer GoodMem — with optional
reranking and an LLM-generated answer on retrieval.
Installation
<dependency>
<groupId>io.github.bashareid</groupId>
<artifactId>goodmem-spring-ai</artifactId>
<version>0.3.0</version>
</dependency>Requires Java 21+ (the GoodMem Java SDK is compiled for 21), Spring AI 1.0.0
(spring-ai-model and spring-ai-rag are provided — your application already has them), and a
running GoodMem server. Use 0.2.2 or later; llmId needs 0.3.0. The artifact is published on
Maven Central under
a personal groupId (io.github.bashareid), which may change.
Configuration
Connection settings are configured in code through GoodMemConnection.builder():
| Setting | Default | Description |
|---|---|---|
baseUrl | — | Required. Base URL of the GoodMem API server. |
apiKey | — | Required. Sent as the x-api-key header, never in a URL or log. |
timeout | 30s | Per-request timeout. |
verifySsl | true | false disables certificate checks for this connection only — for a local self-signed server, never production. |
You can also hand in an SDK client you configured yourself with
GoodMemConnection.of(goodmemClient).
Quick start
import ai.pairsys.goodmem.springai.GoodMemConnection;
import ai.pairsys.goodmem.springai.GoodMemDocumentRetriever;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.rag.advisor.RetrievalAugmentationAdvisor;
GoodMemConnection connection = GoodMemConnection.builder()
.baseUrl(System.getenv("GOODMEM_BASE_URL"))
.apiKey(System.getenv("GOODMEM_API_KEY"))
.build();
GoodMemDocumentRetriever retriever = GoodMemDocumentRetriever.builder()
.connection(connection)
.spaceId("your-space-uuid") // the developer decides what is searched
.topK(5)
.build();
String answer = ChatClient.builder(chatModel).build()
.prompt()
.advisors(RetrievalAugmentationAdvisor.builder().documentRetriever(retriever).build())
.user("When does payroll run?")
.call()
.content();To let an agent search on demand instead, register new GoodMemSearchTool(retriever) with
.tools(...); the model supplies only query and optionally topK, while spaces, filters, the
reranker, and the LLM stay with the developer. Incomplete results are reported, never hidden:
server-reported problems come back with goodmem_partial=true and the statuses instead of
failing the call, and every id argument must be a UUID — anything else is refused before a
request is sent.
Local development. The example above assumes a TLS-verified server URL. If you are running
GoodMem locally with a self-signed certificate, use https://localhost:8080 and set
verifySsl(false) on the connection builder — it disables certificate checks for that
connection only. Keep TLS verification enabled for any deployed server.
Retrieval post-processing
GoodMem's retrieval call accepts these optional post-processing parameters (each framework exposes them under its own naming convention):
| Parameter | Range | Description |
|---|---|---|
reranker_id | UUID | Reranker model that reorders matched chunks by relevance. |
llm_id | UUID | LLM that generates a contextual answer (abstractReply) alongside the chunks. |
relevance_threshold | 0–1 | Minimum relevance score for a result to be included. |
llm_temperature | 0–2 | Sampling temperature for the LLM post-processor. |
max_results | integer | Maximum number of results to return. |
chronological_resort | boolean | Re-sort the final results by creation time instead of relevance. |
The Spring AI connector exposes reranking and LLM answers as the developer-set rerankerId and
llmId retriever settings, the result count as topK, and metadata filters through
GoodMemFilters. It sets no relevance threshold of its own — reranker score ranges are
provider-dependent, so apply a threshold with a DocumentPostProcessor only to documents whose
goodmem_score_kind is reranker.
Learn more
The full README, examples, and API reference live in the upstream repository: PAIR-Systems-Inc/goodmem-spring-ai.