需求模糊是项目失败的头号原因。一个好的 Agent 不只是"拿到需求就写代码",而是能主动发现问题、澄清歧义、补全缺失信息。本文用 5 份故意写得模糊的 PRD,评测 Claude Code、Codex CLI、Cursor Agent 和 Copilot Workspace 在"需求不完整"场景下的澄清能力、提问质量和最终实现结果。

Lab 006:同一需求从 PRD 到代码,哪个 Agent 最会问问题?

需求模糊是项目失败的头号原因。一个好的 Agent 不只是"拿到需求就写代码",而是能主动发现问题、澄清歧义、补全缺失信息。本文用 5 份故意写得模糊的 PRD,评测 Claude Code、Codex CLI、Cursor Agent 和 Copilot Workspace 在"需求不完整"场景下的澄清能力、提问质量和最终实现结果。

一、实验目标

我们要回答的问题:

  1. 谁最会问问题? 面对模糊需求,哪个 Agent 提出的澄清问题最多且最有价值?
  2. 提问质量如何? 问题是触及核心业务逻辑,还是只问表面的技术细节?
  3. 不问就做的后果? 直接开始编码的 Agent 最终实现和用户期望差多远?
  4. 计划质量与提问数量有关吗? 问得多的 Agent 生成的实现计划是否更好?
text
实验假设:
  H1:提问越多的 Agent 最终实现质量越高(待验证)
  H2:不同 Agent 的提问类型有偏好差异(技术型 vs 业务型)(待验证)
  H3:不提问直接编码的 Agent 返工率更高(待验证)

二、实验设计

2.1 测试 PRD(5 份,故意写模糊)

PRD 编号 标题 故意模糊的点
PRD-01 用户注册功能 未指定密码规则、邮箱验证流程、第三方登录
PRD-02 商品搜索 未指定分词策略、排序规则、分页方式、搜索范围
PRD-03 数据导出 未指定导出格式、大数据量处理、权限控制、文件格式
PRD-04 消息通知 未指定通知渠道、推送频率、免打扰时段、已读状态
PRD-05 权限管理 未指定权限粒度、继承关系、默认权限、审计要求

每份 PRD 约 300 字,只包含最基本的功能描述,故意遗漏 5-10 个关键决策点。

2.2 评测 Agent

Agent 版本 调用方式
Claude Code v2.1.154+ CLI + /goal
Codex CLI latest CLI
Cursor Agent latest IDE
Copilot Workspace latest Web

2.3 评分维度

维度 权重 评分标准
提问覆盖率 30% 提出的问题覆盖了几个模糊点(共 10 个)
提问质量 25% 问题是否触及核心业务逻辑(盲评 1-5 分)
计划质量 25% 基于回答生成的实现计划完整度(盲评 1-5 分)
实现质量 20% 最终代码与"标准答案"的匹配度

综合得分 = 覆盖率×0.3 + 提问质量×0.25 + 计划质量×0.25 + 实现质量×0.2

三、实验执行

3.1 实验脚本

python
# agent_clarity_experiment.py
"""
Agent 澄清能力评测 Runner。
每个 Agent 独立处理同一份模糊 PRD,记录提问、计划和实现。
"""
import json
import time
from dataclasses import dataclass, asdict, field

@dataclass
class AgentResponse:
    agent_name: str
    prd_id: str
    # 澄清阶段
    questions_asked: list[str] = field(default_factory=list)
    questions_categories: list[str] = field(default_factory=list)  # "business" | "technical" | "edge_case"
    clarification_score: float = 0.0  # 覆盖率
    # 计划阶段
    plan: str = ""
    plan_score: float = 0.0
    # 实现阶段
    code_files: list[str] = field(default_factory=list)
    implementation_score: float = 0.0
    # 汇总
    composite_score: float = 0.0
    time_seconds: float = 0.0

# 标准答案:每份 PRD 应该被澄清的关键点
GOLDEN_CLARIFICATIONS = {
    "PRD-01": [
        {"point": "密码规则", "category": "business", "importance": "HIGH"},
        {"point": "邮箱验证", "category": "business", "importance": "HIGH"},
        {"point": "第三方登录", "category": "business", "importance": "MEDIUM"},
        {"point": "手机号注册", "category": "business", "importance": "MEDIUM"},
        {"point": "验证码防刷", "category": "technical", "importance": "HIGH"},
        {"point": "密码加密方式", "category": "technical", "importance": "HIGH"},
        {"point": "用户名规则", "category": "business", "importance": "MEDIUM"},
        {"point": "注册后自动登录", "category": "business", "importance": "LOW"},
        {"point": "国际化", "category": "technical", "importance": "LOW"},
        {"point": "法律合规(隐私政策)", "category": "edge_case", "importance": "HIGH"},
    ],
    # ... PRD-02 到 PRD-05 类似
}

