> ## Documentation Index
> Fetch the complete documentation index at: https://cndoc-langchain.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 智能体中的上下文工程

## 概述

构建智能体（或任何 LLM 应用程序）的难点在于使其足够可靠。虽然它们可能适用于原型，但在实际用例中常常失败。

### 智能体为何会失败？

当智能体失败时，通常是因为智能体内部的 LLM 调用采取了错误的操作/未执行我们预期的任务。LLM 失败的原因有两个：

1. 底层 LLM 能力不足
2. 未向 LLM 传递“正确”的上下文

更多时候——实际上是第二个原因导致智能体不够可靠。

**上下文工程** 是指以正确的格式提供正确的信息和工具，以便 LLM 能够完成任务。这是 AI 工程师的首要工作。这种“正确”上下文的缺失是阻碍智能体变得更可靠的最大障碍，而 LangChain 的智能体抽象层专门设计用于促进上下文工程。

<Tip>
  刚接触上下文工程？请从[概念概述](/oss/javascript/concepts/context)开始，了解不同类型的上下文及其使用场景。
</Tip>

### 智能体循环

典型的智能体循环包含两个主要步骤：

1. **模型调用** - 使用提示词和可用工具调用 LLM，返回响应或执行工具的请求
2. **工具执行** - 执行 LLM 请求的工具，返回工具结果

<div style={{ display: "flex", justifyContent: "center" }}>
  <img src="https://mintcdn.com/other-405835d4/3NQVGWwcrOYcKZbP/oss/images/core_agent_loop.png?fit=max&auto=format&n=3NQVGWwcrOYcKZbP&q=85&s=e80aadacf0a151589aaa821313e0916c" alt="核心智能体循环图" className="rounded-lg" width="300" height="268" data-path="oss/images/core_agent_loop.png" />
</div>

此循环持续进行，直到 LLM 决定结束。

### 可控制的内容

要构建可靠的智能体，您需要控制智能体循环每个步骤中发生的事情，以及步骤之间发生的事情。

