Overview

总览

7
比较维度
4→5
里程碑数量变化
3→3
MCP工具数(相同)
0→4
独立工具函数数量
核心分歧起点

两次生成的根本差异始于 intent 对"客户行为分析"的理解深度。第一次将 "分析" 视为 LLM 内部推理步骤(无需独立工具),第二次将其显式化为可测试、可追踪的工具函数。这一初始分歧向下传导,导致 PRD 粒度、里程碑数量、集成方式、测试覆盖面全面分叉。

维度第一次(Failed)第二次(Success)差异性质
Intent 行为分析定位LLM 内部推理独立可测工具架构性分歧
PRD 需求数4(R1-R4)4(REQ-01~04),但粒度更细深度差异
里程碑数4个5个(拆分了 tone 确定步骤)流程粒度
AR数据集成方式MCP + SAP BDC 双轨MCP + OData 直接调用集成路径差异
工具函数设计无独立工具函数,由 LLM 决策3个专用工具函数工具化程度
行为分类类型LOW/MEDIUM/HIGH 风险等级5类行为模式(含dispute、partial)业务语义深度
测试用例数4个6个(每工具函数一个单测)测试覆盖

Layer 1

Intent 理解差异

两份 intent.md 的输入描述近乎相同,但 AI 对核心业务动作的语义拆解出现了分歧。

第一次(Failed)

Business Challenge 描述重心:
强调 AR specialist 的"手动合成"负担,突出 dunning level、overdue days、dispute status,将问题定义为"数据检索 + 自动化撰写"。


Key Milestones(4步):

  • Retrieve AR Data
  • Analyze Payment Behavior
  • Draft Collection Email
  • Present for Review

Fit Gap 亮点:把 "Dispute Management" 标记为 Maybe(可选),暗示 dispute 不是核心流程。

第二次(Success)

Business Challenge 描述重心:
强调邮件"generic"问题与 DSO(Days Sales Outstanding)指标,将目标定义为"tailored, context-aware draft ready for review"——从输出质量角度定义问题。


Key Milestones(5步):

  • Customer AR profile retrieved
  • Payment behavior analyzed
  • Email tone and strategy determined(新增)
  • Personalized email drafted
  • Draft presented for review

Fit Gap 亮点:Dispute Management 标记为 No gap(有 API,直接调用 OData),是已解决项而非可选。

Intent 层分歧分析

第一次将 "tone 确定" 视为 "Draft" 步骤的内部子动作,第二次将其显式提升为独立里程碑。这一拆分决定了后续整个 spec 的粒度:一旦 tone 确定成为独立步骤,它就需要独立的工具函数、独立的日志点、独立的测试用例,最终导致 M3、M4、M5 的全面重设计。

Dispute 的处理策略分歧(可选 vs 已解决)同样在此确立,并一路传导到集成架构层。

Intent 要素第一次第二次
问题定义角度效率(减少手工时间)质量(减少 DSO,提升相关性)
Tone 选择隐含在 Draft 步骤中独立里程碑(tone and strategy determined)
Dispute 处理Maybe gap(可选)No gap(API 已存在,直接用)
行为分析颗粒度LOW/MEDIUM/HIGH 三级5类行为模式(first_time、chronic、escalation、dispute、unknown)
Process Hierarchy 深度只映射到 BPS-366(AR collection)额外映射到 BPS-363(invoice customer)
Intent fit 评分85%85%(相同,但内容更丰富)

Layer 2

PRD(产品需求文档)差异

需求结构对比

第一次(Failed)—— 4 个 Must-Have 需求
  • R1:Retrieve Outstanding Open Items(仅 AR 开项)
  • R2:Retrieve Payment History and Dunning Data(独立)
  • R3:Draft Personalized Collection Email(含行为分析,合并)
  • R4:Present Draft for Human Review

Acceptance Criteria 粒度:较简洁,R3 AC 仅要求"tone adjusted for dunning level",不指定具体分类。


Value Proposition 量化:明确写出 "~15 min → under 1 min"

