Skip to content

[Feature] 工具调用增加 description 字段,提升 UI 可读性 #684

Description

@CATMIAOZHI

背景与动机

当前 Operit 在对话界面展示工具调用时,用户只能看到工具名称和原始参数。对于参数较多或路径较长的调用(如 read_file 带长路径、visit_web 带 URL),用户需要仔细阅读参数才能理解 AI 这一步在做什么,体验不够直观。

参考 opencode(anomalyco/opencode)的设计,它为每个工具调用引入了一个 description 字段——由 LLM 在调用时用自然语言生成一句话摘要,UI 优先展示这个摘要,让用户一眼就能理解 AI 当前操作的意图。

从第一性原理的分析

工具调用的本质是:AI 决定执行一个动作 → 系统执行 → 返回结果。在这个过程中,用户需要回答的核心问题是"AI 正在做什么?"。

当前 Operit 的展示链路:

工具名 + 完整参数 → 用户自行阅读理解

引入 description 后的展示链路:

工具名 + LLM 生成的一句话摘要 → 用户一眼理解 → (展开可看完整参数)

这个设计有三个关键点:

  1. 生成者:由 LLM 在发起工具调用时生成,因为 LLM 最清楚自己的意图
  2. 存储位置:作为工具调用的一个附加参数,不参与实际执行逻辑
  3. 展示优先级:UI 卡片标题优先显示 description,原始参数作为次级信息展开显示

具体建议

1. 工具调用协议层面

在工具调用协议层统一注入一个可选的 description 字段(string 类型),而非修改每个工具的参数 schema。这样所有工具(包括 MCP 工具)都能自动获得此能力。

在 system prompt 中指示 LLM 在每次工具调用时附带一句自然语言描述:

调用工具时,请在 description 参数中用一句话描述你这次操作的目的

示例:

{
  "tool": "read_file",
  "description": "读取用户配置文件",
  "parameters": {
    "path": "/sdcard/Download/config.json"
  }
}

命名建议:工具定义本身已有 description(描述工具功能),调用级的这个字段可考虑命名为 action_descriptionintent 以区分,避免概念混淆。此处暂用 description 与 opencode 参考保持一致。

2. UI 展示层面

  • 折叠状态:工具调用卡片标题显示为 工具名(description 内容),例如 read_file(读取用户配置文件)
  • 展开状态:显示完整参数 + 执行结果
  • 未提供 description 时:降级为当前的展示方式(工具名 + 参数摘要)

3. 兼容性

  • description 为可选字段,不影响工具执行逻辑
  • 对于不支持/不提供 description 的模型或 MCP 工具,UI 自动降级
  • 不改变现有工具的执行流程,仅在调用协议和 UI 层做增量修改

参考

  • opencode (anomalyco/opencode) 旧版 Go 实现中,TUI 从工具调用参数提取 description 字段作为卡片标题(issue #1736)
  • opencode 新版 TS 实现中改为用 title: input.command(工具返回值中的 title 字段),说明此方案经历过迭代
  • 值得注意的教训:opencode 旧版将 description 作为隐式必填参数但未声明在工具 schema 中,导致模型调用失败(有 issue 反馈)。本建议将其作为协议层的显式可选字段可避免此问题

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions