首页 项目 博客 简历 联系 English
返回列表
2026年7月2日 约 3,522 字 预计 8 分钟读完

10:Hooks & Extension:Claude Code 如何把外部工作流接进 Agent Runtime

上一篇写 Fallback & Recovery 时,我把 Claude Code 的失败处理拆成两条线:fallback 处理当前这一步怎么换路,recovery 处理任务走坏以后怎么回到可继续的位置。

#Claude Code#Coding Agent#工程化#Agent Runtime

10:Hooks & Extension:Claude Code 如何把外部工作流接进 Agent Runtime

上一篇写 Fallback & Recovery 时,我把 Claude Code 的失败处理拆成两条线:fallback 处理当前这一步怎么换路,recovery 处理任务走坏以后怎么回到可继续的位置。

到这里,Agent 自己的运行链路已经比较完整了。它能读上下文,能计划,能调用工具,能做权限裁决,能留下轨迹,也能在失败后继续推进。

但真实工程里还有一个问题:Agent 还要走进团队已有的工作现场。检查脚本、代码审查流程、issue 系统、CI、通知、内部文档、发布规则,都需要以某种方式接进来。

这一篇追的问题是:

Claude Code 如何把外部工作流接进 Agent Runtime,同时让 prompt 保持轻一点?

我现在对 Hooks & Extension 的理解是:扩展机制的重点,是在 runtime 的不同位置开入口。入口位置不同,适合放进去的东西也不同。

ChatGPT Image Jul 1, 2026, 07_00_34 PM

外部流程怎么接进来

如果只看内置能力,Claude Code 已经能做很多事:读文件、搜代码、改文件、跑命令、记录过程、处理失败。

但团队里的工程流程通常比本地仓库更大。

提交前要格式化和 lint。
某些目录需要额外审查。
测试结果可能在 CI 里。
需求背景可能在 issue 或文档系统里。
任务结束后要通知团队频道。
有些规则来自项目,有些规则来自用户,有些规则来自组织。

这些东西全写进 prompt 会很臃肿,也不稳定。更合适的做法,是把它们放到不同入口里:该成为工具的成为工具,该成为流程的成为流程,该成为事件拦截的挂到事件上。

所以第 10 篇的主线很简单:

扩展机制真正处理的是:外部流程应该从 runtime 的哪个位置接进来。

别把扩展都叫插件

我一开始很容易把 hook、skill、slash command、MCP 都看成插件。这个叫法方便,但会把真正的差异盖住。

它们都能扩展 Claude Code,可插入的位置不一样。

slash command 更靠近用户发起任务的入口。它回答的是:这次我要按什么固定流程开始。

skill 更靠近可复用能力。它回答的是:做这类任务时,有哪些说明、脚本、模板、示例和判断标准可以加载。

MCP 更靠近工具层。它回答的是:Agent 需要访问仓库外的系统时,怎么把外部系统变成可调用工具。

hook 更靠近执行事件。它回答的是:工具调用前后、权限请求、会话结束、通知这些节点发生时,外部流程怎么自动介入。

参考 Agiflow 对 prompt augmentation 的反向分析,它把 commands、skills、CLAUDE.md、hooks、subagents 放在不同的注入位置看[2]。这对我理解第 10 篇很关键:功能名没有插入位置重要。

四种接入位置

Claude Code 在这个模块上大概可以按四种入口理解。

入口插入位置适合放什么
command用户发起任务时固定任务入口、常用流程模板
skill能力和上下文加载时可复用方法、脚本、模板、示例
MCP / tool工具调用层数据库、issue、浏览器、文档、云服务
hook生命周期事件上检查、格式化、审计、通知、自动验证

这张表不用背配置。它只是提醒我:扩展点要先按位置分,再谈具体机制。

如果一个团队想做“提交前检查”,更可能需要一组入口配合:

  • 用 command 固定任务入口。
  • 用 skill 放审查方法和输出标准。
  • 用 MCP 查 issue、CI 或外部文档。
  • 用 hook 在工具执行前后做检查和记录。
  • 用 permission 控制哪些动作能直接执行,哪些动作要问人。

