第 10 章 从一锅炖到模块化 · Agent架构实操十 开始测验

从「一锅炖」到「模块化」:重塑 Agent 的逻辑骨架

到第 9 章,system prompt 是一大段没人敢改的硬编码字符串——和把数据库连接串写死在业务逻辑里是同一类错误。本章:固定顺序、运行态取值,五个 section。
⏱ 约 12 分钟 🧩 5 个 section 💾 会话级缓存 +dynamic_prompt

🎯 学习目标

学完能答
  • 硬编码 system prompt 的三个痛点是什么?
  • 五个 section 的固定顺序?哪些始终有、哪些按需?
  • Context 为什么必须是严格 JSON?为什么不能用 default=str?
  • 缓存为什么必须属于会话(实例字段)而非模块全局?
  • 第 10 章为什么要把 MemorySession 的消息注入关掉?
  • 动态 Prompt 的缓存命中 = 供应商 API prompt cache 命中吗?

🧠 核心概念

点击展开。
1 · 三个痛点:硬编码 prompt 的问题
  1. 换项目要重写整个 prompt,不知道哪些该改:身份/行为规范可能复用,但工作目录/工具变了,边界完全不可见。
  2. 改一处悄悄影响全局:加段工具描述可能和行为规范语义冲突,LLM 怎么理解不可预测,不报错只变奇怪。
  3. 每次请求带全部内容但不是每次都需要:记忆只在选中相关记录时有意义,没选中保留占位说明只引入噪音。
2 · 解法:固定顺序,运行态取值
Section策略来源
identity始终基础行为指令 + 规范化 JSON context
tools始终ToolRegistry.names 当前快照
workspace始终已解析的 workspace 路径
skills按需SkillRegistry 有界目录(不含正文)
memory按需MemorySession 本轮选中记忆正文

顺序是契约:identity → tools → workspace → skills → memory。没工具时 tools 显示 (none);没 Skill/选中记忆时对应 section 整段省略。生效边界:tools 与 memory 在下一次模型请求就生效(每轮重取);workspace 是构建期解析的固定值;磁盘上装了新 Skill 也不会热加载——要重建 Agent 才可见。

3 · Context 必须是严格 JSON

Context 放章节号、identity、运行模式等小型结构化状态。缓存键和展示文本都来自同一份规范 JSON,不能用 default=str 把未知对象悄悄变字符串。

只接受 JSON object,值递归限制为 scalar/array/object。拒绝 array 外的非普通对象、symbol key、NaN、±Infinity、循环引用。合法值按 key 排序+紧凑 JSON+UTF-8 字符规范序列化——键插入顺序不同但语义相同得到同一 key。

4 · 缓存必须属于会话

旧写法把 lastContextKey/lastPrompt 放模块全局,两 Agent 实例同进程会共享,把一个 workspace 的 Prompt 复用给另一个会话。

DynamicPromptRenderer 把缓存放实例字段。每次 buildAgent(P10) 新建 renderer,缓存天然会话隔离。缓存键覆盖全部可见输入:identity+context+tools+workspace+skills+selected memory,全部相等才复用并 cacheHits++。

注意 这只是进程内避免重复组装字符串的缓存,不等价于供应商 API 的 prompt cache。当前 OpenAI 适配器没把静态/动态 section 分成不同 cache-control block,不能宣称动态内容变化时仍命中 API 级静态前缀缓存。
5 · 零参数 Provider 接入唯一 Loop

AgentRunner 不该知道 Prompt 每个数据源,只依赖零参数 provider:每次模型请求前调 render() 获当下 Prompt。DynamicPromptProvider 在构建阶段绑定 renderer 和运行态对象。

AgentRunner.#renderSystemPrompt() 对返回值做类型与空值校验:返回空串或非字符串立即抛错,不回退到构建期固定 systemPrompt,避免静默用过期指令。

6 · 记忆只注入一次

第 9 章 MemorySession.beforeModel() 额外返回一条 system context 消息。到第 10 章 selected memory 已进动态 Prompt 的 memory section;若原路径还开,同一正文出现两次。

Bootstrap 显式切换所有权:createMemorySession(dependencies, !dynamicPrompt)。P09 没动态 prompt 能力时仍启用消息注入,P10 才关闭。生命周期仍负责选择/提取/整理,只关独立消息注入。测试直接统计 <relevant_memories> 出现次数。

▶️ 交互演示:动态 Prompt 渲染

开关 skills/memory,看五个 section 如何按固定顺序组装,可选 section 按需出现/省略。
切换:
skills 目录(有)
选中记忆(有)
tools(有)

🔑 一句话总结

Prompt 只负责渲染,不重新实现工具发现、记忆选择或路径校验——各 section 唯一来源

QA 测验