ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Agent开发必懂:插槽化架构设计的七个核心模块

Agent开发必懂:插槽化架构设计的七个核心模块

最近好几个朋友跑来问我 Agent 到底怎么入门,我每次都先泼一盆冷水:别急着把 LangChain、Dify、CrewAI 这些框架全装上,先想想你的 Agent 身上需要留几个“插槽”。为什么这么说?因为 Agent 开发本质上已经从“写一个问答脚本”变成了“组装一台电脑”。你把模型当成 CPU、把工具当成显卡、把记忆当成硬盘、把编排当成主板上的总线,一切能力都是散件,而架构的价值,就体现在那些提前预留好的插槽上。

DeepAgents 这类深度智能体系统尤其如此。它不是“用户问一句、模型答一句”的单轮对话,而是要把一个大任务拆成若干子任务、调多个工具、跑多步推理、跨会话保留状态。这样的系统要是把所有组件焊死在业务代码里,改一个模型、加一个工具,都等于重写一遍。所以我特别强调“前置介绍”这个词——真正动手写代码之前,先想清楚有哪些扩展点、每个扩展点的接口长什么样、默认实现用什么。这篇文章就是一份插槽规划说明书,适合两种人看:一是正准备从零搭建 Agent 的开发者,二是已经在写 Agent 但被各种“改需求就返工”折磨的人。

1. 为什么 Agent 开发越来越像装机

1.1 主板、插槽和即插即用

我前阵子帮朋友装了台电脑,装到一半突然发现,装机思路和设计 Agent 架构几乎是同一套逻辑。主板就是你的核心运行时,CPU 插槽对应模型接口,内存插槽对应上下文窗口,显卡插槽对应工具调用能力,M.2 硬盘位则对应记忆存储。一块好的主板不会把 CPU 焊死在板子上,它会留出标准化插槽,让你以后想升级就升级、想换牌子就换牌子。

Agent 也一样。模型、记忆、工具、编排、技能、安全、观测,这七类能力就是散件。如果你在代码里直接写openai.ChatCompletion.create(...),然后在下一行又硬编码一个if action == "query_order",那这些“散件”就变成了一坨焊死的电路。Demo 阶段确实跑得快,但只要业务一变化,比如把模型从 A 家换成 B 家、加一个新的订单查询接口、或者把记忆从内存换成向量库,你就得顺着调用链一层层去改。

插槽的意义,就是拆开这些耦合。你不需要知道未来会插什么牌子的“显卡”,只需要在主板设计阶段把 PCIe 接口留好,长度、速率、供电协议都标准化,后面所有硬件按这个规范造就行。Agent 框架的价值,说白了就是帮你把“主板”做好,而不是帮你把所有“硬件”都焊进去。

1.2 DeepAgents 为什么要把插槽放在前置阶段

DeepAgents 比普通 Chatbot 更依赖插槽,因为它本质上是一个“深度任务执行系统”。你可以把普通 Agent 想成一台家用电脑,装好就能用;而 DeepAgents 更像一台工作站,它会同时跑多个虚拟机、接多块 GPU、做数据渲染,任何一块硬件出问题,都会拖垮整个流程。

一个典型的 DeepAgents 任务是这样的:先接收用户目标,然后规划出几个子任务,每个子任务可能对应一个专用的小模型、一组特定的工具、一段独特的提示词技能。执行过程中还要不断检查中间结果,错了就回头重试。最后把多个子任务的结果汇总,再生成最终回复。整个过程涉及大量组件交替工作,任何一个环节都需要一个清晰边界。如果你没在设计阶段把模型插槽、工具插槽、编排插槽全部定义好,运行时就只能靠一堆全局变量和if-else硬撑,越撑越乱。

所以“前置介绍”这四个字特别重要。它意味着你还在画主板图纸的阶段,就要把所有插槽的位置、针脚定义、供电标准写清楚。先有协议,再有实现;先有清单,再买硬件。顺序一旦反了,后面全是返工。

2. Agent 身上必须预留的七个核心插槽

2.1 模型插槽:最底层也是最先定的槽位

所有 Agent 的分支都从模型插槽开始。它是系统里最先要定下来的接口,因为模型负责理解意图、拆解任务、决定调用哪个工具,整个系统等于围绕模型转。模型插槽的边界其实已经很成熟了,OpenAI 的 ChatCompletion 消息格式——system、user、assistant、tool——已经成了事实标准,大多数本地模型服务也都兼容这套格式。所以最稳妥的做法,就是把模型插槽定义成“输入一组标准消息列表,输出一个模型响应”。

为什么要刻意留这一层?因为模型选择一定不是一成不变的。你很可能先在云端模型上验证效果,再切到私有化部署;或者像 DeepAgents 常见做法那样,用一个便宜的小模型做路由、派发任务,用一个大模型做最终推理。如果模型插槽做得好,切换成本就只是改配置里的provider和model_name字段,上层逻辑完全不动。

这里有个必须留意的细节:模型之间能力差异很大。有的模型支持 Function Calling,有的模型会假装支持但结果不稳定,有的模型完全没有系统提示词概念。我在模型插槽里会额外加一个能力探测接口,返回当前模型是否支持工具调用、最大上下文长度、是否支持结构化输出。后面所有编排逻辑都要先查这个能力表,再决定走哪条路径。

2.2 记忆插槽:让 Agent 记得住上一秒和上个月

记忆是 Agent 最容易做乱的部分。很多团队把记忆简单理解成“把一个 list 存在内存里”,结果对话一长就爆上下文,或者换个服务进程之后什么都忘了。真实的 Agent 需要三类记忆:短期记忆负责最近几轮对话,长期记忆负责业务知识库、用户偏好、历史工单,工作状态记忆负责记录任务进度、中间结果、子任务完成情况。

记忆插槽至少要提供四类操作:保存、读取、搜索、清理。短期记忆可以用内存或者 Redis 实现,长期记忆基本都要上向量库,工作状态记忆更适合放数据库或对象存储。插槽要做的,就是把“存哪里、怎么检索”这些实现细节和对话主流程彻底解耦。替换记忆实现的时候,上层代码不应该感知任何差异。

我做过一个客服机器人,用户上周刚反馈过发票问题,这周又回来问订单状态。如果记忆插槽接的是向量库,Agent 在生成回复前会先检索历史记录,自动关联到“这位用户上次发票没开成功”这个上下文,回答就会精准很多。这个能力不是模型天生自带的,完全是记忆插槽给的。所以记忆插槽在设计阶段就要想清楚:你的业务需不需要跨会话记忆?如果需要,长期记忆的检索维度是什么?按用户 ID、按会话 ID、还是按语义相似度?这些不定清楚,后面换存储就是在埋雷。

2.3 工具插槽:Agent 执行力的最终落点

工具是 Agent 对外部世界唯一的触手。所谓工具插槽,核心就是一张“工具注册表”。每个工具在上架之前,至少要提供三个字段:name是唯一标识,description告诉模型“这个工具什么情况下用”,parameters用 JSON Schema 描述参数结构。模型在推理时会读这张表,判断要不要调用某个工具、传什么参数。

工具插槽不能只做一个dict硬编码映射。我习惯把它设计成一个注册器,支持动态注册和卸载,每个工具还带一个available标志,方便随时灰度下线。真正执行时,工具插槽还要处理超时、重试、并发限制和错误返回。比如你接了一个 HTTP 查询接口,这个接口挂了,你是直接抛异常还是返回一段“查询失败请稍后重试”的文本给模型?后者往往更符合 Agent 的运行逻辑,因为模型可以据此换一种方式完成任务。

工具插槽是最贴近业务的部分,所以一定要独立成模块,不要和模型适配器混在一个文件里。业务团队只需要关心“工具怎么实现”,不需要关心“这些工具怎么被模型调用”。模型怎么把工具结果组装回对话里,是框架层的事。

2.4 编排插槽:决定 Agent 是单线程还是多线程大脑

编排插槽决定任务的拆解和执行顺序。同一个 Agent,既可以用最简单的“用户提问 → 模型回答”线性流程,也可以跑一个“规划 → 执行 → 验证 → 重试”的完整循环。编排插槽就是要支持这些不同模式,并且可以随时替换。

常见的编排实现有这么几类:线性 Pipeline 适合简单问答;事件驱动工作流适合多个独立任务并行处理;图状态机适合需要回退、分支、容错的复杂任务;Plan-and-Execute 循环适合需要多步推理的场景。DeepAgents 里非常典型的“反思-验证”模式,就是一个编排策略:执行完一个子任务,交给另一个验证器节点检查,不过关就打回重做。这套逻辑如果写死在主进程里,每换一种策略都要大改;抽成编排插槽之后,你要换的只是配置里的orchestrator字段。

