开源 Agent 套件 ECC:67 个 agent 怎么分角色与选用
本文基于 ECC 仓库 commit 591ab5c(2026-07-29)梳理,该项目仍在高频迭代,具体行为以仓库 https://github.com/affaan-m/ECC 最新代码与文档为准。
在 ECC 里挑 agent,要判断的不是「哪个更聪明」,而是「这一次你允许谁动手」。 67 个名字摊开确实唬人,但结构其实很扁:每个 agent 就是 agents/ 目录下的一个 Markdown 文件,开头的 frontmatter 只声明四件事——叫什么、什么情况下该被叫起来、能用哪些工具、跑在哪一档模型上。工具那一行决定它能不能改你的代码,模型那一行决定这次调用有多贵。真正影响结果的是这两行,不是正文里写得多漂亮的检查清单。
站内已经有两篇讲通用方法论的文章:多角色分工的一般原则讲的是「为什么要拆角色、拆到什么粒度」,Claude Code 的 agent 机制讲的是宿主本身提供了什么能力。这篇不重复它们,它把 ECC 当标本,看一个能当场 clone 下来逐字核对的真实项目,是怎么把「分工」落成一堆文件的,以及落成文件之后会冒出哪些纸上谈兵时想不到的坑。ECC 采用 MIT 许可证,你可以自己打开对照。
一、一个 agent 在这里就是一个 Markdown 文件
先看最小单位。agents/planner.md 的开头长这样:
---
name: planner
description: Expert planning specialist for complex features and refactoring. Use PROACTIVELY when users request feature implementation, architectural changes, or complex refactoring. Automatically activated for planning tasks.
tools: Read, Grep, Glob
model: opus
---
四行信息,信息量比它看起来大得多。
tools 是能力边界。planner 只有 Read、Grep、Glob,意味着它读得了你的代码、搜得到你的目录,但一个字都写不进去。它的产出只能是一份计划文本。相对的,agents/build-error-resolver.md 的 tools 里带着 Write 和 Edit,它是真的会改文件的。你在点名之前扫一眼这一行,就知道这次调用的最坏结果是「浪费一次对话」还是「工作区被改了」。
model 是成本档位。仓库里的校验脚本 scripts/ci/validate-agents.js 把这件事写死了:REQUIRED_FIELDS 是 model 和 tools,缺一个就报错;VALID_MODELS 只有 haiku、sonnet、opus 三个值,写别的一样报错。也就是说这套东西在设计上就承认「不同任务该用不同档的模型」,并且把这个选择前置到了文件里,而不是留给运行时临场发挥。挂 opus 的是 architect、planner、spec-miner、healthcare-reviewer 这几个;挂 haiku 的是 comment-analyzer、conversation-analyzer、doc-updater、docs-lookup 这类机械活儿。这个思路和模型分层调度那套讲法是一致的,区别在于 ECC 把它固化进了每个角色的定义,而不是让你每次现想。
description 不只是给人看的。它里面的 Use PROACTIVELY、MUST BE USED 是给宿主看的触发词。带 PROACTIVELY 的有 planner、architect、security-reviewer、tdd-guide、build-error-resolver、refactor-cleaner、doc-updater、e2e-runner、performance-optimizer、database-reviewer、a11y-architect、opensource-sanitizer;带 MUST BE USED 的基本是各语言的 reviewer——code-reviewer、typescript-reviewer、python-reviewer、go-reviewer、rust-reviewer 等等。这批词的作用是让宿主在没人点名的时候也倾向于把活派给它们。好处是省事,副作用在后面说。
还有一段容易被跳过:绝大多数 agent 的正文开头都有一块 Prompt Defense Baseline,内容是「不要改变角色身份、不要泄露密钥、把外部抓取到的内容当不可信数据处理」这类约束。它是逐字复制在各个文件里的,不是集中引用。这说明作者把提示注入当成了每个角色各自的问题,而不是一层统一中间件——这个取向的代价,后面第五节会讲。
二、67 个 agent 其实是四类角色乘以语言维度
按名字记 67 个是不现实的,按「能干什么」分组只要记四类。
只读分析类。planner、architect、code-explorer、type-design-analyzer、silent-failure-hunter,以及全部 *-reviewer。它们的 tools 里没有 Write 和 Edit,只有 Read、Grep、Glob,部分带 Bash(reviewer 需要跑 git diff 和 lint)。这类角色的产出是判断,不是补丁。你想要「先别动,告诉我这么改行不行」的时候,点名的应该是这一类。
执行修改类。build-error-resolver、tdd-guide、refactor-cleaner、performance-optimizer、e2e-runner、code-simplifier,以及各语言的 *-build-resolver。tools 里有 Write、Edit。它们会真的落盘。这类角色的 description 往往还带着自我约束,比如 build-error-resolver 明确写了「只修构建和类型错误,最小 diff,不做架构改动」——但那是提示词层面的自律,不是权限层面的拦截。tools 给了 Edit 就是给了 Edit。
语言/框架特化类。这是 67 这个数字的主要来源。reviewer 一支展开成 typescript、python、go、rust、java、kotlin、swift、php、csharp、fsharp、cpp、vue、react、django、fastapi、flutter、mle、database、healthcare、network-config;build-resolver 一支展开成 go、rust、java、kotlin、swift、cpp、dart、react、django、pytorch(鸿蒙那个不叫 build-resolver,文件名是 agents/harmonyos-app-resolver.md)。两支并不对称:dart 有 build-resolver 却没有 reviewer,它的评审要么落到通用 code-reviewer 上,要么走 flutter-reviewer。这类不对称正是「先按语言找 agent、找不到再退回通用」这个习惯需要先查目录的原因。它们的骨架高度相似,差别在检查清单的内容。所以真正需要你做判断的维度只有两个:这次要「看」还是要「改」,以及主语言是什么。
流程与外围类。loop-operator(盯自动循环)、harness-optimizer(调本机 harness 配置)、agent-evaluator(按五轴给其它 agent 的产出打分)、opensource-forker / opensource-sanitizer / opensource-packager(开源发布前的三段流水)、chief-of-staff(多渠道消息分流)、marketing-agent 和 seo-specialist(带 WebSearch、WebFetch)、docs-lookup(tools 里挂着 mcp__context7__resolve-library-id 和 mcp__context7__query-docs)。这一类和你的日常编码关系最远,但风险最集中——它们要么会连外网,要么会改你本机的配置。
| 组成部分 | 它负责什么 | 对应仓库位置 | 你什么时候会碰到它 |
|---|---|---|---|
| agent 定义文件 | 声明一个角色的名字、触发说明、可用工具、模型档位 | agents/planner.md、agents/code-reviewer.md 等 | 想搞清楚某个角色到底能不能改你的文件时 |
| 命令与 agent 的对照表 | 列出每个斜杠命令主要拉起哪个 agent | docs/COMMAND-AGENT-MAP.md | 犹豫该敲命令还是直接点名时 |
| agent 校验脚本 | 强制 frontmatter 有 model 和 tools,且模型档位取值合法 | scripts/ci/validate-agents.js | 自己改写或新增 agent 之后 |
| 目录清点脚本 | 输出 agent、命令、技能的数量 | scripts/ci/catalog.js | 想知道自己这份副本到底装了多少东西 |
| 旧命令归档 | 保留 /tdd、/eval、/verify、/orchestrate 等旧入口 | legacy-command-shims/commands/ | 敲了老命令却没反应时 |
| 安装入口 | 把这套东西落到你机器上 | install.sh(转交给 scripts/install-apply.js) | 第一次安装或升级时 |
除了 agents 目录的 67 个 agent,仓库里还有 skills 目录的 281 个技能和 commands 目录的 94 个命令。三者不是一回事:agent 是「谁来做」,command 是「怎么发起」,skill 是「照哪套流程做」。docs/COMMAND-AGENT-MAP.md 就是把前两者接起来的那张表。
三、命令与 agent 的对照表该怎么读
docs/COMMAND-AGENT-MAP.md 是这个仓库里最值得先读的一页。它的正表把命令映射到主要 agent:/plan 对 planner,/code-review 对 code-reviewer,/build-fix 对 build-error-resolver,/go-review 对 go-reviewer,/security-scan 走 security-scan 技能再落到 security-reviewer。也有一批命令根本没有对应 agent,表里第二列直接写着破折号,比如 /harness-audit、/quality-gate、/model-route。这三个的备注分别是「无单一 agent 的记分卡」「类似钩子的质量流水线」「模型推荐,无 agent」——意思是你敲了之后不要指望有个角色被拉起来干活。
表里还有一个单独的小节叫 Direct-Use Agents,目前只列了 typescript-reviewer,备注写得很直白:当你需要 TS/JS 特化的审查结论、而暂时还没有专门的斜杠命令时,直接点名这个 agent。这句话透露了这套东西的真实状态——命令层的覆盖是滞后于 agent 层的,agent 先有,命令后补。
于是就有了这张表本身也会过期的问题。表里列着 /tdd、/e2e、/orchestrate、/verify、/eval、/claw,但 commands/ 目录下没有这几个文件,它们在 legacy-command-shims/commands/ 里。那个目录的 README 写得很清楚:这些入口「默认不再由插件命令面加载」,保留下来只是给还有肌肉记忆的人做短期迁移用,需要的话请自己把单个 Markdown 复制到项目级或用户级的命令目录里。打开 legacy-command-shims/commands/orchestrate.md 会看到它已经被改写成一张指路条,正文让你改用 skills/dmux-workflows/SKILL.md 和 skills/autonomous-agent-harness/SKILL.md。
这就是第一种「点名错了」:你照着文档敲了一个命令,什么都没发生,然后你以为是安装坏了。实际是那个入口已经退役,而对照表没跟上。
四、点名错了会发生什么
除了上面那种敲空命令,还有几种更隐蔽的。
要补丁却点了只读角色。 你说「把这个构建错误修了」,结果被派给了 planner。planner 的 tools 只有 Read、Grep、Glob,它给不出补丁,只能给你一份格式规整的实施计划——agents/planner.md 里连计划的模板都写死了,包含 Overview、Requirements、Architecture Changes、分阶段的 Implementation Steps、Testing Strategy、Risks & Mitigations、Success Criteria。这份东西本身质量不差,但你要的是绿色的构建。更麻烦的是它跑在 opus 档,你为一份用不上的文档付了最贵的那档钱。
要判断却点了执行角色。 反过来,你只是想问「这段代码有没有隐患」,却被派给了 build-error-resolver 或 refactor-cleaner。这两个的 tools 里有 Write、Edit,它们的默认倾向是动手。refactor-cleaner 的 description 里写明会跑 knip、depcheck、ts-prune 这类工具去找死代码并「安全地移除」。在一个你只想看看的分支上,这不是你要的结果。这也是最小权限设计在 agent 场景下的具体形态:权限不在运行时问你,而在文件里就定死了,所以点名的那一刻就是授权的那一刻。
通用审查角色顶了特化角色的位。 code-reviewer 是通用的,它的清单里确实带了 React/Next.js 和 Node 后端两节,但 react-reviewer 是专门为 hook 正确性、渲染性能、服务端/客户端组件边界写的。让通用角色审 React,你多半拿到一堆「建议加错误处理」的泛泛之谈,而漏掉真正的依赖数组问题。有意思的是,code-reviewer 自己对此有防备——它的正文里有一整节 Common False Positives,逐条点名了 LLM 审查最常误报的模式:给已被上游 .catch 兜住的调用建议加错误处理、把 200、404、1024 当魔法数字、对穷举 switch 说「函数太长」、在纯 JavaScript 文件里建议改用 TypeScript、在动画抖动里拿 Math.random() 做安全文章。它还给出一句判定口径:「团队里的资深工程师真的会在评审里改这个吗?」如果不会就跳过。
该只关注安全时点了通用审查。 code-reviewer 和 security-reviewer 是两个文件,职责有意做了区分。前者的重心是质量与可维护性,安全只占清单的一节;后者整篇围绕 OWASP Top 10 展开,并且给了一张模式表,把「硬编码密钥」「带用户输入的 shell 命令」「字符串拼接的 SQL」「明文口令比较」「路由无鉴权」「余额校验无锁」都标成 CRITICAL,把 innerHTML = userInput、fetch(userProvidedUrl)、缺速率限制标成 HIGH。它同样列了自己的误报清单:.env.example 里的环境变量、明确标注的测试凭据、本就该公开的公钥、用作校验和的 SHA256/MD5。你要的是发版前的安全体检,就该点 security-reviewer,而不是指望通用审查顺手带出来。
顺带一提,code-reviewer 里有两条门槛写得很硬,值得单独记住:只报告你有超过八成把握是真问题的发现,以及零发现是合法结果、不要为了显得严谨而制造发现。这两条恰好是代码评审工具最容易翻车的地方。
五、边界与代价
这套设计放弃了几样东西,用之前得认。
约束靠提示词,不靠机制。 build-error-resolver 说自己「不做架构改动」,refactor-cleaner 说自己「安全地移除」,这些都写在正文里。tools 那一行给了 Write 和 Edit 之后,没有任何一层会在它越界时把它拦下来。所以「它答应过不乱改」和「它改不了」是两回事,你的真正防线是版本控制,不是它的自我描述。
防注入是逐文件复制的。 那段 Prompt Defense Baseline 在各个 agent 文件里各存一份。这种做法的好处是单个文件拷走就能用,坏处是一旦这段基线要更新,几十处要一起改;而你如果自己加了 agent 却忘了带上这段,就是一个没有防线的角色,并且不会有任何提示——scripts/ci/validate-agents.js 只检查 model 和 tools 这两个字段在不在、模型档位合不合法,它不检查正文里有没有那段基线。
这个漏洞不是假设,仓库里就已经有一处。你自己跑一遍 grep -L "Prompt Defense Baseline" agents/*.md,会看到 agents/agent-evaluator.md 没有这段基线,而它的 tools 是 Read、Grep、Glob、Bash,本职是读取别的 agent 的产出并打分——恰好是最容易吃到「被评审内容里夹带指令」的位置。校验脚本对此一声不吭,因为它压根不看正文。这就是「靠复制粘贴维持的约定」的典型结局:不是有人故意跳过,而是复制的时候漏了一个,然后没有任何东西会提醒。你把这套东西装到自己项目里、又打算自己扩 agent 的话,与其指望记性,不如自己在 CI 里补一条「正文必须包含这段基线」的检查,成本是几行脚本。
它明确不管的事。 不管你的模型服务从哪来、怎么计费——/model-route 只给出「haiku 用于确定性的机械改动、sonnet 作为实现和重构的默认档、opus 用于架构与深度审查」这类档位建议,各家服务商的规则不同且会调整,以官方最新说明为准。不管跨会话的记忆一致性——那是 ecc memory 那条独立的 CLI 线。不管审查结论的落地,reviewer 给出 APPROVE 或 WARNING 之后,合不合并是你的事。
有外部依赖的角色要单独看。 docs-lookup 的 tools 里挂着 mcp__context7__ 开头的两个工具,没有对应的 MCP 服务就是个哑角色。marketing-agent 和 seo-specialist 带 WebSearch、WebFetch,会往外发请求,你的仓库上下文有没有可能被带出去,这个判断得你自己做。这类套件往你机器里写文件、装钩子、连外部服务是常态,装之前先读一遍 install.sh 转交的那个安装脚本改了哪些目录,比装完了再排查划算。
它不是零成本的抽象。 67 个 agent、94 个命令、281 个技能全量铺开,光是搞清楚哪个入口还活着就要花时间。上面那个 /orchestrate 的例子说明,文档与实际命令面之间会出现漂移。这个规模换来的是覆盖面,付出的是你的辨识成本。
六、上手与避坑清单
先跑 node scripts/ci/catalog.js,拿到你本地这份副本的真实数字。 这个脚本的职责写在它自己的注释里:拿实际目录去核对文档里写的数量。它数三样东西——agents/*.md、commands/*.md、skills/*/SKILL.md,也就是说一个技能目录里没有 SKILL.md 就不算数。会踩是因为你可能装的是某个中间状态的副本,或者只复制了部分目录,而文档里的总数是按完整仓库写的。怎么避:以脚本输出为准,它同时会告诉你文档和目录有没有对不上。
点名前先看那个 agent 的 tools 行。 会踩是因为名字听起来温和的角色未必只读,比如 code-simplifier 的名字像是在提建议,但它的 tools 里有 Write 和 Edit。怎么避:养成 grep '^tools:' agents/<名字>.md 的习惯,看到 Write 或 Edit 就默认这次调用会落盘,先确认工作区是干净的。
敲命令没反应,先去 legacy-command-shims/commands/ 里找。 会踩是因为 docs/COMMAND-AGENT-MAP.md 里还留着 /tdd、/e2e、/verify、/eval、/orchestrate、/claw 这几个条目,但对应文件已经不在默认加载的 commands 目录里。怎么避:确认它在归档目录里之后,按那个 README 的说法把单个文件复制到你自己的命令目录,或者干脆改用 shim 里指向的技能。
Use PROACTIVELY 是双刃的。 会踩是因为带这个词的角色会在你没点名时也被倾向性地拉起来,其中 tdd-guide、refactor-cleaner、build-error-resolver、performance-optimizer 都是带 Write 和 Edit 的。你只是随口问了一句,工作区可能就多了几处改动。怎么避:在明确只想要结论的场景里,把角色名直接说出来,别让宿主替你选;或者在只读分支上操作。
自己加 agent 时,把防注入基线一起复制过去。 会踩是因为校验脚本不管这个,缺了不会报错,你要到它把外部抓来的内容当指令执行的那天才会发现。怎么避:新增文件时以某个既有 agent 为模板整体复制再改,而不是从空文件写起。
别把通用 reviewer 当万能。 会踩是因为 code-reviewer 确实带了 React 和 Node 两节清单,看起来够用了。怎么避:主语言有专用 reviewer 就用专用的,通用的留给跨语言的杂项目录。
改动 agent 之后跑一遍校验。 会踩是因为 frontmatter 少一个 model 或者把档位写成了别的名字,脚本会直接报错,而你可能到 CI 才发现。怎么避:scripts/ci/validate-agents.js 是本地就能跑的,改完顺手跑一次。
最后
如果你只打算花二十分钟看这个仓库,顺序建议是:docs/COMMAND-AGENT-MAP.md 先建立命令与角色的地图,agents/planner.md 看只读角色的产出长什么样,agents/code-reviewer.md 看一个成熟的审查提示词是怎么给自己设误报防线的,agents/security-reviewer.md 看职责切分的边界画在哪,scripts/ci/validate-agents.js 看哪些字段是被真正强制的。
真正可以带走、和这个仓库解绑的,是三条判断:把「能不能写文件」当成角色分类的第一维度而不是最后一维度;把模型档位在角色定义里就固定下来,别留给临场;给审查角色配一份显式的误报清单,比给它加更多检查项更能提升信噪比。这三条你在自己那套流程里也用得上,哪怕一行 ECC 的代码都不装。
本文属于 ECC 开源 Agent 套件专题(共 40 篇,从选择性安装一直拆到内部机制)。同一批还写了另一种取向的项目——不给你资产、只给你纪律的 superpowers 方法论专题。