Skip to content

工具选择、技能与安全执行 ​

工具和 Skill 是 Agent 把模型输出转换为外部动作的边界。模型只能提出工具调用;真正能否执行,要经过 Agent 配置、能力策略、参数 Schema、租户上下文、超时、幂等 journal 和必要的 HITL。

1. 工具来源与统一形态 ​

来源注册/发现运行时执行器典型场景
本地 Spring/内置工具@Tool、BuiltinShellDispatcher本地方法、DocSpace/VFS/SandboxTODO、文件、命令
数据库业务工具ai_tool + serviceTypeToolExecutorFactoryFeign、HTTP、Java 服务
Feign 工具@FeignToolRegistration 启动扫描FeignToolExecutor内部微服务调用
远程 MCPNacos/Registry + tools/listMcpRemoteToolExecutor、McpNacosToolExecutor外部能力服务
平台 Web SearchAgent 配置之外的能力策略WebSearchBuiltinDispatcher联网搜索

统一工具描述至少包含 name、description、参数 JSON Schema、serviceType、endpoint/方法、timeout、权限标签和 side-effect 级别。同步到 ai_tool 不代表所有 Agent 都能调用,还必须在 Agent 的 toolIds 或绑定关系中授权。

2. 工具进入模型前的过滤 ​

LoadAgentConfigNode 解析 Agent 工具并把平台 web_search 从普通工具列表移除。LoopInit 再根据当前 Agent、Web Search 模式、Sandbox/VFS 能力和用户上下文构造模型可见的 tool specifications。

过滤顺序应理解为:

text
数据库存在
  -> Agent 已绑定
  -> 工具启用且版本有效
  -> 当前租户/用户有权限
  -> 当前 session 能提供依赖(MCP、Sandbox、文件房间)
  -> 当前 WebSearchMode/side-effect 策略允许
  -> 生成 JSON Schema 给 LLM

缺少任何一层都不能把工具描述交给模型,否则模型会不断调用一个运行时必然失败的工具。

3. 工具调用节点执行链 ​

ToolCallNode.executeDirect 有三条优先级:

  1. 有 session 时先交给 BuiltinShellDispatcher,处理 DocSpace、Sandbox、VFS 工具。
  2. 再由 WebSearchBuiltinDispatcher 处理平台搜索,并校验 WebSearchMode 与平台能力。
  3. 最后查询 AiToolEntity,由 ToolExecutorFactory 按 serviceType 选择业务执行器。

业务工具执行有外层超时线程池,默认超时 60 秒;工具实体的正数 timeoutMs 会覆盖默认值。底层调用失败后最多三次尝试,最终转换为“执行失败: …”结果,并写 structured block、工具日志和 Agent 结果。轻量 executeDirect 与 Agentic Loop 入口不同:前者没有完整 state 时不能执行平台 Web Search,也不能依赖 HITL。

4. 智能体循环的日志与幂等 ​

LoopActingNode 对每个 ToolExecutionRequest 以 toolCallId 为幂等键:

text
读取 ToolExecutionJournal
  -> COMPLETED:复用结果
  -> STARTED + 有副作用:结果未知,进入恢复审批
  -> 未执行:写 STARTED
  -> 调用工具
  -> 成功写 COMPLETED / 失败写 FAILED
  -> 写 ToolResultStore 和 ToolExecutionResultMessage

内存 ToolResultStore 用于同一 runtime 的快速复用;journal 用于进程退出或 checkpoint 恢复。副作用调用不能只靠模型重复产生相同参数来判断安全,因为远端系统可能已经写入。

5. 高风险与人在回路(HITL) ​

当前检测规则覆盖递归删除、DROP TABLE、TRUNCATE、git push --force、git reset --hard 等模式,也会拦截上次进程退出时状态为 STARTED 的副作用工具。命中后 state 写入:

text
hitlPending=true
hitlRequest={requestType, promptMessage, toolName, toolCallId,
             toolParams, triggerReason, iteration}

图在 human_review 前中断。当前 /resume 请求只有 clientMessageId 和补充 message;普通工具恢复时 LoopHumanReviewNode 生成 approved=true 并带回原 toolCallId,checkpoint 暂停恢复不会批准工具。新增高风险工具时要明确 side-effect level、审批文本、拒绝策略和恢复后的下一节点。

6. 内置工具分发 ​

内置名称委托节点/服务关键状态
UPDATE_TODO_LISTTaskTodoManagertaskTodoList、todoUpdated
RAG_SEARCHRagNodetaskExecutionResult
SKILL_CALLSkillCallNodeactiveSkill*、执行结果
SUB_AGENT_CALL / SUBMIT_SUBAGENT_TASKSubAgentCallNodetaskId、父子会话回调
CHECK_TASK_STATUSCheckTaskStatusNode子任务状态
READ_TOOL_RESULTToolResultStore按 toolCallId 读取大结果片段
PUBLISH_FILEChatArtifactServiceArtifact 关系和产物事件
Shell/DocSpace/Sandbox/VFSToolCallNode/内置 dispatcherworkspace、命令和文件事件

7. 技能调用协议 ​

SkillCallNode 先从 currentTask.targetResource 读取名称;名称为空时按任务描述在 Agent 的 skills 列表中匹配。命中后:

  1. 校验 Skill 已绑定到 Agent。
  2. 通过 ISkillService.getSkillDetail 获取当前详情。
  3. 官方 Skill 使用发布版本的 skillContent,并展示 runtimePath、workspacePath 和发布包文件索引。
  4. 如果请求带 path/filePath、offset、limit,按需读取 release 文件,限制索引条目和输出长度。
  5. 更新 LoopRuntime.activeSkillName/root/entryPath,下一轮注入 Skill reminder。
  6. 明确提示模型:skill_call 只激活/读取说明,不会自动执行脚本;脚本必须通过 Sandbox 工具按 SKILL.md 协议执行。

没有 Sandbox 或发布目录时,只能使用数据库中的 SKILL.md 内容,不能假定 scripts、references、assets 存在。

8. MCP 和 Feign 注册约束 ​

Feign 自动注册从 FeignRegistryInitializer.registry 读取标注方法,生成 snake case 默认工具名、参数 Schema、接口方法、超时、权限和标签,saveOrUpdate 写入 ai_tool。修改注解后必须检查已有数据库记录。

Nacos MCP 同步先发现健康实例,再调用 tools/list,以 service@group 加锁防重复同步;实例变化由 listener 防抖,定时健康检查负责补偿。服务发现和工具授权是两件事:服务在线不表示某 Agent 可以调用。

9. 新工具上线检查表 ​

  • Schema 是否能被目标模型正确解析,必填字段和枚举是否明确。
  • 是否声明读操作/副作用,是否需要 HITL。
  • 超时、重试和取消时远端动作是否可控。
  • 重试是否幂等,是否写 journal、审计和工具日志。
  • 参数是否受租户、用户、session、workspace 限定。
  • 结果是否有摘要、原文、分页读取和敏感字段脱敏策略。
  • 是否能在 checkpoint 恢复后识别已完成、进行中和未知结果。