第二次(Success)—— 4 个 Must-Have 需求(但粒度更深)
  • REQ-01:Retrieve Customer AR Profile(open items + dunning + payment,合并为整体 profile
  • REQ-02:Analyze Payment Behavior(独立需求,要求识别 first-time、chronic、dispute、partial)
  • REQ-03:Draft Personalized Email(AC 指定:含 itemized invoices、tone 三选一、≤300 words)
  • REQ-04:Present Draft for Human Review

Acceptance Criteria 粒度:REQ-03 AC 指定了邮件结构要素:customer name, itemized invoices, total amount, tone label, message body。


Value Proposition:无具体时间量化,但强调 DSO 和 review-ready

PRD 层差异的关键含义

第一次的 R1/R2 把"open items"和"payment/dunning"拆成两个需求,却在 R3 中把"行为分析 + 邮件起草"合并——分拆维度与业务流程不对齐。第二次 REQ-01 将所有数据获取合并为"AR profile"(更接近业务概念),REQ-02 单独提取行为分析,需求边界与后来的工具函数边界完全对应,使规格可以直接映射为代码。

架构描述差异

第一次

集成路径:MCP + SAP BDC DPQuery


工具列表(3个):

  • get_dunning_history(MCP)
  • query_open_items(DPQuery/BDC)
  • draft_email(LLM via AI Hub)

注意:draft_email 被列为"工具",但它本质上是 LLM 调用——把 LLM 调用伪装为工具,模糊了代理框架与工具的边界。

第二次

集成路径:MCP + S/4HANA OData 直接调用


工具列表(2个数据工具,行为由 LLM 编排):

  • Dunning History MCP Server(read-only)
  • S/4HANA OData:AR Open Items + Customer Payment

LLM 不再被列为"工具"——明确将 LLM 定位为编排者,工具只负责数据获取。

Layer 3

里程碑设计差异

第一次(Failed)—— 4 个里程碑
M1 AR Data Retrieved
M2 Payment Behavior Analyzed
M3 Email Draft Generated
M4 Draft Returned

M3 合并了"tone 确定 + 邮件生成"两个业务动作,日志只记录 word_count,不记录 tone 选择依据。

第二次(Success)—— 5 个里程碑
M1 AR Profile Retrieved
M2 Behavior Classified
M3 Tone Determined
M4 Email Drafted
M5 Draft Presented

M3 独立记录 tone 选择(含 behavior 原因 + overdue days),使 tone 决策路径可审计。

日志模式差异(可观测性)

里程碑第一次日志内容第二次日志内容差异
数据获取 M1.achieved: AR data retrieved for customer {id} — {N} open items, dunning level {LEVEL} M1.achieved: AR profile retrieved for customer {id} — {item_count} open items, {run_count} dunning records 相近,第二次区分了 item/run 两个计数
行为分析 M2.achieved: payment behavior analyzed — risk profile {PROFILE}, tone set to {TONE} M2.achieved: payment behavior classified as {behavior_category} for customer {id} 第一次在M2即记录tone,职责混合;第二次M2只记录分类
Tone确定 (无此里程碑) M3.achieved: email tone set to {tone} for customer {id} — overdue age {days} days 第二次新增独立可观测点
邮件生成 M3.achieved: email draft generated for customer {id} — {WORD_COUNT} words M4.achieved: email draft generated for customer {id} 第一次记录word_count,第二次在M4-log中省略(在其他地方补充)
里程碑层差异的含义

第一次在 M2 的 miss 日志写 "defaulting to neutral tone",说明 AI 将 tone 兜底逻辑内嵌在行为分析失败路径中——这意味着 tone 决策没有独立的失败观测点。第二次 M3.missed 独立记录 "tone selection defaulted to reminder — no behavior signal",使 tone 退化路径在生产日志中可独立检索,显著提升运维可观测性。

Layer 4

系统集成差异

第一次(Failed)—— 双轨集成

数据源1:SAP S/4HANA via MCP server(Dunning)

数据源2:SAP BDC Data Products via DPQuery


AR Open Items → 通过 BDC DPQuery 获取
Customer Payment → 通过 BDC DPQuery 获取
Dunning History → 通过 Dunning MCP Server 获取


asset.yaml requires 只声明了 MCP server,BDC 的连接方式未在 spec 中说明(隐含依赖)。

第二次(Success)—— 单一 S/4HANA 来源

数据源:SAP S/4HANA(两种访问路径)


AR Open Items → S/4HANA OData 直接调用
Customer Payment → S/4HANA OData 直接调用
Dunning History → Dunning MCP Server


注:guidelines 规定 "NEVER call SAP APIs directly",但 PRD 仍写了 OData 直接调用——这是一个在规格层还未完全解决的技术矛盾,在 spec 中通过 MCP 工具模式化解。

集成路径架构图

第一次集成图
Agent
  ├── Dunning MCP Server → S/4HANA (dunning)
  ├── BDC DPQuery → Open Items
  ├── BDC DPQuery → Customer Payment
  └── SAP AI Hub → LLM (email draft)

BDC 作为独立数据平台引入,增加了依赖复杂度。

第二次集成图
Agent
  ├── Dunning MCP Server → S/4HANA (dunning)
  ├── S/4HANA OData → AR Open Items
  ├── S/4HANA OData → Customer Payment
  └── SAP AI Hub → LLM (email draft)

所有 AR 数据来自同一系统(S/4HANA),消除跨平台同步风险。

asset.yaml requires 声明差异

第一次
requires:
  - name: contract-accounting-dunning-history-mcp
    kind: mcp-server
    ordId: sap.mcpbuilder:apiResource:
      contract_accounting_dunning_history_mcp_demo:v1

BDC 连接未在 requires 中声明。

第二次
requires:
  - name: contract-accounting-dunning-history-mcp-demo
    kind: mcp-server
    ordId: sap.mcpbuilder:apiResource:
      contract_accounting_dunning_history_mcp_demo:v1

依赖声明更精确(name 与 ORD ID 一致),且 OData 调用通过 guidelines 约束转为 MCP 工具。

Layer 5

架构设计差异

工具函数设计哲学

第一次——LLM-centric 设计

Agent 的 system prompt 包含所有分析逻辑(风险分级规则、tone 映射规则)。LLM 直接处理原始 MCP 输出,自行推断风险等级和邮件策略。


工具数量:1个数据工具(实质上 BDC DPQuery 和 MCP 被封装为 2 个,但 spec 中未作为独立函数实现)


业务逻辑所在层:system prompt(LLM instruction)


问题:业务规则在 prompt 中,不可单元测试,行为结果不确定。

第二次——Tool-centric 设计

将业务逻辑拆分为 3 个独立工具函数,LLM 只负责调用工具和组装邮件文本。


3 个显式工具函数:

  • get_customer_ar_profile(business_partner) → dict
  • analyze_payment_behavior(ar_profile) → dict(5类分类)
  • select_email_tone(behavior_category, max_dunning_level, oldest_due_date) → str

业务逻辑所在层:Python 函数(确定性代码)


优势:每个工具有明确签名,可独立单测,行为可重现。

架构选择的根本差异

第一次的 @prompt_section 承载了分析规则(低风险level 01 + balance<1000,中风险level 02,高风险level 03+),但 spec 要求 @prompt_section 仅用于系统提示——把业务规则嵌入 prompt 导致它们无法被单独测试,也无法在不触碰 LLM 的情况下修改。第二次将这些规则提升到 Python 层,prompt 只保留行为约束("不伪造数据"、"always top=100")。

行为分类系统对比

第一次——3级风险等级

分类标准(在 system prompt 中):

  • LOW:dunning level 01 + balance < 1000
  • MEDIUM:level 02 或 balance 1000–10000
  • HIGH:level 03+ 或已进入 collection agency

Tone 映射(在 prompt 中):

  • LOW → polite
  • MEDIUM → firm
  • HIGH → formal/urgent

分类维度:数值阈值(level + balance金额)

第二次——5类行为模式

分类标准(在 analyze_payment_behavior 函数中):

  • first_time_overdue:仅1次dunning run,level ≤ L1
  • chronic_late_payer:3+次 runs 或 max level ≥ L3
  • escalation_candidate:max level = L2,2次 runs
  • dispute_history:有 reversed notices
  • unknown:数据不足

Tone 映射(在 select_email_tone 函数中):

  • first_time → reminder
  • chronic / level≥L3 → escalation_warning
  • dispute → firm_notice_with_acknowledgment
  • default → firm_notice

分类维度:行为模式(历史频次 + 状态标志)

Layer 6

规格(Specification)实现差异

Agent 核心实现对比

实现要素第一次(Failed)第二次(Success)
_run_agent() 实现 直接在 spec 中描述为"加载MCP工具→构建图→调用→返回",无工具分层 同上,但额外要求将 3 个工具函数注册进图;LLM 通过工具调用获得结构化输出
system prompt 职责 包含分析规则(风险阈值、tone映射、邮件格式要求) 只保留角色定义 + 数据卫生约束(不伪造、top=100、draft disclaimer)
Business partner 校验 未指定(隐含) 明确:"若 query 未提供 business_partner,agent 先询问再执行"
邮件格式约束 Subject + salutation + body + closing(prompt中) Subject: ...\n---\n 结构化输出 + 300 words上限
MCP mock 数据要求 仅要求生成 mock,未指定场景 明确要求 mock 覆盖3个场景:多dunning-run客户、首次逾期、无历史客户
OTel span 位置 decorator form on helper methods context manager form with tracer.start_as_current_span("M<N>-<name>"): inside _run_agent()
MCP Mock 数据质量差异的影响

第一次 spec 只要求生成 mcp-mock.json,未规定测试场景。若 mock 只包含一种数据模式(如 medium risk),则行为分类的边界测试(首次逾期、高风险升级)无法覆盖,测试通过但业务逻辑有盲区。第二次明确要求 mock 必须包含 3 类不同历史客户,直接对应 5类行为分类的核心路径,确保测试有效性。

Layer 7

测试策略差异

第一次(Failed)—— 4 个测试文件
  • test_list_dunning_runs.py — 验证工具被调用(含 $top=100)
  • test_list_dunned_items.py — 验证 items 被获取
  • test_email_draft.py — 给定 mock 数据,验证邮件非空且 subject 含 balance
  • test_integration.py — 端到端,断言 response 含邮件结构

测试哲学:调用验证(确认工具被调用)


问题:没有测试行为分析函数本身(因为不存在独立函数),分类逻辑的正确性依赖 LLM——不可单测。

第二次(Success)—— 6 个测试文件(4单测 + 1集成)
  • test_get_customer_ar_profile.py — 验证 consolidated dict 结构 + 空响应处理
  • test_analyze_payment_behavior.py测试全部 5 类行为分类的边界输入
  • test_select_email_tone.py — 验证每类行为 → tone 的映射 + 边界情况
  • test_integration.py — 断言输出含 "Subject:"、"draft for your review"、business partner ID

测试哲学:行为验证(测试业务规则是否正确)


优势:分类函数和 tone 映射函数有确定性输入/输出,测试即文档。

Integration Test 断言对比

第一次集成测试断言

断言:response 是"email-like string with subject and body"


不精确:任何包含换行的字符串都能通过。

第二次集成测试断言

断言:输出必须同时包含:

  • "Subject:"
  • "draft for your review"(人机协作声明)
  • business partner ID(确认数据正确绑定)

精确:每个断言对应一个业务需求,测试失败可直接定位问题来源。

测试覆盖范围对比

业务逻辑第一次覆盖第二次覆盖
MCP 工具调用(top=100)
AR profile 构建(consolidated dict)
行为分类(5类)无(在 prompt 中,不可测)全覆盖
Tone 映射规则有(每类+边界)
空数据处理未指定有(empty profile case)
人机协作声明("draft for your review")集成测试中强制断言
覆盖率要求未明确≥ 70%,不足则补

Conclusion

结论:差异的演化链

从 Intent 到实现的差异传导链

Intent 层:第一次将"tone确定"内嵌于"邮件起草";第二次将其显式化为独立业务步骤。
↓ 传导到 PRD:REQ-02(行为分析)从"Draft 的前提条件"变为"独立可测需求",AC 指定了5类分类模式。
↓ 传导到里程碑:M3(tone determined)独立出现,日志记录 tone 选择依据,可审计。
↓ 传导到架构:行为分类逻辑从 prompt 迁移到 Python 函数,3个工具函数出现。
↓ 传导到集成:BDC 数据平台被替换为直接 S/4HANA 数据源,集成路径更简洁。
↓ 传导到测试:工具函数可单测,测试从4个增加到6个,行为分类覆盖率从0到全覆盖。

两次生成的核心认知差异

认知维度第一次理解第二次理解
AI Agent 的角色 LLM 主导的黑盒推理系统,工具只是数据管道 LLM 是编排器,工具是业务逻辑的可测单元
业务规则的归宿 System prompt(自然语言约束) Python 函数(确定性代码)
可测试性 只能端到端测试,依赖 LLM 输出 每个业务规则都有对应的单元测试
Tone 决策 LLM 基于 prompt 规则推断 deterministic 函数映射,输入/输出可预期
数据完整性保证 prompt 指令("不伪造") prompt 指令 + 空数据时 agent halt 的明确规范
生产可观测性 4 个日志点,tone 决策过程不可见 5 个日志点,tone 选择有独立追踪路径

为何第一次生成"失败"

失败的根本原因

不是功能缺失,而是可验证性不足


  • 业务分类规则在 prompt 中,无法独立单测
  • 无独立的 tone 工具函数,tone 决策路径不可观测
  • 测试只能断言"邮件非空",不能断言"正确的 tone 被选择"
  • BDC 数据平台作为隐式依赖未在 asset.yaml 中声明
  • mcp-mock.json 缺乏场景覆盖要求,边界行为无法验证
第二次成功的核心改进

在相同的业务目标下实现了架构可测试性


  • 3个工具函数使每个业务规则有对应单测
  • 5类行为分类有明确判定条件(确定性输入/输出)
  • 集成测试断言包含业务语义(人机协作声明、BP ID绑定)
  • mock 数据场景与行为分类用例一一对应
  • 依赖声明完整,integration 可在 CI 中独立运行