Partie 2 : Construire votre premier agent IA : Guide pratique avec LangChain
La plupart des tutoriels sur les agents IA ignorent les parties compliquĂ©es. Voici comment j'ai créé un agent opĂ©rationnel avec LangChain, tRPC et PostgreSQL â sans cacher les erreurs que j'ai faites en cours de route.

La hype autour des agents IA est bien rĂ©elle. Tout le monde parle de systĂšmes autonomes capables de penser, planifier et exĂ©cuter des tĂąches. Mais voici ce que personne ne vous dit : la plupart des tutoriels vous montrent le "happy path" (le scĂ©nario idĂ©al) et sautent les passages oĂč tout casse.
La semaine derniÚre, j'ai passé deux jours à construire un agent IA à partir de zéro. Pas un simple jouet, mais un vrai agent qui gÚre une plateforme de blog, crée des utilisateurs, rédige des articles et fonctionne réellement. Je vais vous montrer exactement comment j'ai fait, y compris les parties qui n'ont pas marché du premier coup.
Code complet : github.com/giftedunicorn/my-ai-agent
Ce que nous construisons vraiment
Oubliez les exemples abstraits. Nous construisons un agent qui :
- Crée et gÚre des utilisateurs dans une base de données PostgreSQL
- GénÚre des articles de blog à la demande
- Répond de maniÚre conversationnelle tout en utilisant des outils
- Maintient l'historique de la conversation
- Se déploie réellement (pas juste des démos sur localhost)
La stack : Next.js, tRPC, Drizzle ORM, LangChain et Gemini de Google. Pas parce que c'est à la mode, mais parce que c'est type-safe, rapide et que ça fonctionne vraiment en production.
L'Architecture (Plus simple que vous ne le pensez)
Voici ce qui m'a surpris : les agents IA ne sont pas si compliqués. à la base, ce sont juste :
- Un LLM capable d'appeler des fonctions
- Un ensemble d'outils que le LLM peut utiliser
- Une boucle qui exécute ces outils
- De la mémoire pour maintenir le contexte
C'est tout. La complexité vient du fait de faire fonctionner ces piÚces ensemble de maniÚre fiable.
Le schéma de base de données
D'abord, les fondations. Nous avons besoin de tables pour les utilisateurs, les articles et les messages :
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(),
}));
Rien d'extravagant. Juste des donnĂ©es relationnelles propres avec PostgreSQL. La table Message stocke l'historique de la conversation â crucial pour maintenir le contexte entre les requĂȘtes.
Construire les outils (LĂ oĂč la magie opĂšre)
C'est là que la plupart des tutoriels restent vagues. "Créez juste quelques outils", disent-ils. Laissez-moi vous montrer à quoi ça ressemble vraiment.
Les outils sont des fonctions que votre IA peut appeler. Avec DynamicStructuredTool de LangChain, vous définissez :
- Ce que fait l'outil (description)
- Les entrées dont il a besoin (schéma avec Zod)
- Ce qu'il exécute réellement (fonction)
Voici l'outil pour créer des utilisateurs :
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})`;
},
});
La description compte plus que vous ne le pensez. Le LLM l'utilise pour décider quand appeler cet outil. Soyez précis sur quand l'utiliser.
La valeur de retour ? C'est ce que le LLM voit. Je renvoie du texte structurĂ© avec tous les dĂ©tails pertinents â IDs, noms, confirmation. Cela aide le LLM Ă donner de meilleures rĂ©ponses aux utilisateurs.
L'Agent : L'assemblage final
C'est ici que ça devient intéressant. La nouvelle API LangChain (v1.2+) a tout simplifié :
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,
});
C'est tout. Pas de ChatPromptTemplate, pas d'AgentExecutor, pas de chaĂźnes complexes. Juste createAgent et invoke.
Le System Prompt (La personnalité de votre agent)
C'est ici que vous apprenez Ă votre agent comment se comporter :
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.`;
J'ai appris ça à la dure : soyez explicite. Dites à l'agent exactement quoi faire, comment répondre et quels détails inclure. Des prompts vagues mÚnent à des comportements vagues.
Gérer l'historique de conversation
La plupart des exemples sautent cette étape, mais c'est critique pour une bonne expérience utilisateur. Voici comment je le gÚre :
// 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 },
];
Simple, mais efficace. L'agent se souvient maintenant des 10 derniers échanges. Assez pour le contexte, mais pas trop pour ne pas l'embrouiller ou faire exploser les coûts.
Les parties "sales" (Ce qui a vraiment cassé)
Dépendances circulaires : Ma premiÚre tentative a échoué parce que agent.ts importait appRouter, qui importait agentRouter, créant une dépendance circulaire. La solution ? Créer un routeur temporaire inline avec juste les routeurs nécessaires pour les outils.
Extraction de la rĂ©ponse des outils : Le format de rĂ©ponse de LangChain a changĂ© dans la v1.2. Le rĂ©sultat est maintenant dans result.messages[result.messages.length - 1].content, et non plus dans result.output. Ăa m'a pris une heure Ă comprendre.
SĂ©curitĂ© du typage : Le paramĂštre func de l'outil a besoin d'un typage explicite. Vous ne pouvez pas juste dĂ©structurer â vous devez d'abord caster input. TypeScript ne vous aidera pas ici.
Configurez le vĂŽtre
Voici ce dont vous avez réellement besoin :
- Installer les dépendances :
pnpm add @langchain/core @langchain/google-genai langchain drizzle-orm
- Variables d'environnement :
POSTGRES_URL="your-database-url" # Essayez Vercel Postgres, Supabase, ou PostgreSQL local
GOOGLE_GENERATIVE_AI_API_KEY="your-gemini-key" # Obtenez-la sur https://aistudio.google.com/app/apikey
- Configuration de la base de données :
pnpm db:push # Crée les tables à partir du schéma
- Commencez Ă construire :
- Définissez votre schéma de base de données
- Créez des procédures tRPC pour les opérations CRUD
- Construisez des outils LangChain qui enveloppent ces procédures
- Créez l'agent avec vos outils
- Connectez-le Ă votre frontend
Ce que je ferais différemment
Si je recommençais demain :
Commencer avec moins d'outils. J'ai construit 7 outils au départ. Contentez-vous de 3-4 outils principaux d'abord. Faites-les fonctionner parfaitement, puis développez.
Tester les outils indépendamment. N'attendez pas que l'agent soit construit pour tester vos outils. Appelez-les directement avec des données de test d'abord.
Surveiller l'utilisation des outils. J'ai ajoutĂ© des logs pour voir quels outils l'agent appelle et pourquoi. Cela a rĂ©vĂ©lĂ© que les descriptions de mes outils avaient besoin d'ĂȘtre retravaillĂ©es.
Utiliser le streaming. Pour l'instant, les utilisateurs attendent la rĂ©ponse complĂšte. Le streaming donnerait une impression de rapiditĂ©, mĂȘme si cela prend le mĂȘme temps.
Le retour à la réalité
Construire des agents IA n'a rien de magique, mais ce n'est pas trivial non plus. Vous passerez plus de temps sur :
- La conception des outils (que doit faire chaque outil ?)
- Le prompt engineering (comment faire en sorte que l'agent se comporte correctement ?)
- La gestion des erreurs (et si la base de données est hors ligne ? et si le LLM hallucine ?)
- La sécurité du typage (rendre TypeScript heureux avec des réponses LLM dynamiques)
Que sur la partie IA elle-mĂȘme.
Essayez vous-mĂȘme
Le code de ce tutoriel est rĂ©el â je l'ai construit en Ă©crivant ceci. Vous pouvez :
- Le tester avec : "create 3 mock users"
- Essayer : "create 2 blog posts for user 1"
- Demander : "how many users do we have?"
L'agent gÚre tout cela en décidant quels outils appeler, en les exécutant et en répondant de maniÚre conversationnelle.
Et la suite ?
Ce ne sont que les fondations. Ă partir d'ici, vous pourriez :
- Ajouter l'authentification (qui peut créer quoi ?)
- Implémenter les réponses en streaming
- Ajouter des outils plus complexes (recherche, analytics, intégrations)
- Construire une boucle de feedback (l'appel de l'outil a-t-il réussi ?)
- Ajouter du rate limiting (ne laissez pas les utilisateurs créer 10 000 articles)
Mais commencez simple. Faites fonctionner un outil correctement avant d'en ajouter dix médiocres.
Le meilleur dans tout ça ? Une fois que vous comprenez ce pattern â outils + LLM + mĂ©moire â vous pouvez construire des agents pour n'importe quoi. Gestion de base de donnĂ©es, support client, gĂ©nĂ©ration de contenu, peu importe.
Le plus dur, ce n'est pas le code. C'est de concevoir des outils qui résolvent vraiment des problÚmes réels.
Ressources :
- Code source complet : github.com/giftedunicorn/my-ai-agent
- Construit avec Create T3 Turbo
- Documentation LangChain : js.langchain.com
- Obtenir une clé API Gemini : aistudio.google.com
Partager ceci

Feng Liu
shenjian8628@gmail.com