首页
看点啥
插画图片
首页 看点啥 Claude code tools 研究系列-开篇(AskUserQuestion)

Claude code tools 研究系列-开篇(AskUserQuestion)

2026-07-31 0

之前研究过 claude code 的设计,用 Java 写了一个乞丐版的 claude code 开源地址 jooj 。Claude code 的 tools 都设计的非常精巧。所以想逐个研究一下。大家共同学习。

AskUserQuestion

是最常见到的 tools 之一。

作用

AskUserQuestion 是 Claude Code 内置的结构化提问工具。它不是让 Claude 输出一段问题字符串等用户回复,而是把问题渲染成一个交互式选择面板 —— 用户看到的是一组预设选项(卡片形式),而不是一段纯文字提问。

它解决的核心问题是「AI 与用户之间的高效对齐」:

  1. 降低用户负担 —— 从「打字回答」变成「点选项」,响应时间大幅缩短
  2. 结构化输入 —— Claude 拿到的是明确的枚举值,不用再解析自然语言
  3. 收敛歧义 —— 通过预设选项引导用户在明确的方案之间选择,避免「随便你决定」式的模糊回答
  4. 保底逃生舱 —— 系统始终自动附加「其它」选项,允许用户输入自定义文本,避免「选项不合口味只能退出」

一个具体例子

在展开触发条件、技术实现、prompt 细节之前,先看一个具体场景,感受一下「不用 AskUserQuestion 会怎样 vs 用了会怎样」。

场景:用户对 Claude 说 「帮我给这个应用加个用户登录」。

这个需求描述得很不完整 —— 用哪种认证方式没定、登录凭证存哪里没定。Claude 既不能瞎猜(用户可能有团队规范),也没法直接从代码里读出来(新功能没先例)。

反例:如果没有 AskUserQuestion

Claude 只能用一段自由文本把问题甩回去,大概长这样:

用户会遇到几个问题:

  1. 认知负担高 —— 一段长文字里塞了 2 个决策 + 5 个选项,需要用户先解析题目再回答
  2. 回答成本高 —— 要么打一段字回复(「JWT + httpOnly」),要么去网上搜「JWT vs 会话 cookie」看两小时再回来
  3. Claude 解析成本高 —— 拿到「就 JWT 吧,cookie 那个」这种回复,还得反推用户到底选了哪个,可能理解错
  4. 推荐值淹没在文字里 —— Claude 说「建议 JWT」,但和其它选项混在一起,用户容易忽略
  5. 没有兜底 —— 如果用户想用一个 Claude 没提到的方案(比如免密邮件链接),要么另起一段解释,要么被 Claude 的三选一绑架

核心痛点:这种纯文本形式,让「协作对齐」变成了一次昂贵的自然语言往返。

用 AskUserQuestion 是怎么解决的

Claude 会构造一个包含 两个问题 的调用:

第一个问题 ——

之前研究过 claude code 的设计,用 Java 写了一个乞丐版的 claude code 开源地址 jooj 。Claude code 的 tools 都设计的非常精巧。所以想逐个研究一下。大家共同学习。

AskUserQuestion

是最常见到的 tools 之一。

作用

AskUserQuestion 是 Claude Code 内置的结构化提问工具。它不是让 Claude 输出一段问题字符串等用户回复,而是把问题渲染成一个交互式选择面板 —— 用户看到的是一组预设选项(卡片形式),而不是一段纯文字提问。

它解决的核心问题是「AI 与用户之间的高效对齐」:

  1. 降低用户负担 —— 从「打字回答」变成「点选项」,响应时间大幅缩短
  2. 结构化输入 —— Claude 拿到的是明确的枚举值,不用再解析自然语言
  3. 收敛歧义 —— 通过预设选项引导用户在明确的方案之间选择,避免「随便你决定」式的模糊回答
  4. 保底逃生舱 —— 系统始终自动附加「其它」选项,允许用户输入自定义文本,避免「选项不合口味只能退出」

一个具体例子

在展开触发条件、技术实现、prompt 细节之前,先看一个具体场景,感受一下「不用 AskUserQuestion 会怎样 vs 用了会怎样」。

场景:用户对 Claude 说 「帮我给这个应用加个用户登录」。

这个需求描述得很不完整 —— 用哪种认证方式没定、登录凭证存哪里没定。Claude 既不能瞎猜(用户可能有团队规范),也没法直接从代码里读出来(新功能没先例)。

