Skill的多源发现与身份定位机制

在Codex的Agent架构中,Skill并非仅来源于单一固定的目录,而是由多个来源共同组成的动态集合。这些来源包括当前工作仓库、用户主目录、管理员或Codex自身提供的默认资源,以及安装插件后引入的新能力。此外,如果当前会话连接到了其他执行环境或Orchestrator,这些远程环境也能提供专属的Skill。这种多源结构意味着Codex面对的不是一个简单的文件列表,而是一个需要统一管理的分布式技能生态。对于本地Skill,系统直接记录其SKILL.md的文件路径;而对于远程执行环境或Orchestrator提供的Skill,本地可能并不存在对应的物理文件。此时,系统记录的不是普通路径,而是Package或资源定位器(Resource Locator),后续通过特定的读取接口获取正文。这一设计揭示了一个关键细节:Skill的名字仅是给人和模型看的显示信息,真正确定其身份的是来源及定位方式。

“Codex面对的不是一个简单的 Skills 目录,而是多个来源共同组成的 Skill 目录。”

当Codex发现这些Skill后,会将它们组织成一段开发者上下文(Developer Context),外层使用skills_instructions标签包裹。其中包含Skill的名字、描述以及定位正文所需的路径或资源定位器。这里并不会将所有SKILL.md的全文展开,而是给模型提供一张能力目录,让模型知晓有哪些工作流可用。这种设计遵循了渐进式披露原则:先加载元数据,待模型决定使用时再读取正文。这种机制确保了上下文的高效利用,同时保持了系统的灵活性。

目录预算控制与同名冲突处理策略

为了防止Skill元数据占用过多上下文窗口,Codex实施了严格的预算限制机制。如果模型的上下文窗口已知,Skill元数据默认最多占用整个窗口的2%;若窗口大小未知,则退路为8,0随着Skill来源增多,同名冲突不可避免。例如,仓库、用户目录和插件可能都提供名为deploy的Skill。Codex不会自动合并这些同名项,也不会简单以后发现的覆盖前者。当用户通过$deploy引用时,只有在该名字能唯一对应一份已启用Skill时才完成选择。若存在同名冲突或同名的Connector,Codex不会随意挑选。

“Skill的名字只是给人和模型看的显示信息,真正确定它身份的是它来自哪里以及怎样定位到它的正文。”

在界面或命令行中选择Skill时,传入的是包含name(显示名)和path(消除歧义的路径)的结构化信息。这种设计强调了显示名不能作为稳定的身份标识,必须保留明确的来源和定位信息。如果Skill数量过多导致超出预算,Codex会优先缩短描述,若仍无法容纳则移除所有描述仅保留名字和定位信息;进一步超出预算时,才会省略部分Skill并向用户发出警告。这里需区分两个概念:2%的限制针对的是目录元数据,而非选中后正文的加载限制。

会话中的Skill激活与上下文注入流程

当用户在某一轮对话中临时选择某个Skill时,Codex会从当前的Skill快照(Snapshot)中进行解析。这个快照是该轮开始时对可用Skills生成的稳定视图。解析成功后,Codex读取对应的SKILL.md正文,并将其包装为独立的标签片段。该片段包含Skill的名字、路径和工作流说明,在模型请求中以user role发送,内容类型为skills.selected_skill_instructions。这并非系统提示词,也不是改写用户消息,而是Codex为当前轮次额外加入的模型可见上下文。原始用户消息依然保留。

“这段内容在模型请求里使用的是 user role,它还有一个独立的内容类型叫做 skills.selected_skill_instructions。”

这段标记有Skill标签的内容会进入会话记录,而非仅在本轮临时使用。这使得在组织下一轮输入、保存或恢复会话时,系统能识别出这是带有Skill注入的说明。然而,正文能否完整进入上下文取决于加载路径:本地加载通常直接读取整份SKILL.md,而插件或统一扩展加载的Skill受8KB上限限制,超出部分会被截断并提示。因此,不能笼统地说被选中的Skill总会完整放入上下文。

历史可见性与重新触发的逻辑区分

在会话管理中,需厘清三个关键问题:模型是否能看到上一轮加载的正文、下一轮是否会重新激活该Skill,以及再次提及时是否重新读取文件。正常情况下,包含Skill标签的片段已进入会话历史,只要仍在当前模型的历史窗口内,下轮请求即可看到。但历史中存在旧正文不等于保存了该Skill已激活的隐藏开关。显式选择发生在当前对话轮次,新一轮是否遵循旧说明书取决于模型可见的上下文及本轮是否再次触发。

“历史里存在了旧的正文,不等于还保存着一个这个 Skill 已经激活的隐藏开关。”

当重新提及已能从当前快照解析出的Skill时,Codex会再次读取正文。这意味着磁盘上的SKILL.md修改后重新选择可读到新版本。但名字、描述和可见目录属于发现结果,可能受缓存影响。新增或修改元数据需等待自动检测、强制重新加载(force reload)甚至重启Codex。简言之,压缩前旧正文可留历史中,但Skill的显式选择以当前轮次为单位;历史可见、当轮重新注入和重新读取是三件不同的事。

世界状态管理与动态更新机制

Codex并不每轮机械追加完全相同的Skill目录,而是将其作为世界状态(World State)管理。每一轮根据当前配置和环境计算有效Skills状态,若新状态与之前相同则不追加重复快照。模型请求重建上下文时仍保留当前有效目录,仅当Skill或执行环境变化产生新状态时才更新。这解决了两个问题:模型每轮需知可用Skill,且相同目录不应随对话重复占用空间。

