电商订单系统的 Bug 修复有三大痛点:状态机复杂(订单 × 支付 × 退款 × 物流交叉影响)、数据敏感(涉及金额和支付信息)、时效要求高(线上故障必须分钟级响应)。本文以订单、支付、退款三个核心场景为例,展示如何把 Agent 接入现有 Bugfix 流程,从 Issue 创建到 PR 合并全程自动化,同时保留关键节点的人工审批。

案例 001:用 Agent 改造电商订单系统的缺陷修复流程

电商订单系统的 Bug 修复有三大痛点:状态机复杂(订单 × 支付 × 退款 × 物流交叉影响)、数据敏感(涉及金额和支付信息)、时效要求高(线上故障必须分钟级响应)。本文以订单、支付、退款三个核心场景为例,展示如何把 Agent 接入现有 Bugfix 流程,从 Issue 创建到 PR 合并全程自动化,同时保留关键节点的人工审批。

一、业务背景

这是一个日均 50 万单的电商平台,技术栈为 Python(Django)+ PostgreSQL + Redis + RabbitMQ。订单系统有 120 个 API、45 张表、380 个单元测试。团队 15 人,每天新增 3-5 个 Bug Issue。

核心痛点:

问题 具体表现 影响
状态机复杂 一个"订单金额计算错误"的 Bug 可能涉及 6 个模块 人工定位平均 2 小时
回归风险高 改了支付逻辑,可能破坏退款流程 每次修复需要跑 380 个测试
修复时效差 从 Issue 到 PR 平均 3.5 天 严重 Bug 积压影响 GMV

引入 Agent 的目标:把简单 Bug 的修复时间从 3.5 天降到 4 小时,同时保证不引入新 Bug。

二、系统架构与 Agent 接入点

text
┌─────────────────────────────────────────────────────────────────┐
│                        电商平台订单系统                          │
│                                                                 │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐    │
│  │ 订单服务  │──▶│ 支付服务  │──▶│ 退款服务  │──▶│ 物流服务  │    │
│  │ (order)  │   │ (pay)    │   │ (refund) │   │ (ship)   │    │
│  └────┬─────┘   └────┬─────┘   └────┬─────┘   └────┬─────┘    │
│       │              │              │              │            │
│  ┌────▼──────────────▼──────────────▼──────────────▼─────┐      │
│  │              状态机引擎 (StateMachine)                  │      │
│  └───────────────────────────────────────────────────────┘      │
│                                                                 │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │              Agent 工作台接入层                           │    │
│  │  ┌─────────┐  ┌──────────┐  ┌─────────┐  ┌──────────┐ │    │
│  │  │Issue 解析│→│上下文包生成│→│Agent 修复│→│质量门禁   │ │    │
│  │  └─────────┘  └──────────┘  └─────────┘  └────┬─────┘ │    │
│  └────────────────────────────────────────────────│────────┘    │
│                                                   │             │
│  ┌────────────────────────────────────────────────▼────────┐    │
│  │  审批门禁:涉及金额/支付/退款的修改 → 必须人工审批       │    │
│  └─────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────┘

Agent 不是替代开发者,而是作为一个"初级开发者"参与流程:自动完成日志分析、代码定位、补丁编写和测试验证,但涉及核心业务逻辑(金额、支付)的修改必须人工审批。

三、三个核心场景

3.1 场景一:订单金额计算错误

Issue 描述#BUG-2341 使用满减券后订单金额显示为负数

yaml
# 订单金额计算 Bug 的 Agent 上下文包
bugfix_context:
  issue: "#BUG-2341"
  error_log: |
    AssertionError: order.total_amount = -15.00, expected >= 0
    at OrderService.calculate_total (app/order/service.py:287)
  
  # Agent 可以读取的文件
  allowed_files:
    - app/order/service.py        # 订单服务核心逻辑
    - app/order/models.py         # 订单数据模型
    - app/coupon/calculator.py    # 优惠券计算
    - app/order/tests/test_total.py  # 已有测试
  
  # 业务规则(注入到 Prompt)
  business_rules:
    - "订单金额不能小于 0"
    - "满减券抵扣不能超过订单原价的 80%"
    - "运费不参与满减计算"
  
  # 约束
  constraints:
    max_patch_lines: 15
    must_add_test: true
    approval_required: true  # 涉及金额,需审批

