Skip to content

fix(codex): send skill mentions as typed skill input - #9494

Open
ylcn91 wants to merge 3 commits into
pingdotgg:mainfrom
ylcn91:fix/codex-typed-skill-input
Open

fix(codex): send skill mentions as typed skill input#9494
ylcn91 wants to merge 3 commits into
pingdotgg:mainfrom
ylcn91:fix/codex-typed-skill-input

Conversation

@ylcn91

@ylcn91 ylcn91 commented Sep 3, 2026

Copy link
Copy Markdown

What Changed

apps/server/src/provider/Drivers/CodexSkillDispatch.ts (new): resolves the $name tokens in a prompt against the skills Codex reports for the session's cwd. Same token shape as the composer chip and the Claude dispatch, so a rendered chip and a dispatched skill are always the same set. Unknown or disabled names stay literal.

apps/server/src/provider/Layers/CodexSessionRuntime.ts: sendTurn reads skills/list only when the prompt carries a token, then buildTurnStartParams sends each resolved skill as a { type: "skill", name, path } input item beside the text. The vendored app-server schema predates that item, so the turn/start params schema is extended locally next to the existing collaborationMode extension. A failed catalog read logs a warning and sends the mention as text, which is what every turn did before.

docs/user/composer.md: notes that Codex loads a skill only on a turn it starts fresh.

Tests: the dispatch helper (order, de-duplication, unknown and disabled names, whitespace-delimited tokens) and the typed item in the turn params.

Why

Refs #9317.

T3 Code sends $ask-matt to Codex as prose. A skill with policy.allow_implicit_invocation: false is absent from the catalog the model sees, so the prompt names a skill the model cannot reach, and the reply is that the skill is not installed.

I verified what the app server does with each input shape by pointing Codex 0.152.1 at a local endpoint that records every model request and answers a canned response (no model, no quota), with a skill whose SKILL.md carries a marker string:

Input on a fresh turn/start SKILL.md in the model request
{ type: "text", text: "$ask-test hello" } no
text + { type: "mention", name, path } no
text + { type: "skill", name, path } yes, as a <skill> block after the text

So the typed skill item is the one that works, and this change sends it. The text stays as written, which is how the Codex TUI sends the same mention.

The same harness shows the limit the issue title is about. When the second message arrives while a turn is running, whether through a second turn/start (what T3 Code does today; the app server steers it into the active turn) or through turn/steer, the app server drops the skill item and forwards only the text, even when the item is the whole input. That is Codex's own behaviour, so this PR does not claim to fix the active-turn case; it makes explicit invocation work on the turn Codex starts fresh and documents the limit for users. Holding a skill-bearing message until the current turn ends would be a product decision and is left out.

Model and harness: Claude Fable 5.1 in Claude Code.


Note

Medium Risk
Changes Codex turn input wiring and adds a pre-turn RPC; failures degrade to prior text-only behavior, but incorrect resolution could invoke the wrong skill path.

Overview
Composer $skill tokens were reaching Codex as plain text, so skills that only the user may invoke (not in the model catalog) never loaded. This change parses those tokens, optionally calls skills/list when the prompt contains a mention, and sends matching enabled skills as { type: "skill", name, path } items alongside the unchanged prompt text on turn/start.

CodexSkillDispatch handles detection, de-duplication in first-mention order, and ignores unknown, disabled, or non–whitespace-delimited tokens (aligned with composer chips and Claude dispatch). CodexSessionRuntime extends the vendored turn-start input schema for the skill item; catalog failures log a warning and fall back to text-only input. User docs note that Codex only applies typed skills on a fresh turn, not while steering an in-flight turn.

Reviewed by Cursor Bugbot for commit fb4403c. Configure here.

Note

Fix CodexSkillDispatch to send skill mentions as typed skill input

  • Adds an in-memory catalog fixture with enabled and disabled skills for the dispatch tests.
  • Asserts valid skill mentions resolve to skill inputs while dollar amounts and email-style dollar signs are rejected.
  • Asserts repeated mentions are deduplicated and resolved in order of first appearance.
  • Asserts unknown, disabled, absent, and punctuation-adjacent mentions are left as prose with no skill inputs.

Macroscope summarized 78743c1.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 3, 2026
Comment thread apps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment thread apps/server/src/provider/Drivers/CodexSkillDispatch.ts
@macroscopeapp

macroscopeapp Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 78743c1

Macroscope's review found this PR approvable — This is a focused Codex bug fix that enables existing skill mentions through a small typed-input adapter, with ordinary prompts unchanged and catalog failures falling back safely to text-only input. Tests cover token resolution and the turn payload, while the documented in-progress-turn limitation is explicit.

You can add or adjust custom eligibility rules. Learn more.

@ylcn91
ylcn91 force-pushed the fix/codex-typed-skill-input branch from 85c38ce to 78743c1 Compare September 3, 2026 23:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant