Teil 2: Deinen ersten KI-Agenten bauen: Ein Praxis-Guide mit LangChain

Die meisten AI-Agent-Tutorials lassen die chaotischen Details einfach weg. Hier zeige ich, wie ich einen funktionierenden Agenten mit LangChain, tRPC und PostgreSQL gebaut habe – inklusive aller Fehler, die mir dabei passiert sind.

Teil 2: Deinen ersten KI-Agenten bauen: Ein Praxis-Guide mit LangChain
Feng LiuFeng Liu
19. Dezember 2025

Der Hype um AI-Agenten ist real: So habe ich einen gebaut, der tatsÀchlich funktioniert

Der Hype um AI-Agenten ist real. Jeder spricht ĂŒber autonome Systeme, die denken, planen und Aufgaben ausfĂŒhren können. Aber hier ist die Sache, die dir niemand erzĂ€hlt: Die meisten Tutorials zeigen dir nur den "Happy Path" und ĂŒberspringen die Teile, wo Dinge kaputtgehen.

Letzte Woche habe ich zwei Tage damit verbracht, einen AI-Agenten von Grund auf neu zu bauen. Kein Spielzeug-Beispiel – sondern einen echten Agenten, der eine Blog-Plattform verwaltet, User erstellt, Posts schreibt und tatsĂ€chlich funktioniert. Ich werde dir genau zeigen, wie ich das gemacht habe, inklusive der Teile, die beim ersten Mal nicht funktioniert haben.

VollstÀndiger Code: github.com/giftedunicorn/my-ai-agent

Was wir tatsÀchlich bauen

Vergiss die abstrakten Beispiele. Wir bauen einen Agenten, der:

  • User in einer PostgreSQL-Datenbank erstellt und verwaltet
  • Blogposts auf Abruf generiert
  • Konversationell antwortet, wĂ€hrend er Tools benutzt
  • Die Konversationshistorie beibehĂ€lt
  • TatsĂ€chlich deployed wird (nicht nur Localhost-Demos)

Der Tech-Stack: Next.js, tRPC, Drizzle ORM, LangChain und Google's Gemini. Nicht weil es trendy ist – sondern weil es typsicher und schnell ist und in Production tatsĂ€chlich funktioniert.

Die Architektur (Einfacher als du denkst)

Hier ist, was mich ĂŒberrascht hat: AI-Agenten sind gar nicht so kompliziert. Im Kern sind sie einfach nur:

  1. Ein LLM, das Funktionen aufrufen kann
  2. Ein Set von Tools, die das LLM nutzen kann
  3. Ein Loop, der diese Tools ausfĂŒhrt
  4. Ein GedÀchtnis (Memory), um den Kontext zu behalten

Das war's. Die KomplexitÀt entsteht erst, wenn man versucht, diese Teile zuverlÀssig zusammenarbeiten zu lassen.

Das Datenbankschema

Zuerst das Fundament. Wir brauchen Tabellen fĂŒr User, Posts und Nachrichten:

export const User = pgTable("user", (t) => ({
  id: t.integer().primaryKey().generatedAlwaysAsIdentity(),
  name: t.varchar({ length: 255 }).notNull(),
  email: t.varchar({ length: 255 }).notNull().unique(),
  bio: t.text(),
  createdAt: t.timestamp().defaultNow().notNull(),
  updatedAt: t.timestamp().defaultNow().notNull(),
}));

export const Post = pgTable("post", (t) => ({
  id: t.integer().primaryKey().generatedAlwaysAsIdentity(),
  userId: t
    .integer()
    .notNull()
    .references(() => User.id, { onDelete: "cascade" }),
  title: t.varchar({ length: 500 }).notNull(),
  content: t.text().notNull(),
  published: t.boolean().default(false).notNull(),
  createdAt: t.timestamp().defaultNow().notNull(),
  updatedAt: t.timestamp().defaultNow().notNull(),
}));

Nichts Ausgefallenes. Einfach saubere, relationale Daten mit PostgreSQL. Die Message-Tabelle speichert den Konversationsverlauf – entscheidend, um den Kontext zwischen den Anfragen zu wahren.

Das Bauen der Tools (Wo die Magie passiert)

Hier werden die meisten Tutorials vage. "Erstell einfach ein paar Tools", sagen sie. Lass mich dir zeigen, wie das wirklich aussieht.

