智能体编程基本设计
智能体分层架构与抽象接口设计汇总本文汇总内容智能体框架现状、BaseAgent 抽象基类、两种架构对比Agent→Tool / Agent→Skill→Tool可直接保存为agent_arch.md目录智能体编程接口现状无全局统一标准方案A单层架构Agent → Tool最简无技能层单层架构代码实现BaseAgent 抽象 LangChain适配器方案B三层架构Agent → Skill → Tool引入技能层三层架构代码实现BaseSkill 抽象、改造后的BaseAgent两种架构对比 设计取舍扩展方向与局限性1. 智能体编程接口现状无全局统一标准核心结论没有全球统一、底层强制的智能体编程标准各框架原生接口差异很大但正在涌现一批互操作规范/抽象层用来抹平差异。分为两层框架原生API私有、上层协议/抽象规范社区推进可选主流框架原生接口差异框架Agent核心范式工具定义方式执行器/运行时记忆、状态管理LangChainAgent AgentExecutor基于Runnable链tool/ Tool对象AgentExecutor循环调度独立Memory组件可挂载LlamaIndexAgent作为QueryEngine子类ToolSpec / FunctionToolAgentRunner内置Memory绑定Agent实例AutoGen多智能体对话角色Agent是对话参与者register_function装饰器GroupChat/ConversationManager对话消息列表CrewAI任务角色团队编排工具继承BaseToolCrew执行器任务上下文Semantic Kernel微软Kernel作为核心容器Agent是插件集合KernelFunction / PluginKernel调度器Kernel状态痛点同一个自定义工具不能直接跨框架复用Agent循环、状态、scratchpad 都是框架私有实现。正在发展的跨框架规范非强制标准MCPModel Context ProtocolAnthropic工具调用层标准化协议。大模型 ↔ 工具通信统一工具可跨Agent框架复用不是Agent编排规范。OpenAI Function Calling Schema事实通用的工具描述schema绝大多数框架支持转换仅描述函数元数据不定义Agent思考循环。A2AAgent2AgentGoogle解决智能体之间互相通信不解决Agent内部编排代码标准化。分层理解Agent业务编排代码思考循环、任务拆解、状态、记忆无统一规范框架私有工具描述schema函数名、参数OpenAI function schema 为事实通用格式工具远程调用协议MCP正在成为新标准实现跨框架复用工具智能体之间互相通信A2A 目标做跨Agent对话标准2. 方案A单层架构Agent → Tool最简无技能层适用场景工具为独立原子动作不存在固定多工具串行编排无需业务前置校验、权限控制。Agent思考规划、判断意图选择工具调用维护会话记忆与执行循环Tool原子执行单元单一原始动作API调用、计算、数据库查询无业务规则依赖pipinstallpydantic统一数据模型 BaseAgent抽象基类fromabcimportABC,abstractmethodfromtypingimportAny,List,Optional,DictfrompydanticimportBaseModel# 通用消息模型统一各框架消息结构classAgentMessage(BaseModel):统一消息结构替代各框架各自的Messagerole:str# user / assistant / toolcontent:strtool_call_id:Optional[str]Nonetool_name:Optional[str]Nonetool_args:Optional[Dict[str,Any]]NoneclassAgentToolDefinition(BaseModel):统一工具定义模型可直接转OpenAI function schema对接MCPname:strdescription:strparameters:Dict[str,Any]# json schema# 可选工具执行入口远程MCP则填server地址本地则填callableremote_endpoint:Optional[str]NoneclassAgentResult(BaseModel):统一返回结果标准化输出屏蔽框架返回结构体差异success:booloutput:strmessages:List[AgentMessage]intermediate_steps:List[Dict[str,Any]]# 工具调用中间日志error:Optional[str]None# 抽象智能体基类 classBaseAgent(ABC): 抽象Agent基类所有智能体必须实现这些核心方法 上层业务只调用这里的接口不感知LangChain/AutoGen等底层 abstractmethoddefadd_tool(self,tool_def:AgentToolDefinition)-None:注册工具统一工具定义对象子类负责转换成框架原生Toolpassabstractmethoddefset_system_prompt(self,prompt:str)-None:设置系统提示词passabstractmethoddefset_memory(self,memory:Any)-None:挂载记忆组件memory同样可以再做抽象BaseMemorypassabstractmethodasyncdefarun(self,user_input:str,**kwargs)-AgentResult:异步执行智能体推荐优先异步passabstractmethoddefrun(self,user_input:str,**kwargs)-AgentResult:同步执行智能体passabstractmethoddefreset(self)-None:重置会话状态清空scratchpad、清空本轮中间步骤保留工具/系统提示passabstractmethoddefget_history(self)-List[AgentMessage]:获取标准化对话历史passLangChain 适配器实现BaseAgent子类fromlangchain.agentsimportAgentExecutor,create_openai_tools_agentfromlangchain_core.toolsimportToolfromlangchain_openaiimportChatOpenAIfromlangchain_core.promptsimportChatPromptTemplateclassLangChainAgent(BaseAgent):def__init__(self,llm_model:str,llm_api_key:str,temperature:float0):self.llmChatOpenAI(modelllm_model,api_keyllm_api_key,temperaturetemperature)self.tools:List[Tool][]self.system_prompt你是一个智能助手可以调用工具解决问题。self.agent_executor:Optional[AgentExecutor]Noneself._message_history:List[AgentMessage][]defadd_tool(self,tool_def:AgentToolDefinition)-None:# 将统一AgentToolDefinition → LangChain原生Tool对象lc_toolTool(nametool_def.name,descriptiontool_def.description,funclambda*args:ftool placeholder:{tool_def.name})self.tools.append(lc_tool)self._rebuild_agent()defset_system_prompt(self,prompt:str)-None:self.system_promptprompt self._rebuild_agent()defset_memory(self,memory:Any)-None:raiseNotImplementedError(Memory适配按需实现)def_rebuild_agent(self):promptChatPromptTemplate.from_messages([(system,self.system_prompt),(user,{input}),(agent_scratchpad,{agent_scratchpad}),])agentcreate_openai_tools_agent(self.llm,self.tools,prompt)self.agent_executorAgentExecutor(agentagent,toolsself.tools,verboseTrue)defrun(self,user_input:str,**kwargs)-AgentResult:ifnotself.agent_executor:raiseRuntimeError(Agent未初始化请添加工具或设置prompt)try:raw_resself.agent_executor.invoke({input:user_input})resultAgentResult(successTrue,outputraw_res[output],messages[AgentMessage(roleuser,contentuser_input)],intermediate_stepsraw_res.get(intermediate_steps,[]),errorNone)self._message_history.append(AgentMessage(roleuser,contentuser_input))self._message_history.append(AgentMessage(roleassistant,contentraw_res[output]))returnresultexceptExceptionase:returnAgentResult(successFalse,output,messagesself._message_history,intermediate_steps[],errorstr(e))asyncdefarun(self,user_input:str,**kwargs)-AgentResult:ifnotself.agent_executor:raiseRuntimeError(Agent未初始化)try:raw_resawaitself.agent_executor.ainvoke({input:user_input})resultAgentResult(successTrue,outputraw_res[output],messages[AgentMessage(roleuser,contentuser_input)],intermediate_stepsraw_res.get(intermediate_steps,[]),errorNone)self._message_history.append(AgentMessage(roleuser,contentuser_input))self._message_history.append(AgentMessage(roleassistant,contentraw_res[output]))returnresultexceptExceptionase:returnAgentResult(successFalse,output,messagesself._message_history,intermediate_steps[],errorstr(e))defreset(self)-None:self._message_history[]defget_history(self)-List[AgentMessage]:returnself._message_history.copy()业务调用示例defbusiness_demo(agent:BaseAgent):calc_toolAgentToolDefinition(namecalculator,description数学计算器用于计算表达式,parameters{type:object,properties:{expression:{type:string,description:数学表达式}},required:[expression]})agent.add_tool(calc_tool)agent.set_system_prompt(你是擅长数学计算的助手复杂算式调用计算器工具。)resagent.run(计算 (100200)*12)print(结果,res.output)print(是否成功,res.success)print(中间步骤,res.intermediate_steps)if__name____main__:agent:BaseAgentLangChainAgent(llm_modelgpt-3.5-turbo,llm_api_keysk-xxx)business_demo(agent)必须抽象的接口方法add_tool工具注册抹平框架Tool对象差异set_system_prompt系统角色定义run / arun同步/异步执行入口业务调用核心reset会话重置隔离多轮会话get_history标准化读取对话历史用于日志/展示set_memory挂载记忆组件不放入抽象层框架内部私有变量、框架特有参数verbose、迭代上限、框架独有的高级能力。3. 方案B三层架构Agent → Skill → Tool引入技能层适用场景企业业务存在固定子任务编排、权限校验、参数预处理/结果清洗、底层工具需要对LLM屏蔽。分层职责Agent智能体思考、任务规划、意图判断决定调用技能维护会话状态、记忆、多轮思考循环。Agent看不到底层Tool。Skill技能业务能力封装单元。内部编排多个工具自带前置校验、鉴权、参数预处理、结果格式化、异常重试。对外暴露业务语义。Tool工具底层原子执行单元只做原始动作不带业务规则。不直接暴露给LLM。新增 BaseSkill 抽象 修改BaseAgent管理Skill而不是ToolfromabcimportABC,abstractmethodfromtypingimportAny,List,Optional,DictfrompydanticimportBaseModel# 复用前面定义的 AgentMessage / AgentResult / AgentToolDefinition# 【技能抽象层 BaseSkill】 classBaseSkill(ABC): 技能业务能力封装内部编排多个原子Tool Agent只能感知Skill不知道内部的Tool细节 name:strdescription:strparameters_schema:Dict[str,Any]# 暴露给LLM的入参schemaabstractmethodasyncdefexecute(self,params:Dict[str,Any])-Dict[str,Any]: 执行技能 内部逻辑参数校验 → 调用一个/多个底层Tool → 结果处理、异常捕获 返回标准化业务结果给Agent passabstractmethoddefget_required_tools(self)-List[AgentToolDefinition]:返回该技能依赖的底层原子工具列表框架内部注册使用不暴露给LLMpass# 改造BaseAgentAgent挂载Skill不再直接挂载Tool classBaseAgent(ABC):def__init__(self):self.skills:List[BaseSkill][]# Agent挂载【技能】不是直接挂载toolself.system_prompt:strself._message_history:List[AgentMessage][]abstractmethoddefadd_skill(self,skill:BaseSkill)-None:注册技能对外暴露给LLM的是Skill的name/description/schemapassabstractmethoddefset_system_prompt(self,prompt:str)-None:passabstractmethodasyncdefarun(self,user_input:str,**kwargs)-AgentResult:passabstractmethoddefrun(self,user_input:str,**kwargs)-AgentResult:passabstractmethoddefreset(self)-None:passabstractmethoddefget_history(self)-List[AgentMessage]:pass具体Skill实现示例报表生成技能内部编排两个工具classReportSkill(BaseSkill):namegenerate_monthly_reportdescription生成月度业务报表输入月份返回格式化业务报表parameters_schema{type:object,properties:{month:{type:string,description:报表月份格式YYYY-MM}},required:[month]}defget_required_tools(self)-List[AgentToolDefinition]:# 技能内部依赖两个底层原子工具LLM看不见这两个工具return[AgentToolDefinition(namequery_db_sales,description查询销售原始数据,parameters{type:object,properties:{month:{type:string}},required:[month]}),AgentToolDefinition(nameformat_markdown,description将原始数据转为markdown表格,parameters{type:object,properties:{raw_data:{type:object}},required:[raw_data]})]asyncdefexecute(self,params:Dict[str,Any])-Dict[str,Any]:# 技能内部业务逻辑固定编排LLM不用管 monthparams[month]# 1. 前置校验iflen(month)!7:return{ok:False,result:月份格式错误要求YYYY-MM}# 2. 调用底层工具1查询数据库raw_dataawaitself._call_tool(query_db_sales,{month:month})# 3. 调用底层工具2格式化report_textawaitself._call_tool(format_markdown,{raw_data:raw_data})# 4. 后置处理return{ok:True,result:report_text}asyncdef_call_tool(self,tool_name:str,args:Dict):# 技能内部私有方法调用底层原子工具Agent感知不到# 这里可以接入工具执行器、鉴权、日志、超时控制return{sales:123000,order_count:320}LangChain适配器改造思路LangChainAgent 在add_skill的时候提取Skill的name/description/parameters_schema包装成OpenAI function schema暴露给LLM把skill.execute作为function的回调技能依赖的底层Tool仅在适配器内部注册不暴露给大模型。LLM只能看到技能列表不会直接操作底层工具。4. 两种架构对比 设计取舍架构模型适用场景优点缺点单层Agent → Tool简单场景工具独立无固定编排代码简单抽象少LLM承担全部多步编排容易出错业务规则散落在prompt里三层Agent → Skill → Tool企业业务、固定子任务、权限管控、工具编排业务逻辑固化在SkillLLM只做意图判断底层工具可替换统一鉴权审计多一层抽象开发量增加什么时候技能层是多余工具本身就是业务最小单元工具调用不需要前置参数校验、结果清洗、业务权限判断不存在“一个业务能力需要连续调用多个原子工具”业务简单LLM直接决定调用哪个原子工具。什么时候引入Skill层满足任意一条技能层就具备明确价值一个业务能力需要串联多个原子Tool固定执行链路下沉到技能降低LLM规划负担需要业务前置校验、权限控制、参数预处理、结果脱敏、异常重试对外暴露业务语义底层工具变更时不需要修改Agent提示词技能跨多个智能体复用安全管控底层Tool不暴露给LLM所有底层调用由技能代理执行便于审计熔断。5. 扩展方向与局限性扩展方向新增BaseMemory抽象做成适配器LangChainMemoryAdapter、CustomMemoryAdapterMCP工具适配器add_mcp_tool(server_url)自动将MCP工具转为AgentToolDefinition回调钩子on_tool_start / on_tool_end统一日志埋点增加限流、最大迭代次数放在Agent构造参数属于实现层而非抽象接口局限性抽象层只能提取所有Agent共有的最小子集各框架独有高级能力多角色、分层PlanExecute不能塞进BaseAgent需要单独扩展接口。抽象层会带来少量封装开销适合中长期项目简单Demo没必要做这一层。6. 可选后续开发模块Skill执行器统一调度技能内部工具、鉴权、日志、超时熔断完整业务调用示例演示Agent调用ReportSkillBaseMemory抽象类配套适配器实现回调钩子扩展版本