无限循环 + 多终止条件

while(true) 主循环配合多路退出,比递归调用更易管理状态,也更容易扩展新的终止条件。

10+

独立提示词分段

系统提示词由 10+ 个函数段组成,每段独立维护,通过 BOUNDARY 分离缓存域,大幅降低 prompt 工程复杂度。

12

分层权限决策管道

12 步顺序决策,越安全的检查越靠前,免疫绕过的安全检查硬编码在不可绕过的层级。

3

错误恢复路径

React Compact / Max Tokens 恢复 / 模型 Fallback,三条独立的错误恢复路径,大多数错误用户无感知。

10 个核心设计模式
按实用性和可复用性排序,每个模式包含来源文件和具体借鉴建议。
🔄
双层 Generator 架构
QueryEngine.ts · query.ts · queryLoop()
问题:Agent 需要同时处理"会话状态管理"(跨轮次记忆、费用跟踪、SDK输出)和"行为循环"(API调用、工具执行),两者职责不同但又紧密耦合。

Claude Code 方案:外层 QueryEngine(AsyncGenerator)管理会话生命周期,内层 queryLoop(无限 while 循环)只关心一次请求的完整"思考-行动-观察"周期。外层通过 for await...of 消费内层产出的消息流。

两层之间通过 yield* 传递消息,内层的每个 yield 都会透传到 SDK 调用者。这让内层可以独立测试,外层可以专注于状态管理。
借鉴: 将 Agent 的"会话管理"和"行为执行"分离为两层。外层负责持久化、计费、SDK 适配;内层是纯状态机,输入为(消息历史 + 配置),输出为(消息流 + 终止原因)。通过 AsyncGenerator 实现流式输出。
流式工具并发执行(Streaming Tool Executor)
StreamingToolExecutor.ts · toolOrchestration.ts
问题:等待 API 流式响应完全结束再开始执行工具,会造成显著延迟(API 延迟 + 工具执行延迟串行叠加)。

Claude Code 方案:StreamingToolExecutor 在 API 流式过程中,一旦某个 tool_use 块到达,立即异步开始执行该工具,无需等待整个响应完成。通过 isConcurrencySafe() 判断哪些工具可以并发:读操作(文件读/搜索/MCP)并发执行,写操作(文件写/Bash)串行执行。这通常可以节省数百毫秒的延迟。
借鉴: 工具执行不必等 LLM 全部输出完毕。每个工具声明 isConcurrencySafe: boolean,主循环维护一个执行槽位:空槽 → 立即执行;槽满且不安全 → 等待。读类工具几乎总是安全的,写类工具需要严格串行。
📋
系统提示词分段注册表
constants/prompts.ts · systemPromptSections.ts
问题:系统提示词是一个复杂的动态文档,随功能增加变得难以维护。不同部分有不同的缓存需求(静态/动态),手动拼接容易出错。

Claude Code 方案:每个提示词段由独立函数生成,通过 systemPromptSection(name, fn) 注册到注册表,由框架统一调用并缓存。静态段(角色定义、行为规范)走全局 Prompt Cache,动态段(环境信息、MCP 指令)每轮重新计算。BOUNDARY 标记精确分隔缓存域。
借鉴: 设计提示词时,将不同关注点分离到独立函数/模块中(角色、规则、环境、工具指南、记忆等)。明确区分"不变内容"(可全局缓存)和"会话相关内容"(需要动态生成)。使用注册表模式而非硬编码拼接。
🔐
分层权限模型(免疫绕过 + 规则引擎)
permissions.ts · useCanUseTool.tsx · bashPermissions.ts
问题:Agent 工具调用权限控制需要平衡"自动化效率"和"用户安全",纯人工确认太慢,完全自动化太危险。

Claude Code 方案:12步决策管道,越危险的检查越靠前,部分检查"免疫绕过"(即使 bypassPermissions 模式也无法跳过)。5种权限模式满足不同使用场景(开发调试 vs 生产部署)。规则引擎支持精细的内容级规则(如只允许 git status,禁止 git push)。
借鉴: 设计工具权限时,区分三类规则:硬编码安全检查(永远运行)、用户可配置规则(Allow/Deny/Ask)、模式级别控制(开发/生产)。最危险的操作(删除、发布、外部消息)应做到无论何种模式都需要明确的用户授权。
🔧
内建三条错误恢复路径
query.ts · reactiveCompact.ts · FallbackTriggeredError
问题:生产环境中的 Agent 会遭遇各种 API 错误(上下文过长、输出截断、模型不可用),如果每种错误都暴露给用户,体验极差。

Claude Code 方案: (1) 413 prompt_too_long → 触发 Reactive Compact,自动摘要历史消息后重试; (2) max_output_tokens → 先升级到 64k max_tokens,再注入 nudge 消息最多重试 3 次; (3) 模型过载 → 自动切换 fallback 模型,清空孤儿消息,用系统通知告知用户。 三条路径相互独立,失败时才最终将错误暴露给用户。
借鉴: 为每种常见 API 错误设计自动恢复策略,而不是直接返回错误。关键是"扣留"(withhold)错误消息直到确认无法恢复,避免中间状态暴露给用户。每种恢复策略设置最大尝试次数,超限后优雅降级。
📊
Token 预算与自动压缩机制
autoCompact.ts · tokenBudget.ts · query.ts
问题:长任务中对话历史会无限增长,最终触发上下文限制导致任务中断。手动压缩打断用户工作流。

