2026 年,AI Agent 已经从概念验证走向生产落地。据 LangChain 2026 Q1 报告,超过 68% 的企业 LLM 应用采用了某种形式的 Agent 架构,而非简单的单轮问答。但现实是——大多数 Agent 系统在生产环境中表现远不如 Demo,核心原因在于架构设计不合理。本文将从架构模式、工具编排、记忆管理三个维度,深入剖析如何构建真正可靠的 AI Agent 系统。
🏗️ 一、Agent 架构模式对比:选对架构是成功的一半
Agent 的核心问题是:如何让 LLM 有效决策并执行多步任务? 不同架构模式给出了截然不同的答案。
1.1 ReAct 模式:思考-行动循环
ReAct(Reasoning + Acting)是最经典的 Agent 架构。核心思想是让 LLM 在「思考」和「行动」之间交替循环,直到完成任务。
// ReAct Agent 核心循环
async function reactAgent(userQuery, tools, maxSteps = 10) {
const messages = [
{ role: 'system', content: SYSTEM_PROMPT },
{ role: 'user', content: userQuery }
];
for (let step = 0; step < maxSteps; step++) {
// 调用 LLM 进行推理
const response = await llm.chat(messages);
const thought = extractThought(response); // 提取思考过程
const action = extractAction(response); // 提取行动指令
// 如果 LLM 认为任务完成,返回最终答案
if (action.type === 'final_answer') {
return action.content;
}
// 执行工具调用
const toolResult = await executeTool(action.tool, action.input);
// 将结果反馈给 LLM 继续推理
messages.push({ role: 'assistant', content: response });
messages.push({ role: 'tool', content: JSON.stringify(toolResult) });
}
throw new Error('Agent exceeded maximum steps');
}
优势: 实现简单,适合单轮工具调用场景。 劣势: 容易陷入循环,步骤多了容易「迷路」,上下文窗口消耗快。
1.2 Plan-and-Execute 模式:先规划再执行
Plan-and-Execute 将任务拆解为「规划」和「执行」两个独立阶段。Planner 负责生成任务计划,Executor 负责逐步执行,Re-planner 负责根据执行结果调整计划。
// Plan-and-Execute Agent
async function planAndExecuteAgent(userQuery, tools) {
// 阶段 1:生成执行计划
const plan = await planner.generate({
query: userQuery,
availableTools: tools.map(t => t.description)
});
// plan = [
// { id: 1, action: "搜索用户信息", tool: "search_user" },
// { id: 2, action: "获取订单历史", tool: "get_orders", depends: [1] },
// { id: 3, action: "生成分析报告", tool: "generate_report", depends: [1, 2] }
// ]
const results = {};
// 阶段 2:按依赖关系执行
for (const task of topologicalSort(plan)) {
const context = task.depends.map(id => results[id]);
results[task.id] = await executor.run(task, context);
// 阶段 3:检查是否需要重新规划
if (results[task.id].needsReplan) {
const newPlan = await replanner.adjust(plan, results);
return planAndExecuteAgent(userQuery, tools, newPlan); // 递归重新执行
}
}
return results;
}
⚠️ 警告: Plan-and-Execute 模式对 Planner 的能力要求很高。如果计划本身有缺陷,后续执行再精确也无济于济。建议在 Planner prompt 中加入 few-shot 示例。
1.3 三种模式对比
| 维度 | ReAct | Plan-and-Execute | Multi-Agent |
|---|---|---|---|
| 实现复杂度 | ⭐⭐ 低 | ⭐⭐⭐ 中 | ⭐⭐⭐⭐ 高 |
| 任务分解能力 | 弱(隐式) | 强(显式计划) | 最强(专门角色) |
| 上下文效率 | 低(全量传递) | 中(分步传递) | 高(隔离上下文) |
| 错误恢复 | 弱(容易卡死) | 中(可重新规划) | 强(Agent 间监督) |
| Token 消耗 | 高 | 中 | 低(单 Agent 视角) |
| 适用场景 | 简单工具调用 | 复杂多步任务 | 复杂协作任务 |
| 推荐指数 | ✅ 入门首选 | ✅ 生产首选 | ⚠️ 高级场景 |
⚡ 关键结论: 大多数生产场景推荐 Plan-and-Execute 模式。它在复杂度和可靠性之间取得了最佳平衡。ReAct 适合快速原型,Multi-Agent 适合需要专业分工的复杂场景。
🔧 二、工具编排与可靠性工程
Agent 的价值在于调用工具完成任务,但工具调用也是最容易出问题的环节。本节探讨如何构建可靠的工具编排层。
2.1 工具定义与类型安全
工具定义的质量直接决定了 LLM 能否正确调用。一个常见的坑是:工具描述写得太模糊,LLM 选错工具或传错参数。
// ❌ 错误写法:描述模糊,参数含义不清
const badTool = {
name: "search",
description: "搜索",
parameters: {
q: { type: "string" },
n: { type: "number" }
}
};
// ✅ 正确写法:清晰的描述、完整的参数说明、包含示例
const goodTool = {
name: "search_users",
description: "根据条件搜索用户信息。支持按姓名、邮箱、手机号搜索。返回匹配的用户列表,最多返回 50 条结果。",
parameters: {
query: {
type: "string",
description: "搜索关键词,支持模糊匹配。示例:'张三'、'zhangsan@email.com'、'13800138000'"
},
limit: {
type: "number",
description: "返回结果数量上限,默认 10,最大 50",
default: 10,
minimum: 1,
maximum: 50
},
sort_by: {
type: "string",
enum: ["created_at", "name", "last_active"],
description: "排序字段,默认按创建时间倒序",
default: "created_at"
}
},
// 返回值说明同样重要
returns: {
description: "用户列表,每个用户包含 id、name、email、phone、created_at 字段"
}
};
💡 提示: 工具描述中加入「何时不该使用」的说明,能显著减少误调用。例如:「注意:此工具不支持搜索已删除的用户,如需搜索已删除用户请使用 search_deleted_users」。
2.2 工具调用的错误处理与重试
生产环境中,工具调用失败是常态而非异常。网络超时、API 限流、参数错误——每一种都需要妥善处理。
// 生产级工具执行器
class ToolExecutor {
constructor(options = {}) {
this.maxRetries = options.maxRetries ?? 3;
this.timeout = options.timeout ?? 30000;
this.circuitBreaker = new CircuitBreaker({
failureThreshold: 5,
resetTimeout: 60000
});
}
async execute(toolName, params) {
const tool = this.tools.get(toolName);
if (!tool) {
return { success: false, error: `Unknown tool: ${toolName}` };
}
// 参数校验
const validation = tool.validate(params);
if (!validation.valid) {
return {
success: false,
error: `Invalid parameters: ${validation.errors.join(', ')}`,
suggestion: `请检查参数格式。${validation.suggestion || ''}`
};
}
// 熔断器检查
if (this.circuitBreaker.isOpen(toolName)) {
return {
success: false,
error: `Tool ${toolName} is temporarily unavailable (circuit breaker open)`,
retryAfter: this.circuitBreaker.getRetryAfter(toolName)
};
}
// 带重试的执行
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
try {
const result = await Promise.race([
tool.run(params),
this.createTimeout(this.timeout)
]);
this.circuitBreaker.recordSuccess(toolName);
return { success: true, data: result };
} catch (error) {
this.circuitBreaker.recordFailure(toolName);
if (attempt === this.maxRetries) {
return {
success: false,
error: `Tool execution failed after ${this.maxRetries} attempts: ${error.message}`,
shouldRetryWithDifferentApproach: true // 提示 Agent 换个方式
};
}
// 指数退避
await sleep(Math.pow(2, attempt) * 1000);
}
}
}
}
📌 记住: 工具执行失败时,返回的错误信息要对 LLM 友好。不要返回原始的 stack trace,而是返回 LLM 能理解的自然语言错误描述和建议的修复方向。
2.3 并行工具调用优化
当任务涉及多个独立的工具调用时,串行执行会严重拖慢速度。合理利用并行调用可以大幅提升效率。
// 智能并行工具调度器
class ParallelToolScheduler {
// 分析任务依赖关系,自动识别可并行的工具调用
schedule(toolCalls) {
const graph = new DependencyGraph();
// 构建依赖图
for (const call of toolCalls) {
graph.addNode(call.id, call);
for (const dep of call.dependsOn || []) {
graph.addEdge(dep, call.id);
}
}
// 拓扑排序 + 并行执行
const levels = graph.topologicalLevels();
const results = {};
for (const level of levels) {
// 同一层级的任务可以并行执行
const levelResults = await Promise.allSettled(
level.map(async (nodeId) => {
const call = graph.getNode(nodeId);
// 将依赖结果注入到参数中
const resolvedParams = resolveParams(call.params, results);
return { id: nodeId, result: await this.execute(call.tool, resolvedParams) };
})
);
for (const result of levelResults) {
if (result.status === 'fulfilled') {
results[result.value.id] = result.value.result;
} else {
// 单个失败不应阻塞整个流程
results[result.reason.id] = { error: result.reason.message };
}
}
}
return results;
}
}
// 使用示例
const toolCalls = [
{ id: 'user', tool: 'get_user', params: { id: 123 }, dependsOn: [] },
{ id: 'orders', tool: 'get_orders', params: { userId: 123 }, dependsOn: [] },
{ id: 'recommendations', tool: 'get_recommendations', params: { userId: 123 }, dependsOn: [] },
{ id: 'report', tool: 'generate_report', params: {}, dependsOn: ['user', 'orders', 'recommendations'] }
];
// user、orders、recommendations 并行执行,report 等待三者完成后执行
⚡ 关键结论: 并行执行可以将 3 个独立 API 调用的总耗时从 3 秒降低到 1 秒左右。但要注意设置合理的并发上限(建议 5-10),避免触发下游 API 的限流。
🧠 三、记忆管理与上下文工程
Agent 的「智能」很大程度上取决于它能「记住」什么。记忆管理是 Agent 架构中最被低估的环节。
3.1 三层记忆架构
生产级 Agent 通常需要三层记忆:
- 工作记忆(Working Memory) — 当前对话的上下文,存在于 messages 数组中
- 短期记忆(Short-term Memory) — 跨多轮对话的摘要信息,存储在内存或 Redis 中
- 长期记忆(Long-term Memory) — 用户偏好、历史交互模式,存储在向量数据库中
// 三层记忆管理器
class AgentMemoryManager {
constructor(options) {
this.workingMemory = []; // 当前对话 messages
this.shortTermStore = new RedisStore(); // 短期记忆(TTL 24h)
this.longTermStore = new VectorStore(); // 长期记忆(持久化)
this.maxWorkingTokens = options.maxTokens ?? 8000;
}
// 获取完整上下文(组装三层记忆)
async getContext(userId, currentQuery) {
// 1. 工作记忆:当前对话
const working = this.workingMemory;
// 2. 短期记忆:最近的对话摘要
const shortTerm = await this.shortTermStore.get(`session:${userId}`);
// 3. 长期记忆:语义搜索相关的历史记忆
const relevantMemories = await this.longTermStore.similaritySearch({
query: currentQuery,
userId,
topK: 5,
minScore: 0.7
});
// 组装上下文,控制总 token 数
return this.assembleContext(working, shortTerm, relevantMemories);
}
// 对话结束后,提取关键信息存入记忆
async consolidateMemory(userId, conversation) {
// 用 LLM 提取关键信息
const summary = await llm.chat({
messages: [{
role: 'system',
content: '从以下对话中提取关键信息,包括:用户偏好、重要决策、待办事项、关键事实。以 JSON 格式返回。'
}, {
role: 'user',
content: JSON.stringify(conversation)
}]
});
// 存入短期记忆
await this.shortTermStore.set(`session:${userId}`, summary, { ttl: 86400 });
// 提取值得长期保存的信息
const longTermFacts = extractLongTermFacts(summary);
for (const fact of longTermFacts) {
await this.longTermStore.upsert({
userId,
content: fact.content,
embedding: await embed(fact.content),
metadata: { type: fact.type, timestamp: Date.now() }
});
}
}
}
3.2 上下文窗口管理策略
当对话变长时,上下文窗口会被耗尽。简单的截断策略会丢失重要信息,更好的方法是智能压缩。
// ❌ 错误写法:直接截断最旧的消息
function naiveTruncate(messages, maxTokens) {
let total = countTokens(messages);
while (total > maxTokens) {
messages.shift(); // 丢弃最旧的消息,可能丢失关键信息
total = countTokens(messages);
}
return messages;
}
// ✅ 正确写法:分层压缩策略
async function smartCompress(messages, maxTokens) {
let total = countTokens(messages);
if (total <= maxTokens) return messages;
// 第 1 步:压缩工具调用结果(通常占最多 token)
for (const msg of messages) {
if (msg.role === 'tool' && countTokens(msg.content) > 500) {
msg.content = await summarize(msg.content, maxTokens = 200);
}
}
// 第 2 步:将中间轮次的对话压缩为摘要
if (countTokens(messages) > maxTokens) {
const systemMsg = messages[0]; // 保留 system prompt
const recentMsgs = messages.slice(-6); // 保留最近 6 条
const middleMsgs = messages.slice(1, -6); // 中间部分压缩
const summary = await summarize(middleMsgs);
messages = [
systemMsg,
{ role: 'system', content: `[对话历史摘要]\n${summary}` },
...recentMsgs
];
}
// 第 3 步:如果仍然超限,只保留最近 4 条
if (countTokens(messages) > maxTokens) {
messages = [messages[0], ...messages.slice(-4)];
}
return messages;
}
💡 提示: 在压缩对话时,一定要保留
tool_call_id的对应关系。如果压缩掉了工具调用的请求,但保留了响应,会导致 API 报错。建议使用专门的消息配对管理器。
3.3 记忆的检索增强生成(RAG)
长期记忆的最佳实践是结合向量搜索,让 Agent 在需要时自动检索相关信息。
// 带 RAG 的 Agent 记忆检索
async function retrieveRelevantContext(userId, query, conversationHistory) {
// 多路召回策略
const [semanticResults, keywordResults, recentResults] = await Promise.all([
// 语义搜索:理解意图
vectorStore.similaritySearch({
embedding: await embed(query),
filter: { userId },
topK: 5
}),
// 关键词搜索:精确匹配
keywordStore.search({
keywords: extractKeywords(query),
filter: { userId },
topK: 3
}),
// 时间衰减:最近的记忆权重更高
vectorStore.timeDecaySearch({
userId,
halfLife: 7 * 24 * 3600, // 7 天半衰期
topK: 3
})
]);
// 合并去重 + 重排序
const merged = deduplicate([...semanticResults, ...keywordResults, ...recentResults]);
const reranked = await rerank(merged, query, { topK: 5 });
return reranked.map(r => ({
content: r.content,
relevance: r.score,
timestamp: r.metadata.timestamp,
type: r.metadata.type
}));
}
⚡ 关键结论: 记忆管理的核心原则是「宁可少,不可错」。低质量的记忆(过时信息、错误事实)比没有记忆更有害。建议对长期记忆设置置信度阈值(0.7+),并定期清理过时记忆。
🚀 四、生产部署:从 Demo 到上线的最后一公里
Agent 系统从 Demo 到生产,需要解决可观测性、成本控制和安全性三个关键问题。
4.1 可观测性:知道 Agent 在想什么
// Agent 执行追踪器
class AgentTracer {
async trace(execution) {
const trace = {
id: generateId(),
startTime: Date.now(),
userId: execution.userId,
query: execution.query,
steps: [],
tokenUsage: { input: 0, output: 0, total: 0 },
totalCost: 0
};
// Hook into each step
execution.on('step', (step) => {
trace.steps.push({
type: step.type, // 'thought' | 'tool_call' | 'observation'
content: step.content,
tool: step.tool,
duration: step.duration,
tokens: step.tokens
});
trace.tokenUsage.input += step.tokens.input;
trace.tokenUsage.output += step.tokens.output;
trace.totalCost += calculateCost(step.tokens, step.model);
});
execution.on('error', (error) => {
trace.error = { message: error.message, step: trace.steps.length };
});
execution.on('complete', (result) => {
trace.endTime = Date.now();
trace.duration = trace.endTime - trace.startTime;
trace.result = result;
});
// 写入可观测性平台(OpenTelemetry / 自建)
await this.export(trace);
return trace;
}
}
⚠️ 警告: 生产环境中,务必对 Agent 的工具调用设置权限边界。不要让 Agent 拥有无限制的数据库写入权限或 API 调用权限。使用最小权限原则,每个工具只授予必要的权限。
4.2 成本控制实战
Agent 的 Token 消耗是普通 LLM 调用的 5-20 倍。成本控制至关重要。
| 策略 | 节省比例 | 实现难度 | 推荐度 |
|---|---|---|---|
| 工具结果压缩 | 30-50% | ⭐ 低 | ✅ 强烈推荐 |
| 小模型做简单任务 | 40-60% | ⭐⭐ 中 | ✅ 推荐 |
| 缓存高频工具调用 | 20-40% | ⭐ 低 | ✅ 推荐 |
| 限制最大步骤数 | 10-20% | ⭐ 低 | ✅ 必须做 |
| 语义缓存 LLM 响应 | 15-30% | ⭐⭐⭐ 高 | ⚠️ 场景依赖 |
// 多模型路由:根据任务复杂度选择模型
async function routeToModel(task) {
const complexity = await classifyComplexity(task);
if (complexity === 'simple') {
// 简单任务用小模型,成本降低 90%
return { model: 'deepseek-chat', maxTokens: 1024 };
} else if (complexity === 'medium') {
return { model: 'deepseek-chat', maxTokens: 4096 };
} else {
// 复杂推理任务才用大模型
return { model: 'deepseek-reasoner', maxTokens: 8192 };
}
}
✅ 总结与最佳实践清单
构建生产级 AI Agent 系统,核心要点如下:
- ✅ 架构选型: 大多数场景选 Plan-and-Execute,不要上来就搞 Multi-Agent
- ✅ 工具设计: 描述清晰、参数完整、错误信息对 LLM 友好
- ✅ 并行执行: 独立工具调用并行化,但设置并发上限
- ✅ 记忆管理: 三层记忆架构,宁缺毋滥
- ✅ 上下文压缩: 工具结果优先压缩,保留最近对话
- ✅ 成本控制: 多模型路由 + 工具缓存 + 步骤限制
- ✅ 可观测性: 全链路追踪,每次执行都要有 trace
- ✅ 安全边界: 最小权限原则,工具调用必须有权限控制
💡 提示: 推荐使用 MCP(Model Context Protocol) 标准化工具定义和调用,可以获得更好的跨模型兼容性。配合 jsjson.com 开发者工具 进行 JSON 格式化、API 调试等日常开发工作,提升 Agent 开发效率。
构建可靠的 AI Agent 不是一蹴而就的事情。从简单的 ReAct 模式开始,逐步迭代到 Plan-and-Execute,再根据业务需要引入多智能体协作——这是最稳妥的演进路径。记住,Agent 的价值不在于它能做多复杂的事,而在于它能可靠地完成多少事。