☰
【GUI-Agent】阶跃星辰 GUI-MCP 解读---(6)---HITL 配置骨架:从 settings.json 到 TaoToken 统一 Key 通道
2026/9/29 10:07:56 网站建设 项目流程

1. 为什么 HITL 配置总在“最后一公里”卡住

GUI-Agent 跑自动化任务时,最怕的不是模型不会点,而是它太敢点。阶跃星辰 Step-GUI 里的 GUI-MCP 把 HITL(Human In The Loop)做成了协议级能力:当 Agent 遇到验证码、支付确认、信息补充这类需要人类判断的节点,会抛出一个 INFO 动作,把执行权交还给客户端。这个设计本身很清晰,但落到工程配置层,问题就来了——settings.json 里 reply_mode 写哪个值、session_id 怎么透传、人工回复通过什么通道回注给 Agent,这些细节一旦配错,Agent 要么卡死在 INFO 循环里,要么直接跳过确认把敏感操作执行了。

我试过在本地把 GUI-MCP 的 HITL 链路完整跑通,发现真正耗时间的不是理解协议,而是把“人工审批”这个动作接到一个稳定的 Key/API 通道上。因为 HITL 回调本质上是一次带上下文的模型请求:客户端拿到 INFO 动作后,需要把截图、任务描述、Agent 的提问一起发给一个能理解多模态输入的模型,生成人类可读的确认提示,再把用户的回复回注给 Agent 继续执行。这条链路里如果 Key 管理散落在多个配置文件,调试成本会成倍上升。

这篇就聚焦 HITL 的配置骨架:从 settings.json / config.toml 的字段定义,到 CC Switch、Cline 的接入示例,再到用 TaoToken 统一 Key 通道完成一次人工审批回调的验证。目标很明确——把 HITL 从“协议里有个 INFO 动作”变成“我本地能跑通一次带人工确认的完整任务”。

适合谁看:正在给 GUI-Agent 加人工确认环节的开发者,手里已经有 Step-GUI 或类似 GUI-MCP 实现,需要把 HITL 落到配置文件层面的人。如果你还没接触过 GUI-MCP,建议先看前几篇关于 MCP 工具定义和 execute_task 流程的内容,这篇默认你已经知道 ask_agent_start_new_task 和 ask_agent_continue 的区别。

2. TaoToken 在 HITL 链路里承担什么角色

HITL 的核心动作是“暂停—人工输入—恢复”。在 GUI-MCP 的实现里,这个暂停由 reply_mode 控制,恢复靠 session_id + reply_from_client 两个参数。但人工输入的内容不是随便填的,它需要被模型理解成“对当前截图中某个问题的回答”。也就是说,客户端在把用户回复回注给 Agent 之前,往往要先做一次模型调用,把用户的自然语言回复转成 Agent 能消费的 query 字段。

这一步就是 TaoToken 介入的位置。TaoToken 提供统一的 API 通道,把模型调用收敛到一个 Key 上。对于 HITL 场景,这意味着:

  • 客户端侧不需要为“生成确认提示”和“解析用户回复”分别维护不同的模型配置;
  • settings.json 里只需要写一个 base_url 和一个 api_key,所有 HITL 相关的模型请求都走这条通道;
  • 调试时切换模型或调整参数,改一处配置即可,不用在多个文件之间同步。

TaoToken 的 API 地址是https://taotoken.net/api,官网入口在https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=。注意 API 地址不带 UTM 参数,配置里直接写裸地址就行。

需要说清楚的是,TaoToken 在这里不是“替代 GUI-MCP”,而是给 HITL 回调提供一个稳定的模型调用出口。GUI-MCP 负责协议和动作编排,TaoToken 负责让“人工审批”这个环节里的模型请求有统一的 Key 通道。两者是配合关系,不是替代关系。

3. settings.json 与 config.toml 配置骨架

GUI-MCP 的配置通常分两层:一层是 MCP 客户端侧的 settings.json,定义工具调用和 HITL 行为;另一层是模型通道侧的 config.toml,定义 API 端点和 Key。下面给出可复制的骨架。

3.1 settings.json:HITL 行为定义

{ "mcpServers": { "gui-mcp": { "command": "python", "args": ["-m", "gui_mcp.server"], "env": { "GUI_MCP_DEVICE_ID": "emulator-5554", "GUI_MCP_REPLY_MODE": "pass_to_client", "GUI_MCP_MAX_STEPS": "20", "GUI_MCP_SESSION_TIMEOUT": "300" } } }, "hitl": { "enabled": true, "reply_mode": "pass_to_client", "approval_required_actions": ["INFO", "PAYMENT_CONFIRM", "DELETE_CONFIRM"], "auto_reply_fallback": false, "session_persistence": true, "callback_timeout_seconds": 120 } }

这里几个字段值得展开:

reply_mode设成pass_to_client是 HITL 的关键。GUI-MCP 支持四种模式:auto_reply让模型自动生成回复,no_reply直接忽略(Agent 可能卡死),manual_reply在服务端控制台手动输入,pass_to_client把 INFO 动作抛回客户端。要做人工审批,必须用pass_to_client。

