认知减负过滤台: * 鼠标悬停卡片,翻转查看“Why”与“设计巧妙之处”

0. 理论支点:Harness Engineering

评估 Agent 的对象不能是模型单体,而必须是 "Model + Harness"(模型+安全带/外挂系统)。 基于 npm claude-code-2.1.88.tgz 逆向分析。 真正的难点不在模型的单步推理,而在 Durable state (持久化状态)、Tool mediation (工具中介)、Feedback loops (反馈循环) 等外层治理。

支撑系统运转的「四大不变量」 (Invariants)

🔗

轨迹拓扑不能破

Trajectory Stability

Why & 巧妙设计

  • Why 如果 API 消息格式不合法(如缺少 tool_result),后续循环直接崩溃。
  • 巧妙设计 Synthetic Error 补全:即使发生异常,系统也会伪造一个 tool_result 塞回消息流,确保闭环不断,防止 SDK 暴露于半成品状态。
  • Thinking block 保护:在错误边界截断时,宁可保留整个思维块,也不随意裁剪破坏结构。
🧊

缓存前缀不能漂

Prompt Cache Freeze

Why & 巧妙设计

  • Why Context Token 非常贵,打断缓存会导致 API 延迟和成本非线性飙升。
  • 巧妙设计 Fate Frozen:一旦模型“看到”了某段内容,它的字节串命运就被完全冻结。
  • 系统强行规定工具必须按名称排序,确保内置工具永远作为稳定前缀,以最大化命中 Cache。
🚪

能力面延迟敞开

Deferred Capability

Why & 巧妙设计

  • Why 一次性加载所有能力(如数百个MCP工具),会引爆 Token 并让模型分心产生幻觉。
  • 巧妙设计 按需展开 (ToolSearch):初期只告诉模型“有这个工具的名字”,不加载 Schema 参数
  • 明确提示模型:“只有获取后才能调用”。这是一种极具工程成熟度的能力暴露语义。
💾

连续性多态外化

Polymorphic Continuity

Why & 巧妙设计

  • Why 仅靠 Messages 数组(Transcript)无法承载长时间工作,会爆掉窗口。
  • 巧妙设计 分离工件
    - Daily logs: 高频原始追加。
    - MEMORY.md: 低频蒸馏的“大纲”。
    - Session memory: 记录“工作卡断点”用于恢复。

1. 宿主与主循环 (Host & God Loop)

QueryEngine 不仅转发 prompt,更是会话宿主;query.ts 则是维持轨迹合法性的“状态机图”。 主流程的核心不是“提问并解析 JSON”,而是“不断修正和修补同一条对话轨迹”。
📥

落盘优先原则

Transcript Persistence

Why & 巧妙设计

  • Why 若等待模型返回再记录,一旦断网或崩溃,用户的输入和上下文就彻底丢失了。
  • 巧妙设计 BEFORE entering query loop:用户消息一旦接受,哪怕 API 还没请求,先落盘 Transcript。确保随时可进入“可恢复轨迹”。
🧩

合成工具 (Structured Output)

Synthetic Tool

Why & 巧妙设计

  • Why 直接让模型输出 JSON 往往需要事后解析并处理报错,流程易碎。
  • 巧妙设计 宿主把外部 JSON Schema 即时编译成一个一次性的合成工具 (Synthetic Tool)
  • “输出必须满足Schema” 这一约束被前移到了工具执行期,利用 AJV 校验,不合法直接触发 Tool Error 让模型自行重试。
🩺

错误分流即轨迹保护

Recovery Loop

Why & 巧妙设计

  • Why Agent 会遇到各类越界(Token过多、图片太大),简单抛错会导致应用死锁。
  • 巧妙设计 两级恢复机制
    Prompt 过长:先尝试保留结构的 Context collapse,失败再走破坏性的全局 Reactive compact。
    这不是异常处理,这是上下文精细调度。

2. 提示词与系统指令栈 (System Prompts)

System prompt 不是一段静态文案,而是控制 Agent 行为的“第一控制面 (Runtime Law)”。 引入了独立的 Memory Selector、Auto Mode Classifier 等“专用 Prompt Worker”辅助主模型。
🚧

缓存切分边界

Cache-Break Architecture

Why & 巧妙设计

  • Why 混合静态系统指令和动态运行时状态(如当前连接的 MCP),会导致巨大的 Prompt 缓存失效。
  • 巧妙设计 DANGEROUS_uncachedSystemPromptSection:显式拆分结构。
  • 系统强制规定,只有真正跨 turn 漂移的、无法作为附件的内容才允许放入动态区,以此死守静态前缀的缓存命中率。
⚖️

纠偏模型天性法则

Behavior Prompting

Why & 巧妙设计

  • Why LLM 天生喜欢“编造抽象”、“未看先改”、“打包返回半成品”。
  • 巧妙设计 Prompt 中预置了硬核纠偏:
    1. "没读过的代码不准改"
    2. "不要写一次性的 Helper 函数"
    3. "如果有专有工具,不要直接用 Bash"
    这些并非“文笔好”,而是把工程偏差补丁灌入了模型世界观。
📨

第二指令通道

Attachments / Reminders

Why & 巧妙设计

  • Why 如果把所有当前任务相关的约束都写进系统 Prompt,它将变得无比臃肿且难以管理。
  • 巧妙设计 Context Router (attachments.ts)
  • 将短期的强提示(如 critical_system_reminder)包装为 User Meta Message 或 Attachment 注入当前 Turn。实现了法则(长期)与约束(临时)的完美解耦。

3. 能力、工具与策略 (Capabilities & Tools)

ToolUseContext 过于庞大,甚至成了跨界访问宿主状态的万能胶。 权限系统被设计成独立的 Policy Control Plane,支持替换同步 (Replacement Sync)。
🚦

执行与并发控制

Execution Pipeline

Why & 巧妙设计

  • Why 简单地并发执行所有工具会导致严重的状态竞争(比如多工具同时修改文件上下文)。
  • 巧妙设计 读并发,写串行
  • 只读工具(如查询)可以并发收集结果。
  • 但上下文的副作用 (Context Modifiers) 必须按模型调用工具的原顺序严格排队提交,避免后续状态被乱序污染。
🎭

能力的虚拟与隐藏

REPL Virtualization

Why & 巧妙设计

  • Why 基元工具(Bash, Read, Edit, Glob)如果全部平铺,会大幅增加模型的决策成本,也破坏前缀稳定。
  • 巧妙设计 REPL 虚拟层:将海量小工具收束为一个统一的 REPL 虚拟入口。
  • 模型表面只看得到一个入口,但在内层(VM Context)原始能力依然可用,权限系统照样细粒度拦截。
🧠

降维旁路召回

Side Query (Memory)

Why & 巧妙设计

  • Why 让昂贵的主模型 (如 Sonnet) 直接阅读庞大的历史文档并挑选记忆,极其浪费。
  • 巧妙设计 小模型相关性过滤
  • 不使用 RAG 向量检索,而是发起一个 sideQuery
  • 将文档 Manifest (只带头信息不带正文) 喂给辅助模型判断相关性。再通过 readFileState 拦截,避免把刚看过的文件又当成“记忆”注入。

4. 连续性、缓存与恢复 (Continuity & Cache)

这套系统没有单一的 "Memory" 模块,连续性被拆解为指令、能力、语义、操作四大维度。 工具返回结果被替换后,会存入 Exact String 以维持后续重放时字节级一致。
🛡️

部分视图保护

Partial View Guard

Why & 巧妙设计

  • Why 为了省 Token,记忆注入往往会裁掉大文件尾部或头信息。如果模型以为这就是“全量文件”并用 Write 工具覆写,就会破坏代码。
  • 巧妙设计 Raw/Diff 拦截机制
  • 当注入内容与磁盘不一致时,将其标记为 isPartialView
  • 模型试图修改时,系统拦截并强迫其进行真实的 Read 全量操作,这是极具生产价值的一致性防线。
🪢

因果链与逆向回溯

Causality Recovery

Why & 巧妙设计

  • Why 大文件的 JSONL 日志解析极慢,且包含大量 progress 冗余帧。
  • 巧妙设计 Serialization Invariant
  • 源码死定 parentUuid 必须是 JSON 序列化后的第一个键 (First Key)。
  • 恢复时无需完整解析 JSON 结构,仅靠前缀扫描和 parentUuid 链表逆向回溯,即可快速重建剔除无效节点的“对话因果链”。
❄️

精确字符串替换

Exact String Replace

Why & 巧妙设计

  • Why 如果仅保存重试状态,一旦 SDK UI 模板、换行格式更新,重建的 Prompt 就会与之前请求 API 时的完全不一致,导致缓存断裂。
  • 巧妙设计 命运冻结
  • 直接将替换后的 Exact String 原样落盘。后续任何会话恢复,不重新计算格式,原封不动贴回。确保 Wire Prefix (网络层前缀) 绝对稳定。

5. 任务底座与远程执行 (Task Substrate)

Task 框架根本不是 UI 层面的附属品,它是支撑异步 Agent 的底层执行底座 (Substrate)。 Teammate 之间的通信必须依赖 SendMessage 工具 (RPC 调用),而非共享文本流。
📪

