ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从零搭建AI Agent中台:hermes-agent的架构设计与落地实践

从零搭建AI Agent中台:hermes-agent的架构设计与落地实践 hermes-agent这个项目最初是我在接一个自动化需求时顺手起的名字。希腊神话里Hermes是替众神传信、跑腿的信使而agent要干的事情本质上就是传话加跑腿——接收指令、理解意图、调用工具、返回结果。把名字定成hermes-agent之后这个项目就越做越像一个独立可复用的智能体中台了。这篇文章就把我搭这个项目的完整思路、模块拆解、落地场景和踩过的坑一次性讲清楚。想自己从零搭一个AI Agent、或者准备把Agent塞进业务系统的朋友应该都能从这里找到一些能直接用的东西。1. 项目定位与整体设计思路1.1 为什么叫hermes-agent信使神的职责就是agent的职责早期给Agent起名字的时候我列过好几个备选最后留下的就是hermes-agent。原因很简单Hermes这个角色在神话里承担的职责和智能体在系统里承担的职责高度重合。它不负责生产内容而是负责在正确的时机、把正确的信息、送到正确的地方同时把执行结果带回来。这个定位恰好就是任务型Agent的核心能力模型。这个项目最开始的目标也特别朴素把散落在各个内部系统里的操作能力统一收口让业务同事用自然语言就能触发。比如查工单状态、整理数据报表、批量处理文件、发通知。这些事过去要么靠人工点系统要么靠写一次性脚本重复又低效。我想要的Agent不是又一个聊天机器人而是一个能真正干活的执行体。后来的项目演进过程中我把它的能力收敛成了三个关键词理解、规划、执行。理解对应大模型对用户意图的解析规划对应把复杂任务拆成可执行的子步骤执行对应落地到具体工具和接口。这三点也是整个hermes-agent设计的主线后面所有的模块、代码、配置都是围绕这条主线展开的。1.2 整体架构大脑、手脚、笔记本如果你打开hermes-agent的源码目录会发现核心模块并不复杂抽象下来就是三层再加一个控制循环。第一层是大脑也就是大模型调度层。这一层负责所有需要语义理解的部分听懂用户要什么、判断当前该执行哪一步、评估上一步结果是否符合预期。这里我建议把模型调用单独封装成一个服务不要和业务逻辑混在一起否则后面换模型、调参数都会很痛苦。第二层是手脚也就是工具层。这一层负责对接外部系统数据库、HTTP接口、文件系统、消息队列等等。每个工具都被包装成统一的接口形态Agent通过函数调用机制来决定用哪个工具、传什么参数。这一层是整个项目里工作量最大的部分因为每接一个系统都要处理鉴权、超时、错误码这些琐碎但有决定性的细节。第三层是笔记本也就是记忆层。短期记忆负责当前多轮对话的上下文长期记忆负责跨会话的关键信息比如用户偏好、历史任务的执行结果、领域知识点。实际实现里短期记忆可以直接塞给大模型上下文长期记忆则借助向量数据库做检索召回。控制循环是串起这三层的关键官方一点的说法叫ReAct循环说白了就是一个思考-行动-观察的重复过程Agent先根据当前状态决定下一步动作然后调用工具拿到结果后再继续思考直到任务完成或者达到最大轮次。这块是整个系统最值得花时间调优的地方后面我会单独展开。2. 核心模块拆解与实现要点2.1 任务规划与ReAct循环的权衡任务规划是Agent区别于普通脚本的根本特征。早期我做过一版非常重的规划器先让模型一次性输出完整的步骤清单然后按清单逐步执行。看起来很美实际跑起来问题很大真实任务往往在执行过程中才会暴露新的信息预设步骤很容易失真。比如让它整理上季度销售数据并生成图表第一步可能就要确认上季度的起止时间而这个信息用户最初根本没给。后来我切到了ReAct这种边想边做的模式不要求模型一次规划到位而是每一轮都基于当前状态小步决策。这种方式对动态任务极其友好但代价是增加了不确定性模型可能绕弯路、可能重复执行、甚至可能做出错误判断。为了控制风险我做了两件事。第一给每轮决策限定动作空间。不是所有工具都暴露给模型而是根据任务类型动态裁剪只给相关的几个工具。这样能显著降低选错工具的概率。第二设置最大轮次上限。hermes-agent默认单任务最多跑15轮超过就直接终止并输出部分完成的状态避免无限循环烧token。我还加了一个轻量级的前置确认机制。如果任务涉及高风险操作比如删除数据、发对外通知、执行写操作Agent在真正动手前必须先把计划列出来请用户确认。这个设计一开始觉得多余实际用下来帮我们少踩了很多坑。2.2 工具注册与Function Calling机制工具层是整个项目能不能落地的关键。hermes-agent里的每个工具本质上就是一个被结构化描述包裹的函数。描述里包含工具名称、功能说明、参数列表、参数类型、是否必填。大模型看到这些描述之后在合适的时机输出一个结构化的调用请求系统再去执行真实的函数并返回结果。我在设计工具注册表时参考了函数调用Function Calling的通用思路但做了一点改造每个工具除了函数本身还带一份使用说明和失败处理策略。使用说明是给模型看的里面写清楚这个工具适合什么场景、有什么限制失败处理策略是给框架看的比如超时重试几次、失败后是返回错误还是尝试降级方案。这里有两个非常影响成功率的小细节。第一个是工具描述必须写清楚边界。比如一个查询库存的工具如果不写只支持按SKU精确查询不支持模糊搜索模型就会拿一个不存在的模糊条件去调用白白浪费几轮。第二个是参数校验必须在框架层面做不能指望模型输出一定规范。我在hermes-agent里加了一层pydantic校验参数不符合schema就直接打回让模型重新输出比把脏数据传进函数再报错要省很多token。工具列表的维护也是一门学问。一开始我把所有工具都塞给模型很快发现上下文被工具描述占掉一大截而且模型选择困难。后来我改成工具分组动态加载按任务领域把工具分成若干组规划阶段先生成接下来可能需要的工具组再去加载对应的工具描述。效果很直接工具调用准确率从78%左右提升到了89%。2.3 记忆管理上下文窗口与向量检索记忆模块一开始我只做了最简单的方案把历史对话全部拼进上下文。应付短对话没问题一旦任务复杂起来上下文很快就爆了。有一次用户连续问了十几个问题结果请求体积大到响应延迟翻倍单次成本也涨得飞快。我意识到必须分层处理记忆。现在的方案分三层。第一层是最近N轮的完整对话直接放进上下文。N我通常取10到20具体取决于模型窗口大小和任务复杂度。第二层是任务级摘要每完成一个子任务就用模型把关键信息压成一段摘要后续轮次只带摘要不带全文。第三层是长期知识比如用户偏好、历史问题模式、业务规则存入向量数据库每次任务开始时按语义相似度检索最相关的几条注入上下文。这个三层方案跑了一段时间之后我又遇到一个新问题摘要压缩会丢细节。比如用户之前明确说报表要按周维度汇总摘要里如果只留一句用户有格式偏好后面Agent可能就不知道具体偏好是什么了。所以现在我更保守凡是涉及数字、日期、具体配置的信息一律进结构化存储而不是靠摘要记忆。记忆模块的数据安全也要注意敏感信息入库前要做脱敏处理这个千万别省。3. 关键场景与实操落地3.1 场景一工单自动分拣与初步回复工单场景是hermes-agent第一个正式落地的业务。之前客服同学每天要花大量时间把工单分类、标记优先级、回复常见问题。接Agent之后流程变成了这样工单进来先触发webhookAgent自动读取工单标题和正文提取关键要素——问题类型、涉及产品、紧急程度——然后对照规则库生成初步回复建议。如果需要查询订单状态或用户信息Agent会调用对应的内部接口把真实数据带进回复草稿里。这个场景对准确率要求很高因为回复出错会直接影响用户体验。我不指望Agent直接自动回复而是把它定位成智能辅助草稿生成后进入人工审核队列客服只负责确认或修改。跑了一个月之后客服处理单个工单的平均时长从6分钟降到了3分半左右而且因为草稿已经带了数据人工改动的量非常少。落地过程中有一个容易被忽视的点工单类型非常多如果让Agent自由发挥很容易答非所问。我们的做法是先做一个粗粒度的分类模型把工单归入十几个大类再根据类别决定给Agent加载哪些工具和参考文档。比如退换货类工单Agent只需要查订单系统和售后规则库技术故障类工单则需要访问日志查询工具和排障手册。这个先分类再动作的模式比让Agent自己判断要稳得多。3.2 场景二数据分析问答助手这个场景是后来业务方主动找上门的。运营同事每天要查大量数据但他们的SQL水平参差不齐经常写错条件取出来的数对不上。我们用hermes-agent搭了一个数据分析助手用户用自然语言提问比如上个月华东区的复购率环比变化多少Agent把问题翻译成SQL再连接到只读数仓执行最后把结果自动生成简短的分析说明。这里最关键的工程问题是SQL生成的可靠性。我一开始天真地以为给模型一份表结构说明就够了实际测试发现模型经常会把字段名写错、把过滤条件理解偏。后来我在工具描述里不仅放了表结构还把常用的计算口径、枚举值含义、典型查询示例都放了进去。同时给SQL执行套了一层只读连接从机制上杜绝误写操作。数据权限也是一个绕不开的议题。我们通过一个轻量的权限注解在工具层限制不同角色能查的表范围和字段范围。运营同事只能查脱敏后的聚合数据不能直接拉明细。这个限制不是加到prompt里的而是在工具执行层做的硬校验因为prompt对模型的约束是不可靠的硬编码反而是对用户的一种保护。3.3 场景三DevOps日常巡检与异常记录第三个落地的场景是运维侧的辅助巡检。每天早晨Agent按定时任务启动读取各个服务的健康检查结果、错误日志、核心指标然后生成一份巡检摘要把异常项单独高亮并附带初步的排查建议。这个场景本身不算复杂但价值在于把分散在多个平台的信息聚合到了统一入口省去了运维同学一个个系统点开看的耗时。实现上需要注意执行时间的控制。巡检涉及多个数据源的拉取有的接口响应慢容易导致整个任务超时。我给每个工具单独设置了超时时间并且对非关键的数据源做了并行调用。整体跑下来一次巡检从最初的三四分钟压缩到四十秒左右。另外巡检任务失败要有降级方案不要因为某个数据源挂了就导致整个报告出不来。我的做法是partial success机制已取到的数据正常展示失败的数据源在报告里标注数据暂不可用。这个场景让我更确认了一个感受Agent的价值不在于完成多么惊艳的任务而在于把那些重复、繁琐、跨系统的小事稳定地自动化掉。稳定比聪明更重要。3.4 部署方式与接口设计部署上hermes-agent本身是一个无状态的服务。会话状态和记忆都放在外部存储里所以可以水平扩展。Docker打包是标配我直接基于Python写的服务做了一个精简镜像启动入口分两种一种是常驻的API服务对外提供对话和任务提交接口另一种是单次执行的CLI模式适合定时任务和批处理场景。对外接口我设计了三个主要端点submit_task用于提交一个任务并获取任务IDquery_status用于查询任务的执行状态和阶段日志get_result用于获取最终结果和工具调用明细。这种异步任务模式比同步接口更合适因为复杂任务往往要跑几十秒甚至几分钟同步等待在网关层很容易超时异步可以配合回调或者轮询来取结果。为了让业务系统能方便接入我还做了SDK内部系统只需要几行代码就能拉起一个任务并把执行过程的关键事件通过回调推送到企业微信或内部IM。开发者不需要理解Agent内部怎么运作只需要知道我提交了任务它帮我干完然后告诉我结果。这一点对推广Agent内部落地特别重要不要给使用者增加理解成本。4. 踩坑实录与排查技巧4.1 工具返回结果过大导致token爆炸这是我踩过的第一个大坑。Agent在处理一个数据统计任务时查询工具返回了一张几百行的明细表模型把整个表格内容都在上下文中处理了一遍单轮token消耗直接翻了好几倍成本飙升。更麻烦的是后续轮次里这些原始数据还一直占着上下文严重挤占了有效空间。解决办法是在工具返回层加内容裁剪。查询类工具默认只返回结果的前30行并附带一个全文摘要字段如果Agent判断需要完整数据再显式调用另一个工具拿文件或分页数据。还有一个细节非结构化的长文本返回时要先做截断和摘要再给到模型。这个改动下来单任务平均token消耗降了将近40%。4.2 Agent陷入循环出不来有一次测试任务时Agent在一个查询订单状态的动作上反复执行了七八次参数几乎没变中间也没有任何有效进展。原因是工具返回的订单状态字段是可枚举的字符串模型解析时拿不到足够信息就一直试图重新查询。针对循环问题我做了双重保险。第一层是最大轮次限制这个前面已经说过了。第二层是重复动作检测如果Agent连续三轮调用同一个工具且参数高度相似系统会主动中断并提示检测到重复操作请调整策略或结束任务。实测下来重复动作检测能拦截大部分无效循环也帮我们节省了不少token。4.3 模型幻觉导致错误工具调用幻觉问题主要体现在参数生成上。有一次模型把用户ID的格式理解错了生成了一个格式不对的ID去查询查不到结果之后它居然没有报错而是自顾自地编了一段该用户订单状态正常的话术。这个情况非常危险因为输出的东西看起来毫无异常但实际上是凭空捏造的。为了应对幻觉我做了三件事。一是所有工具调用结果必须先经过校验如果返回结果为空或者异常必须在回复里如实说明禁止模型编造。二是在prompt里强制要求只能基于工具返回的数据说话这句话反复强调。三是针对关键结果加了置信度提示如果模型对回答没有把握必须主动说不确定而不是硬编一个答案。这个效果不是百分百但能大大降低幻觉带来的问题。4.4 并发场景下的资源争抢当多个任务同时跑的时候资源争抢问题就显出来了。最早所有任务共享同一个模型实例高峰期经常出现排队单个任务完成时间从几秒膨胀到几十秒。后来我引入了信号量做并发控制把任务分级简单任务并发上限高复杂任务并发上限低。再配合请求级别的超时和退避整体稳定性好了很多。这里还有一个容易忽略的点外部工具接口的限流。有些内部服务每秒只允许几十个请求Agent一旦并发上去就会触到限流报错之后模型又会重试反而加剧问题。我的做法是给每个工具单独配置QPS限制并在Agent内部统一做请求排队。这块说白了就是限流思想要贯穿整个链路不只是管自家接口下游接口更要管。4.5 监控与可观测性设计Agent调试起来比传统程序要难因为它每一步都是模型生成的不可完全复现。这个痛苦我深有体会。后来我给hermes-agent上了完整的事后可观测能力每个任务的每一步都记录下当时的输入、模型输出、选择了哪个工具、传了什么参数、工具返回了什么、最终的决策理由。这些日志全部落库支持按任务ID检索。这套日志在排查问题的时候简直救命。用户反馈刚才那个任务结果不对我不用靠猜直接把执行链路调出来一眼就能看到是哪一步的决策出了问题。我还在系统里加了一个小功能支持回放指定任务把整个思考-行动的链条重新打印出来。这个功能对优化prompt和定位模型行为价值巨大强烈建议每个做Agent的人都装上。5. 效果评估与成本控制5.1 评估指标不是只有回答对不对Agent的效果评估比普通模型评测复杂得多。我一开始只看最终答案对不对后来发现不够两个任务可能结果一样但一个用了5轮、一个用了12轮成本和稳定性完全不同。所以我建了一套多维指标来评估核心看四个维度。第一个维度是任务完成率也就是最终成功产出结果的占比。第二个是平均轮次和执行时长轮次越少越稳定。第三个是工具调用准确率看模型选对工具的比例。第四个是单任务平均成本和成功率分布成本超高的那些任务就是后续优化的重点对象。四个维度组合起来才能比较全面看出一个Agent的实际水平。针对复杂任务分析时我还会额外看一个回退率指标。所谓回退就是模型推翻了之前的判断重新决策。适当的回退是正常的但回退率过高通常说明上下文里信息不足或者工具结果不够清晰。回退率高并不是模型不聪明更可能是你给的信息不够这时候优先优化工具描述和上下文结构比换一个更大的模型更有效也更省钱。5.2 模型选型与成本优化实践模型选型上我并不追求最强模型而是按任务难度做分级路由。简单任务比如信息抽取、关键词提取用便宜模型就够复杂任务比如多工具协同推理再上强模型。hermes-agent里做了一个模型路由器可以根据任务类型和预估难度动态选择模型。跑了一段时间之后总体成本比所有任务都用最强模型降了一半以上而整体质量几乎没有下降。另外输入侧的压缩也能省不少钱。系统会定期清理毫无信息量的系统提示词把那些冗长的规则说明精简成要点。工具描述则优先放到命中后才加载而不是每次都全部注入。这些看起来都是小钱但Agent跑的量大了之后累积起来非常可观。如果预算确实紧张还可以用语义缓存来规避重复请求。同一个问题在短时间内反复出现是常态命中缓存的话直接返回上一次的结构化结果。需要注意缓存粒度要控制好不能把包含实时数据的查询也缓存了否则会拿到过期结果。这块需要按工具类型配置不同的缓存策略像查订单状态这种实时性要求高的完全不缓存。6. 关于hermes-agent未来的一点思路项目走到现在基础能力已经比较完整了但离我理想中的信使还有一些距离。尤其是跨任务的经验沉淀能力目前的长期记忆还停留在存了什么就拿出来什么的层面后续我计划把历史任务的执行方案做一次抽象沉淀让Agent在遇到相似任务时能直接参考过去的成功策略而不是每次从零开始规划。多Agent协作也是我最近在研究的方向。单个Agent处理巨大复杂任务时无论上下文还是决策质量都会明显下降。把它拆成多个专业Agent由一个调度Agent统一协调反而可能更稳定。hermes-agent已经在内部预留了Agent间消息通信的接口下一版准备在这个方向上做一些实际场景的验证。最后还有一个我一直在想的问题Agent的自主性边界到底划在哪里。技术上我们能做的是给Agent加各种限制和确认机制但更重要的其实是业务方想清楚哪些操作允许自动执行、哪些必须保留人工环节。我在实际项目中一直坚持的一个原则是默认保守逐步放开。先在低风险场景里跑稳定再慢慢扩大权限边界这条路走得虽然慢但每一步都比较踏实。这也是我做完hermes-agent之后最大的体会。
返回列表