1. 背景
在企业采购管理中,采购人员要在SAP中进行RFQ查询、供应商信息核对、PO创建等流程操作,存在信息分散、查询效率低、流程衔接不畅等痛点。传统方式下,采购人员需在SAP系统、Excel报表、邮件等多渠道切换,不仅耗时耗力,还容易因信息不对称导致决策延迟或采购风险。本文将介绍如何通过Bedrock AgentCore Runtime, Strands Agents SDK以及Glue,实现与SAP进行数据集成,开发部署Agent,构建SAP智能采购助手的方案。
2. 基于Strands框架和Bedrock AgentCore的SAP智能采购助手系统架构设计
2.1 SAP操作现状分析
企业的采购管理人员需要在SAP GUI中执行多个事务码,如ME41查询询价单、ME47查看报价、XK03查询供应商信息,然后再用ME21N创建采购订单,这一过程需要频繁切换事务码和操作界面;本文要通过AWS的服务和GAI的能力,采购人员以Chat自然语言聊天的方式来替换在SAP GUI中的各项操作。
2.2 解决方案设计思路
SAP智能采购助手,在获取采购人员的自然语言以后,要通过Agent识别采购人员的意图;通过Tools实现采购相关RFQ查询、报价数据查询,供应详细数据查询,以及采购订单的创建;在数据集成和管理层面,过AWS的服务Glue实现SAP数据的ETL,通过AWS的Lambda调用SAP Gateway的API以实现创建采购订单,具体设计思路详见图1。
图1 解决方案设计思路
2.3 方案系统架构设计
本方案以云原生技术为核心,实现SAP数据与AWS AI服务的无缝协同,架构分为数据层、智能层、交互层三个核心部分。
核心业务流程说明
- 数据流转:通过AWS Glue(odata)从SAP抽取数据至S3,Athena 使用 Glue Data Catalog 作为其元数据存储库;
- 智能交互:前端通过调用AgentCore Runtime的智能体发起自然语言请求,Strands Agent调度对应Tools处理;
- Tools执行:查询类请求通过Lambda驱动Athena/S3查询,创建类请求通过Lambda调用SAP Gateway的API接口,知识类请求通过Bedrock Knowledge Base获取;
- 会话管理:Bedrock AgentCore Memory记录对话上下文,支持多轮连续交互。
图2 详细系统架构设计图
3. 系统架构功能实现
3.1 SAP数据系统集成
(1)数据集成协议ODATA
SAP OData 是一种标准 Web 协议,用于使用 ABAP(高级业务应用程序编程)查询和更新 SAP 中存在的数据,应用和构建 HTTP 等 Web 技术,以提供对来自各种外部应用程序、平台和设备的信息的访问权限。OData 更适合现代化的 API 驱动架构,提供更好的可维护性和扩展性;可以实现与 SAP 系统、应用程序或数据无缝集成。
(2)Glue Odata实现SAP数据的ETL
通过OData协议连接SAP系统,批量抽取RFQ、报价单、供应商主数据、物料信息等,经ETL转换后存储至S3;AWS AppFlow也支持OData协议,在本文的方案中,需要数据类型转换等ETL操作,所以最终选择AWS Glue实现与SAP的数据系统集成。
图3 通过Glue SAP OData创建Connection
3.2 Agent框架及功能实现
(1)Agent开发框架
本次实践的Agent采用Strands 框架,Strands Agents SDK是亚马逊云科技发布的开源AI智能体SDK,可以简化智能体开发,充分利用最新大语言模型的原生推理、规划和工具调用能力,而不需要复杂的编排逻辑,用寥寥数行代码构建功能强大的 Agentic AI 应用。
(2)Agent运行逻辑
本次实践采用Orchestrator 模式 (Tool Use),实现模型推理和执行工具的循环过程,直至达到业务目标,代码结构更简单、更符合人的主观逻辑;Agent中提供工具体系化的Prompt;并内置Tools; Tools以自定义的方式实现,包括采购查询、采购订单创建、知识库查询工具,在每个Tool中有准确的功能描述,以实现Agent能准确调用有效的Tool。具体实现逻辑如图4所示。
图4 Agent实现逻辑
(3)自定义Tools实现
本次实践中采购操作执行的Tools通过AWS Lambda进行自定义;供应商提供的物料详细信息、具体付款和可持续性信息,通过Bedrock Knowledge Base实现。
- 基于Lambda的Tools:一个Tool是封装Athena查询,支持采购询价、报价单、价格和供应商基础信息等整个流程所需要的业务数据查询;另一个Tool是通过调用SAP Gateway暴露的API接口实现订单的创建,接口信息和认证通过Lambda的环境变量的URL以及AWS Secrets Manager的认证信息实现。
- 基于Bedrock Knowledge Base的Tools:本文通过自定义方式将Knowledge Base封装成Tool; Bedrock Knowledge Base通过S3存储供应商付款条件、碳排放标准、采购政策等非结构化信息;Amazon Bedrock 知识库作为完全托管式 RAG 解决方案,可以灵活地进行自定义并提高检索准确性。
(4)Agent的部署环境
本文基于Strands框架的Agent通过Amazon Bedrock AgentCore进行部署和运行;Amazon Bedrock AgentCore适用于任何框架和模型,用于安全、可扩展地部署和运营Agent的全套服务。AgentCore 提供各种工具和功能,使代理更高效、更强大;提供专用的基础设施,用于安全地扩展代理。本文将采用Bedrock AgentCore Runtime,托管SAP采购智能体,Bedrock AgentCore Memory提供短期记忆(short-term memory),记录对话上下文。
图5 Agent构建及在AgentCore Runtim的部署逻辑
4、具体配置与代码实现
4.1 SAP数据到AWS的同步实现
AWS Glue数据抽取,通过Glue的/OData连接配置,定时从SAP的EKKO和EKPO表中抽取采购业务的数据,通过Glue的ETL,存入S3。
(1)SAP系统的相关配置实现
- 在 SAP 系统的 SAP 网关中配置要提取的操作数据供应(ODP)数据来源。
- OData V2.0:可以通过事务/IWFND/MAINT_SERVICE 在 SAP 网关中启用 OData V2.0 目录服务。
- 通过事务/IWFND/MAINT_SERVICE 在 SAP 网关中启用 OData V2.0 服务。
图6 SAP Gateway Client测试服务发布状态
(2)Glue的配置实现
创建AWS Glue OData Connection时,提供配置连接的 SAP OData 实例的应用程序主机 URL和SAP OData 实例的应用程序服务路径等信息,AWS Secrets Manager 用于安全存储 SAP 凭证等敏感信息,AWS Glue 作业可以在运行时动态检索信息,从而增强了安全性和灵活性。
图7 OData创建Connection的配置详情
4.2 Agent核心实现
本次的SAP职能采购助手的实践中,我们采用了如下的多Agent编排的架构,让查询等各项操作能够更精确有效的执行;基于Strands框架开发Agent,集成Athena查询Lambda、PO创建Lambda、知识库查询三个核心工具,并配置AgentCore Memory管理会话。
# 系统提示词
SYSTEM_PROMPT = """你是一位专业的SAP可持续性采购顾问,专门从事供应链分析和可持续采购决策支持。
## 专业身份
作为采购领域的专家,你具备深厚的SAP系统经验和可持续性评估能力,能够为企业提供数据驱动的采购决策支持。
## 可用工具
1. **query_sap_data**: 查询SAP数据
- 支持RFQ查询、报价统计等
- 参数:query_type, year, month, days等
- 示例:query_sap_data("monthly_rfqs", year=2025, month=7)
2. **query_sustainability_knowledge**: 查询可持续性知识库
- 获取付款条件、认证信息等
- 参数:query (查询问题)
- 示例:query_sustainability_knowledge("供应商**的付款条件?")
3. **create_purchase_order**: 创建采购订单
- 基于报价单创建采购订单
- 参数:quotation_id (报价单编号)
- 示例:create_purchase_order("6000000262")
## 工作流程
1. 理解用户需求
2. 选择合适的工具获取数据
3. **仔细检查和解析工具返回的数据**
4. 分析数据并提供洞察
5. 给出可执行的建议
(2) Agent核心代码和Tools注册
# Agent配置
agent = Agent(
model=model,
tools=[
query_sap_data,
query_sustainability_knowledge,
create_purchase_order
],
system_prompt=SYSTEM_PROMPT
)
@app.entrypoint
def main(payload):
"""AgentCore Runtime入口点"""
try:
# 标准化输入处理
user_input = payload.get("prompt") or payload.get("user_input", "")
if not user_input:
return "请提供您的问题或需求。
logger.info(f"Processing request: {user_input[:100]}...")
# 执行Agent
result = agent(user_input)
logger.info("Request processed successfully")
return str(result)
except Exception as e:
error_msg = f"处理请求时发生错误: {str(e)}"
logger.error(error_msg)
return error_msg
if __name__ == "__main__":
app.run()
4.3 自定义Tools实现
(1)SAP数据查询Tools
根据RFQ编号、供应商ID查询相关物料、价格及状态信息;代码实现如下:
""
SAP数据查询工具
"""
import boto3
import json
from typing import Dict, Any, Literal
from strands import tool
from ..config import settings
from ..utils import get_logger
logger = get_logger(__name__)
@tool
def query_sap_data(
query_type: Literal[
"monthly_rfqs", "recent_rfqs", "all_rfqs", "count_quotations", "quotation_summary",
"lifecycle_status_query", "quotation_comparison", "material_detail_query",
"payment_terms_analysis", "data_validation_query", "purchasing_org_query",
"amount_range_query", "incoterms_query", "manufacturer_query", "plant_query",
"purchase_requisition_query", "exchange_rate_query"
],
**kwargs
) -> Dict[str, Any]:
"""
查询SAP数据API
Args:
query_type: 查询类型,支持的值:
- monthly_rfqs: 查询指定年月的RFQ (需要year, month参数)
- recent_rfqs: 查询最近的RFQ (需要days参数)
- all_rfqs: 查询所有RFQ (无需参数)
- count_quotations: 统计报价数量 (需要requestforquotation参数)
- quotation_summary: 报价汇总 (需要requestforquotation参数)
- lifecycle_status_query: 生命周期状态查询 (需要status, limit参数)
- quotation_comparison: 报价比较 (需要requestforquotation, limit参数)
- material_detail_query: 物料详情查询 (需要requestforquotation, limit参数)
- purchasing_org_query: 采购组织查询 (需要purchasingorganization, limit参数)
- manufacturer_query: 制造商查询 (需要limit参数)
- plant_query: 工厂查询 (需要limit参数)
- purchase_requisition_query: 采购申请查询 (需要limit参数)
- exchange_rate_query: 汇率查询 (需要limit参数)
**kwargs: 查询参数
- year (int): 年份 (用于monthly_rfqs)
- month (int): 月份 (用于monthly_rfqs)
- days (int): 天数 (用于recent_rfqs)
- requestforquotation (str): RFQ编号 (用于quotations相关查询)
- status (str): 生命周期状态 (用于lifecycle_status_query)
- limit (int): 结果数量限制 (用于多个查询类型)
- supplierquotation (str): 供应商报价单号 (用于data_validation_query)
- purchasingorganization (str): 采购组织 (用于purchasing_org_query)
- min_amount (float): 最小金额 (用于amount_range_query)
- max_amount (float): 最大金额 (用于amount_range_query)
- currency (str): 货币代码 (用于amount_range_query)
Returns:
Dict[str, Any]: 查询结果,包含success状态和data数据
Example:
>>> query_sap_data("monthly_rfqs", year=2025, month=7)
>>> query_sap_data("recent_rfqs", days=30)
"""
try:
logger.info(f"Querying SAP data: {query_type} with params: {kwargs}")
lambda_client = boto3.client('lambda', region_name=settings.AWS_REGION)
# 处理Agent框架包装的kwargs参数
if 'kwargs' in kwargs and isinstance(kwargs['kwargs'], str):
import json
actual_params = json.loads(kwargs['kwargs'])
else:
actual_params = kwargs
# 构建查询参数
payload = {
"query_type": query_type,
"parameters": actual_params
}
# 为需要limit参数的查询添加默认值
limit_required_queries = [
"lifecycle_status_query", "quotation_comparison", "material_detail_query",
"payment_terms_analysis", "purchasing_org_query", "amount_range_query",
"incoterms_query", "manufacturer_query", "plant_query",
"purchase_requisition_query", "exchange_rate_query"
]
if query_type in limit_required_queries and "limit" not in actual_params:
payload["parameters"]["limit"] = 50
response = lambda_client.invoke(
FunctionName=settings.SAP_LAMBDA_NAME,
Payload=json.dumps(payload)
)
result = json.loads(response['Payload'].read())
logger.info(f"SAP query completed successfully: {query_type}")
logger.info(f"Lambda result: {result}")
# 直接返回Lambda的结果,让Agent处理
return result
except Exception as e:
error_msg = f"查询SAP数据时发生错误: {str(e)}"
logger.error(error_msg)
return {
"success": False,
"error": error_msg
}
(2)知识库查询Tools
知识库查询,解答供应商付款条件、物料详情、物料碳排放、采购政策等问题,代码实现如下。
import boto3
from strands import tool
from ..config import settings
from ..utils import get_logger
logger = get_logger(__name__)
@tool
def query_sustainability_knowledge(query: str) -> str:
"""
查询供应商可持续性知识库
Args:
query: 查询问题,如"某供应商的ESG评级"、"可持续发展认证要求"等
Returns:
str: 知识库查询结果
Example:
>>> query_sustainability_knowledge("什么是ESG评级标准?")
"""
try:
logger.info(f"Querying sustainability knowledge: {query[:50]}...")
bedrock_client = boto3.client('bedrock-agent-runtime', region_name=settings.AWS_REGION)
response = bedrock_client.retrieve_and_generate(
input={'text': query},
retrieveAndGenerateConfiguration={
'type': 'KNOWLEDGE_BASE',
'knowledgeBaseConfiguration': {
'knowledgeBaseId': settings.KNOWLEDGE_BASE_ID,
'modelArn': settings.KNOWLEDGE_BASE_MODEL_ARN
}
}
)
result = response['output']['text']
logger.info("Sustainability knowledge query completed successfully")
return result
except Exception as e:
error_msg = f"知识库查询失败: {str(e)}"
logger.error(error_msg)
return error_msg
(3)采购订单(PO)创建Tools
根据报价单ID创建采购订单,需确认采购数量、交货日期等参数,代码实现如下。
import boto3
import json
from typing import Dict, Any
from strands import tool
from ..config import settings
from ..utils import get_logger
logger = get_logger(__name__)
@tool
def create_purchase_order(
quotation_id: str
) -> Dict[str, Any]:
"""
创建SAP采购订单
Args:
quotation_id: 报价单编号 (如: 6000000262)
Returns:
Dict[str, Any]: 采购订单创建结果
Example:
>>> create_purchase_order("6000000262")
"""
try:
logger.info(f"Creating purchase order for quotation: {quotation_id}")
lambda_client = boto3.client('lambda', region_name=settings.AWS_REGION)
payload = {
"apiPath": "/createPO",
"httpMethod": "POST",
"requestBody": {
"QuotationID": quotation_id
}
}
response = lambda_client.invoke(
FunctionName="SAPPOC-action-sap-gai-west-new",
Payload=json.dumps(payload)
)
result = json.loads(response['Payload'].read())
logger.info(f"Purchase order creation completed for quotation: {quotation_id}")
return result
except Exception as e:
error_msg = f"创建采购订单时发生错误: {str(e)}"
logger.error(error_msg)
return {
"success": False,
"error": error_msg
}
4.4 功能测试与效果展示
(1)测试场景1:查询RFQ
- 用户输入:帮我查询一下今天的RFQ
- Agent响应如下图所示:
图8 查询RFQ测试效果
(2)测试场景2:查询RFQ的报价信息
- 用户输入:查询RFQ编号:AW20251108的报价单、 供应商id,以及具体报价,表格形式展示
- Agent响应如下图所示,经过分析,供应商的0000000336的价格最低,具体信息如下:
图9 查询RFQ报价信息测试效果
(3)测试场景3:查询供应商付款条件
- 用户输入:查询供应商的0000000336付款条件和可持续相关信息
- Agent响应如下图所示:
图10 查询供应商付款条件测试效果
(4)测试场景4:创建PO
- 用户输入:基于报价单6000000285创建PO
- Agent响应如下图所示,采购订单创建成功,订单编号为4500008353。
图11 创建PO测试效果
(5)测试场景5:SAP环境中验证PO创建
在SAP GUI中输入T-code(ME23),输入4500008353,查看采购订单详细,具体信息如SAP GUI截图所示,物料、数量、供应商和价格都正确。
图12 SAP环境验证创建PO结果-列表信息
图13 SAP环境验证创建PO结果-详细信息
5、方案优势与价值
- 效率提升:采购人员无需操作SAP系统,通过自然语言快速完成查询与PO创建,流程耗时从小时级缩短至分钟级;
- 降低门槛:非技术人员无需掌握SQL或SAP操作,降低采购流程的技术门槛;
- 数据统一:整合SAP结构化数据与非结构化知识库,避免信息分散;
- 安全可靠:基于AWS IAM权限控制、数据加密、AgentCore安全托管,保障SAP数据安全;
- 可扩展性强:支持新增GAI工具(如供应商评分查询、采购预算校验),适配更多采购以及SAP横向的业务场景。
6、总结与展望
本方案通过Strands Agents框架的灵活工具编排能力、Bedrock AgentCore的企业级托管与记忆功能,与SAP系统深度集成,打造了一站式SAP智能采购助手。该方案不仅解决了传统采购流程的效率痛点,还为企业采购数字化转型提供了可复用的云原生架构。
*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。
本篇作者