项目实践笔记13:多用户事实碎片 Agent 的接口测试与约束设计
本文记录项目一在迭代二阶段的工程化演进过程:从单用户脚本升级为支持多用户的 HTTP API 服务。本轮迭代重点不在功能扩展,而在接口 contract 稳定性、模型不可控行为的工程约束,以及测试视角下的可回归设计。通过引入 author 隔离、最小事实输入门槛与统一响应结构,解决了模型误判、低质量碎片写入与测试不可复现等问题,并给出了对应的接口测试用例与验证结论。
前言:
前面项目一只实现了迭代一,还有迭代二和迭代三,现在先实现迭代二。
项目一在 迭代二阶段,从“单人本地脚本”升级为“多用户 + HTTP API + 可回归测试”的过程,重点放在 接口行为约束、模型不可控问题的工程化兜底,以及测试视角的验证方法。
一、做迭代二的原因
在迭代一中,项目已经实现了:
-
基于 LLM 的事实碎片记录
-
本地 JSONL 持久化
-
简单的“查询 / 打卡 / 拒绝”能力
但在使用和测试过程中,会有这些问题:
1、单用户假设不成立
-
所有碎片默认属于同一个人
-
无法支持多人同时记录、查询
2、交互不可测试
-
CLI 形式不利于接口回归
-
无法做系统化测试用例
3、模型行为不稳定
-
同样的输入,有时 record,有时 reject
-
低质量输入(如“做了啥”)会被错误写入数据
迭代二的目标不是“加功能”,而是“让系统可控、可测、可解释”。
2.1 引入 HTTP API(工程入口)
新增:
POST /api/input
统一所有行为入口:
-
记录事实
-
查询今日碎片
-
打卡确认
-
拒绝无效请求
为后续 接口测试 / 自动化 / 回归 打基础。
2.2 引入 author 字段(多用户隔离)
所有请求 author 必填:
{
"text": "今天完成了WMS用例执行",
"author": "张三"
}
数据层变化:
-
fragments.jsonl 中新增
author -
所有查询默认 按 author 过滤
-
特殊值
author=all才允许全量查询
这是典型的权限/隔离设计,也是后续测试的重点。
2.3 统一返回 contract(测试关键)
所有 API 响应统一结构:
{
"ok": true,
"action": "record | query | confirm | reject",
"tool_called": "record_fragment | get_fragments_by_date | confirm_clock_event | null",
"today_fragments": [],
"input_text": "原始输入"
}
设计原则:
-
reject / confirm 必须返回空数组
-
前端 / 测试代码 不需要猜行为
-
行为通过
action + tool_called判断
目的:“为了测试而设计接口”的特征。
三、关键问题解决方案
问题 1:模型会把“做了啥”当成记录
现象
{
"text": "做了啥",
"author": "11"
}
模型早期会返回:
action=record
导致大量低质量碎片污染数据。
解决策略(非纯 prompt)
-
在 input 层增加最小事实门槛
-
疑问句(做了啥 / 干了什么)→ 强制 query
-
只有“事实 + 动作”才允许 record
目的:不是“更聪明的模型”,而是“更严格的入口约束”
问题 2:confirm / reject 行为污染返回结果
现象
-
confirm 返回历史碎片
-
reject 偶尔返回残留数据
解决方案
在主流程中明确兜底:
if action in (confirm, reject): today_fragments = []
这是 contract 稳定性问题,须用代码兜底,而不是指望模型。
四、接口测试用例设计(核心)
TC-01:author 必填校验
输入:
{ "text": "今天完成了测试" }
预期:
-
HTTP 400
-
error = missing author field
TC-02:事实记录
输入:
{ "text": "今天完成了WMS用例执行", "author": "张三" }
预期:
-
action = record
-
tool_called = record_fragment
-
today_fragments 只包含张三
TC-03:作者隔离查询
输入:
{ "text": "做了啥", "author": "李四" }
预期:
-
action = query
-
today_fragments = []
TC-04:全量查询(all)
输入:
{ "text": "做了啥", "author": "all" }
预期:
-
返回所有 author 的今日碎片
TC-05:reject 行为
输入:
{ "text": "帮我写个日报", "author": "张三" }
预期:
-
action = reject
-
tool_called = null
-
today_fragments = []
TC-06:confirm 行为
输入:
{ "text": "帮我打卡", "author": "张三" }
预期:
-
action = confirm
-
tool_called = confirm_clock_event
-
today_fragments = []
五、迭代二总结
解决三个问题:
-
模型不稳定 → 接口可控
-
多人混用 → 明确隔离
-
无法测试 → 明确 contract + 用例
下一步可以做:
-
自动化接口回归(pytest / requests)
-
历史数据清洗策略
-
打卡规则的异常场景测试(超时 / 重复)
项目代码
本文对应代码为 项目一 · 迭代二最终封板版本:
https://github.com/test202005/project1/releases/tag/iter2-final
说明:
- main 分支保留迭代一作为稳定基线
- iter2-final 为多用户 + API 化后的工程增强版本(接口与行为已封板)
更多推荐



所有评论(0)