设计编排插槽时,最容易被忽视的是“节点间传什么数据”。我建议在所有子任务之间统一传一个TaskContext对象,而不是传裸字符串或dict。任务上下文里包含当前输入、历史结果、预算上限、剩余重试次数。这样无论切到哪种编排器,数据流格式都不用改变。

2.5 技能插槽:把 Prompt、工具和执行策略打包成可复用单元

技能插槽是最近一年被反复提起的概念,很多人容易把它和工具混淆。它们的区别是:工具解决“能做什么”,技能解决“知道怎么做”。一个“写代码”技能,可能包含代码风格指南、脚手架命令、测试工具的调用顺序、甚至这段场景下的提示词模板。一个“客服应答”技能,可能包含话术规范、敏感词处理策略、退款流程的检查点。

新一代 Agent 框架基本都在推技能机制,核心思路非常统一:用固定目录结构存放说明文档、脚本、资源文件,技能插槽会创建一个注册表,每个技能声明自己的name、description、触发条件、依赖工具和执行脚本。Agent 运行时会先检索技能说明,再决定要不要加载某个技能。

技能插槽的接口要预留三个动作:安装、卸载、触发。安装是注册技能元信息和资源;卸载是把技能从上下文中移除;触发是在合适的任务节点上激活技能。DeepAgents 这种多子任务系统,非常适合把每个子任务实现成一个技能。比如“写周报”技能负责生成周报,“发邮件”技能负责投递,既独立又可组合。

2.6 安全与护栏插槽:给所有入口都加上过滤网

只要 Agent 要连接真实世界的工具,安全护栏插槽就必不可少。很多人以为安全就是“接入一个内容审核 API”,实际上更应该把它理解成一层可以插拔的中间件,分别挂在输入侧、输出侧、工具调用前侧。输入侧过滤注入类请求;工具网关侧检查参数、校验白名单、判断权限;输出侧过滤敏感信息,防止模型把不该透露的内部字段带出来。

我强烈建议把权限判断从工具内部抽出来,统一放在一个 Tool Gateway 里。工具本身只负责“执行”,不负责“判断谁可以用”。比如一个删除订单的工具,工具代码里就不要写if current_user == "admin"这种逻辑,而是由网关拦截所有调用,校验用户身份、参数范围和调用频次。否则模型一旦通过 Prompt 注入绕过工具内部检查,整个边界就形同虚设。

护栏插槽还要考虑灰度发布。上线一个新工具,可以先把它放进“只读模式”,只允许模型查数据,不允许它执行写操作;等跑一段时间确认没有异常,再放开写权限。这个开关放在护栏插槽的配置层最合适。

2.7 观测与追踪插槽:没有仪表盘的 Agent 不敢上生产

观测插槽是最容易被拖到后面的一个,但我觉得它反而应该在最早期就挂上去。Agent 的调用链太长了,一次最终回复背后可能有几十次模型调用和工具调用。没有观测,线上出了任何一个诡异问题,你都只能靠猜。

观测插槽至少要暴露四类事件:Agent 会话开始和结束、模型调用、工具调用、编排状态迁移。实现不一定要上重型的链路追踪平台,可以先写一个EventCollector,把事件统一投递到日志文件或者 stdout,后面再接 OpenTelemetry 或者别的平台。指标方面至少统计:单次请求延迟、Token 消耗、累计成本、工具失败率、重试次数。

我给所有 Agent 项目都定了同一个规矩:写第一个 Agent 骨架的同时,就必须把观测插槽挂上,哪怕先只输出“时间、事件类型、耗时、Token数”四列日志。否则你后续排查成本会成倍上涨,而且很多关键过程数据一旦错过就无法再补。

3. 真正动手前:先列散件清单,再定插槽协议

3.1 用一张表把需求翻译成插槽规划

前置阶段的第一步,不是写代码,而是列一张“散件清单”。我会把业务需求逐条拆到七个插槽上,并且给每个插槽写上“本次需求”、“备选实现”和“默认实现”。需求千万不要写“我要一个聪明的 Agent”,要写具体能力,比如“能查用户历史工单”“能自动生成退款单”“能在夜间无人值守时重试失败任务”。

下面是我做电商客服型 DeepAgents 时常用的规划表,你可以直接拿过去改:

插槽本次需求备选实现默认实现
模型插槽支持多模型切换、至少一个大模型一个小模型云端 API / 本地推理gpt-4o-mini 兼容接口
记忆插槽跨会话读取用户历史工单向量库 + Redis文件存储 + 内存缓冲
工具插槽查询订单、生成退款、创建工单HTTP API 封装本地 Mock 工具
编排插槽自动分诊 → 处理 → 质检图状态机 / 线性流程线性 Pipeline
技能插槽客服话术、投诉处理策略skill 包目录基础话术 skill
安全护栏外网请求白名单、写操作审批网关过滤放行 localhost
观测插槽记录调用链路和 Token 成本OpenTelemetry本地日志文件

