Lab

Agent API Lab

这套实验用于观察“大模型请求、模型决策、工具执行、结果回传、下一轮请求”之间的协议关系。默认使用确定性的 FakeProvider,不联网、不需要 API Key,也不会因为模型版本变化而让测试随机失败。

这里的数据结构是跨厂商的教学模型,不是某一家 API 的完整 Schema。OpenAI Responses API、OpenAI-compatible Chat Completions、Anthropic Messages API 和 Gemini API 会使用不同字段名;共同不变量是:模型提出工具调用,Harness 执行工具,并把结果与对应调用建立因果关联。

快速运行

python examples/agent-api-lab/run_lab.py
python examples/agent-api-lab/run_lab.py --scenario invalid_args
python examples/agent-api-lab/run_lab.py --scenario parallel --all-ablations
python examples/agent-api-lab/run_lab.py --transient-failures 1
python examples/agent-api-lab/run_lab.py --fault timeout --fault 5xx

需要查看逐轮协议时,可以输出经过尽力脱敏的 JSONL trace:

python examples/agent-api-lab/run_lab.py `
  --scenario parallel `
  --trace examples/agent-api-lab/artifacts/parallel.jsonl

场景矩阵

场景 观察重点
text 普通文本响应不会误入工具循环
single 一次工具请求和结果回传
parallel 同一轮多个调用如何用 ID 分别关联
parallel_partial_failure 并行调用部分失败时保留成功结果
invalid_args 参数校验失败如何作为结果进入下一轮,并由模型修正
tool_failure 工具失败时不伪造结果
repeat 相同动作重复出现时由 Loop Guard 终止
refusal 内容拒绝不能被误报为正常完成
truncated 输出截断必须进入恢复或失败分支
duplicate_ids 同一批次的重复调用 ID 会在工具执行前被拒绝
truncated_tool_call 带工具请求的截断响应不会产生工具副作用

上下文消融

--all-ablations 对同一任务改变一个变量:

  • complete:完整结构化轨迹,作为基线。
  • drop_assistant_call:删除模型先前提出的工具请求。
  • mismatch_call_id:让工具结果指向不存在的调用。
  • flatten_roles:把所有角色和结构拍平成一段用户文本。
  • sliding_window:机械保留最末消息,切断用户目标与工具结果的因果链。

实验输出包含状态、迭代次数、模型调用次数、工具调用次数和估算输入量。这里的 input_units 只是稳定的本地比较量,不冒充供应商账单 token。真实缓存命中、TTFT、token 和费用只能使用供应商实际返回的指标。

流式响应为什么需要状态机

StreamAssembler 演示两条规则:文本增量可以边到边显示,工具参数则必须等完整 JSON 和完成事件后才能执行。半截流、缺少完成事件或参数 JSON 不完整都会被判为协议错误。

不要把供应商内部推理或原始思维链当作稳定业务接口。生产系统应记录公开输出、工具调用、工具结果、停止原因和供应商允许保存的 reasoning summary,而不是依赖不可移植的私有推理文本。

测试

python -m unittest discover -s examples/agent-api-lab/tests -v

测试覆盖普通文本、正常单工具、并行工具、参数修正、重复动作熔断、限流/超时/5xx 重试、拒绝与截断、无效模型响应、四种上下文破坏、流式参数组装和日志脱敏。

脱敏只能作为纵深防御,不能证明任意自由文本中都没有秘密。生产系统不应把 API Key、Cookie、Authorization Header 或用户敏感数据放进模型消息和工具自由文本;trace 还应配合字段白名单、访问控制和保留期限。

真实 API 适配

实验故意不绑定真实供应商。接入真实 API 时,应在适配器中把供应商的 response items、content blocks 或 candidates 转成这里的 ModelTurn,再把 Message 轨迹映射回供应商请求格式。这样协议测试仍然稳定,供应商差异集中在适配层。