邮箱排水机制

Actor Mailbox Drain

Why & 巧妙设计

  • Why 若其他 Agent (Teammate) 的消息随时注入,会打断当前主模型正在进行的连续思考和工具调用,导致上下文错乱。
  • 巧妙设计 Tool-Round Boundary
  • 引入 Actor Mailbox,消息先进入 pendingMessages 队列。
  • 系统只在“上一轮工具执行完毕,下一轮即将开始”的边界时刻进行 Drain (排水注入)。牺牲即时性,换取推理轨迹安全。
🌿

缓存友好的分叉

Cache-Safe Fork

Why & 巧妙设计

  • Why 创建 Subagent (子代理) 时,如果重新拼接 Prompt,相当于完全浪费了父进程累积的上下文缓存。
  • 巧妙设计 Placeholder Padding
  • 完整拷贝父线程的 Assistant 消息和工具调用,用统一的占位符 (Placeholder) 补齐未完成的 Tool Result。
  • 只让最后一段 Directive (指令) 发生变化,最大化利用共享的 Prompt Cache 树干。
☁️

跨端会话追踪

Remote Agent Poller

Why & 巧妙设计

  • Why 远程任务可能会因为网络波动断开,如果简单认定为失败,会导致昂贵的远程运行丢失。
  • 巧妙设计 精细错误辨析
  • 组合本地 Task Registry + 远端 Session Handle。
  • 恢复时区分 `404 Not Found` (真丢了,需归档) 和网络/认证错误 (可能还活着,保留重连机制)。扩展了 Durable Execution 的边界。

6. 结构债与下一代工程化建议 (Debts & Advice)

最亮眼的实现往往首先是“疤痕”,证明系统的边界曾被突破。过度依赖 Vibe Coding 最终会催生庞大的 God Loop。

为什么要强烈建议引入 XState (显式状态机)?

核心痛点 在 Claude Code 中,由于长期采用 "Vibe Coding"(凭感觉打补丁快速迭代),控制流散落在各种布尔变量中 (如 stopHookActive, hasAttemptedReactiveCompact, pendingToolUseSummary)。

后果 导致 query.ts 变成了一个庞大且脆弱的 God Loop。出现 progressBridge, orphaned permission replay 等极其精巧但也极其危险的“幽灵补丁”。局部问题修了,全局所有权 (Ownership) 却丢失了。


架构升级 从隐式补丁走向显式状态流转图:

  • 利用 XState,将 Agent 复杂的流转 (如:申请权限分类预检等待用户重放工具调用) 定义为严格的数学状态。
  • 它消除所有的“中间非法状态”,当请求被拒绝或中断时,系统只能沿着合法的图边退回,无需手工编写繁琐的重置逻辑。
  • 结论:生产级 Agent 的下一代形态,必须从“一团提示词和胶水代码 (Middleware)”,进化为“显式状态机驱动的执行引擎 (Runtime)”。
🔭

引入可观测性

Observability Plane
  • 代码中 queryProfiler 会详尽统计 Context 装配、API往返、工具执行各自的耗时。
  • 诊断 Cache Break (前缀变动、工具增减)。
  • 没有可观测性,就没有可演化的 Harness。
🚫

万能胶陷阱

Context Bloat
  • ToolUseContext 当前过胖,工具能轻易越权修改宿主系统。
  • 建议明确分离只读查询、事件提交、状态所有权。
  • 不要让所有子系统都能直接 Mutate 同一片共享内存。

💬 关键金句与引言萃取

The rules of thinking are lengthy and fortuitous... Thinking blocks must be preserved for the duration of an assistant trajectory.

— 源码中关于 Thinking block 的神圣约束。

解读:模型思考过程不是富文本,它是 Agent 认知拓扑的一部分,切断它等同于破坏其短期智力。
Do NOT use the Bash tool when a relevant dedicated tool is provided... You can call multiple tools in a single response. If there are no dependencies between them, make all independent tool calls in parallel.

— 工具并行的 System Prompt 法则。

解读:高阶并发语义并非仅靠代码调度,必须首先植入模型的世界观中,实现“知行合一”。
Until fetched, only the name is known — there is no parameter schema, so the tool cannot be invoked.

— ToolSearch 工具的坦白局提示词。

解读:非常直白地向 LLM 声明“延迟加载工具”的半激活状态,防止模型产生“以为自己能用”的幻觉。
Just writing a response in text is not visible to others on your team - you MUST use the SendMessage tool.

— Teammate 协作的 Actor 模型规约。

解读:用 Prompt 强制将纯文本对话扭转为显式的 RPC 协议调用,这是实现 Swarm (群体智能) 的关键门槛。