在电商业务里,用户侧和商户侧的体验优化往往是两套完全不同的工程问题。用户要的是“帮我找到最合适的商品、比价、下单、查物流”;商户要的是“订单处理、退款审核、库存预警、经营报表”。这些流程看起来不复杂,但一旦要让 AI 智能体接手,就需要一套完整的“工具调用 + 权限控制 + 任务编排”方案。
Anthropic 近期开源了 Claude Commerce Agents 智能体蓝图,目的就是给开发者提供一个可直接参考的电商购物与商户智能体实现模板。它不是为了替代你的业务系统,而是把“如何用 Claude 的 Tool Use 能力构建可靠电商 Agent”这件事,拆成一个可运行、可扩展的参考项目。
本文会从概念讲起,逐步拆解 Claude Commerce Agents 的整体架构、核心设计思路,并给出一个完整的 Python 实战示例,帮助你理解:
- 购物智能体(Shopping Agent)是如何完成商品检索、比价、下单、物流查询的;
- 商户智能体(Merchant Agent)是如何处理订单、退款、库存的;
- 真实生产环境中,Agent 工具设计有哪些安全红线与工程坑点。
不管你是刚接触智能体开发的新手,还是已经在做 AI 应用落地的工程师,这篇文章都能帮你少走弯路。
1. 背景与核心概念
1.1 什么是 Claude Commerce Agents
Claude Commerce Agents 是 Anthropic 开源的一套智能体参考实现,聚焦电商购物与商户运营两大场景。
可以把它理解为“给 AI 智能体配套的电商工具集与流程蓝图”。传统电商系统提供的是 API 接口,开发者需要自己写代码把“用户意图”翻译成“API 调用”。而 Commerce Agents 的思路是:把 API 封装成 AI 可调用的工具(Tools),然后由大模型根据用户请求自动决定调用哪些工具、以什么顺序调用。
例如一个用户说:
我想买一台 5000 元左右的轻薄本,最好 16G 内存,下午能送到。购物智能体需要自动完成:
- 调用商品搜索工具,找出符合条件的商品。
- 调用商品详情工具,获取内存、重量、价格、配送时效。
- 对比多个商品后,向用户推荐。
- 用户确认后,调用下单工具。
- 返回订单号,并调用物流查询工具跟踪配送状态。
整个过程在大模型内部表现为“规划-调用-观察-调整”的循环,也就是 Agent 的核心工作模式。
1.2 为什么需要 Commerce Agents
先看传统电商系统的痛点:
| 场景 | 传统实现方式 | 存在的问题 |
|---|---|---|
| 用户比价 | 用户自己打开多个 App 搜索 | 效率低,体验差 |
| 下单流程 | 用户手动填写收货地址、优惠券 | 步骤繁琐,容易出错 |
| 商户订单处理 | 运营人员人工审核订单 | 人力成本高,处理慢 |
| 退款审核 | 人工核对退款条件 | 审核标准不统一 |
Commerce Agents 的核心价值,是把这些重复性、规则性较强的流程,交给 AI 智能体去编排和执行。它并不是要取代电商平台,而是作为“智能中间层”,连接用户/商户与大模型能力。
1.3 智能体与普通 API 调用的区别
这里要区分两个容易混淆的概念:
普通 API 调用模式
用户输入 -> 代码写死逻辑 -> 调用固定 API -> 返回结果比如一个天气查询机器人,用户说“北京天气”,代码里写死了解析逻辑,把“北京”作为参数传给天气接口。这个模式没有“规划”能力。
Agent 模式
用户输入 -> 大模型理解意图 -> 选择并调用工具 A -> 观察结果 -> 选择并调用工具 B -> 观察结果 -> 得出最终答案Agent 模式的核心是:工具选择与调用顺序由模型动态决定,而不是开发者预先写死。
Claude Commerce Agents 正是围绕这个模式设计的。开发者需要提供两样东西:
- 一组功能明确的工具(Tool)。
- 一个系统级 Prompt,告诉模型它的角色、边界和工作流程。
模型负责“思考”,工具负责“执行”,两者通过 Tool Use 机制通信。
2. 蓝图整体架构与核心设计
2.1 双角色划分
Claude Commerce Agents 开源蓝图主要有两个角色:
Shopping Agent(购物智能体)
面向 C 端用户,处理:
- 商品搜索与推荐
- 商品对比与比价
- 购物车管理
- 下单与支付引导
- 订单物流跟踪
- 售后服务入口
Merchant Agent(商户智能体)
面向 B 端商户运营人员,处理:
- 订单查询与统计
- 订单状态修改
- 退款审核
- 库存管理与预警
- 商品信息维护
- 经营报表生成
两个 Agent 共用一套工具调用基础设施,但工具集合和权限边界完全不同。这一点很重要,后面实战部分会详细说明。
2.2 核心机制:Tool Use 循环
Claude 这类大模型本身不能直接执行外部操作,必须通过“工具调用”间接完成。Commerce Agents 的运行时逻辑可以简化为下面的循环:
用户请求 | v [模型] 生成回复(可能包含工具调用请求) | v [应用层] 解析模型返回的工具调用 | v [应用层] 执行对应函数,拿到结构化结果 | v [应用层] 把工具结果回传给模型 | v [模型] 根据工具结果生成最终回复或继续调用下一批工具这个循环会一直持续,直到模型认为任务完成并给出最终答案。
2.3 权限边界与安全沙箱
开源蓝图中特别值得关注的是权限边界设计。购物智能体和商户智能体的工具集合是完全隔离的:
- 购物智能体不能调用退款审核工具。
- 商户智能体不能直接操作用户的支付账户。
在设计上,所有涉及资金、退款、库存修改等高风险操作,都需要额外的确认步骤或人工审批。这是 Commerce Agents 能够安全落地的关键。
2.4 数据流设计
下面用 ASCII 图描述一个典型的购物查询数据流:
用户: "帮我找一款 5000 元以内的轻薄本" | v +----------------+ tool call +------------------+ | Claude 模型 | -------------------> | search_products | +----------------+ +------------------+ | | | <------- 商品列表(JSON)---------------+ v +----------------+ | 模型筛选、对比 | +----------------+ | | tool call v +------------------+ | get_product_info | +------------------+ | | <------- 商品详情(JSON)------- v +----------------+ | 生成推荐结果 | +----------------+整个过程中,模型不直接连数据库,也不直接调第三方服务,所有实际操作都由开发者实现的工具函数完成。
3. 环境准备与项目结构
3.1 运行环境说明
在动手之前,先明确本文示例的运行环境:
- Python 3.9 及以上版本。
- 需要安装
anthropicSDK,版本建议使用官方最新稳定版。 - 如果需要真实调用 Claude API,需要准备
ANTHROPIC_API_KEY环境变量。 - 为了让没有 API Key 的读者也能跑通流程,本文会先提供一个“模拟工具调用模式”,再给出真实接入方式。
版本需要根据你的项目实际情况调整,本文示例以常见环境为例,重点演示配置思路,不绑定某个具体版本号。
3.2 安装依赖
创建项目文件夹并安装依赖:
mkdir claude-commerce-agents-demo cd claude-commerce-agents-demo python -m venv venv source venv/bin/activate # Windows 下执行 venv\Scripts\activate pip install anthropic python-dotenvanthropic用于调用 Claude API,python-dotenv用于读取.env配置文件。
3.3 项目目录结构
推荐按下面的方式组织代码:
claude-commerce-agents-demo/ ├── .env ├── main.py # 入口文件,演示购物 Agent ├── merchant.py # 商户 Agent 演示 ├── tools/ │ ├── __init__.py │ ├── shopping_tools.py # 购物侧工具 │ └── merchant_tools.py # 商户侧工具 ├── data/ │ ├── products.json # 模拟商品数据 │ └── orders.json # 模拟订单数据 └── agent/ ├── __init__.py └── core.py # Agent 工具调用循环核心这样拆分的好处是:工具层、数据层、Agent 逻辑层相互独立,方便后续替换成真实数据库。
4. 购物智能体完整实战
4.1 模拟商品数据
为了让示例不依赖外部服务就能运行,先准备一份模拟商品数据。
文件路径:data/products.json
[ { "id": "p1001", "name": "轻羽轻薄本 Pro", "category": "笔记本电脑", "price": 4699, "memory": "16GB", "weight": "1.2kg", "stock": 25, "shipping_time": "次日达" }, { "id": "p1002", "name": "星航办公本 Air", "category": "笔记本电脑", "price": 5299, "memory": "16GB", "weight": "1.4kg", "stock": 12, "shipping_time": "次日达" }, { "id": "p1003", "name": "极速游戏本", "category": "笔记本电脑", "price": 8999, "memory": "32GB", "weight": "2.1kg", "stock": 8, "shipping_time": "3日达" }, { "id": "p1004", "name": "轻薄办公本青春版", "category": "笔记本电脑", "price": 3999, "memory": "8GB", "weight": "1.3kg", "stock": 40, "shipping_time": "5日达" } ]这里使用 JSON 文件模拟数据库,便于理解。真实项目中,工具函数内部应该换成 SQL 查询或微服务调用。
4.2 实现购物工具集
文件路径:tools/shopping_tools.py
""" 购物智能体工具集。 每个工具都是一段独立的函数,接收参数并返回 JSON 可序列化的结果。 真实项目中,这些函数内改为调用商品中心、交易中心等后端服务。 """ import json import os from typing import Any, Dict, List def _load_products() -> List[Dict[str, Any]]: """从 JSON 文件加载商品数据。""" base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) path = os.path.join(base_dir, "data", "products.json") with open(path, "r", encoding="utf-8") as f: return json.load(f) def search_products(keyword: str = "", max_price: float = 0) -> List[Dict[str, Any]]: """ 搜索商品。 参数: keyword: 商品名称关键词 max_price: 最高价格,0 表示不限制 返回: 符合条件且仍有库存的商品列表 """ products = _load_products() result = [] for p in products: if keyword and keyword not in p["name"]: continue if max_price and p["price"] > max_price: continue if p["stock"] <= 0: continue result.append(p) return result def get_product_detail(product_id: str) -> Dict[str, Any]: """获取商品详情。""" products = _load_products() for p in products: if p["id"] == product_id: return p return {"error": f"商品 {product_id} 不存在"} def create_order(user_id: str, product_id: str, quantity: int = 1) -> Dict[str, Any]: """ 创建订单。 注意:真实系统中,这里必须校验用户身份、地址、支付方式, 并通过幂等键防止重复下单。 """ product = get_product_detail(product_id) if "error" in product: return product if product["stock"] < quantity: return {"error": "库存不足"} # 模拟扣减库存。真实项目应使用数据库事务 + 行锁。 if quantity <= 0: return {"error": "购买数量必须大于 0"} total_price = product["price"] * quantity order = { "order_id": f"ORD{user_id}{product_id}", "product_id": product_id, "product_name": product["name"], "quantity": quantity, "total_price": total_price, "status": "CREATED", "shipping_time": product["shipping_time"], } return order def track_order(order_id: str) -> Dict[str, Any]: """查询订单物流状态。""" # 这里应接入真实的订单查询服务 return { "order_id": order_id, "status": "SHIPPED", "current_location": "华东转运中心", "estimated_delivery": "明日 18:00 前", } # 工具注册表:给模型使用的工具元信息 SHOPPING_TOOLS = [ { "name": "search_products", "description": "搜索商品,支持关键词和最高价格过滤", "input_schema": { "type": "object", "properties": { "keyword": {"type": "string", "description": "商品名称关键词"}, "max_price": {"type": "number", "description": "最高价格,0 表示不限"} } } }, { "name": "get_product_detail", "description": "根据商品 ID 获取商品详细信息", "input_schema": { "type": "object", "properties": { "product_id": {"type": "string", "description": "商品 ID"} }, "required": ["product_id"] } }, { "name": "create_order", "description": "创建订单,购买指定商品", "input_schema": { "type": "object", "properties": { "user_id": {"type": "string", "description": "用户 ID"}, "product_id": {"type": "string", "description": "商品 ID"}, "quantity": {"type": "integer", "description": "购买数量"} }, "required": ["user_id", "product_id"] } }, { "name": "track_order", "description": "查询订单物流信息", "input_schema": { "type": "object", "properties": { "order_id": {"type": "string", "description": "订单 ID"} }, "required": ["order_id"] } } ]工具函数的实现并不复杂,关键是SHOPPING_TOOLS这个注册表,它描述了每个工具的名称、用途和参数结构。Claude API 会根据这些信息,在需要的时候主动发起工具调用。
4.3 实现 Agent 工具调用核心循环
文件路径:agent/core.py
""" Agent 工具调用循环核心。 这个模块负责: 1. 将用户消息发送给 Claude 2. 判断模型是否请求调用工具 3. 如果有工具调用请求,执行对应函数 4. 把结果传回模型,继续对话 5. 直到模型返回最终文字回复 """ from typing import Any, Callable, Dict, List, Optional import anthropic # 工具名称到实际函数的映射 TOOL_MAP: Dict[str, Callable[..., Any]] = {} def register_tool_map(tool_map: Dict[str, Callable[..., Any]]): """注册工具函数映射。""" TOOL_MAP.update(tool_map) def run_agent( client: anthropic.Anthropic, model_name: str, system_prompt: str, tools: List[Dict[str, Any]], user_message: str, max_iterations: int = 5, ) -> str: """ 运行一个单轮 Agent 任务。 参数: client: Anthropic 客户端 model_name: Claude 模型名称 system_prompt: 系统提示词 tools: 工具注册表 user_message: 用户输入 max_iterations: 最大工具调用轮数,防止死循环 返回: 最终文本回复 """ messages = [{"role": "user", "content": user_message}] iteration = 0 while iteration < max_iterations: response = client.messages.create( model=model_name, max_tokens=2048, system=system_prompt, tools=tools, messages=messages, ) # 检查返回内容中是否有工具调用请求 tool_calls = [] content_blocks = response.content for block in content_blocks: if block.type == "tool_use": tool_calls.append({ "id": block.id, "name": block.name, "input": block.input, }) # 如果没有工具调用,说明模型给出了最终回复 if not tool_calls: final_text = "" for block in content_blocks: if block.type == "text": final_text += block.text return final_text or "(模型未返回文本内容)" # 把带工具调用的 assistant 消息加入历史 messages.append(response.model_dump()) # 执行工具调用并收集结果 tool_result_blocks = [] for call in tool_calls: func = TOOL_MAP.get(call["name"]) if not func: tool_result_blocks.append({ "type": "tool_result", "tool_use_id": call["id"], "content": f"未知工具: {call['name']}", }) continue try: result = func(**call["input"]) import json content = json.dumps(result, ensure_ascii=False, default=str) except Exception as e: content = f"工具执行异常: {str(e)}" tool_result_blocks.append({ "type": "tool_result", "tool_use_id": call["id"], "content": content, }) # 将工具执行结果作为 user 消息继续对话 messages.append({ "role": "user", "content": tool_result_blocks, }) iteration += 1 return "已达最大工具调用轮数,任务未完成。"这个循环是 Agent 的核心骨架。我在里面做了三层防护:
max_iterations限制最大轮数,避免模型反复调用工具导致成本失控。- 每种工具都做了异常捕获,避免单个工具出错中断整个 Agent。
- 每次工具调用的结果都转为 JSON 字符串,确保模型能稳定解析。
4.4 购物 Agent 主流程
文件路径:main.py
""" 购物智能体主入口。 运行前需要设置环境变量 ANTHROPIC_API_KEY。 如果没有 API Key,可以先阅读代码逻辑,了解 Agent 工作流程。 """ import os import anthropic from dotenv import load_dotenv from agent.core import run_agent, register_tool_map from tools.shopping_tools import ( SHOPPING_TOOLS, get_product_detail, search_products, create_order, track_order, ) load_dotenv() def build_shopping_system_prompt() -> str: """构造购物智能体的系统提示词。""" return """ 你是一个专业的购物助手。你的职责是帮助用户找到合适的商品、完成下单和查询物流。 工作流程: 1. 用户提出购物需求后,先调用 search_products 搜索商品。 2. 如果搜索结果较多,调用 get_product_detail 获取详细参数进行对比。 3. 向用户清晰展示推荐结果,包括价格、配置、配送时效。 4. 只有在用户明确确认购买时,才能调用 create_order 创建订单。 5. 创建订单后,可以调用 track_order 查询物流。 安全规则: - 未获得用户确认前,不得创建订单。 - 如果用户的需求不够明确,先询问清楚价格预算、配置要求等,再搜索。 - 不要虚构不存在的商品参数。 - 如果搜索没有结果,如实告知用户,不要强行推荐。 """ def main(): api_key = os.getenv("ANTHROPIC_API_KEY") if not api_key: print("请先设置 ANTHROPIC_API_KEY 环境变量") return client = anthropic.Anthropic(api_key=api_key) # 注册购物工具 register_tool_map({ "search_products": search_products, "get_product_detail": get_product_detail, "create_order": create_order, "track_order": track_order, }) system_prompt = build_shopping_system_prompt() user_input = "我想买一台 5000 元以内的轻薄本,16G 内存,帮我推荐一下" print("用户:", user_input) print("=" * 50) result = run_agent( client=client, model_name="claude-sonnet-4-5", system_prompt=system_prompt, tools=SHOPPING_TOOLS, user_message=user_input, max_iterations=5, ) print("Agent:", result) if __name__ == "__main__": main()有一点要特别说明:model_name我写的是"claude-sonnet-4-5",不同时间段 Anthropic 的模型名称会变化。你应该以官方文档或 API 返回的实际模型名为准。如果你的账号可用模型不叫这个名字,配置会失败。
4.5 运行效果说明
如果你配置了可用的 API Key,运行python main.py后,大致的交互过程是:
- 模型收到用户需求。
- 模型觉得需要搜索,于是调用
search_products(keyword="轻薄本", max_price=5000)。 - 工具返回
p1001、p1004两个结果。 - 模型发现两个商品内存不同,再次调用
get_product_detail获取详情。 - 模型综合信息后,给出推荐结论。
最终输出类似:
用户: 我想买一台 5000 元以内的轻薄本,16G 内存,帮我推荐一下 ================================================== Agent: 根据您的需求,我为您筛选出以下商品: 1. 轻羽轻薄本 Pro(p1001) - 价格:4699 元 - 内存:16GB - 重量:1.2kg - 配送:次日达 这款是目前最符合您预算和配置要求的机型,性价比高、重量轻、配送快。这只是模型可能的一种回复,实际内容会根据模型输出变化。
4.6 没有 API Key 时如何理解流程
如果你暂时没有 API Key,可以直接阅读agent/core.py里的循环逻辑,或者自己写一个假的工具调用响应来模拟模型行为。例如:
# mock_run.py —— 模拟工具调用循环,无需 API Key def mock_model_response(messages): """模拟模型输出。第一次调用工具,第二次返回文本。""" if len(messages) == 1: return { "role": "assistant", "content": [ { "type": "tool_use", "id": "call_001", "name": "search_products", "input": {"keyword": "轻薄本", "max_price": 5000}, } ], } else: return { "role": "assistant", "content": [ {"type": "text", "text": "我找到了以下商品,推荐轻羽轻薄本 Pro。"} ], }这段代码演示了 Agent 循环里最关键的一点:模型先输出工具调用请求,应用层执行工具,把结果放回消息历史,再让模型继续。理解了这一点,后面接入真实大模型就很简单了。
5. 商户智能体实现
5.1 商户侧需求分析
商户智能体和购物智能体最大的区别在于:商户工具会直接影响业务数据,例如修改订单状态、审批退款、调整库存。这些操作如果失控,后果比购物推荐严重得多。
因此,商户智能体的设计要额外关注:
- 权限最小化:每个工具只做一件事。
- 人工确认:高风险操作需要二次确认。
- 审计日志:记录每一次工具调用。
- 操作可回滚:涉及数据变更时,提供补偿操作。
5.2 商户工具集实现
文件路径:tools/merchant_tools.py
""" 商户智能体工具集。 注意:商户工具涉及订单、退款、库存等敏感操作, 真实生产环境必须增加权限校验、操作审计和幂等控制。 """ from typing import Any, Dict, List # 模拟订单数据,生产环境应替换为数据库查询 MOCK_ORDERS = [ { "order_id": "ORD20250001", "product_id": "p1001", "quantity": 2, "total_price": 9398, "status": "PAID", "customer": "张三", }, { "order_id": "ORD20250002", "product_id": "p1002", "quantity": 1, "total_price": 5299, "status": "REFUNDING", "customer": "李四", }, ] def list_orders(status: str = "") -> List[Dict[str, Any]]: """查询订单列表。""" if not status: return MOCK_ORDERS return [o for o in MOCK_ORDERS if o["status"] == status] def approve_refund(order_id: str) -> Dict[str, Any]: """ 审批退款。 安全提示:实际系统中,这一步通常还需要: 1. 校验当前操作者是否有退款审批权限 2. 检查订单当前状态是否允许退款 3. 记录操作者、时间、原因到审计日志 4. 通过幂等键防止重复退款 """ for o in MOCK_ORDERS: if o["order_id"] == order_id: if o["status"] != "REFUNDING": return {"error": f"订单 {order_id} 当前状态不允许退款"} o["status"] = "REFUNDED" return { "order_id": order_id, "status": "REFUNDED", "message": "退款审批通过", } return {"error": f"订单 {order_id} 不存在"} def update_inventory(product_id: str, delta: int) -> Dict[str, Any]: """ 调整库存。 delta 为正表示增加库存,为负表示扣减库存。 真实系统应使用数据库事务,防止并发超卖。 """ from tools.shopping_tools import get_product_detail product = get_product_detail(product_id) if "error" in product: return product new_stock = product["stock"] + delta if new_stock < 0: return {"error": f"库存不足,当前库存 {product['stock']}"} # 真实系统应执行 UPDATE product SET stock = stock + delta WHERE id = ... product["stock"] = new_stock return { "product_id": product_id, "current_stock": new_stock, "message": "库存更新成功", } MERCHANT_TOOLS = [ { "name": "list_orders", "description": "查询订单列表,可按状态过滤", "input_schema": { "type": "object", "properties": { "status": {"type": "string", "description": "订单状态,如 PAID、REFUNDING"} } } }, { "name": "approve_refund", "description": "审批通过退款申请。高风险操作,必须确认用户明确要求退款后才可调用。", "input_schema": { "type": "object", "properties": { "order_id": {"type": "string", "description": "订单 ID"} }, "required": ["order_id"] } }, { "name": "update_inventory", "description": "调整商品库存数量", "input_schema": { "type": "object", "properties": { "product_id": {"type": "string", "description": "商品 ID"}, "delta": {"type": "integer", "description": "库存变化量,正数增加,负数扣减"} }, "required": ["product_id", "delta"] } } ]5.3 商户 Agent 系统提示词
商户 Agent 的系统提示词要比购物 Agent 更严格,重点强调“不主动执行敏感操作”。
def build_merchant_system_prompt() -> str: return """ 你是一个商户运营助手,帮助商户处理订单、退款和库存管理。 工作流程: 1. 商户咨询订单情况时,调用 list_orders 查询。 2. 商户要求退款审批时,先确认订单状态,再调用 approve_refund。 3. 商户需要调整库存时,调用 update_inventory。 安全规则: - 退款、库存修改属于敏感操作。没有商户明确指令时,绝不主动调用这些工具。 - 如果参数不明确,先向商户确认清楚再执行。 - 退款操作执行前,必须展示订单信息给商户,获得再次确认。 - 不要批量修改订单状态,一次只能处理一个订单。 """5.4 商户 Agent 入口
文件路径:merchant.py
import os import anthropic from dotenv import load_dotenv from agent.core import run_agent, register_tool_map from tools.merchant_tools import ( MERCHANT_TOOLS, list_orders, approve_refund, update_inventory, ) from tools.merchant_tools import build_merchant_system_prompt load_dotenv() def main(): api_key = os.getenv("ANTHROPIC_API_KEY") if not api_key: print("请先设置 ANTHROPIC_API_KEY 环境变量") return client = anthropic.Anthropic(api_key=api_key) register_tool_map({ "list_orders": list_orders, "approve_refund": approve_refund, "update_inventory": update_inventory, }) result = run_agent( client=client, model_name="claude-sonnet-4-5", system_prompt=build_merchant_system_prompt(), tools=MERCHANT_TOOLS, user_message="有哪些退款中的订单?", max_iterations=5, ) print("Agent:", result) if __name__ == "__main__": main()商户智能体的代码结构几乎和购物智能体一样,区别在于工具集合与权限边界。这也说明 Commerce Agents 蓝图的核心理念:工具决定了 Agent 的能力边界,Prompt 决定了 Agent 的行为边界。
6. 从 Demo 到生产的关键改造
开源蓝图给你的是一个可运行的最小骨架。要真正应用到生产环境,下面几项改造是必须的。
6.1 数据层替换
Demo 中商品和订单数据都是 JSON 文件或内存列表。生产环境必须替换为真实的数据库或后端服务。
真实项目的工具函数应该是这样的:
# 以搜索商品为例 def search_products(keyword: str = "", max_price: float = 0) -> List[Dict[str, Any]]: """ 真实实现:通过商品中心服务或数据库查询商品。 """ # 1. 过滤条件校验 if max_price < 0: return {"error": "价格不能为负数"} # 2. 调用商品服务(示例伪代码) # products = product_service.search( # keyword=keyword, # max_price=max_price, # page_size=10, # ) # return products # 3. 统一异常处理 # try: # ... # except ExternalServiceException: # return {"error": "商品服务暂时不可用"} ...替换过程中要特别注意:
- 工具函数不要直接在内部写 SQL 拼接字符串,防止注入。
- 数据库查询要设置超时时间,避免 Agent 长时间挂起。
- 返回给模型的数据要控制大小,不要一次返回几十万条记录。
6.2 幂等控制
Agent 最大的风险之一是重复执行。模型可能在网络重试后,把同一个下单请求发送两次。
解决办法是引入幂等键:
# 工具函数中增加幂等键校验 def create_order_with_idempotency(user_id: str, product_id: str, idempotency_key: str) -> Dict[str, Any]: # 先检查 Redis / DB 中是否已存在该幂等键 # 如果存在,直接返回之前的处理结果,不重复下单 ...在上面的 Agent 循环中,如果模型连续两次调用create_order,应用层应该通过幂等键识别出这是重复请求,而不是真的下两个订单。
6.3 人工确认机制
对资金、退款、库存这类高风险操作,生产环境建议引入“人工确认队列”:
模型调用 approve_refund | v 写入待确认任务表(状态:PENDING_APPROVAL) | v 运营人员在小程序中点击“确认” | v 确认后系统执行退款Agent 的工具函数此时只负责“创建审批任务”,不直接执行退款。这个改造能极大降低 AI 失控带来的业务风险。
6.4 审计日志
每次工具调用都要记录:
- 调用时间
- 用户/商户 ID
- 工具名称
- 参数内容
- 执行结果
- 模型生成的中间思考(如果允许记录)
日志不仅能用于排错,也是后续合规审计的重要依据。
6.5 成本控制与限流
大模型 Agent 的调用成本包括 token 成本和工具执行消耗。建议:
- 设置单次任务的最大工具调用轮数。
- 对工具返回结果做长度限制,避免大 JSON 撑爆上下文。
- 使用模型缓存功能(如 prompt caching),降低系统提示词重复计费。
- 对模型执行结果做超时控制。
7. 常见问题与排查思路
在实际开发 Claude Commerce Agents 的过程中,容易遇到以下几类问题。
7.1 工具参数格式不符合 JSON Schema
现象:模型生成的工具参数,在你的函数中取不到预期字段。
原因:工具的input_schema描述不够严格,模型自由发挥了。
解决思路:
- 在
input_schema中把必填字段加入required。 - 为每个字段写清类型,例如
"type": "number"。 - 函数的参数必须和 schema 完全一致。
- 函数内部增加参数校验,不合法就返回
{"error": "..."}。
7.2 模型陷入工具调用死循环
现象:Agent 不停调用工具,始终不生成最终回复。
原因:工具返回的数据与模型预期不符,模型想通过反复调用修复。
解决思路:
- 给
run_agent设置合理的max_iterations,建议 5 到 8。 - 检查工具返回的 JSON 是否简洁清晰。
- 在系统提示词中增加“如果已经拿到足够信息,请直接给出答案”的约束。
7.3 工具执行报错导致 Agent 中断
现象:某个工具抛异常后,Agent 直接结束。
原因:agent/core.py中的异常处理不完善,或工具函数内部没有捕获业务异常。
解决思路:
- 工具函数内部用 try-except 包裹业务逻辑,统一返回 JSON 错误信息。
- 不要抛 Python 异常给模型,模型无法理解
KeyError这类信息。 - 在 Agent 循环中为每个工具调用增加独立的异常捕获。
7.4 连接 API 失败或返回 403
现象:使用 Claude API 时出现无法连接或 403 状态码。
原因:常见原因包括 API Key 无效、账号权限不足、网络环境受限、模型名称错误。
解决思路:
- 检查
ANTHROPIC_API_KEY是否正确设置。 - 验证所使用的模型名称在当前账号下是否可用。
- 查看官方 API 文档,确认请求地址是否需要特殊处理。
- 增加重试机制和超时配置,避免临时故障导致 Agent 中断。
client = anthropic.Anthropic( api_key=api_key, timeout=60.0, max_retries=2, )7.5 工具返回的数据太大
现象:某个工具返回几千条商品,模型无法有效处理,且 token 消耗极高。
解决思路:
- 工具函数内部做好分页,只返回前 N 条。
- 不要把全量数据塞给模型,先做聚合统计。
- 推荐场景中,先返回 top 5 商品,再让模型决定是否查看详情。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 授权失败 / 403 | API Key 无效或权限不足 | 检查 Key 与账号权限 |
| 模型不调用工具 | 工具描述不清 / 系统提示词不够明确 | 优化工具 description 和 system prompt |
| 工具参数取不到值 | JSON Schema 定义不严谨 | 补充 required 和字段类型 |
| 重复下单 | 网络重试导致重复调用 | 引入幂等键 |
| Agent 死循环 | 工具返回值不满足模型预期 | 限制轮数、优化返回结构 |
8. 最佳实践与工程建议
8.1 工具设计原则
工具是 Agent 能力的边界。设计时记住一句话:一个工具只做一件事,并把事情描述清楚。
反面示例:
工具名:process_order 描述:处理订单这个工具过于模糊。模型不知道它到底能做什么,也不知道能否用于退款。
正面示例:
工具名:approve_refund 描述:审批通过指定订单的退款申请。仅当商户明确要求退款时调用。清晰、单一、有边界。
8.2 Prompt 工程要点
系统提示词中要写明:
- 角色的工作目标。
- 工具调用顺序。
- 何时不能调用工具。
- 参数不明确时怎么办。
- 如何向用户确认关键操作。
不建议把大段业务规则都写进 Prompt。复杂的规则应下沉到工具函数里做防呆校验,Prompt 只负责约束模型行为。
8.3 安全红线
以下是必须遵守的几条红线:
- 涉及支付、退款、库存修改的高危工具,不能在单轮对话中直接执行。
- Agent 不能拥有比真实操作者更高的权限。
- 所有敏感操作必须有审计日志。
- 生产环境工具调用必须做限流。
- 不要让模型自由拼接 SQL 或 shell 命令。
8.4 可观测性
生产环境的 Agent 一定要有 trace 链路,建议打印如下信息:
[tool_use] call_id=call_001 name=search_products input={"keyword":"轻薄本"} [tool_result] call_id=call_001 status=success result_size=2 [model_message] tokens=234 stop_reason=turn_limit这些日志能帮你快速定位“模型到底做了哪些决策”。
8.5 渐进式上线
不要一开始就把所有电商功能交给 Agent。推荐顺序:
- 先用只读工具上线:商品搜索、订单查询。
- 再加入低风险写操作:购物车管理。
- 最后在人工审核机制到位后,再上线退款、库存修改等高危操作。
每一步都要在小流量下验证模型行为和工具稳定性。
9. 动手实践建议
如果你想真正掌握 Claude Commerce Agents,不建议只看不练。这里给出一条实际可行的学习路径:
第一步,先阅读agent/core.py里的工具调用循环,弄清楚模型、应用层、工具函数三者的关系。
第二步,自己写一个只包含一个工具的 Agent,比如“查天气”。用户说“北京今天适合出门吗”,Agent 调用天气工具后给出建议。这个例子虽然简单,但能帮你跑通整个链路。
第三步,将本文的购物 Demo 跑起来。如果有 API Key,直接运行;如果没有,参考mock_run.py自己模拟模型输出。
第四步,为购物 Agent 增加一个“收藏商品”工具。注意定义好参数 schema,并在工具函数中维护一个收藏列表。
第五步,尝试把商户 Agent 的approve_refund改造成“创建审批任务 + 人工确认”的模式。这一步做完,你就真正理解了生产级 Agent 的安全设计。
每次改动后,记录模型的行为变化。一个好用的 Agent,不是一次写出来的,而是在不断调整工具描述、Prompt 和边界条件中打磨出来的。
如果你在搭建过程中遇到 Agent 不调用工具、参数格式错误或安全设计拿不准的地方,欢迎在评论区带上报错信息或代码片段,我们继续排查。