Roo Code ask_followup_question 工具完全指南:交互式澄清机制的原理与实践
【免费下载链接】Roo-CodeRoo Code gives you a whole dev team of AI agents in your code editor.项目地址: https://gitcode.com/GitHub_Trending/ro/Roo-Code
ask_followup_question是 Roo Code 内置的交互式提问工具,它让 AI 代理在信息缺失、需求模糊或面临多方案选型时,能以结构化方式向用户提问并获取决策依据。本文基于官方文档与仓库源码,系统讲解该工具的参数格式、触发时机、完整工作原理、错误处理机制与实际使用范例,帮助你理解并善用这一"始终可用"的人机协作通道。
工具定位:Roo Code 中的人机对话桥梁
在 Roo Code 的默认工作流程中,AI 代理被设计为尽量自主地使用工具完成任务。但在真实开发场景里,任务请求往往存在信息缺口——例如用户只说"做一个博客网站",却没说明技术栈、样式方案或数据库选型。此时盲目行动可能带来大量返工。
ask_followup_question正是为此而生:它通过向用户提出具体问题,收集完成任务所需的补充信息,在"自主执行"与"用户决策"之间建立一条结构化的对话通道。从仓库源码 src/core/prompts/responses.ts 可以看到,系统提示词明确要求:"If you require additional information from the user, use the ask_followup_question tool."
与随意输出一段文字等待用户回复不同,该工具具备完整的参数校验、建议选项注入、流式渲染与错误计数机制,是一条经过工程化设计、可被测试验证的正式工具调用路径。
参数详解
工具接受两个参数:
| 参数 | 必填 | 说明 |
|---|---|---|
question | 是 | 要向用户提出的具体、清晰的问题 |
follow_up | 是 | 2-4 条建议答案的列表,用于引导用户快速回复;在 UI 中以可选按钮形式展示 |
注意:官方文档 ask-followup-question.md 中将
follow_up标注为可选,但从当前仓库源码看,src/core/prompts/tools/native-tools/ask_followup_question.ts 的 JSON Schema 已将其声明为required,并要求数组长度为 1-4;src/core/tools/AskFollowupQuestionTool.ts 在运行时也会对缺失或非数组的follow_up报出缺少参数错误。因此实际使用时应始终提供建议答案。
在原生(native)工具协议中,follow_up数组的每个元素是一个对象,包含两个字段:
text(必填):用户可直接选中的建议答案,必须是完整、可执行的答案,不能是留有占位符的残缺内容;mode(可选):若用户选中该选项,代理将切换到的模式 slug(如code、architect、debug等),允许"提问即触发模式切换"的联动效果。
该模式切换能力的示例在 native-tools/ask_followup_question.ts 的注释中给出:
{ "question": "Would you like me to implement this feature?", "follow_up": [{ "text": "Yes, implement it now", "mode": "code" }, { "text": "No, just plan it out", "mode": "architect" }] }何时使用该工具
Roo Code 只在下列情况下调用ask_followup_question:
- 原始请求中缺失关键信息,无法推断出合理的默认值;
- 存在多种可行的实现方案,需要用户决策(如技术栈、认证方式选型);
- 缺少继续执行所需的技术细节或用户偏好;
- 遇到必须澄清的需求歧义;
- 额外上下文能够显著提升方案质量时。
同时,系统提示词在 src/core/prompts/sections/rules.ts 中设定了两条重要约束:
- 工具优先原则:如果能用
list_files、read_file等现有工具自行查明信息,就应当直接去做,而不是发问。例如用户提到 Desktop 上的某个文件时,应先列出目录确认,而不是询问文件路径; - 提问下限原则:"Do not ask for more information than necessary"——提问应克制、聚焦,能自证的信息绝不打扰用户。
也就是说,该工具是信息获取的"最后手段",其使用频率受系统提示词纪律约束,避免破坏代理的自主性与任务完成效率。
核心特性
- 提供结构化的信息收集方式,不打断整体工作流;
- 内置建议答案,减少用户输入量、引导回复方向;
- 跨交互保持对话历史与上下文连贯;
- 用户回复支持携带图片与代码片段;
- 作为
always available工具集成员,对所有模式(mode)开放——在 src/shared/tools.ts 的ALWAYS_AVAILABLE_TOOLS列表中,ask_followup_question与attempt_completion、switch_mode、new_task等并列,无需在模式配置中单独声明; - 允许用户直接指导代理的实施方案决策;
- 用户回复统一以
<answer>标签包裹,与普通对话内容清晰区分; - 工具成功执行时重置连续错误计数器,作为代理自我纠错状态的一部分。
工作原理:从调用到回显的完整链路
1. 参数校验
工具入口 src/core/tools/AskFollowupQuestionTool.ts 首先校验参数:
question缺失(空字符串)时,调用recordMissingParamError记录错误;follow_up缺失、为null或非数组时同样报错,且不会继续执行task.ask。
该校验逻辑在测试 src/core/tools/tests/askFollowupQuestionTool.spec.ts 中针对 missing / null / 非数组三种异常输入均有覆盖,确认了"缺参即终止"的安全行为。
2. JSON 标准化转换
源码将传入的follow_up列表映射为 UI 层可消费的标准 JSON 结构:
{ question: "User's question here", suggest: [ { answer: "Suggestion 1", mode: undefined }, { answer: "Suggestion 2", mode: "code" } ] }对应实现见 src/core/tools/AskFollowupQuestionTool.ts:follow_up.map((s) => ({ answer: s.text, mode: s.mode }))。测试 askFollowupQuestionTool.spec.ts 验证了最终传给 UI 的 JSON 中包含"suggest":[{"answer":"Option 1"},{"answer":"Option 2"}]这样的标准化结构。
3. UI 集成
标准化后的 JSON 通过task.ask("followup", ...)方法(src/core/task/Task.ts)传递给 Webview UI 层。用户在界面中看到的是可点击的建议按钮,也可以自由输入自定义回答,形成"点选 + 键入"双通道的交互体验。
值得说明的是流式场景的处理:handlePartial方法在代理流式输出尚未结束时,只传递question文本而暂不发送 JSON(AskFollowupQuestionTool.ts),避免把未完成的原始 JSON 暴露给用户界面;待工具调用完整后再一次性渲染含建议选项的最终内容。对应行为由 askFollowupQuestionTool.spec.ts 验证。
4. 响应收集与处理
用户回复后,流程继续:
- 捕获用户输入的文本以及回复中携带的任何图片;
- 将回复以
<answer>标签包裹后回传给代理; - 保留回复中附带的图片;
- 通过
task.say("user_feedback", text, images)将反馈写入对话历史,维持上下文连续(AskFollowupQuestionTool.ts); - 成功完成后将
task.consecutiveMistakeCount重置为 0。
5. 错误处理与连续错误计数
错误处理机制围绕consecutiveMistakeCount计数器展开(AskFollowupQuestionTool.ts):
- 参数缺失时:
consecutiveMistakeCount自增,调用recordToolError("ask_followup_question")记录错误,并将didToolFailInCurrentTurn置为true,同时向用户返回格式化的缺少参数错误提示; - 成功时:计数器归零,表示代理已从错误状态恢复;
- 执行异常时:统一交由
handleError处理,生成 "asking question" 场景的错误信息。
这套计数机制是代理自我纠错系统的一部分,用于防止连续失败后仍盲目重复同一操作。测试文件 askFollowupQuestionTool.spec.ts 对错误分支的计数器行为有明确断言(错误后计数为 1、且不再调用task.ask)。
提问-回答工作流时序
一个完整的问答周期遵循如下顺序:
- 信息缺口识别:代理判断当前缺少继续执行所需的信息;
- 问题拟定:将缺口转化为清晰、具体、可回答的问题;
- 建议设计:为每个问题准备 2-4 条相关建议答案(推荐提供,非强制但建议);
- 工具调用:代理携带
question与follow_up调用工具; - UI 呈现:问题与建议按钮展示给用户;
- 用户回复:用户点选建议或输入自定义回答;
- 消息处理:系统分别处理流式(partial)与完整消息——流式响应按到达的分块逐段处理,完整消息则一次性处理,无论消息如何分块都保持状态一致;
- 回复加工:回复以
<answer>标签包裹并保留图片; - 上下文整合:回复写入对话历史;
- 任务继续:代理基于新信息推进任务。
其中第 7 步的"状态一致性"由 Task.ts 中的 partial 消息更新逻辑保障:流式渲染时先以partial: true建立占位消息,完整内容到达后原位更新而非重建消息,从而避免界面闪烁与状态错乱。
响应格式:<answer>标签
用户对问题的回答会以<answer>标签包裹,确保与普通对话元素清晰区分:
<answer> Use Tailwind CSS for utility-first styling with maximum flexibility </answer>该格式具备以下特征:
- 被
<answer>标签包围; - 保留原始回复的格式(含换行与长文本);
- 若回复附带图片则一并保留;
- 即使是长回复,也完整返回全部文本。
在调用链末端,回复还会进一步封装为<user_message>块作为工具结果返回给模型(AskFollowupQuestionTool.ts),使得后续模型推理能够明确识别"这是用户对提问的反馈"而非普通工具输出。
使用示例
以下示例来自官方文档,展示了该工具在真实开发决策中的典型用法。
询问实现偏好(样式方案选型):
<ask_followup_question> <question>Which styling approach would you prefer for this web application?</question> <follow_up> <suggest>Use Bootstrap for rapid development with consistent components</suggest> <suggest>Use Tailwind CSS for utility-first styling with maximum flexibility</suggest> <suggest>Use vanilla CSS with custom styling for complete control and minimal dependencies</suggest> </follow_up> </ask_followup_question>请求技术澄清(数据库选型):
<ask_followup_question> <question>What database should this application use for storing user data?</question> <follow_up> <suggest>MongoDB for flexible schema and document-based storage</suggest> <suggest>PostgreSQL for relational data with strong consistency guarantees</suggest> <suggest>Firebase for real-time updates and simplified backend management</suggest> <suggest>SQLite for lightweight local storage without external dependencies</suggest> </follow_up> </ask_followup_question>化解需求歧义(认证方式决策):
<ask_followup_question> <question>How should the application handle user authentication?</question> <follow_up> <suggest>Implement email/password authentication with account verification</suggest> <suggest>Use social login providers (Google, GitHub, etc.) for quick signup</suggest> <suggest>Implement both email/password and social login options</suggest> </follow_up> </ask_followup_question>说明:上述为文档层面的 XML 风格展示。在实际的原生工具协议中,模型按 JSON Schema 调用,格式见前文"参数详解"一节(
question+follow_up数组,每项含text与可选mode)。
局限性
- 每次工具调用只能提出一个具体问题,无法一次抛出多个问题;
- 建议答案在 UI 中以可选项呈现,但用户仍可自由输入任意回复,无法强制其选择;
- 过度使用会拖慢任务完成速度,并造成碎片化、割裂的交互体验;
- 建议答案必须是完整内容,不得留有要求用户自行编辑的占位符;
- 系统不内置对用户回复的校验;
- 没有任何机制能强制用户遵循特定答案格式。
结合 rules.ts 中的系统提示词可知,代理还被要求:建议应"specific, actionable, directly related to the completed task",并按优先级或逻辑顺序排列——遵守这些纪律是发挥该工具价值的前提。
实践建议
- 能用工具查证就不提问:文件路径、目录结构等可通过
list_files/read_file确认的信息,优先自主获取(rules.ts); - 一个问题配 2-4 条建议:既减少用户输入负担,也引导回复朝可执行方向收敛,并善用
mode字段实现"选完即切换模式"; - 建议答案要完整可执行:避免"你想怎么实现?"这类开放问题,尽量给出"用 X 技术实现 Y 效果"式的具体选项;
- 把提问用在真正的决策点上:技术栈选型、数据库选择、认证方案、性能与可读性权衡、架构设计偏好等,才是该工具的用武之地,而非琐碎的执行细节;
- 理解流式渲染行为:流式输出阶段界面只展示问题文本,完整选项在工具调用结束后出现,属正常现象而非缺陷。
通过合理使用ask_followup_question,可以让 Roo Code 在自主执行与关键决策之间取得平衡——既不过度打扰用户,又能在真正需要时获得高质量的方向指引。
【免费下载链接】Roo-CodeRoo Code gives you a whole dev team of AI agents in your code editor.项目地址: https://gitcode.com/GitHub_Trending/ro/Roo-Code
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考