> ## Documentation Index
> Fetch the complete documentation index at: https://langchain-zh.cn/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/python/concepts/context) 开始，了解不同类型的上下文及其使用时机。
</Tip>

### 智能体循环

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

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

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

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

### 你可以控制的内容

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

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

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

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

### 数据源

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

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

### 工作原理

LangChain [中间件](/oss/python/langchain/middleware) 是幕后机制，使上下文工程对使用 LangChain 的开发人员变得实用。

中间件允许你挂钩到智能体生命周期的任何步骤并：

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

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

## 模型上下文

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

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

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

  <Card title="工具" icon="tool" href="#tools">
    智能体可用于采取行动的工具。
  </Card>

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

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

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

### 系统提示词

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

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from langchain.agents import create_agent
    from langchain.agents.middleware import dynamic_prompt, ModelRequest

    @dynamic_prompt
    def state_aware_prompt(request: ModelRequest) -> str:
        # request.messages is a shortcut for request.state["messages"]
        message_count = len(request.messages)

        base = "You are a helpful assistant."

        if message_count > 10:
            base += "\nThis is a long conversation - be extra concise."

        return base

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[state_aware_prompt]
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import dynamic_prompt, ModelRequest
    from langgraph.store.memory import InMemoryStore

    @dataclass
    class Context:
        user_id: str

    @dynamic_prompt
    def store_aware_prompt(request: ModelRequest) -> str:
        user_id = request.runtime.context.user_id

        # Read from Store: get user preferences
        store = request.runtime.store
        user_prefs = store.get(("preferences",), user_id)

        base = "You are a helpful assistant."

        if user_prefs:
            style = user_prefs.value.get("communication_style", "balanced")
            base += f"\nUser prefers {style} responses."

        return base

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[store_aware_prompt],
        context_schema=Context,
        store=InMemoryStore()
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import dynamic_prompt, ModelRequest

    @dataclass
    class Context:
        user_role: str
        deployment_env: str

    @dynamic_prompt
    def context_aware_prompt(request: ModelRequest) -> str:
        # Read from Runtime Context: user role and environment
        user_role = request.runtime.context.user_role
        env = request.runtime.context.deployment_env

        base = "You are a helpful assistant."

        if user_role == "admin":
            base += "\nYou have admin access. You can perform all operations."
        elif user_role == "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

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[context_aware_prompt],
        context_schema=Context
    )
    ```
  </Tab>
</Tabs>

### 消息

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

<Tabs>
  <Tab title="状态">
    在相关时将上传文件的上下文注入到状态中：

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from typing import Callable

    @wrap_model_call
    def inject_file_context(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Inject context about files user has uploaded this session."""
        # Read from State: get uploaded files metadata
        uploaded_files = request.state.get("uploaded_files", [])  # [!code highlight]

        if uploaded_files:
            # Build context about available files
            file_descriptions = []
            for file in uploaded_files:
                file_descriptions.append(
                    f"- {file['name']} ({file['type']}): {file['summary']}"
                )

            file_context = f"""Files you have access to in this conversation:
    {chr(10).join(file_descriptions)}

    Reference these files when answering questions."""

            # Inject file context before recent messages
            messages = [  # [!code highlight]
                *request.messages,
                {"role": "user", "content": file_context},
            ]
            request = request.override(messages=messages)  # [!code highlight]

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[inject_file_context]
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from typing import Callable
    from langgraph.store.memory import InMemoryStore

    @dataclass
    class Context:
        user_id: str

    @wrap_model_call
    def inject_writing_style(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Inject user's email writing style from Store."""
        user_id = request.runtime.context.user_id  # [!code highlight]

        # Read from Store: get user's writing style examples
        store = request.runtime.store  # [!code highlight]
        writing_style = store.get(("writing_style",), user_id)  # [!code highlight]

        if writing_style:
            style = writing_style.value
            # Build style guide from stored examples
            style_context = f"""Your writing style:
    - Tone: {style.get('tone', 'professional')}
    - Typical greeting: "{style.get('greeting', 'Hi')}"
    - Typical sign-off: "{style.get('sign_off', 'Best')}"
    - Example email you've written:
    {style.get('example_email', '')}"""

            # Append at end - models pay more attention to final messages
            messages = [
                *request.messages,
                {"role": "user", "content": style_context}
            ]
            request = request.override(messages=messages)  # [!code highlight]

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[inject_writing_style],
        context_schema=Context,
        store=InMemoryStore()
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from typing import Callable

    @dataclass
    class Context:
        user_jurisdiction: str
        industry: str
        compliance_frameworks: list[str]

    @wrap_model_call
    def inject_compliance_rules(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Inject compliance constraints from Runtime Context."""
        # Read from Runtime Context: get compliance requirements
        jurisdiction = request.runtime.context.user_jurisdiction  # [!code highlight]
        industry = request.runtime.context.industry  # [!code highlight]
        frameworks = request.runtime.context.compliance_frameworks  # [!code highlight]

        # Build compliance constraints
        rules = []
        if "GDPR" in frameworks:
            rules.append("- Must obtain explicit consent before processing personal data")
            rules.append("- Users have right to data deletion")
        if "HIPAA" in frameworks:
            rules.append("- Cannot share patient health information without authorization")
            rules.append("- Must use secure, encrypted communication")
        if industry == "finance":
            rules.append("- Cannot provide financial advice without proper disclaimers")

        if rules:
            compliance_context = f"""Compliance requirements for {jurisdiction}:
    {chr(10).join(rules)}"""

            # Append at end - models pay more attention to final messages
            messages = [
                *request.messages,
                {"role": "user", "content": compliance_context}
            ]
            request = request.override(messages=messages)  # [!code highlight]

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[inject_compliance_rules],
        context_schema=Context
    )
    ```
  </Tab>
