LangGraph और Next.js के साथ स्वायत्त मल्टी-एजेंट वर्कफ़्लो का निर्माण
कस्टम स्टेट चैनल, सशर्त रूटिंग, मानव अनुमोदन और Next.js में वास्तविक समय स्ट्रीमिंग के साथ स्टेटफुल मल्टी-एजेंट LLM ग्राफ़ का आर्किटेक्चर।

साधारण चैट इंटरफ़ेस से आगे बढ़कर प्रोडक्शन एआई एप्लिकेशन बनाते समय, सिंगल-प्रॉम्प्ट LLM चेन जल्दी ही अपनी आर्किटेक्चरल सीमाओं तक पहुँच जाती हैं। जटिल इंजीनियरिंग कार्य — जैसे स्वचालित कोड समीक्षा, बहु-स्रोत अनुसंधान संश्लेषण, या स्वायत्त सिस्टम रिफैक्टरिंग — के लिए विशेष एजेंटों के बीच कार्य विभाजन, पुनरावृत्ति संशोधन लूप और सख्त स्टेट निरंतरता की आवश्यकता होती है।
रेखीय श्रृंखलाएँ (A -> B -> C) तब विफल हो जाती हैं जब एजेंट B गलत परिणाम प्रस्तुत करता है या जब चरण C को प्रोडक्शन डेटाबेस में परिवर्तन करने से पहले मानव सत्यापन की आवश्यकता होती है। लचीले एजेंट नेटवर्क बनाने के लिए, प्रणालियों को साइकिलिक स्टेट ग्राफ़, सशर्त रूटिंग और निश्चित चेकपॉइंटिंग का समर्थन करना चाहिए।
इस गाइड में, हम LangGraph (TypeScript) का उपयोग करके एक स्टेटफुल मल्टी-एजेंट ग्राफ़ आर्किटेक्चर को लागू करेंगे और इसे वास्तविक समय SSE स्ट्रीमिंग के साथ Next.js App Router एप्लिकेशन में एकीकृत करेंगे।
आर्किटेक्चर: स्टेटफुल मल्टी-एजेंट ग्राफ़
प्रत्येक भूमिका निभाने के लिए केवल एक LLM पर निर्भर रहने के बजाय, एक मल्टी-एजेंट सिस्टम साझा स्टेट संदर्भ से जुड़े अलग-अलग नोड्स में जिम्मेदारियों को विभाजित करता है।
+-----------------------+
| User Prompt |
+-----------------------+
|
v
+-----------------------+
| Supervisor Node |
+-----------------------+
/ | \
(Research) / | \ (Drafting)
v | v
+------------+ | +------------+
| Researcher | | | Writer |
| Agent | | | Agent |
+------------+ | +------------+
\ | /
\ v /
+-----------------------+
| Reviewer Node |
+-----------------------+
|
(Needs Revision?)
/ \
[YES / Retry] [NO / Complete]
/ \
v v
+-------------------+ +-------------------+
| Interrupt / Edit | | Final Output |
+-------------------+ +-------------------+LangGraph में मुख्य प्रिमिटिव:
- स्टेट चैनल (State Channels): नोड्स के बीच पास की जाने वाली टाइप-सुरक्षित साझा मेमोरी।
- नोड्स (Nodes): व्यक्तिगत एजेंटों या टूल निष्पादकों का प्रतिनिधित्व करने वाले पृथक TypeScript फ़ंक्शन।
- एज (Edges): नोड्स के बीच निष्पादन को स्थानांतरित करने वाले निर्देशित कनेक्शन।
- सशर्त एज (Conditional Edges): मूल्यांकन मानदंडों या त्रुटि सीमाओं पर आधारित गतिशील रूटिंग तर्क।
- चेकपॉइंटर्स (Checkpointers): स्थायी स्टेट स्टोर जो विराम/पुनः आरंभ और मानव हस्तक्षेप को सक्षम करते हैं।
1. टाइप-सुरक्षित स्टेट चैनलों की परिभाषा
LangGraph में, स्टेट को एनोटेटेड चैनलों का उपयोग करके परिभाषित किया गया है। प्रत्येक नोड वर्तमान ग्राफ़ स्टेट प्राप्त करता है और आंशिक स्टेट अपडेट लौटाता है। रिड्यूसर फ़ंक्शन यह निर्धारित करते हैं कि अपडेट मौजूदा स्टेट के साथ कैसे विलय होते हैं।
src/lib/agents/state.ts बनाएं:
import { Annotation, BaseMessage } from "@langchain/core/messages";
export interface AgentTask {
id: string;
description: string;
assignedTo: "researcher" | "writer" | "reviewer";
status: "pending" | "in_progress" | "completed" | "failed";
result?: string;
}
// Define the central state annotation schema
export const AgentGraphAnnotation = Annotation.Root({
// Append new messages to conversation history
messages: Annotation<BaseMessage[]>({
reducer: (x, y) => x.concat(y),
default: () => [],
}),
// Active task context
tasks: Annotation<AgentTask[]>({
reducer: (x, y) => y, // Overwrite with latest task list
default: () => [],
}),
// Quality rating produced by the Reviewer Agent (0 to 10)
reviewScore: Annotation<number>({
reducer: (_, y) => y,
default: () => 0,
}),
// Re-evaluation loop counter to prevent infinite recursion
iterationCount: Annotation<number>({
reducer: (x, y) => x + y,
default: () => 0,
}),
// Flag indicating human approval requirement
requiresApproval: Annotation<boolean>({
reducer: (_, y) => y,
default: () => false,
}),
});
export type AgentGraphState = typeof AgentGraphAnnotation.State;2. विशिष्ट एजेंट नोड्स का कार्यान्वयन
नोड्स एसिंक्रोनस फ़ंक्शन हैं जो डोमेन-विशिष्ट तर्क निष्पादित करते हैं। यहाँ हम तीन नोड्स परिभाषित करते हैं: Researcher, Writer और Reviewer।
src/lib/agents/nodes.ts बनाएं:
import { SystemMessage, HumanMessage, AIMessage } from "@langchain/core/messages";
import { ChatOpenAI } from "@langchain/openai";
import type { AgentGraphState } from "./state";
const model = new ChatOpenAI({
modelName: "gpt-4o-mini",
temperature: 0.2,
});
// Node 1: Researcher Agent
export async function researcherNode(state: AgentGraphState) {
const lastMessage = state.messages[state.messages.length - 1];
const response = await model.invoke([
new SystemMessage(
"You are a Senior Technical Researcher. Gather structural facts, API constraints, and performance benchmarks."
),
new HumanMessage(lastMessage.content as string),
]);
return {
messages: [new AIMessage({ content: `[Researcher]: ${response.content}` })],
iterationCount: 1,
};
}
// Node 2: Writer Agent
export async function writerNode(state: AgentGraphState) {
const researchData = state.messages
.filter((m) => typeof m.content === "string" && m.content.startsWith("[Researcher]"))
.map((m) => m.content)
.join("\n");
const response = await model.invoke([
new SystemMessage(
"You are a Technical Writer. Synthesize research data into structured, concrete TypeScript guides."
),
new HumanMessage(`Synthesize the following research:\n${researchData}`),
]);
return {
messages: [new AIMessage({ content: `[Writer]: ${response.content}` })],
};
}
// Node 3: Reviewer Node (Evaluates output quality)
export async function reviewerNode(state: AgentGraphState) {
const draftMessage = state.messages.find(
(m) => typeof m.content === "string" && m.content.startsWith("[Writer]")
);
const evaluation = await model.invoke([
new SystemMessage(
"You are a Code Reviewer. Score the technical accuracy from 1 to 10. Respond ONLY with JSON: {\"score\": number, \"feedback\": string}"
),
new HumanMessage((draftMessage?.content as string) || ""),
]);
let score = 5;
try {
const parsed = JSON.parse(evaluation.content as string);
score = parsed.score;
} catch {
score = 6;
}
return {
reviewScore: score,
requiresApproval: score >= 8,
};
}3. सशर्त एज के साथ StateGraph का निर्माण
हम एक सशर्त एज फ़ंक्शन का उपयोग करके नोड्स को एक चक्रिय ग्राफ़ में जोड़ते हैं ताकि यह निर्णय लिया जा सके कि संशोधन के लिए Writer पर वापस जाना है या निष्पादन समाप्त करना है।
src/lib/agents/graph.ts बनाएं:
import { StateGraph, START, END, MemorySaver } from "@langchain/langgraph";
import { AgentGraphAnnotation } from "./state";
import { researcherNode, writerNode, reviewerNode } from "./nodes";
// Router function determining graph execution path
function routeReviewOutcome(state: typeof AgentGraphAnnotation.State) {
// Prevent infinite iteration loops
if (state.iterationCount >= 3) {
return "finalize";
}
// If score meets threshold, proceed to human approval or completion
if (state.reviewScore >= 8) {
return "finalize";
}
// Otherwise, route back to Writer for revision
return "revision";
}
export function buildAgentGraph() {
const workflow = new StateGraph(AgentGraphAnnotation)
.addNode("researcher", researcherNode)
.addNode("writer", writerNode)
.addNode("reviewer", reviewerNode)
// Primary execution path
.addEdge(START, "researcher")
.addEdge("researcher", "writer")
.addEdge("writer", "reviewer")
// Conditional edge after evaluation
.addConditionalEdges("reviewer", routeReviewOutcome, {
revision: "writer",
finalize: END,
});
// Attach memory checkpointer for state retention across HTTP requests
const checkpointer = new MemorySaver();
return workflow.compile({
checkpointer,
});
}4. Server-Sent Events के साथ Next.js API रूट स्ट्रीमिंग
एजेंट निष्पादन के दौरान तत्काल UI अपडेट प्रदान करने के लिए, हम ReadableStream का उपयोग करके Next.js App Router से स्टेट इवेंट्स को स्ट्रीम करते हैं।
src/app/api/agent/stream/route.ts बनाएं:
import { NextRequest, NextResponse } from "next/server";
import { HumanMessage } from "@langchain/core/messages";
import { buildAgentGraph } from "@/lib/agents/graph";
export const runtime = "nodejs";
export async function POST(req: NextRequest) {
const { prompt, threadId } = await req.json();
if (!prompt || !threadId) {
return NextResponse.json({ error: "Missing prompt or threadId" }, { status: 400 });
}
const app = buildAgentGraph();
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
try {
const eventStream = await app.streamEvents(
{
messages: [new HumanMessage(prompt)],
},
{
version: "v2",
configurable: { thread_id: threadId },
}
);
for await (const event of eventStream) {
if (event.event === "on_chain_start") {
controller.enqueue(
encoder.encode(`data: ${JSON.stringify({ type: "node_start", node: event.name })}\n\n`)
);
} else if (event.event === "on_chat_model_stream") {
const chunk = event.data?.chunk?.content;
if (chunk) {
controller.enqueue(
encoder.encode(`data: ${JSON.stringify({ type: "token", text: chunk })}\n\n`)
);
}
} else if (event.event === "on_chain_end" && event.name === "LangGraph") {
controller.enqueue(
encoder.encode(`data: ${JSON.stringify({ type: "done", state: event.data?.output })}\n\n`)
);
}
}
} catch (err: any) {
controller.enqueue(
encoder.encode(`data: ${JSON.stringify({ type: "error", error: err.message })}\n\n`)
);
} finally {
controller.close();
}
},
});
return new NextResponse(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
}5. व्यापार-नाप (Trade-Offs) और आर्किटेक्चरल विचार
यद्यपि मल्टी-एजेंट ग्राफ़ टोपोलॉजी संरचना और लचीलापन प्रदान करती हैं, इंजीनियरिंग टीमों को महत्वपूर्ण परिचालन समझौतों का ध्यान रखना चाहिए:
| पहलू | सिंगल LLM चेन | मल्टी-एजेंट ग्राफ़ |
|---|---|---|
| लेटेंसी (Latency) | कम (एकल अनुरोध) | अधिक (कई अनुक्रमिक / समानांतर कॉल) |
| लागत (Cost) | न्यूनतम टोकन उपयोग | नोड्स के बीच संदर्भ दोहराव के कारण अधिक |
| निश्चितता (Determinism) | कम (जटिल निर्देशों में उच्च भिन्नता) | उच्च (सख्त स्टेट संक्रमण और सीमा जांच) |
| मानव हस्तक्षेप | सफाई से रोकना कठिन | अंतर्निहित चेकपॉइंटर्स (interrupt()) |
प्रोडक्शन इंजीनियरिंग चेकलिस्ट:
- री-एंट्रेंसी और सीरियलाइजेशन: सुनिश्चित करें कि Redis या PostgreSQL में सहेजते समय प्रतीकों के नुकसान के बिना चैनल स्टेट ऑब्जेक्ट को JSON में सीरियलाइज़ किया जा सके।
- लूप सर्किट ब्रेकर्स: विफल संशोधन लूप के दौरान असीमित टोकन खपत से बचने के लिए हमेशा सशर्त एज फ़ंक्शन में अधिकतम पुनरावृत्ति सीमा (
state.iterationCount >= N) लागू करें। - अवलोकन क्षमता (Observability): नोड लेटेंसी बाधाओं का पता लगाने के लिए LangSmith या OpenTelemetry जैसे उपकरणों का उपयोग करके ग्राफ़ संक्रमणों को ट्रैक करें।
निष्कर्ष
मल्टी-एजेंट आर्किटेक्चर LLM इंजीनियरिंग को अनियंत्रित टेक्स्ट जेनरेशन से पूर्वानुमान योग्य वितरित प्रणालियों में स्थानांतरित करते हैं। Next.js के साथ LangGraph का लाभ उठाकर, टीमें स्टेटफुल, स्व-सुधारने वाले एजेंट ग्राफ़ का निर्माण कर सकती हैं जो सख्त मानव पर्यवेक्षण बनाए रखते हुए वास्तविक समय में प्रगति स्ट्रीम करते हैं।