“Codex并不是每轮都向历史末尾机械的追加一份完全相同的目录,当前实现把它作为一个 world state 在管理。”

若运行时安装新Skill,写入磁盘不等于进入当前轮次快照。Codex的Skill发现存在缓存(skills/list),产品支持自动检测变化,代码提供强制重新加载。若更新未被发现,官方建议重启Codex。刷新后新目录作为World State进入后续上下文,无需重写前面所有会话历史。此外存在安全边界:即使用户写出Skill名或路径,Codex仍需在已发现启用的集合中解析,防止任意文件伪装成Skill绕过发现和配置层。安装与启用分为两个状态,用户可在配置文件按名或路径禁用Skill而不删除文件。禁用的Skill不进入可用目录,也不能通过普通提及加载。

隐式调用策略与依赖管理流程

Skill可通过向agents/openai.yaml配置文件设置allow_implicit_invocation选项来控制隐式调用。默认为true,允许模型在任务与描述匹配时自动选择;设为false后,模型不应仅因任务匹配而自动调用,但用户仍可显式选择。此设计适用于有外部副作用、高成本或需明确确认的工作流。因此,Agent系统至少区分三件事:能力是否已安装、当前会话是否启用、以及是否允许隐式调用。

“如果把这个字段设为false,模型就不应该只因为任务匹配而自动调用。”

Skill可依赖其他工具如MCP Server。Codex客户端在skill_mcp_dependency_install功能开启时(默认开启)检查依赖。若未安装,需经策略和权限判断:某些情况自动批准,某些询问用户,部分环境因审批政策跳过。用户允许后Codex才写入MCP配置、完成OAuth并刷新会话中的MCP runtime。因此,Skill被选中不代表依赖可用,完整流程为:确认身份→加载说明→检查依赖→权限判断→执行。这解释了Skill、Plugin和MCP的区别:Skill描述工作流,MCP提供工具,Plugin打包分发。

多Agent继承与上下文压缩恢复

在多智能体系统中,子Agent可能有不同的工作目录、角色配置和执行环境。Codex不要求子Agent的有效目录与父Agent相同,新对话轮次使用当时有效的配置和环境取得Skill快照。源码测试显示父Agent能用某Skill,但子Agent因角色配置禁用该Skill从而不进入其能力视图。这启发我们:共享一套Skill仓库不等于每个Agent都应得到完全相同的能力,目录应根据职责、环境和权限重新筛选。

“共享一套Skill仓库不等于每个 Agent 都应该得到完全相同的能力,Skill 目录应该根据 Agent 的职责环境和权限重新筛选。”

Codex中Skill有两条生命周期:当前可用Skill的目录(World State)和某一轮实际加载过的正文(会话历史)。回滚或恢复时,Codex将Skill标签识别为上下文中的用户消息(Contextual User Message)。但经上下文压缩后,旧Skill标签片段不作为逐字用户历史保留。本地压缩用包含历史的模型输入生成摘要,再用真实消息和摘要重建;远端压缩返回的压缩历史也会过滤此类非真实用户上下文包装。恢复Agent会话时,不能只恢复聊天记录或扫描目录,更完整的做法是同时恢复当时发生的上下文历史并重新计算现在有效的能力状态。

异常处理与Skill全生命周期总结

Skill管理必须处理失败场景:SKILL.md缺少名字/描述、YAML无法解析、路径不可读、目录超预算、正文过长或MCP依赖/OAuth失败。Codex产生不同告警,如目录描述缩短量、忽略/省略的Skill数、显式选择是否成功注入及调用类型。对开发者而言,只统计安装数量无意义,更应关注成功发现、进入模型目录、选择后加载及因依赖权限无法执行的数量。

“对于Agent开发者来说,只统计安装了多少 Skill 没有太大的意义,更应该关心的是有多少被成功发现、多少进入了模型可见的目录。”

基于源码行为,可将Skill旅程归纳为7个阶段(非官方架构命名): 1. Discover:多源发现,仅读最小元数据。 2. Skill Directory:严格预算内提供可选能力给模型。 3. Parse:用稳定路径/资源定位器处理同名冲突。 4. Activate:将选中工作流说明作为独立上下文注入当前轮次。 5. Authorize:检查隐式调用策略、工具依赖和用户权限。 6. Persist:区分当前能力状态与会话历史中真正加载的说明。 7. Observe:记录发现、裁剪、注入和依赖失败情况。Skill不仅是Markdown文件,更是包含发现、路由、权限、状态和恢复机制的完整系统组件。

结论

Codex对Skills的管理并非简单的文件读取,而是一套包含多源发现、严格预算控制、世界状态管理、依赖权限校验及上下文生命周期维护的复杂机制。Skill的身份由来源和定位器决定,而非仅靠名字;其加载遵循渐进式披露原则以优化上下文窗口。系统通过区分目录元数据与正文注入、显式选择与世界状态更新,确保了Agent行为的精确性和安全性。对于开发者而言,理解Skill从发现到执行的七阶段旅程及异常处理逻辑,是构建健壮、可维护Agent系统的关键。恢复会话时需同时重建历史上下文与当前能力状态,而非仅依赖静态目录扫描。