反例:如果没有 AskUserQuestion

Claude 只能用一段自由文本把问题甩回去,大概长这样:

用户会遇到几个问题:

  1. 认知负担高 —— 一段长文字里塞了 2 个决策 + 5 个选项,需要用户先解析题目再回答
  2. 回答成本高 —— 要么打一段字回复(「JWT + httpOnly」),要么去网上搜「JWT vs 会话 cookie」看两小时再回来
  3. Claude 解析成本高 —— 拿到「就 JWT 吧,cookie 那个」这种回复,还得反推用户到底选了哪个,可能理解错
  4. 推荐值淹没在文字里 —— Claude 说「建议 JWT」,但和其它选项混在一起,用户容易忽略
  5. 没有兜底 —— 如果用户想用一个 Claude 没提到的方案(比如免密邮件链接),要么另起一段解释,要么被 Claude 的三选一绑架

核心痛点:这种纯文本形式,让「协作对齐」变成了一次昂贵的自然语言往返。

用 AskUserQuestion 是怎么解决的

Claude 会构造一个包含 两个问题 的调用:

第一个问题 ——

需要配置第三方服务

第二个问题 ——

用户在界面上看到的是两张卡片,每张卡片顶部是那个短标签(「认证方式」/「凭证存储」),下面是 3 个 / 2 个选项 + 一个自动追加的「其它」。用户点两下选完,Claude 拿到的返回值大致是:

  1. 第一个问题 → 用户选了 JWT(推荐)
  2. 第二个问题 → 用户选了 httpOnly cookie(推荐)

决策时间从几分钟压到几秒。这就是 AskUserQuestion 存在的意义 —— 不是「让 AI 问问题」,而是「让协作的每一次澄清都变得低成本」。

对照一下两种形式解决了反例里的哪些痛点

反例痛点AskUserQuestion 的解法
认知负担高拆成 2 张独立卡片,一次聚焦一个决策
回答成本高点选项而不是打字,权衡说明直接标在选项下
Claude 解析成本高返回值是明确的选项文本,不用做自然语言解析
推荐值淹没在文字里「(推荐)」后缀 + 前置位置,第一眼看到
没有兜底「其它」自动追加,用户想输入自定义方案永远有出口

这个对照本质上就是 AskUserQuestion 每个设计点的存在理由 —— 每一条都对应一个自由文本对话解决不了的痛点。带着这个直觉,再往下看触发条件、技术实现和 prompt 细节,会发现每一条约束都对应到这里的某个具体痛点。

触发条件

工具的官方说明里明确写了触发边界:只有在你被卡住,而这个决策又真正属于用户时才使用。

三类该问的场景:

  1. 无法从请求推断 —— 需求本身模糊(比如「帮我加个登录」,没说 OAuth 还是 JWT)
  2. 无法从代码推断 —— 现有代码里没有先例可以模仿
  3. 没有合理默认值 —— 涉及品味 / 业务规则 / 架构分叉,不该由 AI 拍板

三类不该问的场景:

  1. 答案能从代码里读出来 —— 该花时间读代码,而不是打断用户
  2. 只有一种明显合理的做法 —— 直接做,提交信息里说明理由即可
  3. 在计划模式里问「方案 OK 吗」 —— 这是 ExitPlanMode 的职责,用 Ask 是重复

一个典型反模式:避免「这个方案 OK 吗 / 我可以继续吗」这类元问题。ExitPlanMode 本身就是「请求批准」,Ask 用来做这个纯属重复。

技术实现

从工具的入参定义反推,它的核心结构可以用文字描述如下:

Claude 调用这个工具时,传入一个 问题列表(1 到 4 个问题)。列表里每一项是一个 问题对象,包含四个部分:

  1. 问题文本 —— 完整的问题文本,以问号结尾
  2. 卡片短标签 —— 显示在卡片顶部的短标签,最多 12 个字符
  3. 是否多选 —— 布尔值,控制是否允许多选(默认单选)
  4. 选项列表 —— 2 到 4 个选项

每个选项本身又包含三个字段:

  1. 选项文本 —— 用户看到的选项显示文本(1 到 5 个字)
  2. 选项说明 —— 这个选项含义 / 权衡的说明
  3. 视觉预览 —— 可选:当选项差异需要「可视化对比」时(比如两个示意图、两段代码),聚焦这个选项时界面会渲染这段内容

