ECC 智能体钩子系统架构解析:如何为 AI 编码 Agent 装上"会记忆、能拦截、可审计"的行为护栏
【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC
ECC(Everything Claude Code)是一个面向 Claude Code、Codex、OpenCode、Cursor 等 AI 编码智能体的运行时性能优化与安全增强系统。它解决的根本问题是:Agent 会失忆、会越权、会失控——而传统提示词工程对此无能为力。本文从源码层面拆解它的钩子拦截、记忆持久化、会话归一化与控制面设计。
从一次失控会话倒推:Agent 的失忆、越权与失控是怎么发生的
先看一个真实场景。你在 Claude Code 里让它改一个模块,它在第 40 次工具调用后触发了上下文压缩(compaction),之前的约束约定被压缩成一段摘要——然后它忘了"禁止动 linter 配置"这条规则,顺手把 ESLint 关掉了。又或者,它在 tmux 里跑起一个npm run dev长驻进程,把终端日志淹没,你还不知道它干了什么。
这三个缺陷分别对应三个机制层面的根因:
- 失忆:会话上下文是易失的,压缩与重启都会丢状态,且没有"跨会话"的持久层。
- 越权:Agent 的工具调用只受模型自觉约束,没有代码级的强制拦截点。
- 失控:一次长任务的中间过程不可观测,出了事也无法回放审计。
ECC 的回应不是写更多提示词,而是把整条"事件管线"做成可编程的:在工具执行前、执行后、会话开始、压缩前、会话结束这些时点插入 JavaScript 钩子,用退出码当裁判,用 JSON schema 当契约。它的本质,是把"希望 Agent 自觉"转化为"用代码强制"。
钩子拦截图的第一性原理:PreToolUse 的阻断语义与"退出码即裁判"机制
Claude Code 原生提供了一套生命周期事件:PreToolUse、PostToolUse、Stop、SessionStart、SessionEnd、PreCompact。ECC 做的事情,是把每个事件点都变成一道可编程的闸门。
{ "PreToolUse": [ { "matcher": "Bash|Write|Edit|MultiEdit", "hooks": [ { "id": "pre:config-protection", "command": "node scripts/hooks/config-protection.js standard,strict", "timeout": 5 } ] } ] }这段配置声明了一条规则:任何写操作执行前,先跑config-protection脚本。脚本发现目标是 ESLint、Prettier 等配置文件时,直接拒绝执行——它拦截的不是"写文件"这个动作,而是"削弱代码质量约束"这个意图。与之并列的还有gateguard-fact-force(每个文件第一次编辑必须先调查 import、数据结构再放行)、mcp-health-check(MCP 服务不健康就阻断调用)。
整套钩子图的裁判语义只有两条,却足够表达复杂的策略:
| 退出码 | 含义 | 配套输出 | 典型用途 |
|---|---|---|---|
| 0 | 放行 | stderr 输出 → 仅警告 | tmux 提醒、compaction 建议 |
| 2 | 阻断 | stderr 输出 → 拦截并说明原因 | 配置保护、GateGuard、MCP 健康检查 |
| 其他 | 异常 | 记录日志 | 钩子自身崩溃,不误伤主流程 |
为什么只依赖退出码?因为这是钩子宿主协议里唯一无歧义、跨语言、零依赖的裁判信号。脚本可以用 Node、Python 甚至 Shell 编写,只要遵守"0 放行、2 阻断"的约定,就能无缝接入。PostToolUse 侧则由一个同步调度器(posttooluse-dispatcher.js)把多个后置钩子合并进单个进程执行,同时保留每个钩子独立的超时与开关控制,避免 30 个脚本各自 fork 进程带来的启动开销。
用户请求 → Agent 选工具 → PreToolUse 闸门 → 工具执行 → PostToolUse 汇总 │ │ │ │ │ exit 2 阻断 exit 0 记录/格式化 │ │ │ │ └──────── 放行后进入执行 ────────────────────────┘Bootstrap 解析机制:一段内联代码如何在 7 种安装形态下定位自身根目录
钩子配置里有一个值得单独拆解的细节:几乎每个钩子命令都以一段node -e "..."内联脚本开头,而不是直接写脚本路径。为什么?
因为 ECC 可以以插件(ecc@ecc)、marketplace、npm 包、手动安装等至少 7 种形态落盘,钩子宿主(Claude Code)执行钩子时的工作目录并不等于插件根目录。如果写死相对路径,换个安装方式就全盘失效。于是它内联了一个小型解析器resolveEccRoot(),按顺序探测:
- 读取
CLAUDE_PLUGIN_ROOT环境变量,命中即返回。 - 依次尝试
~/.claude及其plugins/ecc、plugins/marketplaces/ecc、plugins/everything-claude-code等 5 个候选路径。 - 遍历
plugins/cache下按名称分组的缓存目录,逐层寻找可解析根。 - 全部失败则回退到
~/.claude本身。
这段"自举"逻辑的巧妙之处在于:解析器与被解析的钩子运行在同一个进程里,先定位根目录,再把真正要执行的脚本注入process.argv拼接执行。用户装完插件后无需手工改任何绝对路径,钩子图是"可搬运"的。配合ECC_HOOK_PROFILE=standard|strict、ECC_DISABLED_HOOKS这类环境变量开关,运维者可以在不触碰hooks.json的前提下按需启停单个钩子——策略与实现彻底解耦。
记忆持久化的三段式生命周期:SessionStart、PreCompact、SessionEnd 如何对抗上下文压缩
失忆问题的解法,是把会话状态"外置"到文件系统。ECC 的记忆钩子组定义了三个关键时点:
SessionStart:加载有界的历史上下文(默认上限 8000 字符,可用ECC_SESSION_START_MAX_CHARS调低),并探测项目包管理器与工作区状态。PreCompact:在上下文压缩发生之前,把当前会话状态持久化——压缩会丢,文件不会。SessionEnd:转录元数据可用时,写入会话结束摘要。
会话开始 ──► SessionStart ──► 工作循环 ──► PreCompact ──► 压缩 ──► 恢复 │ │ │ │ │ │ 载入历史 工具调用 │ 落盘状态快照 │ │ │ └──► observe-runner 记录意图/结果 │ │ └──► suggest-compact(约 50 次调用提醒) └─────────────┴──── SessionEnd 写终结摘要 ──┘中间还有一个常驻的观察者(observe-runner),在每次工具调用前后分别记录"意图"与"结果",喂给 continuous-learning 信号流。这些信号并不直接注入上下文(那会撑爆 token),而是沉淀为后续模式提取与记忆入库的原料。记忆是"写时持久、读时有界"的——写入廉价,读取受控,这是它区别于"把整个历史塞回上下文"的朴素做法的关键取舍。
记忆契约 ecc.memory.v1:schema 约束如何把"不可信记忆"变成可控数据
记忆要跨会话、跨 harness 复用,就必须有统一形状。schemas/memory.schema.json定义了ecc.memory.v1:每份记忆文档必须声明kind(context、decision、fact、handoff、lesson、note、preference、runbook 八选一)、scope(project / team / user)、trust、status与sourceHarness、targetHarnesses。
{ "schema": "ecc.memory.v1", "kind": "lesson", "scope": "project", "trust": "unreviewed", "status": "active", "sourceHarness": "claude", "targetHarnesses": ["claude", "codex"], "tags": ["migration", "schema"], "body": "…" }schema 里有两个设计信号值得注意。其一,trust的枚举值只有unreviewed一个——schema 注释写得直白:"被回忆的记忆只是上下文,不是可执行指令;受治理的真相会被提升为项目规范文档,离开记忆库。"这是对"记忆污染"风险的显式防御:记忆默认低可信,只有人工/流程确认后才升级为正式规范。其二,status支持rejected与superseded,让坏记忆可以被标注作废,而不是物理删除——保证审计链完整。记忆系统通过memory.js、memory-mcp.mjs等脚本提供查询与写入入口,整体遵循"回忆即上下文、约束即数据"的范式。
会话适配层 ecc.session.v1:异构 harness 的状态归一化机制
一个更宏大的问题是:Claude Code 的会话历史、tmux 编排的工作树会话、未来的 Codex/OpenCode 后端,格式各不相同。ECC 用一个"会话适配器契约"(docs/SESSION-ADAPTER-CONTRACT.md)把一切归一为ecc.session.v1快照:
{ "schemaVersion": "ecc.session.v1", "adapterId": "dmux-tmux", "session": { "id": "workflow-visual-proof", "kind": "orchestrated", "state": "active" }, "workers": [ { "id": "seed-check", "state": "running", "health": "healthy", "branch": "feature/seed-check", "worktree": "/tmp/worktree", "runtime": { "kind": "tmux-pane", "command": "codex", "pid": 1234 } } ], "aggregates": { "workerCount": 1, "states": { "running": 1 } } }每个源都通过一个 adapter(如dmux-tmux、claude-history)转换成这个形状。收益是双向的:上层(session-inspect、loop-status、未来的 HUD)只依赖契约,不关心底层是 tmux 还是原生历史文件;底层接入新 harness 时只需新增一个 adapter,无需改任何消费方。契约即边界——这正是它能在 7 类 harness 上保持可移植的原因。
分档安装与 Rust 控制面:性能优化系统如何向"操作系统"演进
ECC 的仓库形态暴露了它的演进路线:manifests/install-profiles.json把 26 个模块(rules-core、hooks-runtime、framework-language、security、ito-compute……)组合成 6 个安装档位:
| 档位 | 是否含 hooks-runtime | 定位 |
|---|---|---|
| minimal | 否 | 低上下文占用的纯规则/命令集 |
| opencode | 否 | OpenCode 专用基线,钩子按需选装 |
| core | 是 | 最小可运行基线 |
| developer | 是 | 工程场景默认档 |
| security | 是 | 安全加固档 |
| full | 是 | 全模块,覆盖机器学习到供应链域 |
"钩子运行时是否默认开启"这一维度的刻意区分,反映了一个权衡:钩子是能力也是成本——它们占启动时间、占 token、可能误伤流程,所以默认档位必须按"上下文预算"与"防护强度"双轴设计,而不是一刀切全装。
向上延伸,ecc2/目录用 Rust 重写了控制面原型:SQLite 会话存储、cargo run -- dashboard终端仪表盘、后台守护进程,以及一个有意思的harness-eval机制——候选配置用 SHA-256 寻址、不可变引用证据,晋升需要满足min-samples 2、min-mean-delta 0.05、min-win-rate 0.5三重复合门限,且整个评估只读、不联网、不碰运行中会话。这套"以证据换晋升、以回滚保安全"的流程,把对 Agent 行为的治理从"事后打补丁"推进到"上线前可证明"。
设计哲学:约束即自由,契约即边界
回看 ECC 的整体架构,能提炼出三条贯穿始终的设计主张:
- 约束即自由:退出码、schema、模块清单这些"限制",恰恰让策略可组合、可替换、可审计——自由不是无限提示词,而是被约束托底的探索空间。
- 记忆要分层:易失的上下文、低可信的记忆库、受治理的规范文档,三者严格区分,宁可丢细节也不让坏数据污染决策。
- 契约先于实现:
ecc.memory.v1、ecc.session.v1、钩子退出码协议,都是先定契约再写实现,这让 7 类 harness 与未来控制面可以并行演进而不互相绑架。
对一个 Agent 系统来说,最危险的从来不是模型不够聪明,而是它"聪明得不可控"。ECC 用一层薄而硬的工程约束,把失控的概率压到可接受区间——这种"用确定性兜底不确定性"的思路,值得每一个把 Agent 接进生产流程的团队借鉴。
【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考