AI Agent 对接 SAP,或许比你想的更简单 — 聊聊 /sap/bc/soap/rfc 这个容易被忽略的接口
AI Agent 对接 SAP,或许比你想的更简单 — 聊聊 /sap/bc/soap/rfc 这个容易被忽略的接口
做 AI Agent 对接 SAP 的过程中,无意间重新发现了一个存在了近二十年的内置端点。在 AI 重新丈量每一个技术细节的今天,这类「老东西」往往藏着意想不到的价值。
起因:给 AI Agent 找一条最省力的 SAP 入口
最近一直在探索 AI 如何在 SAP 场景下真正落地提效——不只是生成报告、辅助分析,而是让 Agent 直接参与业务执行:收货过账、查询库存、核对采购订单状态这类高频但重复的动作。
需求不复杂,但一上手就遇到了老问题:Agent 是 Python 技术栈,而 SAP 对外集成的方式五花八门——JCo、自封装 RESTful、OData……各有各的适用场景,也各有各的门槛。JCo 兼容性最广、不挑 SAP 版本,但得引入 JVM;OData 最现代,但许多 ECC 客户用不上;自封装 RESTful 灵活,但背后往往是一大堆 ABAP 开发在撑着。
引入 JVM、下载闭源的 JCo jar 包、处理 native 库的平台兼容性……这些事情做过的人都知道,不是不能搞定,但和 Agent 轻量化的理念确实格格不入。
起初的想法其实更”野心勃勃”一些——想做一个通用 SKILL,让 AI Agent 能够执行任意 SAP 事务代码或程序,不局限于某个具体业务。在和 AI 反复讨论技术方案、逐步拆解可行路径的过程中,AI 提到了一个之前没有认真对待过的方向——SAP 本身内置了一个通过标准 HTTP 调用 RFC 的端点:
/sap/bc/soap/rfc
这个路径在系统里默默待着,从 ECC 6.0 就有了,激活一下就能通过标准 HTTPS 调用任意 RFC 函数,不需要安装任何客户端库。
试了一下,requests 库发一个 SOAP POST,采购订单的 Header 数据就回来了。当时确实有点惊喜——这个东西一直都在,只是我从来没在这个场景下想到过它。
把这个场景具体化
仓库收货员拿着手机,对着企业的 AI 助手说一句话——
“PO 单号 6060003178,今天收到物料 1000-001,数量 100 件,帮我过账。”
AI 助手理解意图,自动提取关键信息,调用 SAP 完成收货(Goods Receipt)过账,返回物料凭证号。
整个过程,不需要打开 MIGO,不需要手动填表,也不需要 Java 服务做中间层。
这不是未来,今天就可以实现。背后用到的接口,就是这个安静存在了近二十年的 /sap/bc/soap/rfc。
先说说 RFC 是什么
RFC(Remote Function Call)是 SAP 自己定义的一套远程调用协议,简单来说就是让外部系统能够调用 SAP 内部的函数模块(Function Module)。
SAP 里有大量 RFC-enabled 的函数模块,覆盖了几乎所有业务操作——创建采购订单、过账物料凭证、查询库存、获取财务数据……这些函数模块经过 SAP 长期验证,接口稳定,是企业集成 SAP 的核心入口。
RFC 协议本身是 SAP 专有的,走的是特殊端口(通常是 33xx),需要客户端安装专门的连接库才能使用。这在企业内网环境里没问题,但当你想从现代 Web 服务、云环境或 AI 应用来调用时,就开始显得笨重了。
/sap/bc/soap/rfc 是什么
简单说,它是 SAP 在 HTTP 层给 RFC 套了一件新衣服。
通过这个端点,你可以用标准的 HTTPS + SOAP 协议调用任意 RFC-enabled 函数模块,不需要安装任何 SAP 专有客户端库,任何能发 HTTP 请求的工具或语言都能用。
从 SAP NetWeaver 7.0(ECC 6.0)开始,这个端点就已经内置在每一套 SAP 系统里了。不管是老旧的 ECC,还是最新的 S/4HANA On-Premise,只要在 SICF 里激活这个服务,就可以直接使用。这么多年过去,在 SAP On-Premise 的版本体系里,这个接口的兼容性一直保持稳定。
SAP 集成方式的演变:从 JCo 到自封装 REST
SAP 的对外集成方式并不少:RFC/BAPI 直连、PI/PO 消息中间件、IDoc 数据交换、OData REST 接口……每一种都有其适用场景。值得单独说一句的是版本覆盖问题——OData 主要面向 S/4HANA,大量仍在运行 ECC 6.0 的企业很难直接用上;而 /sap/bc/soap/rfc 从 ECC 6.0 就内置了,横跨几乎所有 On-Premise 版本,这一点在面对复杂的客户环境时,是一个实实在在的优势。
第一阶段:Java JCo 的黄金年代
如果你在做企业级 SAP 集成项目,团队里大概率在用或用过 Java JCo(SAP Java Connector)。
JCo 是 SAP 官方提供的 Java 客户端库,经过 SAP 认证,功能完整:支持连接池、支持 IDoc 收发、支持事务性 RFC(tRFC/qRFC)、支持负载均衡连接……几乎是 Java 技术栈做 SAP 集成的标准选择。
大量的 SAP 中间件、定制开发系统、MES/WMS 对接项目,走的都是这条路。在互联网化浪潮到来之前,这套方式运转得相当良好——企业内网稳定,Java 团队配套,Basis 负责开通端口,一切都在可控范围内。
它的问题不是功能,而是门槛:
-
• 需要 SAP Service Marketplace 账号下载闭源 jar 包 -
• 需要配套的 native 库,区分操作系统和 CPU 架构 -
• 需要 JVM 环境,与 Python/Go/Node.js 技术栈格格不入 -
• RFC 端口(33xx)需要防火墙单独开放,在云环境和零信任网络架构下越来越难申请 -
• 部署到容器环境时,native lib 的兼容性问题时常让人头疼
第二阶段:互联网浪潮带来的自封装 RESTful
进入移动互联网和微服务时代,前端和第三方系统普遍只认 RESTful JSON 接口,于是出现了在 SAP 侧通过 ABAP 开发封装一套统一 REST 服务的做法——对外暴露统一入口,通过接口 ID 区分不同业务操作。
这个做法解决了协议层的问题,但落地时往往没那么轻松:标准 BAPI 不一定能直接满足业务需求,复杂场景下需要组合多个 BAPI 才能完成一个完整动作,背后少不了大量 Z 函数模块的开发支撑;每新增一个业务场景就要同步维护 SAP 侧开发和接口层,久而久之形成一个越来越重的自维护体系。
第三阶段:OData 的理想与现实
S/4HANA 时代,SAP 推出了 OData / SAP Gateway,直接在系统内部暴露标准 RESTful 接口,理论上是最干净的解法。
但大量企业仍在运行 ECC 6.0,SAP Gateway 要么没部署,要么版本受限,OData 用不上。即便是 S/4HANA,标准 OData API 的覆盖范围也有限,碰到定制化场景还是绕不开 ABAP 开发。迁移到 S/4HANA 的工程浩大,不少企业的计划还排在好几年之后。
这样看下来,三个阶段的方案各有其历史合理性,也各有无法回避的局限。很多企业今天面对的现实是:JCo 的老系统还在跑,RESTful 封装层越来越重,OData 想用却用不上,新的 AI 集成需求又开始涌进来。
在这个背景下,/sap/bc/soap/rfc 或许值得重新认真看一眼——它不能解决所有问题,但在某些场景下,可能恰好是那块缺失的拼图。
/sap/bc/soap/rfc vs Java JCo:一张对比表
|
|
/sap/bc/soap/rfc |
|
| 客户端依赖 |
|
|
| 语言支持 |
|
|
| 防火墙 |
|
|
| 性能 |
|
|
| 连接池 |
|
|
| IDoc 支持 |
|
|
| 事务性 RFC |
|
|
| SAP 主动回调 |
|
|
| 部署复杂度 |
|
|
| 云/容器友好 |
|
|
| SAP 官方认证 |
|
|
| 监控工具 |
|
|
当然,JCo 在企业级产品化集成场景里依然是更成熟的选择,尤其是需要高并发、IDoc、或者 SAP 主动推送的场景。
但在 AI Agent、快速原型、非 Java 技术栈、或者云原生应用这些场景里,/sap/bc/soap/rfc 的优势非常明显——它让”调 SAP”这件事变得和调任何普通 HTTP 接口一样简单。
在 AI 时代,这个接口为什么值得重新关注
LLM 和 AI Agent 正在重塑企业软件的交互方式。过去需要人工登录 SAP、逐步操作界面的事情,现在可以让 Agent 来完成——用户只需要描述意图,Agent 负责拆解任务、调用接口、处理结果。
但 Agent 调 SAP,面临一个现实问题:Agent 几乎都是 Python 或 JavaScript 技术栈,引入 JVM + JCo 的成本太高,而且和 Agent 的轻量化理念不符。
/sap/bc/soap/rfc 在这里就显出了它的价值:
-
• 零依赖:Python 的 requests库就能搞定,不需要安装任何 SAP 相关的东西 -
• 标准协议:Agent Framework(LangChain、Claude Tools、OpenAI Function Calling)都能直接封装 HTTP 调用 -
• 覆盖范围广:任何 RFC-enabled 的 BAPI 都能调,业务覆盖面和 JCo 一样 -
• 防火墙友好:企业内网的 HTTPS 通道通常已经是畅通的
更重要的是,它让”非 SAP 开发者”也能对接 SAP。一个懂 Python 的 AI 工程师,不需要学 JCo 的那套体系,就能让 Agent 操作 SAP 业务。
实战示例:AI Agent 通过 SOAP 完成采购订单收货(GR)
下面用一个完整的例子说明整个流程。
业务场景
采购订单 6060003178 到货,物料 1000-001,收货数量 100 件,存放工厂 1000,仓库 0001。AI Agent 接收到这个信息后,自动调用 SAP 完成收货过账。
对应的 BAPI 是 BAPI_GOODSMVT_CREATE,这是 SAP 标准的物料移动创建接口,移动类型 101 代表采购订单收货。
Agent 工具定义
首先把这个 SOAP 调用封装成 Agent 可以调用的工具:
import datetimeimport requestsimport xml.etree.ElementTree as ETSAP_HOST = "https://10.112.38.109:8001"SAP_CLIENT = "800"SAP_USER = "sap_agent"SAP_PASSWORD = "your_password"defcreate_goods_receipt(po_number: str, material: str, quantity: float, plant: str, storage_location: str) -> dict:""" AI Agent 工具:针对采购订单创建收货凭证(移动类型 101) Args: po_number: 采购订单号,如 6060003178 material: 物料号,如 1000-001 quantity: 收货数量 plant: 工厂代码,如 1000 storage_location: 库存地点,如 0001 Returns: 包含物料凭证号和执行结果的字典 """ soap_body = f"""<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <BAPI_GOODSMVT_CREATE xmlns="urn:sap-com:document:sap:rfc:functions"> <!-- 凭证抬头:过账日期和凭证日期 --> <GOODSMVT_HEADER> <PSTNG_DATE>{datetime.date.today().isoformat()}</PSTNG_DATE> <DOC_DATE>{datetime.date.today().isoformat()}</DOC_DATE> <REF_DOC_NO>AI-AGENT-GR</REF_DOC_NO> </GOODSMVT_HEADER> <!-- 移动类型代码:01 = MB01 采购订单收货 --> <GOODSMVT_CODE>01</GOODSMVT_CODE> <!-- 行项目 --> <GOODSMVT_ITEM> <item> <MATERIAL>{material}</MATERIAL> <PLANT>{plant}</PLANT> <STGE_LOC>{storage_location}</STGE_LOC> <MOVE_TYPE>101</MOVE_TYPE> <ENTRY_QNT>{quantity}</ENTRY_QNT> <PO_NUMBER>{po_number}</PO_NUMBER> <PO_ITEM>00010</PO_ITEM> <!-- 行项目号,示例值,实际应按 PO 行号传入 --> </item> </GOODSMVT_ITEM> </BAPI_GOODSMVT_CREATE> </SOAP-ENV:Body></SOAP-ENV:Envelope>"""# 发送 SOAP 请求 response = requests.post(f"{SAP_HOST}/sap/bc/soap/rfc?sap-client={SAP_CLIENT}", data=soap_body.encode("utf-8"), headers={"Content-Type": "text/xml; charset=utf-8","SOAPAction": "BAPI_GOODSMVT_CREATE", }, auth=(SAP_USER, SAP_PASSWORD), verify=False, # 企业自签名证书场景,生产环境建议配置正确的 CA 证书 timeout=30, )if response.status_code != 200:return {"success": False, "error": f"HTTP {response.status_code}"}# 解析响应 root = ET.fromstring(response.text) ns = {"rfc": "urn:sap-com:document:sap:rfc:functions"} resp_node = root.find(".//BAPI_GOODSMVT_CREATE.Response", ns) or \ root.find(".//{urn:sap-com:document:sap:rfc:functions}BAPI_GOODSMVT_CREATE.Response") mat_doc = "" doc_year = "" messages = []if resp_node isnotNone: mat_doc = (resp_node.findtext("MATERIALDOCUMENT") or"").strip() doc_year = (resp_node.findtext("MATDOCUMENTYEAR") or"").strip()for item in resp_node.findall(".//RETURN/item"): msg_type = (item.findtext("TYPE") or"").strip() msg_text = (item.findtext("MESSAGE") or"").strip()if msg_text: messages.append({"type": msg_type, "text": msg_text})if mat_doc:# 有物料凭证号,过账成功,提交事务 commit_body = """<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <BAPI_TRANSACTION_COMMIT xmlns="urn:sap-com:document:sap:rfc:functions"> <WAIT>X</WAIT> </BAPI_TRANSACTION_COMMIT> </SOAP-ENV:Body></SOAP-ENV:Envelope>""" requests.post(f"{SAP_HOST}/sap/bc/soap/rfc?sap-client={SAP_CLIENT}", data=commit_body.encode("utf-8"), headers={"Content-Type": "text/xml; charset=utf-8","SOAPAction": "BAPI_TRANSACTION_COMMIT"}, auth=(SAP_USER, SAP_PASSWORD), verify=False, )return {"success": True,"material_document": mat_doc,"document_year": doc_year,"messages": messages, }else:return {"success": False, "messages": messages}
Agent 的完整对话流程
用户:PO 单 6060003178 到货了,物料 1000-001, 收了 100 件,放在 1000 工厂 0001 库位。Agent 思考: → 识别意图:采购订单收货 → 提取参数:PO=6060003178, 物料=1000-001, 数量=100, 工厂=1000, 库位=0001 → 调用工具:create_goods_receipt(...)Agent 工具调用结果: { "success": true, "material_document": "5000012345", "document_year": "2026", "messages": [ {"type": "S", "text": "物料凭证 5000012345 已过账"} ] }Agent 回复: ✅ 收货已成功过账! 物料凭证号:5000012345(2026 年度) PO 6060003178,物料 1000-001,收货 100 件。 你可以在 MIGO 或 MB03 中查看凭证详情。
几个值得注意的细节
COMMIT 不能省:BAPI_GOODSMVT_CREATE 执行成功后必须调用 BAPI_TRANSACTION_COMMIT 提交事务,否则数据不会真正写入数据库。凡是涉及数据写入的 BAPI 调用,都需要在成功后显式提交事务。
GOODSMVT_CODE 的含义:代码 01 对应的是 MB01 事务的收货操作,不是随意填写的,SAP 在 T158G 表里定义了所有合法的 GMCODE 值。
先模拟再过账:如果想加一层校验,可以先在 BAPI_GOODSMVT_CREATE 里加上 <TESTRUN>X</TESTRUN> 参数做模拟运行,确认无误后再去掉这个参数正式过账。
业务价值:这件事为什么值得做
最后聊聊这件事的意义。
SAP 过账对很多企业来说是一项重复性很高的工作——每天有大量的收货、发货、调拨、报废需要操作员一笔一笔录入。这些操作的共同特征是:流程固定、数据来源明确、规则清晰。
这类场景,恰好是 AI Agent 比较擅长处理的。
当 Agent 能够直接对接 SAP,业务价值是多维度的:
-
• 效率:仓库人员口述或扫码,Agent 实时完成过账,减少手动录入时间 -
• 准确:减少人工转录错误,Agent 从源头数据(WMS、IoT、扫码设备)直接提取参数 -
• 可追溯:每次 Agent 调用都有完整的输入输出日志,比人工操作更容易审计 -
• 门槛降低:不熟悉 SAP 界面的人员,通过自然语言也能完成标准业务操作
而 /sap/bc/soap/rfc 的价值,在于它把这条路的技术门槛降到了最低。SAP 这套能力早就在那里,只是需要一个合适的接入方式,让 AI 时代的工具能够顺畅地用起来。
结语
/sap/bc/soap/rfc 不是什么新技术,它在 SAP 系统里已经默默存在了很多年。但在 AI Agent 开始大量进入企业场景的今天,它的价值被重新发现了——作为一个轻量、通用、零依赖的 SAP 接入层,它让 Python 工程师、AI 工程师、甚至不懂 Java 的开发者,都能够把 SAP 的业务能力接进自己的系统里。
JCo 依然是企业级产品化集成的成熟选择,这一点没有变。但对于 AI Agent、轻量工具、快速验证这些场景,不妨重新看一眼这个容易被忽略的老朋友。
有时候,最合适的工具,早就在那里了。
本文代码示例基于真实系统验证,SAP S/4HANA 2021 OP 环境测试通过。
夜雨聆风