7 月 Agent 探索总结:LangChain 还是自研编排,半年后的再判断

发布时间:2026/7/27 11:04:20
7 月 Agent 探索总结:LangChain 还是自研编排,半年后的再判断 7 月 Agent 探索总结LangChain 还是自研编排半年后的再判断一、半年前的选择题今天有了更明确的答案年初团队面临一个选择用 LangChain 作为 Agent 编排框架还是投入资源自研一套编排引擎。当时的决策是先用 LangChain 快速验证同时保留自研选项。半年过去我们分别在 LangChain 上交付了 4 个 Agent 应用在自研编排器上交付了 2 个。实战数据足够做一次系统的对比判断了。这个对比的意义不在于哪个框架好而在于帮助我们理解 Agent 编排领域真正的工程复杂度在哪里。很多选择在 demo 阶段看不出来到了生产环境才能暴露。二、两个方案的系统性对比2.1 代码层面的差异相同的任务——根据用户自然语言查询调用内部 API 获取数据并生成图表——两个方案在代码上的差异揭示了核心问题。LangChain 方案简化后的核心代码from langchain.agents import initialize_agent, Tool from langchain.memory import ConversationBufferMemory tools [ Tool(namequery_api, funcquery_internal_api, description查询内部数据API), Tool(namegenerate_chart, funcgenerate_chart, description生成数据图表), ] memory ConversationBufferMemory(memory_keychat_history) agent initialize_agent( tools, llm, agentconversational-react-description, memorymemory, verboseTrue ) # 问题一ConversationBufferMemory 无界增长 # 问题二Agent 执行循环不可中断 # 问题三verboseTrue 的日志无法接入生产监控自研编排器方案核心逻辑type AgentEngine struct { tools map[string]Tool memory *BoundedMemory // 基于 Redis List固定容量 planner *ReActPlanner execCtx context.Context // 可取消的执行上下文 } func (e *AgentEngine) Execute(ctx context.Context, query string) (*AgentResult, error) { // 设置整体超时和步骤上限 ctx, cancel : context.WithTimeout(ctx, 60*time.Second) defer cancel() plan : e.planner.CreatePlan(query) result : AgentResult{Steps: make([]StepResult, 0, plan.MaxSteps)} for step : 0; step plan.MaxSteps; step { select { case -ctx.Done(): return result, fmt.Errorf(agent execution cancelled: %w, ctx.Err()) default: } action : e.planner.NextAction(result.Steps) tool, ok : e.tools[action.ToolName] if !ok { return result, fmt.Errorf(tool %s not found, action.ToolName) } // 单步超时保护防止工具调用卡死 stepCtx, stepCancel : context.WithTimeout(ctx, 15*time.Second) toolResult, err : tool.Execute(stepCtx, action.Input) stepCancel() if err ! nil { result.Steps append(result.Steps, StepResult{ Action: action, Error: err.Error(), }) // 容错单步失败不中断整体记录后继续 continue } result.Steps append(result.Steps, StepResult{ Action: action, Output: toolResult, }) } // 压缩历史记忆避免上下文膨胀 e.memory.Compact(result.Steps, 4096) // 限制 4096 Token return result, nil }自研方案多写了约 200 行框架代码但换来了三个 LangChain 做不到的能力执行可取消context 传播、步骤级超时保护不依赖 LLM 的自觉停止、记忆容量硬限制。2.2 生产环境的量化对比六个月运行数据揭示了显著的差异指标LangChain 方案自研编排器Agent 任务成功率82%94%平均单任务 Token 消耗8,2005,400内存泄漏相关事故3 次0 次新 Agent 平均开发周期3 天5 天故障排查平均耗时45 分钟15 分钟框架升级导致的兼容性事故2 次0 次数据的结论是明确的LangChain 在开发效率上有优势快 40%但在生产稳定性上明显不如自研方案。任务成功率差了 12 个百分点主要是 LangChain Agent 在复杂多步骤任务中容易陷入无效循环——反复调用同一个工具但拿不到有效结果直到 Token 耗尽。三、Agent 编排工程的核心复杂度到底在哪里半年的实践表明Agent 编排的真正难点不是如何调用 LLM——这部分 LangChain 和自研方案都能做好。真正的难点是三个工程问题状态管理Agent 是多轮对话 多步操作的叠加状态管理。LangChain 的 ConversationBufferMemory 无界增长在第 10 轮对话时上下文已经膨胀到 6000 Token不仅拖慢推理速度还导致 LLM 在过大上下文中迷失焦点。自研方案用固定容量的滑动窗口 摘要压缩解决了这个问题。中断与恢复Agent 任务可能需要 30-60 秒完成。如果在这个期间上游请求取消或者 LLM 返回了一个格式错误的响应LangChain 没有提供优雅的中断机制。自研方案通过 context.Context 传播取消信号每个步骤执行前都有退出检查。可观测性LangSmith 提供了 Trace 可视化但它的数据是封闭的——无法和现有的 Grafana 告警规则集成。自研方案把 Agent 的每步操作都打上了 OpenTelemetry Span可以直接在现有监控体系中看到 Agent 调用的端到端链路并与微服务的 Trace 关联。四、结论不是二选一是分工明确半年的数据不支持完全放弃 LangChain的极端结论但也不支持全部用 LangChain的天真假设。更务实的做法是根据 Agent 复杂度分层简单链式调用≤3 步、无复杂状态用 LangChain 快速交付性价比高。这类任务 LangChain 的成功率在 95% 以上。多步骤任务≥4 步、分支逻辑、超时敏感用自研编排器。LangChain 在这类场景的成功率骤降到 70% 左右。生产关键路径上的 Agent无论复杂度一律用自研方案。LangChain 框架升级的兼容性问题和内存泄漏风险在关键路径上不可接受。当前团队两个方案并行使用3 个简单 Agent 在 LangChain 上运行4 个生产级 Agent 已迁移到自研编排器。五、总结半年前的选择题今天的答案不是哪个更好而是两者各有适用场景。LangChain 在原型验证和简单链式调用场景仍有价值但在多步骤任务和生产关键路径上自研编排器的稳定性、可观测性和资源管控能力是 LangChain 无法替代的。下半年计划将自研编排器的工具注册中心做成插件化接口降低新 Agent 的开发周期从 5 天缩到 3 天让自研方案也能拥有 LangChain 级别的开发效率。Agent 编排这个领域还远没有到标准答案的阶段我们选择用数据说话而不是跟风选框架。