From 9ba10a010c1896a8caf4a67d2e60ca3892c6ce2d Mon Sep 17 00:00:00 2001 From: Aaron Levine Date: Wed, 24 Jun 2026 08:44:50 -0700 Subject: [PATCH] skills: reuse loaded instructions across turns --- codex-rs/core-skills/src/render.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/codex-rs/core-skills/src/render.rs b/codex-rs/core-skills/src/render.rs index 89ea1675d0..5be7185e0d 100644 --- a/codex-rs/core-skills/src/render.rs +++ b/codex-rs/core-skills/src/render.rs @@ -28,10 +28,10 @@ pub const SKILL_DESCRIPTIONS_REMOVED_WARNING_PREFIX: &str = pub const SKILLS_INTRO_WITH_ABSOLUTE_PATHS: &str = "A skill is a set of instructions provided through a `SKILL.md` source. Below is the list of skills that can be used. Each entry includes a name, description, and source locator. `file` locators are on the host filesystem, `environment resource` locators are owned by an execution environment, `orchestrator resource` locators are opaque non-filesystem resources, and `custom resource` locators use their provider's access mechanism."; pub const SKILLS_INTRO_WITH_ALIASES: &str = "A skill is a set of local instructions to follow that is stored in a `SKILL.md` file. Below is the list of skills that can be used. Each entry includes a name, description, and a short path that can be expanded into an absolute path using the skill roots table."; pub const SKILLS_HOW_TO_USE_WITH_ABSOLUTE_PATHS: &str = r###"- Discovery: The list above is the skills available in this session (name + description + source locator). `file` entries live on the host filesystem, `environment resource` entries are owned by their execution environment, `orchestrator resource` entries must be accessed through `skills.list` and `skills.read`, and `custom resource` entries use their provider's access mechanism. -- Trigger rules: If the user names a skill (with `$SkillName` or plain text) OR the task clearly matches a skill's description shown above, you must use that skill for that turn. Multiple mentions mean use them all. Do not carry skills across turns unless re-mentioned. +- Trigger rules: If the user names a skill (with `$SkillName` or plain text) OR the task clearly matches a skill's description shown above, you must use that skill for that turn. Multiple mentions mean use them all. On later turns, select skills again based on the same rule; do not assume that a previously selected skill still applies. Selecting an already-read skill again does not require rereading it when its instructions remain in context. - Missing/blocked: If a named skill isn't in the list or its source can't be read, say so briefly and continue with the best fallback. - How to use a skill (progressive disclosure): - 1) After deciding to use a skill, the main agent must read its `SKILL.md` completely before taking task actions. For a `file` entry, open the listed path. For an `environment resource`, use the filesystem of the owning environment. For an `orchestrator resource`, call `skills.list` with `{"authority":{"kind":"orchestrator"}}`, select the matching package, and pass its `main_resource` to `skills.read`. If a read is truncated or paginated, continue until EOF. + 1) The first time the main agent uses a skill in a conversation, it must read that skill's `SKILL.md` completely before taking task actions. If the skill was already read earlier in the conversation and its instructions remain in context, reuse those instructions and do not reread `SKILL.md` merely because a new turn started. For a `file` entry, open the listed path. For an `environment resource`, use the filesystem of the owning environment. For an `orchestrator resource`, call `skills.list` with `{"authority":{"kind":"orchestrator"}}`, select the matching package, and pass its `main_resource` to `skills.read`. If a read is truncated or paginated, continue until EOF. 2) When `SKILL.md` references another resource, use the same access mechanism. Resolve relative paths against a filesystem-backed skill directory. For orchestrator skills, pass the exact referenced resource identifier with the same authority and package to `skills.read`; do not treat `skill://` identifiers as filesystem paths. 3) If `SKILL.md` points to extra folders such as `references/`, use its routing instructions to identify the resources required for the task. The main agent must read each required instruction or reference file itself before acting on it. Do not delegate reading, summarizing, or interpreting skill instructions to a subagent. Subagents may still perform task work when the selected skill allows it. 4) For filesystem-backed skills, prefer running or patching provided scripts instead of retyping large code blocks. For orchestrator skills, use `skills.read` and the available tools; do not invent a local path. @@ -45,10 +45,10 @@ pub const SKILLS_HOW_TO_USE_WITH_ABSOLUTE_PATHS: &str = r###"- Discovery: The li - When variants exist (frameworks, providers, domains), pick only the relevant reference file(s) and note that choice. - Safety and fallback: If a skill can't be applied cleanly (missing files, unclear instructions), state the issue, pick the next-best approach, and continue."###; pub const SKILLS_HOW_TO_USE_WITH_ALIASES: &str = r###"- Discovery: The list above is the skills available in this session (name + description + short path). Skill bodies live on disk at the listed paths after expanding the matching alias from `### Skill roots`. -- Trigger rules: If the user names a skill (with `$SkillName` or plain text) OR the task clearly matches a skill's description shown above, you must use that skill for that turn. Multiple mentions mean use them all. Do not carry skills across turns unless re-mentioned. +- Trigger rules: If the user names a skill (with `$SkillName` or plain text) OR the task clearly matches a skill's description shown above, you must use that skill for that turn. Multiple mentions mean use them all. On later turns, select skills again based on the same rule; do not assume that a previously selected skill still applies. Selecting an already-read skill again does not require rereading it when its instructions remain in context. - Missing/blocked: If a named skill isn't in the list or the path can't be read, say so briefly and continue with the best fallback. - How to use a skill (progressive disclosure): - 1) After deciding to use a skill, the main agent must expand the listed short `path` with the matching alias from `### Skill roots`, then open and read its `SKILL.md` completely before taking task actions. If a read is truncated or paginated, continue until EOF. + 1) The first time the main agent uses a skill in a conversation, it must expand the listed short `path` with the matching alias from `### Skill roots`, then open and read that skill's `SKILL.md` completely before taking task actions. If the skill was already read earlier in the conversation and its instructions remain in context, reuse those instructions and do not reread `SKILL.md` merely because a new turn started. If a read is truncated or paginated, continue until EOF. 2) When `SKILL.md` references relative paths (e.g., `scripts/foo.py`), resolve them relative to the directory containing that expanded `SKILL.md` first, and only consider other paths if needed. 3) If `SKILL.md` points to extra folders such as `references/`, use its routing instructions to identify the files required for the task. The main agent must read each required instruction or reference file itself before acting on it. Do not delegate reading, summarizing, or interpreting skill instructions to a subagent. Subagents may still perform task work when the selected skill allows it. 4) If `scripts/` exist, prefer running or patching them instead of retyping large code blocks. @@ -1007,12 +1007,21 @@ mod tests { } #[test] - fn skill_usage_instructions_require_complete_main_agent_reads() { + fn skill_usage_instructions_require_complete_initial_reads_and_cross_turn_reuse() { for instructions in [ SKILLS_HOW_TO_USE_WITH_ABSOLUTE_PATHS, SKILLS_HOW_TO_USE_WITH_ALIASES, ] { - assert!(instructions.contains("read its `SKILL.md` completely")); + assert!(instructions.contains("read that skill's `SKILL.md` completely")); + assert!( + instructions.contains( + "Selecting an already-read skill again does not require rereading it" + ) + ); + assert!( + instructions.contains("do not reread `SKILL.md` merely because a new turn started") + ); + assert!(!instructions.contains("Do not carry skills across turns unless re-mentioned")); assert!(instructions.contains("continue until EOF")); assert!(instructions.contains( "The main agent must read each required instruction or reference file itself"