2026-05-20 21:39:12 +08:00

176 lines
9.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 工具系统
created: 2026-04-13
updated: 2026-05-15
type: entity
tags: [tool, agent, runtime, backend]
sources: [packages/backend/src/modules/netaclaw/tools/, packages/backend/src/modules/netaclaw/tools/operations/, packages/backend/src/modules/netaclaw/service/tool_resolver.ts, packages/backend/src/modules/netaclaw/service/tool_registry.ts, packages/backend/src/modules/netaclaw/subagent/worker_tools.ts, packages/backend/src/modules/netaclaw/gateway/tool_risk.ts]
---
# 工具系统
工具系统是 Agent 可调用能力的实现层。当前 NetaClaw 工具架构分为五层:
```text
工具实现
-> Tool Operations
-> Tool Catalog
-> Tool Governance / Resolver
-> Tool Manifest / Runtime Policy
```
其中工具实现层关注参数语义和结果格式,[[tool-operations]] 关注底层文件/进程/搜索后端,[[tool-governance]] 关注“是否允许、如何投影、如何被前端理解”,[[tool-runtime-policy]] 关注“在主进程或子进程里怎么安全执行”。
## 工具接口
运行时工具一般具备:
```typescript
interface AnyAgentTool {
name: string;
description: string;
inputSchema: object;
execute: (args: unknown) => Promise<string | Record<string, unknown>>;
}
```
模型输出 `tool_use` 后,`runAgent` 会从 resolver 提供的工具集合中查找并执行对应工具。当前工具执行结果除了传统字符串结果,还可能携带结构化 `rawResult`,供 WebSocket 和前端渲染层展示文本、JSON、图片等不同结果形态。
## 内置工具分组
| 分组 | 工具 | 说明 |
| --- | --- | --- |
| 文件/搜索 | `read_file``write_file``list_dir``find_files``grep` | workspace 文件读写与检索 |
| Shell | `bash` | 命令执行,受 policy 控制 |
| 编辑 | `edit``patch` | 精确编辑与补丁应用 |
| Skill | `read_skill``read_skill_file``skill_manage``execute_skill` | 技能读取、管理和 compute-entry 执行 |
| Memory | `memory_save``memory_recall` | 长期记忆写入与检索 |
| AIGC | `text_to_image``image_to_image` | 文生图、图生图和图片结果持久化,详见 [[image-generation-tools]] |
| 委派 | `delegate_task``delegate_parallel` | 子 Agent 委派,详见 [[subagent-session]] |
| 微信桌面 | `weixin_send_text` | 通过 [[desktop-op-module]] 在 PC 微信目标群发送文本 |
| MySQL 问数 | `mysql_list_sources``mysql_schema``mysql_table_sample``mysql_query` | 授权 MySQL 数据源的只读 schema、样例和 SQL 查询 |
| 交互 | `clarify``escalate` | 澄清与升级 |
| Todo | `todo` | 会话级任务状态 |
## 主 Agent 执行
主 Agent 的工具调用链路:
```text
LLM 输出 tool_use
-> runAgent 解析工具名和参数
-> ToolResolver 提供可执行工具 Map
-> tool.execute(args)
-> 产生 tool_result
-> 写入 session tree message entry
-> WebSocket 推送 tool_call/tool_result
```
2026-05-02 后Gateway 会在真正执行 bash 前调用 `gateway/tool_risk.ts` 做风险检测。命中 `rm``del``rd``rmdir``drop table``git reset --hard``git clean -f``git push --force` 等模式时,会先推送 `tool_confirmation_request`,等待前端返回 `tool_confirmation_response`;用户拒绝则该工具调用不会执行。
## Operations 注入
文件、搜索、编辑和 bash 类工具现在通过 [[tool-operations]] 访问底层系统能力:
- `read_file``write_file``list_dir` 使用 `FileOperations`
- `edit``patch` 使用 `FileOperations` 和写队列。
- `find_files``grep` 使用 `SearchOperations`
- `bash` 使用 `ProcessOperations`
`tool_resolver.ts` 在构造工具列表时注入 `operations?: ToolOperations`;未提供时使用 `getDefaultOperations()` 的本地实现。这让测试可以用 mock operations也为后续远程 workspace / 沙箱后端留出替换点。
## 子 Agent 执行
子 Agent worker 不会默认拥有所有工具。工具按 manifest 和 runtime policy 分为:
- 本地 worker 工具:适合只读、低风险、可在子进程直接执行。
- 主进程代理工具:需要父进程执行,例如写文件、技能管理、记忆写入。
- 禁用工具:当前策略下不允许执行。
详见 [[tool-runtime-policy]]。
主进程与子进程之间的边界已经进一步明确:
- 子 Agent 使用的不是“主 Agent 全量工具复制品”,而是 resolver 结合 `allowedToolNames`、workspace roots、shell/readonly 策略、manifest 路由之后裁剪出的工具集。
- `delegate_task` / `delegate_parallel` 会把 `toolRuntimeRoutes` 一并带入子 Agent 批次与回放数据,前端据此显示当前任务到底是 `worker-local``main-process-proxy` 还是 `disabled`
- 某个工具能否进入子 Agent不只看它是否启用还要看它的 `effectiveSubagentAllowed``workerRoutingHint` 和运行时 blocked reason。
## Catalog 与治理
`Tool Catalog` 提供工具静态 schema 和基础元数据。`Tool Governance` 把 catalog 同步到 DB支持全局启停、核心工具、Agent 局部覆盖和 Prompt Hint。
这意味着工具实现文件不应直接决定最终可见性;最终口径以 resolver 输出为准。
当前 resolver 的核心输出已经不只是工具名:
- `toolNames`: 最终允许进入 prompt / runtime 的工具集合。
- `toolPromptHints`: Prompt Builder 消费的行为提示。
- `toolManifest`: 子进程安全执行需要的 manifest。
- `toolRuntimeRoutes`: 每个工具在当前会话/Agent 下的实际运行路由。
- `disabledReasons`: 被过滤工具的解释。
因此“工具有没有生效”不能只查内置文件是否存在,必须看 resolver 的最终投影。
## 过程事件
2026-05-07 后,长耗时工具和 compute-entry Skill 可以通过 [[runtime-process-events]] 输出阶段进度。工具执行链路会为一次调用分配 `operationId`,过程事件可以被 WebSocket 流式推送,也可以采样写入 session metadata并把完整 JSONL 日志落到 dataDir。
这条链路主要服务:
- [[vehicle-damage-skill]] 的抽帧、检测、定位和复核过程。
- `execute_skill` 对 compute-entry 子进程过程事件的桥接。
- 前端对话页的 `tool-process-timeline.vue` 历史回放。
## weixin_send_text
2026-05-14 新增的 `weixin_send_text` 属于 `weixin_desktop` toolset是 weixin-db 群聊自动回复的发送工具。
执行要点:
- `channelId` 优先从 `_netaRuntime.bizContext.channelId` 读取,其次才接受显式参数。
- `modelChannelId` 来自 `_netaRuntime.currentAgent.modelChannelId`,即桌面操作 Agent 自己的模型渠道。
- 只允许在 channel 的 `config.weixinReply.enabled=true` 时执行。
- 支持 `suffix``zero-width``none` 三种水印策略。
- 创建 `DesktopTask(appId="weixin", actionType="send-text")` 后调用 `DesktopOpService.runAndWait()`,默认最多等待 60 秒。
这类工具应配置为子 Agent 可用且强制走主进程代理,因为真正的键鼠和窗口操作必须留在主进程控制边界内。
## MySQL 问数工具
2026-05-15 新增的 `mysql` toolset 提供只读智能问数后端能力:
- `mysql_list_sources`:列出当前 Agent 授权的数据源摘要,不返回 host、用户名、密码或连接串。
- `mysql_schema`:读取授权表的字段、索引、主键、外键和脱敏标记。
- `mysql_table_sample`:读取授权表的少量未脱敏字段样例,用于判断字段含义和 JOIN key。
- `mysql_query`:执行经过 guard 校验的只读 `SELECT`,支持授权表范围内的显式 JOIN并写入查询审计。
MySQL 工具在子 Agent manifest 中统一走 `main-process-proxy`。数据库连接、密钥解密、SQL guard、脱敏列拒绝、行数限制和审计都留在主进程服务侧worker 只看到工具 manifest 与代理路由。
这组工具的完整配置面和服务端安全边界见 [[mysql-data-source]]。其中几个容易误判的实现细节是:`mysql_schema` 会拆开读取 `information_schema.TABLES``information_schema.COLUMNS`,避免把 `TABLE_COMMENT` 当作字段元数据;`mysql_table_sample` 用小写映射做权限校验但保留原始列名执行,兼容 `tenantId` 这类驼峰列;`mysql_query` 允许单个末尾分号并在执行前规范化,但真实多语句仍会被 guard 拒绝。
## 前端渲染
前端工具展示不直接硬编码每个工具的 UI。当前实现是
- 工具调用渲染通过 `renderer-registry.ts` 注册。
- `runtime-policy.ts` 负责把后端路由状态投影成页面展示。
- 工具管理页和 Agent 编辑页都消费后端 `runtimeDiagnostic` projection。
- 对话页除了一般工具调用卡片,还会结合 `tool_call_started` / `tool_result_streamed` / `tool_call_completed` 事件展示运行中状态。
这可避免工具新增后只写后端、前端看不到或文案不一致。
## 相关页面
- [[tool-governance]]
- [[tool-runtime-policy]]
- [[tool-operations]]
- [[tool-catalog]]
- [[mysql-data-source]]
- [[image-generation-tools]]
- [[runtime-process-events]]
- [[desktop-op-module]]
- [[agent-runtime]]
- [[subagent-session]]
- [[frontend-architecture]]
- [[prompt-builder]]