这样看,扩展机制就不会散成一堆功能名,而会变成一张 runtime 接入图。

hook 接在执行事件上

hooks 是这一篇最容易写散的部分。它看起来像“配置一些脚本”,但更重要的是事件位置。

腾讯云的 hooks 解析里把 hook 放在生命周期事件里看,比如 PreToolUse、PermissionRequest、PostToolUse、Stop、Notification、SubagentStart / Stop 等[1]。补充资料里也提到 Claude Code 相关分析会把 hook 看成一个事件系统,并提醒 hook 要保持幂等,避免 SessionStart 这类事件触发出重复执行的问题[6]。

这让我对 hook 的理解从“能跑脚本”变成了“能接事件”。

一次工具调用大概可以这样看:

  1. 模型提出工具调用。
  2. runtime 检查参数、权限和上下文。
  3. 工具执行前触发相关事件。
  4. 工具真正执行。
  5. runtime 收到工具结果。
  6. 工具执行后触发相关事件。
  7. 结果进入 transcript、观测记录和下一轮上下文。

hook 的位置就在这条链上。

PreToolUse 适合做执行前检查,比如检查 Bash 命令、路径范围、敏感文件或团队规则。
PermissionRequest 适合在需要用户裁决时补充信息或记录审计。
PostToolUse 适合做执行后动作,比如格式化、解析测试结果、写 trace、触发轻量验证。
Stop 适合做任务收尾,比如发通知、保存摘要、同步外部系统。
Notification 适合把等待、完成、权限请求这类事件推到团队使用的渠道。

hook 的价值在于它接在关键时刻。它可以让外部流程参与 runtime,降低模型每次都要“记得”某件事的压力。

command 管入口,skill 管能力

command 和 skill 容易混在一起,因为它们都能影响 Agent 的行为。

我现在会这样区分:

command 负责把某类任务变成稳定入口。比如 /review-current-diff/fix-test/release-note。用户不用每次重新描述流程,命令本身就带着任务模板。

skill 负责把某类能力沉淀下来。它里面可以有说明、脚本、模板、资源、示例和检查标准。Agent 做到相关任务时,再把这套材料拿出来用。

所以 command 更像“这次从哪里开始”,skill 更像“做这类事时调用哪套能力”。

补充资料里提到 skills 依赖 frontmatter discovery,也就是 skill 需要能被发现、被匹配、被加载[6]。这说明 skill 的核心价值在于把一组可复用材料封装成 Agent 能找到的能力包。

这也解释了为什么固定入口和可复用能力最好分开。入口太多会让用户困惑,能力太散会让 Agent 每次重新拼流程。

MCP 把外部系统变成工具

MCP 的位置又不一样。

command 和 skill 主要影响任务怎么开始、怎么理解。MCP 更直接:它把仓库外的系统变成 Agent 可以调用的工具。

比如 issue、数据库、浏览器、文档平台、CI、云服务、内部 API。只要这些系统进入工具层,Agent 的行动范围就从本地文件扩展到外部世界。

这个扩展很有用,也会放大副作用。

读一个文件,影响通常还在本地。
调用一个外部系统,可能会查生产数据、创建工单、触发 CI、发通知、改远端状态。

所以 MCP 要按“工具边界扩大”来理解。它也需要接回前几篇讲过的底座:

  • permission 判断这次外部动作能不能执行。
  • observability 记录调用了哪个系统、传了什么摘要、结果是什么。
  • fallback / recovery 处理外部工具失败、权限拒绝或结果不可信时的下一步。

GitCode 的 Agent 编排系统分析把 commands、tools、services、hooks、MCP client 等模块放在同一张运行图里看[3]。这个视角很适合第 10 篇:MCP 是工具边界的扩展,hook 是执行事件的扩展,它们都围绕 agent loop 工作。

扩展入口的风险

扩展让 Agent 更贴近真实工程,也让边界变得更重要。

这里我只保留三类和主线最相关的风险。

  1. 配置变成执行入口。