这张表的作用不是写文档交差,而是逼你把每个散件说清楚。哪个格子填不下去,哪个格子里的选项你还不了解,哪个地方就藏着未来最大的返工风险。比如你填“记忆插槽用向量库”,那你必须同时写清楚:向量用什么模型生成?存在哪个库?每个用户的数据怎么隔离?这些不在前置阶段想清楚,后面就是一堆坑。

3.2 用 Schema 而不是内部代码来当接口

插槽和插槽之间用什么语言对话?很多人习惯在代码里直接互相调用函数,今天你调我、明天我调你,看似方便,实际上接口边界很快就模糊了。我的建议是:一切以 Schema 为准。工具参数必须定义成 JSON Schema;记忆插槽用抽象接口定方法签名;模型消息必须统一成标准角色消息;配置项要有一个可校验的 Schema。

记忆插槽的抽象接口可以用 Python 定义成这样:

class MemoryStore(ABC): @abstractmethod def save(self, key: str, data: dict) -> None: """保存一段记忆""" @abstractmethod def load(self, key: str) -> dict | None: """按 key 读取一段完整记忆""" @abstractmethod def search(self, query: str, top_k: int) -> list[dict]: """语义检索最相关的记忆片段""" @abstractmethod def clear(self, key: str) -> None: """删除一段记忆"""

一旦接口长这样,你记忆实现从“内存里存一个 list”换成“Redis 缓存 + 向量库”,上层 Agent 主流程完全不需要改。前端团队和后端团队甚至可以并行开发,只要两边都守着这份 Schema,最后接在一起的成功率就非常高。

3.3 配置化装配:用 YAML 当组装说明书

散件清单和 Schema 定了之后,装配过程就应该交给配置文件。一个 Agent 实例对应一份 YAML,里面写清楚:模型用哪个 Provider、工具加载哪些、记忆用哪种实现、护栏开几层、观测输出到哪里。这样整机的“组装说明书”就变成了一个可读、可版本管理、可复制到其他环境的文件。

下面是一份最小化的 Agent 配置示例:

agent: name: customer_service_agent orchestrator: linear_pipeline model: provider: openai model_name: gpt-4o-mini base_url: https://api.example.com/v1 max_tokens: 2048 support_tools: true memory: impl: file path: ./memory_store tools: - name: query_order enabled: true - name: refund_order enabled: false guardrails: enabled: true allow_hosts: ["api.internal.example.com"] write_actions: require_confirm observability: sink: file path: ./logs/agent_trace.log

这里特别注意:配置文件只控制“选哪个实现”,不承载业务逻辑。业务代码里永远不要直接读config["model"]["model_name"]这种裸配置,而是通过一个组合根(Composition Root)把配置装配成已经实例化的接口,再交给上层使用。这样改配置不动代码,改代码也不用追着配置跑。

4. 实操:搭一个带插槽的 DeepAgents 最小骨架

4.1 先定义插槽基类和注册表

理论说了这么多,还是得落到代码。我用 Python 写一个极简但完整的最小骨架,示范“插槽”到底是怎么抽出来的。以下代码不是某个框架的源码,而是我惯用的一套精简结构,你可以按需扩展。

先定义模型适配器插槽:

class ModelAdapter(ABC): @abstractmethod def chat( self, messages: list[dict], tools: list[dict] | None = None, ) -> str: """传入标准消息列表,返回模型回复文本""" @abstractmethod def support_tools(self) -> bool: """当前模型是否支持 function calling"""

再定义记忆插槽和工具注册表:

class MemoryStore(ABC): @abstractmethod def save(self, key: str, data: dict) -> None: ... @abstractmethod def load(self, key: str) -> dict | None: ... @abstractmethod def search(self, query: str, top_k: int) -> list[dict]: ... @abstractmethod def clear(self, key: str) -> None: ... @dataclass class ToolSpec: name: str description: str parameters: dict handler: Callable[..., str] available: bool = True class ToolRegistry: def __init__(self): self._tools: dict[str, ToolSpec] = {} def register(self, spec: ToolSpec) -> None: self._tools[spec.name] = spec def unregister(self, name: str) -> None: if name in self._tools: self._tools.pop(name) def to_llm_schema(self) -> list[dict]: """把内部工具清单转换为模型能理解的 JSON Schema 列表""" return [ { "type": "function", "function": { "name": t.name, "description": t.description, "parameters": t.parameters, }, } for t in self._tools.values() if t.available ] def invoke(self, name: str, **kwargs) -> str: spec = self._tools.get(name) if not spec: return f"工具 {name} 不存在" if not spec.available: return f"工具 {name} 已下线" # 这里预留切入安全护栏的位置 return spec.handler(**kwargs)

