最近在搭建 Agent 工程化评测流程时,我一直被一个很实际的问题困扰:为了让 Agent 更好地完成 Web 开发任务,团队设计了一大堆“技能”(Skills),但技能到底带来了多少收益,却很难用数据说清楚。有的技能看着专业,实际调用率很低;有的技能不起眼,却是任务完成的关键。于是我把评测思路整理成了一套可复用的 WebDev-Skills-Bench 评测框架,围绕“Agent 技能是否真的有用”这个核心问题,从评测维度、技能分类、实验对比、工程落地四个方面做了完整梳理。
本文适合正在设计 Agent 技能方案的开发者、想评估大模型编码能力的同学,以及关注 Web 开发自动化落地的人。读完你会掌握一套可复用的技能评测方法,也能学会如何设计技能、如何量化技能收益、如何避开评测中的常见陷阱。
1. 背景与核心概念
1.1 什么是 WebDev-Skills-Bench
WebDev-Skills-Bench 是一类面向 Web 开发场景的 Agent 技能评测基准(Benchmark)。它的核心目的是:在可控的评测任务上,给 Agent 配置不同技能组合,观察任务完成率、代码质量、运行稳定性等指标,从而判断某个技能是否真的对 Agent 有帮助。
这里需要先解释一个关键概念:Agent 技能到底是什么。在 LLM 时代,Agent 技能可以理解为一组可复用的工具、代码片段、提示词模板或交互协议。Agent 在接到任务后,根据任务描述和上下文选择调用合适的技能,而不是从零开始用自然语言生成所有内容。例如,在 Web 开发场景中,“使用 HTML5 Canvas 绘制画面”“构建游戏主循环”“定位浏览器报错”都可以封装成技能。
WebDev-Skills-Bench 最常见的做法是:准备一批从易到难的 Web 开发任务,比如还原设计稿、实现一个贪吃蛇游戏、修复一个前端报错、完成前后端接口联调。每个任务都关联若干“候选技能”,Agent 可以在任务过程中按需调用。评测系统记录调用顺序、调用次数、任务结果、运行时间等信息,最后汇总成量化报告。
1.2 Agent 技能解决什么问题
没有技能的 Agent 也能写代码,但存在几个明显痛点:
- 每次任务都从零生成,缺乏稳定输出模式,代码风格漂移。
- 对专业场景(如 Canvas 游戏开发、复杂日志排查)不熟悉,容易写出有缺陷的代码。
- 无法复用历史经验和团队沉淀的最佳实践。
- 难以在任务中途干预和修正,出了问题只能靠模型自行反思。
引入技能后,Agent 可以把“会写代码”升级为“按团队标准写代码”。技能里可以封装项目脚手架模板、错误排查步骤、调试工具用法、测试运行命令。这样不仅能提升成功率,也能让输出结果更容易被人工 review。
1.3 为什么要评测技能是否有用
只定性地觉得“某个技能有用”是不够的。技能本身有成本,主要体现在:
- 开发成本:每个技能都需要设计、编写、测试和维护。
- 上下文成本:技能描述会占用系统提示词空间,技能越多,Agent 的注意力越分散。
- 调用成本:技能如果设计得不好,Agent 可能选错技能或错误调用,反而拖慢任务。
- 监控成本:技能越多,线上日志和排错链路越复杂。
所以我们需要一套评测基准,用数据回答几个关键问题:技能 A 能带来多少完成率提升?技能 B 和技能 C 是叠加关系还是冲突关系?去掉某个技能后,成绩下降多少?这些问题,只有通过设计良好的评测实验才能回答。
2. 评测维度与核心指标
设计 WebDev-Skills-Bench 之前,先要明确评测维度。评测维度决定了我们如何给一次任务结果打分。
2.1 任务完成率(Completion Rate)
任务完成率是最直观的指标。一个评测任务通常会包含若干条明确需求,例如“实现一个贪吃蛇游戏,支持方向键控制”“吃到食物后蛇身变长”“游戏结束后可以重新开始”。如果 Agent 的产出覆盖了全部需求,则视为任务完成;部分覆盖则按比例计分。
需要说明的是,完成率只统计“是否做到”,不统计“做得怎么样”。所以它必须和其他指标配合使用。
2.2 正确性与功能可用性(Correctness)
正确性关注产出结果是否真正可用。对于 Web 开发任务,可以通过以下方式自动或半自动验证:
- 是否能在目标浏览器中正常打开。
- 交互逻辑是否符合预期,例如点击按钮、键盘输入是否触发正确响应。
- 代码是否存在明显运行时错误,如未定义变量、空指针、资源加载失败。
- 是否有配套的测试用例,且测试用例通过。
对于游戏类任务,正确性还包括游戏循环是否正常、碰撞检测是否准确、计分逻辑是否合理。这些功能往往需要启动浏览器执行实际操作来验证,比单纯看代码难度更高。
2.3 代码质量(Code Quality)
代码质量可以从多个角度评估:
- 结构是否清晰,是否合理拆分了函数和模块。
- 命名是否规范,变量、函数、组件名是否表意明确。
- 是否包含明显的硬编码或重复代码。
- 是否遵循了团队既定的代码规范,如 ESLint、Prettier 规则。
- 是否有必要的错误处理和边界判断。
自动评估代码质量时,可以接入静态检查工具,也可以结合代码提交记录和人工评分。为了减少人工成本,通常建议先跑静态检查,再对通过检查的代码做少量人工抽检。
2.4 效率指标(Efficiency)
效率指标用来衡量完成同等级任务所需的代价,常见的包括:
- 任务耗时:从 Agent 接收任务到产出最终结果的总时间。
- Token 消耗:Agent 在完成过程中使用的输入和输出 token 总量。
- 工具调用次数:技能、API、命令行的调用次数。
- 修订轮数:Agent 从首次生成到最终通过验证之间经历的修订次数。
效率指标非常重要,因为它能体现技能“是否让 Agent 更省力”。如果一个技能能把任务的修订轮数从 5 次降到 2 次,即使绝对耗时略有增加,也是很有价值的优化方向。
2.5 稳定性(Stability)
大模型输出具有随机性,同一个任务运行多次可能得到不同结果。稳定性指标通常通过“重复运行 N 次,统计成功次数”来度量,例如:
- 10 次运行中,完整完成率是多少。
- 功能验证通过率是否稳定。
- 生成的代码结构是否相似。
评测时建议固定模型版本、参数(如 temperature)和随机种子,并重复至少 3 次取平均值,这样才能得到相对可靠的结论。
3. Agent 技能的分类与应用场景
3.1 技能分类方法
在 WebDev-Skills-Bench 评测中,我习惯把 Agent 技能分成四类:
| 技能类型 | 说明 | 示例 |
|---|---|---|
| 基础开发技能 | 覆盖通用 Web 开发能力 | 项目脚手架、HTML/CSS/JS 代码生成、组件封装 |
| 领域专项技能 | 面向特定垂直场景 | 游戏循环构建、Canvas 渲染、Canvas 动画优化 |
| 调试排错技能 | 帮助 Agent 定位和修复问题 | 浏览器日志解析、错误定位、接口返回检查 |
| 验证交付技能 | 保证产出质量 | 单元测试生成、测试运行、静态检查、打包部署 |
设计技能时,要注意技能的边界。技能越单一,越容易被 Agent 理解和调用;技能太庞大,Agent 可能只知道技能名字,却不知道内部做了什么,调用后反而引入新的问题。
3.2 开发游戏需要给 Agent 添加哪些技能
最近“开发游戏给 Agent 需要添加哪些技能”是比较热的话题,正好可以拿它来具体说明技能设计。
以“让 Agent 开发一个贪吃蛇网页游戏”为例,如果只给 Agent 一个简单的“编写游戏代码”技能,效果通常不会太好。游戏开发涉及多个相对独立的子问题,更合理的做法是拆分成一组技能:
- 项目初始化技能:自动创建 HTML/CSS/JS 文件,引入必要的依赖。
- Canvas 渲染技能:封装画布创建、坐标系设置、蛇身和食物的绘制函数。
- 游戏循环技能:基于 requestAnimationFrame 或 setInterval 构建游戏主循环,负责更新蛇的位置、检测碰撞、刷新画面。
- 事件绑定技能:统一处理键盘、鼠标和移动端触摸事件,避免监听重复绑定。
- 状态管理技能:管理游戏状态,包括运行中、暂停、结束、得分、关卡等级。
- 调试与性能技能:监控 FPS,捕获运行时异常,输出关键变量日志。
- 测试验证技能:生成并运行基础玩法测试,验证蛇移动、食物生成、碰撞结束等核心逻辑。
这种技能拆分的好处是:每个技能都能单独修改、单独评测。如果去掉“调试与性能技能”后,任务完成率从 82% 下降到 70%,就说明该技能对游戏开发任务有显著增益。
3.3 技能设计误区
在设计技能时,有一个常见误区值得单独说明:技能描述写得太笼统。例如“游戏开发技能”这种名字,Agent 看到后仍然不清楚应该调用什么工具、调用后会执行什么操作。更好的写法是:
技能名称:canvas-render 适用场景:任务需要绘制图形、画布动画、游戏画面、图表可视化时使用。 输入要求:目标画布 id、绘制对象的坐标和尺寸。 执行内容:封装 Canvas 初始化、坐标换算、矩形/圆形/图片绘制方法。 注意事项:不需要自己实现事件绑定,事件绑定请调用 input-event 技能。技能描述越具体,Agent 的调用决策就越准确。评测时也可以通过修改技能描述文本,观察同一任务上的完成率变化,从而验证描述质量的收益。
4. 动手搭建一个 WebDev-Skills 评测环境
接下来进入实战环节。我会用一套最小可运行的示例,演示如何搭建 WebDev-Skills-Bench 评测环境。示例以 Python 为主要语言,适用场景是评测“贪吃蛇网页游戏”这类任务。不同实际环境的参数需要根据你的项目情况调整,重点演示评测思路。
4.1 创建项目结构
先创建评测项目目录:
mkdir webdev-skills-bench cd webdev-skills-bench mkdir skills tasks reports目录说明:
skills/:存放 Agent 技能定义和技能实现。tasks/:存放评测任务 JSON 文件。reports/:存放评测结果输出。
4.2 定义评测任务
在tasks/下创建dev-skills-bench.json,定义一个贪吃蛇小游戏任务:
[ { "task_id": "mini-snake", "title": "贪吃蛇网页小游戏", "requirements": [ "支持方向键控制蛇移动", "食物随机生成,吃到后蛇身变长", "显示当前得分", "蛇碰到墙壁或自身时游戏结束", "游戏结束后可以重新开始" ], "skills": [ "project-scaffold", "canvas-render", "game-loop", "input-event", "state-manager", "debug-tool", "test-runner" ], "timeout": 600 } ]这里skills字段表示该任务允许 Agent 调用的技能集合。评测时可以通过增删这个字段里的技能,来模拟“无技能”“有基础技能”“有完整技能”等不同评测模式。
4.3 注册 Agent 技能
在skills/下创建registry.py,定义技能注册结构。为了便于后续扩展,这里使用简洁的 Python 类:
# skills/registry.py from dataclasses import dataclass, field from typing import Callable, Dict, Any @dataclass class AgentSkill: name: str description: str entry_point: str required_tools: list = field(default_factory=list) metadata: Dict[str, Any] = field(default_factory=dict) SKILL_REGISTRY = [ AgentSkill( name="project-scaffold", description="创建前端项目基础文件,包括 index.html、style.css、main.js。适用所有 Web 页面开发任务。", entry_point="skills/project_scaffold.py", ), AgentSkill( name="canvas-render", description="基于 HTML5 Canvas 完成画面渲染,包含画布创建、坐标系设置、矩形和图片绘制。适用于游戏或可视化任务。", entry_point="skills/canvas_render.py", ), AgentSkill( name="game-loop", description="使用 requestAnimationFrame 构建游戏主循环,负责状态更新和画面刷新控制。适用于需要连续动画的游戏任务。", entry_point="skills/game_loop.py", ), AgentSkill( name="input-event", description="统一处理键盘、鼠标、触摸事件,支持防重复绑定和事件解绑。适用于需要用户交互的页面。", entry_point="skills/input_event.py", ), AgentSkill( name="state-manager", description="管理游戏状态,包括运行中、暂停、结束、得分、关卡等字段,并提供状态变更通知。适用于有明确状态的游戏任务。", entry_point="skills/state_manager.py", ), AgentSkill( name="debug-tool", description="捕获运行时异常、输出关键变量日志、监控 FPS。适用于任务运行异常或性能不佳时。", entry_point="skills/debug_tool.py", ), AgentSkill( name="test-runner", description="根据任务要求生成并运行基础测试,验证核心逻辑是否可用。适用于需要交付验收的任务。", entry_point="skills/test_runner.py", ), ] def get_skill_by_name(skill_name: str): for skill in SKILL_REGISTRY: if skill.name == skill_name: return skill return None每个技能都包含name和description两个核心字段。description会作为系统提示的一部分提供给 Agent,帮助它决定什么时候调用该技能。
4.4 编写评测运行器
在项目根目录创建runner.py,用来加载任务、调用 Agent、记录技能调用信息、输出评测结果。
# runner.py import json import time import random from pathlib import Path from skills.registry import get_skill_by_name def load_tasks(task_file: str): with open(task_file, "r", encoding="utf-8") as f: return json.load(f) def mock_agent_run(task, skill_names, model_name="mock-agent"): """ 模拟 Agent 运行流程。 实际项目中,这里应该替换为真实的大模型或 Agent 框架调用。 此处仅用于演示评测流程。 """ start_time = time.time() # 模拟 Agent 感知技能描述 skill_context = [] for skill_name in skill_names: skill = get_skill_by_name(skill_name) if skill: skill_context.append(f"[{skill.name}] {skill.description}") # 模拟任务结果:demo 模式下随机生成完成情况 base_score = 0.6 if "game-loop" in skill_names and "canvas-render" in skill_names: base_score += 0.2 if "test-runner" in skill_names: base_score += 0.1 # 加一点随机扰动,模拟真实评测的波动 score = min(1.0, base_score + random.uniform(-0.05, 0.05)) elapsed = time.time() - start_time return { "task_id": task["task_id"], "completed": score >= 0.8, "score": score, "runtime": round(elapsed, 2), "skill_context": skill_context, "model": model_name, } def evaluate(task, result): """ 评测后处理:将 Agent 输出转换为评测报告。 真实场景中这里会解析 Agent 生成的代码、运行测试、调用静态检查。 """ passed_requirements = 0 total_requirements = len(task["requirements"]) # 示例逻辑:以 score 是否满足要求为判断依据 threshold = 0.75 if result["score"] >= threshold: passed_requirements = total_requirements else: passed_requirements = int(total_requirements * result["score"] / threshold) correctness = result["score"] code_quality = max(0.4, min(1.0, result["score"] - 0.1)) return { "task_id": result["task_id"], "model": result["model"], "completion_rate": round(passed_requirements / total_requirements, 2), "correctness": round(correctness, 2), "code_quality": round(code_quality, 2), "runtime_seconds": result["runtime"], "skill_count": len(result["skill_context"]), } def run_benchmark(task_file: str, skill_mode: str, model_name: str, repeats: int = 3): tasks = load_tasks(task_file) all_reports = [] for task in tasks: skill_names = task["skills"] if skill_mode == "no-skill": skill_names = [] elif skill_mode == "base-skill": skill_names = [ "project-scaffold", "canvas-render", "input-event", ] elif skill_mode == "full-skill": skill_names = task["skills"] elif skill_mode == "custom": # 自定义模式:按需调整 pass for i in range(repeats): result = mock_agent_run(task, skill_names, model_name=model_name) report = evaluate(task, result) report["repeat"] = i + 1 report["skill_mode"] = skill_mode all_reports.append(report) return all_reports if __name__ == "__main__": reports = run_benchmark( task_file="tasks/dev-skills-bench.json", skill_mode="full-skill", model_name="mock-agent", repeats=5 ) with open("reports/result.json", "w", encoding="utf-8") as f: json.dump(reports, f, ensure_ascii=False, indent=2) print(json.dumps(reports, ensure_ascii=False, indent=2))这是一个演示用的最小实现。实际项目中,“mock_agent_run”需要替换成真实 Agent 框架的调用逻辑,同时还要增加代码解析、浏览器自动化验证、静态检查等模块。
4.5 运行评测
执行以下命令运行评测:
python runner.py预期会输出类似如下的结果(实际数值会因为随机扰动而变化):
[ { "task_id": "mini-snake", "model": "mock-agent", "completion_rate": 1.0, "correctness": 0.82, "code_quality": 0.72, "runtime_seconds": 0.01, "skill_count": 7, "repeat": 1, "skill_mode": "full-skill" } ]其中completion_rate表示需求覆盖比例,correctness表示功能正确性,code_quality表示代码质量评分。通过修改skill_mode参数为no-skill、base-skill、full-skill,就能得到不同技能配置下的对比结果。
4.6 对比实验设计
为了让“技能是否有用”这个结论有说服力,建议至少跑三组对比:
- 无技能组:
skill_mode="no-skill",Agent 只能依靠通用生成能力。 - 基础技能组:
skill_mode="base-skill",只给脚手架、渲染、事件绑定等基础技能。 - 完整技能组:
skill_mode="full-skill",加入游戏循环、状态管理、调试、测试等专项技能。
每组至少重复 3 次,最好 5 次以上,最终取平均值汇总成表格。下面这张表是一个典型的汇总结构(示例数据,仅用于说明格式):
| 技能模式 | 技能配置 | 完成率 | 正确性 | 代码质量 | 平均耗时 |
|---|---|---|---|---|---|
| no-skill | 无技能 | 52% | 0.63 | 0.58 | 482s |
| base-skill | 脚手架 + Canvas + 事件 | 74% | 0.71 | 0.69 | 356s |
| full-skill | 全部技能 | 86% | 0.85 | 0.82 | 328s |
从示例数据可以看出:基础技能能带来明显提升,而专项技能(游戏循环、状态管理、测试验证)在基础技能之上还能进一步拉高完成率和代码质量。这也说明,技能设计需要按场景深度递进,不是随便堆几个技能就能生效的。
5. 常见问题与排查思路
在搭建和运行 WebDev-Skills-Bench 评测时,经常会遇到一些问题。下面整理了几个高频问题,以及对应的排查思路。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 加了技能后任务完成率反而下降 | 技能描述太模糊,Agent 选错工具或重复调用 | 精简技能描述,写明触发条件、输入要求、输出内容 |
| Agent 完全不用技能,直接自己写代码 | Agent 没有意识到技能存在,或技能收益感知低 | 在系统提示词中强调“优先调用技能”,并在评测中记录技能调用率 |
| 评测任务运行超时 | 任务范围过大,或技能执行阻塞 | 拆分子任务,设置每步超时,使用流式输出避免长时间无响应 |
| 不同模型评测结果差异大 | 模型对工具调用的遵循能力不同 | 固定模型版本和参数,重复多次取平均值,并在报告中注明模型型号 |
| 技能能生成代码,但生成的代码跑不起来 | 缺少验证环节,或技能封装内容不完整 | 增加运行验证流程,把“生成后自动打开浏览器验证”作为技能调用的一部分 |
| 评测数据波动大,结论不稳定 | 随机种子未固定,或重复次数太少 | 固定随机种子,至少重复 3~5 次,用平均数和标准差一起报告 |
| 技能之间产生冲突,例如事件绑定重复 | 技能边界不清,多个技能维护同一块逻辑 | 每个技能只负责一件事,并在描述中明确“不要做什么” |
面对完成率下降的问题,我的经验是:先看技能调用日志,确认 Agent 是否在关键步骤调用了技能,还是在可调用时不调用。很多时候问题不在技能本身,而在于技能描述没有让 Agent 理解“当前任务正适用该技能”。
6. 最佳实践与工程建议
评测框架跑通之后,更重要的是形成一套可持续演进的设计规范。下面从技能设计、评测工程、结果解读三个方面给出工程建议。
6.1 技能设计原则
- 技能要小,职责单一。一个技能只解决一个问题,不要试图做一个“万能技能”。
- 描述要写明“何时用”。例如“当任务提到游戏循环、动画刷新时,调用 game-loop 技能”,而不是只写“游戏循环”。
- 要写明“不要做什么”。例如 “input-event 技能不负责处理业务逻辑,只负责事件绑定与解绑”,减少技能之间的职责重叠。
- 技能需要有版本。技能描述或实现一旦修改,建议保留版本号,例如
game-loop-v2,方便回溯评测结果。 - 技能要可测试。如果技能本身没有测试覆盖,就无法判断评测失败是因为 Agent 调用问题还是技能实现问题。
6.2 评测工程规范
评测过程本身也是工程问题,需要注意以下几点:
- 固定模型版本。同一个模型的不同版本,对工具调用的遵循能力差异很大。建议所有对比实验使用同一个模型版本。
- 固定参数配置。记录 temperature、top_p、max_tokens 等参数,避免参数漂移影响结果。
- 增加技能调用日志。只记录最终结果还不够,还要记录 Agent 在哪些步骤调用了哪些技能,调用顺序如何。这能帮助你定位“技能没被调用”还是“技能被调用但效果不好”。
- 引入人工抽检。自动指标有盲区,代码质量、交互体验这类维度需要人工抽检。建议每次评测后从结果中随机抽取 20% 的任务进行人工复核。
- 保证任务难度有梯度。评测任务应该按难度分成几个等级,避免所有任务都太简单或太难导致评测没有区分度。
6.3 迁移到真实 Web 开发场景
WebDev-Skills-Bench 的评测结论,最终要服务于真实开发场景。在从评测环境迁移到线上环境时,有几个点需要特别关注:
- 线上任务往往比评测任务大得多,建议把大任务拆成多个可验收的子任务,并为每个子任务配置合适的技能子集。
- 技能本身可能出现故障或返回不符合预期的结果,评测系统里要有降级方案,例如技能调用失败时自动回退到 Agent 直接生成代码。
- 评测指标要与业务目标对齐。如果团队更关心交付速度和 token 成本,效率指标的权重就应该高于代码质量指标。
- 不要只关注“有没有技能”,还要关注“技能有没有被正确使用”。建议把“技能调用准确率”也作为独立指标输出,例如 Agent 在需要调试的时候是否真的调用了调试技能。
6.4 常见最佳实践清单
整理成清单形式,方便在团队内快速落地方案:
- 先确定评测任务集,再设计技能。不要让技能决定任务,而是让任务驱动技能设计。
- 每个技能记录设计时间、使用次数、收益数据。定期清理调用率低且收益不明确的技能。
- 对比实验至少包含基线组,基线组通常是“无技能”或“仅通用技能”。
- 输出报告时同时包含“绝对指标”和“提升比例”,例如“完成率从 52% 提升 65%”。
- 所有结果数据、评测日志、模型版本配置统一归档,保证评测过程可复现。
- 对技能描述的调整,也要纳入评测范围。描述文案是技能的一部分,改变描述文案就是改变技能本身。
7. 总结与下一步
通过 WebDev-Skills-Bench 这套评测框架,我们可以相对定量地回答“Agent 技能是否真的有用”这个问题。核心结论是:技能确实有用,但不是越多越好,关键看技能与任务场景是否匹配,以及技能描述是否足够清晰。评测的意义在于,把“我觉得这个技能有用”变成“数据显示这个技能提升了多少完成率、降低了多少修订轮数”。
如果你准备在实际项目里落地这套评测流程,建议按照这个顺序推进。第一步,先整理出最近 1~2 个月内 Agent 实际执行过的 Web 开发任务,挑出其中最有代表性的 10~20 条作为评测任务集。第二步,对照任务集,梳理出基础技能和场景专项技能,先用小规模实验验证评测脚本本身是否稳定。第三步,跑对照组实验,把完成率、正确性、代码质量、效率、稳定性五个维度的数据沉淀下来,形成第一版评测基线。后续每调整一次技能描述或技能实现,都跑一遍基线看变化。
在更长期的规划中,还可以考虑把评测结果自动反馈到技能设计流程里。比如,当某个技能连续多轮在任务中没有被调用,或者调用后任务完成率没有提升,就可以标记为“低收益技能”,进入人工复核或自动下线流程。这样,技能库就不再是静态的文档集合,而是一个持续进化的工程资产。
如果你正在做 Agent 编码能力的评测,或者也在为 Agent 设计 Web 开发技能,欢迎把这套评测思路拿去改造。先从小任务跑通闭环,再逐步扩大任务规模,最后形成适合自己团队场景的评测体系。过程中遇到任何坑,欢迎留言交流。