概览
构建代理(或任何 LLM 应用)的难点在于让它们足够可靠。它们可能适合原型,但在真实用例中经常失败。代理为什么会失败?
代理失败时,通常是因为代理内部的 LLM 调用采取了错误操作,或者没有按预期行动。LLM 失败通常有两个原因:- 底层 LLM 的能力不足
- 没有向 LLM 传入“正确”的上下文
代理循环
典型的代理循环包含两个主要步骤:- Model call:使用 prompt 和可用工具调用 LLM,返回响应或执行工具的请求
- Tool execution:执行 LLM 请求的工具,并返回工具结果

你可以控制什么
如需构建可靠代理,你需要控制代理循环每一步中发生的事情,以及步骤之间发生的事情。| 上下文类型 | 你控制什么 | 临时还是持久 |
|---|---|---|
| Model Context | 传入模型调用的内容(指令、消息历史、工具、响应格式) | 临时 |
| Tool Context | 工具可以访问和产生的内容(对 state、store、runtime context 的读写) | 持久 |
| Life-cycle Context | 模型调用和工具调用之间发生的事情(摘要、guardrails、日志记录等) | 持久 |
临时上下文
LLM 在单次调用中看到的内容。你可以修改 messages、tools 或 prompts,而不改变 state 中保存的内容。
持久上下文
跨轮次保存在 state 中的内容。Life-cycle hooks 和工具写入会永久修改这些内容。
数据源
在整个过程中,代理会访问(读取/写入)不同的数据源:| 数据源 | 也称为 | 范围 | 示例 |
|---|---|---|---|
| Runtime Context | 静态配置 | 对话范围 | 用户 ID、API keys、数据库连接、权限、环境设置 |
| State | 短期记忆 | 对话范围 | 当前 messages、上传文件、认证状态、工具结果 |
| Store | 长期记忆 | 跨对话 | 用户偏好、提取的洞察、记忆、历史数据 |
工作原理
LangChain middleware 是底层机制,使使用 LangChain 的开发者能够实际落地 context engineering。 Middleware 允许你挂接到代理生命周期中的任意步骤,并:- 更新上下文
- 跳转到代理生命周期中的不同步骤
Model context
控制每次模型调用传入的内容,包括指令、可用工具、使用哪个模型以及输出格式。这些决策会直接影响可靠性和成本。System Prompt
开发者提供给 LLM 的基础指令。
Messages
发送给 LLM 的完整 messages 列表(对话历史)。
Tools
代理可访问的、用于执行操作的实用工具。
Model
实际调用的模型(包括配置)。
Response Format
模型最终响应的 schema 规范。
System Prompt
System prompt 会设置 LLM 的行为和能力。不同用户、上下文或对话阶段需要不同指令。成功的代理会利用记忆、偏好和配置,为当前对话状态提供正确指令。- State
- Store
- Runtime Context
从 state 访问消息数量或对话上下文:
Messages
Messages 组成了发送给 LLM 的 prompt。 管理 messages 的内容非常关键,这可以确保 LLM 拥有正确的信息来给出高质量响应。- State
- Store
- Runtime Context
当上传文件上下文与当前查询相关时,从 State 注入该上下文:
临时和持久的 message 更新:上面的示例使用
wrap_model_call 进行临时更新,即修改单次调用发送给模型的 messages,而不改变 state 中保存的内容。如需进行会修改 state 的持久更新,可以:- 从
wrapModelCall直接返回Command,从模型调用层注入 state 更新。 - 使用
beforeModel、afterModel或wrapToolCall(用于工具返回)等 life-cycle hooks 更新对话历史。更多详情请参阅 middleware documentation。
Tools
Tools 让模型能够与数据库、API 和外部系统交互。你如何定义和选择 tools,会直接影响模型能否有效完成任务。定义 tools
每个 tool 都需要清晰的名称、描述、参数名称和参数描述。这些不仅是 metadata,它们会引导模型推理何时以及如何使用该工具。选择 tools
并非每个 tool 都适合所有场景。工具太多可能会压垮模型(上下文过载)并增加错误;工具太少则会限制能力。动态工具选择会根据认证状态、用户权限、feature flags 或对话阶段调整可用工具集。- State
- Store
- Runtime Context
仅在达到特定对话里程碑后启用高级工具:
Model
不同模型有不同优势、成本和上下文窗口。请为当前任务选择合适模型,该选择可能会在代理运行期间变化。- State
- Store
- Runtime Context
根据 State 中的对话长度使用不同模型:
Response format
Structured output 会将非结构化文本转换为经过验证的结构化数据。当需要提取特定字段或为下游系统返回数据时,自由格式文本并不足够。 工作原理: 当你提供一个 schema 作为响应格式时,模型的最终响应会保证符合该 schema。代理会运行模型/工具调用循环,直到模型完成工具调用,然后将最终响应强制转换为所提供的格式。定义格式
Schema 定义会引导模型。字段名称、类型和描述会明确指定输出应遵循的格式。选择格式
动态响应格式选择会根据用户偏好、对话阶段或角色调整 schema,在早期返回简单格式,并随着复杂度增加返回详细格式。- State
- Store
- Runtime Context
根据对话状态配置 structured output:
Tool context
Tools 的特殊之处在于它们既会读取上下文,也会写入上下文。 在最基本的情况下,工具执行时会接收 LLM 的请求参数,并返回一条工具消息。工具完成自己的工作并生成结果。 Tools 也可以为模型获取重要信息,使模型能够执行并完成任务。读取
大多数真实世界的 tools 需要的不只是 LLM 参数。它们可能需要用于数据库查询的用户 ID、用于外部服务的 API keys,或用于决策的当前会话状态。Tools 会从 state、store 和 runtime context 中读取这些信息。- State
- Store
- Runtime Context
从 State 读取信息,以检查当前会话信息:
写入
工具结果可用于帮助代理完成给定任务。Tools 既可以直接向模型返回结果,也可以更新代理记忆,让重要上下文可供后续步骤使用。- State
- Store
使用 Command 写入 State,以追踪会话专属信息:
Life-cycle context
控制核心代理步骤之间发生的事情,即拦截数据流以实现摘要、guardrails 和日志记录等横切关注点。 如你在 Model Context 和 Tool Context 中所见,middleware 是让 context engineering 可落地的机制。Middleware 允许你挂接到代理生命周期中的任意步骤,并执行以下操作之一:- 更新上下文:修改 state 和 store 以持久化更改、更新对话历史或保存洞察
- 在生命周期中跳转:根据上下文移动到代理循环中的不同步骤,例如在满足条件时跳过工具执行,或使用修改后的上下文重复模型调用

