What are skills?
Agent Skills explains the general idea behind skills. This note focuses on the Codex implementation: where skills are loaded, how they enter the prompt context, and how they affect tool routing.
Codex skills flow
High-level flow
At a high level, Codex loads the available skills during session setup, exposes them in the instruction context, then resolves explicit skill mentions on each turn.
+------------------------------+
| Session Spawn (Codex::spawn) |
+--------------+---------------+
|
v
+------------------------------+
| SkillsManager::new |
| - installs system skills |
+--------------+---------------+
|
v
+------------------------------+
| skills_for_config(config) |
| - load roots + cache by cwd |
| - disabled paths from config |
+--------------+---------------+
|
v
+------------------------------+
| enabled_skills() |
+--------------+---------------+
|
v
+------------------------------+
| get_user_instructions(...) |
| - render_skills_section(...) |
| - append to AGENTS.md output |
+--------------+---------------+
|
v
+------------------------------+
| Run Turn (run_turn) |
+--------------+---------------+
|
v
+------------------------------+
| skills_for_cwd(cwd) |
| - uses cached or reload |
+--------------+---------------+
|
v
+------------------------------+
| collect_explicit_skill_mentions
| - parse $skill + [link](path)
| - disambiguate vs connectors |
+--------------+---------------+
|
v
+------------------------------+
| resolve_skill_dependencies |
| - env var prompt if missing |
+--------------+---------------+
|
v
+------------------------------+
| build_skill_injections |
| - read SKILL.md contents |
| - make ResponseItem |
+--------------+---------------+
|
v
+------------------------------+
| record_conversation_items |
| - skill instructions in |
| prompt context |
+--------------+---------------+
|
v
+------------------------------+
| run_sampling_request |
| - tool filtering using |
| skill name counts |
+------------------------------+
Entry Points in core/src/codex.rs
use crate::skills::SkillsManager;
pub(crate) async fn spawn( mut config: Config, skills_manager: Arc<SkillsManager>) {
// When Codex spawns a new session, it loads skills from the active config layers.
let loaded_skills = skills_manager.skills_for_config(&config) // loads skills based on config layer stack and seeds the cache.;
let enabled_skills = loaded_skills.enabled_skills(); // filters out disabled paths.
let user_instructions = get_user_instructions(&config, Some(&enabled_skills)).await; // builds the instruction block and appends a **Skills** section via `render_skills_section`.
let session_configuration = SessionConfiguration {
user_instructions
}
}
The skill list becomes part of the session’s base instruction context, together with user instructions and AGENTS.md . The model can see which skills exist and how each skill should be used.
Per-turn skill resolution and injection
pub(crate) async fn run_turn(
) -> Option<String> {
let skills_outcome = Some(
sess.services
.skills_manager
.skills_for_cwd(&turn_context.cwd, false)
.await?,
);
let (skill_name_counts, skill_name_counts_lower) = skills_outcome.as_ref().map_or_else(
|| (HashMap::new(), HashMap::new()),
|outcome| build_skill_name_counts(&outcome.skills, &outcome.disabled_paths),
); // creates name counts (exact + lowercase) for disambiguation.
let mentioned_skills = skills_outcome.as_ref().map_or_else(Vec::new, |outcome| {
collect_explicit_skill_mentions(
&input,
&outcome.skills,
&outcome.disabled_paths,
&skill_name_counts,
&connector_slug_counts,
)
}); // scans user text inputs for `$skill` mentions and linked references like `[$skill](path)`
let explicit_app_paths = collect_explicit_app_paths(&input); // collects explicit `app://` mentions to support app tool routing.
let config = turn_context.client.config();
if config
.features
.enabled(Feature::SkillEnvVarDependencyPrompt)
{
let env_var_dependencies = collect_env_var_dependencies(&mentioned_skills); // finds `env_var` dependencies declared in skill metadata
resolve_skill_dependencies_for_turn(&sess, &turn_context, &env_var_dependencies).await; // checks session cache and process env; then prompts
}
let SkillInjections {
items: skill_items,
warnings: skill_warnings,
} = build_skill_injections(
&mentioned_skills,
Some(&otel_manager),
&sess.services.analytics_events_client,
tracking.clone(),
)
.await; // reads each referenced `SKILL.md` and wraps it into
if !skill_items.is_empty() {
sess.record_conversation_items(&turn_context, &skill_items)
.await;
} // inserts those skill instructions into the conversation history.
}
When the user explicitly mentions a skill, Codex reads that skill file and inserts its instructions into the conversation history before the sampling request.
Tool selection interaction
pub(crate) async fn run_sampling_request(
) -> Option<SamplingResponse> {
let filtered_connectors = filter_connectors_for_input(
&available_connectors,
&explicit_app_paths,
&skill_name_counts_lower,
); // filters app connectors based on explicit mentions and skill name disambiguation.
let connectors_for_tools = if turn_context.client.config().features.enabled(Feature::Apps) {
// If a skill and connector share a slug, connectors are filtered unless the connector is explicitly referenced.
let connectors = connectors::accessible_connectors_from_mcp_tools(&mcp_tools);
Some(filter_connectors_for_input(
connectors,
&input,
tool_selection.explicit_app_paths,
tool_selection.skill_name_counts_lower,
))
} else {
None
};
}
Skill names also influence app connector filtering. If a skill and a connector share a slug, Codex keeps the connector available only when the user explicitly references that connector.
Skill loading details
1) SkillsManager setup
- File:
codex-rs/core/src/skills/manager.rs. -
SkillsManager::newinstalls embedded system skills intoCODEX_HOME/skills/.system. - A per-cwd cache (
cache_by_cwd) storesSkillLoadOutcometo avoid rescanning on every turn.
2) Skill roots and discovery
- File:
codex-rs/core/src/skills/loader.rs. - Roots (ordered by precedence):
- Repo skills:
.codex/skillsin project config layer. - User skills:
-
CODEX_HOME/skills(legacy) -
$HOME/.agents/skills
-
- System skills:
CODEX_HOME/skills/.system(installed from embedded assets) - Admin skills:
/etc/codex/skills(system config layer) - Repo-local agents folders: any
.agents/skillsbetween project root and current cwd.
- Repo skills:
- Discovery:
- Scans each root for
SKILL.mdwithin a limited depth. - Parses YAML frontmatter for
nameanddescription. - Optional metadata from
agents/openai.yamlfor UI interface and dependencies. - Dedupe by path and sort by scope priority.
- Scans each root for
3) Disabled skills
- File:
codex-rs/core/src/skills/manager.rs. - Disabled skill paths are read from the user config layer (
skillsconfig section). - Disabled paths are excluded by
enabled_skills()and by selection logic during injection.
Input context: how skill content reaches the model
-
Session-level instructions
-
get_user_instructionsappends the Skills section (list + usage rules) into the base instructions. - This is visible to the model before any per-turn content.
-
-
Per-turn skill injection
- Skill mentions in the user input drive selection.
- The skill file contents are wrapped into
SkillInstructionsand inserted asResponseItems. - These items are recorded into the conversation history and included in the sampling request input.
-
Tool filtering
- Skill name counts are used to disambiguate connector mentions during tool selection.
Output artifacts produced by the skill flow
-
Skill list output (session instructions)
-
render_skills_sectioncreates a markdown list of available skills and usage rules.
-
-
Skill injection items (per turn)
-
SkillInstructionsresponse items are inserted into the conversation history. - Any failed reads result in warning events for the user.
-
Key files and call sites
- Entry points:
-
codex-rs/core/src/codex.rs
-
- Skill manager and loader:
-
codex-rs/core/src/skills/manager.rs -
codex-rs/core/src/skills/loader.rs -
codex-rs/core/src/skills/system.rs
-
- Mention parsing and injection:
-
codex-rs/core/src/skills/injection.rs -
codex-rs/core/src/mentions.rs
-
- Project doc assembly:
-
codex-rs/core/src/project_doc.rs
-