几个关键设计点:

  1. 一次可以问 1-4 个问题 —— 支持批量决策(比如「选认证方式 + 选凭证存储」一次问完),但不允许无脑打包 10 个问题轰炸用户
  2. 每个问题 2-4 个选项 —— 强制 Claude 做初步归类,把 N 种可能收敛到少数几个可点选项,而不是甩一张长清单给用户
  3. 「其它」是隐式选项 —— 用户端自动追加,Claude 不用手动列。这保证了「Claude 想到的选项 ≠ 全部」时用户不会被卡死
  4. 推荐值机制 —— 如果 Claude 有倾向,把它放第一个选项 + 文本后追加「(推荐)」,用户可以一眼看到并快速采纳
  5. 返回值结构 —— 用问题文本作为 key,映射到用户选择的选项文本;另有一个字段承载用户在视觉预览场景下额外写的注释

视觉预览字段 是一个有意思的进阶点 —— 当选项之间的差异需要「可视化对比」(比如两个界面示意图、两种代码风格),把内容塞在这个字段里,界面会在聚焦某个选项时渲染出来。这对「选哪种 API 设计 / 选哪种排版」这种问题特别有用。

与 EnterPlanMode / ExitPlanMode 的分工:

  1. 计划模式里,用 AskUserQuestion 澄清「选哪种方案」(在方案定稿之前)
  2. 计划模式里,不要用 AskUserQuestion 问「我的方案 OK 吗」(用 ExitPlanMode)
  3. 非计划模式里,用 AskUserQuestion 处理任何需要用户拍板的技术分叉

三个工具串起来是一条完整的决策流水线:Ask 澄清 → EnterPlanMode 展开 → ExitPlanMode 拍板。

prompt 详解

工具官方说明里每一句都在给 Claude 塞一条行为约束,逐条拆一下:

约束 1:严格的适用边界(开篇第一句)

这句话在训练 Claude「不要主动打扰」—— 遇到不确定,第一反应应该是先查代码、先用合理默认值,而不是甩问题给用户。

约束 2:「其它」逃生舱的透明化

系统不是把这个选项藏起来让 Claude 假装不知道 —— 而是明确告诉 Claude「其它会自动加,你不用列」。这样 Claude 不会浪费一个选项去手写「自定义」。

约束 3:多选参数的语义

对应场景:选多个功能开关 / 多个环境 / 多个要修的文件。默认单选保护用户不被过多选择卡住。

约束 4:推荐值的表达形式

有意思的点:推荐值不是单独字段,而是通过「约定俗成的位置 + 后缀」实现的。好处:

  1. 保持入参定义简单,不引入一个「是否推荐」的布尔字段
  2. 界面侧只用渲染选项文本,不用做特殊处理
  3. Claude 要表态必须写进选项文本,无法藏在元数据里 —— 用户一眼能看见

约束 5:与计划模式的时序关系

这段是最有教学价值的 —— 明确了整套流程的时序:

  1. 计划模式里,先用 Ask 澄清方案分叉(如「选 A 还是 B」)
  2. 澄清完后,用 EnterPlanMode 落一份完整方案
  3. 最后一步用 ExitPlanMode 请求批准 —— 不要再用 Ask 问「OK 吗」

尤其注意原文最后半句 —— 「用户在你调用 ExitPlanMode 之前根本看不到方案」—— 这才是「不要在计划模式里问『方案 OK 吗』」的真正原因:不是重复,而是用户根本没东西可批。

三个工具各司其职:Ask 澄清 / EnterPlanMode 展开 / ExitPlanMode 拍板。这套约束本质上是在阻止 Claude 在计划模式里绕回来用 Ask 做「批准」这件事。

约束 6:卡片短标签是必填字段(结构层强制)

这是一个交互约束 —— 界面里每个问题渲染成一张卡片,卡片顶端的标签用这个短字符串,而不是完整的问题文本。这就要求 Claude 把长问题浓缩成一个短标签(比如「登录流程应该用哪种认证方式?」的短标签就是「认证方式」)。

约束 7:问题必须以问号结尾

看似很小的一条,但决定了界面的自然度 —— 问句语气 vs 陈述语气对用户的心理暗示完全不同。这也间接强制 Claude 把内容组织成「真正的疑问」而不是「疑似指令」。