</Tabs>

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

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

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

  * 从 `wrap_model_call` 返回带有 \[`Command`] 的 \[`ExtendedModelResponse`]，以从模型调用层注入状态更新。
  * 使用生命周期钩子如 `before_model`、`after_model` 或 `wrap_tool_call`（用于工具返回）来更新对话历史。有关更多详细信息，请参阅 [中间件文档](/oss/python/langchain/middleware)。

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

### 工具

工具让模型能够与数据库、API 和外部系统交互。你如何定义和选择工具直接影响模型能否有效完成任务。

#### 定义工具

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

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
from langchain.tools import tool

@tool(parse_docstring=True)
def search_orders(
    user_id: str,
    status: str,
    limit: int = 10
) -> str:
    """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.

    Args:
        user_id: Unique identifier for the user
        status: Order status: 'pending', 'shipped', or 'delivered'
        limit: Maximum number of results to return
    """
    # Implementation here
    pass
```

#### 选择工具

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

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from typing import Callable

    @wrap_model_call
    def state_based_tools(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Filter tools based on conversation State."""
        # Read from State: check if user has authenticated
        state = request.state  # [!code highlight]
        is_authenticated = state.get("authenticated", False)  # [!code highlight]
        message_count = len(state["messages"])

        # Only enable sensitive tools after authentication
        if not is_authenticated:
            tools = [t for t in request.tools if t.name.startswith("public_")]
            request = request.override(tools=tools)  # [!code highlight]
        elif message_count < 5:
            # Limit tools early in conversation
            tools = [t for t in request.tools if t.name != "advanced_search"]
            request = request.override(tools=tools)  # [!code highlight]

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[public_search, private_search, advanced_search],
        middleware=[state_based_tools]
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from typing import Callable
    from langgraph.store.memory import InMemoryStore

    @dataclass
    class Context:
        user_id: str

    @wrap_model_call
    def store_based_tools(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Filter tools based on Store preferences."""
        user_id = request.runtime.context.user_id

        # Read from Store: get user's enabled features
        store = request.runtime.store
        feature_flags = store.get(("features",), user_id)

        if feature_flags:
            enabled_features = feature_flags.value.get("enabled_tools", [])
            # Only include tools that are enabled for this user
            tools = [t for t in request.tools if t.name in enabled_features]
            request = request.override(tools=tools)

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[search_tool, analysis_tool, export_tool],
        middleware=[store_based_tools],
        context_schema=Context,
        store=InMemoryStore()
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from typing import Callable

    @dataclass
    class Context:
        user_role: str

    @wrap_model_call
    def context_based_tools(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Filter tools based on Runtime Context permissions."""
        # Read from Runtime Context: get user role
        user_role = request.runtime.context.user_role

        if user_role == "admin":
            # Admins get all tools
            pass
        elif user_role == "editor":
            # Editors can't delete
            tools = [t for t in request.tools if t.name != "delete_data"]
            request = request.override(tools=tools)
        else:
            # Viewers get read-only tools
            tools = [t for t in request.tools if t.name.startswith("read_")]
            request = request.override(tools=tools)

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[read_data, write_data, delete_data],
        middleware=[context_based_tools],
        context_schema=Context
    )
    ```
  </Tab>