Agent 修复过程:

  1. 读取报错文件 service.py:287,发现 total_amount = subtotal - coupon_discount - shipping
  2. 读取 calculator.py,发现满减券的 discount 没有上限检查
  3. 修复:在优惠券计算中增加 min(discount, subtotal * 0.8) 约束
  4. 添加测试:test_coupon_exceeds_subtotal 验证边界条件
  5. 运行 380 个测试 → 全部通过

3.2 场景二:支付回调幂等性问题

Issue 描述#BUG-2356 微信支付回调重复处理导致订单状态异常

yaml
# 支付幂等性 Bug 上下文包
bugfix_context:
  issue: "#BUG-2356"
  error_log: |
    OrderStatusError: Cannot transition from 'paid' to 'paid'
    at OrderStateMachine.transition (app/common/state.py:45)
    triggered by PayCallbackHandler.handle (app/pay/callback.py:89)
  
  allowed_files:
    - app/pay/callback.py         # 支付回调处理
    - app/common/state.py         # 状态机
    - app/order/models.py         # 订单模型
    - app/pay/tests/test_callback.py
  
  business_rules:
    - "支付回调必须幂等:相同交易号重复回调不改变状态"
    - "回调处理使用数据库事务 + 行锁"
  
  constraints:
    max_patch_lines: 20
    must_add_test: true
    approval_required: true  # 涉及支付,需审批

Agent 修复:在 callback.py 中增加幂等检查——用 Redis 分布式锁 + 数据库唯一索引双重保障:

python
# app/pay/callback.py 修复后

class PayCallbackHandler:
    def handle(self, callback_data):
        transaction_id = callback_data["transaction_id"]
        
        # 幂等检查 1:Redis 分布式锁(快速路径)
        lock_key = f"pay_callback:{transaction_id}"
        if not self.redis.set(lock_key, "1", nx=True, ex=3600):
            # 已有处理中的锁,可能是重复回调
            existing_order = self.order_repo.get_by_transaction(transaction_id)
            if existing_order and existing_order.status == "paid":
                return {"status": "already_processed"}  # 幂等返回
        
        # 幂等检查 2:数据库事务 + 行锁
        with db.atomic():
            order = Order.select().where(
                Order.transaction_id == transaction_id
            ).for_update().first()
            
            if order.status == "paid":
                return {"status": "already_processed"}
            
            order.status = "paid"
            order.paid_at = datetime.now()
            order.save()
        
        return {"status": "success"}

3.3 场景三:退款金额计算与库存回滚

Issue 描述#BUG-2378 部分退款后库存未正确回滚

yaml
bugfix_context:
  issue: "#BUG-2378"
  error_log: |
    InventoryWarning: SKU-001 stock mismatch after partial refund
    Expected: 95, Actual: 97
    at InventoryService.rollback (app/inventory/service.py:112)
  
  allowed_files:
    - app/inventory/service.py    # 库存服务
    - app/refund/service.py       # 退款服务
    - app/order/models.py
    - app/inventory/tests/
    - app/refund/tests/
  
  business_rules:
    - "部分退款只回滚被退商品的库存"
    - "已发货的商品不能退库存(只能退货后入库)"
    - "退款金额 = 商品单价 × 退款数量 - 分摊优惠"
  
  constraints:
    max_patch_lines: 25
    must_add_test: true
    approval_required: true
    run_tests: ["test_inventory", "test_refund", "test_order"]  # 跨模块回归

这个场景的难点在于"部分退款"需要精确计算哪些商品被退了、库存该回滚多少。Agent 通过分析 refund/service.py 发现退款时没有区分"已发货"和"未发货"的商品,导致多回滚了 2 件库存。

四、审批与质量门禁

4.1 审批策略

yaml
# approval-policy.yaml
approval_rules:
  - condition: "patch touches files matching 'app/pay/**'"
    action: "require_approval"
    approvers: ["@tech-lead", "@payment-owner"]
    reason: "支付相关修改必须技术负责人和支付模块 owner 双重审批"

  - condition: "patch modifies 'order.total_amount' or 'refund.amount'"
    action: "require_approval"
    approvers: ["@tech-lead"]
    reason: "金额计算修改必须技术负责人审批"

  - condition: "patch.lines_changed > 20"
    action: "require_review"
    reviewers: ["@senior-dev"]
    reason: "修改超过 20 行,需要高级开发者 Review"

  - condition: "all tests pass AND patch.lines_changed <= 10 AND no sensitive files"
    action: "auto_merge"
    reason: "小修改 + 测试通过 = 自动合并"

4.2 质量门禁配置