approval_required_actions列出需要人工确认的动作类型。除了 INFO,支付和删除类操作也建议加进来,避免 Agent 在敏感节点自作主张。

session_persistence打开后,session_id 会持久化到本地,HITL 中断后可以用同一个 session_id 恢复,不用重新初始化任务。

3.2 config.toml:TaoToken 统一 Key 通道

[model_provider] name = "taotoken" base_url = "https://taotoken.net/api" api_key = "sk-your-taotoken-key" default_model = "step-gui" timeout_seconds = 60 max_retries = 3 [hitl_model] provider = "taotoken" model = "step-gui" temperature = 0.2 max_tokens = 512 purpose = "hitl_approval_prompt" [logging] level = "info" log_dir = "./logs/gui-mcp" log_hitl_events = true

base_url写 TaoToken 的 API 地址,api_key从 TaoToken 控制台生成。hitl_model这一段专门给 HITL 回调用,temperature 调低是因为确认提示需要稳定输出,不需要创造性。log_hitl_events打开后,每次 INFO 动作的触发、人工回复、恢复执行都会记日志,排查时很有用。

Key 的获取路径:登录 TaoToken 控制台,在 API Keys 页面创建新 Key。控制台入口是https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=,API Keys 页面是https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=。创建时建议给 Key 起个能识别的名字,比如gui-mcp-hitl-dev,方便后续按环境区分。

3.3 CC Switch 接入示例

CC Switch 用来在多个模型通道之间切换。把 TaoToken 配成一个 profile:

{ "profiles": { "taotoken-hitl": { "base_url": "https://taotoken.net/api", "api_key": "sk-your-taotoken-key", "model": "step-gui", "description": "GUI-MCP HITL 专用通道" } }, "active_profile": "taotoken-hitl" }

切换时只需要改active_profile,不用动 settings.json 里的 HITL 配置。这样调试阶段可以在不同模型之间快速对比 HITL 确认提示的质量。

3.4 Cline 接入示例

Cline 作为 MCP 客户端时,配置写在 Cline 的 settings 里:

{ "cline.mcpServers": { "gui-mcp": { "command": "python", "args": ["-m", "gui_mcp.server"], "env": { "GUI_MCP_REPLY_MODE": "pass_to_client" } } }, "cline.apiProvider": "taotoken", "cline.apiBaseUrl": "https://taotoken.net/api", "cline.apiKey": "sk-your-taotoken-key", "cline.model": "step-gui" }

Cline 侧的关键是apiProvider指向 TaoToken,这样 Cline 在处理 HITL 回调时,模型请求会走统一通道。如果 Cline 和 GUI-MCP 用的是同一个 Key,配置里只需要维护一份 api_key。

4. 验证一次人工审批回调

配置写完后,需要跑一次完整的 HITL 回调来验证链路。下面用一个“打开淘宝搜索生日礼物”的任务来演示,任务会在搜索前触发 INFO 动作,要求人工确认搜索关键词。

4.1 启动 MCP 服务并初始化任务

先确认设备连接:

python -m gui_mcp.server --list-devices

输出里应该能看到设备 ID,比如emulator-5554。然后通过 MCP 客户端调用ask_agent_start_new_task:

{ "tool": "ask_agent_start_new_task", "arguments": { "device_id": "emulator-5554", "task": "打开淘宝,搜索生日礼物,遇到需要确认的步骤停下来问我", "max_steps": 20, "reply_mode": "pass_to_client" } }

注意reply_mode显式写成pass_to_client,覆盖 settings.json 里的默认值,确保这次调用走人工审批路径。

4.2 捕获 INFO 动作

Agent 执行几步后,会在搜索框输入前触发 INFO。返回结构大致如下:

{ "stop_reason": "INFO_ACTION_NEEDS_REPLY", "session_id": "sess_abc123", "final_action": { "action_type": "INFO", "value": "请确认搜索关键词:生日礼物。是否继续?" }, "global_step_idx": 3 }

stop_reason是INFO_ACTION_NEEDS_REPLY,说明 HITL 中断生效。session_id要记下来,恢复时要用。final_action.value就是 Agent 抛给人类的问题。

4.3 通过 TaoToken 通道生成确认提示

客户端拿到 INFO 后,调用 TaoToken 的模型接口,把截图和问题一起发过去,生成人类可读的确认提示:

curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-your-taotoken-key" \ -H "Content-Type: application/json" \ -d '{ "model": "step-gui", "messages": [ { "role": "system", "content": "你是 GUI-Agent 的人工审批助手。根据截图和 Agent 的提问,生成一句简洁的确认提示,不要多余解释。" }, { "role": "user", "content": "Agent 提问:请确认搜索关键词:生日礼物。是否继续?截图描述:淘宝首页,搜索框为空。" } ], "temperature": 0.2, "max_tokens": 128 }'

返回内容类似:

{ "choices": [ { "message": { "content": "Agent 准备在淘宝搜索「生日礼物」,确认继续?" } } ] }

这一步验证了 TaoToken 通道能正常处理 HITL 相关的模型请求。如果返回 401,检查 api_key 是否正确;如果返回 404,检查 base_url 是否写成了带路径的形式,正确写法是https://taotoken.net/api,不要在后面加/v1。

4.4 回注人工回复并恢复任务

用户在客户端确认后,把回复通过ask_agent_continue回注:

{ "tool": "ask_agent_continue", "arguments": { "device_id": "emulator-5554", "session_id": "sess_abc123", "reply_from_client": "确认,搜索生日礼物", "reply_mode": "pass_to_client", "max_steps": 20 } }

关键参数是session_id和reply_from_client。session_id用上一步返回的值,reply_from_client是用户的确认内容。task字段留空,因为这是继续会话,不是新任务。

调用成功后,返回结构里stop_reason会变成TASK_COMPLETED_SUCCESSFULLY或继续到下一个 INFO。如果还是INFO_ACTION_NEEDS_REPLY,说明 Agent 又抛了一个新问题,需要再次走审批流程。

4.5 验证结果

完整的成功链路应该看到:

  • 第一次调用返回INFO_ACTION_NEEDS_REPLY,带 session_id;
  • TaoToken 通道返回确认提示,HTTP 200;
  • 第二次调用返回TASK_COMPLETED_SUCCESSFULLY,global_step_idx 比第一次大;
  • 日志文件./logs/gui-mcp/hitl.log里有 INFO 触发和恢复记录。

如果日志里看到Passing INFO action to client for reply,说明pass_to_client模式生效了。

5. 本篇常见错排查

5.1 INFO 动作反复触发,Agent 卡在同一个问题

现象:调用ask_agent_continue后,返回的stop_reason还是INFO_ACTION_NEEDS_REPLY,final_action.value和上一次一样。

原因通常是reply_from_client没有正确传递,或者session_id对不上。检查两点:一是session_id是否用了第一次返回的值,不要自己拼;二是reply_from_client是否为空字符串,空字符串会被 Agent 当成“没有回复”,继续抛 INFO。

另一个可能是reply_mode在ask_agent_continue里被写成了auto_reply,导致 Agent 自己生成回复后又触发新的 INFO。确保两次调用的reply_mode都是pass_to_client。

5.2 TaoToken 返回 401 或 403

401 一般是 api_key 无效或过期。去 TaoToken 控制台确认 Key 状态,如果刚创建,等几秒再试。403 可能是 Key 没有对应模型的权限,检查default_model是否写成了控制台里已开通的模型名。

还有一种情况是 api_key 前面多了空格或换行,从控制台复制时容易带上。用echo -n "sk-xxx" | wc -c检查长度,或者直接在配置文件里重新粘贴一次。

5.3 settings.json 里 reply_mode 不生效

GUI-MCP 的工具调用参数优先级高于 settings.json 里的环境变量。如果ask_agent_start_new_task的 arguments 里没写reply_mode,才会用GUI_MCP_REPLY_MODE的值。调试时建议在 arguments 里显式写,避免被环境变量覆盖。

另外,GUI_MCP_REPLY_MODE的值必须是auto_reply、no_reply、manual_reply、pass_to_client四个之一,大小写敏感。写成Pass_To_Client会被当成未知模式,可能直接报错或回退到默认值。

5.4 session_id 持久化失败

如果session_persistence设为 true 但重启服务后 session_id 丢了,检查log_dir是否有写权限。session 文件默认存在./logs/gui-mcp/sessions/下,目录不存在时不会自动创建,需要手动建:

mkdir -p ./logs/gui-mcp/sessions chmod 755 ./logs/gui-mcp/sessions

5.5 Cline 侧 HITL 回调不走 TaoToken

Cline 的apiProvider如果写成openai或其他默认值,HITL 回调会走 Cline 内置的通道,不走 TaoToken。检查 Cline settings 里cline.apiProvider是否为taotoken,cline.apiBaseUrl是否为https://taotoken.net/api。改完后重启 Cline,让配置生效。

6. 把 HITL 配置固化下来的几个习惯

跑通一次回调之后,建议把配置固化下来,避免每次调试都重新拼参数。我的做法是:

把 settings.json 和 config.toml 都纳入版本管理,但 api_key 用环境变量注入,不写死在文件里。比如 config.toml 里写api_key = "${TAOTOKEN_API_KEY}",启动前 export 一下。这样配置文件可以共享,Key 不会泄露。

HITL 的日志单独存一个文件,和普通执行日志分开。排查时直接 grepINFO_ACTION_NEEDS_REPLY,能快速定位到所有人工审批节点。如果某个节点的确认提示质量不稳定,把对应的截图和 Agent 提问存下来,单独调 temperature 或换模型对比。

最后,approval_required_actions不要只写 INFO。支付、删除、发送消息这类动作,即使 Agent 没抛 INFO,也建议在客户端侧拦截一次。GUI-MCP 的 HITL 是协议级能力,但客户端侧的二次确认是最后一道防线。两者叠加,才能让 GUI-Agent 在自动化效率和操作安全之间找到平衡。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询