Load selected executor skills through extensions - #27184
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5d7823925c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fec64281b4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
anp-oai
left a comment
There was a problem hiding this comment.
Couple small things, lgtm overall
Why
CCA is moving toward a split runtime where the orchestrator may not have a filesystem, while executors can expose preinstalled plugins and skills. A thread therefore needs to select capabilities without asking app-server or core to interpret executor-owned paths through the orchestrator's filesystem.
The longer-term model is broader than executor skills:
This PR establishes that architecture through one complete vertical: selecting a root on an executor, discovering the skills beneath it, exposing those skills to the model, and reading an explicitly invoked
SKILL.mdthrough the same executor.Contract
thread/startgains an experimentalselectedCapabilityRootsfield:{ "selectedCapabilityRoots": [ { "id": "deploy-plugin@1", "location": { "type": "environment", "environmentId": "workspace", "path": "/opt/codex/plugins/deploy" } } ] }The root is intentionally not classified as a "plugin" or "skill" in the API. It can point at a standalone skill, a directory containing several skills, or a plugin containing skills and other components. This PR only teaches the skills extension how to consume it; later extensions can resolve MCP, connector, and hook components from the same selection.
The platform-supplied
idis stable selection identity. The location says which runtime owns the root and gives that runtime an opaque path. App-server does not inspect or canonicalize the path.What changed
Generic thread extension initialization
App-server converts selected roots into
ExtensionDataInit. Core carries that generic initialization value until the final thread ID is known, then creates thread-scopedExtensionDatabefore lifecycle contributors run.This keeps
Sessionand core independent of the capability-selection contract. The initialization value is consumed during construction; it is not retained as another long-livedSessionfield.Executor-backed skills
The skills extension now owns an
ExecutorSkillProviderthat:EnvironmentManagerExecutorFileSystemSkill catalog and instruction fragments have hard byte bounds, which also bound them below the 10K-token per-item context limit. If a selected executor skill has the same name as a legacy local skill, the executor selection owns that invocation and the local body is not injected a second time.
Existing local and bundled skill loading remains in place. Omitting
selectedCapabilityRootstherefore preserves current local-only behavior.Current semantics
Planned vertical follow-ups
Each follow-up remains reviewable as an end-to-end capability. The platform selects roots, generic thread extension data carries the selection, and the owning extension resolves and operates its component.
Verification
Coverage added for:
Targeted protocol, core-skills, skills-extension, core lifecycle, and app-server executor-skill tests were run during development.