免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

OpenClaw ask_user 工具实战指南:让 Agent 暂停回合、向人类提出结构化问题并等待决策

OpenClaw ask_user 工具实战指南:让 Agent 暂停回合、向人类提出结构化问题并等待决策 OpenClaw ask_user 工具实战指南让 Agent 暂停回合、向人类提出结构化问题并等待决策【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclawask_user是 OpenClaw Agent 运行时内置的阻塞式人机交互工具当任务推进到真正属于用户决策的岔路口时Agent 可以暂停当前回合向用户提出 13 个结构化问题单选、多选或自由文本等待回答后带着答案继续执行。本指南将以 docs/tools/ask-user.md 为骨架结合源码深入讲解工具的工作方式、回答渠道、超时与无应答语义、Tool Schema 与协议实现帮助你理解如何设计、回答与调试一次 ask_user 交互。ask_user 是什么何时该用、何时不该用ask_user的核心契约是让 Agent 向人类提出一个到三个结构化问题并暂停回合等待答案。它只服务于本质上属于用户决策的场景——例如选择部署目标、确认对外发布范围、挑选一组要执行的检查项——而不是常规的进度确认也不是 Agent 可以从请求、代码或合理默认值中自行推导的信息。源码佐证工具描述预设位于 tool-description-presets.ts 中的describeAskUserTool与ASK_USER_TOOL_DISPLAY_SUMMARY模型侧指导见下文模型使用指导明确要求仅在真正被用户拥有的决策阻塞时才提问并且不得用来询问是否可以继续、或确认自己的计划。一个重要限制该工具只在主会话main session中可用。子代理subagent以及其他非主运行不会收到此工具。从实现看工具创建函数createAskUserTool需要携带agentId、sessionKey、runId等主运行上下文并且与当前会话已回答问题的注册表registerPendingAgentQuestion绑定见 ask-user-tool.ts。如何回答一个 ask_user 问题OpenClaw 支持在多种对话表面回答结构化问题回答渠道与呈现方式取决于你所在的界面Web Control UI在输入框composer正上方停靠一个问题面板。多问题提示会一次显示一个问题并通过一个简短的 stepper 逐步推进问题解决后面板关闭聊天中只保留一条紧凑的答案摘要。TUI终端界面在 Gateway 模式和本地模式都会显示问题提示。使用方向键或数字键选择选项选择Other…输入自定义答案或选择Skip跳过。多选提示允许先勾选再确认多问题提示一次推进一个。按 Esc 可退回输入框而不作答之后用/question命令重新打开提示。Telegram单个单选问题会渲染为全宽原生按钮。Other…会切换到 Telegram 的回复输入框而不立即解决该问题。Discord、Slack、Mattermost单个选择、单个问题会渲染原生按钮。Mattermost 会在接受的点击上退休该提示若问题在其他地方被结束按钮会保留在原处直到有人点击并被告知该问题已被回答。任意渠道的纯文本回复只要问题来自一个活跃的 OpenClaw 运行且你当前的权限与创建者匹配就可以用纯文本回复输入数字、选项标签或你自己的答案多选问题用逗号分隔各选项。需要特别注意两种边界情况来自独立attachedMCP 客户端的问题不带 OpenClaw 运行的创建者绑定见 docs/cli/attach.md。这类问题应使用 Control UI、TUI 或原生 App 中的问题控件来回答而不是普通渠道消息。绝对不要用 ask_user 回答凭据类问题。当 Agent 需要 API Key 时应使用secrets工具其掩码提示masked prompt会存储值而不会让它进入聊天、转录或模型上下文。OpenClaw 始终为每个问题启用自由文本Other答案因此Agent 不得在自拟的选项列表中添加Other选项这与下文协议中isOther字段的自动注入一致。各平台行为差异Control UI 与 TUI 一次显示一个问题收起提示后输入框恢复并出现一个细窄的待处理问题指示器。TUI 的/question命令可重新打开提示普通回复依然可以回答符合条件的待处理问题。iOS、macOS 与 Android 显示内联卡片多个问题会刻意保持堆叠排列这是面向触屏的交互习惯TUI 在聊天中保留一条紧凑的解决通知其他平台保留问题到答案摘要且不做定时驱逐。Skip 在所有平台可用用于拒绝整个提示不是单个问题。多问题/多选提示在消息类渠道上会降级为可读文本Control UI 与 TUI 保留完整结构化 stepper。TUI 会显示剩余时间、关闭已过期的提示并在重连或切换会话后为所选会话恢复待处理问题本地模式下问题保存在运行进程中退出 TUI 后不会存续。超时与无应答语义ask_user的默认超时是900 秒15 分钟timeoutSeconds会被钳制在303600 秒范围内。这是一个最大人工等待时间仍然受更早的 Agent 运行取消或整体运行超时约束——待处理问题不会延长明确的运行预算。如果问题在收到答案前过期或被取消工具返回status: no_answerAgent 随后按自己的最佳判断继续执行。被中止的 Agent 运行会取消其待处理的 Gateway 问题。Gateway 的问题记录包含可选的来源runId。客户端可以用它在重连、并通过question.list或question.get恢复问题后将提示及其终态答案摘要与正确的 Agent 回合关联起来。源码中与这些语义一一对应常量定义与钳制逻辑在 ask-user-tool-normalization.tsDEFAULT_ASK_USER_TIMEOUT_SECONDS 900、MIN_ASK_USER_TIMEOUT_SECONDS 30、MAX_ASK_USER_TIMEOUT_SECONDS 3600normalizeQuestionTimeoutSeconds对非法值抛ToolInputError对合法值做Math.min/Math.max钳制。RPC 层面还会叠加QUESTION_RPC_GRACE_MS 10_000的宽限resolveQuestionTimeoutMs返回timeoutSeconds * 1000 10000用于question.waitAnswer这类等待调用避免因网络开销提前判定超时同文件 ask-user-tool-normalization.ts。无应答的结果构造在noAnswerResult中cancelled时提示 The question was cancelled; proceed with best judgment.否则提示 No answer arrived; proceed with best judgment.见 ask-user-tool.ts。运行中止会通过createGatewayQuestionCanceller以run-abort原因取消 Gateway 问题ask-user-tool.ts。Tool Schema 详解ask_user的入参 JSON Schema 如下模型实际收到的参数会经过归一化与校验见下文{ questions: Array{ id: string; // unique snake_case answer key header: string; // short label; truncated to 12 characters question: string; // one sentence options: Array{ label: string; description?: string; }; // 2-4 options multiSelect?: boolean; }; // 1-3 questions timeoutSeconds?: number; // integer; default 900, clamped to 30-3600 }要点说明id唯一的 snake_case 答案键用于把答案映射回问题。正则约束为^[a-z][a-z0-9_]*$。header短标签超过 12 字符会被截断实现使用 UTF-16 安全的截断见truncateUtf16Safeask-user-tool-normalization.ts。question一句话问题。所有可选项都必须放进options不能只写在问题文本里。options24 个选项每个label非空且不超过 64 字符建议 15 个词description可选。multiSelect为true时用户可选择多个选项。无论是否多选答案值对每个问题都以数组形式返回。timeoutSeconds可选整数默认 900钳制在 303600。补充细节归一化器会在每个问题上自动注入isOther: trueask-user-tool-normalization.ts这正是OpenClaw 始终启用自由文本 Other 答案、Agent 不得自拟 Other 选项这一规则的实现来源。回答结果示例{ status: answered, answers: { answers: { deploy_target: [Staging (Recommended)] } } }外层的answers是协议的QuestionAnswers信封内层answers映射以questionId为键每个问题对应一个选中值数组。协议 schema 定义在 packages/gateway-protocol/src/schema/questions.tsexport const QuestionAnswersSchema closedObject({ answers: Type.Record(QuestionIdSchema, Type.Array(Type.String())), });工具侧会把状态与文本结果一起返回给模型answeredResult先输出每道题的header: 值行再附上 JSON 载荷ask-user-tool.ts。底层调用链从工具执行到 Gateway 协议ask_user的执行不是本地一问一答而是一条跨模块的阻塞式 RPC 链路。从 ask-user-tool.ts 的execute实现可以还原出完整流程归一化与校验normalizeAskUserParams(args)校验问题数13、选项数24、id 唯一性与 snake_case 格式、header 截断、超时钳制失败则释放预留并抛ToolInputError。预留与去重同一会话同一时刻只允许一个待处理问题——reserveAskUserPromptDelivery会先检查会话是否已有 pending 问题beginAskUserPromptDelivery在重复请求时抛出 a question is already pending for this sessionask-user-tool.ts。注册与请求通过registerPendingAgentQuestion建立本进程内的问题登记带答案权威校验withAgentQuestionAnswerAuthority再调用 Gateway RPCquestion.request提交{ id, questions, agentId?, sessionKey?, runId?, timeoutMs }。等待答案调用question.waitAnswer带timeoutMs QUESTION_RPC_GRACE_MS与includeResolutionId: true并同时等待提示投递完成用Promise.race竞争提示投递完成与答案到达两个信号。终态处理finishWait根据QuestionWaitAnswerResult的四种状态pending/answered/cancelled/expired决定返回answeredResult还是noAnswerResult若pendingwaitAnswer 先返回待处理会主动调用取消 RPC 争取拿到已提交的答案。失败兜底注册被拒QUESTION_ID_IN_USE或提示投递失败时走cancelPendingQuestion取消必要时返回delivery_failed终态并标记terminate: true。协议层由 packages/gateway-protocol/src/schema/questions.ts 定义关键类型包括QuestionRequestParamsSchemaquestion.request入参questions数组 13 个、可选id/agentId/sessionKey/runId/timeoutMs。QuestionRecordSchema规范化后的完整问题记录含createdAtMs、expiresAtMs、status、answers?、resolvedBy?、runId?。QuestionWaitAnswerResultSchema四种终态联合。QuestionResolveParamsSchema支持提交答案或取消两种形态。QuestionGet/ListParamsSchemaquestion.get、question.list查询。QuestionRequestedEventSchema/QuestionResolvedEventSchema自 2026.7 起的事件协议原生端复用同一QuestionRecordschema。这些 RPC 的 Gateway 端方法位于 src/gateway/server-methods/question.tsQA 场景的 codeRefs 亦指向该文件。模型使用指导Model Guidance模型面对的提示词契约要求 Agent 遵守以下行为这也是写 prompt / 调试时最值得核对的自检清单仅在真正被用户拥有的决策阻塞时才提问每次调用只问一个问题除非多个答案必须一起提交——因为单问题提示可以使用消息渠道的原生控件把每个可选项放进options绝不能只写在问题正文里仅在需要同时选择多个选项时才用multiSelect把推荐选项放第一位并在其 label 后缀加上(Recommended)不要自拟Other选项自由文本会自动添加收到no_answer后按最佳判断继续执行。此外还有一条硬性约束不要用 ask_user 询问是否可以继续或确认自己的计划——这类确认应使用既有的审批/执行授权机制而不是把人机问答当作流程确认开关。实战验证一条端到端 QA 场景仓库的 QA 场景 qa/scenarios/runtime/tools/ask-user.yaml 完整演示了一次提问—阻塞—回答—恢复的往返模型调用一次ask_user同时提交单选框deploy_target、多选框checks与自由文本release_note三种形态60 秒超时QA Channel 在 Agent 运行保持阻塞期间投递结构化提示Gateway 解析后以规范化的选中值恢复同一运行最终回复必须证明 Agent 收到了单选、多选与自由文本三类答案ASK-USER-ROUNDTRIP-OK | deployProduction | checksUnit,E2E | notenight-shift。对应地单元测试 src/agents/tools/ask-user-tool.test.ts共 1000 行覆盖了question.request/question.waitAnswer的发起、同一会话重复提问被拒绝、无应答/取消/过期终态、提示投递失败与delivery_failed终止、以及normalizeAskUserParams对非法参数空选项、超长 label、非法 id 等的拒绝其validArgs示例与文档 schema 完全一致。另有 test/contracts/ask-user-msteams-presentation.test.ts 验证 Microsoft Teams 渠道的按钮化呈现契约。小结ask_user是 OpenClaw 中人机协作决策的正式通道它通过 Gateway 协议把 Agent 回合暂停与全平台问题投递解耦用统一的QuestionAnswers信封回传答案并用no_answer语义保证无人应答时 Agent 仍可自主推进。编写 Agent 提示词时记住三条铁律问题放options、推荐项标(Recommended)并排第一、绝不手写Other回答问题时选择你所在界面最顺手的渠道即可——所有渠道共享同一份 pending 问题状态。深入阅读 docs/tools/ask-user.md、packages/gateway-protocol/src/schema/questions.ts 与 src/agents/tools/ask-user-tool.ts即可掌握从工具契约到协议实现的全貌。【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表