这里几个设计点值得说:to_llm_schema把内部工具转换成 JSON Schema,这样模型插槽和工具插槽的边界非常清晰,模型只是拿到一份只读的“说明书”;invoke是工具执行统一入口,以后加权限校验、审计日志、命令白名单,全在这个方法里加一行就行,不需要改任何业务工具。

4.2 从配置到整机装配

接下来用一个DeepAgent类把这些插槽串起来。核心思路是:类本身不依赖任何具体实现,它只依赖前面定义好的抽象接口。

class DeepAgent: def __init__( self, model: ModelAdapter, memory: MemoryStore, tools: ToolRegistry, orchestrator: str = "linear", max_rounds: int = 5, ): self.model = model self.memory = memory self.tools = tools self.orchestrator = orchestrator self.max_rounds = max_rounds def run(self, user_input: str, user_key: str = "default") -> str: history = self.memory.load(user_key) or [] messages = [{"role": "system", "content": "你是企业级客服助手"}] messages.extend(history) messages.append({"role": "user", "content": user_input}) for _ in range(self.max_rounds): if self.model.support_tools(): response = self.model.chat(messages, self.tools.to_llm_schema()) tool_call = extract_tool_call(response) if tool_call: result = self.tools.invoke(tool_call["name"], **tool_call["args"]) messages.append({ "role": "tool", "tool_call_id": tool_call["name"], "content": result, }) continue else: response = self.model.chat(messages) final_reply = response break else: final_reply = "执行次数达到上限,任务已终止" self.memory.save(user_key, messages[-10:]) return final_reply

组装过程就是典型的“组合根”:

def build_agent_from_config(config: dict) -> DeepAgent: model = create_model_adapter(config["model"]) memory = create_memory_store(config["memory"]) tools = ToolRegistry() for tool_conf in config["tools"]: if tool_conf["enabled"]: tools.register(build_tool(tool_conf)) return DeepAgent( model=model, memory=memory, tools=tools, max_rounds=config.get("max_rounds", 5), )

这份代码看着简单,但已经把七个插槽中的五个抽象出来了:模型、记忆、工具、编排、护栏位置。你以后要给 Agent 加一个“自动纠错”能力,不需要在DeepAgent里堆代码,而是写一个RetryDecorator包装在 run 方法外面,或者换一个实现GraphOrchestrator的编排器对象。这就是插槽化的回报:主流程稳定,扩展点清晰。

4.3 热插拔:只换实现,不换逻辑

插槽真正的价值在运行期体现。你想把模型从“云端 gpt-4o-mini”换成本地模型,只需要写一个实现了ModelAdapter接口的新类;你想把记忆从文件存储换成向量库,只需要写一个实现了MemoryStore接口的新类。然后在配置里改一行,重新build_agent_from_config,整机就换了一种驱动。

但热插拔也不能无脑操作,我有三个实际踩过的注意点。第一,组件替换前先确认当前任务没有处于工具执行的中间状态,否则会出现“新模型读旧上下文”的错乱。第二,模型切换会改变上下文窗口大小,原来 8K 窗口下保存的记忆片段,切到 4K 模型后可能直接导致超长,所以切换前最好做一次上下文裁剪。第三,工具下架前要检查注册表里还有没有未完成的异步任务,别删工具删到一半把正在执行的调用给断了。热插拔是方法论,不是万能魔法,边界意识比操作本身更重要。

5. 插槽设计最容易踩的坑

5.1 模型插槽:模型根本不支持 Function Calling

最常见的故障是:你给模型传了一大堆工具 Schema,它不回工具调用,反而把参数像人话一样打在正文里。这不是你工具代码写错了,而是模型本身不支持或者能力不稳定。很多本地模型说自己兼容 OpenAI 接口,实际在tools参数上常常跑偏。

