资讯详情

Agent-Reach:智能体触达框架,让LLM行动真正落地业务系统

📅 2026/10/27 22:03:02 | 华诺云谱 👁 阅读
Agent-Reach:智能体触达框架,让LLM行动真正落地业务系统
1. 为什么叫“Reach”先从智能体编排的实际痛点说起去年有段时间团队内部一直在讨论一个问题大模型的能力已经这么强了写 prompt 也能让 ChatGPT 帮我们查资料、写周报、做总结但为什么一到“让 AI 自动完成一件跨系统的事情”就卡壳比如最简单的场景让 AI 每天早上帮运营盯一下数据大屏如果转化率异常就发一条告警到钉钉群并在当晚生成一份简短的分析说明。听起来不复杂真做起来却发现一连串麻烦——数据接口要鉴权、告警发送要走 webhook、分析说明需要关联前一天的活动数据、如果遇到数据缺失还得让它自己决定是重试还是跳过。传统机器人写法是一大堆 if-else 预设分支写死了路径换一个场景就又要改代码。那段时间我们试过不少方案直接给 LLM 塞工具函数定义、用 Function Calling 做单步调用、再往后是给模型配各种插件。它们都能解决“某一个环节的智能”但解决不了“多个环节串起来还能自己兜底”的问题。真正缺的东西我后来总结成一句话——Agent 够不够得着它该触达的系统与数据。模型再聪明如果它对内摸不清任务上下文、对外伸不向真实 API它就是一座孤岛。这个“够得着”的能力就是我们内部项目取名 Agent-Reach 的由来。Agent-Reach 的定位很简单一个面向业务场景的智能体触达框架。它不负责把你变身成 Prompt 工程大师也不负责帮你训模型它只解决一件事——让 Agent 的每一步行动真正落到外部系统里并且能够感知行动结果。这里的“外部系统”包括内部数据服务、第三方 API、数据库、消息通道也包括需要人工介入的审批流。你可以把它理解成一个连接大脑与肢体的神经通路大脑负责思考下一步做什么Reach 负责让这一步执行得出去、反馈得回来。适合谁看如果你正在做 AI 应用开发手头有 LLM 接口但不知道怎么稳定地编排工具调用或者你已经做过类似 ChatBot 但发现它只能聊天、不能办事又或者你在企业里负责引入 AI 能力需要一套可审计、可回滚、可观测的 Agent 执行方案——这篇文章的内容就是围绕这些场景展开的。2. Agent-Reach 的三层核心架构连接层、推理层、记忆层怎么分工整个框架我只设计了三个核心层刻意没有做得更复杂。复杂的东西听起来厉害但在实际维护时会变成灾难。三层的职责分开每一层只做自己该做的事调试时就能快速定位问题。2.1 连接层把工具描述变成 Agent 能看懂的系统调用连接层解决的是“Agent 如何触达外部能力”的问题。这一层维护一份工具注册表Tool Registry里面登记了所有可被 Agent 调用的能力。每个工具的描述信息遵循一套规范化的结构包含四部分工具名称、工具用途描述、输入参数 Schema、调用地址与鉴权方式。tool_schema { name: query_order_stats, description: 查询指定日期范围内的订单统计指标包括订单量、销售额、客单价、退款率等。, parameters: { type: object, properties: { start_date: {type: string, description: 起始日期格式YYYY-MM-DD}, end_date: {type: string, description: 结束日期格式YYYY-MM-DD}, channel: {type: string, enum: [all, mini_program, app, h5], default: all} }, required: [start_date, end_date] }, endpoint: http://internal-dashboard-api/v2/stats/order, auth_method: internal_token, timeout_ms: 5000 }这里有个细节值得单独说工具描述的正则语义空间。很多人把工具描述写得特别简陋比如“查询订单统计”模型在复杂场景里根本不知道什么时候该用这个工具、参数该传什么。我的经验是描述里宁可多写一句“当用户询问销售额、订单量等经营指标时优先使用本工具”也不要让模型自己猜。因为现代 LLM 的工具选择本质上是语义匹配你给的信息越贴近真实使用场景选错的概率就越低。连接层还要负责一件事统一返回结果。不管后端 API 返回的是 JSON、XML 还是纯文本连接层都会把它们标准化成结构化的执行结果对象ExecutionResult其中包括状态码、耗时、数据内容、附加元信息。这样推理层在处理结果时就不用关心每个工具的差异了。2.2 推理层让规划不再是一次性的推理层做的事情是 Agent 的“大脑”。它负责接收用户请求拆解任务决定调用哪些工具、按什么顺序调用并且根据工具的返回结果动态调整下一步计划。早期做的时候我的直觉是让 LLM 一次性生成一整套完整计划然后按计划顺次执行。结果发现这个方案在真实场景里完全行不通。原因是计划赶不上变化——第一个工具返回的数据可能跟预期不一致第三步前置条件没满足某个工具直接报错了这些情况下原计划半路就得改。所以 Agent-Reach 的推理层采用动态规划逐步执行的方式核心是一个执行循环循环开始 1. 将用户目标、当前任务上下文、此前工具调用记录整理为 prompt 2. 调用 LLM 进行推理模型决定下一步动作调用某个工具 / 问用户澄清 / 直接生成最终回答 3. 如果是调用工具走连接层执行拿到结果后附加到上下文回到步骤 1 4. 如果是生成回答把最终结果返回给用户循环结束这个循环看起来简单但它有一个隐含的优势——每一步决策都能看到前一步真实执行的结果而不是依赖模型脑补。比如模型第一次选择了query_order_stats结果发现返回里 channel 字段是空值它可以根据真实结果决定是改用all重新查询还是直接告诉用户数据源异常。这就是“够得着”的真正含义不仅能碰到系统还能根据碰到的反馈调整自己。2.3 记忆层短期会话记忆与长期事实记忆的分离推理层解决“当前这一步怎么做”记忆层解决“做这件事需要的背景信息从哪来”。我遇到过很多一次性的智能体 Demo 做得很好、多轮对话就露馅的情况根因就是没有设计记忆层。Agent-Reach 的记忆层分两块短期会话记忆保存当前任务会话里的所有中间状态。包括用户原始描述、工具调用记录、关键计算结果、已经放弃的备选方案。它存在的意义是让模型在每一步推理时都能“想起”之前发生过什么。实际存储时我用的是 JSON 形式的上下文累积每一轮执行后把关键信息追加进去。要注意控制短期记忆的体量——超过上限就把早期信息压缩成摘要否则 token 消耗会失控。长期事实记忆保存与具体会话无关的稳定信息。比如团队的业务术语表、常用数据口径、用户偏好、历史任务中总结出的规则。长期记忆的作用是让 Agent 在新任务里不必每次从零开始理解背景。这一块可以用向量数据库存 embedding需要时做相似度检索拉回上下文。记忆层设计里最重要的原则是——不把模型当作数据库。模型天生适合做推理不适合做精确记忆。凡是需要精确读取的信息比如“上个季度的毛利率是多少”务必走工具查数而不是靠模型回忆。凡是只需要大概印象的信息比如“用户倾向于关注哪些指标”可以用长期记忆模糊召回。这条原则帮我避免了很多“一本正经胡说八道”的尴尬。3. 一个最小可用系统的落地过程从任务规划到服务接入架构说完了来点实在的。我带着团队用一个周末搭了一个最小可用版本端到端跑通了“让 Agent 代替运营盯数据并发告警”的真实场景。下面是完整过程每一步都标了动机和踩坑点。3.1 第一步定义工具清单我们先梳理了执行这个任务需要的全部外部能力工具名用途返回内容query_order_stats查询订单统计指标订单量、销售额、客单价、退款率query_campaign_list查询进行中的活动列表活动ID、名称、时间、预算send_dingtalk_alert发送钉钉告警消息发送结果、消息IDfetch_previous_report读取昨天的分析报告报告文本定义工具清单的时候有一个比较反直觉的点工具数量不是越多越好。刚开始我们把十几个内部接口全部注册进去结果模型经常选错工具——因为它面对太多选项时选择的区分度降低了。后来我们把工具收敛到与当前任务强相关的几个正确率立刻上升。所以我的建议是先按任务维度配置最小工具集跑通了再逐步增加。每个工具的入参 Schema 都需要工程师手工确认。这里有个技巧——给参数加合理的枚举值和默认值。比如 channel 参数如果不加枚举模型可能会传小程序而后端只认识mini_program一次常见的字符串不一致就引发了串联失败。加了枚举后模型只能从给定选项里选出错概率大幅降低。3.2 第二步搭建执行循环执行循环是整个系统的心脏。最核心的一段代码如下async def agent_reach_loop(user_goal: str, context: AgentContext, max_steps: int 8): Agent-Reach 的核心执行循环 # 初始化短期会话记忆和工具执行历史 context.short_term_memory.add_event(user_goal, user_goal) step_count 0 while step_count max_steps: # 1. 组装推理 prompt messages build_reasoning_messages( goaluser_goal, memorycontext.short_term_memory.dump(), long_term_factscontext.long_term_memory.retrieve(user_goal) ) # 2. 调用 LLM 推理层决定下一步动作 action await llm_reason(messages) # 3. 根据决策类型分发处理 if action.type call_tool: tool tool_registry.get(action.tool_name) if not tool: context.short_term_memory.add_event(system_error, ftool not found: {action.tool_name}) continue result await tool.execute(action.arguments) context.short_term_memory.add_event(tool_result, { tool: tool.name, arguments: action.arguments, result: result.to_dict() }) elif action.type ask_user: return AgentResponse(requires_clarificationTrue, messageaction.message) elif action.type final_answer: return AgentResponse(requires_clarificationFalse, resultaction.message) else: context.short_term_memory.add_event(system_error, funknown action type: {action.type}) step_count 1 # 达到最大步数仍未收敛强制终止防止失控 return AgentResponse(requires_clarificationTrue, message已达到最大执行步数请确认流程是否合理)有两处值得解释。一是build_reasoning_messages。它不是简单地把历史记录堆进 prompt而是做了一层“上下文压缩”把工具返回的大段 JSON 提取成关键摘要避免 token 爆炸。比如查询订单统计返回了 100 行明细在执行历史里只留下汇总值、异常值和抽样样例即可。二是提前设计好的max_steps安全上限。真实场景里模型偶尔会陷入循环——反复调用同一个工具、得到同样的结果、再次调用像掉进死循环。限制最大步数是为了在失控时优雅退出而不是无限消耗 API 费用。这个上限的值要根据任务复杂度调简单任务 6 步以内复杂任务可以给到 15 步没有固定答案。3.3 第三步让 Agent 处理真实查询最小系统跑通后我们做了几个真实场景测试。最典型的输入是帮我看看昨天整体订单情况如果退款率超过 5% 就发个钉钉告警顺便发一条昨天活动的数据情况。如果你以为 Agent 会直接调用query_order_stats那就太小看这个任务的复杂度了。实际执行链路是这样的模型先识别出“昨天”需要日期计算于是隐含地需要获取当前日期然后调用query_order_stats传入昨天日期区间channel 默认为all拿到结果后模型需要判断退款率是否超过 5%——这一步是数值判断比较大小模型做得很稳因为用户提到了“昨天活动”模型调用query_campaign_list查活动列表再关联查询相关活动的统计最后把综合结果格式化输出报告文本。如果触发告警条件则调用send_dingtalk_alert。这个过程看起来很顺但在第 4 步上我们踩了一个有趣的坑模型先调了query_campaign_list拿到了活动名称再调用query_order_stats时把活动名写进了 channel 参数而后端 channel 只接受枚举值这一下就报参数错误。后来我们修改了query_order_stats的描述明确注明“如需查询某活动的数据请使用 activity_id 参数channel 仅用于渠道维度”同时还加了入参校验在连接层直接拦掉非法参数并返回错误信息让模型自己纠正。这说明给工具的输入做硬校验其实也是给模型当陪练。3.4 为什么这一步的工程质量决定上限我见过很多团队兴致勃勃搭完第一版 Demo就急着去接更多工具了。我要泼一盆冷水——Demo 能跑和系统稳定是两码事而这个阶段恰恰决定你能走多远。第一个要关注的是可观测性。Agent 的推理过程是黑盒你需要把每一步推理、每一个工具调用、每一次失败重试都记录成日志。我们在执行循环里埋了结构化日志包含步数、动作类型、工具名、入参、出参、耗时、模型响应。出问题时可以像回放电影一样把整个链路拉出来看。没有这套日志系统后面排查任何问题都是大海捞针。第二个是超时与重试策略。一个工具调用可能因为网络抖动、上游服务拥堵而超时。需要区分两种失败一种是立即失败比如参数错误重试没有意义一种是暂时失败比如上游 503重试可能成功。连接层针对不同错误码配置了不同的重试次数和退避策略。这里我的经验是不要盲目重试超过两次。试过就知道第三次重试成功率提升极其有限反而会让系统响应时间飙升。第三个是 Prompt 的稳定性。LLM 的输出不是确定的同样的输入可能导致不同的推理路径。我们后来引人了“固定思维链”技巧在系统提示词里写清楚每一步应该先做什么、遇到异常怎么处理。这本质上是把工程经验注入到模型的思考过程里让模型少走弯路。实测效果很明显——固定思维链之后工具选择准确率提升了近二十个百分点。4. 实战踩坑三连上下文丢失、超时误判、状态不同步把最小系统真跑起来之后问题像雨后春笋一样冒出来。这一节写三个我们花时间最长才定位的坑尤其是排查链路比最终答案更有价值。4.1 多轮调用之后 Agent 突然“失忆”的排查链路现象Agent 执行到第 4、5 步时突然像一个“金鱼记忆”的人明明第 2 步已经查过了订单数据它却再次调用同样的工具查同样的数据或者用户在第一轮明确说了“只看小程序渠道”到后面几步它突然忘了扩大到了全部渠道。第一次遇到的时候我第一反应是 Prompt 里的历史信息被截断了。顺着这个方向查发现代码里确实做了上下文压缩——build_reasoning_messages里把工具返回的长 JSON 转成了摘要。摘要里保存了“订单量、销售额、退款率”等汇总指标但丢掉了“channel: mini_program”这个筛选条件。看似无关紧要的细节被压缩掉了模型自然就忘了。排查链路总结如下先确认是不是截断问题看日志里实际发送给 LLM 的 prompt 上下文长度与上下文窗口上限比对再看压缩逻辑把压缩前后的文本拿来对照看哪些信息丢了最后发现是关键约束信息被压缩策略误删了。修复方案压缩策略改为“保留所有显式约束条件压缩数据细节”。也就是说用户说过的“只看小程序”“只看昨天”这类条件必须原样保留而工具返回的具体数值列表可以适当省略。这条原则后来写进了代码注释成了团队的铁律。还有个隐藏更深的坑短期记忆里的事件顺序。我们最初用 append-only 方式追加事件但多轮工具调用后模型对时间顺序会产生混乱。后来给每个事件加上了 step_id在组装 prompt 时按 step_id 排序彻底解决了这个顺序错乱问题。4.2 工具调用超时被误判为“系统不可用”现象用户让 Agent 查询一个跨月订单汇总这个查询在后端数据库里跑了大约 8 秒超过了我们设定的 5 秒超时阈值。连接层抛出了 TimeoutError模型看到错误后以为系统完全不可用于是回答“抱歉当前系统不可用请稍后再试”。而实际上数据查询只是慢不是挂了。这个坑的本质是错误信息语义不够精细。timeout和unavailable在模型看来差异不够明显都容易触发“无能为力”的回应。修复分两层。第一层是从执行结果里区分超时类型和具体错误码把timeout包装成“查询超时但服务状态正常可考虑缩小查询范围或稍后重试”第二层是把之前提到的 5 秒超时阈值提高到了 15 秒并增加了“工具执行进度提示”的机制——如果工具执行超过 3 秒就让模型向用户输出一条中间反馈比如“我正在查询上个月的订单数据数据量较大预计需要几秒钟”。这不只是体验优化也是在逼着模型理解“慢≠错”。4.3 多 Agent 并行时的状态边界后来我们把系统从单 Agent 升级到多 Agent 协作——一个负责查询数据一个负责撰写报告一个负责发送消息。问题来了三个 Agent 共享同一个短期记忆存储导致它们互相覆盖状态。负责写报告的 Agent 读到的“订单量”可能是负责查询的 Agent 上一个任务遗留的数据。这个问题的根源是没有给每个 Agent 划清状态边界。我们用session_id agent_role做记忆隔离每个 Agent 只读写自己的记忆空间需要传递信息时必须通过显式的“消息总线”传递而不是共享存储。在实际运行中这个方案还有一个附带的好处可追踪性大大增强。哪个 Agent 基于什么数据产生了什么结论全部有迹可循。做企业级应用时这一点对审计要求特别重要。5. 从“能跑”到“敢用”评估、护栏和扩展思路系统稳定跑起来离真正敢在企业环境里大规模使用还差几步。这一步是我建议所有做 Agent 应用的人都要认真对待的。5.1 离线评测集是“敢用”的入场券大模型应用的评测不能靠感觉。我们准备了一个小型但真实的评测集包含三类样本典型场景常见的查询、告警、报告生成任务占比约 60%边界场景数据缺失、参数非法、工具超时、上下文超长等占比约 30%对抗场景用户提问模糊、多条件交叉、前后矛盾、故意诱导调用无关工具等占比约 10%。每次改动推理层代码或调整 Prompt就整体跑一遍评测集看成功率变化。这个习惯帮我拦截了很多“看起来没问题一上线就翻车”的改动。评估指标方面不要只看最终成功率还要看过程质量。比如工具调用次数是否合理过度调用说明规划能力差、失败后模型是否能自我纠正有纠错能力比一次成功更有价值、执行耗时是否在可接受范围。我们把这三个维度的得分合成一个“执行健康度”作为每次迭代的对比基准。5.2 护栏设计权限、审计、人工确认Agent 能执行真实操作之后安全性的重要程度立刻超出功能本身。在 Agent-Reach 里我们加了三条护栏缺一不可。第一是权限控制。连接层里每个工具都绑定了调用权限不同用户角色只能调用被授权的工具。不能让普通运营的 Agent 拥有删库的能力。这里的实现不能只靠代码层过滤还要在外部 API 侧做校验防止绕过框架直连接口。第二是审计日志。Agent 的每一步执行都要写入独立的审计日志系统包括发起人、目标、工具、参数、结果、耗时。这不仅仅是合规需求也是回溯问题时最可靠的数据源。第三是高风险操作的人工确认。我们将工具按风险等级分类只读查询类低风险、写入类中等风险如发送通知、删除/变更类高风险如取消订单。低风险自动执行中高风险在执行前必须暂停等待用户在客户端点击确认。实现上就是在执行循环里增加一个requires_confirmation的状态触发之后暂停循环并推送确认请求。5.3 扩展思路向多智能体的协作网络演进单 Agent 是一个能干活的手多 Agent 才是一个能扛事的团队。Agent-Reach 当前版本以单 Agent 固定的工具集为主但架构设计上已经为多 Agent 协作留了接口。一个值得尝试的方向是“规划器-执行器”模式规划器 Agent 负责拆分任务和调度执行器 Agent 负责具体工具调用两边的记忆层物理隔离通过消息总线传递任务书和执行结果。这样可以做到扩展新执行器时不影响规划器的逻辑也能针对不同任务类型动态切换执行器组合。另一个方向是让 Agent 之间能“互相追问”。比如报告撰写 Agent 发现查询结果缺少对比基准它可以主动向数据查询 Agent 发出补充请求而不是在信息不完整的情况下硬着头皮写报告。这需要消息总线上支持请求-响应式的语义。如果要把 Agent-Reach 推向生产环境前置条件和环境准备是绕不开的功课。框架部署需要一台独立的节点机建议配置 4 核 8G 以上跑 LLM 推理可以走内部部署的模型服务也可以接托管的模型能力关键在于 API 访问的稳定性和权限隔离。数据库层面推荐 PostgreSQL用于存储任务记录、审计日志和长期记忆向量向量检索组件直接在数据库里扩展即可初期没有必要单独引入一套生态。工具接入涉及内部 API 网关时提前在网关侧开通独立的调用凭据会省去很多联调后期的效率拉扯。根据我个人经验Agent-Reach 最合适的切入场景不是“造一个全知全能的超级助手”而是“给现有业务里的人手边添一个能办事的副手”。把一条具体业务流程理清楚把工具打磨好把护栏立起来让它在一两个场景里老老实实干活比追求大而全靠谱得多。最后再分享一个小技巧实测在 Agent 的 prompt 里加入固定思维链之后工具挑选准确率和执行稳定性提升非常明显。你可以试着在系统提示词中写一段类似“先确认用户明确意图再判断是否需要工具介入调用工具后先验证返回结果再决定下一步行动”的引导语——这个细节能让模型减少很多无效推理。后续如果你也准备往多 Agent 的方向扩展建议提前把每个 Agent 的职责边界定义清楚接口层做好参数契约一旦跑起来还想大改成本就比现在高得多了。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