Was ist ein AI Agent? Detaillierte Erklärung mit Java-Beispielen
1. Überblick
“AI Agent” ist ein überall auftauchendes Schlagwort, aber die Definition ist oft verschwommen: Manche nennen jeden Chatbot einen Agent, andere sehen nur komplexe mehrstufige Systeme als echte Agents an. Dieser Artikel erklärt, was ein AI Agent ist, welche Komponenten erforderlich sind, und wie der Schleifenmechanismus dahinter funktioniert. Danach kannst du selbst einen minimalen Agent mit purem Java bauen, um seine “innere Funktionsweise” zu verstehen, und ihn dann mit einem echten LLM und Spring AI aufrüsten.
2. Was ist ein AI Agent?
Kurze Definition: Ein AI Agent ist ein System, das ein LLM als “Gehirn” nutzt, um selbstständig Aktionen zu entscheiden und ein Ziel zu erreichen, statt nur eine Frage zu beantworten und dann zu stoppen.
Unterschied zu gewöhnlichen Chatbots:
| Merkmal | Gewöhnlicher Chatbot | AI Agent |
|---|---|---|
| Anzahl der Verarbeitungsschritte | 1 Schritt: Frage → Antwort | Mehrere Schritte: Beobachtung → Überlegung → Aktion → Wiederholung |
| Tool/API aufrufen? | Normalerweise nicht | Ja, entscheidet selbst, welche Tools aufgerufen werden |
| Langfristiges Ziel? | Nein | Ja, der Agent unterteilt die Aufgabe selbst in Teilschritte |
| Beispiel | “Wie ist das Wetter in Hanoi?” → Textbeschreibung | “Buche das günstigste Flugticket Hanoi - Ho-Chi-Minh-Stadt morgen” → sucht Tickets, vergleicht Preise, bucht, bestätigt |
Mit anderen Worten: Ein LLM ist nur ein “Sprachgehirn”, das Texte generieren kann. Ein Agent verwandelt diesen Brain in eine Entität, die handeln kann in der realen Welt (APIs aufrufen, Dateien lesen, Datenbanken abfragen) und diesen Denk-Prozess selbstständig wiederholen kann, bis die Aufgabe erledigt ist.
3. Kernkomponenten eines AI Agent
Ein minimaler Agent benötigt 4 Komponenten. Fehlt eine davon, ist das System nur ein “verkleideter” Chatbot.
3.1. LLM – das Denkzentrum
Das LLM empfängt einen Prompt (mit Ziel, Verlauf, Liste verfügbarer Tools) und generiert die nächste Entscheidung: direkt antworten oder ein Tool aufrufen, und mit welchen Parametern.
3.2. Tool (Function Calling) – die Hände des Agent
Ein Tool ist eine konkrete Funktion, die der Agent aufrufen kann: Bestellung nachschlagen, Wetter-API aufrufen, Datenbank abfragen. Das ist der Teil, der den Agent von “kann reden” zu “kann handeln” macht.
public interface Tool {
String name();
boolean canHandle(String input);
String execute(String input);
}
canHandle prüft, ob dieses Tool die aktuelle Eingabe verarbeiten kann; execute führt die Aktion aus und gibt das Ergebnis (Observation) zurück.
3.3. Memory – das Gedächtnis
Der Agent muss sich merken, was er im vorherigen Schritt getan hat (Chat-Verlauf, Ergebnisse aufgerufener Tools), um unnötige Wiederholungen zu vermeiden. Memory kann so einfach sein wie eine List<String> mit Logs von Schritten, oder komplexer wie ein Vector Store zur Wiederherstellung relevanter Informationen.
3.4. Control Loop – die Steuerungsschleife
Das ist der “Motor”, der den gesamten Prozess antreibt: wiederholt Thought → Action → Observation, bis das Ziel erreicht ist oder die maximal erlaubte Schrittanzahl überschritten wird. Der nächste Abschnitt geht tiefer in diesen Mechanismus ein.
4. Die ReAct-Schleife: Wie ein Agent “denkt und handelt”
ReAct (Reasoning + Acting) ist das populärste Schleifenmodell für Agents:
- Thought: Das LLM denkt nach: “Was soll ich als Nächstes tun?”
- Action: Wählt ein Tool und ruft es mit passenden Parametern auf.
- Observation: Erhält das Ergebnis vom Tool und fügt es dem Kontext hinzu.
- Wiederholt ab Schritt 1, bis das LLM entscheidet, dass genug Informationen für die finale Antwort vorhanden sind, oder bis
maxStepsüberschritten wird.
Um diesen Mechanismus ohne echte LLM-Aufrufe (spart API-Schlüssel) zu verstehen, bauen wir einen Mini-Agent mit purem Java, der if-else statt echtem LLM benutzt.
public class SimpleAgent {
private final List<Tool> tools;
private final int maxSteps;
public SimpleAgent(List<Tool> tools, int maxSteps) {
this.tools = tools;
this.maxSteps = maxSteps;
}
public String run(String goal) {
String observation = goal;
for (int step = 1; step <= maxSteps; step++) {
Tool chosen = tools.stream()
.filter(t -> t.canHandle(observation))
.findFirst()
.orElse(null);
if (chosen == null) {
return "Kein Tool kann damit umgehen: " + observation;
}
System.out.printf("Schritt %d - Thought: brauche Tool '%s'%n", step, chosen.name());
String result = chosen.execute(observation);
System.out.printf("Schritt %d - Observation: %s%n", step, result);
return result; // einfaches Beispiel: fertig nach 1 Schritt
}
return "Max. Schrittanzahl (" + maxSteps + ") überschritten, Aufgabe nicht erledigt.";
}
}
maxSteps ist das “Budget” für Schleifeniterationen — es ist notwendig, um zu verhindern, dass der Agent endlos läuft, wenn er das Ziel nie erreicht. Die for-Schleife simuliert Thought (Tool wählen), Action (execute), Observation (Ergebnis auf Konsole ausgeben).
Drei beispielhafte Tools:
public class WeatherTool implements Tool {
@Override
public String name() {
return "WeatherTool";
}
@Override
public boolean canHandle(String input) {
return input.toLowerCase().contains("wetter");
}
@Override
public String execute(String input) {
return "Hanoi heute: 28°C, bewölkt.";
}
}
public class OrderStatusTool implements Tool {
@Override
public String name() {
return "OrderStatusTool";
}
@Override
public boolean canHandle(String input) {
return input.toLowerCase().contains("bestellung");
}
@Override
public String execute(String input) {
return "Bestellung #1023 wird gerade versendet, Lieferung in 2 Tagen erwartet.";
}
}
public class CalculatorTool implements Tool {
@Override
public String name() {
return "CalculatorTool";
}
@Override
public boolean canHandle(String input) {
return input.matches(".*\\d+\\s*\\+\\s*\\d+.*");
}
@Override
public String execute(String input) {
String digits = input.replaceAll("[^0-9+]", "");
String[] parts = digits.split("\\+");
int sum = Integer.parseInt(parts[0]) + Integer.parseInt(parts[1]);
return "Ergebnis: " + sum;
}
}
Schnelltest:
SimpleAgent agent = new SimpleAgent(
List.of(new CalculatorTool(), new WeatherTool(), new OrderStatusTool()),
3
);
String result = agent.run("Sag mir das Wetter in Hanoi heute");
System.out.println(result);
Ausgabe:
Schritt 1 - Thought: brauche Tool 'WeatherTool'
Schritt 1 - Observation: Hanoi heute: 28°C, bewölkt.
Hanoi heute: 28°C, bewölkt.
Test schreiben, um das Tool-Auswahl-Verhalten zu überprüfen und Fälle zu handhaben, in denen kein Tool passt:
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class SimpleAgentTest {
@Test
void shouldPickWeatherToolWhenGoalMentionsWeather() {
SimpleAgent agent = new SimpleAgent(
List.of(new CalculatorTool(), new WeatherTool(), new OrderStatusTool()),
3
);
String result = agent.run("Sag mir das Wetter in Hanoi heute");
assertThat(result).contains("Hanoi");
}
@Test
void shouldReturnErrorWhenNoToolMatches() {
SimpleAgent agent = new SimpleAgent(List.of(new CalculatorTool()), 3);
String result = agent.run("Sing mir ein Lied");
assertThat(result).startsWith("Kein Tool kann damit umgehen");
}
}
Dieses Beispiel nutzt if-else statt eines echten LLM, deshalb ist die “Überlegung” sehr starr. Ein echter Agent unterscheidet sich: Statt starren canHandle-Prüfungen liest das LLM die Tool-Beschreibungen und entscheidet selbst, welches Tool aufgerufen wird, mit Parametern, die das LLM aus einer natürlichsprachigen Frage extrahiert.
5. Einen echten Agent mit Spring AI und Tool Calling bauen
Um zu sehen, wie ein echtes LLM entscheidet, nutzen wir Spring AI — ein Framework, das AI-Modelle in Spring Boot integriert und bereits Tool Calling unterstützt.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>1.0.0</version>
</dependency>
API-Schlüssel und Modell konfigurieren:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4o-mini
Tool mit @Tool-Annotation deklarieren — genau wie OrderStatusTool im vorherigen Beispiel, aber dieses Mal ruft es ein echtes LLM auf:
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
@Component
public class OrderTools {
@Tool(description = "Nachschlagen des Bestellstatus nach Bestellnummer")
public String getOrderStatus(String orderId) {
// in der Realität würde hier OrderService / Datenbank aufgerufen
return "Bestellung " + orderId + " wird gerade versendet, Lieferung in 2 Tagen erwartet.";
}
}
Die description ist extrem wichtig: Das LLM basiert auf dieser Beschreibung seine Entscheidung ob es dieses Tool aufrufen soll und welche Parameter es übergeben soll.
Service mit ChatClient, um Tools an den Agent zu binden:
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
@Service
public class OrderAssistantService {
private final ChatClient chatClient;
public OrderAssistantService(ChatClient.Builder builder, OrderTools orderTools) {
this.chatClient = builder
.defaultTools(orderTools)
.build();
}
public String ask(String question) {
return chatClient.prompt(question).call().content();
}
}
Wenn du ask("Wo befindet sich meine Bestellung ORD-1023?") aufrufst, macht Spring AI dahinter:
- Sendet die Frage mit Tool-Beschreibungen zum Modell.
- Das Modell antwortet “ruf
getOrderStatusmitorderId="ORD-1023"auf” statt direkt zu antworten. - Spring AI ruft automatisch die entsprechende Java-Methode auf, holt das Ergebnis.
- Sendet das Ergebnis zurück ans Modell, damit es eine finale natürlichsprachige Antwort formuliert.
Ihre Bestellung ORD-1023 wird gerade versendet und sollte in 2 Tagen ankommen.
Genau diese 4 Schritte bilden eine vollständige ReAct-Schleife — nur dass Spring AI die for-Schleife versteckt hat und du die Control Loop nicht selbst wie im Java-Beispiel in Abschnitt 4 schreiben musst.
Anmerkung: Die Version von
spring-ai-starter-model-openaiund der Artefakt-Name können sich mit der Zeit ändern; überprüfe immer die entsprechende BOM für deine Spring-Boot-Version, bevor du die Abhängigkeit hinzufügst.
6. Häufige Agent-Typen
- Single-Agent ReAct: Ein einzelner Agent, der Thought-Action-Observation wiederholt. Passt für mittlere Aufgaben wie die beiden Beispiele oben.
- Plan-and-Execute: Der Agent erstellt zuerst einen detaillierten Plan (Schrittliste), führt dann jeden Schritt aus, ohne ständig neu zu überlegen wie bei ReAct. Eignet sich für strukturierte Mehrschrittaufgaben (z.B. “erstelle einen Bericht mit 5 Teilen”).
- Multi-Agent: Mehrere spezialisierte Agents arbeiten zusammen, normalerweise mit einem “Supervisor”-Agent, der mehrere “Worker”-Agents koordiniert (z.B.: Suchagent, Schreibagent, Datenprüfagent), und die Ergebnisse werden zusammengefasst.
Welcher Typ passt, hängt von der Aufgabenkomplexität ab: einfache Aufgaben → Single-Agent, Aufgaben mit vielen Domains (Suche + Schreiben + Prüfung) → Multi-Agent für bessere Kontrolle und Debugging.
7. Häufige Fehler und wann man KEINEN Agent verwenden sollte
- Endlose Schleifen, Token-Verschwendung: Ohne
maxStepsoder Token-Budget kann der Agent endlos weiterlaufen, weil das LLM “meint”, noch nicht fertig zu sein. Setze immer ein klares Schrittlimit wieSimpleAgentin Abschnitt 4. - Vage Tool-Beschreibungen: Wenn die
descriptioneines Tools unklar ist, wird das LLM das falsche Tool aufrufen oder Parameter mit falschen Typen übergeben. Schreib spezifische Descriptions, nenne klar erwartete Parameterformate. - Keine Safeguards für gefährliche Aktionen: Wenn der Agent die Berechtigung hat, Daten zu löschen, Geld zu überweisen… ohne Bestätigungsschritt, ist das ein großes Risiko. Füge immer eine Kontrollschicht hinzu (human-in-the-loop oder regelbasierte Checks) vor irreversiblen Aktionen.
- Overkill für einfache Aufgaben: Wenn die Frage nur eine LLM-Antwort braucht (z.B. einen Satz übersetzen), bau nicht gleich eine ganze Agent-Schleife mit Tool Calling. Das kostet nur zusätzliche Latenz und API-Aufrufe ohne Mehrwert.
Anmerkung: Wenn dein System nicht außerhalb handeln muss (keine APIs, Datenbanken) und nur Text generiert, ist das keine Agent-Aufgabe — das ist für ein normales LLM. Verkompliziere nicht ohne Grund.
8. Fazit
Ein AI Agent unterscheidet sich von gewöhnlichen Chatbots durch seine Fähigkeit, Aktionen selbst zu entscheiden und den Denkprozess zu wiederholen, bis das Ziel erreicht ist — basierend auf vier Komponenten: LLM, Tools, Memory und Control Loop. Die ReAct-Schleife (Thought-Action-Observation) ist der Mechanismus hinter den meisten heutigen Agents, und du kannst ihn mit purem Java nachbauen, um die Grundlagen zu verstehen, bevor du zu Frameworks wie Spring AI für Production wechselst. Das Wichtigste: Setze Schrittgrenzen, schreib klare Tool-Descriptions, und füge Safeguards für nicht-reversible Aktionen ein — Agents sind mächtig, aber auch anfällig dafür, “zu viel zu tun”, wenn sie nicht kontrolliert werden.