</Tabs>

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

### 模型

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

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from langchain.chat_models import init_chat_model
    from typing import Callable

    # Initialize models once outside the middleware
    large_model = init_chat_model("claude-sonnet-4-6")
    standard_model = init_chat_model("gpt-4.1")
    efficient_model = init_chat_model("gpt-4.1-mini")

    @wrap_model_call
    def state_based_model(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Select model based on State conversation length."""
        # request.messages is a shortcut for request.state["messages"]
        message_count = len(request.messages)  # [!code highlight]

        if message_count > 20:
            # Long conversation - use model with larger context window
            model = large_model
        elif message_count > 10:
            # Medium conversation
            model = standard_model
        else:
            # Short conversation - use efficient model
            model = efficient_model

        request = request.override(model=model)  # [!code highlight]

        return handler(request)

    agent = create_agent(
        model="gpt-4.1-mini",
        tools=[...],
        middleware=[state_based_model]
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from langchain.chat_models import init_chat_model
    from typing import Callable
    from langgraph.store.memory import InMemoryStore

    @dataclass
    class Context:
        user_id: str

    # Initialize available models once
    MODEL_MAP = {
        "gpt-4.1": init_chat_model("gpt-4.1"),
        "gpt-4.1-mini": init_chat_model("gpt-4.1-mini"),
        "claude-sonnet": init_chat_model("claude-sonnet-4-6"),
    }

    @wrap_model_call
    def store_based_model(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Select model based on Store preferences."""
        user_id = request.runtime.context.user_id

        # Read from Store: get user's preferred model
        store = request.runtime.store
        user_prefs = store.get(("preferences",), user_id)

        if user_prefs:
            preferred_model = user_prefs.value.get("preferred_model")
            if preferred_model and preferred_model in MODEL_MAP:
                request = request.override(model=MODEL_MAP[preferred_model])

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[store_based_model],
        context_schema=Context,
        store=InMemoryStore()
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from langchain.chat_models import init_chat_model
    from typing import Callable

    @dataclass
    class Context:
        cost_tier: str
        environment: str

    # Initialize models once outside the middleware
    premium_model = init_chat_model("claude-sonnet-4-6")
    standard_model = init_chat_model("gpt-4.1")
    budget_model = init_chat_model("gpt-4.1-mini")

    @wrap_model_call
    def context_based_model(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Select model based on Runtime Context."""
        # Read from Runtime Context: cost tier and environment
        cost_tier = request.runtime.context.cost_tier
        environment = request.runtime.context.environment

        if environment == "production" and cost_tier == "premium":
            # Production premium users get best model
            model = premium_model
        elif cost_tier == "budget":
            # Budget tier gets efficient model
            model = budget_model
        else:
            # Standard tier
            model = standard_model

        request = request.override(model=model)

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[context_based_model],
        context_schema=Context
    )
    ```
  </Tab>
</Tabs>

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

### 响应格式

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

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

#### 定义格式

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

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
from pydantic import BaseModel, Field

class CustomerSupportTicket(BaseModel):
    """Structured ticket information extracted from customer message."""

    category: str = Field(
        description="Issue category: 'billing', 'technical', 'account', or 'product'"
    )
    priority: str = Field(
        description="Urgency level: 'low', 'medium', 'high', or 'critical'"
    )
    summary: str = Field(
        description="One-sentence summary of the customer's issue"
    )
    customer_sentiment: str = Field(
        description="Customer's emotional tone: 'frustrated', 'neutral', or 'satisfied'"
    )
```

#### 选择格式

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

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from pydantic import BaseModel, Field
    from typing import Callable

    class SimpleResponse(BaseModel):
        """Simple response for early conversation."""
        answer: str = Field(description="A brief answer")

    class DetailedResponse(BaseModel):
        """Detailed response for established conversation."""
        answer: str = Field(description="A detailed answer")
        reasoning: str = Field(description="Explanation of reasoning")
        confidence: float = Field(description="Confidence score 0-1")

    @wrap_model_call
    def state_based_output(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Select output format based on State."""
        # request.messages is a shortcut for request.state["messages"]
        message_count = len(request.messages)  # [!code highlight]

        if message_count < 3:
            # Early conversation - use simple format
            request = request.override(response_format=SimpleResponse)  # [!code highlight]
        else:
            # Established conversation - use detailed format
            request = request.override(response_format=DetailedResponse)  # [!code highlight]

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[state_based_output]
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from pydantic import BaseModel, Field
    from typing import Callable
    from langgraph.store.memory import InMemoryStore

    @dataclass
    class Context:
        user_id: str

    class VerboseResponse(BaseModel):
        """Verbose response with details."""
        answer: str = Field(description="Detailed answer")
        sources: list[str] = Field(description="Sources used")

    class ConciseResponse(BaseModel):
        """Concise response."""
        answer: str = Field(description="Brief answer")

    @wrap_model_call
    def store_based_output(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Select output format based on Store preferences."""
        user_id = request.runtime.context.user_id

        # Read from Store: get user's preferred response style
        store = request.runtime.store
        user_prefs = store.get(("preferences",), user_id)

        if user_prefs:
            style = user_prefs.value.get("response_style", "concise")
            if style == "verbose":
                request = request.override(response_format=VerboseResponse)
            else:
                request = request.override(response_format=ConciseResponse)

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[store_based_output],
        context_schema=Context,
        store=InMemoryStore()
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.agents import create_agent
    from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
    from pydantic import BaseModel, Field
    from typing import Callable

    @dataclass
    class Context:
        user_role: str
        environment: str

    class AdminResponse(BaseModel):
        """Response with technical details for admins."""
        answer: str = Field(description="Answer")
        debug_info: dict = Field(description="Debug information")
        system_status: str = Field(description="System status")

    class UserResponse(BaseModel):
        """Simple response for regular users."""
        answer: str = Field(description="Answer")

    @wrap_model_call
    def context_based_output(
        request: ModelRequest,
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        """Select output format based on Runtime Context."""
        # Read from Runtime Context: user role and environment
        user_role = request.runtime.context.user_role
        environment = request.runtime.context.environment

        if user_role == "admin" and environment == "production":
            # Admins in production get detailed output
            request = request.override(response_format=AdminResponse)
        else:
            # Regular users get simple output
            request = request.override(response_format=UserResponse)

        return handler(request)

    agent = create_agent(
        model="gpt-4.1",
        tools=[...],
        middleware=[context_based_output],
        context_schema=Context
    )
    ```
  </Tab>
</Tabs>

## 工具上下文

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

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

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

### 读取

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

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from langchain.tools import tool, ToolRuntime
    from langchain.agents import create_agent

    @tool
    def check_authentication(
        runtime: ToolRuntime
    ) -> str:
        """Check if user is authenticated."""
        # Read from State: check current auth status
        current_state = runtime.state
        is_authenticated = current_state.get("authenticated", False)

        if is_authenticated:
            return "User is authenticated"
        else:
            return "User is not authenticated"

    agent = create_agent(
        model="gpt-4.1",
        tools=[check_authentication]
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.tools import tool, ToolRuntime
    from langchain.agents import create_agent
    from langgraph.store.memory import InMemoryStore

    @dataclass
    class Context:
        user_id: str

    @tool
    def get_preference(
        preference_key: str,
        runtime: ToolRuntime[Context]
    ) -> str:
        """Get user preference from Store."""
        user_id = runtime.context.user_id

        # Read from Store: get existing preferences
        store = runtime.store
        existing_prefs = store.get(("preferences",), user_id)

        if existing_prefs:
            value = existing_prefs.value.get(preference_key)
            return f"{preference_key}: {value}" if value else f"No preference set for {preference_key}"
        else:
            return "No preferences found"

    agent = create_agent(
        model="gpt-4.1",
        tools=[get_preference],
        context_schema=Context,
        store=InMemoryStore()
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.tools import tool, ToolRuntime
    from langchain.agents import create_agent

    @dataclass
    class Context:
        user_id: str
        api_key: str
        db_connection: str

    @tool
    def fetch_user_data(
        query: str,
        runtime: ToolRuntime[Context]
    ) -> str:
        """Fetch data using Runtime Context configuration."""
        # Read from Runtime Context: get API key and DB connection
        user_id = runtime.context.user_id
        api_key = runtime.context.api_key
        db_connection = runtime.context.db_connection

        # Use configuration to fetch data
        results = perform_database_query(db_connection, query, api_key)

        return f"Found {len(results)} results for user {user_id}"

    agent = create_agent(
        model="gpt-4.1",
        tools=[fetch_user_data],
        context_schema=Context
    )

    # Invoke with runtime context
    result = agent.invoke(
        {"messages": [{"role": "user", "content": "Get my data"}]},
        context=Context(
            user_id="user_123",
            api_key="sk-...",
            db_connection="postgresql://..."
        )
    )
    ```
  </Tab>
</Tabs>

### 写入

工具结果可用于帮助智能体完成给定任务。工具既可以直接向模型返回结果，也可以更新智能体的内存，以便将来步骤可以使用重要上下文。

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from langchain.tools import tool, ToolRuntime
    from langchain.agents import create_agent
    from langgraph.types import Command

    @tool
    def authenticate_user(
        password: str,
        runtime: ToolRuntime
    ) -> Command:
        """Authenticate user and update State."""
        # Perform authentication (simplified)
        if password == "correct":
            # Write to State: mark as authenticated using Command
            return Command(
                update={"authenticated": True},
            )
        else:
            return Command(update={"authenticated": False})

    agent = create_agent(
        model="gpt-4.1",
        tools=[authenticate_user]
    )
    ```
  </Tab>

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

    ```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
    from dataclasses import dataclass
    from langchain.tools import tool, ToolRuntime
    from langchain.agents import create_agent
    from langgraph.store.memory import InMemoryStore

    @dataclass
    class Context:
        user_id: str

    @tool
    def save_preference(
        preference_key: str,
        preference_value: str,
        runtime: ToolRuntime[Context]
    ) -> str:
        """Save user preference to Store."""
        user_id = runtime.context.user_id

        # Read existing preferences
        store = runtime.store
        existing_prefs = store.get(("preferences",), user_id)

        # Merge with new preference
        prefs = existing_prefs.value if existing_prefs else {}
        prefs[preference_key] = preference_value

        # Write to Store: save updated preferences
        store.put(("preferences",), user_id, prefs)

        return f"Saved preference: {preference_key} = {preference_value}"

    agent = create_agent(
        model="gpt-4.1",
        tools=[save_preference],
        context_schema=Context,
        store=InMemoryStore()
    )
    ```
  </Tab>
</Tabs>

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

## 生命周期上下文

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

正如你在 [模型上下文](#model-context) 和 [工具上下文](#tool-context) 中所见，[中间件](/oss/python/langchain/middleware) 是使上下文工程实用的机制。中间件允许你挂钩到智能体生命周期的任何步骤并：

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

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

### 示例：摘要

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

LangChain 为此提供了内置中间件：

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware

agent = create_agent(
    model="gpt-4.1",
    tools=[...],
    middleware=[
        SummarizationMiddleware(
            model="gpt-4.1-mini",
            trigger={"tokens": 4000},
            keep={"messages": 20},
        ),
    ],
)
```

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

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

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

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

## 最佳实践

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

## 相关资源

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

***

<div className="source-links">
  <Callout icon="edit">
    [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/i18n\zh-CN\oss\langchain\context-engineering.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).
  </Callout>

  <Callout icon="terminal-2">
    [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers.
  </Callout>
</div>
