Agent Skills: langchain-agents (JavaScript/TypeScript)

Create and use LangChain agents with createAgent - includes agent loops, ReAct pattern, tool execution, and state management

UncategorizedID: evanfang0054/cc-system-creator-scripts/langchain-agents

Install this agent skill to your local

pnpm dlx add-skill https://github.com/evanfang0054/cc-system-creator-scripts/tree/HEAD/skills/langchain-skills/langchain-agents

Skill Files

Browse the full folder contents for langchain-agents.

Download Skill

Loading file tree…

skills/langchain-skills/langchain-agents/SKILL.md

Skill Metadata

Name
langchain-agents
Description
Create and use LangChain agents with createAgent - includes agent loops, ReAct pattern, tool execution, and state management

langchain-agents (JavaScript/TypeScript)

概述

代理(Agents)结合语言模型和工具来创建可以推理任务、决定使用哪些工具并迭代地朝着解决方案工作的系统。createAgent() 函数提供了基于 LangGraph 构建的生产就绪的代理实现。

核心概念:

  • 代理循环(Agent Loop):模型决定 → 调用工具 → 观察结果 → 重复直到完成
  • ReAct 模式:推理和行动(Reasoning and Acting)- 代理推理要做什么,然后通过调用工具来行动
  • 基于图的运行时:代理在具有节点(模型、工具、中间件)和边的 LangGraph 图上运行

何时使用代理

| 场景 | 使用代理? | 原因 | |----------|-----------|-----| | 需要调用外部 API/数据库 | ✅ 是 | 代理可以动态选择调用哪些工具 | | 有决策点的多步骤任务 | ✅ 是 | 代理循环处理迭代推理 | | 简单的提示-响应 | ❌ 否 | 直接使用聊天模型 | | 预定义的工作流 | ❌ 否 | 改用 LangGraph 工作流 | | 需要工具调用但不迭代 | ⚠️ 可能 | 考虑直接使用 model.bindTools() |

决策表

选择代理配置

| 需求 | 配置 | 示例 | |------|---------------|---------| | 带工具的基本代理 | createAgent({ model, tools }) | 搜索、计算器、天气 | | 自定义系统指令 | 添加 systemPrompt | 特定领域的行为 | | 敏感操作的人工批准 | 添加 humanInTheLoopMiddleware | 数据库写入、电子邮件 | | 跨会话持久化 | 添加 checkpointer | 多轮对话 | | 结构化输出格式 | 添加 responseFormat | 提取联系信息、解析表单 |

工具策略

| 工具类型 | 何时使用 | 示例 | |-----------|-------------|---------| | 静态工具 | 工具在执行期间不变 | 搜索、天气、计算器 | | 动态工具 | 工具依赖于运行时状态 | 用户特定的 API | | 内置工具 | 需要常用功能 | 文件系统、代码执行 | | 自定义工具 | 特定于领域的操作 | 您的业务逻辑 |

代码示例

带工具的基本代理

import { createAgent } from "langchain";
import { tool } from "langchain";

// 定义工具
const searchTool = tool(
  async ({ query }: { query: string }) => {
    // 您的搜索实现
    return `${query} 的搜索结果`;
  },
  {
    name: "search",
    description: "在网络上搜索信息",
    schema: z.object({
      query: z.string().describe("搜索查询"),
    }),
  }
);

const weatherTool = tool(
  async ({ location }: { location: string }) => {
    return `${location} 的天气:晴,72°F`;
  },
  {
    name: "get_weather",
    description: "获取某个地点的当前天气",
    schema: z.object({
      location: z.string().describe("城市名称"),
    }),
  }
);

// 创建代理
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, weatherTool],
});

// 调用代理
const result = await agent.invoke({
  messages: [
    { role: "user", content: "旧金山的天气怎么样?" }
  ],
});

console.log(result.messages[result.messages.length - 1].content);

带系统提示的代理

import { createAgent } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, calculatorTool],
  systemPrompt: `您是一个有用的研究助手。
使用搜索工具时始终引用您的来源。
执行计算时展示您的工作过程。`,
});

代理循环执行流程

// 代理在循环中运行:
// 1. 模型接收用户消息
// 2. 模型决定调用工具(或完成)
// 3. 工具执行并返回结果
// 4. 结果返回给模型
// 5. 重复直到模型决定完成

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, weatherTool],
});

// 这个单个 invoke() 调用处理整个循环
const result = await agent.invoke({
  messages: [
    {
      role: "user",
      content: "搜索法国的首都,然后获取其天气"
    }
  ],
});

// 代理自动:
// - 调用搜索工具查找首都
// - 接收 "巴黎"
// - 调用巴黎的天气工具
// - 接收天气数据
// - 用最终答案响应

流式传输代理进度

import { createAgent } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
});

// 使用 updates 模式流式传输以查看每个步骤
for await (const chunk of await agent.stream(
  { messages: [{ role: "user", content: "搜索 LangChain" }] },
  { streamMode: "updates" }
)) {
  console.log("步骤:", chunk);
}

// 使用 messages 模式流式传输 LLM token
for await (const chunk of await agent.stream(
  { messages: [{ role: "user", content: "搜索 LangChain" }] },
  { streamMode: "messages" }
)) {
  const [token, metadata] = chunk;
  if (token.content) {
    process.stdout.write(token.content);
  }
}

带持久化的代理

import { createAgent } from "langchain";
import { MemorySaver } from "@langchain/langgraph";

const checkpointer = new MemorySaver();

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
  checkpointer,
});

