Agent 项目从 Demo 走到生产环境,真正让人头疼的往往不是模型选型或 Prompt 调优,而是怎么把它跟企业里已经跑了十几年的 OA、ERP 系统接上。我最近刚交付完一个基于 MCP 协议的 Agent 集成项目,踩坑无数,也积累了一些实战经验。这篇文章就把整个过程中的核心思路、技术选型、实操步骤和避坑心得完整梳理一遍,适合正在做 Agent 落地、或者准备把 AI 能力接入企业存量系统的朋友参考。全文围绕 MCP 协议、OA/ERP 集成、FDE 角色定位、Agent 生产化这几个关键词展开,不讲虚的,只讲能直接抄作业的东西。
1. 为什么 Agent 接 OA、ERP 比调模型难十倍
1.1 模型能力早已不是瓶颈
过去一年我参与过好几个 Agent 项目,从最开始的"能不能跑通"到现在的"能不能上生产",感受特别深。模型侧的能力进步太快了,无论是工具调用、多轮推理还是结构化输出,主流大模型基本都能满足企业场景的需求。你让模型去理解一段采购申请、解析一张报销单、判断一个审批流程该走哪个分支,它做得比很多初级实施顾问都靠谱。
但问题在于,模型再聪明,它也得能"看见"OA 里的数据、"操作"ERP 里的单据。这就好比招了一个智商 180 的新员工,结果公司门禁不给他开、ERP 账号不给他建、OA 流程他不知道找谁审批——能力再强也白搭。
我见过太多团队在 Demo 阶段用 Mock 数据跑得飞起,一接真实系统就全线崩溃。崩溃的原因五花八门:OA 的接口文档是五年前的、ERP 的字段命名是拼音缩写、审批流的回调地址配错了、单点登录的 Token 过期策略跟 Agent 的长连接冲突……每一个都能让你调一整天。
1.2 OA 和 ERP 的"历史包袱"到底有多重
企业存量系统的复杂度,没做过集成的人很难想象。我拿几个真实案例说明:
泛微 OA 的建模引擎,字段类型有几十种,明细表里的下拉框变更会触发合计字段重算,这个联动逻辑在页面上是前端 JS 控制的,但通过 API 写入时如果不按它的规则来,合计字段就是错的。更坑的是,有些客户在建模引擎里加了自定义的触发脚本,你从外部写入数据会绕过这些脚本,导致业务数据不一致。
通达 OA的 CAS 单点登录,Token 有效期默认很短,而且不支持刷新。Agent 如果维持长连接,Token 过期后所有请求都会 401。你得在 Agent 侧做一个 Token 池,或者改用服务账号加 IP 白名单的方式绕开。
金蝶、用友这类 ERP,接口分好几层:有标准的 WebAPI,有老版本的 SDK,还有直接读数据库的"野路子"。标准接口稳定但覆盖不全,SDK 要装客户端,读数据库快但风险高。选哪条路,取决于你对数据实时性和一致性的要求。
1.3 FDE 这个角色为什么突然火了
FDE(Forward Deployed Engineer,前置交付工程师)这个概念最近被频繁提起,本质上就是"懂业务、懂系统、懂 AI"的复合型角色。Agent 上生产这件事,纯算法工程师搞不定,因为他不了解 OA 审批流的业务规则;纯实施顾问也搞不定,因为他不懂 Agent 的工具调用机制。必须有一个能同时跟业务方、IT 部门、算法团队对话的人,把需求翻译成技术方案。
我在项目里的角色就类似 FDE:上午跟财务总监聊报销流程的合规要求,下午跟 IT 部门确认 ERP 接口的权限边界,晚上回来改 Agent 的 Tool 定义。这个角色累,但价值极高,因为他是唯一能把"业务语言"和"技术语言"对齐的人。
2. MCP 协议到底解决了什么集成难题
2.1 从"每个系统写一个适配器"到"统一协议"
在没有 MCP 之前,Agent 接系统的方式是:给 OA 写一个 Tool,给 ERP 写一个 Tool,给 CRM 再写一个 Tool。每个 Tool 的入参格式、返回格式、错误码都不一样。Agent 的 Prompt 里要写一大堆"调用 OA 接口时参数是 A 格式,调用 ERP 时是 B 格式",模型很容易搞混。
MCP(Model Context Protocol)的核心价值,是把"工具的定义和调用"标准化了。它规定了 Server 怎么暴露工具、Client 怎么发现工具、调用时参数怎么传、结果怎么返回。这样一来,Agent 侧只需要实现一套 MCP Client,所有接进来的系统都通过统一的协议交互。
打个比方:以前每个系统说自己的方言,Agent 要学十种方言;现在 MCP 规定大家都说普通话,Agent 只需要会普通话就行。方言的翻译工作交给各个系统的 MCP Server 去做。
2.2 MCP Server 的三种典型实现方式
在实际项目里,我见过三种 MCP Server 的实现路径,各有适用场景:
| 实现方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 直接封装 HTTP API | 系统有完善的 REST API | 实现快,稳定 | 受限于 API 覆盖范围 |
| 封装 SDK/客户端库 | 系统提供官方 SDK | 功能全,类型安全 | 依赖特定运行环境 |
| 数据库直连 | API 缺失或性能要求极高 | 灵活,快 | 风险高,需严格权限控制 |
我个人的建议是:优先用官方 API,API 覆盖不到的地方再用 SDK 补,数据库直连作为最后手段,而且必须走只读账号加视图,绝对不能直接操作基表。
2.3 MCP 不是银弹:它解决的是"接口标准化",不是"业务语义对齐"
这里要泼一盆冷水。MCP 让工具调用变简单了,但它不解决业务语义的问题。比如 OA 里的"请假申请"和 ERP 里的"考勤异常",在业务上可能是同一件事,但字段定义、审批逻辑、数据归属完全不同。Agent 要正确处理,需要你在 MCP Server 里做语义映射,或者在 Agent 的 Prompt 里写清楚业务规则。
我踩过的一个坑:Agent 收到"帮我提交一个三天的事假申请",它调用了 OA 的请假接口,但没注意到这个客户的 OA 里事假和年假走的是不同审批流,结果提交到了错误的流程,被审批人打回。后来我在 MCP Server 的工具描述里加了详细的业务规则说明,才解决这个问题。
3. 把泛微 OA 接进 Agent 的完整实操
3.1 先搞清楚泛微 OA 的接口体系
泛微的接口能力在国产 OA 里算比较强的,但文档质量参差不齐。我梳理了一下常用的几类接口:
- 标准 REST API:
/api/workflow/request这类,用于发起流程、查询流程状态 - 建模引擎 API:
/api/formmode/data这类,用于操作自定义建模的数据 - 组织架构 API:
/api/hrm/user这类,用于查询人员、部门信息 - 文档 API:
/api/doc这类,用于操作文档中心
实际项目里,最常用的是流程和建模两类。流程接口负责"发起审批",建模接口负责"读写业务数据"。
3.2 认证方式的选择与 Token 管理
泛微支持多种认证:Token 认证、Session 认证、OAuth2。Agent 场景下我强烈建议用 Token 认证,因为它是无状态的,适合服务端调用。
Token 的获取方式:
# 获取 Token curl -X POST "https://oa.example.com/api/ec/dev/auth/applytoken" \ -H "Content-Type: application/json" \ -d '{ "appid": "your_appid", "secret": "your_secret" }'返回的 Token 默认有效期是 2 小时。Agent 如果长时间运行,必须做 Token 自动刷新。我的做法是在 MCP Server 里维护一个 Token 缓存,每次调用前检查剩余有效期,小于 10 分钟就重新获取。
注意:泛微的 Token 接口有频率限制,不要每次调用都去申请新 Token,否则会被限流。缓存是必须的。
3.3 流程发起接口的参数构造
这是最容易出错的地方。泛微的流程发起接口需要传一个复杂的 JSON,包含流程 ID、创建人、表单数据、审批人等信息。我拿一个请假流程举例:
{ "workflowId": "123", "creatorId": "1001", "requestName": "张三的请假申请", "formData": { "leaveType": "事假", "startTime": "2024-06-01 09:00", "endTime": "2024-06-03 18:00", "reason": "家中有事" }, "nextNodeId": "node_approve_1" }坑点在于:formData里的字段名不是随便起的,必须跟 OA 后台建模时的字段标识完全一致。而且不同客户、不同流程的字段标识都不一样。我的做法是先在 OA 后台导出流程的字段定义,然后在 MCP Server 里做一层映射,把 Agent 传过来的自然语言参数转换成 OA 需要的字段格式。
3.4 建模引擎数据写入的联动陷阱
前面提到过,泛微建模引擎的明细表下拉框变更会触发合计字段重算。这个逻辑在页面上是前端 JS 做的,通过 API 写入时不会自动触发。如果你写入的明细数据涉及金额、数量等需要合计的字段,必须自己算好合计值一起写入,否则数据就是错的。
我遇到过一个真实案例:Agent 帮用户提交报销单,明细里填了三条费用,但合计金额字段是空的。审批人看到合计为 0,直接打回。后来我在 MCP Server 里加了一个后处理逻辑,写入明细后自动计算合计并更新主表。
3.5 审批回调与 Agent 的状态同步
流程发起后,Agent 需要知道审批结果。泛微支持配置审批回调,审批完成后会 POST 一个通知到指定地址。我的做法是在 MCP Server 里暴露一个回调接口,收到通知后更新 Agent 侧的任务状态。
这里有个坑:回调地址必须是公网可访问的,而且泛微对回调的格式有要求。如果 Agent 部署在内网,需要做端口映射或者用消息队列中转。我一般用消息队列,MCP Server 收到回调后丢到队列里,Agent 异步消费,这样解耦更彻底。
4. ERP 集成的特殊挑战与应对策略
4.1 ERP 接口的"三层结构"
ERP 系统的接口通常分三层:
- 业务层 API:如"创建销售订单""查询库存",语义清晰,但覆盖有限
- 数据层 API:如"写入表 A 的记录",灵活但需要懂数据库结构
- 报表层 API:如"查询某报表数据",适合读取,不适合写入
Agent 集成优先用业务层 API,因为它的语义跟 Agent 的理解能力匹配。数据层 API 作为补充,但必须严格限制权限。
4.2 金蝶 ERP 的接口实践
金蝶的云星空系列提供了比较完善的 WebAPI。我以创建采购订单为例:
import requests def create_purchase_order(order_data): url = "https://erp.example.com/k3cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc" payload = { "formid": "PUR_PurchaseOrder", "data": { "FBillNo": order_data["order_no"], "FSupplierId": {"FNumber": order_data["supplier_code"]}, "FDate": order_data["date"], "FEntry": [ { "FMaterialId": {"FNumber": item["material_code"]}, "FQty": item["quantity"], "FPrice": item["price"] } for item in order_data["items"] ] } } response = requests.post(url, json=payload, cookies=get_session_cookie()) return response.json()金蝶的坑在于:它的字段名都是F开头的内部编码,而且不同版本、不同模块的字段名可能不一样。你必须拿到对应版本的字段对照表。我的做法是让客户 IT 部门导出一份字段清单,然后在 MCP Server 里做映射。
4.3 用友 ERP 的接口差异
用友的 U8 和 NC 系列接口风格差异很大。U8 比较老,很多接口是基于 COM 组件的,Agent 直接调用很麻烦。NC 系列有 REST API,相对友好。
对于 U8,我的建议是不要直接对接,而是在中间加一层适配服务,用 .NET 或 Java 封装 COM 调用,然后暴露 REST 接口给 MCP Server。这样虽然多了一层,但稳定性和可维护性好很多。
4.4 ERP 集成的权限与审计
ERP 涉及财务、库存等敏感数据,权限控制必须严格。我的做法是:
- MCP Server 使用专用的服务账号,只授予必要的权限
- 所有写操作记录审计日志,包括 Agent 的调用来源、参数、结果
- 敏感操作(如删除、修改金额)需要二次确认,Agent 不能直接执行
提示:ERP 的审计要求通常比 OA 高,上线前一定要跟客户的财务和内控部门确认权限方案,否则后期整改成本极高。
5. Agent 生产化的并发、稳定性与安全
5.1 并发场景下的 Token 与连接管理
Agent 上生产后,并发量可能远超预期。我遇到过一个场景:月底报销高峰期,Agent 同时处理几十个报销申请,每个都要调 OA 接口。结果 Token 申请接口被限流,大量请求失败。
解决方案是:
- Token 池化:预先申请多个 Token,轮询使用
- 请求队列:MCP Server 侧做限流,超过阈值的请求排队
- 连接复用:HTTP 连接池配置合理,避免频繁建连
5.2 错误处理与重试策略
企业系统的接口不稳定是常态。我的重试策略是:
- 网络超时:重试 3 次,间隔指数退避
- 业务错误(如参数错误):不重试,直接返回给 Agent
- 系统错误(如 500):重试 2 次,仍失败则告警
关键是区分错误类型,不能无脑重试。无脑重试会导致重复提交,比如重复创建了采购订单,那就麻烦了。
5.3 Agent 的安全边界
Agent 能操作 OA 和 ERP,意味着它有了很大的权限。安全边界必须划清楚:
- 只读操作:Agent 可以直接执行
- 写操作:需要人工确认,或者限制在特定范围内
- 删除、审批等敏感操作:禁止 Agent 直接执行
我在项目里实现了一个"操作分级"机制,MCP Server 根据操作类型决定是否需要人工介入。这个机制救过我好几次,有一次 Agent 误判了一个流程分支,差点提交了错误的付款申请,幸好被拦截了。
6. 从 Demo 到生产的完整交付清单
6.1 上线前的检查项
- OA/ERP 接口的连通性测试,覆盖所有用到的接口
- Token 刷新机制验证,模拟长时间运行
- 并发压力测试,确认限流和队列生效
- 错误场景测试,包括网络中断、接口报错、数据异常
- 权限验证,确认服务账号的权限范围符合预期
- 审计日志验证,确认所有操作可追溯
6.2 灰度上线的节奏
不要一次性全量上线。我的节奏是:
- 内部测试环境跑通全流程
- 客户测试环境用真实数据验证
- 小范围用户灰度,收集反馈
- 逐步扩大范围,监控指标
- 全量上线,持续监控
每个阶段至少观察一周,确认稳定后再进入下一阶段。
6.3 监控与告警
生产环境必须有监控。我关注的指标包括:
- 接口调用成功率
- 平均响应时间
- Token 刷新失败次数
- 队列积压长度
- Agent 任务完成率
告警阈值根据业务重要性设定,关键接口的成功率低于 99% 就告警。
7. 一些踩坑后的个人体会
做 Agent 集成这几年,最大的体会是:技术方案再先进,也得尊重企业存量系统的现实。OA 和 ERP 里沉淀了企业十几年的业务逻辑,这些逻辑可能没有文档、可能不合规范,但它们是真实运行的。Agent 要融入这个体系,不是去颠覆它,而是去适配它。
MCP 协议确实让集成工作标准化了很多,但它不是万能药。真正的难点在于理解业务、梳理流程、处理边界情况。FDE 这个角色的价值,就在于能把这些"脏活累活"扛下来,让 Agent 真正能在生产环境跑起来。
最后分享一个小技巧:每次集成新系统前,先花半天时间跟客户的业务人员聊天,让他们演示一遍完整的业务流程。你会发现很多文档里没写、但实际运行中必须遵守的"潜规则"。这些潜规则,往往就是 Agent 上线后最容易踩的坑。