一场始于"这些工具都装好了吗"的自我追问,最终演变成一个自动化工具分配系统的设计与实现。
背景
作为 AI Agent 深度用户,我习惯给 OpenCode 安装各种 MCP 和 Skill——看到好的工具就装,久而久之,工具数量越来越多:
- 8 个 MCP:playwright、lark、memory、one-search、supabase、clerk、neon、chrome-cdp
- 34 个 Skills:frontend-design、lark-* 系列、vercel-* 系列、summarize-pro、persistent-memory……
某天我突然意识到一个问题:这些工具真的被用起来了吗?
Plan:问题定义与目标设定
现状分析
我检查了 opencode.json 中的 Agent 配置,发现有 4 个协作 Agent:
{
"agent": {
"AIBA": { "description": "需求分析师" },
"AIUIUX": { "description": "UI/UX设计师" },
"AITA": { "description": "技术架构师" },
"AICA": { "description": "编码工程师" }
}
}
问题是:每个 Agent 的配置文件里,工具清单是手写的、静态的。当安装新工具后,我需要手动更新每个 Agent 的 MD 文件。更糟糕的是,工具分配完全凭直觉——"感觉这个工具应该给谁"。
核心痛点
- 工具闲置:装了 40+ 工具,但 Agent 可能只用了其中 10%
- 分配主观:没有客观依据,凭感觉分配
- 维护困难:每次装新工具都要手动更新配置
- 不可扩展:换了 Agent 名称或新增角色,规则全部失效
目标设定
构建一个自动化的工具分配系统,让工具根据 Agent 的实际职能自动分配。
具体目标:
- ✅ 自动发现所有已安装的工具(MCP + Skills)
- ✅ 自动分析 Agent 职能(不依赖名称硬匹配)
- ✅ 生成合理的工具分配方案
- ✅ 自动同步到 Agent 配置文件
Do:方案设计与实现
第一版:关键词匹配
最初的想法很简单——从 Agent 名称推断职能。
const ROLE_KEYWORDS = {
'coder': ['coder', 'coding', 'code', '程序员'],
'designer': ['designer', '设计', '设计师'],
'architect': ['architect', '架构师'],
'analyst': ['analyst', '分析师', '需求']
};
这样 AIBA 能被识别为 analyst,AIUIUX 能被识别为 designer。
效果:勉强能用,但问题很快暴露——
如果有人给 Coder Agent 取名叫 "Steve" 或 "小码" 呢?系统直接失效。
第二版:描述字段 + 名称双重匹配
吸取教训,我增加了 opencode.json 中 description 字段的分析:
function extractAgentRoles(agent) {
const description = (agent.description || '').toLowerCase();
const name = (agent.name || '').toLowerCase();
// 检查名称 + 描述中的关键词
}
效果:好了一点,但仍然不够。
描述里写"编码工程师,生成生产代码"——能识别出"工程师",但识别不出这是 Coder 角色还是 Fullstack 角色。
第三版:多维度综合分析(最终方案)
痛定思痛,我决定从多个维度综合判断 Agent 职能:
维度 1:MD 文件内容分析(权重最高)
读取 Agent 的 MD 配置文件,分析:
| 分析内容 | 说明 | 权重 |
|---|---|---|
| 已有工具清单 | 配置了 playwright → QA/Coder | 10 |
| 关键词 | 代码、设计、架构、需求等 | 5 |
| 动词 | 生成(代码)、设计(界面)、分析(需求)等 | 8 |
| 交付物描述 | 需求文档、设计规范、架构方案等 | 6 |
function analyzeAgentMdFile(agentName, agentDir) {
const content = fs.readFileSync(mdPath, 'utf-8');
// 检查已有工具(最可靠的信号)
if (/playwright|chrom[e]?[- ]?cdp/i.test(content)) {
roles.add('qa');
}
// 检查动词
if (/生成|编写|实现/.test(content)) {
roles.add('coder');
}
}
维度 2:权限链分析
如果 Agent 能调用 AICA,说明是上游的 AITA:
if (calledAgents.includes('AICA')) {
roles.add('architect'); // 能调用 coder 的,可能是 architect
}
维度 3:描述字段分析
分析 description 中的输出物描述:
const outputPatterns = [
{ pattern: /输出需求文档|产出需求/i, role: 'ba' },
{ pattern: /输出设计规范|产出设计/i, role: 'designer' },
{ pattern: /输出架构方案|产出架构/i, role: 'architect' },
{ pattern: /生成代码|产出代码/i, role: 'coder' }
];
维度 4:名称分析(兜底)
检查名称中的角色关键词:
for (const [role, keywords] of Object.entries(ROLE_KEYWORDS)) {
if (nameLower.includes(keyword)) {
roles.add(role);
}
}
核心算法:加权得分
每个 Agent 的最终角色由加权得分决定:
function extractAgentRoles(agent, agentDir, allAgents) {
const evidence = [];
// 四个维度收集证据...
// 计算每个角色的加权得分
const roleScores = {};
for (const ev of evidence) {
roleScores[ev.role] = (roleScores[ev.role] || 0) + ev.weight;
}
// 按得分排序,取前 4 个
return Object.entries(roleScores)
.sort((a, b) => b[1] - a[1])
.slice(0, 4);
}
工具匹配策略
根据工具能力标签,匹配到合适的 Agent:
const CAPABILITY_TO_AGENT = {
// 前端/设计 → 主要 designer
'frontend': ['designer', 'frontend'],
'design': ['designer'],
// 测试/调试 → 主要 QA
'testing': ['qa', 'coder'],
'browser': ['qa', 'frontend'],
// 飞书业务工具 → 主要 BA
'calendar': ['ba'],
'task': ['ba'],
'meeting': ['ba'],
// 全局 → 所有人
'memory': ['*'],
'search': ['*']
};
系统架构
┌─────────────────────────────────────────────────────────┐
│ 1. 发现工具 │
│ 扫描 ~/.config/opencode/skills/ │
│ 扫描 ~/.agents/skills/ │
│ 读取 opencode.json 中的 MCP 配置 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 2. 多维度角色分析 │
│ 读取每个 Agent 的 MD 文件 │
│ 分析已有工具、关键词、动词、交付物 │
│ 分析权限链、描述字段、Agent 名称 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 3. 智能匹配 │
│ 工具能力标签 ↔ Agent 职能得分 │
│ 加权计算,生成分配推荐 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 4. 同步配置 │
│ 更新 Agent 配置文件 │
│ 更新全局记忆文件 │
│ 输出分配报告 │
└─────────────────────────────────────────────────────────┘
Check:验证结果
角色识别效果
运行 tool-allocator sync 后:
🔍 Agent 角色多维度分析:
📌 AIBA
识别角色: designer, ba, coder, analyst
证据来源:
- designer (得分:38) <- MD文件:已有工具, MD文件:关键词:design, MD文件:动词:设计
- ba (得分:37) <- MD文件:关键词:ba, MD文件:交付物, 描述:需求分析师
📌 AIUIUX
识别角色: designer, coder, qa, ui
证据来源:
- designer (得分:69) <- MD文件:关键词:design, MD文件:动词:设计, 描述:设计师
📌 AITA
识别角色: architect, designer, coder, qa
证据来源:
- architect (得分:53) <- MD文件:关键词:architecture, MD文件:动词:架构设计
📌 AICA
识别角色: coder, designer, qa, architect
证据来源:
- coder (得分:43) <- MD文件:关键词:coding, 描述:编码, 描述:生成
工具分配结果
| 工具类型 | 分配给 |
|---|---|
lark-* 业务工具 | AIBA(BA 角色) |
supabase / clerk | AITA, AICA(后端/架构) |
playwright / chrome-cdp | AIUIUX, AITA, AICA(测试) |
vercel-* 前端工具 | AIBA, AIUIUX, AITA(前端能力) |
frontend-design | AIBA, AIUIUX, AITA, AICA(全局设计) |
memory / one-search | 所有人(全局) |
无闲置工具
✅ 正在使用:
- chrome-cdp ← AIUIUX, AITA, AICA
- summarize-pro ← AIBA
- ui-ux-pro-max ← AIUIUX, AIBA, AITA
- playwright ← AIUIUX, AITA, AICA
- supabase ← AITA, AICA
……
⚠️ 可能闲置:0 个工具
Act:标准化与持续改进
成果固化
-
封装为 Skill:将工具命名为
tool-allocator,上传到 GitHub -
标准化使用流程:
# 安装 /cocoloop install tool-allocator # 同步分配 /tool-allocator sync # 检查闲置 /tool-allocator check -
文档完善:编写 SKILL.md 和 README.md,记录使用方法和配置选项
经验总结
| 教训 | 收获 |
|---|---|
| 不能仅靠名称推断职能 | 必须多维度综合分析 |
| 主观分配容易出错 | 用证据和得分量化决策 |
| 工具越多越容易闲置 | 自动化发现 + 智能匹配 |
| 硬编码规则不可扩展 | 基于能力的自适应匹配 |
未来改进方向
- 机器学习优化:根据工具实际使用情况自动调整权重
- 可视化配置:提供 Web 界面查看分配矩阵
- 冲突检测:检测两个工具功能重复,建议移除
- 使用率统计:追踪每个 Agent 实际使用了哪些工具
结语
这个项目源自我对"工具是否真的被用起来"的追问。最初的方案很简单,但随着问题深入,解决方案也越来越完善。
核心洞察:AI Agent 的工具分配不能依赖名称或描述的字面匹配,必须从 Agent 的实际行为(已有工具、动词使用、交付物描述)来推断其职能。
正如 PDCA 的精髓——持续改进。第一版方案虽然粗糙,但它指明了方向;第二版改进了描述分析;第三版才真正解决了问题。每一次迭代都让系统更接近"智能分配"的理想状态。
如果你也在管理多个 Agent 和大量工具,不妨试试这个方案。相信我,工具装得多不是问题,不知道怎么用才是。
关键词:OpenCode、Multi-Agent、MCP、Skill、工具管理、自动化配置