如何构建自定义代理脚手架
本文介绍了使用LangChain的create_agent和中间件构建自定义代理脚手架的方法。代理由模型和脚手架组成,脚手架负责将模型连接到真实世界。通过中间件,可以在代理循环的各个阶段插入自定义逻辑、工具、状态管理等,从而实现高度定制化的代理。
构建有用的代理在很大程度上取决于定制化:将代理连接到正确的上下文、数据和环境以完成特定任务。从本质上看,代理是一个模型在循环中调用工具,直到完成任务并返回结果。你也可以将代理定义为:代理 = 模型 + 脚手架。脚手架是围绕模型的框架,将模型连接到真实世界。一个代理的好坏取决于提供给模型的上下文,而脚手架的工作就是在每一步为模型提供正确的上下文。因此,要构建有用的代理,你需要一个擅长为给定任务传递正确上下文的脚手架。
create_agent是LangChain用于构建脚手架的原语。传入模型、工具和系统提示,你就拥有了一个可工作的代理。像Deep Agents和Claude Agent SDK这样的脚手架预装了意见性的中间件堆栈:记忆、上下文管理、沙箱等。它们旨在让你快速获得一个生产就绪的代理,并且在大多数情况下表现良好。但许多代理需要比这些脚手架支持的更细粒度的定制:自定义提示、业务逻辑、护栏等。
create_Agent采用了不同的方法:它故意保持极简。我们的理念与高度可配置的编码代理脚手架Pi类似。create_agent仅实现核心代理循环,并将中间件作为定制化的原语公开。中间件在代理循环的每个步骤中挂接:模型调用前后、工具调用前后、代理启动和关闭时。每个中间件处理一个关注点,并可以与其他中间件自由组合。
中间件允许你通过几个通常协同工作的杠杆为代理添加能力:确定性逻辑、工具、自定义状态和流处理器。确定性逻辑包括业务逻辑、策略执行、动态代理控制等,这些都不能也不应该放在提示中。工具方面,中间件可以处理工具的完整生命周期——设置、拆除、注册——并给代理提供一套干净的工具。自定义状态允许中间件在钩子之间跟踪状态,例如维护计数器、标志或其他在代理运行期间持续存在的值。流处理器可以拦截和转换代理的输出流——过滤事件、注入元数据、将不同事件类型路由到不同消费者。
中间件的优点在于:它允许在代理循环的任何点进行定制,并将相关逻辑捆绑到可组合、可共享的代码单元中。LangChain为最常见的模式提供了预构建的中间件。任何针对你用例的定制都可以通过一个自定义中间件实现。由于每个中间件是隔离的,同一个中间件可以跨组织中的每个代理重用,从而新代理无需重新构建即可继承经过实战检验的行为。
脚手架的工作是在正确的时间为给定任务提供正确的上下文。下表将常见能力映射到支持这些能力的中间件。大多数生产代理最终会同时使用多种中间件,具体取决于代理的需求(是否长时间运行?任务有多复杂?代理的行为有多敏感?等):防止上下文溢出(SummarizationMiddleware, ContextEditingMiddleware)、访问和更新记忆(FilesystemMiddleware, MemoryMiddleware, SkillsMiddleware)、在环境中执行操作(ShellToolMiddleware, FilesystemMiddleware, CodeInterpreterMiddleware)、委托任务(SubAgentMiddleware, AsyncSubAgentMiddleware, TodoListMiddleware)、处理暂时性故障(ToolRetryMiddleware, ModelRetryMiddleware, ModelFallbackMiddleware)、执行策略(PIIMiddleware, HumanInTheLoopMiddleware)、引导代理(HumanInTheLoopMiddleware)、控制成本(ModelCallLimitMiddleware, ToolCallLimitMiddleware, PromptCachingMiddleware)。
任务与脚手架的匹配度决定了你的脚手架与实际任务需求的契合程度:所需的上下文、将遇到的失败、必须执行的策略、操作的环境。客服代理的脚手架与长时间运行的编码代理的脚手架截然不同。我们在LangChain构建的每个代理,包括我们的GTM代理、异步编码代理和无代码代理构建器,都基于create_agent,并配有适合该代理使命的中间件堆栈。最好的代理不仅由强大的模型构建,还由紧密契合任务的脚手架构建。使用create_agent构建自定义脚手架是最简单的方法。