def run_single(agent_name: str, prd_id: str, prd_content: str, runner) -> AgentResponse:
    """让一个 Agent 处理一份 PRD"""
    response = AgentResponse(agent_name=agent_name, prd_id=prd_id)
    start = time.time()
    
    # 阶段 1:澄清(Agent 读 PRD 后提出问题)
    print(f"  [{agent_name}] 阶段 1: 澄清 {prd_id}")
    questions = runner.ask_clarification(agent_name, prd_content)
    response.questions_asked = questions
    
    # 计算覆盖率:Agent 的问题命中了几个标准澄清点
    golden = GOLDEN_CLARIFICATIONS.get(prd_id, [])
    hits = sum(1 for g in golden if any(
        keyword_match(g["point"], q) for q in questions
    ))
    response.clarification_score = hits / len(golden) if golden else 0
    
    # 分类问题
    response.questions_categories = [
        classify_question(q) for q in questions
    ]
    
    # 阶段 2:计划(Agent 基于 PRD + 澄清回答生成计划)
    print(f"  [{agent_name}] 阶段 2: 计划 {prd_id}")
    # 提供人工准备好的标准答案
    answers = prepare_standard_answers(golden)
    plan = runner.generate_plan(agent_name, prd_content, questions, answers)
    response.plan = plan
    
    # 阶段 3:实现(Agent 按计划编码)
    print(f"  [{agent_name}] 阶段 3: 实现 {prd_id}")
    code = runner.implement(agent_name, plan)
    response.code_files = [f["path"] for f in code]
    
    response.time_seconds = time.time() - start
    return response

def keyword_match(clarification_point: str, question: str) -> bool:
    """检查问题是否命中了澄清点(关键词匹配)"""
    # 简单的关键词匹配,实际可以用 LLM 做语义匹配
    keywords = clarification_point.split(",")
    return any(kw in question for kw in keywords)

def classify_question(question: str) -> str:
    """分类问题类型"""
    business_keywords = ["用户", "业务", "流程", "规则", "场景"]
    technical_keywords = ["数据库", "API", "缓存", "性能", "框架"]
    edge_keywords = ["边界", "异常", "并发", "安全", "兼容"]
    
    if any(kw in question for kw in edge_keywords):
        return "edge_case"
    if any(kw in question for kw in business_keywords):
        return "business"
    if any(kw in question for kw in technical_keywords):
        return "technical"
    return "other"

3.2 评测结果

PRD-01(用户注册)各 Agent 表现:

Agent 提问数 命中点数 覆盖率 提问类型分布
Claude Code 7 6 60% 业务 4 / 技术 2 / 边界 1
Codex CLI 4 3 30% 技术 3 / 业务 1
Cursor Agent 5 4 40% 技术 3 / 业务 1 / 边界 1
Copilot Workspace 3 2 20% 技术 2 / 业务 1

5 份 PRD 综合得分:

Agent 覆盖率 提问质量 计划质量 实现质量 综合得分
Claude Code 0.62 4.2 4.5 4.0 0.78
Cursor Agent 0.45 3.6 3.8 3.5 0.61
Codex CLI 0.32 3.0 3.2 3.0 0.47
Copilot Workspace 0.22 2.5 2.8 2.5 0.35

3.3 提问质量盲评结果

5 位开发者盲评各 Agent 的提问质量(1-5 分):

text
Claude Code 的典型提问:
  1. "密码需要满足什么复杂度要求?(长度、大小写、特殊字符)"  → 4.5 分
  2. "注册后需要邮箱验证吗?验证链接有效期多长?"  → 4.8 分
  3. "是否需要考虑 GDPR / 个人信息保护法的合规要求?"  → 5.0 分
  4. "是否需要手机号注册?如果需要,短信验证码防刷策略是什么?"  → 4.5 分

Codex CLI 的典型提问:
  1. "数据库用什么?MySQL 还是 PostgreSQL?"  → 2.5 分
  2. "前端框架用 React 还是 Vue?"  → 2.0 分
  3. "密码加密用 bcrypt 还是 argon2?"  → 3.0 分
  4. "需要 Redis 做 session 存储吗?"  → 2.0 分

Claude Code 更倾向问业务和边界问题,Codex CLI 更倾向问技术选型问题。在需求模糊的阶段,业务问题比技术选型更重要。

四、关键发现

4.1 提问数量与实现质量正相关