Tools sind Funktionen, die deine KI aufrufen kann. Mit LangChains DynamicStructuredTool definierst du:

  1. Was das Tool tut (Beschreibung)
  2. Welche Inputs es benötigt (Schema mit Zod)
  3. Was es tatsĂ€chlich ausfĂŒhrt (Funktion)

Hier ist das Tool zum Erstellen von Usern:

const createUserTool = new DynamicStructuredTool({
  name: "create_user",
  description:
    "Create a new user in the database. Use this when asked to add, create, or register a user.",
  schema: z.object({
    name: z.string().describe("The user's full name"),
    email: z.string().email().describe("The user's email address"),
    bio: z.string().optional().describe("Optional biography"),
  }),
  func: async (input) => {
    const { name, email, bio } = input as {
      name: string;
      email: string;
      bio?: string;
    };
    const user = await caller.user.create({ name, email, bio });
    return `Successfully created user: ${user.name} (ID: ${user.id}, Email: ${user.email})`;
  },
});

Die Beschreibung ist wichtiger, als du denkst. Das LLM nutzt sie, um zu entscheiden, wann dieses Tool aufgerufen werden soll. Sei spezifisch, wann es genutzt werden soll.

Der RĂŒckgabewert? Das ist das, was das LLM sieht. Ich gebe strukturierten Text mit allen relevanten Details zurĂŒck – IDs, Namen, BestĂ€tigung. Das hilft dem LLM, den Nutzern bessere Antworten zu geben.

Der Agent: Alles zusammenfĂŒgen

Hier wird es interessant. Die neue LangChain API (v1.2+) hat alles vereinfacht:

const agent = createAgent({
  model: new ChatGoogleGenerativeAI({
    apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
    model: "gemini-2.0-flash-exp",
    temperature: 0.7,
  }),
  tools: [...createUserTools(caller), ...createPostTools(caller)],
  systemPrompt: AGENT_SYSTEM_PROMPT,
});

const result = await agent.invoke({
  messages: conversationMessages,
});

Das war's. Kein ChatPromptTemplate, kein AgentExecutor, keine komplexen Chains. Einfach createAgent und invoke.

Der System-Prompt (Die Persönlichkeit deines Agenten)

Hier bringst du deinem Agenten bei, wie er sich verhalten soll:

const AGENT_SYSTEM_PROMPT = `You are an AI assistant that helps manage a blog platform.

You have access to tools for:
- User management (create, read, list, count)
- Post management (create, list)

When users ask you to perform actions:
1. Use the appropriate tools to complete the task
2. Be conversational and friendly
3. Provide clear confirmation with specific details
4. When creating mock data, use realistic names and content

Always confirm successful operations with relevant details.`;

Das habe ich auf die harte Tour gelernt: Sei explizit. Sag dem Agenten genau, was er tun soll, wie er antworten soll und welche Details er einbeziehen muss. Vage Prompts fĂŒhren zu vagem Verhalten.

Umgang mit der Konversationshistorie

Die meisten Beispiele ĂŒberspringen das, aber es ist kritisch fĂŒr eine gute User Experience. So handhabe ich das:

// Get last 10 messages from database
const history = await ctx.db
  .select()
  .from(Message)
  .orderBy(desc(Message.createdAt))
  .limit(10);

// Convert to LangChain format
const conversationMessages = [
  ...history.reverse().map((msg) => ({
    role: msg.role === "user" ? "user" : "assistant",
    content: msg.content,
  })),
  { role: "user", content: input.message },
];

Einfach, aber effektiv. Der Agent erinnert sich jetzt an die letzten 10 Austausche. Genug fĂŒr den Kontext, aber nicht so viel, dass er verwirrt wird oder es teuer wird.

Die chaotischen Teile (Was wirklich kaputt ging)

ZirkulĂ€re AbhĂ€ngigkeiten: Mein erster Versuch scheiterte, weil agent.ts den appRouter importierte, welcher wiederum agentRouter importierte – eine klassische zirkulĂ€re AbhĂ€ngigkeit. Die Lösung? Erstelle einen temporĂ€ren Router inline, nur mit den Routern, die du fĂŒr die Tools brauchst.

Tool Response Extraction: Das Antwortformat von LangChain hat sich in v1.2 geÀndert. Das Ergebnis ist jetzt in result.messages[result.messages.length - 1].content, nicht mehr in result.output. Das herauszufinden hat mich eine Stunde gekostet.

