AI Agent 上线后,真正棘手的问题不是“能不能回答”,而是错误能否被稳定复现、自动发现并阻止进入生产环境。Motorway 与 AWS 构建的端到端评估流水线,将错误结果从每 8 次查询约 1 次降到每 50 次约 1 次,同时把问题发现时间从数小时缩短到几分钟。其核心组合是 Strands Agents SDK 与 Amazon Bedrock AgentCore:前者负责 Agent 的构建与编排,后者负责规模化部署和运行。
把评估做成流水线,而不是上线前抽查
Agent 的输出通常不是固定字符串。它可能调用工具、检索文档、执行多步推理,还可能因上下文和模型采样产生变化。因此,只检查最终文本是否与标准答案完全一致,覆盖不了真实风险。
一条面向生产的评估流水线可以拆成五个环节:
- 从真实请求、历史故障和人工设计的边界条件中维护评估数据集。
- 在隔离环境中运行 Strands Agent,记录回答、工具调用、延迟和异常。
- 使用确定性规则、模型裁判和人工复核组合评分。
- 将当前版本与稳定基线比较,设置发布门禁。
- 部署到 AgentCore 后持续采样生产轨迹,把新问题回灌到数据集。
这形成了一个闭环:生产故障不只生成告警,还会变成下一轮回归测试。检测时间之所以能从小时级缩短到分钟级,关键并非某个单独评分器,而是评估能够自动触发、批量执行并立即聚合结果。
不要只看“答对率”
生产 Agent 至少需要观察以下维度:
- 任务正确性:回答是否满足用户目标,关键事实是否正确。
- 工具调用:是否选择了正确工具,参数是否合法,是否出现重复或危险调用。
- 依据一致性:回答是否得到检索内容或工具结果支持。
- 安全边界:是否泄露敏感信息,是否执行未经授权的操作。
- 运行质量:延迟、错误率、超时率和单次执行成本是否恶化。
确定性检查适合验证 JSON Schema、必填字段、金额、ID 和工具调用参数;模型裁判适合判断相关性、完整性和依据一致性。模型裁判本身也会波动,因此应固定提示词与模型版本,保存评分理由,并用人工标注样本定期校准。
发布门禁也不宜只设一个总分。例如平均正确率上升,可能掩盖支付场景中的严重回归。更稳妥的做法是按场景分组,并对高风险用例设置零容忍阈值。
可以这样实践:先建立可运行的回归门禁
下面是一个不依赖特定 SDK 版本的最小示例。假设 Strands Agent 或 AgentCore 测试任务已经把结果导出为 results.jsonl。每行包含用例 ID、场景、是否正确、延迟和工具调用是否合规。字段结构是示例约定,需要根据实际追踪数据调整。
创建 results.jsonl:
{"id":"support-001","category":"support","correct":true,"latency_ms":820,"tool_valid":true}
{"id":"support-002","category":"support","correct":true,"latency_ms":940,"tool_valid":true}
{"id":"payment-001","category":"payment","correct":false,"latency_ms":1100,"tool_valid":false}
创建 evaluate.py:
#!/usr/bin/env python3
import json
import sys
from collections import defaultdict
from pathlib import Path
path = Path(sys.argv[1] if len(sys.argv) > 1 else "results.jsonl")
rows = [json.loads(line) for line in path.read_text().splitlines() if line.strip()]
if not rows:
raise SystemExit("No evaluation results found")
by_category = defaultdict(list)
for row in rows:
by_category[row["category"]].append(row)
accuracy = sum(r["correct"] for r in rows) / len(rows)
tool_validity = sum(r["tool_valid"] for r in rows) / len(rows)
latencies = sorted(r["latency_ms"] for r in rows)
p95_index = min(len(latencies) - 1, int(len(latencies) * 0.95))
p95_latency = latencies[p95_index]
failures = []
if accuracy < 0.98:
failures.append(f"accuracy {accuracy:.1%} is below 98%")
if tool_validity < 1.0:
failures.append(f"tool validity {tool_validity:.1%} is below 100%")
if p95_latency > 3000:
failures.append(f"p95 latency {p95_latency} ms exceeds 3000 ms")
# High-risk payment cases must have no correctness or tool-call failures.
for row in by_category.get("payment", []):
if not row["correct"] or not row["tool_valid"]:
failures.append(f"critical payment case failed: {row['id']}")
print(json.dumps({
"cases": len(rows),
"accuracy": round(accuracy, 4),
"tool_validity": round(tool_validity, 4),
"p95_latency_ms": p95_latency,
"failures": failures,
}, indent=2))
raise SystemExit(1 if failures else 0)
运行评估:
python3 evaluate.py results.jsonl
脚本在指标未达标时返回非零退出码,可以直接接入 CI。实际项目中,可把“当前候选版本”和“生产基线版本”各执行多次,除了绝对阈值,还拒绝统计上明显的回归。
对于难以用规则判定的答案,可以增加一个模型裁判步骤。裁判提示词应要求输出结构化 JSON,例如:
你是生产级 Agent 评估器。请根据用户问题、参考资料和 Agent 回答评分。
只输出 JSON:
{"correct": true|false, "grounded": true|false, "reason": "简短理由"}
用户问题:{{question}}
参考资料:{{reference}}
Agent 回答:{{answer}}
不要让同一个裁判分数直接决定高风险操作是否安全。支付、权限变更和数据删除等场景仍应使用确定性检查与人工复核。
Strands 与 AgentCore 各自承担什么
可以把 Strands Agent 视为待测应用:它定义模型、工具、提示词和执行流程。测试运行器用固定数据集调用 Agent,并收集完整轨迹。AgentCore 则提供托管的部署和运行环境,使团队可以在接近生产的条件下执行候选版本,并持续观察线上 Agent。
落地时应把以下内容作为一个可追踪的评估版本保存:
- Agent 代码提交、模型标识和推理参数。
- 系统提示词、工具定义与知识库版本。
- 数据集版本及各场景样本数量。
- 评分器提示词、规则代码和阈值。
- 原始轨迹、聚合指标与失败样本。
如果只保存一个总分,团队很难回答“哪次改动导致哪类请求退化”。保留版本和轨迹,才能让几分钟内出现的告警继续指向可修复的原因。
上线前的采用清单
先从历史故障构建几十个高价值用例,比一开始追求庞大数据集更有效。随后把回归评估接入每次提示词、工具、模型或知识库变更,并在 AgentCore 生产运行中采样真实轨迹。
上线门禁至少应满足四项要求:高风险场景单独设阈值;规则检查与模型裁判并用;失败样本能够回放;评分配置和 Agent 版本能够追溯。还要控制评估成本和数据隐私,尤其不要未经脱敏就把生产对话送入外部评分模型。
最终目标不是追求一个漂亮的离线分数,而是缩短“引入问题、发现问题、复现问题、验证修复”的整个周期。Motorway 与 AWS 的结果说明,当评估成为持续运行的工程系统后,Agent 的可靠性和团队响应速度可以同时改善。