NATIVE PICKER / POC

阶段性验证报告 · CURRENT STATE

能力已证实,产品化仍差一步。

Codex 在 Default Mode 中确实可以显示原生三选一界面;但当前实现依赖隐藏开关, 且启用后必须新建任务才能生效。技术路径跑通了,顺滑的一次会话体验还没有跑通。

01 / 验证路线与证据

一条路线讲完:能不能做、在哪里失败、最后为什么停。

每一步只回答三件事:观察到了什么、证据在哪里、它改变了什么判断。 不先讲完过程再补证据,也不把一个平台的成功外推到另一个平台。

先从官方协议确认“它是什么”

官方公开名称是 request_user_input;App Server 对应 tool/requestUserInput。它能展示 1–3 个结构化问题,但官方仍将 这条接口标为 experimental。

官方资料

第一轮 POC:证明交互形态存在

我们先做最小验证,只问一个问题、给三个润色方向。目标不是完成产品,而是确认 “模型调用工具 → 客户端显示选择器 → 用户提交答案”这条链路真实存在。

关键转折:Default Mode 被 Feature Flag 挡住

公开源码包含 default_mode_request_user_input,但当前处于 under development,默认关闭。Skill 可以要求模型调用工具,却不能凭空把一个 当前任务没有注册的工具“变出来”。

配置依据

绕开原生限制:手写 MCP 在 Ubuntu CLI 成功

我们实现了一个最小 MCP form elicitation。在 Ubuntu Codex CLI 的 Default Mode 中,它能稳定显示三选一表单并回传选择,证明外部协议路线本身可行。

实测成功|Ubuntu Codex CLI · Default Mode · 外部 MCP form elicitation

迁移到 Windows App:服务能接入,界面没有落地

同一思路进入 Windows 后,MCP 服务可以被注册,调用过程也能被观察到; 但 Windows Codex App 没有把它渲染为可用选择界面。CLI 的成功不能直接外推为 App 成功。

实测失败|Windows Codex App · 外部 MCP 路线 · 未观察到可用选择控件

回到原生路线:安装时启用,最多做到“两次任务”

安装 Skill 时可以顺带打开隐藏开关;新建任务后,原生选择器能正常出现。 但开关不会把工具热注入当前任务,因此“安装并立即使用”仍需跨任务。到这里, 技术可行性与产品体验的边界已经清楚。

实测成功|Windows Codex App · 新任务 · 原生 request_user_input
02 / 实现剖面

真正交付的不是一个界面,而是一套安装、开关与新任务调用的组合。

Skill 负责“怎么问”;安装脚本负责“把能力装进去”;开关脚本负责“让新任务获得工具”。 三者缺一不可,但也正因为工具表不会在当前任务重建,体验被切成了两段。

ROUTE A
外部 MCP
01 / BUILD 自研 form elicitation MCP
02 / UBUNTU CLI 三选一表单成功显示
03 / WINDOWS APP 服务可注册,调用可观察
04 / STOP 没有形成可用选择界面
ROUTE B
原生能力
01 / INSTALL 下载并校验 Skill 包
02 / COPY 复制到 Codex Skills 目录
03 / ENABLE 脚本写入 Feature Flag
04 / SESSION BOUNDARY 当前任务不刷新,必须新建任务
05 / WINDOWS APP Skill 调用原生 Picker 成功

四个文件,分别承担四个边界。

页面只展示会改变业务判断的核心片段:Skill 如何要求原生三选一、安装器如何校验并复制、 开关脚本如何备份和写入配置,以及为什么脚本成功后仍然要新建任务。

distribution/
├── install.ps1
└── native-picker-bootstrap-poc.zip
    └── native-picker-bootstrap-poc/
        ├── SKILL.md
        ├── agents/
        │   └── openai.yaml
        └── scripts/
            └── enable-native-picker.ps1
SKILL.md

只在工具可用时调用原生 Picker

Skill 不自己画三选一,也不退化成文本列表。它只定义问题与选项;如果当前任务没有工具, 就明确返回不可用。

Call `request_user_input` once:

- Header: `润色方向`
- Question: `请选择这次短文润色的方向。`
- Options:
  1. `自然流畅 (Recommended)`
  2. `生动有画面`
  3. `正式简洁`

If `request_user_input` is unavailable,
report `PICKER_NOT_INSTALLED` exactly.
install.ps1

下载、校验、复制,再调用开关脚本

安装器先核对 Skill 包的 SHA-256,避免把未知内容直接装进用户目录;校验通过后才复制并运行开关脚本。

$actualSha256 = (Get-FileHash $archivePath -Algorithm SHA256).
    Hash.ToLowerInvariant()
if ($actualSha256 -ne $expectedSha256) {
    throw "Package checksum mismatch"
}

Copy-Item -LiteralPath $sourceSkill `
    -Destination $installedSkill -Recurse
$enableScript = Join-Path $installedSkill `
    "scripts\enable-native-picker.ps1"
$featureResult = & powershell.exe -NoProfile `
    -ExecutionPolicy Bypass -File $enableScript |
    ConvertFrom-Json
enable-native-picker.ps1

备份配置,再把隐藏开关写成 true

脚本只修改 [features] 下的目标键:存在就替换,不存在就补入;写入前保留备份,写入后再读回验证。

$feature = "default_mode_request_user_input"
$configPath = Join-Path $env:USERPROFILE `
    ".codex\config.toml"

if (-not (Test-Path -LiteralPath $backupPath)) {
    [IO.File]::WriteAllBytes(
        $backupPath,
        [IO.File]::ReadAllBytes($configPath)
    )
}

$newBody =
    "default_mode_request_user_input = true" +
    $newline + $body

[IO.File]::WriteAllText(
    $configPath, $text, $utf8NoBom
)

if (-not $afterEnabled) {
    throw "Failed to enable $feature"
}
03 / 核心限制

Feature Flag 能打开能力,却不能改写当前任务的工具表。

这里最容易混淆的不是“开关有没有写进配置”,而是“当前任务启动时是否已经拿到工具”。 我们实测的边界是:配置可改,当前任务的能力集合不会随之重建。

TASK 01 / INSTALL

安装 Skill,并打开隐藏开关

配置写入成功;但这个任务启动时没有原生 Picker 工具,无法在同一任务内立即调用。

NEW TASK
REQUIRED
TASK 02 / USE

重新进入业务任务,选择器出现

新任务按最新配置构建工具表,Skill 才能调用原生 Picker 并继续短文润色。

技术上只是多一步,体验上却是一次明显中断。

普通用户想做的是“安装后马上使用”。如果必须先完成安装,再主动新建任务并重新输入业务需求, 用户会感知到系统边界,Skill 也失去了“一句话开始工作”的价值。因此当前不建议强行面向普通用户发布。

已证明 / PROVEN
Ubuntu CLI 的外部 MCP 表单可用;Windows App 的原生 Picker 在开关启用后的新任务中可用。
未证明 / OPEN
当前版本尚未证明能在同一任务中完成“安装 → 启用 → 立即调用”,也未证明外部 MCP 表单可在 Windows App 中形成稳定 UI。
当前判断 / DECISION
不把两次任务流程作为正式体验发布;保留成果、观察官方演进,并把下一轮资源投入到更自然的会话内呈现方式。
04 / 未来展望

现在最合理的策略,不是继续堆补丁,而是等待能力成熟。

官方协议已经存在,原生界面也已实测出现;当前缺口集中在 Default Mode 的成熟度与会话内刷新机制。 这比“从零不存在”更接近官方后续可以自然补齐的状态。

NOW / 当前策略

保留 POC,不把两次任务包装成完整体验

保存 Skill、脚本与实测证据,避免继续为临时限制叠加复杂安装逻辑。

WATCH / 关注信号

等待 Default Mode 原生开放或支持任务内刷新

重点关注 Feature maturity、客户端工具注册和 App Server 相关更新。

REUSE / 已沉淀资产

CLI MCP 路线与原生路线都已明确边界

后续无需重复证明基础协议;只需验证新版本是否跨过当前会话边界。

DECISION / 阶段结论

技术验证通过,产品化暂缓

这不是功能做不到,而是当前实现成本与用户体验不匹配。

05 / 下一步

把问题从“工具能否注入”转向“选择如何自然出现”。

下一轮只验证一个新命题:能否在会话进行中直接弹出 HTML,承接用户选择并继续业务流程。

当前原生 Picker POC 到此阶段性收口。新方向独立验证,不把尚未验证的路线提前写成结论。