阅读视图

发现新文章,点击刷新页面。

Agent 开发必学 —— LangChain 生态、MCP 协议与 SOP 落地实战

引言

在 AI Agent 开发从“写着玩”进入“工业化落地”的阶段后,开发者面临的挑战已不再是如何调用 API,而是如何构建一个可控、可扩展、且具备标准接口的系统。

本文将结合 LangChain 最新生态、MCP (Model Context Protocol) 协议以及 SOP (标准作业程序) 思维,为你拆解一套现代 Agent 开发的“黄金组合”。


一、 Agent 开发的“四根支柱”

在构建一个复杂的 AI 应用时,我们需要清晰地定义四个层面:

  1. 大脑 (LLM) :核心算力,负责推理。
  2. 骨架 (@langchain/core) :定义标准化的接口(Runnable、BaseMessage),让不同模型可切换。
  3. 手脚 (MCP / Tools) :连接外部数据与 API 的标准通道。
  4. 灵魂 (SOP / LangGraph) :定义 Agent 的思考路径,确保其行为符合业务规范。

二、 剖析 LangChain 生态系统

正如你所看到的,LangChain 已演变为一个模块化的帝国。理解这些包的依赖关系是开发的第一步:

1. @langchain/core:一切的基石

它是生态系统的“宪法”,定义了所有组件必须遵守的协议。

  • 统一接口:无论你用 OpenAI 还是 Gemini,它们在代码里都是 BaseChatModel
  • Runnable 协议:所有的组件(Prompt, LLM, Parser)都通过 .pipe() 串联,实现了流式处理(Streaming)和异步调用的原生支持。

2. @langchain/langgraph:从“链”到“图”

如果说传统的 Chain 是线性的,那么 LangGraph 就是循环且有状态的。它是目前落地 SOP 的最佳工具,支持:

  • 持久化状态:Agent 聊到一半可以“断点续传”。
  • 人机协作 (Human-in-the-loop) :在 SOP 的关键节点(如打款、删库)强制介入人工审批。

三、 引入 MCP:AI 界的 USB-C 接口

在你的 Agent 想要调用外部工具(比如查询 SQL 或发送 Slack)时,传统的做法是手动编写 BaseTool。但现在,我们有了 MCP (Model Context Protocol)

为什么 MCP + LangChain 是绝配?

  • 解耦:你不需要在 LangChain 代码里写复杂的数据库连接逻辑。
  • 标准化:一个符合 MCP 协议的工具服务器,可以同时被 LangChain、Claude Desktop 和 Cursor 识别。
  • 多语言:你可以用 Go 写一个高性能的 MCP 工具服务器,然后在 TypeScript 编写的 LangChain Agent 中调用它。

四、 核心实战:用 TS 构建 SOP 驱动的 MCP Agent

下面我们通过 TypeScript 演示如何将这些组件缝合在一起,构建一个具备 “查询 -> 判定 -> 执行” SOP 流程的智能体。

1. 环境准备

Bash

npm install @langchain/core @langchain/openai @langchain/langgraph @langchain/mcp

2. 完整代码实现

TypeScript

import { ChatOpenAI } from "@langchain/openai";
import { StateGraph, Annotation, START, END } from "@langchain/langgraph";
import { McpClient } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { convertMcpToLangChainTool } from "@langchain/mcp";
import { ToolNode } from "@langchain/langgraph/prebuilt";

// --- 第一部分:初始化 MCP 工具 (手脚) ---
async function setupMcpTools() {
  const transport = new StdioClientTransport({
    command: "npx",
    args: ["-y", "@modelcontextprotocol/server-everything", "run"],
  });
  const client = new McpClient({ name: "MyToolBox", version: "1.0.0" }, { capabilities: {} });
  await client.connect(transport);
  
  // 将 MCP 能力转化为 LangChain 可用的 Tool 数组
  return await convertMcpToLangChainTool(client);
}

// --- 第二部分:定义 SOP 状态与节点 (灵魂) ---
const AgentState = Annotation.Root({
  messages: Annotation<any[]>({
    reducer: (x, y) => x.concat(y),
    default: () => [],
  }),
  isApproved: Annotation<boolean>({
    reducer: (x, y) => y,
    default: () => false,
  })
});

// --- 第三部分:编排 SOP 流程 (骨架) ---
async function run() {
  const mcpTools = await setupMcpTools();
  const model = new ChatOpenAI({ modelName: "gpt-4o" }).bindTools(mcpTools);

  const workflow = new StateGraph(AgentState)
    // 节点 1: 思考/决策
    .addNode("agent", async (state) => {
      const response = await model.invoke(state.messages);
      return { messages: [response] };
    })
    // 节点 2: 执行工具 (MCP)
    .addNode("action", new ToolNode(mcpTools))
    
    // 设置 SOP 逻辑线
    .addEdge(START, "agent")
    .addConditionalEdges("agent", (state) => {
      const lastMsg = state.messages[state.messages.length - 1];
      return lastMsg.tool_calls?.length > 0 ? "action" : END;
    })
    .addEdge("action", "agent");

  const app = workflow.compile();
  
  // 运行 Agent
  const finalState = await app.invoke({
    messages: [{ role: "user", content: "请使用 MCP 工具列举当前目录文件并分析" }]
  });
  console.log(finalState.messages.map(m => m.content));
}

run();

五、 深度总结对比

为了方便记忆,我们通过下表总结这三个核心概念的协作关系:

组件 对应包 解决的问题 核心心法
LangChain Core @langchain/core 接口不统一、代码耦合。 标准化:一切皆为 Runnable。
MCP @langchain/mcp 扩展能力难复用、环境隔离。 解耦:工具是独立的服务。
LangGraph @langchain/langgraph Agent 行为不可控、无状态。 可预测:思考路径就是流程图。

六、 为什么我们要采用这种模块化架构?

  1. 按需安装:正如你所提到的,不需要 OpenAI 就不装 @langchain/openai,保持项目精简。
  2. 工程化可观测:在 LangGraph 中,你可以清晰地看到 Agent 停在哪个 SOP 节点。
  3. 未来兼容性:即使明年出现了比 LangChain 更火的框架,你的 MCP 工具服务器 依然可以直接迁移使用。

结语

AI 开发正从“魔法”走向“工程”。理解 LangChain 的包结构只是第一步,真正的进阶在于如何利用 MCP 协议 扩展 Agent 的边界,并用 SOP (LangGraph) 驯服 LLM 的不确定性。

❌