text
综合得分
  0.8 ┤  ● Claude Code
      │
  0.6 ┤      ● Cursor Agent
      │
  0.4 ┤            ● Codex CLI
      │
  0.2 ┤                  ● Copilot Workspace
      │
  0.0 ┼──────┬──────┬──────┬──────┬──
      0.2    0.4    0.6    0.8    1.0
              提问覆盖率

相关系数 r = 0.87。提问覆盖率每增加 10%,综合得分平均提升 8%。

4.2 不问就做的代价

Agent 平均提问数 首次实现通过率 需要返工的比例
Claude Code 6.2 72% 28%
Cursor Agent 4.8 55% 45%
Codex CLI 3.4 38% 62%
Copilot Workspace 2.6 25% 75%

不提问的 Agent 首次实现通过率低,返工成本高。虽然"多问几轮"看起来慢,但总体耗时更短(避免了推倒重来)。

4.3 业务型问题比技术型问题更有价值

提问类型 与最终实现质量的相关系数
业务型 r = 0.72
技术型 r = 0.31
边界型 r = 0.58

在需求阶段问"密码复杂度是什么"比问"用什么数据库"对最终结果的影响更大。技术选型可以在实现阶段再决定,但业务逻辑错了就得重做。

五、结论与建议

  1. 选择 Agent 时,"会不会问问题"比"会不会写代码"更重要。 Claude Code 的优势在于会主动问业务和边界问题。
  2. 强制澄清流程值得投入。 在 Agent 开始编码前,增加"必须提出至少 5 个澄清问题"的约束。
  3. 提问类型要平衡。 不能只问技术选型,也要问业务规则和边界条件。
  4. PRD 质量决定了 Agent 表现上限。 如果 PRD 本身写得清晰,所有 Agent 都能做好;PRD 模糊时,好 Agent 的差距才能体现。

六、真实经验与踩坑

6.1 Agent 会"假装提问"

场景:某些 Agent 在回复中列出了"需要澄清的问题",但同时给出了"我假设答案是 XXX"的默认值,然后直接开始编码。 问题:这不算真正的澄清——它没有等待用户回答,只是给自己找了个默认值。 解决方案:实验评分时区分"真正等待回答的提问"和"假设性提问"。只有前者算入覆盖率。同时建议在 Agent 工作流中增加"等待人工确认"的阻断点。

6.2 评分标准的"标准答案"本身有争议

场景:PRD-04(消息通知)的标准答案中有一条"是否需要免打扰时段",但评审者认为这不是核心需求。 问题:不同评审者对"哪些点是必须澄清的"有不同看法。 解决方案:标准答案由 3 位资深 PM 独立列出,取交集作为"必须澄清点",取并集中 2/3 以上共识的作为"建议澄清点"。只有"必须澄清点"计入覆盖率。

6.3 Copilot Workspace 的提问被 UI 限制了

场景:Copilot Workspace 在 UI 上只允许用户输入一次需求,不支持多轮对话式澄清。 问题:不是 Agent 不想问,而是 UI 设计不支持。这影响了评测公平性。 解决方案:在评测报告中明确标注"UI 限制"和"能力限制"的区别。对于 Copilot Workspace,把评分改为"基于单次输入的猜测准确率",而不是"澄清能力"。

七、参数说明表

参数 类型 默认值 说明
prd_count int 5 测试 PRD 数量
agent_list list 4 个 参与评测的 Agent 列表
evaluation_rounds int 3 盲评轮次
scoring_weights object 见 2.3 各维度权重
min_clarification_count int 5 Agent 最少提问数
standard_answer_reviewers int 3 标准答案评审人数
consensus_threshold float 0.67 共识阈值(2/3)
blind_review bool true 是否盲评
time_limit_per_prd int 1800 单 PRD 处理时限(秒)
repeat_count int 2 每个 Agent 重复次数(取均值)

八、落地检查清单

  • 测试 PRD 故意包含 5-10 个模糊点,由资深 PM 审核
  • 标准答案由 3 位以上评审者独立列出,取共识
  • 各 Agent 在相同环境下运行(网络、配置)
  • 提问质量盲评者不知道问题来自哪个 Agent
  • 区分"真正等待回答的提问"和"假设性提问"
  • 结果按提问类型(业务/技术/边界)分组统计
  • 记录了首次实现通过率和返工率
  • 结论包含"提问覆盖率 vs 实现质量"的相关性分析

九、系列导航

上一篇:Jira / Linear 集成实战:从需求卡片到 Agent 执行计划 下一篇:多模型路由系统:任务难度、风险等级与成本预算如何决策