// 第一次对话
const config = { configurable: { thread_id: "user-123" } };
await agent.invoke({
  messages: [{ role: "user", content: "我的名字是 Alice" }]
}, config);

// 后续对话 - 代理记得
await agent.invoke({
  messages: [{ role: "user", content: "我的名字是什么?" }]
}, config);
// 响应:"您的名字是 Alice"

并行调用多个工具

// 模型可以同时调用多个工具
const agent = createAgent({
  model: "gpt-4.1",
  tools: [weatherTool, newsToolTool],
});

const result = await agent.invoke({
  messages: [{
    role: "user",
    content: "获取纽约的天气和旧金山的最新新闻"
  }],
});

// 代理可能会在单个步骤中并行调用两个工具

动态工具(依赖于运行时)

import { createAgent } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: (state) => {
    // 工具可以依赖于当前状态
    const userId = state.config?.configurable?.user_id;
    return [
      getUserSpecificTool(userId),
      commonTool,
    ];
  },
});

代理中的错误处理

import { createAgent, wrapToolCall } from "langchain";

// 自定义错误处理中间件
const errorHandler = wrapToolCall({
  name: "ErrorHandler",
  wrapToolCall: async (toolCall, handler) => {
    try {
      return await handler(toolCall);
    } catch (error) {
      return {
        ...toolCall,
        content: `工具错误:${error.message}`,
      };
    }
  },
});

const agent = createAgent({
  model: "gpt-4.1",
  tools: [riskyTool],
  middleware: [errorHandler],
});

边界

代理可以配置什么

模型:任何聊天模型(OpenAI、Anthropic、Google 等) ✅ 工具:自定义工具、内置工具、动态工具 ✅ 系统提示:代理行为的指令 ✅ 中间件:人工在环、错误处理、日志记录 ✅ 检查点:跨对话的内存/持久化 ✅ 响应格式:结构化输出模式 ✅ 最大迭代次数:防止无限循环

代理不能配置什么

直接图结构:直接使用 LangGraph 进行自定义流程 ❌ 工具执行顺序:模型决定调用哪些工具 ❌ 中断模型决策:只能在工具执行前中断 ❌ 多个模型:一个代理 = 一个模型(使用子代理实现多个)

注意事项

1. 代理不停止(无限循环)

// ❌ 问题:没有明确的停止条件
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
});

await agent.invoke({
  messages: [{ role: "user", content: "持续搜索直到完美" }]
});

// ✅ 解决方案:设置最大迭代次数
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
  maxIterations: 10, // 在 10 次工具调用后停止
});

2. 工具未被调用

// ❌ 问题:模糊的工具描述
const badTool = tool(
  async ({ input }: { input: string }) => "result",
  {
    name: "tool",
    description: "做些事情", // 太模糊了!
    schema: z.object({ input: z.string() }),
  }
);

// ✅ 解决方案:清晰、具体的描述
const goodTool = tool(
  async ({ query }: { query: string }) => "result",
  {
    name: "web_search",
    description: "在网络上搜索关于某个主题的当前信息。当您需要训练中没有的最新数据时使用此工具。",
    schema: z.object({
      query: z.string().describe("搜索查询(2-10 个词)"),
    }),
  }
);

3. 状态未持久化

// ❌ 问题:没有检查点
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
});

// 每次 invoke 都是隔离的 - 没有内存
await agent.invoke({ messages: [{ role: "user", content: "嗨,我是 Bob" }] });
await agent.invoke({ messages: [{ role: "user", content: "我的名字是什么?" }] });
// 代理不记得 "Bob"

// ✅ 解决方案:添加检查点和 thread_id
import { MemorySaver } from "@langchain/langgraph";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
  checkpointer: new MemorySaver(),
});

const config = { configurable: { thread_id: "session-1" } };
await agent.invoke({ messages: [{ role: "user", content: "嗨,我是 Bob" }] }, config);
await agent.invoke({ messages: [{ role: "user", content: "我的名字是什么?" }] }, config);
// 代理记得:"您的名字是 Bob"

4. 消息与状态混淆

// 代理状态包含不仅仅是消息
const result = await agent.invoke({
  messages: [{ role: "user", content: "你好" }]
});

// ✅ 访问完整的对话历史
console.log(result.messages); // 所有消息的数组

// ✅ 访问结构化输出(如果配置了)
console.log(result.structuredResponse);

// ❌ 不要尝试直接访问 result.content
// console.log(result.content); // undefined!

5. 工具结果必须是可序列化的

// ❌ 问题:返回不可序列化的对象
const badTool = tool(
  async () => {
    return new Date(); // Date 对象默认情况下不是 JSON 可序列化的
  },
  { name: "get_time", description: "获取当前时间" }
);

// ✅ 解决方案:返回可序列化的数据
const goodTool = tool(
  async () => {
    return new Date().toISOString(); // 字符串是可序列化的
  },
  { name: "get_time", description: "获取当前时间" }
);

6. 流式模式很重要

// 不同的流式模式显示不同的信息

// "values" - 每步后的完整状态
for await (const chunk of await agent.stream(input, { streamMode: "values" })) {
  console.log(chunk.messages); // 到目前为止的所有消息
}

// "updates" - 仅每步中变化的内容
for await (const chunk of await agent.stream(input, { streamMode: "updates" })) {
  console.log(chunk); // 仅仅是增量
}

// "messages" - LLM token 流
for await (const chunk of await agent.stream(input, { streamMode: "messages" })) {
  const [token, metadata] = chunk;
  console.log(token.content); // 每个 token
}

文档链接

langchain-agents (JavaScript/TypeScript) Skill | Agent Skills