小结:AskUserQuestion 的精妙之处,不在于它「让 AI 问用户问题」这个功能本身,而在于它通过入参结构约束 + prompt 约束,把「什么时候问 / 怎么问 / 用什么形式呈现 / 和谁配合」 全都规范住了。相当于把「AI 提问」这个泛用能力,收敛成一个可预测、可组合、可维护的交互原语。

需要配置第三方服务

第二个问题 ——

用户在界面上看到的是两张卡片,每张卡片顶部是那个短标签(「认证方式」/「凭证存储」),下面是 3 个 / 2 个选项 + 一个自动追加的「其它」。用户点两下选完,Claude 拿到的返回值大致是:

  1. 第一个问题 → 用户选了 JWT(推荐)
  2. 第二个问题 → 用户选了 httpOnly cookie(推荐)

决策时间从几分钟压到几秒。这就是 AskUserQuestion 存在的意义 —— 不是「让 AI 问问题」,而是「让协作的每一次澄清都变得低成本」。

对照一下两种形式解决了反例里的哪些痛点

反例痛点AskUserQuestion 的解法
认知负担高拆成 2 张独立卡片,一次聚焦一个决策
回答成本高点选项而不是打字,权衡说明直接标在选项下
Claude 解析成本高返回值是明确的选项文本,不用做自然语言解析
推荐值淹没在文字里「(推荐)」后缀 + 前置位置,第一眼看到
没有兜底「其它」自动追加,用户想输入自定义方案永远有出口

这个对照本质上就是 AskUserQuestion 每个设计点的存在理由 —— 每一条都对应一个自由文本对话解决不了的痛点。带着这个直觉,再往下看触发条件、技术实现和 prompt 细节,会发现每一条约束都对应到这里的某个具体痛点。

触发条件

工具的官方说明里明确写了触发边界:只有在你被卡住,而这个决策又真正属于用户时才使用。

三类该问的场景:

  1. 无法从请求推断 —— 需求本身模糊(比如「帮我加个登录」,没说 OAuth 还是 JWT)
  2. 无法从代码推断 —— 现有代码里没有先例可以模仿
  3. 没有合理默认值 —— 涉及品味 / 业务规则 / 架构分叉,不该由 AI 拍板

三类不该问的场景:

  1. 答案能从代码里读出来 —— 该花时间读代码,而不是打断用户
  2. 只有一种明显合理的做法 —— 直接做,提交信息里说明理由即可
  3. 在计划模式里问「方案 OK 吗」 —— 这是 ExitPlanMode 的职责,用 Ask 是重复

一个典型反模式:避免「这个方案 OK 吗 / 我可以继续吗」这类元问题。ExitPlanMode 本身就是「请求批准」,Ask 用来做这个纯属重复。

技术实现

从工具的入参定义反推,它的核心结构可以用文字描述如下:

Claude 调用这个工具时,传入一个 问题列表(1 到 4 个问题)。列表里每一项是一个 问题对象,包含四个部分:

  1. 问题文本 —— 完整的问题文本,以问号结尾
  2. 卡片短标签 —— 显示在卡片顶部的短标签,最多 12 个字符
  3. 是否多选 —— 布尔值,控制是否允许多选(默认单选)
  4. 选项列表 —— 2 到 4 个选项

每个选项本身又包含三个字段:

  1. 选项文本 —— 用户看到的选项显示文本(1 到 5 个字)
  2. 选项说明 —— 这个选项含义 / 权衡的说明
  3. 视觉预览 —— 可选:当选项差异需要「可视化对比」时(比如两个示意图、两段代码),聚焦这个选项时界面会渲染这段内容

几个关键设计点:

  1. 一次可以问 1-4 个问题 —— 支持批量决策(比如「选认证方式 + 选凭证存储」一次问完),但不允许无脑打包 10 个问题轰炸用户
  2. 每个问题 2-4 个选项 —— 强制 Claude 做初步归类,把 N 种可能收敛到少数几个可点选项,而不是甩一张长清单给用户
  3. 「其它」是隐式选项 —— 用户端自动追加,Claude 不用手动列。这保证了「Claude 想到的选项 ≠ 全部」时用户不会被卡死
  4. 推荐值机制 —— 如果 Claude 有倾向,把它放第一个选项 + 文本后追加「(推荐)」,用户可以一眼看到并快速采纳
  5. 返回值结构 —— 用问题文本作为 key,映射到用户选择的选项文本;另有一个字段承载用户在视觉预览场景下额外写的注释

