在过去几个月里,我们已经陆续发布了需求分析、测试点生成、测试用例评审等多个智能体。这些智能体在实际使用中效果不错,但逐渐暴露出一些问题:
-
智能体之间无法复用能力:每个智能体都要重新实现类似的需求解析、文档读取逻辑 -
中间结果无法持久化:生成的测试点、用例都在对话上下文里,无法版本管理和持续优化 -
缺乏标准化流程:不同智能体处理同一类任务的方式不一致,维护成本高
这次我们引入了Skills模式,重新设计了测试用例智能体。核心改进有三个:
-
Skills模式:把专业能力封装成可复用的技能模块,像乐高积木一样灵活组合 -
文件系统:所有中间产物都持久化到文件,可追溯、可迭代优化 -
中间件机制:统一处理缓存、权限、日志等横切关注点
最重要的是,基于文件系统后,测试用例可以持续迭代优化——第一次生成后,可以基于评审反馈不断改进,而不是每次重新生成。
今天就来聊聊这个基于Skills架构的测试用例智能体是怎么设计的。
一、为什么要用Skills架构?
传统的AI助手都是"大而全"的设计:一个超级大模型,配上几十个工具函数,然后让它自己判断该用哪个工具。这种方式有个致命缺陷:AI不知道在什么场景下该做什么。
举个例子,当你让它"分析这个需求文档并生成测试用例"时,AI可能会:
-
直接开始写测试用例(漏掉需求分析) -
一次性把所有内容塞到一个超长文件里(不便于后续使用) -
反复获取同一个需求文档(浪费API调用)
这就像让一个实习生直接上手复杂项目,没有章法,全凭感觉。
Skills架构的核心思想是:把专业知识封装成独立的技能模块,每个技能包含特定领域的最佳实践。就像给AI配了一套"标准作业指导书"。
在我们的测试用例设计智能体中,定义了5个核心技能:
1. requirements-analysis 需求分析技能
2. test-point-design 测试点设计技能
3. test-case-writing 测试用例编写技能
4. test-case-review 测试用例评审技能
5. test-case-export 测试用例导出技能
每个技能都是独立的,可以单独使用,也可以组合使用。就像乐高积木,灵活可组合。
二、技能是如何设计的?
以"测试点设计技能"为例,看看一个技能到底包含什么。
每个技能目录下有三个核心文件:
testcase-skills/test-point-design/
├── SKILL.md # 技能说明文档(给AI看的)
├── tools.py # 工具函数实现
└── prompts.py # 领域专家提示词
1. SKILL.md:AI的使用手册
这个文件告诉AI:"这个技能是干什么的,怎么用,什么时候用"。
# 测试点设计技能
## 核心功能
从需求文档中提取关键测试点,覆盖正常、边界、异常场景。
## 使用场景
当用户提供需求URL或需求文本,需要设计测试点清单时使用。
## 工作流程
1. 调用 analyze_requirements_from_input() 获取需求内容
2. 分析需求,识别功能模块、业务规则、数据流转
3. 设计测试点清单(正常/边界/异常场景)
4. 保存 requirements.md 和 test_points.md 两个文件
注意最后一步:保存两个文件。这是我们精心设计的细节。为什么要保存requirements.md?因为后续的"测试用例编写技能"需要参考需求文档,如果不保存,AI就会重复获取,浪费token。
2. tools.py:封装领域工具
在测试点设计技能中,我们封装了一个核心工具:
def analyze_requirements_from_input(url_or_text: str):
"""
从URL或文本中获取需求文档
支持:
- 语雀文档URL
- Markdown格式文本
- 纯文本
"""
# 判断是URL还是文本
if url_or_text.startswith('http'):
# 调用文档解析服务获取内容
content = fetch_document(url_or_text)
else:
content = url_or_text
return {
"content": content,
"source_type": "url" if url_or_text.startswith('http') else "text"
}
这个工具看起来很简单,但它封装了一个重要的业务逻辑:自动识别输入类型。用户不需要告诉AI"这是个URL"还是"这是文本",AI也不需要判断,工具自己搞定。
3. prompts.py:领域专家知识
这个文件定义了一个"虚拟的测试专家",指导AI如何思考。
TEST_POINT_DESIGN_EXPERT_PROMPT = """
你是一位资深测试工程师,擅长从需求中提取测试点。
测试点设计原则:
1. 功能覆盖:每个功能点都要有对应测试点
2. 场景分类:正常场景、边界场景、异常场景
3. 数据覆盖:有效数据、无效数据、边界数据
4. 交互覆盖:UI交互、接口调用、数据库操作
测试点格式:
- 功能模块
- 正常场景
- [测试点] 描述
- 边界场景
- [测试点] 描述
- 异常场景
- [测试点] 描述
"""
这个提示词不是简单地告诉AI"请生成测试点",而是提供了一套完整的测试方法论。AI会按照这个思路去分析需求,而不是想到哪写到哪。
三、文件系统:智能体的记忆
人类测试工程师在设计测试用例时,会创建很多文档:需求分析文档、测试点清单、测试用例文档。这些文档不是一次性的,而是会反复查阅、修改。
AI也需要这样的"工作目录"。我们给智能体配置了一个文件系统,支持:
-
写入文件(write_file) -
读取文件(read_file) -
编辑文件(edit_file) -
查看目录(ls) -
版本控制(undo_file_change、view_file_checkpoints)
特别是版本控制功能,这是对标Claude Code的设计。每次修改文件时,自动创建一个检查点(checkpoint),支持回退到任意历史版本。
filesystem_backend = CheckpointFilesystemBackend(
default_root_dir=files_dir,
virtual_mode=True,
checkpoint_retention_days=30, # 保留30天
max_checkpoints_per_file=50 # 每个文件最多50个检查点
)
更关键的是,我们实现了"动态工作空间"机制。每个用户、每个会话都有独立的工作目录:
workspace/
├── user_123/
│ ├── thread_001/
│ │ ├── requirements.md
│ │ ├── test_points.md
│ │ └── test_cases.md
│ └── thread_002/
└── user_456/
这样,多个用户同时使用智能体时,文件不会互相干扰。
四、中间件:智能体的能力增强器
如果说Skills是智能体的"专业技能",那中间件就是它的"通用能力"。我们为智能体配置了一套完整的中间件栈:
1. 动态工作空间中间件
这个中间件负责根据会话ID自动切换工作目录。用户发起对话时,携带thread_id,中间件自动创建或切换到对应的工作空间。
create_dynamic_workspace_middleware(
agent_type="test_case_design_deep_agent"
)
2. 上下文注入中间件
AI有个问题:它看不到"全局"。比如用户说"继续完善测试用例",AI可能不记得之前做了什么。
上下文注入中间件解决这个问题:自动提取关键信息(用户意图、工具调用结果),注入到每次AI调用中。
context_middleware = ContextInjectionMiddleware(
extractors=[
UserIntentExtractor(), # 提取用户原始意图
ToolResultExtractor(
tool_patterns=[
"analyze_requirements_from_input", # 需求分析结果
"write_file", # 文件写入记录
"read_file", # 文件读取记录
]
),
],
injector=PrependContextInjector(),
max_context_tokens=5000,
)
这样,AI就能"记住"之前的操作,做出更连贯的决策。
3. LLM监控中间件
AI调用是有成本的,我们需要防止它"失控"。LLM监控中间件提供了多层保护:
LLMMonitoringMiddleware(
max_calls=50, # 单次对话最多50次模型调用
max_messages=100, # 消息历史最多100条
max_context_messages=30, # 传给模型的消息最多30条
token_warning_threshold=30000, # Token超过3万时警告
token_critical_threshold=50000, # Token超过5万时中断
enable_message_truncation=True, # 自动删除过旧的消息
)
同时,它还会实时监控Token消耗、响应时间等指标,方便我们优化。
五、标准工作流程:像人类一样工作
有了Skills、文件系统、中间件,我们就可以定义一个标准的测试用例设计流程:
1. 需求分析
加载 requirements-analysis 技能
→ 调用 analyze_requirements_from_input(url_or_text)
→ 分析需求,识别功能点、业务规则、约束条件
→ 保存分析结果到 requirements.md
2. 测试点设计
加载 test-point-design 技能
→ 读取 requirements.md(已保存,无需重复获取)
→ 设计测试点清单(正常/边界/异常场景)
→ 保存到 test_points.md
3. 测试用例编写
加载 test-case-writing 技能
→ 读取 test_points.md 和 requirements.md
→ 为每个测试点编写详细用例
→ 保存到 test_cases.md
4. 测试用例评审
加载 test-case-review 技能
→ 读取 test_cases.md 和 requirements.md
→ 检查覆盖率、用例质量、步骤完整性
→ 输出评审报告和优化建议
5. 文档导出
加载 test-case-export 技能
→ 调用 export_test_cases_to_files()
→ 生成 XMind 脑图和 Excel 表格
→ 返回下载链接
注意每个步骤之间的文件传递:测试点设计阶段保存requirements.md,后续直接读取,避免重复获取。这是通过Skills之间的"协议"来实现的。
六、实际效果如何?
我们用一个真实需求测试了这个智能体。需求是"用户登录功能,支持手机号和邮箱登录,需要短信验证码验证"。
智能体的执行过程:
-
加载需求分析技能,识别出4个功能模块、12条业务规则 -
加载测试点设计技能,生成32个测试点(正常18个、边界8个、异常6个) -
加载测试用例编写技能,编写了32条详细测试用例 -
加载测试用例评审技能,发现3个遗漏场景,补充后达到40条用例 -
加载导出技能,生成XMind和Excel文件
整个过程耗时约2分钟,生成的测试用例质量达到了初级测试工程师的水平。更重要的是,流程是标准化的,每次都能保证基本的覆盖率。
七、设计心得
几点关键经验:
1. Skills单一职责:每个Skill只做一件事,避免"超级Skill"。
2. 文件系统让AI有记忆:持久化中间结果,才能持续优化,而不是每次从头开始。
3. 中间件统一处理横切关注点:监控、限流、缓存等通用功能,不要在每个Skill里重复实现。
4. 提示词是核心:好的领域知识和方法论,能让通用模型表现出专家水平。
结语
做AI应用最大的挑战不是技术,而是如何让AI"专业"。Skills架构提供了一种思路:把专业知识封装成技能模块,让AI像人类专家一样工作。
如果你也在做类似的AI应用,不妨试试Skills架构。也许会给你带来一些新的启发。