解决思路是在模型插槽里做“能力降级”。保持support_tools()接口,检测到模型不支持时,编排层自动切换到另一种策略:把工具描述塞进 system prompt,规定模型必须输出一段特定 JSON,再由代码解析执行。这样同一个 DeepAgent,在不同模型之间跑的逻辑是统一的,只是驱动方式不同。另外记得控制工具数量,有些模型在工具超过二十个时,调用准确率就会直线下降,这时候要给工具插槽加一层“工具路由”,让模型先选分类,再选具体工具。

5.2 记忆插槽:向量维度冲突和过期脏数据

记忆插槽切换实现时,最容易爆的问题是 embedding 维度不一致。你今天用一个 768 维的向量模型存数据,明天想换成 1536 维的新模型,查询接口直接报错。解决方法是给每条向量打上模型版本标签,写入时记录embedding_model和dimension,查询时如果发现版本不一致,要么做维度映射,要么强制重建索引。

另一个坑是长期记忆没有清理策略。Agent 运行几个月后,会把过期数据当成最新事实回答给用户。我的做法是每条记忆都带时间戳和来源等级,检索时先把超过保留期限的片段过滤掉,再按相关度排序。记忆插槽不是“存了就完事”,它必须承担数据的生命周期管理。

5.3 工具插槽:权限边界被绕开

很多团队为了让 Agent 跑得快,把权限判断写进工具函数内部。表面上没问题,实际却被模型生成的参数轻松绕过。比如让模型解释“../../etc/passwd”路径,如果你在工具内部只判断“路径开头是 /home”,路径穿越直接就过了。

正确做法是把权限校验放在ToolRegistry.invoke这一层统一处理。无论哪个工具被执行,都必须先经过网关检查,包括参数范围校验、用户身份校验、敏感操作二次确认。我还会在网关层记录一次工具调用的完整参数,方便事后审计。最小权限原则在 Agent 场景里比在传统后端里更重要,因为模型不是人,它不会主动“手抖”,它只会按概率选一个看起来合理的参数。

5.4 编排插槽:死循环和 Token 烧穿

Plan-and-Execute 模式写起来爽,但如果不设上限,它会在错误路径上无限循环。你可能遇到模型反复说“我重新规划一下”“让我再试一次”,结果一次简单提问烧掉几千 Token。为此编排插槽必须内置三个参数:最大循环次数、最大模型调用次数、单任务成本阈值。任何一个参数达到上限,立即终止当前任务,并把失败原因写进观测日志。

这三个参数不要散落在业务代码里,直接在编排插槽初始化时作为必填配置。我一般设置最大循环 5 次、单任务成本不超过 2 美元。如果你预算充足,可以把阈值调高,但绝对不能没有上限。Agent 的自主性越强,失控的破坏力越大,编排插槽就是拉住它脖子的那根绳。

5.5 配置地狱:YAML 嵌套太深没人敢碰

插槽一多,配置文件就会变成一个没人敢动的巨型 YAML。每个人都有过这种体验:明明只是改一个enabled字段,结果缩进错一个空格,整个 Agent 起不来。我的建议是三条:每个配置项必须有默认值,配置文件里只写差异项;整个配置进组合根之前必须先做 Schema 校验,类型错误早发现;敏感密钥一律走环境变量,不要写进 YAML。

配置这东西,理想状态是“看一眼就知道整机什么配置”。如果哪个配置项需要翻三层文档才能理解,说明命名和层级设计有问题。重新审视你的插槽规划,把聚合根调整到更直观的粒度。

6. 前置规划的最后几条建议

我最早做 Agent 的时候,代码里什么插槽都没有。模型调用直接写在业务类里,工具用一排 if-else 散落在各个模块,记忆就只有一个全局列表。第一个 demo 确实很快,三小时就跑通了。可一接真实业务,需求从“单轮问答”变成“多轮工单处理”,我几乎把整个系统重写了一遍。后来我痛定思痛,把所有跨边界能力全部抽象成插槽,之后每次加新需求都变成了“往清单里补散件”,很少再推倒重来。

所以如果你正打算做一个 Agent,别急着写本体。先拿一支笔,把你需要的插槽列出来。模型、记忆、工具、编排这四个是必装槽位,安全护栏和观测至少要留出位置,哪怕第一版只接一个空实现。技能插槽可以后补,但注册表的目录结构最好在一开始就定好。

这串插槽清单,比任何框架模板都值钱。框架会过时,模板会被嫌弃,但一张清晰的分层接口协议,能让你的 Agent 从“一次性试验品”慢慢长成“可持续迭代的整机”。先定插槽,再谈智能,顺序千万不能反。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进