# Tool 管理 + Agent 工具授权 + 多模态 OCR 前置治理 实施文档 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 为 Neta 实现一套真正可落地的 Tool 治理体系,包括全局 Tool 管理、Agent 级 toolset/tool 授权、运行时统一 Tool 解析、Prompt Builder 接入、前端管理页面和后续多模态 OCR 接入的前置能力。 **Architecture:** 保留现有 `catalog.ts` 作为代码注册层,新增 `netaclaw_tool` 作为全局治理表,扩展 `netaclaw_agent` 的 `toolsets/tools` 配置,新增 `tool_registry.ts` 和 `tool_resolver.ts` 统一打通 catalog、DB 配置、Agent 授权、模型能力约束和运行时 Tool 实例组装。前端新增 Tool 管理页和 Agent 编辑页中的工具配置 Tab。Prompt Builder 改为消费 resolver 的结果,而不是静态推导工具列表。 **V1 Scope Constraint:** 首版 Agent 授权模型收敛为 `toolsets + tools.disabled`。`tools.enabled` 不进入首版实施,避免 UI、运行时、数据库语义同时过重。 **Tech Stack:** MySQL + TypeORM + Midway.js + Vue 3 + Element Plus + TypeScript **Spec:** `docs/superpowers/specs/2026-04-18-tool-management-and-agent-tool-governance-design.md` --- ## 一、实施范围 本实施覆盖以下内容: 1. 数据库表与字段设计落库 2. 后端 Tool 元数据同步与运行时解析 3. Agent 配置模型扩展 4. Prompt Builder 接入 Tool Resolver 5. 前端 Tool 管理页面 6. 前端 Agent 编辑页工具配置 7. 联调、验收、回滚预案 本实施不直接实现 OCR,但会为 OCR 接入完成全部前置基础设施。 --- ## 二、文件结构 ### 新增文件 | 文件 | 职责 | |------|------| | `packages/backend/src/modules/netaclaw/entity/tool.ts` | Tool 全局治理实体 | | `packages/backend/src/modules/netaclaw/service/tool_registry.ts` | catalog -> DB 同步、后台查询 | | `packages/backend/src/modules/netaclaw/service/tool_resolver.ts` | 运行时统一工具解析 | | `packages/backend/src/modules/netaclaw/controller/admin/tool.ts` | Tool 管理接口 | | `packages/frontend/src/modules/agent/views/tools.vue` | Tool 管理页面 | ### 修改文件 | 文件 | 改动 | |------|------| | `packages/backend/src/entities.ts` | 注册新实体 | | `packages/backend/src/modules/netaclaw/tools/catalog.ts` | 扩展 ToolSchema 元数据 | | `packages/backend/src/modules/netaclaw/tools/common.ts` | 对齐 visibility/capability 类型 | | `packages/backend/src/modules/netaclaw/entity/agent.ts` | 新增 `toolsets`、`tools` 字段 | | `packages/backend/src/modules/netaclaw/service/agent_executor.ts` | 改为使用 Tool Resolver | | `packages/backend/src/modules/netaclaw/gateway/server.ts` | 改为使用 Tool Resolver | | `packages/backend/src/modules/netaclaw/service/crew_orchestrator.ts` | 接入 Tool Resolver | | `packages/backend/src/modules/netaclaw/service/crew_delegate.ts` | 接入 Tool Resolver | | `packages/backend/src/modules/netaclaw/runtime/prompt_builder.ts` | 接入 resolved tool names + prompt hints | | `packages/backend/src/modules/netaclaw/runtime/prompt_guidance.ts` | 支持 tool prompt hint 注入 | | `packages/backend/src/modules/netaclaw/service/skill_context.ts` | 改为消费 resolver 输出的 builtin tool names | | `packages/backend/src/modules/netaclaw/controller/agent.ts` | previewPrompt 接入 resolver | | `packages/frontend/src/modules/agent/config.ts` | 新增 Tool 管理菜单 | | `packages/frontend/src/modules/agent/views/agent-edit.vue` | 新增“工具配置”Tab | | `packages/frontend/src/modules/agent/types/index.d.ts` | 扩展 Agent 类型定义 | --- ## 三、数据库实施 ## Task 1: 新增 Tool 治理表 **Files:** - Create: `packages/backend/src/modules/netaclaw/entity/tool.ts` - Modify: `packages/backend/src/entities.ts` - [ ] **Step 1: 创建 `tool.ts` Entity** ```typescript // packages/backend/src/modules/netaclaw/entity/tool.ts import { BaseEntity } from '../../base/entity/base.js'; import { Column, Entity, Index } from 'typeorm'; @Entity('netaclaw_tool') export class NetaClawToolEntity extends BaseEntity { @Index({ unique: true }) @Column({ comment: 'Tool 名称', length: 100 }) name: string; @Column({ comment: '展示名', length: 200, nullable: true }) label: string; @Index() @Column({ comment: '所属 toolset', length: 50 }) toolset: string; @Column({ comment: '描述', type: 'text', nullable: true }) description: string; @Column({ comment: '可见性', length: 20, nullable: true }) visibility: string; @Column({ comment: '能力要求', length: 20, nullable: true }) capability: string; @Index() @Column({ comment: '状态 0=禁用 1=启用', default: 1 }) status: number; @Column({ comment: '是否核心工具', default: 0 }) isCore: number; @Column({ comment: '是否允许禁用', default: 1 }) canDisable: number; @Column({ comment: 'Prompt Hint 覆写', type: 'text', nullable: true }) promptHint: string; @Column({ comment: '排序', default: 0 }) sort: number; @Column({ comment: '扩展字段', type: 'json', nullable: true }) extra: Record; } ``` 说明: - `toolset/visibility/capability/isCore/canDisable` 属于代码注册镜像字段 - 后台只允许修改 `label/description/status/promptHint/sort/extra` - 不允许将运行时能力语义下放为运营配置 - [ ] **Step 2: 在 `entities.ts` 注册 Entity** 仿照现有模式添加: ```typescript import * as entityXX from './modules/netaclaw/entity/tool'; ``` 并在 `entities` 数组中追加: ```typescript ...Object.values(entityXX), ``` - [ ] **Step 3: 启动后端验证表创建** Run: `cd packages/backend && npx midway-bin dev` Expected: - `netaclaw_tool` 自动建表成功 - [ ] **Step 4: 提交** ```bash git add packages/backend/src/modules/netaclaw/entity/tool.ts packages/backend/src/entities.ts git commit -m "feat(netaclaw): add netaclaw_tool entity for global tool governance" ``` --- ## Task 2: 扩展 Agent 表 **Files:** - Modify: `packages/backend/src/modules/netaclaw/entity/agent.ts` - [ ] **Step 1: 新增 `toolsets` 和 `tools` 字段** 在 `NetaClawAgentEntity` 中新增: ```typescript @Column({ type: 'json', comment: '启用的 toolset 列表', nullable: true }) toolsets: string[]; @Column({ type: 'json', comment: '工具精细配置', nullable: true }) tools: { disabled?: string[]; }; ``` - [ ] **Step 2: 启动后端验证字段增加** Expected: - `netaclaw_agent` 表新增 `toolsets`、`tools` - [ ] **Step 3: 提交** ```bash git add packages/backend/src/modules/netaclaw/entity/agent.ts git commit -m "feat(netaclaw): extend agent entity with toolsets and tools config" ``` --- ## 四、后端基础设施实施 ## Task 3: 扩展 catalog 元数据 **Files:** - Modify: `packages/backend/src/modules/netaclaw/tools/catalog.ts` - Modify: `packages/backend/src/modules/netaclaw/tools/builtin/*.ts`(按需) - [ ] **Step 1: 扩展 `ToolSchema`** 将: ```typescript export interface ToolSchema { name: string; toolset: string; description: string; } ``` 改为: ```typescript export interface ToolSchema { name: string; toolset: string; description: string; visibility?: 'internal' | 'tool' | 'skill'; capability?: 'text' | 'vision' | 'multimodal'; isCore?: boolean; canDisable?: boolean; supportsPromptHint?: boolean; } ``` - [ ] **Step 2: 增加 catalog 查询方法** 新增: ```typescript export function getAllToolSchemas(): ToolSchema[] { ... } export function getToolSchema(name: string): ToolSchema | undefined { ... } export function getToolNamesByToolset(toolset: string): string[] { ... } ``` - [ ] **Step 3: 为核心工具补默认元数据** 至少给以下工具补齐: - `bash` - `read_file` - `write_file` - `list_dir` - `patch` - `clarify` - `todo` 建议规则: - `base` 工具默认 `capability=text` - `clarify/todo` 默认 `isCore=1` - `todo` 可 `visibility=internal` - `clarify` 可 `visibility=tool` - [ ] **Step 4: 预留 `vision` / `document` toolset 常量** 不必现在接入 OCR,只需允许这些 toolset 名存在。 - [ ] **Step 5: 编译验证** Run: `cd packages/backend && npm run build` - [ ] **Step 6: 提交** ```bash git add packages/backend/src/modules/netaclaw/tools/catalog.ts packages/backend/src/modules/netaclaw/tools/builtin git commit -m "feat(netaclaw): extend tool catalog metadata for governance" ``` --- ## Task 4: 新增 Tool Registry Service **Files:** - Create: `packages/backend/src/modules/netaclaw/service/tool_registry.ts` - [ ] **Step 1: 创建 Service** 职责: 1. 读取 catalog 全量工具 2. 同步到 `netaclaw_tool` 3. 分页查询 4. 返回 Agent 配置可选工具 建议结构: ```typescript @Provide() @Scope(ScopeEnum.Singleton) export class NetaClawToolRegistryService { @InjectEntityModel(NetaClawToolEntity) toolRepo: Repository; async syncCatalogToDb() { ... } async page(params) { ... } async info(id: number) { ... } async update(data) { ... } async all() { ... } async listForAgentConfig() { ... } } ``` - [ ] **Step 2: 实现 `syncCatalogToDb()`** 逻辑: 1. 读取 `getAllToolSchemas()` 2. DB 无记录则插入 3. DB 已有记录则保留人工字段,仅补齐缺失元数据 4. catalog 中不存在但 DB 中存在的记录不物理删除 启动策略: - 后端启动时自动执行一次幂等 `syncCatalogToDb()` - `/admin/netaclaw/tool/sync` 仅作为人工刷新入口 - 不允许把首屏正确性依赖在手工点击同步按钮上 默认回填规则: - `label = name` - `status = 1` - `capability = schema.capability ?? 'text'` - `visibility = schema.visibility ?? 'tool'` - `isCore = schema.isCore ? 1 : 0` - `canDisable = schema.canDisable ?? (schema.isCore ? 0 : 1)` - [ ] **Step 3: 实现 `update()` 的保护逻辑** 要求: - `isCore=1 && canDisable=0` 时,禁止将 `status` 改为 0 - `name/toolset/visibility/capability/isCore/canDisable` 默认不允许后台修改 - 若 `supportsPromptHint !== true`,则禁止写入 `promptHint` - [ ] **Step 4: 编译验证** - [ ] **Step 5: 提交** ```bash git add packages/backend/src/modules/netaclaw/service/tool_registry.ts git commit -m "feat(netaclaw): add tool registry service for catalog-db sync" ``` --- ## Task 5: 新增 Tool Resolver Service **Files:** - Create: `packages/backend/src/modules/netaclaw/service/tool_resolver.ts` - [ ] **Step 1: 创建解析接口** ```typescript interface ResolveToolParams { agent: NetaClawAgentEntity | null; modelCapability?: 'text' | 'vision' | 'multimodal'; memoryEnabled?: boolean; hasSkills?: boolean; crewRole?: 'master' | 'sub'; } interface ResolveToolResult { tools: AnyAgentTool[]; toolNames: string[]; builtinToolNames: string[]; toolPromptHints: Record; disabledReasons: Array<{ name: string; reason: string }>; } ``` - [ ] **Step 2: 实现 toolset 展开逻辑** 默认规则: 1. 老 Agent 无 `toolsets` 时: - 使用 `TOOLSET_DEFAULTS` 2. 有 `toolsets` 时: - 按 `toolsets` 从 catalog 展开 3. 再剔除 `tools.disabled` - [ ] **Step 3: 实现全局 Tool 配置过滤** 从 `netaclaw_tool` 查询配置,过滤: - `status=0` - 不满足场景约束 - [ ] **Step 4: 实现 capability 过滤** 统一判断: ```typescript function matchCapability(toolCap: string, modelCap?: string): boolean { ... } ``` 规则: - `text` 工具允许任意模型 - `vision` 工具要求 `vision|multimodal` - `multimodal` 工具要求 `multimodal` - [ ] **Step 4.1: 补齐模型能力来源** 要求: - 优先在 `model_channel.ts` 的运行时解析接口中直接返回 `capability` - `agent_executor.ts` / `gateway/server.ts` / `crew_*` 禁止各自重复解析模型能力 - 若 Agent 未绑定 channel,需定义统一 fallback: - 显式配置 capability 时用显式值 - 未配置时按 `text` 处理,并在 disabledReasons 中保留解释能力 - [ ] **Step 5: 组装运行时工具实例** 这里不要复刻 Hermes 的 handler registry。 Neta 应继续按现有工厂方式组装: - 静态工具: - `bashTool` - `readFileTool` - `writeFileTool` - `listDirTool` - `patchTool` - `clarifyTool` - Memory 工具: - 在 `memoryEnabled` 时工厂创建 - Skill 工具: - 在 `hasSkills` 时工厂创建 - Crew 工具: - 在 `crewRole=master` 时工厂创建 - [ ] **Step 5.1: 输出 `builtinToolNames` 给 skill context** 要求: - resolver 需要区分“所有注入工具名”和“提供给 skill system 的 builtin tool names” - `buildSkillContext()` 不再使用硬编码 builtin 列表 - [ ] **Step 6: 输出 `toolPromptHints`** 从 `netaclaw_tool.promptHint` 收集: ```typescript { patch: '...', clarify: '...' } ``` - [ ] **Step 7: 编译验证** - [ ] **Step 8: 提交** ```bash git add packages/backend/src/modules/netaclaw/service/tool_resolver.ts git commit -m "feat(netaclaw): add tool resolver for runtime tool governance" ``` --- ## Task 6: 新增 Tool 管理 Controller **Files:** - Create: `packages/backend/src/modules/netaclaw/controller/admin/tool.ts` - [ ] **Step 1: 创建 Admin Controller** 接口: - `/admin/netaclaw/tool/page` - `/admin/netaclaw/tool/info` - `/admin/netaclaw/tool/update` - `/admin/netaclaw/tool/all` - `/admin/netaclaw/tool/sync` - `/admin/netaclaw/tool/forAgent` - [ ] **Step 2: `sync` 接口调用 `syncCatalogToDb()`** 建议首次进入页面前手动调用一次,也可在服务启动时懒同步。 - [ ] **Step 3: 启动后端验证接口可达** - [ ] **Step 4: 提交** ```bash git add packages/backend/src/modules/netaclaw/controller/admin/tool.ts git commit -m "feat(netaclaw): add admin tool controller" ``` --- ## 五、运行时接入实施 ## Task 7: 改造 agent_executor.ts **Files:** - Modify: `packages/backend/src/modules/netaclaw/service/agent_executor.ts` - [ ] **Step 1: 注入 `NetaClawToolResolverService`** 新增: ```typescript @Inject() toolResolver: NetaClawToolResolverService; ``` - [ ] **Step 2: 删除 `defaultTools` 硬编码依赖** 从: ```typescript private readonly defaultTools: AnyAgentTool[] = [...] ``` 迁移为 resolver 统一输出。 - [ ] **Step 3: 在解析模型后得到 `modelCapability`** 从当前 channel / modelConfig 推导 capability: 1. 优先调用 `model_channel.ts` 统一运行时解析接口 2. 直接拿到 `capability` 3. 禁止在 executor 内手写重复解析逻辑 - [ ] **Step 4: 调用 resolver** ```typescript const resolvedTools = await this.toolResolver.resolve({ agent: agentEntity, modelCapability, memoryEnabled: !!memoryConfig?.enabled, hasSkills: !!agentEntity.skills?.length, }); ``` - [ ] **Step 5: 将 `resolvedTools.builtinToolNames` 传给 `buildSkillContext()`** 替换现在的硬编码: ```typescript const builtinToolNames = ['bash', 'read_file', 'write_file', 'list_dir', 'patch']; ``` -- [ ] **Step 6: 将 `resolvedTools.toolNames` 传给 Prompt Builder** 替换现在的: ```typescript collectAvailableToolNames(...) ``` 为: ```typescript availableToolNames: resolvedTools.toolNames ``` - [ ] **Step 7: 将 `resolvedTools.tools` 传给 runAgent** - [ ] **Step 8: 编译验证** - [ ] **Step 9: 提交** ```bash git add packages/backend/src/modules/netaclaw/service/agent_executor.ts git commit -m "refactor(netaclaw): agent executor uses tool resolver" ``` --- ## Task 8: 改造 gateway/server.ts **Files:** - Modify: `packages/backend/src/modules/netaclaw/gateway/server.ts` - [ ] **Step 1: 注入 Tool Resolver** - [ ] **Step 2: 替换默认工具拼装** 要求: - WS 路径与 REST 路径使用相同解析逻辑 - 不再各自维护工具集合 - [ ] **Step 3: Prompt Builder 改用 resolved tool names** - [ ] **Step 4: 编译验证** - [ ] **Step 5: 提交** ```bash git add packages/backend/src/modules/netaclaw/gateway/server.ts git commit -m "refactor(netaclaw): gateway uses tool resolver" ``` --- ## Task 9: 改造 crew_orchestrator.ts / crew_delegate.ts **Files:** - Modify: `packages/backend/src/modules/netaclaw/service/crew_orchestrator.ts` - Modify: `packages/backend/src/modules/netaclaw/service/crew_delegate.ts` - [ ] **Step 1: master 场景接入 resolver** `crewRole='master'` - [ ] **Step 2: sub 场景接入 resolver** `crewRole='sub'` - [ ] **Step 3: 验证 `delegate_*` 只在 master 中出现** - [ ] **Step 4: 编译验证** - [ ] **Step 5: 提交** ```bash git add packages/backend/src/modules/netaclaw/service/crew_orchestrator.ts packages/backend/src/modules/netaclaw/service/crew_delegate.ts git commit -m "refactor(netaclaw): crew runtime uses tool resolver" ``` --- ## 六、Prompt Builder 实施 ## Task 10: prompt_builder.ts 接入 Tool Prompt Hint **Files:** - Modify: `packages/backend/src/modules/netaclaw/runtime/prompt_builder.ts` - Modify: `packages/backend/src/modules/netaclaw/runtime/prompt_guidance.ts` - Modify: `packages/backend/src/modules/netaclaw/service/skill_context.ts` - Modify: `packages/backend/src/modules/netaclaw/controller/agent.ts` - [ ] **Step 1: 扩展 `getToolBehaviorGuidance()`** 从: ```typescript getToolBehaviorGuidance(toolNames: string[]) ``` 改为: ```typescript getToolBehaviorGuidance( toolNames: string[], toolPromptHints?: Record ) ``` 逻辑: - 若某 Tool 有 DB `promptHint` 覆写,则优先使用覆写 - 否则回退默认 guidance - [ ] **Step 2: Prompt Builder 接收 `toolPromptHints`** 在 `BuildSystemPromptParams` 中新增: ```typescript toolPromptHints?: Record; ``` - [ ] **Step 3: skill_context 改为消费 resolver 输出** 要求: - `buildSkillContext()` 的 builtin tool names 参数由 resolver 提供 - 不能再保留硬编码 builtin 工具列表 - [ ] **Step 4: previewPrompt 接口接入 resolver** 让预览接口返回: - `layers` - `toolNames` - `disabledReasons` 这样前端可解释“为什么某工具没有被注入”。 - [ ] **Step 5: 编译验证** - [ ] **Step 6: 提交** ```bash git add packages/backend/src/modules/netaclaw/runtime/prompt_builder.ts packages/backend/src/modules/netaclaw/runtime/prompt_guidance.ts packages/backend/src/modules/netaclaw/service/skill_context.ts packages/backend/src/modules/netaclaw/controller/agent.ts git commit -m "feat(netaclaw): prompt builder supports resolved tools and prompt hints" ``` --- ## 七、前端实施 ## Task 11: 新增 Tool 管理菜单 **Files:** - Modify: `packages/frontend/src/modules/agent/config.ts` - [ ] **Step 1: 在 Skill 管理上方插入路由** ```typescript { path: '/agent/tools', meta: { label: 'Tool 管理' }, component: () => import('./views/tools.vue') }, ``` - [ ] **Step 2: 本地验证菜单顺序** - [ ] **Step 3: 提交** ```bash git add packages/frontend/src/modules/agent/config.ts git commit -m "feat(frontend): add tool management route" ``` --- ## Task 12: 实现 Tool 管理页 **Files:** - Create: `packages/frontend/src/modules/agent/views/tools.vue` - [ ] **Step 1: 创建页面骨架** 包含: - 筛选区 - 表格区 - 编辑抽屉 - 同步按钮 - [ ] **Step 2: 对接接口** 使用: - `/admin/netaclaw/tool/page` - `/admin/netaclaw/tool/update` - `/admin/netaclaw/tool/sync` - [ ] **Step 3: 页面字段** 表格列: - name - label - toolset - capability - visibility - isCore - status - promptHint 状态 - [ ] **Step 4: 编辑抽屉** 允许编辑: - label - description - status - promptHint - sort 只读: - name - toolset - capability - visibility - isCore - canDisable - [ ] **Step 5: 对核心工具加禁用保护** 前端禁用开关,后端再次校验。 - [ ] **Step 6: 浏览器验证** 验证: - 页面可打开 - 同步后出现工具列表 - 可编辑提示词 - 核心工具不能关闭 - [ ] **Step 7: 提交** ```bash git add packages/frontend/src/modules/agent/views/tools.vue git commit -m "feat(frontend): add tool management page" ``` --- ## Task 13: 扩展前端 Agent 类型 **Files:** - Modify: `packages/frontend/src/modules/agent/types/index.d.ts` - [ ] **Step 1: 为 AgentInfo 增加字段** 新增: ```typescript toolsets?: string[]; tools?: { disabled?: string[]; }; ``` - [ ] **Step 2: 编译验证** - [ ] **Step 3: 提交** ```bash git add packages/frontend/src/modules/agent/types/index.d.ts git commit -m "feat(frontend): extend agent types with toolsets and tools" ``` --- ## Task 14: 改造 agent-edit.vue **Files:** - Modify: `packages/frontend/src/modules/agent/views/agent-edit.vue` - [ ] **Step 1: 新增“工具配置”Tab** 位置: - 与 `Skill配置` 平级 - [ ] **Step 2: 新增 toolset 多选区** 数据源: - `/admin/netaclaw/tool/forAgent` 从接口中提取唯一 toolset 列表。 - [ ] **Step 3: 新增工具精细控制双栏** 展示: - 可用工具 - 已禁用覆盖 最小实现建议: - 左栏: 可选工具 - 右栏: 已禁用工具 通过 `toolsets` 先决定默认启用范围,`tools.disabled` 做剔除。 - [ ] **Step 4: loadAgent 回填** 回填: - `toolsets` - `tools.disabled` - [ ] **Step 5: handleSave 提交** 请求体追加: ```typescript toolsets: form.value.toolsets, tools: form.value.tools, ``` - [ ] **Step 6: Prompt 预览展示被过滤工具** 若后端 previewPrompt 返回: - `toolNames` - `disabledReasons` 则页面增加一个提示区域显示。 - [ ] **Step 7: 浏览器验证** 验证: - 可勾选 toolsets - 可禁用单工具 - 保存后再次打开可回填 - preview 可看到过滤原因 - [ ] **Step 8: 提交** ```bash git add packages/frontend/src/modules/agent/views/agent-edit.vue git commit -m "feat(frontend): add agent toolsets and tools configuration tab" ``` --- ## 八、联调与验收 ## Task 15: 数据同步验证 - [ ] **Step 1: 启动后端** - [ ] **Step 2: 调用 `/admin/netaclaw/tool/sync`** Expected: - `netaclaw_tool` 中出现 catalog 全量工具 - [ ] **Step 3: 检查核心字段** 至少检查: - `todo` - `clarify` - `bash` - `read_file` - `patch` --- ## Task 16: Agent 工具授权联调 - [ ] **Step 1: 新建一个 Agent** 配置: - `toolsets = ['base', 'planning']` - `tools.disabled = ['bash']` - [ ] **Step 2: 预览 Prompt** Expected: - `bash` 不在 toolNames 中 - `read_file/write_file/list_dir/patch/todo` 仍在 - [ ] **Step 3: 发起真实对话** 构造任务要求执行 bash。 Expected: - 模型看不到 `bash` - 不应产生 bash tool call --- ## Task 17: capability 过滤联调 - [ ] **Step 1: 准备一个 text 模型 Agent** - [ ] **Step 2: 准备一个代码注册层声明 `capability=vision` 的测试 Tool** 要求: - 不通过后台或 DB 手工修改 `capability` - 若暂时没有真实视觉工具,可在本地临时注册一个测试 Tool 用于联调 - [ ] **Step 3: 预览 Prompt** Expected: - 该工具被过滤 - disabledReasons 中出现 `capability_mismatch` --- ## Task 18: Tool Prompt Hint 联调 - [ ] **Step 1: 在 Tool 管理页给 `patch` 写入 promptHint** - [ ] **Step 2: 预览 Prompt** Expected: - Layer 4 中优先出现 DB 覆写内容,而不是默认 guidance --- ## 九、验收标准 以下全部满足才算完成: ### 数据库 - `netaclaw_tool` 表存在 - `netaclaw_agent` 新增 `toolsets/tools` ### 后端 - catalog 可同步到 DB - Tool Resolver 成为统一事实来源 - `model_channel.ts` 统一提供运行时 `capability` - REST/WS/Crew 三条路径都走 resolver - skill_context 消费 resolver 输出的 builtin tool names - previewPrompt 可返回 toolNames 和 disabledReasons ### 前端 - 出现 Tool 管理菜单与页面 - Tool 管理页可编辑全局状态和 promptHint - Agent 编辑页可配置 toolsets 与单工具覆盖 - Prompt 预览能看到工具生效与过滤原因 ### 行为 - 全局禁用的工具不会被注入 - Agent 禁用的工具不会被注入 - capability 不满足的工具不会被注入 - 核心不可禁用工具不能被后台关闭 --- ## 十、回滚预案 若某阶段出问题,按以下顺序回滚。 ### 1. 页面级回滚 - 隐藏 `/agent/tools` - 隐藏 Agent 编辑页中的“工具配置”Tab 不影响现有 Agent 基本能力。 ### 2. 运行时回滚 若 resolver 逻辑异常,可临时回退: - `agent_executor.ts` 恢复 `defaultTools` - `gateway/server.ts` 恢复原工具拼装 数据库结构可保留,不影响运行。 ### 3. 数据级回滚 - `netaclaw_tool` 表可保留 - `toolsets/tools` 字段即使存在,也不影响老代码 因此本方案具备较好的渐进式上线条件。 --- ## 十一、实施顺序建议 建议严格按以下顺序推进: 1. 数据库实体 2. catalog 扩展 3. tool_registry 4. tool_resolver 5. model capability 统一解析链路 6. agent_executor / gateway / crew 接入 7. prompt_builder / skill_context 接入 7. Tool 管理页 8. Agent 编辑页工具配置 9. 联调验收 不要先做前端页面。否则会出现“配置存在但运行时无效”的假闭环。 --- ## 十二、后续 OCR 接入说明 当本实施完成后,接入 OCR 的工作将降维为一项普通功能开发: 1. 在 `catalog.ts` 注册 `vision_ocr` 2. 设置: - `toolset='vision'` - `capability='vision'` 3. 在 Tool 管理页全局启用 4. 在 Agent 工具配置中勾选 5. 由 resolver 自动判断模型是否支持 也就是说,这份实施文档完成后,OCR 不再是架构问题,而只是业务工具实现问题。