In diesem Tutorial baust du ein kleines Java-Modul, das eigene Tools bereitstellt, Notizen als JSON in der Oracle AI Database speichert und sie per Volltextsuche wiederfindet.
Wenn du KI-Agenten baust, reicht der kurzfristige Chatverlauf meist nicht aus. Echte Assistenten brauchen oft etwas dauerhaften Speicher, um wichtige Fakten abzulegen und später wieder abzurufen.
Dieses Tutorial zeigt, wie du dieses Muster mit einem minimalen Java-Modul umsetzt. Du nutzt LangChain4j-Tools, ein schlankes Agenten-Interface und Oracle AI Database als Datenspeicher. Anstatt Embeddings oder eine vollständige Retrieval-Pipeline hinzuzufügen, bleibt das Design bewusst klein: Notizen werden als JSON-Dokumente gespeichert und mit Oracle Text durchsucht.
Am Ende weißt du, wie das Modul Folgendes zusammenführt:
Ein LangChain4j-Agenteninterface
Zwei individuelle @Tool-Methoden
Ein JDBC-Repository für dauerhafte Notizspeicherung
Eine Konsolenanwendung, die den gesamten Ablauf zusammenführt
Was ist toolbasierte LangChain4j-Memory?
LangChain4j erlaubt es dir, ganz normale Java-Methoden als Tools zu exponieren, die ein Modell bei Bedarf aufrufen kann. In diesem Modul sind diese Fähigkeiten auf Speicher ausgerichtet:
searchMemories(String question) findet passende gespeicherte Notizen
storeMemory(String note) schreibt eine neue dauerhafte Notiz
Das unterscheidet sich von einem gewöhnlichen Chatverlauf, der Nachrichten nur im In-Memory-Kontextfenster hält.
Persistente, toolbasierte Memory entscheidet eigenständig, wann gesucht oder gespeichert wird, und die Daten liegen in einer Datenbank.
Dieses Muster ist hilfreich, wenn ein Agent Fakten wie Incident-Notizen, Runbook-Erinnerungen oder Folgeaktionen behalten soll, ohne zu früh ein großes Retrieval-System aufzubauen.
Persistenter, datenbankgestützter Speicher kann außerdem gleichzeitig von einem oder mehreren Agenten ohne Datenkonflikte genutzt werden.
Toolbasierte Memory ermöglicht es dem Assistenten, bestehende Notizen abzurufen oder neue Notizen in einer dauerhaften Datenbank abzulegen.
Wichtige Features des LangChain4j- und Oracle-AI-DB-Moduls
Das Beispiel ist klein, zeigt aber mehrere zentrale Entwurfsideen für Agenten.
Eigene LangChain4j-Tools
Die Klasse MemoryTools stellt zwei Methoden mit @Tool bereit. Dadurch kann LangChain4j sie dem Agenten ohne zusätzlichen Wrappercode verfügbar machen.
// Retrieve relevant notes and format them for the assistant.@Tool("Search saved memory notes when earlier context might help answer the user.")publicStringsearchMemories(String question){List<MemoryRepository.Note> matches = repository.search(question,3);if(matches.isEmpty()){return"No saved memory matched that question.";}StringBuilder builder =newStringBuilder();for(int i =0; i < matches.size(); i++){MemoryRepository.Note note = matches.get(i);
builder.append(i +1).append(". [M").append(note.id()).append("] ").append(note.text());if(i +1< matches.size()){
builder.append('\n');}}return builder.toString();}Bereitgestellt von
Diese Methode erledigt zwei Dinge: Sie delegiert die Suche ans Repository und formatiert die Ergebnisse modellfreundlich, etwa als [M12] some note text.
So kann der Agent das Tool-Output leicht in seiner finalen Antwort zitieren.
Dauerhafte Memory in der Oracle AI Database
Notizen werden in einer Tabelle agent_memories als native JSON-Dokumente gespeichert. Jede Zeile enthält:
Eine Identitätsspalte id
Eine JSON-Spalte namens memory_doc
Einen created_at-Zeitstempel
Das Modul initialisiert das Schema automatisch:
-- Create a JSON-backed table for durable agent notes.CREATETABLEIFNOTEXISTS agent_memories (
id NUMBER GENERATED ALWAYS ASIDENTITYPRIMARYKEY,
memory_doc JSON NOTNULL,
created_at TIMESTAMPDEFAULTCURRENT_TIMESTAMPNOTNULL)Bereitgestellt von
Das hält das Speichermodell einfach und liefert dennoch strukturierte Daten mit Datenbank-Dauerhaftigkeit.
Schlagwortsuche mit Oracle Text
Das Repository erzeugt keine Embeddings. Stattdessen extrahiert es Schlüsselwörter aus der Frage des Nutzers, entfernt Stoppwörter, baut mit ACCUM einen Oracle Text-Ausdruck und durchsucht den JSON-Inhalt mit json_textcontains.
Das ist besonders hilfreich für Bezeichner und operationale Begriffe wie CHG2145, bei denen exakte oder nahezu exakte Token-Treffer oft wichtiger sind als semantische Ähnlichkeit.
Ein minimaler Konsolen-Workflow
Die Klasse Application erstellt das Repository, initialisiert das Schema, befüllt ein paar Notizen, konstruiert das Chatmodell und startet eine Terminalschleife. So lässt sich das Beispiel leicht ausführen und später in andere Services übernehmen.
So startest du dein LangChain4j-Memory-Projekt
Bevor du das Modul ausführst, stelle sicher, dass deine lokale Umgebung die Projektanforderungen erfüllt.
Voraussetzungen
Du brauchst:
Java 21 oder neuer
Maven 3.9 oder neuer
Oracle AI Database Free lokal oder remote
Eine Umgebungsvariable OPENAI_API_KEY
Das Maven-Projekt hängt ab von:
langchain4j
langchain4j-open-ai
ojdbc11
JUnit und Testcontainers für Integrationstests
Beispiel ausführen
Setze zuerst deinen OpenAI-API-Schlüssel:
# Set the API key used by the chat model.exportOPENAI_API_KEY=<your key>Bereitgestellt von
Dann starte die App aus dem Projektverzeichnis:
# Compile and run the sample with the database connection details.
mvn compile exec:java \-Dexec.args="jdbc:oracle:thin:@localhost:1521/freepdb1 testuser testpwd"Bereitgestellt von
Die Anwendung erwartet genau drei Argumente:
1. JDBC-URL
2. Datenbank-Benutzername
3. Datenbank-Passwort
Fehlen diese, wirft Application.main() eine IllegalArgumentException. Fehlt OPENAI_API_KEY, folgt eine IllegalStateException.
Was beim Start passiert
Beim Start der App werden:
1. Ein MemoryRepository erstellt
2. Das Datenbankschema initialisiert
3. Drei Beispielsnotizen befüllt, falls die Tabelle leer ist
4. Ein OpenAiChatModel gebaut
5. Modell und Tools in AiServices verdrahtet
6. Eine CLI-Schleife gestartet, die Eingaben liest, bis du exit eintippst
So kannst du Memory-Retrieval sofort testen, ohne vorher manuell Zeilen einzufügen.
Einen Java-Agenten mit Memory in LangChain4j bauen
Gehen wir das Modul nun in der Reihenfolge durch, in der die Anwendung es nutzt.
Agenteninterface definieren
LangChain4j beschreibt den Agentenvertrag über ein Java-Interface. In diesem Projekt ist das MemoryAssistant.
// Define the interface that receives each user message.publicinterfaceMemoryAssistant{@SystemMessage("""
You are a simple assistant with access to durable memory notes.
Use searchMemories when earlier notes might help answer the user.
If the user explicitly asks you to remember something for later, call storeMemory.
Keep answers concise.
""")@UserMessage("{{message}}")Stringchat(@V("message")String message);}Bereitgestellt von
Wichtig ist die Systemnachricht. Sie erklärt dem Modell, wann welches Tool zu nutzen ist:
Suchen, wenn frühere Notizen helfen könnten
Speichern, wenn der Nutzer ausdrücklich bittet, sich etwas zu merken
Das ist ein gutes Beispiel für eine schlanke Tool-Policy. Der Prompt ist kurz, aber präzise genug für die Toolauswahl.
Memory-Operationen als Tools bereitstellen
Der Agent spricht nicht direkt mit dem Repository. Stattdessen ruft er die Schicht MemoryTools auf.
Hier ist die Speichermethode:
// Save a note and return its generated memory identifier.@Tool("Store a new memory note when the user asks you to remember something "+"important for later.")publicStringstoreMemory(String note){long id = repository.store(note);return"Stored memory M"+ id +".";}Bereitgestellt von
Das ist bewusst kompakt. Ein Nutzer könnte sagen:
Remember that the next shift should verify the checkout retry queue stays below 50.Bereitgestellt von
Folgt das Modell der Systemanweisung, ruft es storeMemory() auf, das Repository speichert die Notiz, und das Tool liefert etwa:
Dann kann der Agent searchMemories() aufrufen und die gefundene Notiz zur Antwort verwenden.
Repository-Schicht erstellen
Im Repository steckt der Großteil der Logik für dauerhafte Memory. Es ist weiterhin pures JDBC, was das Design leicht nachvollziehbar macht.
Auf hoher Ebene ist MemoryRepository zuständig für:
Schemaerstellung
Optionales Seed-Daten
Einfügen von Notizen
Schlüsselwortextraktion
Oracle Text-Suche
Fallback: Abruf jüngster Notizen, wenn keine brauchbaren Schlüsselwörter vorhanden sind
Beim Einfügen wird der Notiztext normalisiert und validiert, bevor er gespeichert wird:
// Normalize the note, store its JSON document, and return the generated ID.publiclongstore(String note){String normalized =normalizeNote(note);Instant createdAt =Instant.now();try(Connection connection = dataSource.getConnection();PreparedStatement statement = connection.prepareStatement(INSERT_SQL,newString[]{"id"})){
statement.setObject(1,toJsonDocument(normalized, createdAt),OracleTypes.JSON);
statement.setTimestamp(2,Timestamp.from(createdAt));
statement.executeUpdate();try(ResultSet keys = statement.getGeneratedKeys()){if(keys.next()){return keys.getLong(1);}}thrownewIllegalStateException("No generated id returned for stored memory.");}catch(SQLException e){thrownewRuntimeException("Failed to store memory", e);}}Bereitgestellt von
Das JSON-Dokument sieht so aus:
{"noteText":"Runbook note: use section 3 to validate checkout recovery after a rollback.","createdAt":"2026-04-27T17:00:00Z"}Bereitgestellt von
Die Struktur ist simpel, reicht aber für Persistenz und Textsuche aus.
Die Suchstrategie verstehen
Der interessanteste Teil des Repositories ist die Methode search():
// Search by extracted keywords or fall back to recent notes.publicList<Note>search(String question,int maxResults){List<String> keywords =extractKeywords(question);if(keywords.isEmpty()){returnfindRecent(maxResults);}returntextSearch(buildTextExpression(keywords), maxResults);}Bereitgestellt von
Diese Methode folgt einem pragmatischen Ablauf:
1. Die Nutzerfrage tokenisieren
2. Tokens in Kleinbuchstaben umwandeln
3. Stoppwörter wie the, what und remember entfernen
4. Bedeutungsvolle kurze Tokens mit Ziffern beibehalten
5. Einen Oracle Text-Ausdruck mit ACCUM bauen
6. Die JSON-Daten mit json_textcontains durchsuchen
Dieses Detail „Ziffern sind erlaubt“ ist wichtig. So überleben Begriffe wie CHG2145 die Keyword-Extraktion – genau die Art kennzeichnerlastiger Suche, die viele Operations-Agenten brauchen.
Der Such-Workflow wandelt eine Frage in einen Keyword-Ausdruck um und liefert gerankte Memory-Notizen.
Die SQL-Suchabfrage lautet:
-- Rank matching notes by Oracle Text relevance.SELECT id,
JSON_VALUE(
memory_doc,'$.noteText'RETURNING VARCHAR2(2000CHAR))AS note_text,
created_at,
SCORE(1)AS text_score
FROM agent_memories
WHERE JSON_TEXTCONTAINS(memory_doc,'$', ?,1)ORDERBY SCORE(1)DESC, id DESCFETCHFIRST ? ROWS ONLYBereitgestellt von
Ergibt die Frage keine brauchbaren Schlüsselwörter, fällt das Repository auf jüngste Notizen zurück. So hat der Agent einen sinnvollen Standard, statt zu früh eine leere Suche zurückzugeben.
Alles in der Anwendung zusammenführen
Die Anwendung verdrahtet die Bausteine mit AiServices.builder():
// Build the chat model, then attach the memory tools to the assistant.ChatModel chatModel =OpenAiChatModel.builder().apiKey(apiKey).modelName("gpt-5-nano").build();MemoryAssistant assistant =AiServices.builder(MemoryAssistant.class).chatModel(chatModel).tools(newMemoryTools(repository)).build();Bereitgestellt von
Das Muster auf einen Blick:
Ein Chatmodell erstellen
Tool-Methoden exponieren
Diese Tools an einen Interface-gesteuerten Agenten binden
Anschließend leitet die Konsolenschleife die Eingaben einfach an assistant.chat(input) weiter.
Die Demo-Prompts ausprobieren
Die Anwendung druckt ein paar Startprompts:
What do we know about CHG2145?
Remember that the next shift should verify the checkout retry queue stays below 50.
What should the next shift verify?Bereitgestellt von
Diese Prompts sind hilfreich, weil sie den kompletten Memory-Lebenszyklus abdecken:
Eine bestehende Seed-Notiz abrufen
Eine neue Notiz speichern
Die neu gespeicherte Notiz später abrufen
Tipps und Troubleshooting
Das Modul ist bewusst fokussiert – ideal, um das Muster zu lernen. Ein paar praktische Punkte solltest du dennoch beachten.
Tool-Anweisungen klar formulieren
Der System-Prompt weist das Modell an, nur dann zu speichern, wenn der Nutzer es ausdrücklich verlangt. Das reduziert versehentliche Schreibvorgänge. Wenn du den Prompt unbedacht erweiterst, könnte das Modell anfangen, wenig wertige Notizen zu persistieren.
Als dauerhafte Notiz-Memory nutzen, nicht als vollwertiges Knowledge-Retrieval
Dieses Repository eignet sich am besten für kurze Operationsnotizen, Erinnerungen und Bezeichner. Es ist noch kein vollständiges Retrieval-Augmented-Generation-System mit Embeddings, Chunking, Hybrid-Suche oder Ranking.
Oracle Text nutzen, wenn Bezeichner zählen
Für Strings wie Incident-IDs, Ticketnummern und Change-Request-Referenzen ist schlüsselwortorientiertes Retrieval oft der bessere Startpunkt als semantische Suche. Dieses Beispiel spiegelt diesen Trade-off klar wider.
Datenbank- und Docker-Setup separat prüfen
Die Tests des Projekts sind Integrationstests mit Testcontainers. Ist Docker nicht verfügbar, schlägt mvn test fehl, bevor die Repository-Logik läuft. Das ist ein Umgebungsproblem, kein zwingender Anwendungsfehler.
Die Tests decken zwei wichtige Verhaltensweisen ab:
Notizen können über das Repository gespeichert und wieder abgerufen werden
Tool-Ausgaben enthalten Memory-IDs und relevante Notiztexte
Einfach starten, bevor du mehr Memory-Features hinzufügst
Ein häufiger Fehler in Agentenprojekten ist, Vektorspeicher, Gesprächsverlauf, Zusammenfassungen und Retrieval-Policies gleichzeitig einzubauen. Dieses Beispiel zeigt eine bessere Reihenfolge:
1. Einen konkreten Memory-Anwendungsfall definieren
2. Explizite Tools bereitstellen
3. Diese Tools mit dauerhafter Speicherung hinterlegen
4. Das Retrieval-Verhalten verifizieren
5. Erst dann erweiterte Memory-Muster in Betracht ziehen
Weiterlernen
Wenn du nach diesem Tutorial weiter Agentenkompetenzen aufbauen willst, sind diese DataCamp-Ressourcen ein guter nächster Schritt:
Du hast gesehen, wie du mit LangChain4j, Java und Oracle AI Database einen kleinen, aber nützlichen Agenten mit Memory baust. Der Kern ist einfach: Gib dem Modell explizite Memory-Tools, speichere Notizen dauerhaft als JSON und rufe sie mit einer geradlinigen Suchstrategie ab.
Dieses Design ist eine starke Basis, weil es leicht zu verstehen und zu erweitern ist. Sobald das Muster steht, kannst du bessere Filter, reichere Notizschemata, Nutzerscoping oder bei Bedarf auch Vektorsuche ergänzen.
Wenn du mehr über Agentendesign lernen möchtest, vergleiche dieses toolbasierte Memory-Muster als Nächstes mit größeren Agentenframeworks und Orchestrierungs-Workflows. Besonders spannend ist, wie explizite Tools, Retrieval-Muster und mehrschrittige Agenten in größeren KI-Systemen zusammenspielen.
FAQs
Welche Art von Memory implementiert dieses Tutorial?⌄
Dieses Tutorial implementiert toolbasierte, persistente Memory. Notizen werden in einer Datenbanktabelle gespeichert und explizit über Toolaufrufe abgerufen, statt automatisch ins Prompt-Fenster angehängt zu werden.
Verwendet dieses Projekt Vektor-Embeddings?⌄
Nein. Dieses Beispiel verzichtet bewusst auf Embeddings, Vektorsuche und Reranking. Es nutzt Oracle Text mit json_textcontains, um den Notizinhalt zu durchsuchen.
Warum Tools für Memory nutzen statt alles im Chatverlauf zu behalten?⌄
Toolbasierte Memory gibt dir mehr Kontrolle darüber, was wann gespeichert wird und wie der Abruf funktioniert. Außerdem eignet sie sich besser für dauerhafte Notizen, die länger als eine einzelne Unterhaltung bestehen müssen.
Was brauche ich, um die Live-Demo auszuführen?⌄
Du brauchst Java 21 oder neuer, Maven 3.9 oder neuer, Zugriff auf die Oracle AI Database und einen OPENAI_API_KEY in deiner Shell.
Brauchen die Tests Docker?⌄
Ja. Die Integrationstests verwenden Testcontainers, um Oracle AI Database Free zu starten. Daher muss Docker in deiner Umgebung verfügbar sein.
Als Developer Evangelist bei Oracle helfe ich Entwicklerinnen und Entwicklern, moderne Apps zu bauen – von Microservices über Event-Driven-Architekturen bis hin zu Cloud-nativen Systemen und mehr. Wenn du mit Tools wie Kubernetes, Spring Boot oder Kafka arbeitest und dich fragst, wie Oracle in dieses Ökosystem passt, bin ich dein Ansprechpartner.Mein Ziel ist es, praxisnahe, hands-on Anleitungen zu teilen, mit denen du schneller entwickelst, smarter auslieferst und das Beste aus Oracles Datenbanktechnologie herausholst. Ob du mit JSON arbeitest, Event-Streaming nutzt, Vektorsuche einsetzt oder gerade erst einsteigst – ich sorge dafür, dass alles klarer und entwicklerfreundlicher wird.
Lerne die wichtigsten Arten von KI-Agenten kennen, wie sie mit ihrer Umgebung interagieren und wie sie in verschiedenen Branchen eingesetzt werden. Verstehe einfache reflexive, modellbasierte, zielbasierte, nutzenbasierte, lernende Agenten und mehr.
Mach dich mit Python-Datenstrukturen vertraut: Lerne mehr über Datentypen und primitive sowie nicht-primitive Datenstrukturen wie Strings, Listen, Stapel usw.
In diesem Tutorial baust du ein kleines Java-Modul, das eigene Tools bereitstellt, Notizen als JSON in der Oracle AI Database speichert und sie per Volltextsuche wiederfindet.
Wenn du KI-Agenten baust, reicht der kurzfristige Chatverlauf meist nicht aus. Echte Assistenten brauchen oft etwas dauerhaften Speicher, um wichtige Fakten abzulegen und später wieder abzurufen.
Dieses Tutorial zeigt, wie du dieses Muster mit einem minimalen Java-Modul umsetzt. Du nutzt LangChain4j-Tools, ein schlankes Agenten-Interface und Oracle AI Database als Datenspeicher. Anstatt Embeddings oder eine vollständige Retrieval-Pipeline hinzuzufügen, bleibt das Design bewusst klein: Notizen werden als JSON-Dokumente gespeichert und mit
Oracle Textdurchsucht.Am Ende weißt du, wie das Modul Folgendes zusammenführt:
LangChain4j-Agenteninterface@Tool-MethodenJDBC-Repository für dauerhafte NotizspeicherungWas ist toolbasierte LangChain4j-Memory?
LangChain4jerlaubt es dir, ganz normale Java-Methoden als Tools zu exponieren, die ein Modell bei Bedarf aufrufen kann. In diesem Modul sind diese Fähigkeiten auf Speicher ausgerichtet:searchMemories(String question)findet passende gespeicherte NotizenstoreMemory(String note)schreibt eine neue dauerhafte NotizDas unterscheidet sich von einem gewöhnlichen Chatverlauf, der Nachrichten nur im In-Memory-Kontextfenster hält.
Persistente, toolbasierte Memory entscheidet eigenständig, wann gesucht oder gespeichert wird, und die Daten liegen in einer Datenbank.
Dieses Muster ist hilfreich, wenn ein Agent Fakten wie Incident-Notizen, Runbook-Erinnerungen oder Folgeaktionen behalten soll, ohne zu früh ein großes Retrieval-System aufzubauen.
Persistenter, datenbankgestützter Speicher kann außerdem gleichzeitig von einem oder mehreren Agenten ohne Datenkonflikte genutzt werden.
Toolbasierte Memory ermöglicht es dem Assistenten, bestehende Notizen abzurufen oder neue Notizen in einer dauerhaften Datenbank abzulegen.
Wichtige Features des LangChain4j- und Oracle-AI-DB-Moduls
Das Beispiel ist klein, zeigt aber mehrere zentrale Entwurfsideen für Agenten.
Eigene LangChain4j-Tools
Die Klasse
MemoryToolsstellt zwei Methoden mit@Toolbereit. Dadurch kannLangChain4jsie dem Agenten ohne zusätzlichen Wrappercode verfügbar machen.Diese Methode erledigt zwei Dinge: Sie delegiert die Suche ans Repository und formatiert die Ergebnisse modellfreundlich, etwa als
[M12] some note text.So kann der Agent das Tool-Output leicht in seiner finalen Antwort zitieren.
Dauerhafte Memory in der Oracle AI Database
Notizen werden in einer Tabelle
agent_memoriesals native JSON-Dokumente gespeichert. Jede Zeile enthält:idmemory_doccreated_at-ZeitstempelDas Modul initialisiert das Schema automatisch:
Das hält das Speichermodell einfach und liefert dennoch strukturierte Daten mit Datenbank-Dauerhaftigkeit.
Schlagwortsuche mit Oracle Text
Das Repository erzeugt keine Embeddings. Stattdessen extrahiert es Schlüsselwörter aus der Frage des Nutzers, entfernt Stoppwörter, baut mit
ACCUMeinenOracle Text-Ausdruck und durchsucht den JSON-Inhalt mitjson_textcontains.Das ist besonders hilfreich für Bezeichner und operationale Begriffe wie
CHG2145, bei denen exakte oder nahezu exakte Token-Treffer oft wichtiger sind als semantische Ähnlichkeit.Ein minimaler Konsolen-Workflow
Die Klasse
Applicationerstellt das Repository, initialisiert das Schema, befüllt ein paar Notizen, konstruiert das Chatmodell und startet eine Terminalschleife. So lässt sich das Beispiel leicht ausführen und später in andere Services übernehmen.So startest du dein LangChain4j-Memory-Projekt
Bevor du das Modul ausführst, stelle sicher, dass deine lokale Umgebung die Projektanforderungen erfüllt.
Voraussetzungen
Du brauchst:
OPENAI_API_KEYDas Maven-Projekt hängt ab von:
langchain4jlangchain4j-open-aiojdbc11Testcontainersfür IntegrationstestsBeispiel ausführen
Setze zuerst deinen OpenAI-API-Schlüssel:
Dann starte die App aus dem Projektverzeichnis:
Die Anwendung erwartet genau drei Argumente:
1.
JDBC-URL2. Datenbank-Benutzername
3. Datenbank-Passwort
Fehlen diese, wirft
Application.main()eineIllegalArgumentException. FehltOPENAI_API_KEY, folgt eineIllegalStateException.Was beim Start passiert
Beim Start der App werden:
1. Ein
MemoryRepositoryerstellt2. Das Datenbankschema initialisiert
3. Drei Beispielsnotizen befüllt, falls die Tabelle leer ist
4. Ein
OpenAiChatModelgebaut5. Modell und Tools in
AiServicesverdrahtet6. Eine CLI-Schleife gestartet, die Eingaben liest, bis du
exiteintippstSo kannst du Memory-Retrieval sofort testen, ohne vorher manuell Zeilen einzufügen.
Einen Java-Agenten mit Memory in LangChain4j bauen
Gehen wir das Modul nun in der Reihenfolge durch, in der die Anwendung es nutzt.
Agenteninterface definieren
LangChain4jbeschreibt den Agentenvertrag über ein Java-Interface. In diesem Projekt ist dasMemoryAssistant.Wichtig ist die Systemnachricht. Sie erklärt dem Modell, wann welches Tool zu nutzen ist:
Das ist ein gutes Beispiel für eine schlanke Tool-Policy. Der Prompt ist kurz, aber präzise genug für die Toolauswahl.
Memory-Operationen als Tools bereitstellen
Der Agent spricht nicht direkt mit dem Repository. Stattdessen ruft er die Schicht
MemoryToolsauf.Hier ist die Speichermethode:
Das ist bewusst kompakt. Ein Nutzer könnte sagen:
Folgt das Modell der Systemanweisung, ruft es
storeMemory()auf, das Repository speichert die Notiz, und das Tool liefert etwa:Später kann der Nutzer fragen:
Dann kann der Agent
searchMemories()aufrufen und die gefundene Notiz zur Antwort verwenden.Repository-Schicht erstellen
Im Repository steckt der Großteil der Logik für dauerhafte Memory. Es ist weiterhin pures
JDBC, was das Design leicht nachvollziehbar macht.Auf hoher Ebene ist
MemoryRepositoryzuständig für:Oracle Text-SucheBeim Einfügen wird der Notiztext normalisiert und validiert, bevor er gespeichert wird:
Das JSON-Dokument sieht so aus:
Die Struktur ist simpel, reicht aber für Persistenz und Textsuche aus.
Die Suchstrategie verstehen
Der interessanteste Teil des Repositories ist die Methode
search():Diese Methode folgt einem pragmatischen Ablauf:
1. Die Nutzerfrage tokenisieren
2. Tokens in Kleinbuchstaben umwandeln
3. Stoppwörter wie
the,whatundrememberentfernen4. Bedeutungsvolle kurze Tokens mit Ziffern beibehalten
5. Einen
Oracle Text-Ausdruck mitACCUMbauen6. Die JSON-Daten mit
json_textcontainsdurchsuchenDieses Detail „Ziffern sind erlaubt“ ist wichtig. So überleben Begriffe wie
CHG2145die Keyword-Extraktion – genau die Art kennzeichnerlastiger Suche, die viele Operations-Agenten brauchen.Der Such-Workflow wandelt eine Frage in einen Keyword-Ausdruck um und liefert gerankte Memory-Notizen.
Die SQL-Suchabfrage lautet:
Ergibt die Frage keine brauchbaren Schlüsselwörter, fällt das Repository auf jüngste Notizen zurück. So hat der Agent einen sinnvollen Standard, statt zu früh eine leere Suche zurückzugeben.
Alles in der Anwendung zusammenführen
Die Anwendung verdrahtet die Bausteine mit
AiServices.builder():Das Muster auf einen Blick:
Anschließend leitet die Konsolenschleife die Eingaben einfach an
assistant.chat(input)weiter.Die Demo-Prompts ausprobieren
Die Anwendung druckt ein paar Startprompts:
Diese Prompts sind hilfreich, weil sie den kompletten Memory-Lebenszyklus abdecken:
Tipps und Troubleshooting
Das Modul ist bewusst fokussiert – ideal, um das Muster zu lernen. Ein paar praktische Punkte solltest du dennoch beachten.
Tool-Anweisungen klar formulieren
Der System-Prompt weist das Modell an, nur dann zu speichern, wenn der Nutzer es ausdrücklich verlangt. Das reduziert versehentliche Schreibvorgänge. Wenn du den Prompt unbedacht erweiterst, könnte das Modell anfangen, wenig wertige Notizen zu persistieren.
Als dauerhafte Notiz-Memory nutzen, nicht als vollwertiges Knowledge-Retrieval
Dieses Repository eignet sich am besten für kurze Operationsnotizen, Erinnerungen und Bezeichner. Es ist noch kein vollständiges Retrieval-Augmented-Generation-System mit Embeddings, Chunking, Hybrid-Suche oder Ranking.
Oracle Text nutzen, wenn Bezeichner zählen
Für Strings wie Incident-IDs, Ticketnummern und Change-Request-Referenzen ist schlüsselwortorientiertes Retrieval oft der bessere Startpunkt als semantische Suche. Dieses Beispiel spiegelt diesen Trade-off klar wider.
Datenbank- und Docker-Setup separat prüfen
Die Tests des Projekts sind Integrationstests mit
Testcontainers. Ist Docker nicht verfügbar, schlägtmvn testfehl, bevor die Repository-Logik läuft. Das ist ein Umgebungsproblem, kein zwingender Anwendungsfehler.Führe die Tests so aus:
Die Tests decken zwei wichtige Verhaltensweisen ab:
Einfach starten, bevor du mehr Memory-Features hinzufügst
Ein häufiger Fehler in Agentenprojekten ist, Vektorspeicher, Gesprächsverlauf, Zusammenfassungen und Retrieval-Policies gleichzeitig einzubauen. Dieses Beispiel zeigt eine bessere Reihenfolge:
1. Einen konkreten Memory-Anwendungsfall definieren
2. Explizite Tools bereitstellen
3. Diese Tools mit dauerhafter Speicherung hinterlegen
4. Das Retrieval-Verhalten verifizieren
5. Erst dann erweiterte Memory-Muster in Betracht ziehen
Weiterlernen
Wenn du nach diesem Tutorial weiter Agentenkompetenzen aufbauen willst, sind diese DataCamp-Ressourcen ein guter nächster Schritt:
Fazit
Du hast gesehen, wie du mit
LangChain4j, Java und Oracle AI Database einen kleinen, aber nützlichen Agenten mit Memory baust. Der Kern ist einfach: Gib dem Modell explizite Memory-Tools, speichere Notizen dauerhaft als JSON und rufe sie mit einer geradlinigen Suchstrategie ab.Dieses Design ist eine starke Basis, weil es leicht zu verstehen und zu erweitern ist. Sobald das Muster steht, kannst du bessere Filter, reichere Notizschemata, Nutzerscoping oder bei Bedarf auch Vektorsuche ergänzen.
Wenn du mehr über Agentendesign lernen möchtest, vergleiche dieses toolbasierte Memory-Muster als Nächstes mit größeren Agentenframeworks und Orchestrierungs-Workflows. Besonders spannend ist, wie explizite Tools, Retrieval-Muster und mehrschrittige Agenten in größeren KI-Systemen zusammenspielen.