Claude Code 方案:每轮迭代前检查 token 数量,超过阈值时调用独立的压缩 API 生成摘要,以摘要替换原始历史(AutoCompact)。TOKEN_BUDGET 特性允许用户指定目标 token 消耗量,不足时自动注入 nudge 消息促使 Agent 继续工作直至目标达到。
借鉴: 在 Agent 主循环中定期检测上下文大小,提前触发压缩而不是等到 API 报错。设计可以插拔的压缩策略(滑动窗口 / LLM摘要 / 工具结果截断)。对于长任务,提供"强制继续"机制(nudge)让 Agent 持续工作。
🤝
异步 Worker + task-notification 通信
AgentTool.tsx · LocalAgentTask.tsx · Coordinator
问题:大型任务需要多 Agent 并行执行,但 LLM 的对话模型天生是同步单线程的,如何实现真正的并行?

Claude Code 方案:主 Agent 通过 AgentTool 派发异步 Worker,立即返回不等待。Worker 的结果以 XML 格式(task-notification)注入到主 Agent 的下一轮用户消息中,主 Agent 通过 task-id 识别来源并综合处理。SendMessageTool 允许主 Agent 向运行中的 Worker 发送追加指令。
借鉴: 多 Agent 通信不需要复杂的实时通道。将 Worker 结果以结构化 XML/JSON 注入到协调者的消息流中是最简单有效的方案。关键设计:每个结果带唯一 task-id(用于关联)、状态(用于检测失败)、简短摘要(用于快速过滤)。
🔌
MCP 工具的动态注册与名称空间化
services/mcp/client.ts · types.ts
问题:第三方工具(MCP 服务器)的工具名称可能与内置工具冲突,且连接状态可随时变化。如何设计可插拔的工具生态系统?

Claude Code 方案:所有 MCP 工具自动添加 mcp__服务器名__工具名 前缀命名空间,避免冲突。服务器连接状态有明确的状态机(connected/pending/failed/needs-auth/disabled),UI 实时反映。工具发现通过 ListTools RPC,结果被 memoize 缓存。Agent 的 MCP 配置支持继承(子 Agent 获得父 Agent 的所有 MCP clients)和扩展(Agent 定义文件中声明专属 MCP 服务器)。
借鉴: 设计工具生态系统时,为第三方工具使用命名空间前缀(plugin__toolName),避免冲突。提供清晰的工具注册 API(工具名、描述、JSON Schema、执行函数),让第三方工具与内置工具完全等价。连接状态的可见性对调试至关重要。
🧠
系统提示词优先级覆盖链
utils/systemPrompt.ts · buildEffectiveSystemPrompt()
问题:Agent 框架需要同时支持多种定制场景:完全自定义的 Agent、系统集成商的定制、用户的个性化偏好,以及框架的默认行为。如何优雅管理这些层次?

Claude Code 方案:4层优先级覆盖链:overridePrompt(完全覆盖)→ Coordinator 提示词 → Agent 定义提示词 → 用户自定义提示词 → 默认提示词。每层可以"替换"或"追加",appendSystemPrompt 则无论哪层都追加到末尾。
借鉴: 设计 Agent 框架时,明确定义提示词的优先级层次(框架默认 → 产品定制 → 用户偏好 → 实例覆盖)。"追加"操作比"替换"操作更安全(不会意外丢失安全规则)。为高优先级提示词提供"免疫保护"机制,防止低优先级内容覆盖核心安全规则。
🪝
Hooks 系统:工具调用前后的可编程干预
utils/hooks.ts · postSamplingHooks.ts · stopHooks.ts
问题:不同的部署场景(企业合规、安全审计、工作流集成)需要在 Agent 行为的关键节点插入自定义逻辑,但又不希望侵入核心代码。

Claude Code 方案:4类 hooks:pre-tool-use(工具调用前,可修改输入或拒绝)、post-tool-use(工具完成后,可检查输出)、user-prompt-submit(用户提交前)、stop(助手消息完成后,可阻止 Agent 继续)。Hooks 以 shell 命令形式配置,通过 stdin/stdout 交互,语言无关。
借鉴: 在 Agent 生命周期的关键节点暴露 hooks 接口:工具调用前后、LLM 响应后、循环终止前。Hooks 以进程/shell 命令形式实现,而非代码注入,降低集成复杂度。Hook 的返回值应明确表达意图:allow/deny/modify,而不是隐式失败。
快速参考:关键源文件
当你想深入研究某个特定机制时,这些文件是最好的入口。
机制 核心文件 关键函数/类 行数
Agent 主循环src/query.tsqueryLoop()1729
SDK 会话管理src/QueryEngine.tsQueryEngine.submitMessage()1295
系统提示词构建src/constants/prompts.tsgetSystemPrompt()914
提示词覆盖优先级src/utils/systemPrompt.tsbuildEffectiveSystemPrompt()123
权限决策管道src/utils/permissions/permissions.tshasPermissionsToUseToolInner()1500+
Bash 规则匹配src/tools/BashTool/bashPermissions.tsbashToolHasPermission()1400+
并发工具执行src/services/tools/toolOrchestration.tsrunTools(), partitionToolCalls()188
流式工具执行器src/services/tools/StreamingToolExecutor.tsaddTool(), getCompletedResults()530+
Coordinator 模式src/coordinator/coordinatorMode.tsgetCoordinatorSystemPrompt()300+
Agent 派生执行src/tools/AgentTool/runAgent.tsrunAgent()200+
MCP 客户端src/services/mcp/client.tsconnectToServer(), listTools()3348
Mailbox 通信src/utils/teammateMailbox.tswriteToMailbox(), readMailbox()200+