示例:摘要
最常见的 life-cycle 模式之一,是在对话历史过长时自动压缩它。与 Model Context 中展示的临时消息裁剪不同,摘要会持久更新 state,即使用摘要永久替换旧 messages,并保存供所有未来轮次使用。 LangChain 为此提供了内置 middleware:SummarizationMiddleware 会自动:
- 使用单独的 LLM 调用总结较早 messages
- 在 State 中用摘要 message 替换它们(永久替换)
- 保留最近 messages 作为上下文
如需查看内置 middleware、可用 hooks 以及如何创建自定义 middleware 的完整列表,请参阅 Middleware documentation。
最佳实践
- 从简单开始:先使用静态 prompts 和 tools,仅在需要时添加动态逻辑
- 增量测试:一次只添加一个 context engineering 功能
- 监控性能:追踪模型调用、token 用量和延迟
- 使用内置 middleware:利用
SummarizationMiddleware、LLMToolSelectorMiddleware等 - 记录上下文策略:清楚说明传递了什么上下文以及为什么传递
- 理解临时和持久的区别:Model context 更改是临时的(按调用生效),而 life-cycle context 更改会持久保存到 state
相关资源
- Context conceptual overview:了解上下文类型以及何时使用它们
- Middleware:完整 middleware 指南
- Tools:工具创建和上下文访问
- Memory:短期记忆和长期记忆模式
- Agents:核心代理概念
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