hook 可以执行命令,也可以调用外部服务。如果项目配置里藏着高风险 hook,用户没有意识到它会在某个事件上自动触发,配置文件就变成了执行入口。Backslash 的安全分析也提醒过,配置、hook、MCP 和 trust boundary 之间有很强关系[7]。

  1. 外部工具扩大副作用。

MCP 把外部系统接进来以后,Agent 的副作用半径会变大。一次错误调用可能不只是改坏本地文件,还可能影响远端数据、CI、通知或内部系统。

  1. 多来源上下文会冲突。

CLAUDE.md、command、skill、MCP 返回、hook 结果、后面要讲的 subagent,都可能向任务提供信息。来源多了以后,优先级、作用范围和审计记录就很重要。

所以扩展层要和权限、观测、恢复放在一起看。

权限让外部能力可控。
观测让外部能力可追踪。
恢复让外部能力出错后还有退路。

第 10 篇放在 07、08、09 后面,就是因为扩展系统需要这些底座支撑。

例子:接入代码审查

用代码审查举一个短例子。

用户想让 Claude Code review 当前改动。如果只靠一句 prompt,也可以开始:

帮我看一下这次改动有没有问题。

这句话能用,但流程不稳定。更工程化的接法可以拆成几层。

第一层是 command。

/review-current-diff 作为入口,固定任务范围:读取当前 diff,按风险排序输出问题,优先看行为回归、安全风险、缺失测试和边界条件。

第二层是 skill。

团队的审查标准放进 skill:什么算高风险改动,哪些模块要特别检查,输出格式怎么写,什么时候只提问题、什么时候可以建议修改。

第三层是 MCP。

如果审查需要 issue、设计文档、CI 结果或历史缺陷,就通过 MCP 去取外部上下文。Agent 不需要把这些系统的访问方式写进 prompt,只需要把它们当工具调用。

第四层是 hook。

Edit 后自动格式化,Bash 前检查危险命令,任务结束时把 review 摘要写入 trace 或发给团队渠道。这些动作适合接在事件上,而不是靠模型每次想起来。

第五层是 permission。

默认 review 可以只读。它要自动修改代码、触发 CI 或调用外部系统时,再进入 ask 或明确授权。

这样拆完以后,扩展机制就不再是一堆名词。它们分别接在入口、能力、工具、事件和权限边界上。

我会怎么设计扩展层

如果自己写一个 coding agent,我会先设计扩展入口,而不是先想“插件市场”。

最小版本可以有四个接口:

接口解决什么问题
CommandRegistry把常用任务注册成稳定入口
SkillRegistry发现和加载可复用能力包
ToolRegistry管理内置工具、MCP 工具和权限元数据
HookBus在运行事件上触发检查、通知和审计

每个扩展入口都要声明四件事。

第一,作用范围。它影响当前任务、当前项目,还是全局环境。

第二,权限要求。它会不会读敏感文件、写文件、跑命令、访问外部系统。

第三,审计字段。它触发了什么,输入摘要是什么,结果是什么,耗时和错误类型是什么。

第四,失败处理。它失败后是继续、重试、跳过、问用户,还是中断任务。

这样设计以后,扩展层会更像 runtime 的一部分,一组有边界的运行时接口。

我现在对 Hooks & Extension 的理解可以收成一句话:

扩展层负责把外部工作流接进 Agent Runtime,但每个入口都要说清自己插在哪里、能影响什么、出了问题怎么留下证据。

参考资料

Hook 生命周期与扩展入口

源码架构与编排分析

补充资料与风险背景

下一篇:为什么需要 subagent

这一篇把 Hooks & Extension 理解成外部流程接入 runtime 的几种入口。

command 让任务有稳定入口。
skill 让能力可以复用。
MCP 把外部系统变成工具。
hook 把检查、通知、审计和验证接到执行事件上。

但还有一种扩展没有在这里展开:subagent。

subagent 牵涉的已经从“能力怎么接进来”走到了“任务要不要拆出去”。一旦拆出去,就会出现新的问题:子 Agent 能看到什么上下文,能调用哪些工具,能继承哪些权限,做完以后怎样把结果和证据带回主线。

所以 11 继续追的问题是:

Claude Code 什么时候需要 subagent?它怎样做上下文隔离、工具边界和结果回传?