| 上下文类型                   | 您控制的内容                          | 临时或持久 |
| ----------------------- | ------------------------------- | ----- |
| **[模型上下文](#模型上下文)**     | 进入模型调用的内容（指令、消息历史、工具、响应格式）      | 临时    |
| **[工具上下文](#工具上下文)**     | 工具可以访问和生成的内容（对状态、存储、运行时上下文的读/写） | 持久    |
| **[生命周期上下文](#生命周期上下文)** | 模型和工具调用之间发生的事情（摘要、防护栏、日志记录等）    | 持久    |

<CardGroup>
  <Card title="临时上下文" icon="bolt" iconType="duotone">
    LLM 在单次调用中看到的内容。您可以修改消息、工具或提示词，而无需更改保存在状态中的内容。
  </Card>

  <Card title="持久上下文" icon="database" iconType="duotone">
    跨轮次保存在状态中的内容。生命周期钩子和工具写入会永久修改此内容。
  </Card>
</CardGroup>

### 数据源

在此过程中，您的智能体访问（读/写）不同的数据源：

| 数据源        | 也称为  | 范围   | 示例                         |
| ---------- | ---- | ---- | -------------------------- |
| **运行时上下文** | 静态配置 | 对话范围 | 用户 ID、API 密钥、数据库连接、权限、环境设置 |
| **状态**     | 短期记忆 | 对话范围 | 当前消息、上传的文件、身份验证状态、工具结果     |
| **存储**     | 长期记忆 | 跨对话  | 用户偏好、提取的见解、记忆、历史数据         |

### 工作原理

LangChain [中间件](/oss/javascript/langchain/middleware)是底层机制，使上下文工程对使用 LangChain 的开发者变得实用。

中间件允许您钩入智能体生命周期中的任何步骤，并：

* 更新上下文
* 跳转到智能体生命周期中的不同步骤

在本指南中，您将频繁使用中间件 API 作为实现上下文工程的手段。

## 模型上下文

控制进入每次模型调用的内容 - 指令、可用工具、使用哪个模型以及输出格式。这些决策直接影响可靠性和成本。

<CardGroup cols={2}>
  <Card title="系统提示词" icon="message-2" href="#系统提示词">
    开发者向 LLM 提供的基础指令。
  </Card>

  <Card title="消息" icon="messages" href="#消息">
    发送给 LLM 的完整消息列表（对话历史）。
  </Card>

  <Card title="工具" icon="tool" href="#工具">
    智能体可用于执行操作的实用程序。
  </Card>

  <Card title="模型" icon="cpu" href="#模型">
    要调用的实际模型（包括配置）。
  </Card>

  <Card title="响应格式" icon="braces" href="#响应格式">
    模型最终响应的模式规范。
  </Card>
</CardGroup>

所有这些类型的模型上下文都可以从**状态**（短期记忆）、**存储**（长期记忆）或**运行时上下文**（静态配置）中获取。

### 系统提示词

系统提示词设置 LLM 的行为和能力。不同的用户、上下文或对话阶段需要不同的指令。成功的智能体利用记忆、偏好和配置，为对话的当前状态提供正确的指令。

<Tabs>
  <Tab title="状态">
    从状态访问消息计数或对话上下文：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { createAgent } from "langchain";

    const agent = createAgent({
      model: "gpt-5.4",
      tools: [...],
      middleware: [
        dynamicSystemPromptMiddleware((state) => {
          // 从状态读取：检查对话长度
          const messageCount = state.messages.length;

          let base = "You are a helpful assistant.";

          if (messageCount > 10) {
            base += "\nThis is a long conversation - be extra concise.";
          }

          return base;
        }),
      ],
    });
    ```
  </Tab>

  <Tab title="存储">
    从长期记忆访问用户偏好：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createAgent, dynamicSystemPromptMiddleware } from "langchain";

    const contextSchema = z.object({
      userId: z.string(),
    });

    type Context = z.infer<typeof contextSchema>;

    const agent = createAgent({
      model: "gpt-5.4",
      tools: [...],
      contextSchema,
      middleware: [
        dynamicSystemPromptMiddleware<Context>(async (state, runtime) => {
          const userId = runtime.context.userId;

          // 从存储读取：获取用户偏好
          const store = runtime.store;
          const userPrefs = await store.get(["preferences"], userId);

          let base = "You are a helpful assistant.";

          if (userPrefs) {
            const style = userPrefs.value?.communicationStyle || "balanced";
            base += `\nUser prefers ${style} responses.`;
          }

          return base;
        }),
      ],
    });
    ```
  </Tab>

  <Tab title="运行时上下文">
    从运行时上下文访问用户 ID 或配置：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createAgent, dynamicSystemPromptMiddleware } from "langchain";

    const contextSchema = z.object({
      userRole: z.string(),
      deploymentEnv: z.string(),
    });

    type Context = z.infer<typeof contextSchema>;

    const agent = createAgent({
      model: "gpt-5.4",
      tools: [...],
      contextSchema,
      middleware: [
        dynamicSystemPromptMiddleware<Context>((state, runtime) => {
          // 从运行时上下文读取：用户角色和环境
          const userRole = runtime.context.userRole;
          const env = runtime.context.deploymentEnv;

          let base = "You are a helpful assistant.";

          if (userRole === "admin") {
            base += "\nYou have admin access. You can perform all operations.";
          } else if (userRole === "viewer") {
            base += "\nYou have read-only access. Guide users to read operations only.";
          }

          if (env === "production") {
            base += "\nBe extra careful with any data modifications.";
          }

          return base;
        }),
      ],
    });
    ```
  </Tab>
</Tabs>

### 消息

消息构成了发送给 LLM 的提示词。
管理消息的内容至关重要，以确保 LLM 拥有正确的信息来做出良好响应。

<Tabs>
  <Tab title="状态">
    当与当前查询相关时，从状态注入上传的文件上下文：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { createMiddleware } from "langchain";

    const injectFileContext = createMiddleware({
      name: "InjectFileContext",
      wrapModelCall: (request, handler) => {
        // request.state 是 request.state.messages 的快捷方式
        const uploadedFiles = request.state.uploadedFiles || [];  // [!code highlight]

        if (uploadedFiles.length > 0) {
          // 构建关于可用文件的上下文
          const fileDescriptions = uploadedFiles.map(file =>
            `- ${file.name} (${file.type}): ${file.summary}`
          );

          const fileContext = `Files you have access to in this conversation:
    ${fileDescriptions.join("\n")}

    Reference these files when answering questions.`;

          // 在最近消息之前注入文件上下文
          const messages = [  // [!code highlight]
            ...request.messages,  // 对话的其余部分
            { role: "user", content: fileContext }
          ];
          request = request.override({ messages });  // [!code highlight]
        }

        return handler(request);
      },
    });

    const agent = createAgent({
      model: "gpt-5.4",
      tools: [...],
      middleware: [injectFileContext],
    });
    ```
  </Tab>

  <Tab title="存储">
    从存储注入用户的电子邮件写作风格以指导起草：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createMiddleware } from "langchain";

    const contextSchema = z.object({
      userId: z.string(),
    });

    const injectWritingStyle = createMiddleware({
      name: "InjectWritingStyle",
      contextSchema,
      wrapModelCall: async (request, handler) => {
        const userId = request.runtime.context.userId;  // [!code highlight]

        // 从存储读取：获取用户的写作风格示例
        const store = request.runtime.store;  // [!code highlight]
        const writingStyle = await store.get(["writing_style"], userId);  // [!code highlight]

        if (writingStyle) {
          const style = writingStyle.value;
          // 从存储的示例构建风格指南
          const styleContext = `Your writing style:
    - Tone: ${style.tone || 'professional'}
    - Typical greeting: "${style.greeting || 'Hi'}"
    - Typical sign-off: "${style.signOff || 'Best'}"
    - Example email you've written:
    ${style.exampleEmail || ''}`;

          // 附加在末尾 - 模型更关注最后的消息
          const messages = [
            ...request.messages,
            { role: "user", content: styleContext }
          ];
          request = request.override({ messages });  // [!code highlight]
        }

        return handler(request);
      },
    });
    ```
  </Tab>

  <Tab title="运行时上下文">
    根据用户的司法管辖区从运行时上下文注入合规规则：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createMiddleware } from "langchain";

    const contextSchema = z.object({
      userJurisdiction: z.string(),
      industry: z.string(),
      complianceFrameworks: z.array(z.string()),
    });

    type Context = z.infer<typeof contextSchema>;

    const injectComplianceRules = createMiddleware<Context>({
      name: "InjectComplianceRules",
      contextSchema,
      wrapModelCall: (request, handler) => {
        // 从运行时上下文读取：获取合规要求
        const { userJurisdiction, industry, complianceFrameworks } = request.runtime.context;  // [!code highlight]

        // 构建合规约束
        const rules = [];
        if (complianceFrameworks.includes("GDPR")) {
          rules.push("- Must obtain explicit consent before processing personal data");
          rules.push("- Users have right to data deletion");
        }
        if (complianceFrameworks.includes("HIPAA")) {
          rules.push("- Cannot share patient health information without authorization");
          rules.push("- Must use secure, encrypted communication");
        }
        if (industry === "finance") {
          rules.push("- Cannot provide financial advice without proper disclaimers");
        }

        if (rules.length > 0) {
          const complianceContext = `Compliance requirements for ${userJurisdiction}:
    ${rules.join("\n")}`;

          // 附加在末尾 - 模型更关注最后的消息
          const messages = [
            ...request.messages,
            { role: "user", content: complianceContext }
          ];
          request = request.override({ messages });  // [!code highlight]
        }

        return handler(request);
      },
    });
    ```
  </Tab>
</Tabs>

<Note>
  **临时与持久的消息更新：**

  上述示例使用 `wrap_model_call` 进行**临时**更新 - 修改发送给模型的消息以进行单次调用，而不更改保存在状态中的内容。

  对于修改状态的**持久**更新，您可以：

  * 直接从 `wrapModelCall` 返回 [`Command`](https://reference.langchain.com/javascript/langchain-langgraph/index/Command)，以从模型调用层注入状态更新。
  * 使用生命周期钩子，如 `beforeModel`、`afterModel` 或 `wrapToolCall`（用于工具返回）来更新对话历史。有关更多详细信息，请参阅[中间件文档](/oss/javascript/langchain/middleware)。

  有关更多信息，请参阅[状态更新](/oss/javascript/langchain/middleware/custom#state-updates)。
</Note>

### 工具

工具使模型能够与数据库、API 和外部系统交互。您定义和选择工具的方式直接影响模型能否有效完成任务。

#### 定义工具

每个工具都需要一个清晰的名称、描述、参数名称和参数描述。这些不仅仅是元数据——它们指导模型关于何时以及如何使用该工具的推理。

```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const searchOrders = tool(
  async ({ userId, status, limit }) => {
    // 在此实现
  },
  {
    name: "search_orders",
    description: `Search for user orders by status.

    Use this when the user asks about order history or wants to check
    order status. Always filter by the provided status.`,
    schema: z.object({
      userId: z.string().describe("Unique identifier for the user"),
      status: z.enum(["pending", "shipped", "delivered"]).describe("Order status to filter by"),
      limit: z.number().default(10).describe("Maximum number of results to return"),
    }),
  }
);
```

#### 选择工具

并非每个工具都适用于每种情况。工具太多可能会使模型不堪重负（上下文过载）并增加错误；工具太少则会限制能力。动态工具选择根据身份验证状态、用户权限、功能标志或对话阶段调整可用工具集。

<Tabs>
  <Tab title="状态">
    仅在达到某些对话里程碑后启用高级工具：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { createMiddleware } from "langchain";

    const stateBasedTools = createMiddleware({
      name: "StateBasedTools",
      wrapModelCall: (request, handler) => {
        // 从状态读取：检查身份验证和对话长度
        const state = request.state;  // [!code highlight]
        const isAuthenticated = state.authenticated || false;  // [!code highlight]
        const messageCount = state.messages.length;

        let filteredTools = request.tools;

        // 仅在身份验证后启用敏感工具
        if (!isAuthenticated) {
          filteredTools = request.tools.filter(t => t.name.startsWith("public_"));  // [!code highlight]
        } else if (messageCount < 5) {
          filteredTools = request.tools.filter(t => t.name !== "advanced_search");  // [!code highlight]
        }

        return handler({ ...request, tools: filteredTools });  // [!code highlight]
      },
    });
    ```
  </Tab>

  <Tab title="存储">
    根据存储中的用户偏好或功能标志过滤工具：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createMiddleware } from "langchain";

    const contextSchema = z.object({
      userId: z.string(),
    });

    const storeBasedTools = createMiddleware({
      name: "StoreBasedTools",
      contextSchema,
      wrapModelCall: async (request, handler) => {
        const userId = request.runtime.context.userId;  // [!code highlight]

        // 从存储读取：获取用户启用的功能
        const store = request.runtime.store;  // [!code highlight]
        const featureFlags = await store.get(["features"], userId);  // [!code highlight]

        let filteredTools = request.tools;

        if (featureFlags) {
          const enabledFeatures = featureFlags.value?.enabledTools || [];
          filteredTools = request.tools.filter(t => enabledFeatures.includes(t.name));  // [!code highlight]
        }

        return handler({ ...request, tools: filteredTools });  // [!code highlight]
      },
    });
    ```
  </Tab>

  <Tab title="运行时上下文">
    根据运行时上下文中的用户权限过滤工具：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createMiddleware } from "langchain";

    const contextSchema = z.object({
      userRole: z.string(),
    });

    const contextBasedTools = createMiddleware({
      name: "ContextBasedTools",
      contextSchema,
      wrapModelCall: (request, handler) => {
        // 从运行时上下文读取：获取用户角色
        const userRole = request.runtime.context.userRole;  // [!code highlight]

        let filteredTools = request.tools;

        if (userRole === "admin") {
          // 管理员获得所有工具
        } else if (userRole === "editor") {
          filteredTools = request.tools.filter(t => t.name !== "delete_data");  // [!code highlight]
        } else {
          filteredTools = request.tools.filter(t => t.name.startsWith("read_"));  // [!code highlight]
        }

        return handler({ ...request, tools: filteredTools });  // [!code highlight]
      },
    });
    ```
  </Tab>
</Tabs>

有关过滤预注册工具和在运行时注册工具（例如，从 MCP 服务器）的更多信息，请参阅[动态工具](/oss/javascript/langchain/agents#dynamic-tools)。

### 模型

不同的模型具有不同的优势、成本和上下文窗口。为手头的任务选择合适的模型，这可能在智能体运行期间发生变化。

<Tabs>
  <Tab title="状态">
    根据状态中的对话长度使用不同的模型：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { createMiddleware, initChatModel } from "langchain";

    // 在中间件外部初始化模型一次
    const largeModel = initChatModel("claude-sonnet-4-6");
    const standardModel = initChatModel("gpt-5.4");
    const efficientModel = initChatModel("gpt-5.4-mini");

    const stateBasedModel = createMiddleware({
      name: "StateBasedModel",
      wrapModelCall: (request, handler) => {
        // request.messages 是 request.state.messages 的快捷方式
        const messageCount = request.messages.length;  // [!code highlight]
        let model;

        if (messageCount > 20) {
          model = largeModel;
        } else if (messageCount > 10) {
          model = standardModel;
        } else {
          model = efficientModel;
        }

        return handler({ ...request, model });  // [!code highlight]
      },
    });
    ```
  </Tab>

  <Tab title="存储">
    使用存储中用户偏好的模型：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createMiddleware, initChatModel } from "langchain";

    const contextSchema = z.object({
      userId: z.string(),
    });

    // 一次初始化可用模型
    const MODEL_MAP = {
      "gpt-5.4": initChatModel("gpt-5.4"),
      "gpt-5.4-mini": initChatModel("gpt-5.4-mini"),
      "claude-sonnet": initChatModel("claude-sonnet-4-6"),
    };

    const storeBasedModel = createMiddleware({
      name: "StoreBasedModel",
      contextSchema,
      wrapModelCall: async (request, handler) => {
        const userId = request.runtime.context.userId;  // [!code highlight]

        // 从存储读取：获取用户偏好的模型
        const store = request.runtime.store;  // [!code highlight]
        const userPrefs = await store.get(["preferences"], userId);  // [!code highlight]

        let model = request.model;

        if (userPrefs) {
          const preferredModel = userPrefs.value?.preferredModel;
          if (preferredModel && MODEL_MAP[preferredModel]) {
            model = MODEL_MAP[preferredModel];  // [!code highlight]
          }
        }

        return handler({ ...request, model });  // [!code highlight]
      },
    });
    ```
  </Tab>

  <Tab title="运行时上下文">
    根据运行时上下文中的成本限制或环境选择模型：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createMiddleware, initChatModel } from "langchain";

    const contextSchema = z.object({
      costTier: z.string(),
      environment: z.string(),
    });

    // 在中间件外部初始化模型一次
    const premiumModel = initChatModel("claude-sonnet-4-6");
    const standardModel = initChatModel("gpt-5.4");
    const budgetModel = initChatModel("gpt-5.4-mini");

    const contextBasedModel = createMiddleware({
      name: "ContextBasedModel",
      contextSchema,
      wrapModelCall: (request, handler) => {
        // 从运行时上下文读取：成本层级和环境
        const costTier = request.runtime.context.costTier;  // [!code highlight]
        const environment = request.runtime.context.environment;  // [!code highlight]

        let model;

        if (environment === "production" && costTier === "premium") {
          model = premiumModel;
        } else if (costTier === "budget") {
          model = budgetModel;
        } else {
          model = standardModel;
        }

        return handler({ ...request, model });  // [!code highlight]
      },
    });
    ```
  </Tab>
</Tabs>

有关更多示例，请参阅[动态模型](/oss/javascript/langchain/agents#dynamic-model)。

### 响应格式

结构化输出将非结构化文本转换为经过验证的结构化数据。当提取特定字段或为下游系统返回数据时，自由格式文本是不够的。

**工作原理：** 当您提供模式作为响应格式时，模型的最终响应保证符合该模式。智能体运行模型/工具调用循环，直到模型完成调用工具，然后最终响应被强制转换为提供的格式。

#### 定义格式

模式定义指导模型。字段名称、类型和描述精确指定输出应遵循的格式。

```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
import { z } from "zod";

const customerSupportTicket = z.object({
  category: z.enum(["billing", "technical", "account", "product"]).describe(
    "Issue category"
  ),
  priority: z.enum(["low", "medium", "high", "critical"]).describe(
    "Urgency level"
  ),
  summary: z.string().describe(
    "One-sentence summary of the customer's issue"
  ),
  customerSentiment: z.enum(["frustrated", "neutral", "satisfied"]).describe(
    "Customer's emotional tone"
  ),
}).describe("Structured ticket information extracted from customer message");
```

#### 选择格式

动态响应格式选择根据用户偏好、对话阶段或角色调整模式——在早期返回简单格式，随着复杂性增加返回详细格式。

<Tabs>
  <Tab title="状态">
    根据对话状态配置结构化输出：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import { createMiddleware } from "langchain";
    import { z } from "zod";

    const simpleResponse = z.object({
      answer: z.string().describe("A brief answer"),
    });

    const detailedResponse = z.object({
      answer: z.string().describe("A detailed answer"),
      reasoning: z.string().describe("Explanation of reasoning"),
      confidence: z.number().describe("Confidence score 0-1"),
    });

    const stateBasedOutput = createMiddleware({
      name: "StateBasedOutput",
      wrapModelCall: (request, handler) => {
        // request.state 是 request.state.messages 的快捷方式
        const messageCount = request.messages.length;  // [!code highlight]

        let responseFormat;
        if (messageCount < 3) {
          // 早期对话 - 使用简单格式
          responseFormat = simpleResponse; // [!code highlight]
        } else {
          // 已建立的对话 - 使用详细格式
          responseFormat = detailedResponse; // [!code highlight]
        }

        return handler({ ...request, responseFormat });
      },
    });
    ```
  </Tab>

  <Tab title="存储">
    根据存储中的用户偏好配置输出格式：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createMiddleware } from "langchain";

    const contextSchema = z.object({
      userId: z.string(),
    });

    const verboseResponse = z.object({
      answer: z.string().describe("Detailed answer"),
      sources: z.array(z.string()).describe("Sources used"),
    });

    const conciseResponse = z.object({
      answer: z.string().describe("Brief answer"),
    });

    const storeBasedOutput = createMiddleware({
      name: "StoreBasedOutput",
      wrapModelCall: async (request, handler) => {
        const userId = request.runtime.context.userId;  // [!code highlight]

        // 从存储读取：获取用户偏好的响应风格
        const store = request.runtime.store;  // [!code highlight]
        const userPrefs = await store.get(["preferences"], userId);  // [!code highlight]

        const style = userPrefs?.value?.responseStyle || "concise";
        const responseFormat =
          style === "verbose" ? verboseResponse : conciseResponse;  // [!code highlight]

        return handler({
          ...request,
          responseFormat,
        });
      },
    });
    ```
  </Tab>

  <Tab title="运行时上下文">
    根据运行时上下文（如用户角色或环境）配置输出格式：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createMiddleware } from "langchain";

    const contextSchema = z.object({
      userRole: z.string(),
      environment: z.string(),
    });

    const adminResponse = z.object({
      answer: z.string().describe("Answer"),
      debugInfo: z.record(z.any()).describe("Debug information"),
      systemStatus: z.string().describe("System status"),
    });

    const userResponse = z.object({
      answer: z.string().describe("Answer"),
    });

    const contextBasedOutput = createMiddleware({
      name: "ContextBasedOutput",
      wrapModelCall: (request, handler) => {
        // 从运行时上下文读取：用户角色和环境
        const userRole = request.runtime.context.userRole;  // [!code highlight]
        const environment = request.runtime.context.environment;  // [!code highlight]

        let responseFormat;
        if (userRole === "admin" && environment === "production") {
          responseFormat = adminResponse;  // [!code highlight]
        } else {
          responseFormat = userResponse;  // [!code highlight]
        }

        return handler({ ...request, responseFormat });
      },
    });
    ```
  </Tab>
</Tabs>

## 工具上下文

工具的特殊之处在于它们既读取又写入上下文。

在最基本的情况下，当工具执行时，它接收 LLM 的请求参数并返回一条工具消息。工具执行其工作并产生结果。

工具还可以为模型获取重要信息，使其能够执行和完成任务。

### 读取

大多数现实世界的工具需要的不仅仅是 LLM 的参数。它们需要用于数据库查询的用户 ID、用于外部服务的 API 密钥，或用于决策的当前会话状态。工具从状态、存储和运行时上下文读取以访问此信息。

<Tabs>
  <Tab title="状态">
    从状态读取以检查当前会话信息：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createAgent, tool, type ToolRuntime } from "langchain";

    const checkAuthentication = tool(
      async (_, runtime: ToolRuntime) => {
        // 从状态读取：检查当前身份验证状态
        const currentState = runtime.state;
        const isAuthenticated = currentState.authenticated || false;

        if (isAuthenticated) {
          return "User is authenticated";
        } else {
          return "User is not authenticated";
        }
      },
      {
        name: "check_authentication",
        description: "Check if user is authenticated",
        schema: z.object({}),
      }
    );
    ```
  </Tab>

  <Tab title="存储">
    从存储读取以访问持久化的用户偏好：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createAgent, tool, type ToolRuntime } from "langchain";

    const contextSchema = z.object({
      userId: z.string(),
    });

    const getPreference = tool(
      async ({ preferenceKey }, runtime: ToolRuntime) => {
        const userId = runtime.context.userId;

        // 从存储读取：获取现有偏好
        const store = runtime.store;
        const existingPrefs = await store.get(["preferences"], userId);

        if (existingPrefs) {
          const value = existingPrefs.value?.[preferenceKey];
          return value ? `${preferenceKey}: ${value}` : `No preference set for ${preferenceKey}`;
        } else {
          return "No preferences found";
        }
      },
      {
        name: "get_preference",
        description: "Get user preference from Store",
        schema: z.object({
          preferenceKey: z.string(),
        }),
      }
    );
    ```
  </Tab>

  <Tab title="运行时上下文">
    从运行时上下文读取配置，如 API 密钥和用户 ID：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { tool } from "@langchain/core/tools";
    import { createAgent } from "langchain";

    const contextSchema = z.object({
      userId: z.string(),
      apiKey: z.string(),
      dbConnection: z.string(),
    });

    const fetchUserData = tool(
      async ({ query }, runtime: ToolRuntime<any, typeof contextSchema>) => {
        // 从运行时上下文读取：获取 API 密钥和数据库连接
        const { userId, apiKey, dbConnection } = runtime.context;

        // 使用配置获取数据
        const results = await performDatabaseQuery(dbConnection, query, apiKey);

        return `Found ${results.length} results for user ${userId}`;
      },
      {
        name: "fetch_user_data",
        description: "Fetch data using Runtime Context configuration",
        schema: z.object({
          query: z.string(),
        }),
      }
    );

    const agent = createAgent({
      model: "gpt-5.4",
      tools: [fetchUserData],
      contextSchema,
    });
    ```
  </Tab>