视觉预览字段 是一个有意思的进阶点 —— 当选项之间的差异需要「可视化对比」(比如两个界面示意图、两种代码风格),把内容塞在这个字段里,界面会在聚焦某个选项时渲染出来。这对「选哪种 API 设计 / 选哪种排版」这种问题特别有用。

与 EnterPlanMode / ExitPlanMode 的分工:

  1. 计划模式里,用 AskUserQuestion 澄清「选哪种方案」(在方案定稿之前)
  2. 计划模式里,不要用 AskUserQuestion 问「我的方案 OK 吗」(用 ExitPlanMode)
  3. 非计划模式里,用 AskUserQuestion 处理任何需要用户拍板的技术分叉

三个工具串起来是一条完整的决策流水线:Ask 澄清 → EnterPlanMode 展开 → ExitPlanMode 拍板。

prompt 详解

工具官方说明里每一句都在给 Claude 塞一条行为约束,逐条拆一下:

约束 1:严格的适用边界(开篇第一句)

这句话在训练 Claude「不要主动打扰」—— 遇到不确定,第一反应应该是先查代码、先用合理默认值,而不是甩问题给用户。

约束 2:「其它」逃生舱的透明化

系统不是把这个选项藏起来让 Claude 假装不知道 —— 而是明确告诉 Claude「其它会自动加,你不用列」。这样 Claude 不会浪费一个选项去手写「自定义」。

约束 3:多选参数的语义

对应场景:选多个功能开关 / 多个环境 / 多个要修的文件。默认单选保护用户不被过多选择卡住。

约束 4:推荐值的表达形式

有意思的点:推荐值不是单独字段,而是通过「约定俗成的位置 + 后缀」实现的。好处:

  1. 保持入参定义简单,不引入一个「是否推荐」的布尔字段
  2. 界面侧只用渲染选项文本,不用做特殊处理
  3. Claude 要表态必须写进选项文本,无法藏在元数据里 —— 用户一眼能看见

约束 5:与计划模式的时序关系

这段是最有教学价值的 —— 明确了整套流程的时序:

  1. 计划模式里,先用 Ask 澄清方案分叉(如「选 A 还是 B」)
  2. 澄清完后,用 EnterPlanMode 落一份完整方案
  3. 最后一步用 ExitPlanMode 请求批准 —— 不要再用 Ask 问「OK 吗」

尤其注意原文最后半句 —— 「用户在你调用 ExitPlanMode 之前根本看不到方案」—— 这才是「不要在计划模式里问『方案 OK 吗』」的真正原因:不是重复,而是用户根本没东西可批。

三个工具各司其职:Ask 澄清 / EnterPlanMode 展开 / ExitPlanMode 拍板。这套约束本质上是在阻止 Claude 在计划模式里绕回来用 Ask 做「批准」这件事。

约束 6:卡片短标签是必填字段(结构层强制)

这是一个交互约束 —— 界面里每个问题渲染成一张卡片,卡片顶端的标签用这个短字符串,而不是完整的问题文本。这就要求 Claude 把长问题浓缩成一个短标签(比如「登录流程应该用哪种认证方式?」的短标签就是「认证方式」)。

约束 7:问题必须以问号结尾

看似很小的一条,但决定了界面的自然度 —— 问句语气 vs 陈述语气对用户的心理暗示完全不同。这也间接强制 Claude 把内容组织成「真正的疑问」而不是「疑似指令」。

小结:AskUserQuestion 的精妙之处,不在于它「让 AI 问用户问题」这个功能本身,而在于它通过入参结构约束 + prompt 约束,把「什么时候问 / 怎么问 / 用什么形式呈现 / 和谁配合」 全都规范住了。相当于把「AI 提问」这个泛用能力,收敛成一个可预测、可组合、可维护的交互原语。

喜欢(0)

上一篇

我最推荐的 4 个 AI 编程 Skills:grill-me、research、diagnosing-bugs、code-review

我最推荐的 4 个 AI 编程 Skills:grill-me、research、diagnosing-bugs、code-review

下一篇

1M Context 也会失忆:Coding Agent 为什么需要 Context Ledger

1M Context 也会失忆:Coding Agent 为什么需要 Context Ledger
猜你喜欢