ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Gemini CLI 的 ask_user 工具深度解析:从参数 Schema 到确认总线实现的交互式提问机制

Gemini CLI 的 ask_user 工具深度解析:从参数 Schema 到确认总线实现的交互式提问机制 Gemini CLI 的 ask_user 工具深度解析从参数 Schema 到确认总线实现的交互式提问机制【免费下载链接】gemini-cliAn open-source AI agent that brings the power of Gemini directly into your terminal.项目地址: https://gitcode.com/GitHub_Trending/gemi/gemini-cli在 Gemini CLI 中模型与用户之间的双向沟通主要依赖ask_user工具它允许 Agent 在执行过程中暂停并弹出交互式对话框以选择题、自由文本或 Yes/No 三种形式向用户收集偏好、澄清需求或请求决策。本文基于仓库文档 docs/tools/ask-user.md结合 packages/core/src/tools/ask-user.ts 的实现、packages/core/src/confirmation-bus/types.ts 的总线协议与 JSON Schema 定义完整讲解该工具的参数结构、运行行为、结果格式与源码级工作原理读完后可理解其提问流程如何在确认总线confirmation bus上闭环并能编写符合其 Schema 约束的调用参数。工具定位与基本信息ask_user是 Gemini CLI 内置的沟通类Kind.Communicate工具用于把模型的疑问转化为用户可操作的 UI 交互。其基本信息如下属性值工具名Tool nameask_user显示名Display nameAsk User实现文件packages/core/src/tools/ask-user.ts是否需要确认是。该工具天然包含用户交互执行前必须等待用户在对话框中作答或关闭返回给模型的内容以题目序号为键的 JSON 字符串如{answers:{0: Option A, 1: Some text}}从源码结构看工具类AskUserTool在构造时接收一个MessageBus实例packages/core/src/tools/ask-user.ts说明其提问-作答流程是通过确认总线MessageBus在 core 层与 UI 层之间传递消息完成的而不是在工具内部直接渲染界面。参数 Schemaquestions 数组的完整结构ask_user只接受一个参数questions一个 1 到 4 个问题的对象数组。该约束不仅写在文档里也直接体现在工具的 JSON Schema 中——default-legacy.ts 中parametersJsonSchema声明了minItems: 1、maxItems: 4并将question、header、type列为每个问题的必填字段。单个问题对象Question的字段字段类型必填说明questionstring是完整的提问文本Schema 描述要求清晰、具体、以问号结尾headerstring是短标签文档约定最长 16 字符以 chip/tag 形式展示例如 Auth、DatabaseSchema 描述建议用缩写用 Auth 而非 Authenticationtypestring是Schema 层取值choice|text|yesno默认choiceoptionsobject 数组choice类型时必填2-4 个可选项对text/yesno类型会被忽略multiSelectboolean否仅对choice生效为true时允许多选且存在多个标准选项时会自动追加 All the above 选项placeholderstring否输入框提示文本text类型显示在主输入框choice/yesno类型显示在自动附加的 Other 自定义输入框中type的三种取值对应不同的 UI 渲染形态choice多选项列表支持多选multiSelecttext自由文本输入yesno是/否确认。源码类型注释types.ts进一步说明yesno会附带一个可选的 Other 反馈输入框而 Schema 描述也指出 Other 选项会为choice与yesno类型自动追加。参数名的集中定义在 base-declarations.tsASK_USER_PARAM_QUESTIONS、ASK_USER_QUESTION_PARAM_QUESTION/HEADER/TYPE/OPTIONS/MULTI_SELECT/PLACEHOLDER、ASK_USER_OPTION_PARAM_LABEL/DESCRIPTIONSchema 中所有字段均引用这些常量保证声明与运行时校验使用同一套命名。TypeScript 侧的类型定义除了面向模型的 JSON Schemacore 层还定义了供程序使用的Question接口packages/core/src/confirmation-bus/types.tsexport enum QuestionType { CHOICE choice, TEXT text, YESNO yesno, } export interface Question { question: string; header: string; type: QuestionType; options?: QuestionOption[]; multiSelect?: boolean; placeholder?: string; /** 允许题目占用更多纵向空间而非被严格限高 */ unconstrainedHeight?: boolean; }值得注意的是该接口比文档列出的参数多了一个unconstrainedHeight可选字段从源码结构看它用于控制对话框渲染时题目区域的高度约束属于面向 UI 层的扩展能力并不要求模型在工具调用中提供。三类问题的调用示例以下是文档给出的三个标准示例均可直接作为ask_user的参数体使用。选择题Multiple Choice{ questions: [ { header: Database, question: Which database would you like to use?, type: choice, options: [ { label: PostgreSQL, description: Powerful, open source object-relational database system. }, { label: SQLite, description: C-library that implements a SQL database engine. } ] } ] }文本输入Text Input{ questions: [ { header: Project Name, question: What is the name of your new project?, type: text, placeholder: for example, my-awesome-app } ] }是/否确认Yes/No{ questions: [ { header: Deploy, question: Do you want to deploy the application now?, type: yesno } ] }编写调用参数时的实用约束均由 Schema 与运行时校验共同保证一次最多问 4 个问题questions为空会直接报错choice类型必须提供 2-4 个options每个 option 的label必须是非空字符串、description必须提供源码校验见 ask-user.tslabel建议 1-5 个词description给出一句话说明便于用户在对话框中快速判断。运行行为、结果格式与边界情况行为模型ask_user的执行流程为弹出包含全部题目的对话框 → 暂停执行等待用户作答或关闭对话框 → 把用户答案返回给模型。从源码看这一暂停-等待语义由确认流程实现AskUserInvocation.shouldConfirmExecute返回type: ask_user的确认详情把归一化后的questions交给 UI并通过onConfirm回调捕获用户的最终结果ask-user.tsreturn { type: ask_user, title: Ask User, questions: normalizedQuestions, onConfirm: async (outcome, payload?) { this.confirmationOutcome outcome; if (payload answers in payload) { this.userAnswers payload.answers; } }, };返回给模型的 llmContentexecute的返回分两种情况ask-user.ts用户正常提交llmContent为JSON.stringify({ answers: this.userAnswers })即文档所述的以题目位置为键的 JSON 字符串如{answers:{0: Option A, 1: Some text}}returnDisplay会以header → 答案的缩进格式展示在终端中未作答时显示 User submitted without answering questions.用户关闭对话框CancelllmContent固定为User dismissed ask_user dialog without answering.并附带dismissed: true的指标数据让模型明确知道提问被放弃可以据此决定跳过或重新提问。两种路径都会写入data.ask_user指标question_types各题类型列表、dismissed、empty_submission、answer_count可用于遥测与会话统计。参数的防御性归一化模型生成的 JSON 字符串常携带字面转义序列如\\n。createInvocation在进入执行前会对question、header、placeholder以及每个 option 的label/description做unescape处理把字面\r\n、\n还原为真实换行并 trim option 的 descriptionask-user.ts。这保证了用户在对话框里看到的是干净的文本而不是带转义符的原始字符串。消息总线ask_user 在确认总线上的协议ask_user与 UI 层之间的通信走 core 层的MessageBus。总线定义了独立的请求/响应消息类型types.tsexport enum MessageBusType { // ... ASK_USER_REQUEST ask-user-request, ASK_USER_RESPONSE ask-user-response, // ... }对应消息结构为export interface AskUserRequest { type: MessageBusType.ASK_USER_REQUEST; questions: Question[]; correlationId: string; } export interface AskUserResponse { type: MessageBusType.ASK_USER_RESPONSE; correlationId: string; answers: { [questionIndex: string]: string }; /** true 表示用户未提交答案而取消了对话框 */ cancelled?: boolean; }correlationId用于把响应与请求配对answers以题目序号字符串形式的下标为键与llmContent的格式一致cancelled标志对应前文所述的用户关闭对话框分支。此外工具确认体系中的可序列化确认详情SerializableConfirmationDetails也内置了ask_user变体携带title与questionstypes.ts供确认队列组件渲染。UI 侧的消费方包括 AskUserActionsContext.tsx提问动作上下文以及确认队列组件 ToolConfirmationQueue.tsx。政策引擎侧同样把ask_user作为一种可能的决策方向ToolConfirmationRequest允许forcedDecision?: allow | deny | ask_usertypes.ts且多份策略文件如 plan.toml、non-interactive.toml、write.toml中包含对ask_user的规则配置从源码结构看非交互与计划模式下的行为受这些策略约束。Schema 的管理基线定义与按模型族覆盖ask_user的声明不是硬编码的单份 Schema而是采用基线 覆盖的管理方式。在 coreTools.ts 中export const ASK_USER_DEFINITION: ToolDefinition { get base() { return DEFAULT_LEGACY_SET.ask_user; }, overrides: (modelId) getToolSet(modelId).ask_user, };base指向 default-legacy.ts 中的默认声明前文引用的完整 JSON Schema 即来自这里工具描述为 Ask the user one or more questions to gather preferences, clarify requirements, or make decisions.overrides则允许针对特定模型族返回不同的声明仓库中存在gemini-3.ts、default-legacy.ts等模型族定义集。工具类通过getSchema(modelId)调用resolveToolDeclaration完成解析ask-user.ts因此不同模型拿到的是适配其能力的同一语义 Schema。工具在注册时的描述也取自该定义的base.description。测试、行为评估与可运行示例围绕该工具仓库提供了多层次的验证与演示资源单元测试ask-user.test.ts 覆盖参数校验、归一化与执行结果等行为行为评估evalask_user.eval.ts 以端到端方式评估模型在真实会话中提问的行为是否符合预期evals 目录的用途见 evals/README.mdUI 演示packages/cli/examples/ask-user-dialog-demo.tsx 是一个独立的可运行示例展示对话框的交互形态相关文档工具总览见 docs/reference/tools.mdask_user也在 docs/cli/plan-mode.md、docs/cli/telemetry.md 等文档中被引用说明它与计划模式确认、遥测统计等场景存在联动。小结ask_user把模型想问什么和用户如何作答解耦成了清晰的三段式协议模型按严格的 JSON Schema1-4 题、三种题型、2-4 选项发起调用 → core 层通过AskUserInvocation的确认回调把问题投递到 UI 并挂起执行 → 用户答案经确认总线以{ [questionIndex]: string }形式回流最终序列化为{answers: {...}}返回给模型用户关闭对话框则得到明确的取消信号与指标。理解这条链路ask-user.ts、confirmation-bus/types.ts、model-family-sets后你既可以准确构造该工具的调用参数也能判断其在非交互模式、计划模式等受策略约束场景下的行为边界。【免费下载链接】gemini-cliAn open-source AI agent that brings the power of Gemini directly into your terminal.项目地址: https://gitcode.com/GitHub_Trending/gemi/gemini-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进