yaml
# quality-gate.yaml
gates:
  - name: "编译检查"
    command: "python -m py_compile app/**/*.py"
    blocking: true

  - name: "单元测试"
    command: "pytest app/{affected_module}/tests/ -v --tb=short"
    blocking: true
    timeout: 120

  - name: "回归测试"
    command: "pytest app/order/tests app/pay/tests app/refund/tests -v"
    blocking: true
    timeout: 300

  - name: "Lint 检查"
    command: "ruff check app/ --fix"
    blocking: false

  - name: "安全扫描"
    command: "semgrep --config=auto app/"
    blocking: true
    fail_on: ["ERROR", "HIGH"]

五、验收命令与效果

bash
# 验收:运行全部相关测试
pytest app/order/tests app/pay/tests app/refund/tests app/inventory/tests \
  -v --tb=short --cov=app --cov-report=term-missing

# 验收:检查 Agent 修复的 PR
gh pr list --author "agent-bot" --state open
gh pr checks <pr-number>

# 验收:审计日志
cat .agent-audit/$(date +%Y-%m-%d).json | jq '.[] | select(.action == "patch")'

接入 Agent 后的效果(运行 30 天):

指标 接入前 接入后 变化
简单 Bug 修复时间 3.5 天 4 小时 -85%
复杂 Bug 修复时间 7 天 5 天 -29%
回归引入率 8% 3% -62%
测试覆盖率 72% 81% +9%
人工审批次数 N/A 日均 4.2 次

六、真实经验与踩坑

6.1 状态机是 Agent 最难理解的部分

场景:订单有 12 个状态、47 种转换路径。Agent 第一次修 Bug 时,把"待支付"直接转到了"已退款",跳过了中间的"支付失败"状态。 问题:Agent 不理解状态机的约束——它只看到"需要退款",不知道必须经过合法的状态转换路径。 解决方案:在上下文包中注入状态机定义文件(state_machine.py 的完整内容),并在 Prompt 中明确约束:"所有状态修改必须通过 OrderStateMachine.transition() 方法,不能直接修改 order.status 字段"。

6.2 金额计算必须用 Decimal,不能用 float

场景:Agent 写的补丁用了 float 做金额计算,在测试中通过了(测试数据凑巧没有精度问题),上线后出现 0.1 + 0.2 != 0.3 的问题。 问题:项目规范中写了"金额使用 Decimal",但 Agent 没有在上下文中看到这个规范。 解决方案:把 .cursorrules 中关于数据类型的规则提取成独立的 rules/money-rules.md,在涉及金额文件的上下文包中强制注入。同时增加 Lint 规则:禁止对 Decimal 字段使用 float() 转换。

6.3 跨模块回归不能只跑"改了的模块"

场景:Agent 修了 refund/service.py 的一个 Bug,回归测试只跑了 test_refund,通过了。合并后发现 inventory 模块挂了——因为退款逻辑改了,库存回滚的入参变了。 问题:Agent 不知道 refundinventory 之间有隐式依赖。 解决方案:维护一张"模块依赖图"(module_deps.yaml),每次修复后根据依赖图扩展测试范围。refund 修改 → 同时跑 refund + inventory + order 的测试。

七、参数说明表

参数 类型 默认值 说明
issue_id string 必填 Bug Issue 编号
allowed_files list 必填 Agent 可读写的文件范围
business_rules list 必填 业务规则(注入 Prompt)
max_patch_lines int 20 补丁最大修改行数
must_add_test bool true 是否必须添加回归测试
approval_required bool false 是否需要人工审批
approvers list [] 审批人列表
run_tests list ["affected"] 测试范围:affected / full / 指定模块列表
test_timeout int 300 测试超时时间(秒)
auto_merge_threshold int 10 修改行数低于此值且测试通过时自动合并

八、落地检查清单

  • 订单状态机定义文件在 Agent 上下文中可访问
  • 涉及金额计算的 Prompt 中注入了 Decimal 规则
  • 支付回调的幂等性有专项测试
  • 退款库存回滚有跨模块回归测试
  • 审批策略配置正确(金额、支付、退款必须审批)
  • 模块依赖图已维护,回归测试范围能自动扩展
  • 审计日志记录了每次 Agent 修复的完整过程
  • 上线前做了人工 Review,不是全自动合并

九、系列导航

上一篇:Lab 005:上下文包越大越好吗?Token 成本与修复成功率实验 下一篇:案例 002:用 Agent 维护 SaaS 后台的 CRUD 与权限模块