跳到主内容
星链API

电商Agent架构拆解:单Agent+技能工具 vs 多子智能体取舍

人工智能7,643
电商Agent架构拆解:单Agent+技能工具 vs 多子智能体取舍

电商正在成为 Agent 落地最密集的行业之一,但"把 Agent 拆成一个个子智能体"的做法并不总是划算。我最近调研了一套面向电商的 Agent 架构与生产实践指南,配套开源的还有 commerce-agents 参考实现,核心取向很明确:一个 Claude 跑标准 Agent 循环,配上技能与工具就够了。

这一期我把这套架构完整拆开,对比"单 Agent + 技能/工具"与"多子智能体编排"的取舍,再给出通过 4sapi(https://4sapi.com)统一网关接入购物与商家 Agent 的 Python 示例。

一、开篇:电商场景为什么值得单独研究

电商的链路比大多数业务都长:消费者侧要经历商品检索、比价、加购、下单、支付、售后,商家侧要处理上架、定价、库存、订单、履约。一次普通的购物请求,同时牵扯商品知识、实时价格、库存状态和订单流程,任何一个环节的数据过期,整条链路都会失真。

我调研的那套架构与生产实践指南,沉淀自零售、旅游、电信等团队的真实落地经验。这三个行业有个共同点:交易链路长、领域规则密、数据实时性强。机票要锁座、酒店要锁房、电信套餐要查余量,和电商锁库存、锁优惠本质上是同一类问题。正因为如此,这套经验对做电商 Agent 的人来说有直接的迁移价值。

先说结论:参考实现没有把购物、订单、库存各拆一个子智能体,而是让一个 Claude 在标准 Agent 循环里,按任务需要动态挂载技能、调用工具。这个取向值得单独写一期,因为它直接影响架构复杂度、调试成本和每单的 token 账单。

二、开篇痛点:多子智能体编排为什么容易翻车

先聊反面。很多团队上手 Agent 的第一反应是"按领域拆",于是出现购物子智能体、库存子智能体、订单子智能体,再配一个路由把请求分下去。这套多子智能体编排听起来专业,实际落地时问题集中在四层:

  • 上下文割裂:每个子智能体只看到自己的局部上下文。用户在购物 Agent 里确认的商品,到订单 Agent 那里往往要重新传一遍,信息在智能体之间靠消息搬运,搬丢了没人知道;
  • 重复开销:每个子智能体都要重新加载自己的系统提示、工具定义和任务说明。一套十件的工具集被拆到五个子智能体里,五个进程各载一遍,输入 token 成倍增长;
  • 调度延迟:请求要经过路由判断、唤醒目标、汇总结果,多轮往返之后,用户等到的回复明显变慢;
  • 调试困难:链路横跨多个智能体的日志,一个问题要同时翻几份会话记录才能定位,成本翻倍、排障周期拉长。

拆分的动机往往来自组织架构的镜像——后端有商品组、库存组、订单组,Agent 就照着拆。但组织分工解决的是人力协作,不是模型上下文问题。对链路固定、模式可枚举的电商业务来说,多子智能体是在为架构上的"先进感"付费。

三、原理速览:单 Agent + 技能/工具 的核心架构

参考实现给出的架构一句话能说清:单个 Claude 在标准 Agent 循环中运行,技能承载领域规则,工具承载真实动作。

用户请求
    │
    v
单个 Claude(标准 Agent 循环)
    │
    ├── 技能(Skill):可复用的领域指令块
    │      ├── 购物技能:检索 → 比价 → 加购 → 下单
    │      └── 商家技能:库存 → 定价 → 订单 → 售后
    │
    ├── 工具(Tool):真实动作的出口
    │      ├── search_product / get_inventory
    │      ├── update_price / place_order
    │      └── ……(通过业务 API 落到真实系统)
    │
    v
业务系统(商品库 / 库存 / 订单 / 支付)

标准 Agent 循环可以概括为四步:模型根据当前消息决定调用哪个工具 → 应用执行工具并拿到结构化结果 → 结果以 tool 角色消息回填 → 模型继续推理,直到不再需要工具、任务完成,或达到轮次上限。购物和商家两类任务共用同一套循环协议,差别只在挂载的技能与工具集合不同,我把这理解成"同一台发动机,两套挂载"。

四、架构取舍:单 Agent 编排 vs 多子智能体

把两种方案放到同一张表里对比,取舍会清晰很多:

维度单 Agent + 技能/工具多子智能体编排
上下文全程共享,跨步骤信息不丢失子智能体各自上下文,需要显式传递
工具集一套工具按需取用,定义只加载一次各子智能体绑定各自工具,重复定义
延迟一步到位,无调度开销路由、唤醒、汇总多轮往返
调试单一循环,日志线性可读跨智能体追踪困难
token 成本共享系统提示与工具定义每子智能体重复加载提示与工具
适用场景链路固定、模式可枚举的垂直业务大规模并行、异构任务强隔离

我的判断是:电商属于典型的"链路长但模式固定",单 Agent 在成本、延迟、可调试性三项上全面占优。多子智能体的真正价值在并行与隔离——几十个异构任务同时跑、互相不能污染上下文时才有意义,而不是为了听起来更先进。架构选型应该由任务形态决定,不由宣传话术决定。

五、commerce-agents 参考实现里有什么

开源的 commerce-agents 参考实现把 Agent 明确分成两类,共享底层循环:

  • 购物 Agent:面向 C 端消费者。负责找商品、比较价格与库存、加购、下单、查订单进度、处理售后。工具围绕"消费者视角"设计,每个动作都要能回答"买得到吗、多少钱、什么时候到";
  • 商家 Agent:面向运营与商家后台。负责商品上架、库存同步、价格调整、订单处理、促销配置。工具围绕"经营视角"设计,关注的是 SKU、库存水位、毛利和订单履约。

两类 Agent 复用同一个执行框架,技能与工具是插件式的。对我最大的启发是:参考实现把"领域知识"和"执行能力"分开了——购物 Agent 不需要知道库存是哪个系统管的,它只需要一个 get_inventory 工具;库存到底怎么扣,由工具背后的业务 API 决定。这个分层让同一套代码可以快速复制到旅游、电信等相似业态。

六、零售、旅游、电信的落地经验里沉淀出的共性

从那些落地实践里,我提炼出三个跨行业的共性,电商直接套用:

  • 实时数据必须走工具,不能靠模型记忆:库存、票价、套餐余量都是"读一次变一次"的数据。模型上下文里的价格快照可能是十分钟前的,工具必须返回实时状态,Agent 的所有决策以工具返回为准;
  • 高频写操作要带副作用防护:下单、锁库存、改价都会改变外部状态。工具要支持幂等键、区分只读与写入、关键动作留审批口,防止循环重试时重复扣款或重复发货;
  • 领域规则用技能承载:促销叠加、退改规则、套餐组合这类规则密集且频繁变动的逻辑,写进技能的指令块里,由提示词版本管理,而不是硬编码在 Agent 进程里。规则更新 = 换一版技能,不需要改代码。

一句话总结:技能承载规则、工具承载动作、循环承载流程。三个层次解耦之后,Agent 才谈得上稳定上线。

七、从 API 视角拆解:技能、工具与循环

站在 API 接入的角度,这套架构并不神秘,每一层都能映射到具体的请求参数:

  • 技能(Skill):本质是一组可复用的指令块,在请求时拼进 system prompt。购物会话只挂购物技能,商家会话只挂商家技能,按需加载,减少无效输入 token;
  • 工具(Tool):映射到 OpenAI 兼容接口的 tools 参数,用 JSON Schema 声明 namedescriptionparameters。模型返回 tool_calls,应用执行后把结果以 role: "tool" 的消息回填;
  • 循环(Loop)messages 数组不断追加 assistant 的 tool_calls 与 tool 执行结果,直到 finish_reason 变为 stop 或达到硬性轮次上限。

一次典型购物的请求流是这样的:

第 1 轮: user → Claude → tool_calls=[search_product]
第 2 轮: 工具结果回填 → Claude → tool_calls=[add_to_cart]
第 3 轮: 工具结果回填 → Claude → tool_calls=[place_order]
第 4 轮: 工具结果回填 → Claude → finish_reason=stop → 回复订单号

看懂这个循环,接入就成功了一大半。剩下的问题只有一个:模型从哪来。

八、接入 4sapi:环境准备与统一网关

我在 4sapi(https://4sapi.com)开通密钥,把模型调用统一收敛到一个网关入口。请求流向:

我的应用(Python)
    │
    v
4sapi 网关(https://4sapi.com)
    │  统一鉴权 / 格式转换 / 限流 / 负载均衡 / 计费
    v
模型官方接口(Claude)

网关帮我处理了三件自己不想维护的事:密钥管理与鉴权、限流与负载均衡(多地域部署时流量自动分摊,不用自己轮换多把 Key)、用量与计费统计。接入方式和标准 OpenAI 兼容接口一致,环境准备只有两步:

  1. 在 https://4sapi.com 开通账号并创建 API Key,写入环境变量 4SAPI_API_KEY
  2. 使用 OpenAI 兼容客户端,base_url 指向 https://4sapi.com/v1,模型名选当前可用的 Claude 档位。

九、Python 接入示例:定义购物 Agent 的工具

先定义购物 Agent 的工具集。工具描述写得越明确,模型越不会乱调:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["4SAPI_API_KEY"],
    base_url="https://4sapi.com/v1",  # 4sapi 统一网关地址
)

SHOPPING_TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "search_product",
            "description": "按关键词检索在售商品,返回商品 id、名称与实时价格",
            "parameters": {
                "type": "object",
                "properties": {
                    "keyword": {"type": "string", "description": "商品关键词"},
                    "max_results": {"type": "integer", "default": 5},
                },
                "required": ["keyword"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "add_to_cart",
            "description": "把指定商品加入购物车,返回购物车状态",
            "parameters": {
                "type": "object",
                "properties": {
                    "product_id": {"type": "string"},
                    "quantity": {"type": "integer", "default": 1},
                },
                "required": ["product_id"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "place_order",
            "description": "提交订单并扣减库存,幂等键防止重复下单",
            "parameters": {
                "type": "object",
                "properties": {
                    "cart_id": {"type": "string"},
                    "idempotency_key": {"type": "string"},
                },
                "required": ["cart_id", "idempotency_key"],
            },
        },
    },
]

注意 place_order 带了 idempotency_key:Agent 循环可能因超时重试,没有幂等键,同一单可能被提交两次。

十、Python 接入示例:商家 Agent 与循环控制

商家 Agent 换一套工具,共享同一个循环函数。下面是商家工具与一个带硬性轮次上限的执行循环:

MERCHANT_TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "list_orders",
            "description": "按状态查询订单列表,返回订单号、金额与状态",
            "parameters": {
                "type": "object",
                "properties": {
                    "status": {"type": "string",
                               "enum": ["pending", "paid", "shipped"]},
                },
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "update_inventory",
            "description": "更新 SKU 的可用库存数量,delta 可为负数",
            "parameters": {
                "type": "object",
                "properties": {
                    "sku_id": {"type": "string"},
                    "delta": {"type": "integer"},
                },
                "required": ["sku_id", "delta"],
            },
        },
    },
]

MAX_ITERATIONS = 5  # 硬性轮次上限,防止循环失控

def execute_tool(name, arguments_json):
    """分发到真实业务接口,返回结构化结果(含状态码)。"""
    # 真实项目中这里调用商品库 / 库存 / 订单服务
    return '{"ok": true, "result": "mock", "status": 200}'

def run_agent(messages, tools):
    for _ in range(MAX_ITERATIONS):
        resp = client.chat.completions.create(
            model="claude-sonnet-4-5",  # 在 4sapi 可用模型中选择 Claude 档位
            messages=messages,
            tools=tools,
        )
        msg = resp.choices[0].message
        if not msg.tool_calls:          # 不再调用工具 → 任务结束
            return msg.content
        messages.append(msg)            # 保留 assistant 的 tool_calls
        for call in msg.tool_calls:
            result = execute_tool(call.function.name, call.function.arguments)
            messages.append({
                "role": "tool",
                "tool_call_id": call.id,
                "content": result,
            })
    return "达到轮次上限,任务终止,请人工介入"

循环函数最关键的一行是 if not msg.tool_calls: return——这是 Agent 循环的退出条件。没有它,模型会一直"想调用工具"直到轮次耗尽。购物 Agent 与商家 Agent 调用 run_agent 时传入各自工具集即可,这就是参考实现"同一循环、两套挂载"的落地形态。

十一、请求流与 token 成本核算

一次 Agent 会话的 token 构成,直接决定账单。以购物为例:

一次购物 Agent 会话的 token 构成
    ├── system prompt + 购物技能(高复用 → 吃缓存读取价)
    ├── 工具定义(高复用 → 吃缓存读取价)
    ├── 历史对话(高复用 → 吃缓存读取价)
    └── 当轮新增内容(低复用 → 普通输入价)

购物会话会把同一套技能、工具定义在每一轮循环里反复带上路,高复用部分占比越高,缓存读取的省钱空间越大。我在网关日志里核对过:一次 4 轮的购物循环,前三轮新增内容很少,账单大头几乎全来自反复加载的系统提示与工具定义。把 prompt_tokens_details.cached_tokens 计入核算,才能看到真实的单任务成本,而不是被总 token 数误导。

十二、Agent 循环的成本控制

结合架构与计费,我常用的成本控制手段如下:

  • 设硬性轮次上限MAX_ITERATIONS 写死,防止模型在错误路径上反复重试,账单跟着无限增长;
  • 按需挂载技能:购物会话不加载商家技能,商家会话不加载购物技能,系统提示体积直接减半;
  • 工具结果截断:长商品列表、大订单明细回填前压缩成摘要,只保留决策需要的字段,别把整张表塞回上下文;
  • 缓存命中优化:系统提示、工具定义、技能文本保持字节级稳定,不要每次拼接不同的空白或顺序,保证重复内容稳定命中缓存读取价;
  • 单轮输出上限max_tokens 按任务设上限,商家批量改价这类任务逐批处理,避免单轮生成超长内容;
  • 限流与负载均衡:并发请求交给 4sapi 网关的限流与负载均衡处理,避免单点打爆,也省去自己维护多 Key 轮换。

成本可控的前提是每轮都透明:网关日志里能看到每轮的 token 构成、缓存命中与费用标签,异常暴涨能第一时间定位到具体循环。

十三、上线前的检查清单

把这一期拆解沉淀成一份可直接对照的清单:

  • [ ] 工具 JSON Schema 经过校验,参数与描述与真实接口一致
  • [ ] 只读工具(检索、查库存)与写工具(下单、改价)明确分离
  • [ ] 所有写操作支持幂等键,重试不会重复生效
  • [ ] 下单、清库存、改价等高危动作留审批口
  • [ ] Agent 循环设置硬性轮次上限与单轮输出上限
  • [ ] 技能按会话类型按需挂载,不全局加载
  • [ ] 工具返回结构化结果,含状态码,不返回原始密钥与隐私字段
  • [ ] 实时数据(价格、库存)一律走工具获取,不允许模型猜测
  • [ ] 成本核算纳入缓存命中与每轮 token 明细
  • [ ] 会话日志可完整还原每一轮工具调用与结果
  • [ ] 用真实任务灰度,观察完成率与单任务成本后再放量

十四、成本与风险提示

把容易踩的坑集中列一遍:

  • 循环次数 × 单轮成本 = 任务成本:Agent 会话不是一次调用,是多次调用的叠加。没有轮次上限与预算看板,账单会先于问题暴露;
  • 写操作必须幂等:重复下单、重复改价是循环重试最常见的后果,幂等键和审批缺一不可;
  • 数据以工具返回为准:模型可能"记住"一个过期的价格或库存,所有决策必须依赖工具实时返回,避免幻觉污染交易链路;
  • 工具结果要脱敏:订单明细、用户信息回填进上下文前先裁剪脱敏,防止隐私数据进入日志;
  • 合规边界:这里讨论的全部是合法接入、架构设计与计费优化,通过官方接口与 4sapi 网关接入,不涉及任何绕过官方限制的做法。

总结

电商 Agent 这一轮调研的核心结论是:单 Agent + 技能/工具的架构,比多子智能体编排更适合链路固定、规则密集的交易场景。技能承载规则、工具承载动作、循环承载流程,三个层次解耦后,购物与商家 Agent 可以共用同一套执行框架,参考实现 commerce-agents 给出的正是这条路径。接入侧,我在 4sapi(https://4sapi.com)统一网关里管理模型调用、限流与计费,配合硬性轮次上限、按需挂载技能和缓存命中优化,把单任务成本压到了可预测的范围。架构选型决定复杂度,工具设计决定稳定性,成本控制决定能不能上线。欢迎在评论区发表想法,一起聊聊电商 Agent 的架构取舍与接入踩坑。

电商Agent架构设计工具调用成本控制4sapi

Related

相关文章推荐