How Codex Routes Skills When Multiple Keywords Match

Codex resolves ambiguous skill requests by scoring keyword matches across candidate skills and applying deterministic tie-breakers, falling back to user clarification when confidence is low.

When a user query triggers multiple installed skills in the OpenAI plugins repository, Codex employs a sophisticated routing algorithm to select the most appropriate handler. The system analyzes keyword overlaps between the user input and each skill’s manifest, calculates match scores, and applies deterministic tie-breaking rules to ensure consistent behavior. This process ensures that even when multiple skills share similar terminology—such as "search" or "report"—the correct skill is invoked reliably.

How Codex Scores and Selects Skills

Candidate Skill Collection

First, Codex scans all installed plugins and extracts skills whose keywords arrays intersect with words from the user query. For example, skills defined in plugins/fyxer/.codex-plugin/plugin.json or plugins/zoom/.codex-plugin/plugin.json become candidates if any of their keywords appear in the request. This initial filtering creates a candidate pool of all potentially relevant skills.

Keyword Match Scoring

For each candidate, Codex computes a match score using the internal score_keyword_match function. The scoring algorithm applies differentiated weights based on match quality:

  • Exact matches: When a query word equals a manifest keyword, the skill receives a high weight (+10)
  • Partial matches: When a query word contains a keyword as a substring, the skill receives a lower weight (+3)
  • Synonym expansion: The internal synonym map can boost scores for semantically related terms

This weighted approach ensures that precise terminology matches outweigh vague substring overlaps.

Deterministic Tie-Breaking

When multiple skills achieve identical scores, Codex applies a strict priority chain to guarantee reproducible selection:

  1. Explicit priority: The optional priority field in the skill manifest breaks ties in favor of higher values
  2. Alphabetical ordering: Plugin names provide a final fallback, ensuring the same skill wins across identical requests

Confidence Thresholds and Disambiguation

If the highest-scoring skill fails to exceed the configured CONFIDENCE_THRESHOLD, Codex raises a ClarificationNeeded exception rather than executing the match. This safety mechanism triggers a clarifying question when generic terms (e.g., "get" or "list") match too many skills, preventing incorrect invocations on ambiguous queries.

Code Implementation

The routing logic operates through a pipeline that processes the query against installed plugin manifests:

def route_request(query: str, installed_plugins: List[Plugin]) -> Skill:
    # 1. Extract keywords from the query

    query_words = set(query.lower().split())

    # 2. Gather candidates

    candidates = [
        skill for plugin in installed_plugins
        for skill in plugin.skills
        if query_words & set(skill.manifest["keywords"])
    ]

    # 3. Score candidates

    scores = {}
    for skill in candidates:
        score = 0
        for kw in skill.manifest["keywords"]:
            if kw in query_words:
                score += 10          # exact match

            elif any(kw in w for w in query_words):
                score += 3           # partial match

        scores[skill] = score

    # 4. Pick best skill (with deterministic tie‑break)

    best_skill = max(
        scores,
        key=lambda s: (scores[s],
                       s.manifest.get("priority", 0),
                       s.name)                 # alphabetical fallback

    )

    # 5. Confidence check

    if scores[best_skill] < CONFIDENCE_THRESHOLD:
        raise ClarificationNeeded("Which skill did you mean?")
    return best_skill

Once selected, Codex forwards the request to the skill’s entrypoint as defined in its manifest.

Key Configuration Files

Skill routing depends on metadata defined in plugin manifests and entry points. Critical files in the OpenAI plugins repository include:

Summary

  • Codex collects candidate skills by intersecting user query words with manifest keywords arrays found in files like plugins/fyxer/.codex-plugin/plugin.json
  • Match scoring weights exact matches (+10) higher than partial substring matches (+3), with additional boosts from synonym expansion
  • Deterministic tie-breakers use the manifest priority field first, then alphabetical plugin names to ensure consistent selection
  • Low-confidence matches trigger ClarificationNeeded exceptions rather than executing ambiguous commands
  • Selected skills route to their entrypoint scripts (e.g., SKILL.md files) for execution

Frequently Asked Questions

How does Codex handle queries that match keywords in multiple skills simultaneously?

Codex scores every matching skill based on keyword overlap quality using the score_keyword_match logic, then selects the highest scorer. If scores tie, it checks the priority field in each skill’s manifest, falling back to alphabetical plugin naming to ensure deterministic selection.

What happens when no skill achieves a high confidence score?

When the top candidate’s score falls below CONFIDENCE_THRESHOLD, Codex raises a ClarificationNeeded exception and prompts the user to specify which skill they intended, preventing incorrect invocations on ambiguous queries.

Can developers influence skill selection priority?

Yes. Developers can set an optional priority field in the skill manifest (e.g., in .codex-plugin/plugin.json). Higher priority values break ties in favor of that skill when multiple candidates achieve identical keyword match scores.

Where does a routed request ultimately execute?

After selection, Codex dispatches the request to the skill’s entrypoint as defined in its manifest. For example, the Zoom Video-SDK skill routes to plugins/zoom/skills/video-sdk/SKILL.md according to the repository structure.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →