DirectProject 客户端 Skill 自然语言触发能力缺口 #236
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
DirectProject 客户端 Skill 自然语言触发能力缺口
1. 问题摘要
AGC 已经可以把用户导入的 Skill 安装到客户端,并在下一次 DirectProject 启动时注入真实 Codex app-server。使用 Codex 原生的
$skill-name形式时,导入的 Skill 可以被读取并执行。目前缺少的是:用户在普通自然语言中直接提到 Skill 名称时,AGC 没有把这次请求确定性地绑定为 Codex 的 Skill 输入项。结果是模型可能只看到用户提到了一个名称,并把“调用 Skill”误解成调用一个工具,返回“没有可调用接口”,而不是读取
SKILL.md。这不是 Skill 导入失败,也不是需要把 Skill 改造成 MCP 工具;是 AGC 客户端没有复用 Codex 官方客户端的 Skill 输入适配层。
2. 当前 AGC 如何使用 Skill
2.1 客户端导入
用户在客户端设置的“扩展”页面导入文件、目录或 zip。目录或 zip 中发现的每个
SKILL.md会成为独立的 Skill 扩展项,可以单独启用、禁用、重命名和删除。已识别的 Skill 导入后默认启用。扩展内容保存于 AGC 客户端扩展仓库,不直接写入用户全局
CODEX_HOME。2.2 DirectProject 启动时注入
创建或复用 DirectProject 的 Codex app-server 时,AGC 会:
enabled=true的 Skill;skills/extraRoots/set;skills/list重新发现 Skill。AGC 侧的运行时目录准备位于
client_extensions.rs的prepare_enabled_client_skill_root,app-server 的 Skill root 注册位于codex_app_server.rs。Skill 配置从下一次 DirectProject 启动生效,当前已经运行的 Codex 会话不热更新。首页的 DirectHome 不作为客户端 Skill 的运行时入口。
2.3 当前可用的触发方式
Codex 原生显式触发方式是:
这个方式已经在 AGC 中验证成功,测试 Skill 返回:
这证明导入、启用、运行时 Skill root 注入、Codex 发现和 Skill 正文执行链路已经打通。
3. 当前缺少的能力
3.1 普通自然语言名称没有确定性绑定
以下输入目前不能稳定触发导入的 Skill:
实际结果是模型报告“当前没有可调用该 Skill 的工具接口”。这句话在“Skill 不是工具”这一点上没有错,但没有完成 Skill 指令的读取和应用。
3.2 AGC 没有发送结构化 Skill 输入项
Codex 官方 TUI 在识别
$skill-name或用户从 Skill 提及菜单选择后,会向turn/start输入中追加类似内容:对应实现见 Codex 仓库中的
codex-rs/tui/src/chatwidget/input_submission.rs。随后 Codex core 会根据结构化输入加载 Skill 正文。AGC 当前的
codex_app_server_turn_input只把用户消息整理成普通文本和图片输入,没有追加type: "skill"项。3.3 “能发现”与“本轮已使用”没有明确的客户端绑定
AGC 启动时会设置
skills/extraRoots并调用skills/list,这只能证明 Skill 在当前 app-server 进程的发现范围内。它不等于本轮已经选中了某个 Skill,也不等于模型一定会读取该 Skill 的正文。Codex 的 Skill 扩展会把可用 Skill 目录和使用规则放入模型上下文,但普通文本相关性判断主要交给模型;它不是 AGC 客户端已经完成的确定性绑定。
4. Codex 源码中的相关分层
4.1 模型侧使用规则
Codex 仓库中的
codex-rs/ext/skills/src/catalog_prompt.rs会向模型说明:用户用$SkillName或普通文本点名 Skill,或者任务符合 Skill 描述时,应使用该 Skill。这是一条模型行为指令,不是一个保证命中的
if user_text.contains(...)路由器。普通自然语言是否命中,仍取决于模型能否看到对应目录、是否理解名称和描述,以及是否调用skills.read。4.2 显式 Skill 选择
Codex 仓库中的
codex-rs/ext/skills/src/selection.rs会处理结构化UserInput::Skill,也会解析文本中的$skill-name。选中后,core 在回合开始阶段读取并注入 Skill 正文。4.3 “隐式 Skill”不是普通自然语言路由
源码中的
implicit invocation主要用于命令或脚本访问某个 Skill 的资源目录时记录/识别对应 Skill,入口在 Codex 仓库的codex-rs/ext/skills/src/invocation.rs。它不是一个根据任意用户自然语言自动选择 Skill 的通用分类器。4.4 相关性选择实验不是当前确定性注入
Codex 的
shadow_selection/skill_search相关实现会对任务和 Skill 描述做词法/相关性排序,但当前是 shadow 观测路径,不直接替当前回合注入 Skill,不能作为 AGC 当前缺口的现成解决方案。5. 复现步骤
准备一个普通的 Skill 导入目录,目录中放置一个
SKILL.md。例如:该目录和文件可以由 Issue 提交者在自己的测试环境中临时创建,不依赖仓库外的固定目录或本机产物。
复现:
在客户端“扩展”中导入包含上述
SKILL.md的目录;确认列表显示
import-smoke-skill、类型为 Skill、状态为“已启用”;新开一个 DirectProject 会话;
依次发送:
预期现象:前两条不会稳定加载 Skill,第三条返回
SKILL_IMPORT_OK。6. 可能的修复方向
以下只是供 Issue 讨论的候选方向,不在本文锁定具体实现。
方向 A:客户端显式绑定用户点名的 Skill
AGC 在发送回合前,根据当前已启用 Skill 列表识别用户明确提到的名称,并把匹配项转换成 Codex 原生的
type: "skill"输入项,同时保留原始用户文本。优点是行为确定、与官方 TUI 的协议一致;需要讨论名称边界、重名处理和用户文本中普通单词与 Skill 名称的冲突。
方向 B:增加 Skill 提及选择入口
在聊天输入框提供 Skill 名称补全或选择入口。用户选择后,客户端保存/发送结构化 Skill 绑定,而不是要求用户手写
$。优点是用户不需要了解 Codex 协议标记;需要额外的前端交互设计,且要决定是否在 DirectProject 聊天区增加入口。
方向 C:仅支持 Codex 原生
$skill-name保持当前实现,只把
$skill-name作为 Skill 的正式调用方式,并在测试和使用说明中明确这一点。优点是改动最小;缺点是用户需要知道 Codex 的 Skill 提及语法,普通中文“请使用某 Skill”仍不会得到确定性支持。
方向 D:依赖模型根据 Skill 目录自行判断
让 Skill 目录和描述保持模型可见,由模型在普通任务中自行判断是否需要调用
skills.read。这种方式可以覆盖“任务适合某 Skill”而不仅是精确名称,但结果受模型判断和上下文影响,不适合作为“用户明确点名后必须使用”的唯一保证。
7. Issue 建议关注点
提 Issue 时建议先确认产品契约,而不是直接指定实现:
$skill-name;本 Issue 不应扩大为:重新设计 Skill/MCP 导入格式、把 Skill 做成 MCP 工具、增加第三方内容安全扫描、增加脚本沙箱,或重做 Codex Plugin Runtime。
Issue 已经把“发现 Skill”和“本轮确定使用 Skill”区分清楚,建议把方向 A 作为默认产品契约:普通中文明确点名已启用 Skill 时,客户端按启用清单做名称匹配并生成 Codex 原生的结构化 skill 输入,同时保留原始用户文本;单纯依赖模型相关性判断不能作为确定性保证。
实现前请锁定边界:手动重命名后的精确匹配与规范化规则、重名 Skill 的处理、禁用/未找到时的提示和普通对话回退、与 MCP Server 同名时的解析优先级,以及是否在回合记录/UI 展示本轮实际注入的 Skill。回归用例应同时覆盖普通中文点名、原生 $skill-name、名称出现在普通句子但未明确要求使用、找不到 Skill 和重启后新 DirectProject 会话;不要把 Skill 改造成 MCP 工具。