</Tabs>

### 写入

工具结果可用于帮助智能体完成给定任务。工具既可以将结果直接返回给模型，也可以更新智能体的记忆，以便为后续步骤提供重要的上下文。

<Tabs>
  <Tab title="状态">
    使用 Command 写入状态以跟踪特定于会话的信息：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { tool } from "@langchain/core/tools";
    import { createAgent } from "langchain";
    import { Command } from "@langchain/langgraph";

    const authenticateUser = tool(
      async ({ password }) => {
        // 执行身份验证
        if (password === "correct") {
          // 写入状态：使用 Command 标记为已验证
          return new Command({
            update: { authenticated: true },
          });
        } else {
          return new Command({ update: { authenticated: false } });
        }
      },
      {
        name: "authenticate_user",
        description: "Authenticate user and update State",
        schema: z.object({
          password: z.string(),
        }),
      }
    );
    ```
  </Tab>

  <Tab title="存储">
    写入存储以跨会话持久化数据：

    ```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    import * as z from "zod";
    import { createAgent, tool, type ToolRuntime } from "langchain";

    const savePreference = tool(
      async ({ preferenceKey, preferenceValue }, runtime: ToolRuntime<any, typeof contextSchema>) => {
        const userId = runtime.context.userId;

        // 读取现有偏好
        const store = runtime.store;
        const existingPrefs = await store.get(["preferences"], userId);

        // 与新偏好合并
        const prefs = existingPrefs?.value || {};
        prefs[preferenceKey] = preferenceValue;

        // 写入存储：保存更新后的偏好
        await store.put(["preferences"], userId, prefs);

        return `Saved preference: ${preferenceKey} = ${preferenceValue}`;
      },
      {
        name: "save_preference",
        description: "Save user preference to Store",
        schema: z.object({
          preferenceKey: z.string(),
          preferenceValue: z.string(),
        }),
      }
    );
    ```
  </Tab>
</Tabs>

有关在工具中访问状态、存储和运行时上下文的全面示例，请参阅[工具](/oss/javascript/langchain/tools)。

## 生命周期上下文

控制核心智能体步骤**之间**发生的事情 - 拦截数据流以实现横切关注点，如摘要、防护栏和日志记录。

正如您在[模型上下文](#模型上下文)和[工具上下文](#工具上下文)中所看到的，[中间件](/oss/javascript/langchain/middleware)是使上下文工程变得实用的机制。中间件允许您钩入智能体生命周期中的任何步骤，并：

1. **更新上下文** - 修改状态和存储以持久化更改、更新对话历史或保存见解
2. **在生命周期中跳转** - 根据上下文移动到智能体周期中的不同步骤（例如，如果满足条件则跳过工具执行，使用修改后的上下文重复模型调用）

<div style={{ display: "flex", justifyContent: "center" }}>
  <img src="https://mintcdn.com/other-405835d4/3NQVGWwcrOYcKZbP/oss/images/middleware_final.png?fit=max&auto=format&n=3NQVGWwcrOYcKZbP&q=85&s=4c4db62fcf650935ce6703625c5aa548" alt="智能体循环中的中间件钩子" className="rounded-lg" width="500" height="560" data-path="oss/images/middleware_final.png" />
</div>

### 示例：摘要

最常见的生命周期模式之一是在对话历史过长时自动压缩。与[模型上下文](#消息)中显示的临时消息修剪不同，摘要**持久地更新状态** - 用保存供所有未来轮次使用的摘要永久替换旧消息。

LangChain 提供了内置的中间件来实现此功能：

```typescript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
import { createAgent, summarizationMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-5.4",
  tools: [...],
  middleware: [
    summarizationMiddleware({
      model: "gpt-5.4-mini",
      trigger: { tokens: 4000 },
      keep: { messages: 20 },
    }),
  ],
});
```

当对话超过令牌限制时，`SummarizationMiddleware` 会自动：

1. 使用单独的 LLM 调用总结较旧的消息
2. 在状态中用摘要消息替换它们（永久）
3. 保留最近的消息以保持上下文

总结的对话历史被永久更新 - 未来的轮次将看到摘要而不是原始消息。

<Note>
  有关内置中间件的完整列表、可用钩子以及如何创建自定义中间件，请参阅[中间件文档](/oss/javascript/langchain/middleware)。
</Note>

## 最佳实践

1. **从简单开始** - 从静态提示词和工具开始，仅在需要时添加动态内容
2. **增量测试** - 一次添加一个上下文工程功能
3. **监控性能** - 跟踪模型调用、令牌使用情况和延迟
4. **使用内置中间件** - 利用 [`SummarizationMiddleware`](/oss/javascript/langchain/middleware#summarization)、[`LLMToolSelectorMiddleware`](/oss/javascript/langchain/middleware#llm-tool-selector) 等。
5. **记录您的上下文策略** - 明确传递了什么上下文以及为什么传递
6. **理解临时与持久**：模型上下文更改是临时的（每次调用），而生命周期上下文更改会持久化到状态

## 相关资源

* [上下文概念概述](/oss/javascript/concepts/context) - 了解上下文类型及其使用场景
* [中间件](/oss/javascript/langchain/middleware) - 完整的中间件指南
* [工具](/oss/javascript/langchain/tools) - 工具创建和上下文访问
* [记忆](/oss/javascript/concepts/memory) - 短期和长期记忆模式
* [智能体](/oss/javascript/langchain/agents) - 核心智能体概念

***

<div className="source-links">
  <Callout icon="terminal-2">
    [将这些文档](/use-these-docs)通过 MCP 连接到 Claude、VSCode 等，以获取实时答案。
  </Callout>

  <Callout icon="edit">
    [在 GitHub 上编辑此页面](https://github.com/langchain-ai/docs/edit/main/src/oss/langchain/context-engineering.mdx) 或 [提交问题](https://github.com/langchain-ai/docs/issues/new/choose)。
  </Callout>
</div>
