用 Strands Evals 和 Amazon Bedrock AgentCore 评估配备技能的智能体
通用智能体能处理各种任务,但你还需要它们遵循业务运转的既定流程:合规检查、文档处理工作流、升级策略、工程规范。把这些全塞进一个系统提示或应用逻辑里,维护和更新都会变得很困难。
技能(Skill)是一种模块化的替代方案。一个技能就是一组可复用的指令,通常存放在 SKILL.md 文件里,用来教智能体完成某个特定领域的任务,比如对合同做脱敏处理、核对发票,或者遵循团队的拉取请求(PR)规范。由于技能遵循开放的 Agent Skills 标准,它们可以在兼容的运行框架之间移植,而且智能体在运行时只加载需要的那一个技能,而不必把所有流程都塞进核心指令里。
一个技能把工具和智能体正确使用这些工具所需的上下文打包在一起:
- 指令(Instructions):注入智能体上下文中的领域专属指导和约束。
- 工具绑定(Tool bindings):技能依赖的 API、Model Context Protocol(MCP,模型上下文协议)服务器或本地命令。
- 知识(Knowledge):参考资料和示例。
- 工作流(Workflow):技能遵循的多步骤流程或决策逻辑。
- 护栏(Guardrails):格式要求、范围限制和校验规则。
这种模块化方式能帮团队更快地让智能体具备专项能力,在不同智能体和工作流之间复用经过验证的流程,保持行为一致,还能在不微调底层模型、不重写智能体核心逻辑的前提下更新领域专属指导。
不过,智能体中的这种技能组合也会带来两种失败模式,而通用的输出质量指标往往发现不了:
- 智能体调用了不适合当前任务的技能;
- 智能体调用了正确的技能,却跳过或只部分遵循了它的指令。
这两种失败都可能产出一段流畅、看似合理的回答,但实际上并没有用上你预设的领域知识。因此,评估不能只看最终的回答。
为了让这些失败可量化,Strands Evals SDK 和 Amazon Bedrock AgentCore Evaluations(Amazon Bedrock AgentCore 的一项能力)新增了以技能为核心的评估器:
- 技能选择准确性(Skill Selection Accuracy):判断每次调用的技能是否适合当前任务,对每个被调用的技能返回二元结果。
- 技能指令遵循度(Skill Instruction Following):衡量 agent 对某个技能指令的遵循程度,针对技能规定的每个步骤,给出有证据支撑的五级评分。
此外,Strands Evals 上还有一个 Skill Invoked,它是确定性检查,用来判断指定技能是否成功加载。
本文将介绍:如何在 Strands Evals 中根据录制的轨迹评估技能选择和指令遵循;如何向测试套件添加确定性的路由检查;如何用 AgentCore Evaluations 从 OpenTelemetry 追踪数据评估技能行为;以及如何解读每个技能的结果来选择合适的修复方案——全部通过 AgentCore CLI 完成。
了解每个评估器衡量什么
agent 收到一个任务和一份技能目录,从中选择技能、加载它,然后执行操作。整个过程会在 Strands Evals 中记录为一条轨迹,或在你的可观测层中记录为一条 OpenTelemetry 追踪。现在,这三种技能评估器都可以使用这份记录。
技能选择准确性检查每次调用的技能是否与任务匹配,以及 agent 是否调用了正确的技能。下图展示了 agent 如何从提供给它的 1:n 技能中做出选择。技能选择准确性随后评估所选技能是否是当前任务的正确选择。你可以在提示词模板文档中找到该评估器的提示词模板和评分标准。
图 1:技能选择准确性检查 agent 是否为任务选择了合适的技能
技能指令遵循度关注的是 agent 对该技能规定步骤的遵循程度。你可以在提示词模板文档中找到该评估器的提示词模板和评分标准。
图 2:技能指令遵循度衡量 agent 对技能步骤的遵循程度
Skill Invoked 是确定性的:它不调用任何模型,且专属于 Strands Evals。
这些技能评估器的整体结构如下图所示。
图 3:三种技能评估器总览
设想一个 HR 助手智能体,它具备两个技能:带薪休假(PTO)规划和员工福利咨询。员工问起自己的牙科与视力福利。如果智能体调用了福利技能,它给出的回答可能更完善。假如工具调用成功了,但智能体选错了技能,那么「技能选择准确性」(Skill Selection Accuracy)就能把这次错误的路由决策单独拎出来。
再假设智能体正确地调用了 PTO 规划技能来处理一个相关请求。该技能要求智能体先确认 employee_id,查询 PTO 余额,对照最新 HR 政策检查结转规则,条件允许时再提交休假申请。如果智能体查了余额却跳过了结转规则检查,它仍可能返回一个看似合理的回答,但已经违反了既定流程。这时「技能指令遵循度」(Skill Instruction Following)会把这次执行失误单独定位出来,并指出被跳过的那一步。
两类失败的修复方向并不相同。选错技能,往往说明技能描述之间有重叠或含义不清;指令遵循不完整,则可能需要更清晰的步骤、不同的技能结构,或者换成能力更强的智能体模型。
| 评估器 | 可用来源 | 评分方式 | 回答的问题 |
|---|---|---|---|
| Skill Selection Accuracy | Strands Evals 和 AgentCore Evaluations | 二值,按调用的技能计 | 调用这个技能对当前任务是否合适? |
| Skill Instruction Following | Strands Evals 和 AgentCore Evaluations | 五个等级,按调用的技能计 | 智能体在多大程度上遵循了该技能规定的步骤? |
| Skill Invoked | Strands Evals | 二值,确定性判断 | 这个指定的技能是否成功加载? |
由于基于裁判(judge)的评估器会按每一次技能调用来返回结果,多技能场景仍然可诊断:你可以找出是哪一次技能选择或指令遵循结果把整体评分拉低了。如果没有调用任何技能,基于裁判的评估器不会给出评分。当回归测试对路由有明确要求时,可以把它和 SkillInvoked 搭配使用。
前置条件
- Python 3.10 或更高版本。
一个能访问 Amazon Bedrock 的 AWS 账户,以及有权限调用评判模型(judge model)的凭证,具体是 InvokeModel 权限。要跟着 Strands Evals 这一节动手,先装好 SDK:pip install strands-agents-evals strands-agents 另外还需要一份记录好的智能体运行轨迹(agent run)。技能评估器(skill evaluators)既接受 Strands Evals 的 Session 对象,也接受原始的消息列表作为轨迹。上线时,技能提取能识别来自这些来源的信号:Strands AgentSkills 插件、Claude Code、Claude Agent SDK、OpenAI Agents SDK、Codex、Gemini CLI、OpenHands、Google ADK,以及通用 SKILL.md 文件读取。 要跟着 AgentCore Evaluations 这一节动手,需要:一个托管在 Amazon Bedrock AgentCore 运行时或其他地方的智能体。我们会用 HR 助手智能体作为例子,你可以把它部署到自己的账户里。为该智能体打开可观测性(Observability),让它把遥测数据发给 Amazon CloudWatch。在 CloudWatch 中启用事务搜索(Transaction Search)。本文示例使用 AgentCore CLI:npm install -g @aws/agentcore 用 Strands Evals 评估一段记录好的轨迹 当你能掌控测试用例、并且可以在开发或持续集成过程中重跑智能体时,Strands Evals 很好用。完整的 Strands Evals 代码示例可以在这里查看,是为 HR 助手智能体准备的。 1. 定义用例和评估器 from strands_evals import Case, Experiment
from strands_evals.evaluators import (
SkillInstructionFollowingEvaluator,
SkillInvoked,
SkillSelectionAccuracyEvaluator,
)
case = Case(
name="q3-revenue-tables",
input="Summarize the revenue tables in q3-report.pdf",
)
evaluators = [
SkillSelectionAccuracyEvaluator(),
SkillInstructionFollowingEvaluator(),
SkillInvoked(skill_name="pdf-table-extraction"),
]
2. 运行 Agent,并记录它的执行轨迹
技能类评估器需要读取这次运行的执行轨迹(trajectory)。TracedHandler 会收集 Agent 产生的所有 span,并把它们作为轨迹挂上去:
from strands import Agent
from strands_evals import TracedHandler, eval_task
@eval_task(TracedHandler())
def task_function():
return Agent(...) # 你那个装了技能的 Agent
experiment = Experiment(cases=[case], evaluators=evaluators)
report = experiment.run_evaluations(task_function)
report.run_display()
3. 读懂这份报告
假设 Agent 确实加载了 pdf-table-extraction,也跑了 pdftotext -layout,但它从来没有打开过提取出来的文件,也没去定位表格的边界。简化后的报告大致是这样:
SkillSelectionAccuracyEvaluator: score=1.00, pass=True
pdf-table-extraction: 该技能与请求直接匹配。
SkillInstructionFollowingEvaluator: score=0.50, pass=False
pdf-table-extraction: 提取阶段完成了,
定位表格边界这一步被跳过了。
Steps:
- 保留布局提取文本:已完成
- 定位表格边界:已跳过
- 汇总每张表格的头条数字:部分完成
SkillInvoked: score=1.00, pass=True
skill 'pdf-table-extraction' was invoked
Skill Instruction Following(技能指令遵循)采用五档评分:完全遵循(1.0)、大部分遵循(0.75)、部分遵循(0.5)、少量遵循(0.25)、未遵循(0.0)。达到「大部分遵循」及以上即算通过。
把检查变成部署门禁
对每个关键技能,只要它必须被某个回归用例调用,就加一条 SkillInvoked 检查。它不会调用模型,因此只是一个快速的路由断言。
用 report.test_passes 给构建加门禁:
if not all(report.test_passes):
raise SystemExit(1)
聚合分数可以用来观察更长远的趋势,但在真正启用阈值之前,请先用自己的用例把它校准好。
用 AgentCore Evaluations 评估生产链路数据
AgentCore Evaluations 能直接处理现有的 OpenTelemetry 链路数据(trace),支持按需评估、对已存会话做批量处理,以及对实时流量做持续采样。
遥测数据按 session(会话)、trace(链路)、span(跨度)三层组织。由于技能评估器工作在工具调用这一层,每条结果都会带上一个 spanContext,里面记录了被识别出的技能调用对应的 sessionId、traceId 和 spanId。
识别一次技能调用有两种途径:一是读取 SKILL.md 文件——这种方式跨框架通用;二是通过原生技能加载工具,Strands Agents、LangGraph Deep Agents、Google ADK 和 Claude Agent SDK 都支持。
给自定义评估器用的链路占位符
AgentCore Evaluations 内置了两个基于裁判模型(judge)的技能评估器。如果要评内置评估器没覆盖的内容,可以在 TOOL_CALL 这一层创建自定义评估器。工具层的模板可以引用技能相关的占位符:
| 占位符 | 内容 |
|---|---|
{invoked_skill} |
本次工具调用加载的技能名称 |
{skill_content} |
加载进来的 SKILL.md 正文 |
{available_skills} |
运行时提供的技能目录,或「(not recorded by this harness)」 |
{user_message} |
触发这次调用的请求 |
{context} |
对话记录 |
举个例子,一个只检查技能运行中某一项属性的模板:
## Skill instructions
{skill_content}
## Conversation record
{context}
评估问题
智能体是否按照上面技能指令中的编号顺序,完成了每一个步骤?回答 Yes 或 No。你引用的占位符也决定了评估器何时运行。包含 {invoked_skill} 的模板只在技能调用片段(skill-invocation span)上运行;包含 {skill_content} 的模板还需要加载技能正文。
下面的命令针对单独的、启用了技能的运行时。请把 skills-evaluation/agent_config.json 里的运行时名称(agent_id 或 agent_arn)替换到 <skill-runtime> 的位置。Strands.SkillInvoked 只在客户端可用,命令行没有对应项。
运行按需评估
想排查某次会话、验证最近的改动,或者评估正在灰度中的流量,可以用按需评估:
agentcore run eval \
--runtime <skill-runtime> \
--evaluator Builtin.SkillSelectionAccuracy Builtin.SkillInstructionFollowing \
--session-id <session-id>
运行批量评估
想一次性给大量已保存的会话打分,比如在改动技能目录前建立基线,可以用批量评估:
agentcore run batch-evaluation \
--runtime <skill-runtime> \
--evaluator Builtin.SkillSelectionAccuracy Builtin.SkillInstructionFollowing
配置持续在线评估
在线评估会对线上流量采样,帮你发现那些人工设计的测试集没有预料到的行为:
agentcore add online-eval \
--name HRSkillsProductionEval \
--runtime <skill-runtime> \
--evaluator Builtin.SkillSelectionAccuracy Builtin.SkillInstructionFollowing \
--sampling-rate 100 \
--enable-on-create
然后部署,配置在线评估:
agentcore deploy
持续评估特别适合发现三类问题:目录漂移(新技能和已有技能的描述出现重叠)、意料之外的提问方式(真实请求和精心准备的测试提示不一样)、长会话失败(上下文越来越长,模型遵循指令的能力逐渐下降)。
最佳实践
评估智能体技能时,首先要记住:路由和执行是两种不同的失败模式,评估策略必须把它们干净地分开。
如果选择得分很高、但指令遵循得分很低,说明路由器挑对了技能,但技能没有被完整执行。反过来,如果选择得分低而指令遵循得分高,说明这个技能本身没问题,只是压根没被调用。
把这两项评估分开跑,而不是合并成一个通过/失败的数字,才能区分出上面这两种情况。
自己动手写评估逻辑之前,先用内置评估器建立基线。这样后面加的自定义逻辑,才能真正补上基线没覆盖到的那部分缺口。
如果某个需求里你已经明确知道正确的路由行为,就别依赖裁判模型来判断。给每个必须触发的技能加一条确定性的 SkillInvoked 断言。
开始跑评估之后,别只盯着总分看。真正的诊断信息藏在每一步的证据里。它能告诉你某条指令是完整覆盖了、只做了一半,还是干脆被跳过了——正是这种颗粒度,才能把一次失败的评估变成可执行的修复动作。
这也是为什么你应该在生命周期的每个阶段都做评估,而不是等最终结果出来才看。等到最后才失败,你根本分不清是路由器把请求送错了地方,还是正确的技能执行得很糟。这两种信号你都需要,才能判断该修哪里。
技能级评估和端到端评估要配套使用,因为一个技能可能执行得完美无缺,却仍然不是当前请求所需的那个技能。
很多歧义其实可以在上游就消掉,办法是把技能描述写得真正有区分度。技能的范围也是同样的道理。一个技能如果包办了六个互不相关的功能,它就不存在唯一一种「正确行为」的定义,也就几乎不可能做出一致的评估。要明确写清楚:只评估某次运行中实际走过的那条路径,否则没走到的分支会被误算成被跳过的步骤,悄悄拉低通过率。另外,在采信这些分数之前,先确认你的提取流水线确实是在真实调用链(live trace)上跑通的。
随着你把这套东西铺到更多工具上,阈值未必能直接照搬。每个评估面都要按各自的语境单独校准,因为在 Strands Evals 上拿到通过的分数,和在 AgentCore Evaluations 上拿到通过的分数,并不一定是同一个意思。
最后,这些工作都不该游离在部署流水线之外。技能质量的退化应该像单元测试失败一样直接卡住发布,否则你此前做的评估工作就没有真正保护到生产环境。
结论
技能让智能体可以低成本地做专项化,但一个看起来合理的最终答案,并不能证明智能体选对了流程,或者照着流程走完了。Skill Selection Accuracy(技能选择准确率)和 Skill Instruction Following(技能指令遵循度)把这两类失败模式区分开来,并针对每个被调用的技能给出证据。在 Strands Evals 里,SkillInvoked 为已知的路由要求提供了一道确定性防线。在 AgentCore Evaluations 里,这两个基于评判模型(judge)的指标可以按需跑某个指定会话,也可以对已存储的会话批量评估,或者对采样流量持续监控。手头有测试用例和可重放的轨迹记录时,用 Strands Evals;想评估来自预发布或线上智能体的 OpenTelemetry 链路时,用 AgentCore Evaluations。很多团队会两者都用:部署前用确定性和评判模型两道关卡,上线后用基于链路的监控。
上手
- Strands Evals 快速入门
- Strands Evals 代码仓库
- Amazon Bedrock AgentCore Evaluations 开发者指南
- 评估 AI 智能体的博客文章
致谢
感谢 Ritvika Pillai、Vincent Chen、Qiaoxuan Xue 和 Shoaib Javed 完成 AgentCore Evaluations 的实现;感谢 Po-Shin Chen 审阅 Strands Evals;感谢 Anwesan Pal 在技能评估方面的早期讨论;感谢 Ben Coombs 的产品指导;也感谢所有为这项工作提供帮助的同事。
作者简介
Sangmin Woo
Sangmin 是 AWS AI Labs 的应用科学家,从事智能体 AI(agentic AI)方向的机器学习研究与方案开发,重点关注评估框架以及智能体行为与性能的提升。他的研究兴趣包括智能体 AI、生成模型和多模态 AI。工作之余,他喜欢旅行,探索新的地方。
Bharathi Srinivasan
Bharathi 是 AWS 的生成式 AI 数据科学家,热衷于推动负责任 AI,以提升智能体在真实场景中的可靠性。她为内部团队和 AWS 客户提供负责任 AI 方面的指导。
Shruthi Rajoli
Shruthi 是 AWS 的解决方案架构师,常驻伊利诺伊州芝加哥。她主要负责美国东部地区的初创企业,帮助早期和成长期公司设计并构建可扩展的 AWS 云架构,重点关注生成式 AI、智能体 AI 工作流、数据以及迁移类工作负载。工作之余,她喜欢散步、瑜伽,也爱发掘新的美食和咖啡馆。
Visakh Madathil
Visakh 是 AWS 的解决方案架构师,与客户及内部团队合作,致力于让生产环境中的 AI 更加清晰可读、可信可靠。他在智能体可靠性和 AI 安全方面的研究成果曾在机器学习会议上展示。工作之余,他喜欢音乐、观鸟和运动。
Renu Rozera
Renu 是 Amazon Web Services 的软件开发工程师,负责 Amazon Bedrock AgentCore。她此前参与构建了 AgentCore Memory,目前专注于为 AgentCore Evaluations 及优化功能开发可扩展系统,帮助客户评估并持续提升其智能体应用的质量。
Vinayak Arannil
Vinayak 是 Amazon Web Services 的资深应用科学家。
Vinayak 有多年从业经验,涉足计算机视觉、自然语言处理、推荐系统等多个 AI 领域。目前他在 AgentCore 和 Strands 上开发新功能,帮助客户轻松、准确、高效地评估自己的智能体应用。
Haibo Ding
Haibo 是 Amazon 的首席应用科学家兼经理,从事智能体 AI 相关工作,拥有犹他大学博士学位。他的研究聚焦大语言模型(LLM)和 AI 智能体,主导智能体评估、智能体工具优化、提示词优化、模型路由等方向的工作。他曾担任 AAAI、ACL 等会议的分区主席(area chair),此前还担任过 KDD 2025 提示词优化研讨会(Workshop on Prompt Optimization)的程序主席。
Jonathan Buck
Jonathan 是 AWS 的高级软件工程师。他负责构建智能体运行环境、评估框架和训练后基础设施,把智能体 AI 领域的研究进展落地为可靠的生产系统。