Typsicherheit: Der func-Parameter des Tools braucht explizites Typing. Du kannst nicht einfach destrukturieren – du musst input zuerst casten. TypeScript wird dir hier nicht helfen.

Dein eigenes Setup aufsetzen

Hier ist, was du wirklich brauchst:

  1. Dependencies installieren:
pnpm add @langchain/core @langchain/google-genai langchain drizzle-orm
  1. Umgebungsvariablen:
POSTGRES_URL="your-database-url"  # Versuch Vercel Postgres, Supabase oder lokales PostgreSQL
GOOGLE_GENERATIVE_AI_API_KEY="your-gemini-key"  # Bekommst du hier: https://aistudio.google.com/app/apikey
  1. Datenbank-Setup:
pnpm db:push  # Erstellt Tabellen aus dem Schema
  1. Fang an zu bauen:
  • Definiere dein Datenbankschema
  • Erstelle tRPC-Prozeduren fĂŒr CRUD-Operationen
  • Baue LangChain-Tools, die diese Prozeduren wrappen
  • Erstelle den Agenten mit deinen Tools
  • Verbinde alles mit deinem Frontend

Was ich anders machen wĂŒrde

Wenn ich morgen neu anfangen wĂŒrde:

Fang mit weniger Tools an. Ich habe anfangs 7 Tools gebaut. Bleib erst mal bei 3-4 Kern-Tools. Bring die dazu, perfekt zu funktionieren, und erweitere dann.

Teste Tools unabhÀngig. Warte nicht, bis der Agent fertig ist, um deine Tools zu testen. Ruf sie zuerst direkt mit Testdaten auf.

Überwache die Tool-Nutzung. Ich habe Logging hinzugefĂŒgt, um zu sehen, welche Tools der Agent aufruft und warum. Das hat gezeigt, dass meine Tool-Beschreibungen ĂŒberarbeitet werden mussten.

Nutze Streaming. Im Moment warten die User auf die komplette Antwort. Streaming wĂŒrde es schneller wirken lassen, selbst wenn es die gleiche Zeit braucht.

Der RealitÀtscheck

AI-Agenten zu bauen ist keine Magie, aber auch nicht trivial. Du wirst mehr Zeit verbringen mit:

  • Tool-Design (Was soll jedes Tool tun?)
  • Prompt Engineering (Wie bringe ich den Agenten dazu, sich korrekt zu verhalten?)
  • Error Handling (Was, wenn die Datenbank down ist? Was, wenn das LLM halluziniert?)
  • Typsicherheit (TypeScript mit dynamischen LLM-Antworten glĂŒcklich machen)

Als mit dem eigentlichen AI-Teil.

Probier es selbst aus

Der Code fĂŒr dieses Tutorial ist echt – ich habe ihn gebaut, wĂ€hrend ich das hier geschrieben habe. Du kannst:

  • Testen mit: "create 3 mock users"
  • Versuchen: "create 2 blog posts for user 1"
  • Fragen: "how many users do we have?"

Der Agent handhabt all das, indem er entscheidet, welche Tools er aufruft, sie ausfĂŒhrt und konversationell antwortet.

Wie es weitergeht

Das ist nur das Fundament. Von hier aus könntest du:

  • Authentifizierung hinzufĂŒgen (Wer darf was erstellen?)
  • Streaming-Antworten implementieren
  • Komplexere Tools hinzufĂŒgen (Suche, Analytics, Integrationen)
  • Einen Feedback-Loop bauen (War der Tool-Aufruf erfolgreich?)
  • Rate Limiting hinzufĂŒgen (Lass User nicht 10.000 Posts erstellen)

Aber fang einfach an. Bring ein Tool dazu, gut zu funktionieren, bevor du zehn mittelmĂ€ĂŸige hinzufĂŒgst.

Das Beste daran? Sobald du dieses Pattern verstanden hast – Tools + LLM + Memory – kannst du Agenten fĂŒr alles bauen. Datenbankmanagement, Kundensupport, Content-Generierung, was auch immer.

Der schwierige Teil ist nicht der Code. Es ist das Designen von Tools, die tatsÀchlich echte Probleme lösen.


Ressourcen:

Teilen

Feng Liu

Feng Liu

shenjian8628@gmail.com

Teil 2: Deinen ersten KI-Agenten bauen: Ein Praxis-Guide mit LangChain | Feng Liu