ARTICLE DETAIL

资讯详情

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

Agent上生产:系统接入才是拦路虎,MCP与适配层实战复盘

Agent上生产:系统接入才是拦路虎,MCP与适配层实战复盘 这个项目上线那天我们在会议室里等第一个真实工单。演示环境里模型表现得像个十年老员工能总结、能推断、能把完整执行计划列得清清楚楚。但生产环境里它要做的第一件事是把 OA 里一张审批单读进来再对着 ERP 里的科目去改一条凭证记录。就这一小步我们磨了整整两天。所以标题那句话不是段子是复盘完整个项目之后我们几个人一致认可的结论Agent 上生产最难的从来不是模型本身而是把 OA、ERP 这类企业存量系统接进来。模型再聪明拿不到业务数据就是空手道高手。这篇就是把我们这段经历中系统接入这部分完整拆开讲——包括我们为什么选择了 MCP 协议、为什么在 MCP 之上又加了一层 FDE MCP Blade 适配层、以及生产环境里那些文档永远不告诉你的坑。如果你正在做一个要连接企业系统的 Agent 项目或者你只是好奇AI Agent 落地时到底卡在哪这篇文章应该能帮你少走不少弯路。1. 模型从来不是短板系统接入才是拦路虎1.1 demo 的错觉模型会聊天不代表能连接做 Agent 项目几乎所有人都会先被模型的表现征服。我们当时的演示场景是让 Agent 扮演财务助理用户说一句帮我把这周报销单统计一下超预算的标出来模型回答得滴水不漏还能自己写 SQL、做汇总。客户当场拍板要上生产。但生产环境的内网里数据不是一张干净的 CSV而是一个个独立运行了几年的业务系统。OA 里有审批流、待办、表单ERP 里有供应商、科目、凭证、预算。Agent 第一步要做的不是思考而是连接——它得知道 OA 的登录地址、拿到会话票据、找到那张审批单的接口、解析返回参数再把结果翻译成 ERP 能认的科目编码。这一整套链路和模型聪明不聪明没有半点关系。说白了模型的能力是想清楚之后怎么做系统接入解决的是能不能够得着做这件事的原料。演示时我们喂给模型的是整理好的数据生产时模型要自己去一锅乱炖里捞食材难度完全不在一个量级。1.2 集成成本为什么总被严重低估很多人以为企业系统都有 API调一下就行。真实的情况是几十个系统、几百个接口文档七零八落字段命名各有一套方言接口返回的数据格式和数据库里的还不一样。我们当时做了个粗略盘点一个中等规模企业的核心业务链路涉及的接口调用串起来至少有七八层每一层都可能断。集成成本被低估主要在三个地方接口盘点阶段就要喝一壶。很多老系统的接口文档是 Word 版和线上版本已经对不上了只能靠抓包和翻旧代码一点点还原。语义对齐比技术对接更耗时。OA 里的报销项目和 ERP 里的费用科目明明是一件事字段名完全不一样枚举值也对不上Agent 传参时稍微模糊一点就出错。历史包袱躲不掉。字符集、时区、金额精度、分页上限这些脏活累活没有技术含量但每一个都可能让一次看似简单的调用直接失败。这些坑在项目规划和 demo 阶段几乎看不见只有真的把 Agent 挂到生产环境让它在真实数据上跑一遍才会集中爆发。我们正是在这个阶段慢慢意识到需要一套专门处理系统接入的中间层而不是靠模型自己去歪打正着。2. OA 与 ERP 原生集成差在哪三个最让人头疼的真实问题2.1 协议方言一套系统一套登录与调用标准OA 和 ERP 是两类完全不同的物种它们当初被设计出来时压根没想过有一天会让 AI Agent 来调用。拿 OA 来说以我们项目对接的泛微、致远这类产品为例最常见的是 SOAP WebService 加一套自定义的登录票据机制。你要先拿着账号密码换一个 session ticket后续每个请求都得带着它而且票据有过期时间可能在一次长任务跑到一半时就失效了。有些老版本 OA 还混合着 cookie、token、甚至 IP 白名单多种鉴权方式各自的过期策略还不一样。ERP 又是另一套脾气。金蝶、用友这类系统通常有企业服务网关接口风格五花八门有同步返回的也有提交后返回一个 job_id、真正结果要异步轮询的。也就是说Agent 调用一个创建凭证接口拿到的不一定是成功或失败而是一个我收到了你等会儿再来问的中间状态。模型对这种异步语义天然不敏感如果中间层不做封装它会把任务已提交误判成操作已完成。再加上字符集、时间格式、金额精度这些细节你会发现每个系统都在说自己的方言Agent 不可能靠通用能力去猜必须有人替它做翻译。这正是接入层必须存在的最直接理由。2.2 对象网络给 Agent 的不能只是接口得是领域答案更隐蔽的坑是业务对象之间的关联。一张 OA 里的报销单背后牵扯的不是一条记录而是一张关系网发起人属于哪个部门、部门挂在哪个成本中心、费用走哪个预算科目、审批流当前到哪一层、附件里有没有发票影像。Agent 要正确理解这张单能不能报销、超没超预算需要一次性拿到整张关系网而不是孤立地查一两个字段。我们最早犯的错就是把 OA 的查询表单详情接口直接暴露给 Agent。结果模型拿到一坨字段 ID 和部门编码完全不知道这些数字是什么意思只能瞎猜。后来才明白接入层不应该把原始接口抛出去而应该把系统翻译成模型能理解的领域答案。比如查完报销单后直接返回申请人王总监部门销售部费用类型差旅金额12800预算剩余3200当前审批人李总这种结构化描述模型才能做出后续判断。这也是为什么不能只做接口转发而必须做语义适配。中老年系统里字段命名混乱、冗余字段多、空值不空值也没个统一规范这些脏活如果不在一层里处理干净模型的错误率会居高不下。2.3 权限矩阵接口能调通不代表你有权调系统接入里最容易被忽视、也是讨论起来最容易起争执的是权限问题。接口层能连通不代表以 Agent 的身份调用就一定合法。企业系统的权限是分层的数据权限管你能看哪些部门/哪些金额范围功能权限管你能执行哪些操作审批权限管你能批到哪一级。更麻烦的是很多老系统的接口自身不做权限校验校验逻辑写在业务代码里。比如新增一张凭证接口可能只校验字段完整性真正判断这个人有没有权限往这个成本中心挂账的逻辑在后面的业务校验里。Agent 调用接口时如果带的是系统管理员的高权限 token它确实能调通但生产环境里这种能调通恰恰是事故的开始。我们后来定的原则是Agent 永远不要用管理员身份去调用业务系统每个工具调用都要映射一个最小权限的真实用户身份每一次写操作都要留下审计痕迹。这一块留到第 5 章详细讲但它绝对是上生产之前必须想清楚的问题。3. MCP 帮忙完成协议统一Blade 做的才是适配层的功夫3.1 MCP 到底是什么把接口爆炸变成工具列表MCPModel Context Protocol解决的是一个很朴素的问题如果每个业务系统都有一套自己的接入方式Agent 框架没法为每一个都写适配代码。MCP 把Agent 调用外部工具这件事标准化了Agent 端跑一个 MCP Client业务系统侧可以部署一个个 MCP ServerServer 把能力描述成工具列表每个工具包含名字、描述、参数 SchemaAgent 看到这些描述就知道该怎么调。这个抽象非常有用。我们先后对比过 Function Calling 直连、自研调度网关、MCP 三套路线。Function Calling 直连的问题是每个系统都得写一遍胶水代码系统一多就爆炸自研调度网关灵活但要自己维护一整套协议和客户端成本高。MCP 是现成的开源标准生态社区里已经有大量现成 Server而且主流 Agent 框架基本都原生支持。MCP 还有一个关键价值它把工具暴露和工具实现解耦了。Agent 框架只看 MCP Server 抛出来的工具描述完全不关心背后连的是 SOAP 还是 REST是同步还是异步。这相当于给各种系统的方言装了一层统一翻译机Agent 终于不用关心对面是谁了。3.2 为什么光有 MCP 还不够Blade 把适配层做薄做干净不过用上 MCP 只是第一步。我们很快发现如果只是把 OA 和 ERP 的原始接口原封不动注册成 MCP 工具模型面对几百个零散接口照样会迷路。你给模型一万个工具它连选哪个都费劲更别说每个接口的参数还那么不友好。于是就有了 FDE MCP Blade 这层设计。它本质上是一个运行在企业内网的轻量级 MCP 网关做三件事接口收敛把 OA、ERP 的几十上百个原始接口收敛成十几个有业务含义的领域动作比如发起审批、查询预算、创建凭证。语义翻译把系统返回的原始数据结构处理成 Agent 能直接理解的领域答案同时把脏数据、空值、枚举码这些问题在这一层消化掉。安全收敛统一在这里做身份映射、权限校验、操作审计、幂等控制不让模型直接碰到业务系统的原始凭证和 token。Blade 这个词在我们内部其实就是薄薄的一层刀片的意思——它不该变成巨石应用也不该承载复杂业务逻辑它只负责把系统世界和模型世界之间的边界切干净。模型越自由适配层越要克制越要稳。3.3 工具 Schema 设计的核心心得让模型少猜多做工具 Schema 写得好不好直接决定 Agent 的调用准确率。我们的经验是三个字少、明、稳。少指的是参数必填项尽量少。模型每次调用都要自己推断参数必填项越多错得越多。默认值能在适配器里处理的就绝不让模型填。明指的是每个参数描述的颗粒度要到给实习生看也能看懂的程度。比如date_range要写成查询的起止日期范围格式 YYYY-MM-DD默认近30天而不是简单写时间。稳指的是返回结构永远稳定status、data、message 三段式哪怕出错也要返回结构化错误信息绝不允许模型面对一段裸报错自己猜。这套设计听起来不复杂但实际效果非常明显。改完 Schema 之后Agent 的首次调用成功率从不到六成提到了九成以上很多无谓的重试和幻觉直接消失了。4. 一条真实接入链路复盘从 OA 里查单到 ERP 里改单4.1 场景设定财务助理完成差旅报销过账拿一个我们生产环境里真实跑过的场景举例用户说查一下王总监上个月的差旅报销批了没批了的话在 ERP 里做一张凭证。这个需求本质上要跨 OA 和 ERP 两个系统完成一段完整的业务闭环第一跳Agent 调用 OA 的模糊查询工具按申请人、时间段找到对应审批单第二跳调用 OA 的单据详情工具拿到审批状态、金额、部门、费用类型第三跳Agent 判断状态为已审批通过后调用 ERP 的凭证创建工具把报销单信息映射成科目和金额第四跳回写状态把 ERP 生成的凭证号写回 OA 的自定义字段方便业务人员核对。这四个跳看起来简单但我们第一次跑通花了快两周。问题不发生在任何一步的单点能力上而是每一步之间的衔接——比如 OA 返回的审批状态枚举值是数字模型不知道 3 到底代表通过还是驳回再比如 ERP 的科目编码和 OA 的费用类型不是一一对应的中间需要一个映射表。4.2 工具的 Schema 与适配器细节下面是我们实际注册到 FDE MCP Blade 里的三个核心工具简化版{ name: oa_search_approval, description: 按申请人和时间范围查询OA审批单列表返回审批单ID、标题、状态、金额。状态枚举0草稿/1审批中/2已通过/3已驳回, inputSchema: { type: object, properties: { applicant: {type: string, description: 申请人姓名必填示例王总监}, start_date: {type: string, description: 开始日期格式YYYY-MM-DD默认当月1日}, end_date: {type: string, description: 结束日期格式YYYY-MM-DD默认今天} }, required: [applicant] } }{ name: erp_create_voucher, description: 创建ERP记账凭证。调用前必须确认审批单状态为已通过(2)。凭证号为异步返回需要调用erp_query_voucher确认最终结果。该操作不可重复提交重复调用需携带相同request_id, inputSchema: { type: object, properties: { request_id: {type: string, description: 幂等键建议用OA审批单号}, voucher_date: {type: string, description: 凭证日期YYYY-MM-DD}, amount: {type: number, description: 金额单位元保留两位小数}, cost_center: {type: string, description: 成本中心编码来自OA部门映射}, subject_code: {type: string, description: 会计科目编码差旅费默认550101} }, required: [request_id, amount, subject_code] } }这里有个心得工具描述里要把隐含业务规则显式写出来。比如 erp_create_voucher 里明确写了调用前必须确认审批状态为已通过模型看到这句话就会先做前置校验而不是盲目创建凭证。这就是文档不写但生产必需的细节。4.3 三个绕不过去的坑会话过期、重复提交、异步回执生产联调阶段我们踩了三个最有代表性的坑。第一个是 OA 会话过期。OA 的登录票据有效期一般是 30 分钟而 Agent 处理一条复杂链路可能要反复调用十几次中途票据就失效了。我们在适配层做了一个透明处理工具调用前自动检测票据有效期剩五分钟时先刷新再执行业务动作。这个逻辑如果放在 Agent 层模型是感知不到票据只剩两分钟这种系统细节的。第二个是 ERP 重复提交。Agent 在等待异步返回时可能超时重试如果重试时再调一次创建凭证ERP 里就会出现两张一模一样的凭证。解决办法就是我们工具定义里的 request_id 幂等键——用 OA 审批单号做幂等键适配层在请求创建前先查一下这个 request_id 是否已存在存在就把旧结果返回而不是重复创建。第三个是异步回执的中间状态误导。ERP 创建凭证接口通常立即返回一个 job_idAgent 看到返回成功就以为完事了实际上凭证可能还在排队甚至最终失败。我们的解法是把工具返回结构统一改成已提交但未确认状态并强制要求 Agent 调用查询接口确认最终结果后才允许向下执行。这三个坑有一个共性它们都是系统世界与模型世界信息不对称造成的。模型习惯了一步到位的交互方式而企业系统充满了中间态、过期态和不确定态。适配层存在的意义就是替模型把这些不确定性消化掉。5. 敢上生产的底线设计权限收敛、审计与可控性5.1 最小权限与身份映射Agent 绝不拿着管理员钥匙跑系统接入跑通之后团队内部最容易松的那根弦是反正都连上了给 Agent 配个高权限账号最省事。这个想法非常危险因为模型的行为不是百分百可预测的你无法保证它在哪次调用里会做出超范围的写操作。我们采用的方案是双身份映射每一次工具调用都以当前对话的发起人作为业务系统里的操作身份。也就是说用户让 Agent 查自己部门的报销单Agent 在 OA 里实际使用的就是该用户本人的账号权限查不出权限范围外的数据要执行创建凭证这类写操作同样走该用户的权限校验。同时适配层还要做一道清单检查哪些工具属于只读类、哪些属于写操作类。只读工具可以直接放行写操作工具默认进入待确认状态除非在系统配置里明确标记为可信自动执行。这个开关一开始我们全部置为需要人工确认跑了两个月逐步放开一小部分才敢让 Agent 真正无人值守。5.2 审计与断点接管Agent 的每个动作都要讲得清楚Agent 项目上线后业务方最常问的一句话不是它做对了没有而是它做了什么、为什么要这么做。所以我们从第一天起就坚持把两条日志写全一条是工具调用轨迹记录每次调用的工具名、参数、返回结果、耗时、对应到哪个业务系统另一条是模型推理摘要记录它基于什么信息做出了这个调用决策。这两条日志的作用在出问题的时候就能体现出来。有一次 ERP 里多了一张凭证财务来问怎么回事我们翻工具调用轨迹发现是 Agent 在异步轮询时误判了 job_id 的归属把上一个任务的凭证状态当成了当前任务的于是又补了一张修正凭证。如果没有轨迹日志这种连锁误操作几乎没法定位。另外我们还做了一个小功能人工断点接管。Agent 在执行链路中如果检测到异常比如审批状态从通过变成了驳回会主动停下来在协作工具里通知人而不是自作聪明地绕过去。后来复盘时我们认为这个停下来问人的设计比任何护栏都管用。5.3 稳定性设计超时、重试和限流都得在适配层做最后聊稳定性的几个细节。Agent 业务的特点是并发不确定用户可能同时发起几十个任务也可能一个任务里连续调用几十次接口。企业系统的接口从来不是给这种访问模式设计的被冲垮的风险是真实存在的。我们在 FDE MCP Blade 里做了三件小事第一给外部系统调用统一设置超时时间OA 的读操作给 10 秒ERP 的写操作因为可能排队给到 60 秒超过就返回超时错误而不是无限等第二重试区分幂等与非幂等读操作可以自动重试三次写操作只允许使用幂等键重试否则直接转人工第三对后端系统做简单的并发限流每系统每秒最多放行多少请求超出部分排队等待避免 Agent 的一波并发把老系统打挂。这些设计在联调阶段完全看不见价值但生产跑一段时间后你会发现系统稳定性问题的根源基本都在接入层。模型本身反而不容易出幺蛾子它出问题是有规律可循的而系统超时、票据失效、数据对不上这些事才是真正防不胜防的。如果你也在做类似的 Agent 接入项目我的建议很简单先把系统接入层当成一个独立的工程来对待别把它当成模型能力的附属品。模型迭代很快但企业系统不会一夜之间长出新接口把那层脏乱差消化在适配器里所有的业务逻辑和权限控制都在这一层收敛清楚Agent 上层反而可以保持轻盈。最后再分享一个我们在写工具描述时总结的小技巧把所有工具的 description 都当成给实习生写的操作手册来写明确写清楚前置条件、返回含义、枚举值、注意事项而不是写查询报销单这种一句话描述。模型每次调用前都会读这些文字你写得多清楚它就执行得多靠谱。这套 FDE MCP Blade 我们还在往更多系统上铺但核心思路没变模型负责聪明适配层负责靠谱。
返回列表