19 KiB
| title | type | date | origin |
|---|---|---|---|
| feat: Agent Wave 1 快速补强 (verify 回灌/prompt cache/schema 校验/delta_flush) | feat | 2026-06-29 | docs/brainstorms/2026-06-29-advanced-agent-gap-optimization-requirements.md |
Summary
落地 brainstorm Wave 1 的 4 项自包含快速补强:G1 verify 失败回灌 ReAct、G2 prompt cache 三层结构跨 provider、G3 工具调用 schema 校验、G8 delta_flush_interval 调速。四项均作用于 ReAct 引擎层,同 plan 内 G2→G8 顺序执行(共享 execute_stream 改动),每项附最小自检测试。
Problem Frame
agentkit 对比 Qoder/Codex/Hermes/Trae 后发现 9 个真新缺口(已在生产/测试观察到痛点),brainstorm 分 3 波交付。本 plan 实现 Wave 1——自包含、低风险的 4 项快速补强,覆盖反馈稳定性(verify 不回灌、工具无 schema 校验)与响应效率(prompt cache 命中率低、token chunk 无节流)。
验证器已核对仓库现状(见 origin Sources & Research):verification_loop.py:111-145 verify 失败仅调 fix_callback 不回灌 ReAct;react.py:1042-1059 记忆注入拼到 system prompt 末尾破坏 cache 前缀;react.py:1118-1134 每个 token chunk 都 yield 无节流;tools/base.py:50-77 safe_execute 无 schema 校验直接 await execute()。
Requirements
G1 Verify 失败回灌 ReAct (origin R1-R3)
- R1. verify 失败时,系统自动把 errors 作为新 user 消息注入 conversation,继续 ReAct 循环,而非直接退出。
- R2. 回灌后若二次 verify 仍失败,系统中断执行并返回错误给用户,附 verify log。
- R3. 回灌最大重试次数可配置(默认 1 次),受
max_steps上限约束。
G2 Prompt Cache 三层结构 (origin R4-R7)
- R4. system prompt 重构为双块结构:stable(技能配置/系统指令)+volatile(记忆检索+时间戳)。原 context(会话上下文)层由 conversation messages 承载,不进 system prompt。
- R5. 记忆检索注入从 system prompt 末尾移到 volatile 层,stable 层保持不变。
- R6. 跨 provider 统一 cache 策略:Anthropic 显式插入
cache_control断点;OpenAI 等依赖自动前缀缓存。 - R7. 多轮对话输入 token 成本降低(目标 ~50%)。
G3 工具调用 Schema 校验 (origin R8-R10)
- R8.
safe_execute调用execute()前,基于tool.input_schema校验参数(类型/必填)。 - R9. 校验失败时返回类型化错误码(
tool_call_invalid/schema_mismatch),不执行工具。 - R10. 错误以 tool 角色消息回灌 conversation,给 LLM 自我修正机会。
G8 delta_flush_interval 调速 (origin R11-R12)
- R11.
execute_stream的 token chunk yield 加可配置节流(默认flush_interval_ms)。 - R12. 节流配置化,允许客户端调高降低渲染开销。
Cross-cutting (origin R26-R27)
- R13. 所有优化项配置化(
agentkit.yaml新增对应配置节)。 - R14. 每个优化项附最小自检测试(ponytail 规则)。
Key Technical Decisions
KTD1:G3 schema 校验放在 Tool.safe_execute(base.py),而非 _execute_tool(react.py)
校验在工具基类层,所有调用方(ReActEngine、ExpertTeam、StandaloneAgent)统一受益。以 tool.input_schema(JSON Schema dict)为契约源,input_schema=None 时跳过校验保持向后兼容。用 jsonschema 库(已是 Python 生态标准,无新依赖)。
KTD2:G2 双块结构用 content blocks + cache_control 标记,Anthropic provider 需改 _convert_messages
system message 的 content 从字符串改为 content blocks 列表([{"type":"text","text":stable,"cache_control":{"type":"ephemeral"}},{"type":"text","text":volatile}])。注意:src/agentkit/llm/providers/anthropic.py 是 httpx 直连实现(非 LiteLLM),其 _convert_messages(:102-197)假设 system content 为字符串(:116),需修改以支持 list-type system content 并透传 cache_control blocks。OpenAI 等 provider 的 chat completions API 不支持 list-type system content,_build_system_message 需按 provider 能力检测:Anthropic 返回 blocks,其余返回字符串拼接(stable+volatile),依赖 stable 前缀命中自动前缀缓存。不改 gateway 方法签名。
KTD3:G1 verify 回灌包进 ReAct 主循环,而非外层 wrapper
verify 当前在循环外 final answer 后运行(react.py:887 execute / :1603 execute_stream)。回灌改为:检测到 final answer(无 tool_calls)→ 运行 verify → 失败则把 errors 作为 user 消息 append 到 conversation → continue 主循环(LLM 自纠正)→ 二次 final answer 再 verify → 仍失败则 break 带 verify log。保留现有 VerificationLoop 类与 verify_and_retry 方法不动(向后兼容),回灌逻辑在 ReActEngine 内。
KTD4:G8 delta_flush 用 time.monotonic 节流,非计数器
在 execute_stream chunk 循环内累积 chunks,按 flush_interval_ms 间隔批量 yield。flush_interval_ms=0 时退化为逐 chunk yield(向后兼容)。流结束 mid-interval 时最终 flush。用 time.monotonic()(不受系统时钟跳变影响)。
KTD5:G2→G8 同 plan 内顺序执行,共享 execute_stream 改动
G2 改 system prompt 构造(循环前),G8 改 chunk yield 逻辑(循环内),两者不冲突但都触 execute_stream。G2 先落地确保 stable 前缀结构稳定,G8 再加节流避免在未稳定结构上叠加。
KTD6:ServerConfig 到 ReActEngine 的接线用独立构造参数(带默认值)
ReActEngine.__init__(react.py:154-198)不接受 ServerConfig 对象,采用独立构造参数:prompt_cache_enable: bool = True、flush_interval_ms: int = 0、max_reinjections: int = 1(默认值保当前行为,向后兼容)。ServerConfig 在 agent 工厂/handler 层(chat/handler.py 等 ReActEngine 构造点)读取并传入。实现时需列出所有构造 ReActEngine 的调用点并更新。
Implementation Units
U1. G3 工具调用 Schema 校验
Goal: 在 Tool.safe_execute 调用 execute() 前校验参数,失败返回类型化错误。
Requirements: R8, R9, R10, R14
Dependencies: 无(独立,奠基性——定义错误回灌模式)
Files:
- 修改:
src/agentkit/tools/base.py(safe_execute加校验 +ToolValidationError) - 修改:
src/agentkit/core/react.py(_execute_tool:1897-1916捕获ToolValidationError并 append tool 角色消息) - 测试:
tests/unit/test_tool_schema_validation.py
Approach:
- 新增
ToolValidationError(Exception),带error_code(tool_call_invalid/schema_mismatch)与details。 safe_execute在before_execute后、execute前:若self.input_schema非 None,用jsonschema.validate(kwargs, self.input_schema);校验失败抛ToolValidationError。input_schema=None→ 跳过(向后兼容,旧工具无 schema)。_execute_tool(react.py:1897-1916)在现有except Exception之前加except ToolValidationError as e:优先捕获,返回{"error": str(e), "error_code": e.error_code, "details": e.details}(保留类型化错误码,不被通用 except 平坦化为字符串)。现有调用方_build_tool_result_message把返回 dict 转为 tool 角色消息 append 到 conversation,给 LLM 自纠正机会。
Patterns to follow: VerificationResult 的类型化错误模式(verification_loop.py:18-24);jsonschema 标准用法。
Test scenarios:
- Covers R8. Happy path: tool 有
input_schema={"type":"object","properties":{"count":{"type":"integer"}},"required":["count"]},传count=5→ 校验通过,execute 正常执行。 - Covers R9. Edge:
input_schema=None→ 跳过校验,execute 正常(向后兼容)。 - Covers R9. Error: 传
count="abc"(类型错)→ 抛ToolValidationError(error_code="tool_call_invalid"),execute 不调用。 - Covers R9. Error: 缺
count(必填)→ 抛ToolValidationError(error_code="schema_mismatch")。 - Covers R10. Integration:
_execute_tool捕获ToolValidationError→ conversation append tool 角色消息 → LLM 下一轮看到错误并修正参数 → 重试成功。
Verification: python3 -m pytest tests/unit/test_tool_schema_validation.py -x -q 通过;现有工具测试不回归。
U2. G2 Prompt Cache 双块结构
Goal: system prompt 重构为 stable/volatile 双块结构,记忆注入移到 volatile,加 cache_control 断点。
Requirements: R4, R5, R6, R7, R13, R14
Dependencies: 无(独立,与 U1 不触同代码区)
Files:
- 修改:
src/agentkit/core/react.py(execute_stream:1042-1059记忆注入 + system message 构造;execute 同路径若有,可选 — 见 Scope Boundaries) - 修改:
src/agentkit/llm/providers/anthropic.py(_convert_messages:102-197支持 list-type system content,透传 cache_control blocks) - 配置:
src/agentkit/config.py或ServerConfig(prompt_cache.enable: bool) - 测试:
tests/unit/test_prompt_cache_layers.py
Approach:
- 新增
_build_system_message(base_prompt, memory_context, enable_cache, provider)工具方法:Anthropic provider 返回 content blocks 列表,stable 块在前(带cache_control: {"type":"ephemeral"}),volatile 块(记忆+时间戳)在后;非 Anthropic provider 返回字符串拼接(stable+volatile),依赖 stable 前缀命中自动前缀缓存。 - execute_stream
:1042-1059:记忆注入从system_prompt += "## 参考信息"改为收集memory_context,传给_build_system_message。 - conversation 的 system 消息 content:Anthropic 用 blocks 列表,其余用字符串;gateway
chat_stream经**kwargs透传。 anthropic.py的_convert_messages(:102-197)需修改::116从system_prompt = content改为支持 list-type content 直接透传(payload["system"]接受字符串或 content blocks)。- 配置
prompt_cache.enable: bool(默认 True)。断点数硬编码为 1(stable 层),不暴露配置(YAGNI — 2 块结构下 >1 无语义)。 enable_cache=False或 provider 非 Anthropic → 退化为字符串拼接(向后兼容)。
Patterns to follow: LiteLLM/Anthropic cache_control content block 规范;现有 memory_retriever.get_context_string 调用不变。
Test scenarios:
- Covers R4, R5. Happy path: 多轮对话,stable 层(技能配置)跨轮不变,volatile 层(记忆)随 query 变 → system message content blocks 结构正确,stable 在前 volatile 在后。
- Covers R6. Integration: Anthropic provider 收到带
cache_control的 content blocks →_convert_messages透传 → cache 命中 stable 前缀。 - Covers R6. Edge: OpenAI provider(provider != anthropic)→
_build_system_message返回字符串拼接,不报错;stable 前缀命中自动前缀缓存。 - Covers R5. Edge:
memory_retriever返回空 → 无 volatile 块,system message 仅 stable。 - Covers R13. Config:
prompt_cache.enable=False→ 退化为字符串拼接,行为同改动前。
Verification: python3 -m pytest tests/unit/test_prompt_cache_layers.py -x -q 通过;多轮对话 system message 结构符合预期。
U3. G8 delta_flush_interval 调速
Goal: execute_stream token chunk yield 加时间节流。
Requirements: R11, R12, R13, R14
Dependencies: U2(共享 execute_stream,G2 先改 system prompt 结构,G8 后改 yield 逻辑)
Files:
- 修改:
src/agentkit/core/react.py(execute_streamchunk 循环:1118-1134;execute 同路径若有) - 配置:
ServerConfig(streaming.flush_interval_ms) - 测试:
tests/unit/test_delta_flush.py
Approach:
- chunk 循环内:累积
stream_content_chunks同时累积_flush_buffer;用time.monotonic()记_last_flush_ts。 - 当
now - _last_flush_ts >= flush_interval_ms/1000时:yield 合并后的 buffer,清空,更新 ts。 flush_interval_ms=0→ 逐 chunk yield(向后兼容,当前行为)。- 流结束(for 循环退出)→ 最终 flush 剩余 buffer。
Patterns to follow: time.monotonic() 用法(已在 :1080 _stream_start 使用);现有 ReActEvent(event_type="token") 结构不变。
Test scenarios:
- Covers R11. Happy path:
flush_interval_ms=50,模拟连续 chunks → 按 50ms 间隔批量 yield,合并 content。 - Covers R12. Config:
flush_interval_ms=0→ 逐 chunk yield(向后兼容)。 - Edge: 流结束 mid-interval → 最终 flush 剩余 buffer,不丢 content。
- Edge: 单个 chunk 后流结束 → 立即 flush。
- Covers R14. Self-check: 断言 yield 的合并 content 等于原始 chunks 拼接(不丢字符)。
Verification: python3 -m pytest tests/unit/test_delta_flush.py -x -q 通过;token 流无字符丢失。
U4. G1 Verify 失败回灌 ReAct
Goal: verify 失败时把 errors 注入 conversation 继续 ReAct,二次失败中断带 log。
Requirements: R1, R2, R3, R13, R14
Dependencies: U1(复用错误回灌模式;U1 的 ToolValidationError 回灌与 G1 verify 回灌同模式)
Files:
- 修改:
src/agentkit/core/react.py(execute:886-907verify 块;execute_stream:1601-1629verify 块) - 配置:
ServerConfig(verification.max_reinjections: int = 1) - 测试:
tests/unit/test_verify_reinjection.py
Approach:
- 把 verify 从"循环后一次性运行"改为"final answer 检测点 + 回灌重试"。
- 主循环内检测到 final answer(无 tool_calls)时:
if self._verification_enabled→ 运行 verify。 - verify 通过 →
break,正常结束。 - verify 失败且
reinjections < max_reinjections:append{"role":"user","content":f"验证失败,错误如下:\n{vresult.errors}"}到 conversation,continue主循环(LLM 见 errors 自纠正)。 - verify 失败且
reinjections >= max:记录 verify log 到 trajectory,break返回失败结果。 - 保留现有
VerificationLoop类与verify_and_retry不动(向后兼容,外部调用方仍可用)。
Patterns to follow: 现有 verify 块的 trajectory/event 记录模式;U1 的 ToolValidationError 回灌模式。
Execution note: 先加 characterization 测试覆盖现有 verify 行为(失败仅记录),再改实现确保不回归。
Test scenarios:
- Covers R1. Happy path: verify 首次失败 → errors 注入 conversation → LLM 自纠正 → 二次 verify 通过 → 任务完成。
- Covers R2. Error: verify 二次失败 → 中断,返回错误附 verify log(测试输出 + errors 列表)。
- Covers R3. Config:
max_reinjections=0→ 等价于不回灌(当前行为),verify 失败直接退出。 - Covers R3. Edge: 回灌期间达到
max_steps→ 中断(不无限循环)。 - Covers R1. Integration: 回灌的 user 消息出现在 conversation,LLM 下一轮 input 含 errors 文本。
- Covers R14. Self-check:
max_reinjections默认值为 1。
Verification: python3 -m pytest tests/unit/test_verify_reinjection.py -x -q 通过;pytest tests/unit/ -x -q 全量不回归。
Scope Boundaries
Deferred for later
- Wave 2(G4 辅助 LLM 分流 / G7 三级降级链 / G9 原子化 rollback)——见 origin Wave 2 section,单独 plan。
- Wave 3(G5 函数级代码分片 / G6 SOLO 状态机)——见 origin Wave 3 section,单独 plan。
- G7 Emergency 层规则模板、G5 tree-sitter 集成方式——origin Deferred to Planning。
Deferred to Follow-Up Work
execute()(非流式)的 G2/G8 改动:本 plan 优先execute_stream(WebSocket 主路径),execute()同步改动可顺带做但非必须,若拆 PR 则归 follow-up。- prompt cache 命中率指标化(R7 的 ~50% 目标):本 plan 落结构,埋点量化归 follow-up。
Outside this product's identity
- 重写编排逻辑/拓扑排序/Board 辩论——继承自 2026-06-24-004。
- 节点级 checkpoint——继承自 2026-06-24-004 KTD3。
- 全盘迁移 LangGraph——继承自 2026-06-24-004。
Risks & Dependencies
- 风险:G2 content blocks 改动破坏现有 message 序列化。 gateway/messages 假设
content: str,改为 blocks 列表需核对所有序列化路径(WebSocket、日志、trace)。缓解:仅 system 消息用 blocks,user/assistant 保持 str;enable_cache=False退化路径保底。 - 风险:G1 回灌增加 token 消耗。 二次 verify 循环会多跑一轮 LLM。缓解:
max_reinjections默认 1,受max_steps上限约束;KTD3 设计为循环内 continue 而非递归,无栈溢出风险。 - 依赖:U3 依赖 U2 完成。 两者共享
execute_stream,G2 先改 system prompt 结构稳定后再加 G8 节流(KTD5)。 - 依赖:G2 需修改
anthropic.py的_convert_messages支持 list-type system content。anthropic.py是 httpx 直连实现(非 LiteLLM),需手动改:116从system_prompt = content改为支持 content blocks 透传。非 Anthropic provider 走字符串拼接退化路径,不报错。 - 依赖:G3 的
jsonschema库。jsonschema>=4.0已在pyproject.toml核心依赖中(line 22),无需新增依赖。
Acceptance Examples
- AE1(Covers R1, R2, R3):ReAct 任务 final answer 后 verify 失败 → errors 注入 conversation 继续 ReAct → LLM 修正后二次 verify 通过 → 完成。若二次失败 → 中断返回错误附 verify log。
- AE2(Covers R4, R5, R6, R7):50 轮长对话 → stable 层不变,volatile 随 query 变 → Anthropic cache 命中 stable 前缀,OpenAI 命中自动前缀缓存 → 输入 token 降低。
- AE3(Covers R8, R9, R10):LLM 传错参数类型 → schema 校验失败 →
tool_call_invalid→ 错误回灌 conversation → LLM 修正后重试成功。 - AE4(Covers R11, R12):弱网客户端 → token chunk 按 50ms 批量 yield → 前端渲染无卡顿,无字符丢失。
Sources & Research
- Origin:
docs/brainstorms/2026-06-29-advanced-agent-gap-optimization-requirements.md— Wave 1 需求文档(KTD1-KTD7、R1-R27) - 上游 plan:
docs/plans/2026-06-24-004-feat-long-horizon-reliability-optimization-plan.md— U1-U7 长程可靠性护栏(本 plan 增补) - Learnings:
docs/solutions/logic-errors/long-horizon-reliability-code-review-fixes.md— 14 个 finding 教训(新字段默认值保契约、跨模块契约显式化、清理方法接入生命周期) - 代码 grounding(验证器核对):
src/agentkit/core/verification_loop.py:111-145—verify_and_retry接fix_callback,不回灌 ReActsrc/agentkit/core/react.py:1042-1059— 记忆注入拼到 system prompt 末尾src/agentkit/core/react.py:1118-1134— chunk 循环逐 token yield 无节流src/agentkit/core/react.py:886-907, 1601-1629— verify 在循环后运行,失败仅记录 trajectorysrc/agentkit/core/react.py:1897-1916—_execute_tool无 schema 校验src/agentkit/tools/base.py:21,28,50-77—Tool.input_schema(JSON Schema dict,可选),safe_execute无校验src/agentkit/llm/gateway.py:268-281—chat_stream(**kwargs)可透传 cache_controlsrc/agentkit/llm/providers/anthropic.py:316— Anthropic provider chat_stream
- 外部研究(brainstorm 阶段): Qoder(Spec→Verify 闭环、delta_flush_interval)、Hermes(cache_control system_and_3、validate_function_call_schema)、Codex(prompt caching 前缀匹配)